Module:Point standings table

From Liquipedia StarCraft 2 Wiki
local Arguments = require('Module:Arguments')
local Array = require('Module:Array')
local Faction = require('Module:Faction')
local Flags = require('Module:Flags')
local Logic = require('Module:Logic')
local Lua = require('Module:Lua')
local PageVariableNamespace = require('Module:PageVariableNamespace')
local String = require('Module:StringUtils')

local PlayerExt = Lua.import('Module:Player/Ext/Custom')
local PlayerDisplay = Lua.import('Module:Player/Display/Custom')

local globalVars = PageVariableNamespace()

local p = {}

function p._intro(mode, events, cut, manual_title, width)
	local tpm
	local title
	if mode == 'player' then
		tpm = 'players'
		title = 'Player'
	elseif mode == 'team' then
		tpm = 'teams'
		title = 'Team'
	else
		tpm = ((manual_title or '') ~= '' and manual_title .. 's') or 'teams'
		title = ((manual_title or '') ~= '' and manual_title) or 'Team'
	end
	local output = tostring(mw.html.create('table', { selfClosing = true }) -- hack part I
			:addClass('wikitable wikitable-striped wikitable-bordered prizepooltable collapsed')
			:css('text-align', 'center')
			:attr('data-cutafter', cut)
			:attr('data-opentext', 'Show remaining ' .. tpm)
			:attr('data-closetext', 'Hide remaining ' .. tpm)
		):gsub('/>$', '>') -- hack part II, because mw.html does not support unclosed tags
	
	header = mw.html.create('tr')
		:tag('th')
			:css('min-width', 21 ..'px')
			:wikitext(''):done()
		header:tag('th')
			:css('min-width', (width or 180) .. 'px')
			:wikitext(title):done()
		if mode == 'player' then
			header:tag('th')
				:css('min-width', 200 .. 'px')
				:wikitext('Team'):done()
		end
		header:tag('th')
			:css('width', 80 .. 'px')
			:wikitext('Total'):done()
	for key, event in ipairs(events) do
		header:tag('th')
			:css('min-width', 80 .. 'px')
			:wikitext('[['.. event.link ..'|'.. event.name ..']]'):done()
	end
  
	output = '<div class="table-responsive">' .. output .. tostring(header)
	
	return output
end

function p.get(frame)
	local args = Arguments.getArgs(frame)
	local mode = args.mode or ''
	local output = '<div class="table-responsive">'
	local width = args.width
	if mode ~= 'team' and mode ~= 'manual' then
		mode = 'player'
	end
	local cutafter = args.cutafter or 10
	local rows = ''
	local events = {}
	if mode == 'player' then
		rows, events = p._get_rows_player(args)
	elseif mode == 'team' then
		rows, events = p._get_rows_team(args)
	else
		rows, events = p._get_rows_manual(args)
	end
	
	local header = p._intro(mode, events, cutafter, args.manual_title, width)
	
	return header .. rows .. '</table></div>'
	
end

