Module:TournamentResults

local util_args = require('Module:ArgsUtil') local util_cargo = require('Module:CargoUtil') local util_esports = require('Module:EsportsUtil') local util_html = require('Module:HtmlUtil') local util_math = require('Module:MathUtil') local util_table = require('Module:TableUtil') local util_text = require('Module:TextUtil') local util_toggle = require('Module:ToggleUtil') local util_vars = require('Module:VarsUtil') local i18n = require('Module:i18nUtil') local m_currency = require('Module:Currency') local m_team = require('Module:Team')

local ROWSPANS = { place = true, prize_display = true, usd = true, eur = true, prizepct = true, qual = true, points = true }

local CLASSES = { place = 'tournament-results-place', team = 'tournament-results-team', player = 'tournament-results-player', prize_display = 'tournament-results-prize', }

local CURRENCY_ORDER = { 'USD', 'Euros' }

local LINE_ARG_ORDER = { 'place', 'forcenewplace', 'sameplaces', 'date', 'prize', 'otherprize', 'prizepct', 'prizeunit', 'points', 'qual', 'quallink', 'qual2', 'qual2link', 'team', 'nocargo', 'date', 'rosterpage', 'groupstage', 'group', 'lastresult', 'lastopponent', 'lastopponentlink', 'lastopponentteam', 'lastoutcome', 'lastresultpoints', 'player', 'playerlink', 'hide', 'qualified' }

local TOGGLES = { class = 'TRL_toggle%s', }

local PRIZE_TOGGLE_DATA = { order = {}, sep = ' &#8226; ', section = 'prizepool-togglers-currency', all = 'prizepool-currency-all', hiddenclass = 'prizepool-currency-hidden', }

local HAS_TOGGLES = false

local h = {} local p = {} function p.main(frame) i18n.initGlobalFromFile('TournamentResults') local args = util_args.merge(true) local processedArgs = h.getProcessedArgs(args) h.initCurrencyToggle(processedArgs) local cols = h.getCols(args, processedArgs) local linesData = h.getLinesData(args, processedArgs) h.storeCargo(linesData) return h.makeOutput(args, processedArgs, cols, linesData) end

function h.getProcessedArgs(args) h.checkConversions({ args.usdrate, args.eurorate }) local processedArgs = { prizeunit = args.prizeunit or 'USD', totalprize = util_math.formatNumber(args.totalprize), totalprizenum = args.totalprize and util_math.tonumber(args.totalprize), usdrate = tonumber(args.usdrate), eurorate = tonumber(args.eurorate), phase = args.phase, nocargo = util_args.castAsBool(args.nocargo), preload = args.preload or 'Team', showprize = util_args.castAsBool(args.prize), showusd = util_args.castAsBool(args.usdrate), showeuro = util_args.castAsBool(args.eurorate), showpoints = util_args.castAsBool(args.points), showqual = util_args.castAsBool(args.qual), showteam = util_args.castAsBool(args.showteam), showplayer = util_args.castAsBool(args.showplayer), combinequal = util_args.castAsBool(args.combinequal), }	processedArgs.hasconversion = processedArgs.usdrate or processedArgs.eurorate return processedArgs end

