Leaguepedia | League of Legends Esports Wiki

Edit the documentation or categories for this module. This module has an i18n file.

This module runs and makes the following hooks available:

  • onMatchHistoryPlayerGetWhere - added by:{{MVPHistory}}m
  • onMatchHistoryPlayerGetJoin - added by:{{MVPHistory}}m
  • onMatchHistoryPlayerPrintColspanHeader - added by:{{MVPHistory}}m
  • onMatchHistoryPlayerGetTables - added by:{{MVPHistory}}m

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 Sprite = require('Module:Sprite').sprite
local ChampionList = require('Module:ChampionList')
local RoleList = require('Module:RoleList')
local RegionList = require('Module:RegionList')
local Item = require('Module:Item')
local m_team = require('Module:Team')
local Stats = require('Module:ScoreboardPlayerStats')
local ColumnShowHide = require('Module:ColumnShowHide')
local ReplaceRedirects = require('Module:ReplaceRedirects')
local Hook = require('Module:Hook')
local SETTINGS = require('Module:MatchHistoryPlayer/Settings')
local PRELOAD
local DEFAULT_LIMIT = 50

local s = {}
function s.ItemSprite(id)
	return Sprite{
		id,
		size = 25,
		type = 'Item',
		--nosize = true,
		notext = true,
		nolink = true
	}
end
function s.SummonerSprite(id)
	return Sprite{
		id,
		size = 25,
		type = 'Summoner',
		notext = true,
		nolink = true
	}
end
function s.KeystoneSprite(id)
	return Sprite{
	id,
	size = 25,
	type = 'Keystone',
	notext = true,
	nolink = true,
	}
end
local h = {}
local p = {}
function p.main(frame)
	local args = util_args.merge()
	return p._main(args)
end

function p._main(args)
	h.setPreloadAndValidate(args)
	i18n.init('MatchHistoryPlayer')
	local args2 = h.castArgs(args)
	local data = h.getData(args2)
	if util_args.castAsBool(args.textonly) then
		h.formatDataText(data)
	else
		h.formatDataPretty(data)
	end
	return ReplaceRedirects.main(h.makeOutput(data, args, args2))
end

function h.setPreloadAndValidate(args)
	local preload = h.getPreload(args.preload)
	if args.preload == 'ChampionPlayerTournament' and not args.tournament then
		args.preload = 'General'
		PRELOAD = h.getPreload('General')
	else
		PRELOAD = preload
	end
	util_stats.validatePreload(args, PRELOAD)
end

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

function h.castArgs(args)
	local args2 = mw.clone(args)
	args2.role = RoleList(args2.role, {sep=','})
	args2.champion = ChampionList(args2.champion)
	args2.championvs = ChampionList(args2.championvs)
	args2.region = RegionList(args2.region)
	args2.item = Item(args2.item):get()
	return args2
end

-- cargo
function h.getData(args)
	local data = util_cargo.queryAndCast(h.getQuery(args))
	return data
end

function h.getQuery(args)
	return {
		tables = h.getTables(args),
		join = h.getJoin(args),
		fields = h.getFields(args),
		where = h.getWhere(args),
		limit = h.getLimit(args),
		orderBy = h.getOrderBy(args),
	}
end

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

function h.getTables(args)
	local ret = {
		'ScoreboardGames=SG',
		'Tournaments=IT',
		'ScoreboardPlayers=SP',
		'ScoreboardPlayers=SPVs',
		'PlayerRedirects=PR',
	}
	Hook.run('onMatchHistoryPlayerGetTables', ret)
	return ret
end

function h.getJoin(args)
	local ret = {
		'SG.GameId=SP.GameId',
		'IT.OverviewPage=SG.OverviewPage',
		'SP.UniqueRoleVs=SPVs.UniqueRole',
		'SP.Link=PR.AllName',
	}
	Hook.run('onMatchHistoryPlayerGetJoin', ret)
	return ret
end