function p._get_rows_player(args)
	local output = ''
	local PlayerList = {}
	local EventsList = {}
	local Player_index = 0
	local Events_index = 0	
  
	 -- Get the date
	local date = args.date or globalVars:get('tournament_enddate') or os.date('%F')
  
	-- parse parameters 
	for key, item in pairs(args) do
		if item == '' or item == '\n' then
			args[key] = nil
		end
		
		if type(key) == 'string' and item ~= '' then
			if key:match('event%d*$') then
				local temp, index = key:match('(%a*)(%d*)$')
				Events_index = Events_index + 1
				EventsList[Events_index] = {name = args['event'..index], link = args['event'..index..'link'] or args['event'..index], index = index}
			elseif key:match('%a*%d$') then
				local param, index = key:match('(%a*)(%d*)$')
				index = tonumber(index)
				if param == 'p' or param == 'player' then
					Player_index = Player_index + 1
					local player = {
						displayName = item,
						flag = String.nilIfEmpty(Flags.CountryName(args[param .. index .. 'flag'])),
						pageName = args[param .. index .. 'link'] or item,
						faction = Faction.read(args[param .. index .. 'race']),
					}
					PlayerExt.populatePlayer(player, {date = date})
					local player_team = PlayerExt.populateTeam(player.pageName, args[param .. index .. 'team'], {date = date})
					local player_dq = args[param .. index .. 'dq'] or 'false'
					local player_note = args[param .. index .. 'note'] or ''
					local player_qual = args[param .. index .. 'qualified'] or args[param .. index .. 'qual'] or 'false'
					PlayerList[Player_index] = {
						dq = player_dq,
						flag = player.flag,
						index = index, 
						name = player.displayName,
						note = player_note, 
						player = player.pageName,
						qual = player_qual, 
						faction = player.faction,
						team = player_team,
					}
				end
			end
		end
	end
	
	for j=1, Player_index do
		local player_total = 0
		local player_total_qual = 0
		local player_points = {}
		for i=1,Events_index do
			player_points[i] = args['p' .. PlayerList[j]['index'] .. 'points' .. i] or args['player' .. PlayerList[j]['index'] .. 'points' .. i] or 0
			if string.lower(player_points[i]) ~= 'q' then
				player_total = player_total + player_points[i]
			else
				player_total_qual = 'Q'
				player_points[i] = '<b>Q</b>'
				PlayerList[j]['qual'] = 1
			end
			if player_points[i] == 0 then
				player_points[i] = '-'
			end
		end
		local sort = 99999
		if player_total_qual == 0 then
			player_total_qual = player_total
			sort = player_total
		end
		PlayerList[j]['total'] = player_total_qual
		PlayerList[j]['points'] = player_points
		PlayerList[j]['sort'] = sort
	end
	
	Array.sortInPlaceBy(PlayerList, function(x) return {-x.sort, x.name} end)
	Array.sortInPlaceBy(EventsList, function(event) return event.index end)
	
	for i=1,Player_index do
		if i ~= 1 and PlayerList[i]['total'] == PlayerList[i-1]['total'] then
			PlayerList[i]['rank'] = PlayerList[i-1]['rank']
		else
			PlayerList[i]['rank'] = i
		end
	end
  
	local output = ''
		
	if Player_index == 0 then
		row = mw.html.create('tr'):tag('td'):attr('colspan','42'):css('text-align', 'center'):css('font-style', 'italic'):wikitext('To be determined'):done()
		output = output .. tostring(row)
	else
		for i=1, Player_index do
			local class = ''
			local dqed1 = ''
			local dqed2 = ''
			if PlayerList[i].dq == 'true' or PlayerList[i].dq == '1' then
				class = 'bg-staydown'
				dqed1 = '<s>'
				dqed2 = '</s>'
			elseif PlayerList[i].qual ~= 'false' then
				class = 'bg-up'
			end
			
			local row = mw.html.create('tr')
			row:tag('td')
				:addClass(class)
				--:css('font-weight', 'bold')
				:wikitext(PlayerList[i].rank .. '.')
			local player = {
				pageName = PlayerList[i].player,
				displayName = PlayerList[i].name,
				flag = PlayerList[i].flag,
				faction = PlayerList[i].faction,
			}
			local playerNode = PlayerDisplay.InlinePlayer{
				player = player,
				dq = Logic.readBool(PlayerList[i].dq),
				note = String.nilIfEmpty(PlayerList[i].note),
			}
			local playerCell = row:tag('td')
				--:css('font-weight', 'bold')
				:css('text-align', 'left')
				:addClass(class)
				:node(playerNode)

			row:tag('td')
				:addClass(class)
				:css('text-align', 'left')
				:wikitext(PlayerList[i].team and (dqed1 .. mw.ext.TeamTemplate.team(PlayerList[i].team:gsub('_', ' '), date) .. dqed2))
			row:tag('td')
				:addClass(class)
				:css('font-weight', 'bold')
				:wikitext(dqed1 .. PlayerList[i].total .. dqed2)
			for j=1, Events_index do
				row:tag('td')
				:addClass(class)
					:wikitext(dqed1 .. PlayerList[i]['points'][j] .. dqed2)
			end
			
			output = output .. tostring(row)
		end
	end
	return tostring(output), EventsList
end

