Call of Duty Esports Wiki
Register
Advertisement

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


local lang = mw.getLanguage('en')
local m_team = require('Module:Team')
local TeamHistory = require('Module:Infobox/TeamHist').teamHist
local util_args = require('Module:ArgsUtil')
local util_cargo = require('Module:CargoUtil')
local util_game = require('Module:GameUtil')
local util_html = require('Module:HtmlUtil')
local util_infobox = require('Module:InfoboxUtil')
local util_map = require('Module:MapUtil')
local util_sentence = require("Module:SentenceUtil")
local util_table = require('Module:TableUtil')
local util_text = require("Module:TextUtil")
local util_title = require("Module:TitleUtil")
local util_vars = require('Module:VarsUtil')
local i18n = require('Module:i18nUtil')
local RoleList = require('Module:RoleList')
local Country = require('Module:Country')
local CountryList = require('Module:CountryList')
local Region = require('Module:Region')
local RegionList = require('Module:RegionList')
local ChampionList = require('Module:ChampionList')
local PlayerCurrentTeam = require('Module:PlayerCurrentTeam').main
local IntroSentence = require('Module:IntroSentence/Player').main

local NOIMAGE = 'Unknown Infobox Image - Player.png'

local Infobox = require('Module:Infobox'):extends()

Infobox.type = 'Player'

Infobox.LAYOUT = {
	tabs = 'PlayerTabsHeader',
	sections = { 'Background Information', 'Competitive', 'Social Media & Links', 'Team History' },
	contents = {
		{ 'Name', 'Country', 'Nationality', 'Birthday', 'Died', 'Residency', 'ResidencyPrev' },
		{ 'Team', 'Role', 'PreviousRole', 'Input', 'Platform', 'PlatformPrev',  'CompIDs', 'PSNIDs','XBLIDs','BattleTags' },
		{ 'social', social = 'wide' },
		{ 'teamhist', teamhist = 'wide' },
	},
}

local h = {} -- helper functions
local p = {}
function p.main(frame)
	local args = util_args.merge()
	return Infobox(args):run()
end

function Infobox:getSettings(args, processed)
	local ret = self:super('getSettings', args, processed)
	ret.nocat = false
	return ret
end

function Infobox:castArgs(args)
	self:super('castArgs', args)
	args._display = args.id
	args.role = RoleList(args.role, { sub = util_args.castAsBool(args.checkboxIsSub) })
	args.role_prev = RoleList(util_args.numberedArgsToTable(args, 'prev'))
	args.favchamps = ChampionList(util_args.numberedArgsToTable(args, 'favchamp'))
	args.residency = Region(args.residency)
	args.res_prev1 = Region(args['residency-prev1'])
	args.res_prev2 = Region(args['residency-prev2'])
	args.res_prev = RegionList(util_args.numberedArgsToTable(args, 'residency-prev'))
	args.country = Country(args.country)
	args.nationality = CountryList(args.nationality)
	
	-- we only want to display a nationality if it's different from the country
	if args.country:name() == args.nationality:names() then
		args.nationality = CountryList()
	end
	
	args.isretiredplayer = util_args.castAsBool(args.isretiredplayer)
	args.isretired = util_args.castAsBool(args.isretired)
	args.towildrift = util_args.castAsBool(args.towildrift)
	
	args.isLowContentHasBio = util_args.castAsBool(args.has_bio)
end

function Infobox:getProcessed(args)
	if util_args.castAsBool(args.checkboxAutoTeams) then
		args.team = nil
		args.team2 = nil
	end
	local processed = {
		pagename = mw.title.getCurrentTitle().text,
		bday = h.getBirthdayAndAgeIfAppropriate(args),
		died = h.getDeathDateIfNeeded(args),
		lc = args.id and lang:lcfirst(args.id) == args.id,
		hasAutoTeams = util_args.castAsBool(args.checkboxAutoTeams),
		image = h.getImage(args),
	}
	processed.entity = processed.lc and util_text.lcfirst(processed.pagename) or processed.pagename
	local teamhist, last = TeamHistory(args)
	processed.teams = h.getTeamsTable(args, processed, last)
	processed.teamhist = not processed.hasAutoTeams and teamhist
	processed.roleLast = h.getCargoLastRole(args, processed)
	processed.resPrevList = h.getResPrevList(args, processed.teams, processed.hasAutoTeams)
	return processed
end

function h.getImage(args)
	if not util_args.castAsBool(args.checkboxAutoImage) then
		return util_infobox.getFile(args.image, NOIMAGE)
	end
	return util_infobox.getFileNoExistenceCheck(h.queryForImage(args), NOIMAGE)
end

