Module:Game

From Liquipedia Commons Wiki
Module documentation[view] [edit] [history] [purge]

Used to retrieve Game data.

API[edit]

Programmatic name: Game

toIdentifier(args: table) → string

Returns the standardized identifier of a game. If no entry is made and it is not disabled it uses the defaultGame value from Module:Info.


raw(args: table) → table

Retrieves the game data of a given game from Module:Info.


abbreviation(args: table) → string

Returns the abbreviation of a given game.


name(args: table) → string

Returns the name of a given game.


link(args: table) → string

Returns the link of a given game.


icon(args: table) → string

Builds the (lightmode + darkmode) icon of a given game.


defaultTeamLogoData(args: table) → string

Retrieves the default team logo (lightmode + darkmode) of a given game.


isDefaultTeamLogo(args: table) → boolean

Checks if a given logo is among the default team logos set in Module:Info for any game (or if specified for a given game).


See all our documentation here.

Parameters[edit]

isDefaultTeamLogo function[edit]

|logo=
The logo for which to check if it is among the default team logos
If no logo is specified the function will return false
|game=
If specified the function will only check the given logo against the default team logos of the given game
If not specified the function will check all default team logos of all the games set in Module:Info

All other functions[edit]

|game=
The game for which to retireve data.
|useDefault=true
Set this to false to not use the default game when no game is entered

icon function (additionally)[edit]

|size=
The size in which the icon is to be displayed (default: 25x25px)
|noLink=false
Set this to true for the icon not to link
|link=
Set manual link to which the icon shall link
Does not work if |noLink=true is set
Defaults to the link retrieved for the specified game from Module:Info

---
-- @Liquipedia
-- wiki=commons
-- page=Module:Game
--
-- Please see https://github.com/Liquipedia/Lua-Modules to contribute
--

local Abbreviation = require('Module:Abbreviation')
local Array = require('Module:Array')
local Class = require('Module:Class')
local FnUtil = require('Module:FnUtil')
local Logic = require('Module:Logic')
local Lua = require('Module:Lua')
local Page = require('Module:Page')
local String = require('Module:StringUtils')
local Table = require('Module:Table')

local Info = Lua.import('Module:Info')

---@class GameData
---@field abbreviation string
---@field name string
---@field link string
---@field logo {darkMode: string, lightMode: string}
---@field defaultTeamLogo {darkMode: string, lightMode: string}
---@field order number?
---@field unlisted boolean?

local GamesData = Info.games --[[@as table<string, GameData>]]

local ICON_STRING = '[[File:${icon}|${alt}|link=${link}|class=${class}|${size}]]'
local DEFAULT_SIZE = '32x32px'
local DEFAULT_SPAN_CLASS = 'icon-16px'
local ICON_PLACEHOLDER = 'LeaguesPlaceholder.png'

local Game = {}

Game.getIdentifierByAbbreviation = FnUtil.memoize(function()
	return Table.map(GamesData, function(gameIdentifier, gameData)
		return gameData.abbreviation:lower(), gameIdentifier end)
end)

Game.getIdentifierByName = FnUtil.memoize(function()
	return Table.map(GamesData, function(gameIdentifier, gameData) return gameData.name:lower(), gameIdentifier end)
end)

---Get the identifier of a entered game. Checks against identifiers, full names and abbreviations.
---@param options? {game: string?, useDefault: boolean?}
---@return string?
function Game.toIdentifier(options)
	options = options or {}
	local gameInput = options.game

	if String.isEmpty(gameInput) and Logic.nilOr(Logic.readBoolOrNil(options.useDefault), true) then
		return Info.defaultGame
	elseif String.isEmpty(gameInput) then
		return
	end
	---@cast gameInput -nil

	gameInput = gameInput:lower()

	return Game.getIdentifierByAbbreviation()[gameInput]
		or Game.getIdentifierByName()[gameInput]
		or GamesData[gameInput] and gameInput
		or nil
end

---Check if a given game is a valid game.
---@param game string?
---@return boolean
function Game.isValid(game)
	return Table.isNotEmpty(Game.raw{game = game})
end

---Fetches the raw data for a given game
---@param options? {game: string?, useDefault: boolean?}
---@return table
function Game.raw(options)
	local identifier = Game.toIdentifier(options)
	if not identifier then
		return {}
	end

	return GamesData[identifier] or {}
end

---Fetches all valid game identifiers, potentially ordered
---@param options? {ordered: boolean?}
---@return string[]
function Game.listGames(options)
	options = options or {}

	local function getGameOrder(gameIdentifier)
		return tonumber(GamesData[gameIdentifier].order)
	end

	local gamesList = Array.extractKeys(GamesData)

	gamesList = Array.filter(gamesList, function(gameIdentifier)
		return not GamesData[gameIdentifier].unlisted
	end)

	if Logic.readBool(options.ordered) and Array.all(gamesList, getGameOrder) then
		return Array.sortBy(gamesList, getGameOrder)
	end

	return gamesList