function p._get_rows_team(args)
	local output = ''
	local TeamList = {}
	local EventsList = {}
	local Team_index = 0
	local Events_index = 0	
  
	 -- Get the date
	local date = args.date or gloalVars:get('tournament_enddate') or os.date('%F')
  
	-- parse parameters 
	for key, item in pairs(args) do
		if item == '' or item == '\n' then
			args[key] = nil
		end
		
		if type(key) == 'string' and item ~= '' then
			if key:match('event%d*$') then
				local temp, index = key:match('(%a*)(%d*)$')
				Events_index = Events_index + 1
				EventsList[Events_index] = {name = args['event'..index], link = args['event'..index..'link'] or args['event'..index], index = index}
			elseif key:match('%a*%d$') then
				local param, index = key:match('(%a*)(%d*)$')
				index = tonumber(index)
				if param == 't' or param == 'team' then
					Team_index = Team_index + 1				
					local Team_name = args[param .. index .. 'link'] or item
					local Team_dq = args[param .. index .. 'dq'] or 'false'
					local Team_note = args[param .. index .. 'note'] or ''
					local Team_qual = args[param .. index .. 'qualified'] or args[param .. index .. 'qual'] or 'false'
					TeamList[Team_index] = {name = Team_name, dq = Team_dq, note = Team_note, qual = Team_qual, index = index}
				end
			end
		end
	end
	
	for j=1, Team_index do
		local Team_total = 0
		local Team_points = {}
		local Team_total_qual = 0
		for i=1,Events_index do
			Team_points[i] = args['p' .. TeamList[j]['index'] .. 'points' .. i] or args['Team' .. TeamList[j]['index'] .. 'points' .. i] or 0
			if string.lower(Team_points[i]) ~= 'q' then
				Team_total = Team_total + Team_points[i]
			else
				Team_total_qual = 'Q'
				Team_points[i] = '<b>Q</b>'
				TeamList[j]['qual'] = 1
			end
			if Team_points[i] == 0 then
				Team_points[i] = '-'
			end
		end
		local sort = 99999
		if Team_total_qual == 0 then
			Team_total_qual = Team_total
			sort = Team_total
		end
		TeamList[j]['total'] = Team_total_qual
		TeamList[j]['points'] = Team_points
		TeamList[j]['sort'] = sort
	end
	
	Array.sortInPlaceBy(TeamList, function(x) return {-x.sort, x.name} end)
	Array.sortInPlaceBy(EventsList, function(event) return event.index end)
	
	for i=1,Team_index do
		if i ~= 1 and TeamList[i]['total'] == TeamList[i-1]['total'] then
			TeamList[i]['rank'] = TeamList[i-1]['rank']
		else
			TeamList[i]['rank'] = i
		end
	end
  
	local output = ''
		
	if Team_index == 0 then
		row = mw.html.create('tr'):tag('td'):attr('colspan','42'):css('text-align', 'center'):css('font-style', 'italic'):wikitext('To be determined'):done()
		output = output .. tostring(row)
	else
		for i=1, Team_index do
			local class = ''
			local dqed1 = ''
			local dqed2 = ''
			if TeamList[i].dq == 'true' or TeamList[i].dq == '1' then
				class = 'bg-staydown'
				dqed1 = '<s>'
				dqed2 = '</s>'
			elseif TeamList[i].qual ~= 'false' then
				class = 'bg-up'
			end
			local row = mw.html.create('tr')
			row:tag('td')
				:addClass(class)
				--:css('font-weight', 'bold')
				:wikitext(TeamList[i].rank .. '.')
			local TeamCell = row:tag('td')
				--:css('font-weight', 'bold')
				:css('text-align', 'left')
				:addClass(class)
				:wikitext(dqed1 .. mw.ext.TeamTemplate.team(TeamList[i].name:gsub('_', ' '), date) .. dqed2 .. '&nbsp;<sup>' .. TeamList[i].note .. '</sup>')
			row:tag('td')
				:addClass(class)
				:css('font-weight', 'bold')
				:wikitext(dqed1 .. TeamList[i].total .. dqed2)
			for j=1, Events_index do
				row:tag('td')
					:addClass(class)
					:wikitext(dqed1 .. TeamList[i]['points'][j] .. dqed2)
			end
			
			output = output .. tostring(row)
		end
	end
	return tostring(output), EventsList
