Module:CrossTableLeague/dota2

local p = {} -- p stands for package

function p.formatDate(date) if(date < os.time({day=1,month=1,year=1980,hour=0,min=0,sec=0})) then return '' else return os.date("!%b %d", date) end end

function p.adjustDate(date, timezone) if type(date) == 'string' then year,month,day,hour,min,sec=date:match('(%d+)-(%d+)-(%d+) (%d+):(%d+):(%d+)') date = os.time({day=day,month=month,year=year,hour=hour,min=min,sec=sec}) end if not timezone or timezone == '' then timezone = '+00:00' end local timezoneSign, timezoneHour, timezoneMin = string.match(timezone, '^([+-])(%d+):(%d+)') return date + tonumber(timezoneSign .. '1') * (timezoneHour * 3600 + timezoneMin * 60) end

function p.getLPDBResults(args, tournaments, rowTeamlist, colTeamlist, aliasList) local parseLPDate = function(date) local month,day,year,hour,min,timezone=date:match('^(%a+)%s(%d+),%s(%d+)%D+(%d+):(%d+)%D*([+-]%d+:%d+)') if month then return mw.language.getContentLanguage:formatDate( 'r', month .. '-' .. day .. ', ' .. year .. ' ' .. hour .. ':' .. min .. timezone ) else return date end end local LPDBConditions for key, team in ipairs(rowTeamlist or {}) do	 	if (key > 1) then LPDBConditions = LPDBConditions .. ' OR ' end LPDBConditions = (LPDBConditions or '(') .. 'opponent1::' .. team.page .. ' OR opponent2::' .. team.page .. 	end   	if next(colTeamlist) then		for key, team in ipairs(colTeamlist) do			LPDBConditions = LPDBConditions .. 'OR opponent1::' .. team.page .. ' OR opponent2::' .. team.page .. 		end	end  	if next(aliasList) then		for alias, team in pairs(aliasList) do			LPDBConditions = LPDBConditions .. 'OR opponent1::' .. alias .. ' OR opponent2::' .. alias .. ''		end	end  	if LPDBConditions then		LPDBConditions = LPDBConditions .. ') AND ('	end	for key, item in ipairs(tournaments) do	 	if (key > 1) then			LPDBConditions = LPDBConditions .. ' OR '	  	end	 	LPDBConditions = (LPDBConditions or '(') .. 'pagename::' .. item .. '' --remove namespace on live end LPDBConditions = LPDBConditions .. ')' 	if (args.sdate) then		LPDBConditions = LPDBConditions .. 'AND (date::>' .. parseLPDate(args.sdate) .. ' OR date::' .. parseLPDate(args.sdate) .. ')'	end  	if (args.edate) then		LPDBConditions = LPDBConditions .. 'AND (date::<' .. parseLPDate(args.edate) .. ' OR date::' .. parseLPDate(args.edate) .. ')'	end	local output = mw.ext.LiquipediaDB.lpdb('match', { limit = 1000, offset = 0, order = 'date asc', conditions = LPDBConditions }) 	return output end

function p.getScores(cell) local scores = {'0','0'} if cell.walkover == '1' then scores = {'W', 'FF'} elseif cell.walkover == '2' then scores = {'FF', 'W'} elseif cell.walkover == '0' then scores = {'FF', 'FF'} elseif cell.finished == '1' then scores = {cell.opponent1score, cell.opponent2score} if (cell.opponent1score == '0' and cell.opponent2score == '0' and cell.winner == 'draw') then scores.zerodraw = 'true' end end return scores end

