Call of Duty Esports Wiki
Advertisement

To edit the documentation or categories for this module, click here. This module has an i18n file. Click here to edit it.

See {{MatchDetails}} for usage information.


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_map = require('Module:MapUtil')
local util_matches = require('Module:MatchesUtil')
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 m_team = require('Module:Team')

local lang = mw.getLanguage('en')

sep = '%s*,%s*'

local VODLIST = { 'Vod', 'Vod2', 'Vod3', 'Vod4', 'Vod5', 'Vod6', 'Vod7' }

local HIDDENCLASS = 'toggle-section-hidden'
local TAB_TOGGLES = {
	row = 'mdv-allweeks mdv-week%s %s',
	all = {
		show_attr = '.mdv-allweeks',
		hide_attr = '.mdv-showbuttons',
		show_class = 'mdv-allweeks',
		hide_class = 'mdv-showbuttons',
		show_text = 'show all',
		hide_text = 'hide all',
	},
	week = {
		show_attr = '.mdv-week%s',
		hide_attr = '.mdv-showbutton%s',
		show_class = 'mdv-allweeks mdv-week%s',
		hide_class = 'mdv-showbuttons mdv-showbutton%s',
	}
}

local i18n = {
	Vod = 'Vod',
	Vod2 = 'Vod2',
	Vod3 = 'Vod3',
	Vod4 = 'Vod4',
	Vod5 = 'Vod5',
	Vod6 = 'Vod6',
	Vod7 = 'Vod7',
	Team1Display = 'Team 1',
	Team2Display = 'Team 2',
	Selection = 'Side Sel',
	header = 'VODs & Match Links',
	Highlights = 'HL',
}

local FIELD_ORDER = {
	match = { 'Team1', 'Team2', 'Score', 'PBP', 'Color', 'Interview', 'With', 'Highlights', 'Recap', 'Reddit', 'MVP', 'VODs' },
	game = { 'Blue', 'Red', 'Selection', 'MH', 'Interview', 'With', 'MVP' }
}

local FIELD_LOOKUP = {
	match = {
		pbp = 'PBP',
		color = 'Color',
		int = 'Interview',
		interview = 'Interview',
		w = 'With',
		with = 'With',
		recap = 'Recap',
		reddit = 'Reddit',
		vods = 'VODs',
		mvp = 'MVP',
		hl = 'Highlights',
		highlights = 'Highlights'
	},
	game = {
		b = 'Blue',
		blue = 'Blue',
		r = 'Red',
		red = 'Red',
		ssel = 'Selection',
		['side selection'] = 'Selection',
		mh = 'MH',
		['match history'] = 'MH',
		int = 'Interview',
		interview = 'Interview',
		w = 'With',
		with = 'With',
		mvp = 'MVP',
	}
}

local THIS

local h = {}

local p = {}
function p.main(frame)
	local args = util_args.merge()
	local overviewPage = util_esports.getOverviewPage(args.page)
	local matchData = h.getMatchData(overviewPage, args)
	THIS = util_matches.determineThis(matchData, args.This)
	local gameData = h.getGameData(overviewPage, args)
	h.addGameDataToMatches(matchData, gameData)
	local fields = h.pickFields(args.matchfields, args.gamefields)
	return h.makeOutput(matchData, fields)
end

function h.getMatchData(page, args)
	local matchResult = util_cargo.queryAndCast(h.makeMatchQuery(page, args))
	util_map.rowsInPlace(matchResult, h.processMatchRow)
	local matchData = util_cargo.groupResultOrdered(matchResult, 'Tab')
	return matchData
end

function h.makeMatchQuery(page, args)
	local query = {
		tables = 'MatchSchedule',
		fields = {
			'Team1',
			'Team2',
			'Player1',
			'Player2',
			'Winner [number]',
			'Team1Score [number]',
			'Team2Score [number]',
			'FF [number]',
			'Tab',
			'UniqueMatch',
			'CastersPBP',
			'CastersColor',
			'MVP',
			'VodInterview',
			'Vod',
			'Vod2',
			'Vod3',
			'Vod4',
			'Vod5',
			'Vod6',
			'Vod7',
			'InterviewWith',
			'Recap',
			'Reddit',
			'DateTime_UTC=UTC',
		},
		where = h.makeMatchWhere(page, args),
		orderBy = 'N_Page ASC, N_TabInPage ASC, N_MatchInTab ASC',
		groupBy = 'UniqueMatch',
	}
	return query
end

function h.makeMatchWhere(page, args)
	local tbl = {
		('OverviewPage="%s"'):format(page)
	}
	return util_table.concat(tbl,' AND ')
end
	