function h.getFields(args)
	local ret = {
		'COALESCE(PR._pageName,SP.Link)=Link',
		'SP.Name',
		'SP.Team',
		'SP.Champion',
		'SP.Champion=TypedChampion [champion]',
		'SP.Kills=K [number]',
		'SP.Deaths=D [number]',
		'SP.Assists=A [number]',
		'SP.Gold=G [number]',
		'SP.CS [number]',
		'SP.IngameRole=Role',
		'SP.IngameRole=TypedRole [role]',
		'SP.Items__full=Items [list]',
		'SP.Trinket',
		'SP.TeamKills [number]',
		'SP.TeamGold [number]',
		'SP.DamageToChampions=DMG [number]',
		'IT.StandardName=Tournament',
		'SP.PlayerWin [boolean]',
		'SP.GameId',
		'SP._pageName',
		'SG._pageName=_pageName2',
		'SP.SummonerSpells__full=SummonerSpells',
		'SP.KeystoneMastery',
		'SP.KeystoneRune',
		'SP.Side',
		'SPVs.Champion=ChampionVs [champion]',
		'SPVs.Link=LinkVs',
		'SPVs.Name=NameVs',
		'SPVs.CS=CSVs [number]',
		'SPVs.Team=TeamVs',
		'SG.Gamelength_Number=Len [number]',
		'SG.Gamelength=LenDisplay',
		'SG.DateTime_UTC=Date',
		'SG.MatchHistory',
		'SG.Patch',
		'SG.VOD',
		'SG.Team1Picks [championList]',
		'SG.Team2Picks [championList]',
		'IT.Region [region]',
		'IT.Region=RegionPlaintext',
	}
	return ret
end