function p.printEmptyCell(row) row:tag('td') :css('display','none') end function p.printCell(row, colTeam, rowTeam, cell, toggleArea) if next(cell) then local scores = p.getScores(cell) local body = '\'\'\'' .. scores[1] .. '-' .. scores[2] .. '\'\'\''	 	if cell.footer then if body then body = body .. ' '			end body = body .. ' ' .. cell.footer .. ' '	 	end row:tag('td') :addClass('crosstable-bgc-r' .. scores[1] .. '-r' .. scores[2] .. (scores.zerodraw and '-draw' or '')) :css('min-width','45px') :wikitext(body) :attr('data-toggle-area-content',toggleArea) elseif (colTeam.page == rowTeam.page) then row:tag('td') :addClass('crosstable-bgc-cross') :attr('data-toggle-area-content',toggleArea) else row:tag('td') :addClass('crosstable-bgc-r-r') :attr('data-toggle-area-content',toggleArea) end end

function p.getCellData(row, col, rowTeam, colTeam, crosstable, isDouble, walkoverWin) function flipScores(cell) local tempCell = {} for key, item in pairs(cell or {}) do			tempCell[key] = item end tempCell.opponent1score, tempCell.opponent2score = cell.opponent2score, cell.opponent1score if cell.walkover and cell.walkover ~= '' then tempCell.walkover = tostring(3 - tonumber(cell.walkover)) end if tonumber(cell.winner) then tempCell.winner = tostring(3 - tonumber(cell.winner)) end return tempCell end local cellData, mirrorCellData = {}, {} if crosstable[rowTeam.page] and crosstable[rowTeam.page][colTeam.page] then cellData = crosstable[rowTeam.page][colTeam.page] end if crosstable[colTeam.page] and crosstable[colTeam.page][rowTeam.page] then mirrorCellData = crosstable[colTeam.page][rowTeam.page] end if isDouble then -- bottom left triangle if (row > col) then if not next(cellData[1] or {}) and next(mirrorCellData[1] or {}) then return flipScores(mirrorCellData[1]), flipScores(mirrorCellData[2] or {}) elseif next(cellData[1] or {}) and not next(mirrorCellData[1] or {}) then return cellData[1], cellData[2] or {} else return cellData[1] or {}, flipScores(mirrorCellData[1] or {}) end else if next(cellData[1] or {}) and not next(mirrorCellData[1] or {}) then return cellData[2] or {}, cellData[1] elseif not next(cellData[1] or {}) and next(mirrorCellData[1] or {}) then return flipScores(mirrorCellData[2] or {}), flipScores(mirrorCellData[1]) else return cellData[1] or {}, flipScores(mirrorCellData[1] or {}) end end else if next(cellData[1] or {}) then return cellData[1], {} else return flipScores(mirrorCellData[1] or {}), {} end end end

function p.get(frame, data) local rowTeamlist = {} local colTeamlist = {} local aliasList = {} local tournaments = {} local crosstable = {} local output = '' if not getArgs then getArgs = require('Module:Arguments').getArgs end args = getArgs(frame) -- parse parameters tournamentX and teamX and X-X_p local isSingle = (args.single == 'true') local isDouble = not(isSingle) local walkoverWin = args.walkover_win or 0 for key, item in pairs(args) do		if item == '' or item == '\n' then args[key] = nil end if type(key) == 'string' and item ~= '' then -- tournamentX if key:match('^tournament(%d*)$') then table.insert(tournaments, (mw.ext.TeamLiquidIntegration.resolve_redirect(item):gsub('%s','_'))) -- teamX elseif key:match('^team(%d*)$') then local teamPage = safeExpand(frame,'TeamPage', {item:lower}) local teamIcon = safeExpand(frame,'TeamIcon', {item:lower}) local index = key:match('^team(%d*)$') table.insert(rowTeamlist, {page=teamPage:match('(.-)%s*$'), icon=teamIcon, index=tonumber(index)}) rowTeamlist[teamPage] = #rowTeamlist local alias_list = args['team' .. index .. 'alias'] or '' if alias_list ~= '' then for alias in mw.text.gsplit(alias_list, ",") do		 				local aliasPage = safeExpand(frame,'TeamPage', {alias:lower}) aliasList[aliasPage] = teamPage end end

