Module:TopSchedule

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 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 = h.getFields, groupBy = 'MS.UniqueMatch', orderBy = 'MS.DateTime_UTC ASC', where = h.getWhere, limit = 250, types = { TimeEntered = 'boolean' }	} end

function h.getFields local ret = { 'MS.Team1', 'MS.Team2', 'MS.Player1', 'MS.Player2', 'MS.DateTime_UTC=DateTime', 'MS.OverviewPage', 'MS.HasTime=TimeEntered', 'MS.ShownName', 'MS.Round', 'MS.Tab', 'MS.Stream' }	return ret 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"', }	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, 25) 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) local tbl = { h.makeTeamAndPlayer(row.Team1, row.Player1, 1), h.makeTeamAndPlayer(row.Team2, row.Player2, 2), }	return table.concat(tbl, '') end

function h.makeTeamAndPlayer(team, player, i)	local output = mw.html.create('div') :addClass(('topschedule-vs-1v1-player-%s'):format(i)) :wikitext(m_team.onlyimageshort(team)) :wikitext(util_esports.playerLinked(player)) return tostring(output) 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.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') :wikitext(matchup) end

function h.printVs(div, matchup) local vsOuter = div:tag('div') :addClass('topschedule-vs') :wikitext(matchup) end

function h.printTime(div, row) local timeOuter = div:tag('div') :addClass('topschedule-time plainlinks') :wikitext(row.Countdown, ' &bull; ', row.Calendar) end

return p