function h.getWhere(args)
	local tbl = {
		util_cargo.whereFromArg('(%s)', args.where),
		util_cargo.whereFromArgList('SP.OverviewPage="%s"', args.tournament, nil, util_title.target),
		h.getLinkWhereCondition(args.link),
		util_cargo.whereFromArgList('SP.Team="%s"', args.team, nil, m_team.teamlinkname),
		util_cargo.whereFromCompoundEntity('SP.Champion="%s"', args.champion),
		util_cargo.whereFromCompoundEntity('SPVs.Champion="%s"', args.championvs),
		util_cargo.whereFromCompoundEntity('SP.IngameRole="%s"', args.role),
		util_cargo.whereFromCompoundEntity('IT.Region="%s"', args.region),
		util_cargo.whereFromArgList('IT.Year="%s"', args.year),
		util_cargo.whereFromArgList('IT.TournamentLevel="%s"', args.tournamentlevel),
		args.jungleitem and util_cargo.fakeHolds('SP.Items', args.jungleitem .. ' - .*', ";"),
		args.jungleenchant and util_cargo.fakeHolds('SP.Items', '.* - ' .. args.jungleenchant, ";"),
		util_cargo.whereFromArgList('SP.KeystoneRune="%s"', args.rune),
		util_cargo.whereFromArgList('SP.Trinket="%s"', args.trinket),
		util_cargo.whereFromArgList('SG.Patch="%s"', args.patch),
	}
	if args.item and not util_table.nextNonFalse(tbl) then
		tbl[#tbl+1] = ('SP.Items HOLDS "%s"'):format(args.item)
	elseif args.item then
		tbl[#tbl+1] = util_cargo.fakeHolds('SP.Items', args.item, ";")
	end
	Hook.run('onMatchHistoryPlayerGetWhere', tbl)
	return util_cargo.concatWhere(tbl)
end

function h.getLinkWhereCondition(link)
	if not link then return nil end
	if mw.title.new(link, '').exists then
		return util_cargo.whereFromArgList('PR._pageName="%s"', link, nil, util_title.target)
	else
		return util_cargo.whereFromArgList('SP.Link="%s"', link, nil, util_title.target)
	end
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
	if args.record:lower() == "kda" then
  		return ("(SP.Kills + SP.Assists) / (CASE WHEN SP.Deaths = 0 THEN 1 ELSE SP.Deaths END) DESC") 
  	end
	local order = util_args.castAsBool(args.recordorder) and 'ASC' or 'DESC'
	return ('SP.%s %s'):format(args.record, order)
end

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

function h.formatRowPretty(row, n)
	util_stats.infoLinks(row)
	row.N = n
	row.TournamentDisplay = util_stats.tournamentAndRegion(row)
	row.ChampionDisplay = row.TypedChampion:image()
	row.ChampionLong = row.TypedChampion:flair()
	row.ChampionVsDisplay = row.ChampionVs:image()
	row.attrs = {
		ChampionVsDisplay = {
			['data-sort-value'] = row.ChampionVs:get(),
		},
		ChampionDisplay = {
			['data-sort-value'] = row.Champion,
		},
		CSDiff = {
			['data-sort-value'] = row.CSVs and row.CS and row.CS - row.CSVs,
		},
	}
	row.Items = h.concatItemsPretty(row)
	row.CSDiff = row.CSVs and row.CS and util_esports.diff(row.CS - row.CSVs)
	row.Result = row.PlayerWin and 'Win' or 'Loss'
	row.class = row.PlayerWin and 'winner' or 'loser'
	row.TeamDisplay = m_team.onlyimagelinked(row.Team)
	row.TeamVs = m_team.onlyimagelinked(row.TeamVs)
	row.Patch = row.Patch and util_text.intLink('Patch ' .. row.Patch, row.Patch)
	h.getKDA(row)
	row.Date = util_time.strToDateStr(row.Date)
	row.Spells = h.getSpellsPretty(row)
	row.Player = util_text.intLink(row.Link, row.Name)
	row.ChampionList = h.getChampionsPretty(row, row.Side)
	row.ChampionListVs = h.getChampionsPretty(row, util_esports.otherTeamN(row.Side))
	row.RoleDisplay = row.TypedRole:get('short')
	row.Side = util_game.side_names[row.Side]
	row.GoldDisplay = util_math.roundedThousands(row.G)
	row.DmgDisplay = util_math.roundedThousands(row.DMG)
end

function h.concatItemsPretty(row)
	local tbl = {
		util_table.concat(util_map.arrayInPlace(row.Items, s.ItemSprite), ""),
		row.Trinket and s.ItemSprite(row.Trinket)
	}
	return util_table.concat(tbl, ' ')
end

function h.getKDA(row)
	local function tryKDA()
		row.KDA = util_esports.calculateKDA(row.K, row.D, row.A)
	end
	if pcall(tryKDA) then
		return
	else
		error(i18n.print('error_kda', row._pageName or row._pageName2 or '???'))
	end
end

function h.getSpellsPretty(row)
	local tbl = {
		util_map.splitAndConcat(row.SummonerSpells, nil, s.SummonerSprite),
		row.KeystoneRune and s.KeystoneSprite('Rune ' .. row.KeystoneRune),
		row.KeystoneMastery and s.KeystoneSprite('Mastery ' .. row.KeystoneMastery),
	}
	util_table.removeFalseEntries(tbl, 3)
	return util_table.concat(tbl, '', nil)
end

function h.getChampionsPretty(row, N)
	return row['Team' .. N .. 'Picks']:images()
end

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

function h.formatRowText(row, n)
	row.N = n
	row.TournamentDisplay = row.Region:name() .. ',' .. row.Tournament
	row.ChampionDisplay = row.TypedChampion:name()
	row.ChampionLong = row.TypedChampion:name()
	row.ChampionVsDisplay = row.ChampionVs:name()
	row.CSDiff = row.CSVs and row.CS and util_esports.diff(row.CS - row.CSVs)
	row.Result = row.PlayerWin and 'Win' or 'Loss'
	row.KDA = util_esports.calculateKDA(row.K, row.D, row.A)
	row.Spells = h.getSpellsText(row)
	row.Items = h.concatItemsText(row)
	row.Player = row.Link
	row.ChampionList = row['Team' .. row.Side .. 'Picks']:names()
	row.ChampionListVs = row['Team' .. util_esports.otherTeamN(row.Side) .. 'Picks']:names()
	row.Scoreboard = util_text.intLink(row._pageName, 'SB')
	row.Side = util_game.side_names[row.Side]
	row.TeamDisplay = row.Team
end

function h.concatItemsText(row)
	local tbl = {
		util_table.concat(row.Items),
		row.Trinket
	}
	return util_table.concat(tbl, ' ')
end

function h.getSpellsText(row)
	local tbl = {
		row.SummonerSpells,
		row.KeystoneRune,
		row.KeystoneMastery,
	}
	return util_table.concat(tbl, '', nil, 3)
end

-- print
function h.makeOutput(data, args, args2)
	local output = h.initializeOutput()
	ColumnShowHide.printToggles(output, PRELOAD.headings)
	local tbl = h.initializeTable(output, args)
	ColumnShowHide.printTableClass(tbl)
	h.printColspanHeader(tbl, args)
	h.printHeadings(tbl)
	util_html.printEmptySortRow(tbl, #PRELOAD.headings)
	h.printRows(tbl, data)
	h.printStats(tbl, data, args, #PRELOAD.headings)
	h.printPermalink(output, args, args2)
	return output
end

function h.initializeOutput()
	local output = mw.html.create('div')
		:addClass('wide-content-scroll')
	return output
end

function h.initializeTable(output, args)
	local tbl = output:tag('div'):addClass('wide-content-scroll'):tag('table')
		:addClass('wikitable mhplayer sortable plainlinks hoverable-rows')
	if args.record then
		tbl:addClass(h.getClassName('record-' .. args.record:lower()))
	end
	return tbl
end

function h.printColspanHeader(tbl, args)
	if PRELOAD.noheading then return end
	if not Hook.run('onMatchHistoryPlayerPrintColspanHeader', tbl, #PRELOAD.headings) then return end
	local displayTbl = {
		util_stats.heading(args, 'MatchHistoryPlayer', h.getLimit(args)),
		util_stats.openAsQueryLink(SETTINGS.form_info, args)
	}
	util_html.printColspanHeader(tbl, util_table.concat(displayTbl, ' - '), #PRELOAD.headings)
end

function h.printHeadings(tbl)
	local tr = tbl:tag('tr')
		:addClass(h.getClassName('headings'))
	for _, col in ipairs(PRELOAD.headings) do
		local th = tbl:tag('th')
			:wikitext(i18n.print(col))
		util_html.printCellAttrs(th, SETTINGS, col)
	end
end

function h.printRows(tbl, data)
	for _, row in ipairs(data) do
		local tr = tbl:tag('tr')
		tr:addClass(h.getClassName(row.class))
		h.printOneRow(tr, row)
	end
end

function h.printOneRow(tr, row)
	for _, col in ipairs(PRELOAD.headings) do
		local td = tr:tag('td')
			:addClass(h.getClassFromCol(col))
			:wikitext(row[col])
		util_html.printCellAttrs(td, row, col)
	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 'mhplayer-' .. str
end

function h.printStats(tbl, data, args, colspan)
	if PRELOAD.nostats or util_args.castAsBool(args.nostats) then return end
	local statsArgs = h.getArgsForStats(args)
	if statsArgs.preload == 'CPTMH' then
		local StatsTable = util_html.innerColspanTable(tbl, colspan)
		Stats:CPTMH(StatsTable, data, statsArgs)
	else
		local statsCell = util_html.innerColspanCellOnly(tbl, colspan)
		Stats:printOutputFromData(statsCell, data, statsArgs)
	end
end

function h.getArgsForStats(args)
	local statsArgs = mw.clone(args)
	statsArgs.hidetournamentlist = util_args.boolToStringYN(true)
	statsArgs.preload = h.guessStatsPreload(statsArgs)
	statsArgs.class = 'nested-table'
	statsArgs.spl = false
	return statsArgs
end

function h.guessStatsPreload(statsArgs)
	if not statsArgs.tournament then
		return 'ByTournament'
	elseif statsArgs.link and statsArgs.champion then
		return 'CPTMH'
	elseif statsArgs.link then
		return 'PlayerByChampion'
	elseif statsArgs.champion then
		return 'ChampionByPlayer'
	else
		return 'ByTournament'
	end
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