-- bteamX elseif key:match('^bteam(%d*)$') then isDouble = false local teamPage = safeExpand(frame,'TeamPage', {item:lower}) local teamIcon = safeExpand(frame,'TeamIcon', {item:lower}) local index = key:match('^bteam(%d*)$') table.insert(colTeamlist, {page=teamPage:match('(.-)%s*$'), icon=teamIcon, index=tonumber(index)}) colTeamlist[teamPage] = #colTeamlist local alias_list = args['bteam' .. index .. 'alias'] or '' if alias_list ~= '' then for alias in mw.text.gsplit(alias_list, ",") do		 				local aliasPage = safeExpand(frame,'TeamPage', {alias:lower}) aliasList[aliasPage] = teamPage end end end end end local hasArgs = {['row'] = next(rowTeamlist), ['col'] = next(colTeamlist)} if hasArgs.row and not(hasArgs.col) then for key, item in ipairs(rowTeamlist) do	 		table.insert(colTeamlist, item) colTeamlist[item.page] = #colTeamlist end end if not next(tournaments) then table.insert(tournaments,(mw.title.getCurrentTitle.text:gsub('%s','_'))) end if not data then data = p.getLPDBResults(args, tournaments, rowTeamlist, colTeamlist, aliasList) --or p.getSMWResults(frame, tournaments) end if type(data) == 'table' then -- get list of unique teams if no set teams for key, item in ipairs(data) do output = output .. item.opponent1 .. ' ' .. item.opponent2 .. ' ' .. item.date .. ' '	 		if not hasArgs.row then if not rowTeamlist[item.opponent1] and item.opponent1 ~='TBD' then local teamIcon = safeExpand(frame,'teamIcon', {item.opponent1:lower}) table.insert(rowTeamlist, {page=item.opponent1, index=string.lower(item.opponent1), icon=teamIcon}) table.insert(colTeamlist, {page=item.opponent1, index=string.lower(item.opponent1), icon=teamIcon}) rowTeamlist[item.opponent1] = #rowTeamlist colTeamlist[item.opponent1] = #colTeamlist end if not rowTeamlist[item.opponent2] and item.opponent2 ~='TBD' then local teamIcon = safeExpand(frame,'teamIcon', {item.opponent2:lower}) table.insert(rowTeamlist, {page=item.opponent2, index=string.lower(item.opponent2), icon=teamIcon}) table.insert(colTeamlist, {page=item.opponent2, index=string.lower(item.opponent2), icon=teamIcon}) rowTeamlist[item.opponent2] = #rowTeamlist colTeamlist[item.opponent2] = #colTeamlist end end local opponents = {item.opponent1, item.opponent2} if aliasList[item.opponent1] then opponents[1] = aliasList[item.opponent1] end if aliasList[item.opponent2] then opponents[2] = aliasList[item.opponent2] end output = output .. opponents[1] .. ' ' .. opponents[2].. ' ' .. item.date .. ' '	 		if not crosstable[opponents[1]] then crosstable[opponents[1]] = {} end if not crosstable[opponents[1]][opponents[2]] then crosstable[opponents[1]][opponents[2]] = {} end table.insert(crosstable[opponents[1]][opponents[2]], {			 	opponent1 = item.opponent1,			  	opponent2 = item.opponent2,			  	opponent1score = (item.walkover and item.walkover == '1') and walkoverWin or item.opponent1score,			  	opponent2score = (item.walkover and item.walkover == '2') and walkoverWin or item.opponent2score,		  		date = p.adjustDate(item.date, (item.extradata or {}).timezone),			  	footer = p.formatDate(p.adjustDate(item.date, (item.extradata or {}).timezone)),			  	finished = item.finished,			  	winner = item.winner,			  	walkover = item.walkover			}) table.sort(crosstable[opponents[1]][opponents[2]], function(item1,item2) return item1.date < item2.date end) end table.sort(rowTeamlist, function(team1,team2) return team1.index < team2.index end) table.sort(colTeamlist, function(team1,team2) return team1.index < team2.index end) else error(data) end local divWrapper = mw.html.create('div') :addClass('table-responsive toggle-area toggle-area-1') :attr('data-toggle-area','1') local openText, closeText = 'Show Aggregate', 'Show Individual' if isSingle then openText, closeText = 'Show Duplicates', 'Hide Duplicates' end if (isDouble or isSingle) and args.button ~= 'hide' then divWrapper:tag('span') :attr('data-toggle-area-content','1') :tag('span') :addClass('toggle-area-button btn btn-primary') :attr('data-toggle-area-btn','2') :css('width','150px') :css('margin-bottom','12px') :wikitext(openText) :done:done divWrapper:tag('span') :attr('data-toggle-area-content','2') :tag('span') :addClass('toggle-area-button btn btn-primary') :attr('data-toggle-area-btn','1') :css('width','150px') :css('margin-bottom','12px') :wikitext(closeText) :done:done end

