Leaguepedia | League of Legends Esports Wiki
Advertisement

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_game = require('Module:GameUtil')
local util_html = require('Module:HtmlUtil')
local util_map = require('Module:MapUtil')
local util_math = require('Module:MathUtil')
local util_sort = require('Module:SortUtil')
local util_stats = require('Module:StatsUtil')
local util_table = require('Module:TableUtil')
local util_text = require('Module:TextUtil')
local util_time = require('Module:TimeUtil')
local util_title = require('Module:TitleUtil')
local util_vars = require('Module:VarsUtil')
local i18n = require('Module:i18nUtil')
local m_team = require('Module:Team')
local RegionList = require('Module:RegionList')
local ColumnShowHide = require('Module:ColumnShowHide')
local ReplaceRedirects = require('Module:ReplaceRedirects')
local SETTINGS = require('Module:MatchHistoryGame/Settings')
local PRELOAD
local DEFAULT_LIMIT = 50

local h = {}
local p = {}
function p.main(frame)
	local args = util_args.merge()
	local args2 = h.castArgs(args)
	i18n.init('MatchHistoryGame')
	h.setPreloadAndValidate(args)
	local data = h.getData(args2)
	h.countData(data, args)
	if util_args.castAsBool(args.textonly) then
		h.formatDataText(data, args)
	else
		h.formatDataPretty(data, args)
	end
	return ReplaceRedirects.main(h.makeOutput(data, args, args2), args)
end

function h.castArgs(args)
	local args2 = mw.clone(args)
	args2.region = RegionList(args2.region)
	return args2
end

function h.setPreloadAndValidate(args)
	local preload = h.getPreload(args.preload .. (util_args.castAsBool(args.textonly) and 'text' or ''))
	PRELOAD = preload or h.getPreload(args.preload)
	util_stats.validatePreload(args, PRELOAD)
end

function h.getPreload(str)
	return SETTINGS.preloads[str:lower()]
end

-- cargo
function h.getData(args)
	local query = {
		tables = {
			'ScoreboardGames=SG',
			'Tournaments=IT'
		},
		join = {
			'SG.OverviewPage=IT.OverviewPage'
		},
		fields = {
			'SG.DateTime_UTC=Date',
			'IT.Region=Region [region]',
			'IT.StandardName=Tournament',
			'SG.Patch=Patch',
			'SG.Team1=Team1',
			'SG.Team2=Team2',
			'SG.WinTeam=WinTeam',
			'SG.Team1Bans__full=Team1Bans [ChampionList]',
			'SG.Team2Bans__full=Team2Bans [ChampionList]',
			'SG.Team1Picks__full=Team1Picks [ChampionList]',
			'SG.Team2Picks__full=Team2Picks [ChampionList]',
			'SG._pageName=_pageName',
			'SG.MatchHistory=MatchHistory',
			'SG.VOD=VOD',
			'SG.Gamelength=Gamelength',
			'SG.Team1Gold=Team1Gold',
			'SG.Team1Kills=Team1Kills',
			'SG.Team1Towers=Team1Towers',
			'SG.Team1Barons=Team1Barons',
			'SG.Team1Inhibitors=Team1Inhibitors',
			'SG.Team1Dragons=Team1Dragons',
			'SG.Team1RiftHeralds=Team1RiftHeralds',
			'SG.Team1VoidGrubs=Team1VoidGrubs',
			'SG.Team2Gold=Team2Gold',
			'SG.Team2Kills=Team2Kills',
			'SG.Team2Towers=Team2Towers',
			'SG.Team2Barons=Team2Barons',
			'SG.Team2Inhibitors=Team2Inhibitors',
			'SG.Team2Dragons=Team2Dragons',
			'SG.Team2RiftHeralds=Team2RiftHeralds',
			'SG.Team2VoidGrubs=Team2VoidGrubs',
			'SG.Team1Players__full=Team1Links',
			'SG.Team2Players__full=Team2Links',
			'IT._pageName=TournamentPage',
			'SG._pageName=ScoreboardPage',
			'SG.GameId',
		},
		where = h.getWhere(args),
		limit = h.getLimit(args),
		orderBy = h.getOrderBy(args),
		offset = args.offset,
	}
	local data = util_cargo.queryAndCast(query)
	return data
end