end

---Fetches the abbreviation for a given game
---@param options? {game: string?, useDefault: boolean?}
---@return string?
function Game.abbreviation(options)
	return Game.raw(options).abbreviation
end

---Fetches the name for a given game
---@param options? {game: string?, useDefault: boolean?}
---@return string?
function Game.name(options)
	return Game.raw(options).name
end

---Fetches the link for a given game
---@param options? {game: string?, useDefault: boolean?}
---@return string?
function Game.link(options)
	return Game.raw(options).link
end

---Fetches the defaultTeamLogos (light & dark) for a given game
---@param options? {game: string?, useDefault: boolean?}
---@return table?
function Game.defaultTeamLogoData(options)
	return Game.raw(options).defaultTeamLogo
end

---@class gameIconOptions
---@field game string?
---@field size string?
---@field noLink boolean?
---@field link string?
---@field noSpan boolean?
---@field spanClass string?

---Builds the icon for a given game
---@param options gameIconOptions?
---@return string
function Game.icon(options)
	options = options or {}

	local gameData = Game.raw(options)

	local gameIcons
	local link = Logic.readBool(options.noLink) and '' or options.link or gameData.link
	local spanClass = (Logic.readBool(options.noSpan) and '') or
		(String.isNotEmpty(options.spanClass) and options.spanClass) or
		(String.isEmpty(options.size) and DEFAULT_SPAN_CLASS or '')

	if Table.isEmpty(gameData) then
		gameIcons = Game._createIcon{icon = ICON_PLACEHOLDER, size = options.size}
	elseif gameData.logo.lightMode == gameData.logo.darkMode then
		gameIcons = Game._createIcon{icon = gameData.logo.lightMode, size = options.size, link = link, alt = gameData.name}
	else
		gameIcons = Game._createIcon{icon = gameData.logo.lightMode, size = options.size,
				link = link, alt = gameData.name, mode = 'light'} ..
			Game._createIcon{icon = gameData.logo.darkMode, size = options.size,
				link = link, alt = gameData.name, mode = 'dark'}
	end

	if String.isNotEmpty(spanClass) then
		return tostring(mw.html.create('span'):addClass(spanClass):node(gameIcons))
	else
		return gameIcons
	end
end

---@param options {mode: string?, icon: string?, size: string?, link: string?, alt: string?}
---@return string
function Game._createIcon(options)
	return String.interpolate(
		ICON_STRING,
		{
			icon = options.icon,
			size = options.size or DEFAULT_SIZE,
			class = options.mode and ('show-when-' .. options.mode .. '-mode') or '',
			link = options.link or '',
			alt = options.alt or options.link or '',
		}
	)
end

---Fetches a text display for a given game
---@param options? {game: string?, useDefault: boolean?, noLink: boolean?, link: string?, useAbbreviation: boolean?}
---@return string?
function Game.text(options)
	options = options or {}

	local useAbbreviation = Logic.readBool(options.useAbbreviation)
	local gameData = Game.raw(options)
	if Table.isEmpty(gameData) then
		return Abbreviation.make(useAbbreviation and 'Unkwn.' or 'Unknown Game', 'The specified game input is not recognized')
	end

	if Logic.readBool(options.noLink) then
		return useAbbreviation and gameData.abbreviation or gameData.name
	else
		return Page.makeInternalLink({},
			useAbbreviation and gameData.abbreviation or gameData.name,
			options.link or gameData.link
		)
	end
end

Game.defaultTeamLogos = FnUtil.memoize(function()
	local defaultTeamLogos = {}
	for _, gameData in pairs(GamesData) do
		local teamLogos = gameData.defaultTeamLogo
		defaultTeamLogos[teamLogos.darkMode] = true
		defaultTeamLogos[teamLogos.lightMode] = true
	end

	return defaultTeamLogos
end)

---@param options {logo: string?, game: string?, useDefault: boolean?}
---@return boolean
function Game.isDefaultTeamLogo(options)
	local logo = options.logo
	if String.isEmpty(logo) then
		return false
	end
	---@cast logo -nil

	logo = logo:gsub('_', ' ')

	if String.isEmpty(options.game) then
		return Game.defaultTeamLogos()[logo] ~= nil
	end

	local defaultLogos = Game.raw(options).defaultTeamLogo
	if not defaultLogos then
		error('Invalid game input "' .. options.game .. '"')
	end

	return Table.includes(defaultLogos, logo)
end

return Class.export(Game)