local tableWidth = 64*(#colTeamlist+1) + 26 if args.button == 'above' and isSingle then tableWidth = 64*(#colTeamlist) + 26 end local tableWidthWrapper = divWrapper:tag('div') :css('min-width',tostring(tableWidth) .. 'px') if args.button ~= 'above' then tableWidthWrapper:css('float','left') end local tableWrapper = tableWidthWrapper:tag('table') :addClass('table table-bordered table-condensed crosstable') :css('margin','0px 13px 13px 0px') for row, rowTeam in ipairs(rowTeamlist) do	 	-- start of new row local tableRow = tableWrapper:tag('tr') :addClass('crosstable-tr') tableRow:tag('th') :wikitext(rowTeam.icon) if isSingle and row == 1 then tableRow:attr('data-toggle-area-content','2') end

for col, colTeam in ipairs(colTeamlist) do			local cellData, mirrorCellData = p.getCellData(row, col, rowTeam, colTeam, crosstable, isDouble, walkoverWin) if isSingle then if row > col then p.printCell(tableRow, rowTeam, colTeam, cellData) else p.printCell(tableRow, rowTeam, colTeam, cellData, '2') end elseif isDouble then p.printCell(tableRow, rowTeam, colTeam, cellData, '1') else p.printCell(tableRow, rowTeam, colTeam, cellData) end end if isDouble then for col, colTeam in ipairs(colTeamlist) do local cellData, mirrorCellData = p.getCellData(row, col, rowTeam, colTeam, crosstable, isDouble, walkoverWin) if next(cellData) and next(mirrorCellData) then local totalCellData = { opponent1score = tostring(tonumber(cellData.opponent1score) + tonumber(mirrorCellData.opponent1score)), opponent2score = tostring(tonumber(cellData.opponent2score) + tonumber(mirrorCellData.opponent2score)), footer = table.concat(p.getScores(cellData),'-') .. ', ' .. table.concat(p.getScores(mirrorCellData),'-'), finished = '1', }					p.printCell(tableRow, rowTeam, colTeam, totalCellData, '2') else p.printCell(tableRow, rowTeam, colTeam, cellData, '2') end end end end

local tableRow = tableWrapper:tag('tr') :addClass('crosstable-tr') tableRow:tag('th') for col, colTeam in ipairs(colTeamlist) do		if isSingle and col == #colTeamlist then tableRow:tag('th') :wikitext(colTeam.icon) :attr('data-toggle-area-content','2') else tableRow:tag('th') :wikitext(colTeam.icon) end end return divWrapper end

function safeExpand(frame, templateTitle, templateArgs) local result, value = pcall(frame.expandTemplate, frame, {title = templateTitle, args = templateArgs}) if result then return value else return 'Template:' .. templateTitle .. '' end end

return p