function h.getWhere(args)
	local tbl = {
		util_cargo.whereFromArg('(%s)', args.where),
		h.getEitherTeamWhereArg('', args.team and m_team.teamlinkname(args.team)),
		util_cargo.whereFromArgList('SG.OverviewPage="%s"', args.tournament, nil, util_title.target),
		h.getBanWhere(args.ban),
		h.getTeamHeadToHeadWhereArg(args.team1, args.team2),
		util_cargo.whereFromArgList('IT.TournamentLevel="%s"', args.tournamentlevel),
		util_cargo.whereFromCompoundEntity('IT.Region="%s"', args.region),
		util_cargo.whereFromArgList('IT.Year="%s"', args.year),
		util_cargo.whereFromArg('SG.DateTime_UTC >= "%s"', args.startdate),
		util_cargo.whereFromArg('SG.DateTime_UTC <= "%s"', args.enddate),
	}
	if args.record then
		tbl[#tbl+1] = ('%s IS NOT NULL'):format(args.record)
	end
	return util_cargo.concatWhere(tbl)
end

function h.getLimit(args)
	return args.limit or PRELOAD.limit or DEFAULT_LIMIT
end

function h.getEitherTeamWhereArg(str, value)
	if not value then return nil end
	return ('(SG.Team1%s="%s" OR SG.Team2%s="%s")'):format(str, value, str, value)
end

function h.getBanWhere(ban)
	if not ban then return nil end
	local tbl = {
		util_cargo.fakeHolds('SG.Team1Bans', ban),
		util_cargo.fakeHolds('SG.Team2Bans', ban)
	}
	return util_cargo.concatWhereOr(tbl)
end

function h.getTeamHeadToHeadWhereArg(team1, team2)
	if not (team1 and team2) then return nil end
	team1 = m_team.teamlinkname(team1)
	team2 = m_team.teamlinkname(team2)
	return ('((SG.Team1="%s" AND SG.Team2="%s") OR (SG.Team1="%s" AND SG.Team2="%s"))'):format(
		team1,
		team2,
		team2,
		team1
	)
end

function h.getOrderBy(args)
	if args.orderBy then return args.orderBy end
	if not args.record then
		return PRELOAD.orderBy or 'SG.DateTime_UTC DESC'
	end
	local order = util_args.castAsBool(args.ascending) and 'ASC' or 'DESC'
	return ('SG.%s %s'):format(args.record, order)
end

-- count
function h.countData(data, args)
	data.wins = {}
	for _, row in ipairs(data) do
		data.wins[row.WinTeam] = (data.wins[row.WinTeam] or 0) + 1
	end
end

-- format
function h.formatDataPretty(data, args)
	for n, row in ipairs(data) do
		h.formatRowPretty(row, args, n)
	end
end

function h.formatRowPretty(row, args, n)
	row.N = n
	row.UsN = h.getUsN(row, args)
	row.TournamentDisplay = util_stats.tournamentAndRegion(row)
	util_stats.infoLinks(row)
	row.Date = util_time.strToDateStr(row.Date)
	row.Patch = row.Patch and util_text.intLink('Patch ' .. row.Patch, row.Patch)
	row.Team1Display = m_team.onlyimagelinked(row.Team1)
	row.Team2Display = m_team.onlyimagelinked(row.Team2)
	row.WinTeamDisplay = m_team.onlyimagelinked(row.WinTeam)
	row.Side = row.UsN and util_game.side_names[row.UsN]
	row.BannedBy = row.Side
	row.class = row.Team1 == row.WinTeam and 'blue' or 'red'
	row.TournamentLink = util_text.intLinkOrText(row.Tournament)
	row.RegionDisplay = row.Region:flair()
	row.Team1BansDisplay = row.Team1Bans:images()
	row.Team2BansDisplay = row.Team2Bans:images()
	row.Team1PicksDisplay = row.Team1Picks:images()
	row.Team2PicksDisplay = row.Team2Picks:images()
	h.linkedRosters(row)
	h.addUsThemFields(row, args)
	h.setClassTHTH(row, args)
	h.checkIfTruePerfect(row)
end

function h.getUsN(row, args)
	if not PRELOAD.bias then
		return
	elseif PRELOAD.bias == 'Team' and m_team.teamlinkname(args.team) == row.Team1 then
		return 1
	elseif PRELOAD.bias == 'Team' and m_team.teamlinkname(args.team) == row.Team2 then
		return 2
	elseif PRELOAD.bias == 'Ban' and row.Team2Bans:has(nil, args.ban) then
		return 2
	elseif PRELOAD.bias == 'Ban' and row.Team1Bans:has(nil, args.ban) then
		return 1
	elseif PRELOAD.bias == 'Perfect' and row.Team2Kills == '0' and row.Team2Towers == '0' then
		return 1
	elseif PRELOAD.bias == 'Perfect' and row.Team1Kills == '0' and row.Team1Towers == '0' then
		return 2
	elseif PRELOAD.bias == 'AlmostPerfect' and row.Team2Kills <= args.maxkills and row.Team2Towers <= args.maxtowers then
		return 1
	elseif PRELOAD.bias == 'AlmostPerfect' and row.Team1Kills <= args.maxkills and row.Team1Towers <= args.maxtowers then
		return 2
	end
	error(i18n.print('invalidUsThem', row.GameId, row.ScoreboardPage, row.Team1, row.Team2))
end

function h.addUsThemFields(row, args)
	if not row.UsN then return end
	h.addSetOfUsThemFields(row, row.UsN, '')
	h.addSetOfUsThemFields(row, util_esports.otherTeamN(row.UsN), 'Vs')
	row.ResultBiased = m_team.teamlinkname(row.WinTeam) == row.Team and 'Win' or 'Loss'
	row.class = m_team.teamlinkname(row.WinTeam) == row.Team and 'winner' or 'loser'
end

function h.addSetOfUsThemFields(row, us, suffix)
	for _, v in ipairs({ 'BansDisplay', 'PicksDisplay', 'Roster', 'Gold', 'Kills', 'Towers', 'Dragons', 'Barons', 'Inhibitors', 'RiftHeralds', 'VoidGrubs', 'Bans', 'Picks', 'Display', }) do
		row[v .. suffix] = row['Team' .. us .. v]
	end
	row['Team' .. suffix] = row['Team' .. us]
end

function h.linkedRosters(row)
	row.Team1Roster = h.oneLinkedRoster(row, 1)
	row.Team2Roster = h.oneLinkedRoster(row, 2)
end

function h.oneLinkedRoster(row, n)
	local ret = {}
	local links = util_text.split(row['Team' .. n .. 'Links'])
	for i, v in ipairs(links) do
		ret[#ret+1] = util_esports.playerLinked(v)
	end
	return util_table.concat(ret, ', ')
end

function h.setClassTHTH(row, args)
	if not PRELOAD.thth then return end
	if row.WinTeam == m_team.teamlinkname(args.team1) then
		row.class = 'thth-team1'
	else
		row.class = 'thth-team2'
	end
end

function h.formatDataText(data, args)
	for n, row in ipairs(data) do
		h.formatRowText(row, args, n)
	end
end

function h.formatRowText(row, args, n)
	row.N = n
	row.TournamentDisplay = row.Region:name() .. ',' .. row.Tournament
	row.Team1Roster = row.Team1Links
	row.Team2Roster = row.Team2Links
	row.UsN = h.getUsN(row, args)
	row.Team1BansDisplay = row.Team1Bans:names()
	row.Team2BansDisplay = row.Team2Bans:names()
	row.Team1PicksDisplay = row.Team1Picks:names()
	row.Team2PicksDisplay = row.Team2Picks:names()
	h.addUsThemFields(row, args)
	row.Side = row.UsN and util_game.side_names[row.UsN]
	row.BannedBy = row.Side
	row.Scoreboard = util_text.intLink(row._pageName, 'SB')
end

function h.checkIfTruePerfect(row)
	if row.BaronsVs == '0' and row.DragonsVs == '0' then
		row.TruePerfect = tostring(mw.html.create('div'):addClass('greencheck'))
		-- Only if one of them is null we can still apply the criteria using 
		-- only the other one
		if (
			(row.RiftHeraldsVs == '0' and row.VoidGrubsVs == '0') or
			(row.RiftHeraldsVs == '0' and row.VoidGrubsVs == nil) or
			(row.RiftHeraldsVs == nil and row.VoidGrubsVs == '0')
		) then
			row.TruePerfect = row.TruePerfect .. tostring(mw.html.create('div'):addClass('greencheck'))
		end
	end
end

-- output
function h.makeOutput(data, args, args2)
	local output = mw.html.create()
	local headings = h.getHeadings()
	ColumnShowHide.printToggles(output, headings)
	local tbl = output:tag('div'):addClass('wide-content-scroll'):tag('table')
		:addClass('wikitable hoverable-multirows mhgame sortable plainlinks')
		:addClass(PRELOAD.class)
	ColumnShowHide.printTableClass(tbl)
	h.printColspanHeader(tbl, args, #headings)
	h.printHeaderTHTH(tbl, args, data.wins, #headings)
	h.printUpperHeadings(tbl)
	h.printLowerHeadings(tbl, headings.headerCells or headings)
	util_html.printEmptySortRow(tbl, #headings)
	h.printRows(tbl, data, headings)
	h.printPermalink(output, args, args2)
	return output
end

function h.printColspanHeader(tbl, args, colspan)
	if PRELOAD.noheading then return end
	local displayTbl = {
		util_stats.heading(args, 'MatchHistoryGame', h.getLimit(args)),
		util_stats.openAsQueryLink(SETTINGS.form_info, args)
	}
	util_html.printColspanHeader(tbl, util_table.concat(displayTbl, ' - '), colspan)
end

function h.printHeaderTHTH(tbl, args, winData, colspan)
	if not PRELOAD.thth then return end
	local div = tbl:tag('tr'):tag('th'):attr('colspan', colspan):tag('div'):addClass(h.getClassName('thth-outer'))
	for n = 1, 2 do
		h.printHeaderTHTHTeam(div, args, winData, n)
	end
end

function h.printHeaderTHTHTeam(div, args, winData, n)
	div:tag('div')
		:addClass(h.getClassName('thth-team' .. n))
		:wikitext(h.getHeaderTHTHTeamText(args, winData, n))
end

function h.getHeaderTHTHTeamText(args, winData, n)
	local team = m_team.teamlinkname(args['team' .. n])
	return ('%s: %s %s'):format(m_team.rightmedium(team), winData[team] or 0, i18n.print('ththWins'))
end

function h.getHeadings()
	if PRELOAD.upper then
		return h.getHeadingsWhenTwoRowsOfHeadings()
	elseif PRELOAD.multiline then
		return h.getHeadingsWhenTwoRowsPerDataLine()
	else
		return PRELOAD.headings
	end
end

function h.getHeadingsWhenTwoRowsOfHeadings()
	local ret = { headerCells = {} }
	for _, group in ipairs(PRELOAD.headings) do
		for _, col in ipairs(PRELOAD.headings[group]) do
			ret[#ret+1] = col
			if #PRELOAD.headings[group] > 1 then
				ret.headerCells[#ret.headerCells+1] = col
			end
		end
	end
	return ret
end

function h.getHeadingsWhenTwoRowsPerDataLine()
	local ret = { row2 = {} }
	for _, row in ipairs(PRELOAD.headings) do
		for _, col in ipairs(row) do
			ret[#ret+1] = col
			ret[col] = row.rowspan
			if row.rowspan == 1 then
				ret.row2[#ret.row2+1] = col
			end
		end
	end
	return ret
end

function h.printUpperHeadings(tbl)
	if not PRELOAD.upper then return end
	local tr = tbl:tag('tr')
	for _, col in ipairs(PRELOAD.headings) do
		local th = tr:tag('th')
			:wikitext(i18n.print(col))
			:attr('colspan', #PRELOAD.headings[col])
		if #PRELOAD.headings[col] == 1 then
			th:attr('rowspan', 2)
		end
	end
end

function h.printLowerHeadings(tbl, headings)
	local tr = tbl:tag('tr')
	for _, col in ipairs(headings) do
		tr:tag('th')
			:wikitext(i18n.print(col))
	end
end

function h.printRows(tbl, data, headings)
	for i, row in ipairs(data) do
		h.printOneRow(tbl, row, headings, i)
		h.printOneSecondRow(tbl, row, headings.row2, i)
	end
end

function h.printOneRow(tbl, row, headings, i)
	local tr = tbl:tag('tr')
	tr:addClass(h.getClassName(row.class))
	tr:attr('data-highlight-row', i)
	tr:addClass('multirow-highlighter')
	for _, col in ipairs(headings) do
		local td = tr:tag('td')
			:addClass(h.getClassFromCol(col))
			:wikitext(row[col:gsub('TeamN', 'Team' .. 1)])
		if headings[col] then
			td:attr('rowspan', headings[col])
		end
	end
end

function h.printOneSecondRow(tbl, row, headingsRow2, i)
	if not headingsRow2 then return end
	local tr = tbl:tag('tr')
	tr:addClass(h.getClassName(row.class))
	tr:attr('data-highlight-row', i)
	tr:addClass('multirow-highlighter')
	for _, col in ipairs(headingsRow2) do
		tr:tag('td')
			:addClass(h.getClassFromCol(col))
			:wikitext(row[col:gsub('TeamN', 'Team' .. 2)])
	end
end

function h.getClassFromCol(col)
	return h.getClassName(SETTINGS.classes[col])
end

function h.getClassName(str)
	if not str then return nil end
	return 'mhgame-' .. str
end

function h.printPermalink(output, args, args2)
	if not util_args.castAsBool(args.spl) then return end
	util_form.permalink(output, args, SETTINGS.form_info)
	output:tag('hr')
	output:wikitext(i18n.print('debugInfo'))
	output:wikitext(h.getWhere(args2))
	util_form.printLog(output)
end

return p
Advertisement