function h.checkConversions(tbl) for _, v in ipairs(tbl) do		if v and not tonumber(v) then error(i18n.print('invalid_currency', i18n.print('conversion_rate'))) end end end function h.initCurrencyToggle(processedArgs) local rates = { USD = processedArgs.usdrate, Euros = processedArgs.eurorate, }	for _, v in ipairs(CURRENCY_ORDER) do		if rates[v] then PRIZE_TOGGLE_DATA.order[#PRIZE_TOGGLE_DATA.order+1] = v		end end if next(PRIZE_TOGGLE_DATA.order) then table.insert(PRIZE_TOGGLE_DATA.order, 1, 'prize') HAS_TOGGLES = true end util_toggle.oflInit(PRIZE_TOGGLE_DATA) end

function h.getCols(args, processedArgs) local cols = { 'place', processedArgs.showprize and 'prize_display', h.pctCol(args), processedArgs.showpoints and 'points', processedArgs.showqual and 'qual', (processedArgs.showteam or processedArgs.preload == 'Team') and 'team', (processedArgs.showplayer or processedArgs.preload == 'Player') and 'player', }	util_table.removeFalseEntries(cols) local names = h.getNames(args) cols.displays = {} for i, v in ipairs(cols) do cols.displays[i] = names[v] or i18n.print('col_' .. v)	end return cols end

function h.pctCol(args) if util_args.castAsBool(args.prize) and not util_args.castAsBool(args.nomoney) then return 'prizepct' else return false end end

function h.getNames(args) return { points = args.pointstitle, team = args.teamtitle } end

function h.getLinesData(args, processedArgs) local rowData = {} for i, v in ipairs(args) do		rowData[i] = h.processArgRow(v, processedArgs) end h.determineRowspans(rowData) return rowData end

function h.processArgRow(str, processedArgs) local lineArgs = util_args.splitArgs(str, LINE_ARG_ORDER) local lineDisplay = h.makeDisplayLineFromArgs(lineArgs, processedArgs) lineDisplay.cargo = h.argsToCargoLine(lineArgs, processedArgs, lineDisplay) return lineDisplay end

function h.makeDisplayLineFromArgs(lineArgs, processedArgs) local lineDisplay = { place = lineArgs.place and util_esports.placementIcon(lineArgs.place), placeraw = lineArgs.place, team = m_team.rightmediumlinked(lineArgs.team), player = h.getPlayerDisplay(lineArgs, processedArgs), points = lineArgs.points, qual = h.getQual(lineArgs), forcenewplace = util_args.castAsBool(lineArgs.forcenewplace), hide = util_args.castAsBool(lineArgs.hide), }	local prizes = h.getPrizeDisplay(lineArgs, processedArgs) prizes.prize_display = prizes.prize_toggle or prizes.prize util_table.merge(lineDisplay, prizes) if processedArgs.combinequal then lineDisplay.points = lineDisplay.points or lineDisplay.qual or '' end return lineDisplay end

function h.getPlayerDisplay(lineArgs, processedArgs) local output = { lineArgs.team and m_team.onlyimagelinkedshort(lineArgs.team), util_text.intLink(lineArgs.playerlink, lineArgs.player) }	util_table.removeFalseEntries(output, 2) return util_table.concat(output, ' ') end

function h.getQual(lineArgs) local quals = util_args.numberedArgsToTable(lineArgs, 'qual') or {} lineArgs.qual1link = lineArgs.quallink for i, qual in ipairs(quals) do local link = lineArgs['qual' .. i .. 'link'] quals[i] = util_text.intLink(link, qual) end return util_table.concat(quals,' ') end

function h.getPrizeDisplay(lineArgs, processedArgs) if not (lineArgs.prize or lineArgs.prizepct) then return { prize = lineArgs.otherprize } end local prizeNum = h.getPrizeNum(lineArgs, processedArgs) if not prizeNum then return { prize = lineArgs.otherprize, prizepct = lineArgs.prizepct .. '%' }	end local prizes = { prize = h.getPrize(prizeNum, lineArgs, processedArgs), usd_number = h.getPrizeConverted(prizeNum, processedArgs.prizeunit, processedArgs.usdrate, 'USD'), eur_number = h.getPrizeConverted(prizeNum, processedArgs.prizeunit, processedArgs.eurorate, 'Euro'), prizepct = h.getPrizePct(prizeNum, lineArgs, processedArgs), }	prizes.USD = m_currency.short(prizes.usd_number, 'usd') prizes.Euros = m_currency.short(prizes.eur_number, 'euro') prizes.prize_toggle = h.getPrizeToggle(prizes, processedArgs.prizeunit) return prizes end

function h.getPrizeNum(lineArgs, processedArgs) local prize = lineArgs.prize if prize then if not util_math.tonumber(prize) then error(i18n.print('invalid_currency',i18n.print('prize'))) end return util_math.tonumber(prize) end local prizepct = lineArgs.prizepct local totalprize = processedArgs.totalprizenum if totalprize then return util_math.roundnum(prizepct / 100 * totalprize, .01) end return nil end

function h.getPrize(prizeNum, lineArgs, processedArgs) local fullPrize = { m_currency.short(prizeNum, processedArgs.prizeunit), lineArgs.otherprize }	return util_table.concat(fullPrize, ' + ',nil,2) end

function h.getPrizeConverted(prize, prizeunit, rate, unitToGet) if prizeunit == unitToGet then return prize elseif prize and rate then return util_math.roundnum(prize * tonumber(rate), .01) else return nil end end

function h.getPrizePct(prizeNum, lineArgs, processedArgs) if lineArgs.prizepct then return lineArgs.prizepct .. '%'	elseif processedArgs.totalprizenum then return util_math.roundnum(prizeNum / processedArgs.totalprizenum * 100, .01) .. '%'	else return nil end end

function h.getPrizeToggle(prizes, prizeunit) if not HAS_TOGGLES then return nil end local tbl = mw.html.create for _, v in ipairs(PRIZE_TOGGLE_DATA.order) do		util_toggle.oflCellClasses(tbl:tag('span'):wikitext(prizes[v]), PRIZE_TOGGLE_DATA, v)	end return tostring(tbl) end

function h.argsToCargoLine(lineArgs, processedArgs, lineDisplay) if processedArgs.nocargo or lineArgs.nocargo then return end local cargoData = { Event = util_vars.getVar('Event Name'), Tier = util_vars.getVar('Event Tier'), Date = lineArgs.date or util_vars.getVar('Event Date'), Place = util_math.deserialize(lineArgs.place) or lineArgs.place, Prize = lineArgs.prize, PrizeUnit = processedArgs.prizeunit, Prize_Markup = lineArgs.prize and m_currency.short(lineArgs.prize, processedArgs.prizeunit), Prize_USD = lineDisplay.usd_number, Prize_Euro = lineDisplay.eur_number, Prize_Other = lineArgs.otherprize, Team = lineArgs.team and m_team.teamlinkname(lineArgs.team), UniqueLine = mw.title.getCurrentTitle.text .. '_' .. util_vars.setGlobalIndex('TRL_line'), Phase = processedArgs.phase, OverviewPage = mw.title.getCurrentTitle.text, ForceNewPlace = lineArgs.forcenewplace, }	local extraCargoData if processedArgs.preload == 'Player' then extraCargoData = h.getPlayerSpecificCargo(lineArgs, processedArgs, lineDisplay) elseif processedArgs.preload == 'Team' then extraCargoData = h.getTeamSpecificCargo(lineArgs, processedArgs, lineDisplay) end util_table.merge(cargoData, extraCargoData) -- return a table containing the table because maybe we want 2 dif cargo tables -- storing per line, e.g. TournamentResults & TournamentRosters return { cargoData } end

function h.getPlayerSpecificCargo(lineArgs, processedArgs, lineDisplay) local playerData = { _table = 'TournamentResults1v1', Player = lineArgs.player, PlayerLink = lineArgs.playerlink or lineArgs.player, }	local lastResult = h.playerLastResultCargo(lineArgs) util_table.merge(playerData, lastResult) return playerData end

function h.playerLastResultCargo(lineArgs) local lastResult = { LastResult = lineArgs.lastresult, LastOpponent = lineArgs.lastopponent, LastOpponentLink = lineArgs.lastopponentlink or lineArgs.lastopponent, LastOutcome = lineArgs.lastoutcome and util_esports.outcomes[lineArgs.lastoutcome:lower], LastOpponentTeam = lineArgs.lastopponentteam and m_team.teamlinkname(lineArgs.lastopponentteam), OverviewPage = mw.title.getCurrentTitle.text, }	return lastResult end

function h.getTeamSpecificCargo(lineArgs, processedArgs, lineDisplay) local teamData = { _table = 'TournamentResults', Place_Number = util_math.deserialize(lineArgs.place), Qualified = h.determineQualified(lineArgs), RosterPage = lineArgs.rosterpage or mw.title.getCurrentTitle.text, }	local teamlink = lineArgs.team and m_team.teamlinkname(lineArgs.team) or '' teamData.PageAndTeam = teamData.RosterPage .. '_' .. teamlink local lastResult = h.teamLastResultCargo(lineArgs) util_table.merge(teamData, lastResult) return teamData end

function h.determineQualified(lineArgs) if util_args.castAsBool(lineArgs.qualified) then return 'Yes' end return lineArgs.place == 'Q' and 'Yes' end

function h.teamLastResultCargo(lineArgs) if lineArgs.groupstage then return h.lastResultGroupstage(lineArgs) elseif lineArgs.lastresultpoints then return h.lastResultPoints(lineArgs) else return h.lastResultDefault(lineArgs) end end

function h.lastResultGroupstage(lineArgs) return { LastResult = lineArgs.lastresult or lineArgs.groupstage, GroupName = lineArgs.group or 'Group Stage', LastOpponent_Markup = m_team.rightshortlinked('group stage') } end

function h.lastResultPoints(lineArgs) return { LastResult = lineArgs.lastresultpoints, LastOpponent_Markup = m_team.rightshortlinked('points') } end

function h.lastResultDefault(lineArgs) local lastResult = { LastResult = lineArgs.lastresult, LastOutcome = util_esports.getOutcomeName(lineArgs.lastoutcome) }	if lineArgs.lastopponent then lastResult.LastTeam = m_team.teamlinkname(lineArgs.lastopponent) lastResult.LastOpponent_Markup = m_team.rightshortlinked(lineArgs.lastopponent) end return lastResult end

function h.determineRowspans(rowData) local curPlace, curRow, count for _, row in ipairs(rowData) do		if curPlace ~= row.placeraw or row.forcenewplace then if curRow then curRow.rowspan = count end curRow = row count = 1 curPlace = row.placeraw else count = count + 1 end end if count or 0 > 1 then curRow.rowspan = count end end

-- cargo function h.storeCargo(linesData) if h.doWeStoreCargo then for _, line in ipairs(linesData) do			local cargoData = line.cargo if cargoData then for _, tbl in ipairs(cargoData) do					util_cargo.store(tbl) end end end end end

function h.doWeStoreCargo return mw.title.getCurrentTitle.nsText == '' end

-- make output function h.makeOutput(args, processedArgs, cols, linesData) h.initializeToggleData local output = mw.html.create output:wikitext(h.introSentence(args, processedArgs)) h.printCurrencyToggles(output) h.printTable(output, cols, linesData) h.creditCurrencyRates(output, args, processedArgs) return output end

function h.initializeToggleData local i = util_vars.setGlobalIndex('TRL_i') TOGGLES.class = TOGGLES.class:format(i) end

function h.introSentence(args, processedArgs) if not args.totalprize then return '' end local tempdate = util_args.nilToFalse(args.tempprizedate) local sentenceParts = { m_currency.long(processedArgs.totalprize, processedArgs.prizeunit), tempdate and i18n.print('temp_date', tempdate), i18n.print('intro'), }	return util_table.concat(sentenceParts, ' ') end

function h.printCurrencyToggles(output) if not HAS_TOGGLES then return end local div = output:tag('div'):addClass('toggle-button') util_toggle.printOptionFromListTogglers(div, PRIZE_TOGGLE_DATA) end

function h.printTable(output, cols, linesData) local tbl = output:tag('table') :addClass('wikitable2') :addClass('tournament-results') :addClass('zebra-manual') h.printStartCols(tbl, cols) local hidden = h.printLines(tbl, cols, linesData) if hidden then h.endHiddenResults(tbl, #cols) end end

function h.printStartCols(tbl, cols) local tr = tbl:tag('tr') for i, v in ipairs(cols) do		tr:tag('th') :wikitext(cols.displays[i]) end end

function h.printLines(tbl, cols, linesData) local hidden = false local rowspanLeft = 0 local odd = false for _, line in ipairs(linesData) do		if line.hide then hidden = true h.printShowButton(tbl, #cols) end local tr = tbl:tag('tr') if hidden then util_toggle.sepCellClasses(tr, TOGGLES) end local isFullRow = h.printOneLine(tr, cols, line, rowspanLeft, odd) if rowspanLeft == 1 then odd = not odd end if odd then tr:addClass('zebra-manual-odd') end if line.rowspan then rowspanLeft = line.rowspan else rowspanLeft = rowspanLeft - 1 end end return hidden end

function h.printShowButton(tbl, colspan) local tr = tbl:tag('tr') local th = tr:tag('th') :attr('colspan', colspan) util_toggle.printSepToggler(th, TOGGLES) util_toggle.sepCellClasses(tr, TOGGLES, true) end

function h.printOneLine(tr, cols, lineDisplay, rowspanLeft, odd) local isFullRow = false for _, col in ipairs(cols) do		if rowspanLeft > 1 and ROWSPANS[col] then -- pass else local td = tr:tag('td') :wikitext(lineDisplay[col]) :addClass(CLASSES[col]) if ROWSPANS[col] then td:attr('rowspan', lineDisplay.rowspan) end end end end

function h.endHiddenResults(tbl, colspan) local tr = tbl:tag('tr') local th = tr:tag('th') :attr('colspan', colspan) util_toggle.sepCellClasses(tr, TOGGLES, false) util_toggle.printSepToggler(th, TOGGLES, true) end

function h.creditCurrencyRates(output, args, processedArgs) if not (args.conversionsource and processedArgs.hasconversion) then return nil end local source = args.conversionsource:lower local date = args.conversiondate local rates = { USD = processedArgs.usdrate, Euros = processedArgs.eurorate, }	local originalUnit = processedArgs.prizeunit output:wikitext(i18n.print('credit_' .. source,date or i18n.print('unknown_date'))) local ul = output:tag('ul') for _, v in ipairs(CURRENCY_ORDER) do		if rates[v] then util_vars.log(v) ul:tag('li') :wikitext(m_currency.long(1, originalUnit)) :wikitext(' = ') :wikitext(m_currency.long(rates[v], v)) end end return output end

return p