function h.processMatchRow(row)
	row.Team1Display = h.getPlayerOrTeamDisplay(row, 1)
	row.Team2Display = h.getPlayerOrTeamDisplay(row, 2)
	if row.FF then
		row['Team' .. row.FF .. 'Score'] = 'FF'
		row['Team' .. util_esports.otherTeamN(row.FF) .. 'Score'] = 'W'
	else
		-- don't print casters if it's a forfeit
		row.PBP = util_esports.playersLinked(row.CastersPBP)
		row.Color = util_esports.playersLinked(row.CastersColor)
	end
	if row.Team1Score and row.Team2Score then
		row.Score = ('%s - %s'):format(row.Team1Score, row.Team2Score)
	else
		row.Score = 'TBD'
	end
	row.MVP = util_esports.playersLinked(row.MVP)
	row.With = util_esports.playersLinked(row.InterviewWith)
	row.Recap = util_text.extLink(row.Recap)
	row.Interview = util_text.extLink(row.VodInterview)
	row.Highlights = util_text.extLink(row.VodHighlights)
	row.Reddit = util_text.extLink(row.Reddit)
	row.VODs = h.makeMatchVodList(row)
	row.classes = {
		Team1 = row.Winner == 1 and 'md-winner',
		Team2 = row.Winner == 2 and 'md-winner'
	}
end