function h.getBirthdayAndAgeIfAppropriate(args)
	local bday = util_infobox.makeBday(args.birth_date_year, args.birth_date_month, args.birth_date_day)
	if args.died then
		bday.age = nil
		bday.displayandage = bday.display
	end
	return bday
end

function h.getDeathDateIfNeeded(args)
	if not args.died then return {} end
	return util_infobox.makeBday(args.birth_date_year, args.birth_date_month, args.birth_date_day, args.died)
end

function h.getTeamsTable(args, processed, last)
	if processed.hasAutoTeams then
		return PlayerCurrentTeam(mw.title.getCurrentTitle().text)
	end
	local teams = h.getLegacyTeams(args, processed)
	teams.last = last or {}
	return teams
end

function h.getLegacyTeams(args, processed)
	local ret = util_map.inPlace(
		util_args.numberedArgsToTable(args, 'team') or {},
		h.getOneLegacyTeam, args, processed
	)
	return ret
end

function h.getOneLegacyTeam(team, args, processed)
	local ret = {
		team = m_team.teamlinkname(team),
		role = args.role,
		sub = util_args.castAsBool(args.checkboxIsSub),
	}
	return ret
end

function h.getCargoLastRole(args, processed)
	if not processed.hasAutoTeams then return args.role end
	
	-- role could be nil if player has 0 team entries
	if not processed.teams.last.RoleList then return args.role end
	return processed.teams.last.RoleList:_or(args.role)
end

function h.getResPrevList(args, teams, hasAutoTeams)
	if not hasAutoTeams then
		return args.res_prev
	end
	if not teams.resPrevList then return RegionList() end
	if teams.resPrevList and #teams.resPrevList == 0 then return RegionList() end
	local resPrevList = teams.resPrevList
	return RegionList(util_table.concat(util_table.reverse(util_table.uniqueArray(resPrevList))))
end

function Infobox:getDisplay(args, processed)
	local display = self:super('getDisplay', args, processed)
	local tbl = {
		title = args.id or processed.pagename,
		image = not args.isLowContent and processed.image,
		notice = h.getNotice(args),
		
		-- background info
		Name = args.name and (args.name .. (args.nativename and (' (%s)'):format(args.nativename) or '')),
		Country = args.country:flair(),
		Nationality = args.nationality:flairs{sep='<br>'},
		Birthday = processed.bday.displayandage,
		Died = processed.died.displayandage,
		Residency = args.residency:flair(),
		ResidencyPrev = processed.resPrevList:flairs{sep='<br>'},
		
		-- competitive
		Team = h.getCurrentTeam(processed.teams),
		Contract = h.getContract(processed.teams),
		Role = args.role:flairs{len='role'},
		PreviousRole = args.role_prev:flairs{sep='<br>'},
		Input = args.input,
		Platform = args.platform,
		PlatformPrev = util_table.concatFromArgs(args, 'platform-prev', '<br>'),
		
		Champions = args.favchamps:images(),
		CompIDs = util_table.concatFromArgs(args, 'compID',', '),
		PSNIDs = args.psn,
		XBLIDs = args.xbl,
		BattleTags = args.battletag,
		
		-- social
		teamhist = processed.teamhist,
		
		class = h.getClass(args, processed)
	}
	return Infobox.mergeDisplay(display, tbl)
end

function h.queryForImage(args)
	local query = {
		tables = {
			'PlayerRedirects=PR',
			'PlayerImages=PI',
			'Tournaments=T',
		},
		join = {
			'PR.AllName=PI.Link',
			'PI.Tournament=T.OverviewPage',
		},
		where = h.getImageWhere(args),
		fields = { 'PI.FileName' },
		orderBy = 'COALESCE(PI.SortDate, T.DateStartFuzzy, T.Date) DESC',
	}
	return util_cargo.getOneResult(query)
end

function h.getImageWhere(args)
	local where = {
		('PR._pageName="%s"'):format(mw.title.getCurrentTitle().text),
		('PI._pageName IS NOT NULL'),
		('PI.IsProfileImage="1"'),
	}
	return where
end

function h.getNotice(args)
	-- args.died is not a boolean
	if args.died then
		return i18n.print('notice_deceased')
	end
	if args.isretiredplayer then
		return i18n.print('notice_retiredPlayer')
	end
	if args.isretired then
		return i18n.print('notice_retiredCompetition')
	end
	if args.towildrift then
		return util_text.intLink(
			('wildrift:%s'):format(args.id or processed.pagename),
			i18n.print('notice_towildrift')
		)
	end
	return nil
end

function h.getCurrentTeam(teams)
	if #teams == 0 then return nil end
	return util_table.concat(
		util_map.extractField(teams, 'team', m_team.rightmediumlinked),
		'<br>'
	)
end

