[checked revision] | [checked revision] |
([ST] add title attr) |
([ST]) |
||
Line 115: | Line 115: | ||
function h.makeWhere(page, args) |
function h.makeWhere(page, args) |
||
+ | if args.where then return args.where end |
||
local tbl = { |
local tbl = { |
||
('OverviewPage="%s"'):format(page), |
('OverviewPage="%s"'):format(page), |
Revision as of 05:32, 12 June 2021
Edit the documentation or categories for this module. This module has an i18n file.
local util_args = require('Module:ArgsUtil')
local util_cargo = require('Module:CargoUtil')
local util_esports = require('Module:EsportsUtil')
local util_form = require('Module:FormUtil')
local util_html = require('Module:HtmlUtil')
local util_map = require('Module:MapUtil')
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_tournament = require('Module:TournamentUtil')
local util_vars = require('Module:VarsUtil')
local lang = mw.getLanguage('en')
local i18n = require('Module:I18nUtil')
local m_team = require('Module:Team')
local Region = require('Module:Region')
local SHOW_LINKS = true
local sep = '%s*,%s*'
local CLASSES = {
init = 'crossbox-cell',
[1] = 'crossbox-win crossbox-cell',
[0] = 'crossbox-draw crossbox-cell',
[-1] = 'crossbox-loss crossbox-cell'
}
local TOTALCLASSES = {
init = 'crossbox-total',
[1] = 'crossbox-total crossbox-total-win',
[0] = 'crossbox-total crossbox-total-draw',
[-1] = 'crossbox-total crossbox-total-loss'
}
local TOGGLES = {
order = { 'match', 'game' },
}
local FORM_INFO = { form = 'TeamHeadToHeadSchedule', template = 'TH2HS' }
local h = {}
local p = {}
function p.fromCargo(frame)
i18n.init('Crossbox')
local args = util_args.merge()
if not args.crossboxtype then
error('Must specify |crossboxtype=')
end
local crossboxtype = lang:lc(args.crossboxtype)
local overviewPage = util_esports.getOverviewPage(args.page)
local data = h.getData(overviewPage, args)
if util_args.castAsBool(args.initializeall) then
h.addZeroes(data)
end
return h.makeOutput(data, crossboxtype, util_args.castAsBool(args.groups))
end
function p.fromArgs(frame)
i18n.init('Crossbox')
local args = util_args.merge()
h.setConstants(args)
if not args.crossboxtype then
error('Must specify |crossboxtype=')
end
local crossboxtype = lang:lc(args.crossboxtype)
local data = h.getDataFromArgs(args)
return h.makeOutput(data, crossboxtype, util_args.castAsBool(args.groups))
end
function h.setConstants(args)
if util_args.castAsBool(args.nolinks) then
SHOW_LINKS = false
end
end
-- CARGO DATA COLLECTION
function h.getData(overviewPage, args)
local result = h.makeAndRunQuery(overviewPage, args)
if #result == 0 then
return {}
end
local data = h.parseResult(result)
local groupresult
if util_args.castAsBool(args.groups) or args.onlygroup then
groupresult = util_tournament.getGroups(overviewPage)
if #groupresult == 0 then
args.groups = false
else
h.addGroupDataToTeams(data, groupresult)
end
end
local teamlist = h.getTeamOrder(args.teamlist, groupresult, args.onlygroup)
h.sortData(data, teamlist)
return data
end
function h.makeAndRunQuery(page, args)
local query = {
tables = 'MatchSchedule',
fields = {
'Team1Final=Team1',
'Team2Final=Team2',
'Winner',
'Team1Score [number]',
'Team2Score [number]',
'FF [number]',
},
groupBy = 'MatchId',
where = h.makeWhere(page, args),
}
return util_cargo.queryAndCast(query)
end
function h.makeWhere(page, args)
if args.where then return args.where end
local tbl = {
('OverviewPage="%s"'):format(page),
}
if lang:lc(args.tiebreakers or '') == 'only' then
tbl[#tbl+1] = '(IsTiebreaker = "1")'
elseif not util_args.castAsBool(args.tiebreakers) then
tbl[#tbl+1] = '(IsTiebreaker != "1" OR IsTiebreaker IS NULL)'
end
if args.excludetabs then
for v in util_text.gsplit(args.excludetabs, sep) do
tbl[#tbl+1] = ('Tab != "%s"'):format(v)
end
end
if args.onlytabs then
local onlyrounds_tbl = {}
for v in util_text.gsplit(args.onlytabs, sep) do
onlyrounds_tbl[#onlyrounds_tbl+1] = ('Tab = "%s"'):format(v)
end
tbl[#tbl+1] = ('(%s)'):format(util_table.concat(onlyrounds_tbl, ' OR '))
end
return util_table.concat(tbl, ' AND ')
end
function h.parseResult(result)
local teams = {}
for _, row in ipairs(result) do
local team1, team2 = row.Team1, row.Team2
h.initializeMatchup(teams, team1, team2)
h.addResults(teams, row, team1, team2)
end
return teams
end
function h.initializeMatchup(teams, team1, team2)
if not team1 or not team2 then
return
end
h.initializeTeam(teams, team1)
h.initializeTeam(teams, team2)
if teams[team1][team2] then
return
end
h.addMatchupZeroes(teams[team1], team1, team2)
h.addMatchupZeroes(teams[team2], team2, team1)
return
end
function h.addMatchupZeroes(team1tbl, team1, team2)
team1tbl[team2] = {
wgames = 0,
lgames = 0,
wins = 0,
losses = 0,
ties = 0,
team2 = team2,
link = h.getLink(team1, team2)
}
end
function h.getLink(team1, team2)
if not SHOW_LINKS then return nil end
return util_form.makeTableCellFilterLink(FORM_INFO, {team1, team2}, 'crossbox-match-link')
end
function h.initializeTeam(tbl, team)
if tbl[team] then
return
end
tbl[#tbl+1] = team
tbl[team] = { wgames = 0, lgames = 0, wins = 0, losses = 0, ties = 0, team = team }
return
end
function h.addResults(teams, row, team1, team2)
if not team1 or not team2 then
return
end
local results = {
[team1] = h.getResults('1', '2', row),
[team2] = h.getResults('2', '1', row)
}
local opponents = { [team1] = team2, [team2] = team1 }
for team, data in pairs(results) do
for k, v in pairs(data) do
teams[team][opponents[team]][k] = teams[team][opponents[team]][k] + v
teams[team][k] = teams[team][k] + v
end
end
return
end
function h.getResults(n, vs, row)
local lossesFromFF = row.FF == 0 and 1 or 0
return {
wins = row.Winner == n and 1 or 0,
losses = row.Winner == vs and 1 or 0 + lossesFromFF,
ties = row.Winner == '0' and row.FF ~= 0 and 1 or 0,
wgames = row['Team' .. n .. 'Score'],
lgames = row['Team' .. vs .. 'Score']
}
end
function h.addGroupDataToTeams(data, groupresult)
local dict = util_cargo.makeConstDict(groupresult, 'Team', 'GroupDisplay')
for _, team in ipairs(data) do
data[team].group = dict[team]
end
end
function h.getTeamOrder(teamlist, groupresult, onlygroup)
if teamlist then
return util_map.split(teamlist, sep, m_team.teamlinkname)
elseif groupresult then
if onlygroup then
for k, row in ipairs(groupresult) do
if row.GroupName ~= onlygroup then
groupresult[k] = false
end
end
util_table.removeFalseEntries(groupresult)
end
return util_table.arrayFromField(groupresult, 'Team')
else
return nil
end
end
function h.sortData(tbl, teamlist)
if teamlist then
local onlyteams = util_table.hash(teamlist)
for k, v in ipairs(tbl) do
if not onlyteams[v] then
tbl[k] = false
end
end
util_table.removeFalseEntries(tbl)
end
if teamlist then
util_table.sortByKeyOrder(tbl, teamlist)
else
table.sort(tbl, function(a, b)
return lang:lc(a) < lang:lc(b)
end
)
end
return
end
-- ARGS DATA COLLECTION
function h.getDataFromArgs(args)
local teams = util_args.numberedArgsToTable(args, 'team')
local groups = args.groups and util_text.split(args.groups, sep) or {}
util_map.inPlace(teams, m_team.teamlinkname)
for i, team1 in ipairs(teams) do
teams[team1] = {
wgames = 0,
lgames = 0,
wins = 0,
losses = 0,
ties = 0,
group = groups[i],
region = Region(args['region' .. i]),
team = team1
}
for j, team2 in ipairs(teams) do
local link = h.getLink(team1, team2)
teams[team1][team2] = { team2 = team2, link = link }
h.addSeriesScore(teams[team1][team2], teams[team1], args[('t%st%sscore'):format(i, j)])
h.addGameScore(teams[team1][team2], teams[team1], args[('t%st%sgames'):format(i, j)])
end
end
return teams
end
function h.addSeriesScore(teamtbl, totaltbl, arg)
if not arg then return end
local numbers = util_text.split(arg, '%s*-%s*')
if #numbers < 2 then
error(('A series arg with value "%s" has incorrect formatting, must be "x - x" or "x - x - x"'):format(arg))
end
if #numbers == 3 then
teamtbl.wins = tonumber(numbers[1] or '') or 0
teamtbl.ties = tonumber(numbers[2] or '') or 0
teamtbl.losses = tonumber(numbers[3] or '') or 0
teamtbl.wgames = 2 * teamtbl.wins + teamtbl.ties
teamtbl.lgames = 2 * teamtbl.losses + teamtbl.ties
totaltbl.wgames = totaltbl.wgames + teamtbl.wgames
totaltbl.lgames = totaltbl.lgames + teamtbl.lgames
elseif #numbers == 2 then
teamtbl.wins = tonumber(numbers[1] or '') or 0
teamtbl.losses = tonumber(numbers[2] or '') or 0
teamtbl.ties = 0
end
totaltbl.wins = totaltbl.wins + teamtbl.wins
totaltbl.losses = totaltbl.losses + teamtbl.losses
totaltbl.ties = totaltbl.ties + teamtbl.ties
return
end
function h.addGameScore(teamtbl, totaltbl, arg)
if not arg then return end
local w, l = arg:match('(%d+)%s*-%s*(%d+)')
if not w or not l then
error(('A game arg with value "%s" has incorrect formatting, must be "x - x"'):format(arg))
end
teamtbl.wgames = tonumber(w or '') or 0
teamtbl.lgames = tonumber(l or '') or 0
totaltbl.wgames = totaltbl.wgames + teamtbl.wgames
totaltbl.lgames = totaltbl.lgames + teamtbl.lgames
return
end
function h.addZeroes(data)
for _, team in ipairs(data) do
for _, team2 in ipairs(data) do
if not data[team][team2] then
h.addMatchupZeroes(data[team], team2)
end
end
end
end
-- DISPLAY
function h.makeOutput(data, crossboxtype, usegroups)
local output = mw.html.create()
if crossboxtype ~= 'bo1' then
h.printToggler(output)
end
h.printTable(output, data, crossboxtype, usegroups)
return output
end
function h.printToggler(tbl)
local div = tbl:tag('div')
:addClass('toggle-button')
util_toggle.printOptionFromListTogglers(div, TOGGLES)
util_html.clear(tbl)
return
end
function h.printTable(output, data, crossboxtype, usegroups)
local f = h.getCellFunction(crossboxtype)
local div = output:tag('div')
:addClass('crossbox-outer')
local tbl = div:tag('table')
:addClass('wikitable2')
:addClass('plainlinks')
:addClass('crossbox')
h.printHeading(tbl, data, crossboxtype, usegroups)
for _, team in ipairs(data) do
local tr = h.printRow(tbl, team, data, f, usegroups)
end
return output
end
function h.getCellFunction(bestof)
if bestof == 'bo1' then
return h.printCellBO1
elseif bestof == 'bo2' then
return h.printCellBO2
else
return h.printCellBO3
end
end
function h.printHeading(tbl, data, crossboxtype, usegroups)
local tr = tbl:tag('tr')
tr:tag('td')
:addClass('crossbox-mirror')
:addClass('crossbox-firstcol')
if usegroups then
tr:tag('td')
:addClass('crossbox-mirror')
end
for _, team in ipairs(data) do
local th = h.printTeamCell(tr, team, data[team])
th:addClass('crossbox-teamvs')
:attr('data-crossbox-highlight-vs', team)
end
tr:tag('th'):wikitext(i18n.print('total'))
tr:tag('th'):wikitext(i18n.print('wr'))
return
end
function h.printTeamCell(tr, team, teamData)
local th = tr:tag('th')
:addClass('crossbox-cell')
if teamData.region then
th:wikitext(teamData.region:image())
end
th:wikitext(m_team.onlyimage(team,{size=45}))
:attr('title', m_team.teamname(team))
return th
end
function h.printRow(tbl, team, data, f, usegroups)
local tr = tbl:tag('tr')
util_esports.addTeamHighlighter(tr, team)
if usegroups then
tr:tag('th')
:wikitext(data[team].group)
:addClass('crossbox-firstcol')
end
local th = h.printTeamCell(tr, team, data[team])
if not usegroups then
th:addClass('crossbox-firstcol')
end
for _, v in ipairs(data) do
h.printCell(tr, data, team, v, f)
end
f(tr, data[team], TOTALCLASSES)
f(tr, data[team], TOTALCLASSES, true)
return tr
end
function h.printCell(tr, data, team1, team2, f)
if team1 == team2 then
tr:tag('td')
:addClass('crossbox-mirror')
:addClass('crossbox-cell')
:attr('data-crossbox-highlight-vs', team2)
return
elseif not data[team1][team2] then
tr:tag('td')
:addClass('crossbox-cell')
:attr('data-crossbox-highlight-vs', team2)
return
else
return f(tr, data[team1][team2], CLASSES)
end
end
function h.printCellBO1(tr, teamdata, classes, isPercent)
local w, l = teamdata.wins, teamdata.losses
local td = h.printRecordCell(tr, teamdata.team2)
h.addColorClass(td, w, l, 0, classes)
local div = h.printRecordDiv(td)
if w and l then
if not isPercent then
div:wikitext(('%s - %s'):format(w, l))
div:wikitext(teamdata.link)
else
h.printPercent(div, w, l)
end
end
return
end
function h.printCellBO2(tr, teamdata, classes, isPercent)
local w, l, t = teamdata.wins, teamdata.losses, teamdata.ties
local tdMatch = h.printRecordCell(tr, teamdata.team2, 'match')
h.addColorClass(tdMatch, w, l, t, classes)
local divSeries = h.printRecordDiv(tdMatch)
wg, lg = teamdata.wgames, teamdata.lgames
local tdGame = h.printRecordCell(tr, teamdata.team2, 'game')
h.addColorClass(tdGame, wg, lg, 0, classes)
local divGame = h.printRecordDiv(tdGame)
if not isPercent then
divSeries:wikitext(('%s - %s - %s'):format(w, t, l), teamdata.link)
divGame:wikitext(('%s - %s'):format(wg, lg), teamdata.link)
else
divSeries:wikitext('-')
h.printPercent(divGame, wg, lg)
end
end
function h.printCellBO3(tr, teamdata, classes, isPercent)
local w, l = teamdata.wins, teamdata.losses
local tdMatch = h.printRecordCell(tr, teamdata.team2, 'match')
h.addColorClass(tdMatch, w, l, 0, classes)
local divMatch = h.printRecordDiv(tdMatch)
wg, lg = teamdata.wgames, teamdata.lgames
local tdGame = h.printRecordCell(tr, teamdata.team2, 'game')
h.addColorClass(tdGame, wg, lg, 0, classes)
local divGame = h.printRecordDiv(tdGame)
if not isPercent then
divMatch:wikitext(('%s - %s'):format(w, l), teamdata.link)
divGame:wikitext(('%s - %s'):format(wg, lg), teamdata.link)
else
h.printPercent(divMatch, w, l)
h.printPercent(divGame, wg, lg)
end
end
function h.printRecordCell(tr, team2, cellType)
local td = tr:tag('td')
:attr('data-crossbox-highlight-vs', team2)
if cellType then
util_toggle.oflCellClasses(td, TOGGLES, cellType)
end
return td
end
function h.addColorClass(td, w, l, t, lookup)
w = w or 0
l = l or 0
t = t or 0
if w + l + t == 0 then
td:addClass(lookup.init)
else
td:addClass(lookup[util_math.sign(w-l)])
end
end
function h.printRecordDiv(td)
local div = td:tag('div')
:addClass('table-cell-container')
return div
end
function h.printPercent(div, w, l)
div:wikitext(util_esports.winrate(w, l, .01), '%')
end
return p