function h.makeMatchVodList(row)
	local tbl = {}
	for _, v in ipairs(VODLIST) do
		if row[v] then
			tbl[#tbl+1] = ('[%s %s]'):format(row[v], i18n[v])
		end
	end
	return table.concat(tbl, ' • ')
end

function h.getPlayerOrTeamDisplay(row, i)
	if not row['Player' .. i] then
		return row['Team' .. i] and m_team.rightshort(row['Team' .. i])
	end
	return m_team.onlyimageshort(row['Team' .. i]) .. util_esports.playerLinked(row['Player' .. i])
end

function h.getPostersDisplay(row)
	if not row.Team1Poster and not row.Team2Poster then return nil end
	local tbl = {}
	tbl[#tbl+1] = row.Team1Poster and util_text.intLink(':' .. row.Team1Poster, m_team.short(row.Team1))
	tbl[#tbl+1] = row.Team2Poster and util_text.intLink(':' .. row.Team2Poster, m_team.short(row.Team2))
	return util_table.concat(tbl, ' • ')
end

function h.getGameData(page, args)
	local gameResult = util_cargo.queryAndCast(h.makeGameQuery(page, args))
	util_map.rowsInPlace(gameResult, h.processGameRow)
	local gameData = util_cargo.groupResultByValue(gameResult, 'UniqueMatch')
	return gameData
end

function h.makeGameQuery(page, args)
	local query = {
		tables = 'MatchScheduleGame',
		fields = {
			'Blue',
			'Red',
			'Winner [number]',
			'Selection',
			'ShownName=Selection',
			'Recap',
			'VodInterview',
			'InterviewWith',
			'MVP',
			'MatchHistory',
			'UniqueMatch',
		},
		where = h.makeGameWhere(page, args),
		orderBy = 'N_Page ASC, N_TabInPage ASC, N_MatchInTab, N_GameInMatch',
		limit = 9999,
		groupBy = 'UniqueLine',
	}
	return query
end

function h.makeGameWhere(page, args)
	local tbl = {
		('OverviewPage="%s"'):format(page)
	}
	return util_table.concat(tbl,' AND ')
end

function h.processGameRow(row)
	local hasteams = row.Blue and row.Red
	local sel = h.getSelectionSide(row)
	row.VODs = h.makeGameVodList(row)
	row.Interview = util_text.extLink(row.VodInterview)
	row.Blue = m_team.short(row.Blue)
	row.Red = m_team.short(row.Red)
	row.Selection = row.Selection and m_team.short(row.Selection)
	row.Recap = util_text.extLink(row.Recap)
	row.MH = util_text.extLink(row.MatchHistory)
	row.MVP = util_esports.playersLinked(row.MVP)
	row.With = util_esports.playersLinked(row.InterviewWith)
	row.Summary = h.makeSummary(row.Summary)
	row.Reddit = util_text.extLink(row.Reddit)
	row.classes = {
		Blue = row.Winner == 1 and 'md-winner',
		Red = row.Winner == 2 and 'md-winner',
		Selection = hasteams and row.Selection and ('standings-mh%s'):format(sel)
	}
end

function h.getSelectionSide(row)
	if not row.Selection then
		return
	end
	return row.Selection == row.Blue and 'Blue' or 'Red'
end

function h.makeGameVodList(row)
	local tbl = {}
	for _, v in ipairs(VODLIST) do
		if row[v] then
			tbl[#tbl+1] = ('[%s %s]'):format(row[v], i18n[v])
		end
	end
	return table.concat(tbl, ' • ')
end

function h.makeSummary(summary)
	if not summary then return nil end
	local popupButton = util_toggle.popupButton()
	popupButton.wrapper
		:addClass('written-summary-outer')
	popupButton.inner:addClass('written-summary-inner')
		:wikitext(summary)
	return tostring(popupButton.tbl)
end

function h.addGameDataToMatches(matchData, gameData)
	for _, tab in ipairs(matchData) do
		for _, row in ipairs(tab) do
			row.gameData = gameData[row.UniqueMatch] or { { classes = {} } }
		end
	end
	return true
end

-- output
function h.pickFields(matcharg, gamearg)
	local matchfields = util_text.split(matcharg or '',sep)
	local gamefields = util_text.split(gamearg or '',sep)
	local tbl = {
		match = { 'Team1Display', 'Team2Display', 'Score' },
		game = {}
	}
	for _, v in ipairs(matchfields) do
		tbl.match[#tbl.match+1] = FIELD_LOOKUP.match[lang:lc(v)]
	end
	for _, v in ipairs(gamefields) do
		tbl.game[#tbl.game+1] = FIELD_LOOKUP.game[lang:lc(v)]
	end
	util_table.sortByKeyOrder(tbl.match, FIELD_ORDER.match)
	util_table.sortByKeyOrder(tbl.game, FIELD_ORDER.game)
	return tbl
end

function h.makeOutput(matchData, fields)
	local colspan = #fields.match + #fields.game
	local output = mw.html.create()
	local tbl = output:tag('table')
		:addClass('wikitable')
		:addClass('md-table')
		:attr('id','md-table')
		:css('min-width', math.max(22, 2 * colspan) .. 'em')
	if #matchData > 1 then
		util_toggle.printToggleHeader(tbl, colspan, i18n.header, TAB_TOGGLES.all)
	else
		util_html.printColspanHeader(tbl, i18n.header, colspan)
	end
	for i, tabData in ipairs(matchData) do
		h.printTab(tbl, tabData, fields, i, THIS == i)
	end
	return output
end

function h.printTab(tbl, tabData, fields, i, isfocused)
	h.printColspanHeading(tbl, tabData.name, fields, i, isfocused)
	local toggle_class = h.getRowToggleClass(i, isfocused)
	h.printHeading(tbl, fields, toggle_class)
	for _, row in ipairs(tabData) do
		h.printRow(tbl, row, fields, toggle_class)
	end
end

function h.printColspanHeading(tbl, name, fields, i, isfocused)
	local toggle_data = h.getWeekToggleData(i, isfocused)
	local colspan = #fields.match + #fields.game
	util_toggle.printToggleHeader(tbl, colspan, name, toggle_data)
end

function h.getWeekToggleData(i, isfocused)
	local data = mw.clone(TAB_TOGGLES.week)
	data.initshown = isfocused
	util_toggle.prepDataByWeek(data, i)
	return data
end

function h.getRowToggleClass(i, isfocused)
	return TAB_TOGGLES.row:format(i, isfocused and '' or HIDDENCLASS)
end

function h.printHeading(tbl, fields, toggle_class)
	local tr = tbl:tag('tr')
		:addClass('column-label-small')
		:addClass(toggle_class)
	for _, v in ipairs(fields.match) do
		tr:tag('th'):wikitext(i18n[v] or v)
	end
	for _, v in ipairs(fields.game) do
		tr:tag('th'):wikitext(i18n[v] or v)
	end
	return
end

function h.printRow(tbl, row, fields, toggle_class)
	local tr = tbl:tag('tr')
		:addClass(toggle_class)
	local rowspan = h.getRowspan(fields.game, row.gameData, row.FF)
	h.printMatchFields(tr, row, fields.match, rowspan)
	local gameData = row.FF and { { classes = {} } } or row.gameData
	h.printGamesFields(tbl, tr, gameData, fields.game, toggle_class)
end

function h.getRowspan(game, gameData, isFF)
	if not game or not next(gameData) or isFF then
		return 1
	else
		return #gameData
	end
end

function h.printMatchFields(tr, row, fields, rowspan)
	for _, v in ipairs(fields) do
		tr:tag('td')
			:attr('rowspan',rowspan)
			:addClass(row.classes[v] or '')
			:wikitext(row[v])
	end
end

function h.printGamesFields(tbl, tr, gameData, fields, toggle_class)
	for i, game in ipairs(gameData) do
		if i ~= 1 then
			tr = tbl:tag('tr')
				:addClass(toggle_class)
		end
		h.printOneGameFields(tr, game, fields)
	end
end

function h.printOneGameFields(tr, game, fields)
	for _, v in ipairs(fields) do
		tr:tag('td')
			:addClass(game.classes[v] or '')
			:wikitext(game[v])
	end
end

return p
Advertisement