function h.getContract(teams)
	if #teams == 0 then return nil end
	if not teams.contractDates then return nil end
	if #teams == 1 then
		return h.getContractDateFromFirstTeam(teams)
	end
	
	-- if they are on two teams but it's one org, we just show the date, nothing else
	-- but if they're on more than one org then we need to show a team icon next to the contract date
	local allSisterTeams = h.getListOfSisterTeamPages(teams)
	if #allSisterTeams == 1 then
		return h.getContractDateFromFirstTeam(teams)
	end
	return h.getAllContracts(teams)
end

function h.getContractDateFromFirstTeam(teams)
	util_vars.log(teams.contractDates)
	return teams.contractDates[teams[1].SisterTeamPage]
end

function h.getAllContracts(teams)
	local contracts = {}
	for _, team in ipairs(teams) do
		local contract = teams.contractDates[team.SisterTeamPage]
		if contract then
			contracts[#contracts+1] = ('%s%s'):format(
				m_team.onlyimagelinked(team.team),
				contract
			)
		end
	end
	if #contracts == 0 then return nil end
	return util_table.concat(contracts, '<br>')
end

function h.getListOfSisterTeamPages(teams)
	local sisterTeamsUsed = {}
	local allSisterTeams = {}
	for _, team in ipairs(teams) do
		if not sisterTeamsUsed[team.SisterTeamPage] then
			allSisterTeams[#allSisterTeams+1] = team.SisterTeamPage
			sisterTeamsUsed[team.SisterTeamPage] = true
		end
	end
	return allSisterTeams
end

function h.getClass(args, processed)
	local listOfClasses = {
		processed.hasAutoTeams and 'infobox-player-narrow',
		args.isLowContent and 'infobox-low-content',
		args.isLowContentHasBio and 'infobox-has-bio',
	}
	return util_table.concat(listOfClasses, ' ')
end

function Infobox:getCargo(args, processed)
	local cargo = self:super('getCargo', args, processed)
	cargo[#cargo+1] = h.getPlayersCargo(args, processed)
	util_table.mergeArrays(
		cargo,
		h.getPlayerLeagueHistory(args)
	)
	return cargo
end

function h.getPlayersCargo(args, processed)
	local ret = {
		_table = 'Players',
		OverviewPage = mw.title.getCurrentTitle().text,
		Image = h.getImageCargo(args, processed),
		Name = args.name,
		Player = processed.entity,
		NativeName = args.nativename,
		NameAlphabet = args.namealphabet,
		NameFull = args.name and (args.name .. (args.nativename and (' (%s)'):format(args.nativename) or '')),
		Country = args.country,
		Nationality = args.nationality,
		NationalityPrimary = args.nationality:first(),
		Age = processed.bday.age or '',
		Birthdate = processed.bday.store or '',
		ResidencyFormer = args['residency-prev1'],
		Team = processed.teams[1] and processed.teams[1].team,
		Team2 = processed.teams[2] and processed.teams[2].team,
		TeamSystem = 'PC',
		Team2System = 'PC',
		Residency = args.residency,
		Role = args.role,
		Input = args.input,
		Platform = args.platform,
		PlatformPrev = util_table.concatFromArgs(args, 'platform-prev', ', '),
		FavChamps = util_table.concatFromArgs(args, 'favchamp', ','),
		TeamLast = processed.teams.last and processed.teams.last.team,
		RoleLast = processed.roleLast,
		IsSubstitute = args.checkboxIsSub,
		IsLowercase = processed.lc,
		IsAutoTeam = args.checkboxAutoTeams,
		SoloqueueIds = args.ids,
		IsPersonality = args.page_type == 'Personality',
		IsLowContent = args.isLowContent,
		ID = args.id,
		IsRetired = args.isretired or args.towildrift,

		-- social fields
		Askfm = args.askfm,
		Discord = args.discord,
		Facebook = args.facebook,
		Instagram = args.instagram,
		Lolpros = args.lolpros,
		Reddit = args.reddit,
		Stream = args.stream,
		Twitter = args.twitter,
		Vk = args.vk,
		Website = args.website,
		Weibo = args.weibo,
		Youtube = args.youtube,
		GameBattles = args.gamebattles,
		UMG = args.umg
	}
	return ret
end

function h.getImageCargo(args, processed)
	if util_args.castAsBool(args.checkboxAutoImage) then
		return nil
	end
	if processed.image == NOIMAGE then return nil end
	if not processed.image then return nil end
	return processed.image:gsub('_', ' ')
end

function h.getPlayerLeagueHistory(args)
	if util_args.castAsBool(args.noplh) then return {} end
	if not util_game.store_player_league_history then return {} end
	local plhTable = require('Module:PlayerLeagueHistory')._main(mw.title.getCurrentTitle().text)
	return plhTable
end

function Infobox:getDisambigSentence(args, processed)
	-- we can't store "now known as" here but we can store everything else
	-- the "now known as" text is going to have to change, but that's ok maybe
	local replacements = {
		RESIDENCY = args.residency:image(),
		LINK = util_text.intLinkOrText(mw.title.getCurrentTitle().text),
		
		-- TODO: should this, actually be country...?
		NATIONALITY = args.country:exists() and args.country:get('adjective'),
		FORMER = not processed.teams[1] and i18n.default('former') or '',
		ROLE = processed.roleLast:sentence(),
		TEAM = processed.teams[1] and m_team.rightmediumlinked(processed.teams[1].team),
		-- NOW_KNOWN_AS = row.CurrentName and i18n.default('nowKnownAs', row.CurrentName) or '',
	}
	return util_sentence.makeReplacements(i18n.default('disambigSentence'), replacements)
end

function Infobox:getVariables(args, processed)
	local variables = self:super('getVariables', args, processed)
	local tbl = {
		suppressorgnavbox = args.checkboxSuppressOrgNavbox,
		introSentence = h.getIntroSentence(args, processed, 'Display'),
		description = h.getIntroSentence(args, processed, 'Description'),
		checkboxAutoTeams = args.checkboxAutoTeams,
		residency = args.residency:get(),
		isretired = args.isretired or args.isretiredplayer or args.towildrift,
		towildrift = args.towildrift,
		current_id = processed.entity,
	}
	local i = 2
	repeat
		thisteam = 'team' .. i
		tbl[thisteam] = args[thisteam] and m_team.teamlinkname(args[thisteam])
		i = i + 1
	until(not args[thisteam])
	return util_table.merge(variables, tbl)
end

function h.getIntroSentence(args, processed, sentenceType)
	local data = mw.clone(args)
	local name = mw.text.split(args.name or '', ' ')
	data.firstname = table.remove(name, 1)
	data.lastname = table.concat(name, ' ')
	data.lastteam = processed.teams.last.team
	data.role = args.role:_or(processed.roleLast)
	data.teamStr = args.team and m_team.teamlinkname(args.team)
	data.isasub = util_args.castAsBool(args.checkboxIsSub)
	data.ispersonality = args.page_type == 'Personality'
	data.page_type = args.page_type
	data.isretired = args.isretired
	data.lastteampresent = h.getLastTeamPresent(args, processed)
	data.currentTeamList = processed.teams
	data.hasAutoTeams = processed.hasAutoTeams
	return IntroSentence(data, sentenceType)
end

function h.getLastTeamPresent(args, processed)
	if processed.teams and #processed.teams > 0 then return true end
	return processed.teams.last.date and processed.teams.last.date:find('Present')
end

function Infobox:getCategories(args, processed)
	local inheritedCategories = self:super('getCategories', args)
	local ns = mw.title.getCurrentTitle().nsText
	if ns == 'Self' then
		return { 'SelfPlayers', }
	end
	if ns ~= '' then return {} end
	-- now assume ns is main
	local tbl = {
		'Players',
		args.residency:exists() and args.residency:get('adjective') .. ' Residents',
		args.res_prev1:exists() and ('Former %s Residents'):format(args.res_prev1:get('adjective')),
		args.res_prev2:exists() and ('Former %s Residents'):format(args.res_prev2:get('adjective')),
		not args.role:exists() and 'Players Without Role',
		h.getSuspendedCategory(args, processed),
		h.isAFreeAgent(args, processed) and 'Free Agents',
		args.isretired and 'Retired Players',
		args.birth_date_year and 'Players Born In ' .. args.birth_date_year,
		args.role:has(nil, 'Coach') and 'Coaches',
	}
	
	if args.country:exists() then
		if args.page_type == 'Personality' then
			tbl[#tbl+1] = ('%s Personalities'):format(args.country:get('adjective'))
		else
			tbl[#tbl+1] = 'Players Born in ' .. args.country:name{the=true}
		end
	end
	
	for _, region in ipairs(processed.resPrevList) do
		tbl[#tbl+1] = ('Former %s Residents'):format(region:get('adjective'))
	end
	
	if not util_args.castAsBool(args.checkboxAutoImage) then
		tbl[#tbl+1] = 'Manual Image'
	end
	return util_table.mergeArrays(tbl, inheritedCategories)
end

function h.isAFreeAgent(args, processed)
	if not util_args.castAsBool(args.checkboxAutoTeams) then
		if args.team then return false end
		if args.isretired then return false end
		return true
	end
	return not h.getCurrentTeam(processed.teams)
end

function h.getSuspendedCategory(args, processed)
	if processed.teams.last.team ~= 'Suspended' then return false end
	if not processed.teams.last.date then return false end
	if not processed.teams.last.date:find('Present') then return false end
	return 'Suspended Players'
end

return p
Advertisement