Edit the documentation or categories for this module.
To exclude a match from the top schedule, use |no_topschedule=Yes
in {{Infobox Tournament}}
.
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_table = require('Module:TableUtil')
local util_text = require('Module:TextUtil')
local util_time = require('Module:TimeUtil')
local util_vars = require('Module:VarsUtil')
local m_team = require('Module:Team')
local MIN_EVENTS_COUNT_TO_GROUP = 3
local MIN_EVENTS_COUNT_TO_GROUP_WITH_UNKNOWN_TEAMS = 2
local SECONDS_IN_HOUR = 60 * 60
local MAX_SERIES_TO_INCLUDE = 50
local FORM_INFO = {
form = 'SpoilerFreeSchedule',
template = 'SFS'
}
local h = {}
local p = {}
function p.main(frame)
local args = util_args.merge()
local result = h.doQuery()
local processed = h.processResult(result)
h.formatResults(processed)
return h.makeOutput(processed)
end
function h.doQuery()
local query = h.makeQuery(where)
return util_cargo.queryAndCast(query)
end
function h.makeQuery(where)
return {
tables = 'MatchSchedule=MS, Tournaments=T',
join = { 'MS.OverviewPage=T.OverviewPage' },
fields = {
'MS.Team1',
'MS.Team2',
'MS.Player1',
'MS.Player2',
'MS.DateTime_UTC=DateTime',
'MS.OverviewPage',
'MS.HasTime=TimeEntered [boolean]',
'MS.ShownName',
'MS.Round',
'MS.Tab',
'MS.Stream',
'T.StandardName',
'T.Name'
},
groupBy = 'MS.MatchId',
orderBy = 'MS.DateTime_UTC ASC',
where = h.getWhere(),
limit = 250,
}
end
function h.getWhere()
local ret = {
'MS.DateTime_UTC > NOW() - INTERVAL 3 HOUR AND WINNER IS NULL',
'T.SuppressTopSchedule IS NULL OR T.SuppressTopSchedule="0"',
-- suppress all self pages from storing here automatically since they don't write cargo
'T._pageName IS NOT NULL',
}
return util_cargo.concatWhere(ret)
end
function h.processResult(result)
local eventCount = h.countEvents(result)
local eventsWrittenToOutput = {}
local processed = {}
for _, row in ipairs(result) do
if not eventsWrittenToOutput[row.groupKey] then
row.count = eventCount[row.groupKey]
processed[#processed+1] = row
end
eventsWrittenToOutput[row.groupKey] = eventCount[row.groupKey]
end
local output = util_table.slice(processed, 1, MAX_SERIES_TO_INCLUDE)
return output
end
function h.countEvents(result)
local tracker = {}
local eventCount = {}
for _, row in ipairs(result) do
row.groupKey = row.OverviewPage .. row.DateTime
h.updateTracker(tracker, row)
if h.doWeGroup(row, tracker.counter) then
eventCount[row.groupKey] = tracker.counter
end
end
return eventCount
end
function h.updateTracker(tracker, row)
if tracker.groupKey == row.groupKey then
tracker.counter = (tracker.counter or 0) + 1
else
tracker.counter = 1
end
tracker.groupKey = row.groupKey
end
function h.doWeGroup(row, counter)
if row.Team1 == 'TBD' and row.Team2 == 'TBD' then
return counter >= MIN_EVENTS_COUNT_TO_GROUP_WITH_UNKNOWN_TEAMS
end
return counter >= MIN_EVENTS_COUNT_TO_GROUP
end
function h.formatResults(result)
for i, row in ipairs(result) do
h.addMatchup(row)
h.addEventLinked(row)
h.addCountdown(row, i)
h.addCalendar(row)
end
end
function h.addMatchup(row)
if row.count then
row.Matchup = ('%s Matches'):format(row.count)
elseif not (row.Team1 or row.Team2) and not (row.Player1 or row.Player2) then
row.Matchup = row.Round or row.Tab
elseif row.Player1 or row.Player2 then
row.Is1v1 = true
row.Matchup = h.make1v1Matchup(row)
else
Team1Formatted = h.formatTeamForMatchup(row.Team1)
Team2Formatted = h.formatTeamForMatchup(row.Team2)
row.Matchup = ('%s vs %s'):format(Team1Formatted, Team2Formatted)
end
end
function h.make1v1Matchup(row)
return ('%s vs %s'):format(util_esports.playerLinked(row.Player1), util_esports.playerLinked(row.Player2))
end
function h.formatTeamForMatchup(team)
if team == 'TBD' then
return 'TBD'
end
return m_team.onlyimagelinked(team, {size = 45})
end
function h.addEventLinked(row)
row.EventLinked = util_text.intLink(row.OverviewPage, row.ShownName or row.StandardName or row.Name or row.OverviewPage)
end
function h.addCountdown(row, i)
local countdown = util_time.countdown(row.DateTime, {
data_end = 'toggle',
i = 'ts-' .. i,
default = 'LIVE'
})
row.Countdown = util_text.extLinkOrText(row.Stream, countdown)
end
function h.addCalendar(row)
row.Calendar = util_esports.calendarExtLink(util_form.fullURL(FORM_INFO, {row.OverviewPage}))
end
function h.makeOutput(result)
local output = mw.html.create('div'):addClass('topschedule')
:attr('id', 'top-schedule')
:css('display', 'none')
h.printContent(result, output)
return output
end
function h.printContent(result, div)
for i, row in ipairs(result) do
local innerDiv = h.initializeInnerDiv(div, row, i)
h.printHeader(innerDiv, row.EventLinked)
if row.Is1v1 then
h.printVs1v1(innerDiv, row.Matchup)
else
h.printVs(innerDiv, row.Matchup)
end
h.printTime(innerDiv, row)
end
end
function h.initializeInnerDiv(div, row, i)
local expiration = util_time.unixNumber(row.DateTime) + SECONDS_IN_HOUR
local innerDiv = div:tag('div')
:addClass('topschedule-box')
:attr('data-expiration', expiration)
:attr('data-i',i)
return innerDiv
end
function h.printHeader(div, event)
div:tag('div')
:addClass('topschedule-header')
:wikitext(event)
end
function h.printVs1v1(div, matchup)
local vsOuter = div:tag('div')
:addClass('topschedule-vs-1v1')
:attr("data-nosnippet", "true")
:wikitext(matchup)
end
function h.printVs(div, matchup)
local vsOuter = div:tag('div')
:addClass('topschedule-vs')
:attr("data-nosnippet", "true")
:wikitext(matchup)
end
function h.printTime(div, row)
local timeOuter = div:tag('div')
:addClass('topschedule-time plainlinks')
:attr("data-nosnippet", "true")
:wikitext(row.Countdown, ' • ', row.Calendar)
end
return p