end

function p._get_rows_manual(args)
	local output = ''
	local List = {}
	local EventsList = {}
	local List_index = 0
	local Events_index = 0
  
	-- parse parameters 
	for key, item in pairs(args) do
		if item == '' or item == '\n' then
			args[key] = nil
		end
		
		if type(key) == 'string' and item ~= '' then
			if key:match('event%d*$') then
				local temp, index = key:match('(%a*)(%d*)$')
				Events_index = Events_index + 1
				EventsList[Events_index] = {name = args['event'..index], link = args['event'..index..'link'] or args['event'..index], index = index}
			elseif key:match('%a*%d$') then
				local param, index = key:match('(%a*)(%d*)$')
				index = tonumber(index)
				if param == 't' or param == 'team' or param == 'p' or param == 'name' or param == 'player' or param == 'entry' then
					List_index = List_index + 1				
					local List_name = args[param .. index .. 'link'] or item
					local List_dq = args[param .. index .. 'dq'] or 'false'
					local List_note = args[param .. index .. 'note'] or ''
					local List_qual = args[param .. index .. 'qualified'] or args[param .. index .. 'qual'] or 'false'
					List[List_index] = {name = List_name, dq = List_dq, note = List_note, qual = List_qual, index = index}
				end
			end
		end
	end
	
	for j=1, List_index do
		local List_total = 0
		local List_total_qual = 0
		local List_points = {}
		for i=1,Events_index do
			List_points[i] = args['t' .. List[j]['index'] .. 'points' .. i] or args['team' .. List[j]['index'] .. 'points' .. i] or args['p' .. List[j]['index'] .. 'points' .. i] or args['player' .. List[j]['index'] .. 'points' .. i] or args['entry' .. List[j]['index'] .. 'points' .. i] or 0
	  
			if string.lower(List_points[i]) ~= 'q' then
				List_total = List_total + List_points[i]
			else
				List_total_qual = 'Q'
				List_points[i] = '<b>Q</b>'
				List[j]['qual'] = 1
			end
			if List_points[i] == 0 then
				List_points[i] = '-'
			end
		end
		local sort = 99999
		if List_total_qual == 0 then 
			List_total_qual = List_total
			sort = List_total
		end
		List[j]['total'] = List_total_qual
		List[j]['points'] = List_points
		List[j]['sort'] = sort
	end
	
	Array.sortInPlaceBy(List, function(x) return {-x.sort, x.name} end)
	Array.sortInPlaceBy(EventsList, function(event) return event.index end)
	
	for i=1,List_index do
		if i ~= 1 and List[i]['total'] == List[i-1]['total'] then
			List[i]['rank'] = List[i-1]['rank']
		else
			List[i]['rank'] = i
		end
	end
  
	local output = ''
		
	if List_index == 0 then
		row = mw.html.create('tr'):tag('td'):attr('colspan','42'):css('text-align', 'center'):css('font-style', 'italic'):wikitext('To be determined'):done()
		output = output .. tostring(row)
	else
		for i=1, List_index do
			local class = ''
			local dqed1 = ''
			local dqed2 = ''
			if List[i].dq == 'true' or List[i].dq == '1' then
				class = 'bg-staydown'
				dqed1 = '<s>'
				dqed2 = '</s>'
			elseif List[i].qual ~= 'false' then
				class = 'bg-up'
			end
			local row = mw.html.create('tr')
			row:tag('td')
				:addClass(class)
				--:css('font-weight', 'bold')
				:wikitext(List[i].rank .. '.')
			local TeamCell = row:tag('td')
				--:css('font-weight', 'bold')
				:css('text-align', 'left')
				:addClass(class)
				:wikitext(dqed1 .. List[i].name .. dqed2 .. '&nbsp;<sup>' .. List[i].note .. '</sup>')
			row:tag('td')
				:addClass(class)
				:css('font-weight', 'bold')
				:wikitext(dqed1 .. List[i].total .. dqed2)
			for j=1, Events_index do
				row:tag('td')
					:addClass(class)
					:wikitext(dqed1 .. List[i]['points'][j] .. dqed2)
			end
			
			output = output .. tostring(row)
		end
	end
	return tostring(output), EventsList
end

return p