Module:Region

From Zelda Wiki, the Zelda encyclopedia
Revision as of 21:10, 31 October 2022 by PhantomCaleb (talk | contribs)
Jump to navigation Jump to search

The source of truth for world region data relevant to The Legend of Zelda series.

This is the main module for the following templates: In addition, this module exports the following functions.

getRegion

getRegion(code, [options])

Parameters

Returns

  • An object containing the region's name and flag(s), or nil if no region exists for the given code.
  • An error category if no region exists for the given code.

local p = {}
local h = {}
local Data = mw.loadData("Module:Region/Data")

local utilsArg = require("Module:UtilsArg")

local DEFAULT_FLAG_SIZE = "20px"
local CATEGORY_INVALID_ARGS = "[[Category:"..require("Module:Constants/category/invalidArgs").."]]"
local CLASS_TOOLTIP = require("Module:Constants/class/tooltip")

function p.Flag(frame)
	local args, err = utilsArg.parse(frame:getParent().args, p.Templates.Flag)
	if err then
		return err.categoryText
	else
		local region = Data.regions[args.code]
		local flags = h.flags(region, args)
		local result = table.concat(flags, " ")
		return result
	end
end

function p.enum()
	local enum = {}
	for k, v in pairs(Data.regions) do
		if k ~= "jp" and k ~= "us" then
			table.insert(enum, {
				code = k,
				name = v.name
			})
		end
	end
	-- We put the wiki's native region (us) first followed by Nintendo's native region (jp)
	-- followed by every other country ordred by country name
	table.sort(enum, function(a, b)
		return a.name < b.name
	end)
	for i, v in ipairs(enum) do
		enum[i] = v.code
	end
	table.insert(enum, 1, "jp")
	table.insert(enum, 1, "us")
	
	enum.reference = "[[Module:Region/Data]]"
	return enum
end

function p.getRegion(code, options)
	options = options or {}
	local flagSize = options.flagSize or DEFAULT_FLAG_SIZE
	local flagTooltip = options.flagTooltip or "official"

	local region = Data.regions[code]
	if not region then
		local utilsError = require("Module:UtilsError")
		utilsError.warn(string.format("Invalid region <code>%s</code>. See [[Module:Region/Data]] for a list of supported regions.", code))
		return nil, CATEGORY_INVALID_ARGS
	else
		local result = {}
		result.name = region.name
		result.flags = h.flags(region, {
			size = flagSize,
			tooltip = flagTooltip,
		})
		result.abbr = mw.getCurrentFrame():expandTemplate({
			title = "Exp",
			args = {region.name, region.abbr}
		})
		return result, ""
	end
end

function h.flags(region, options)
	if not region then
		return nil, CATEGORY_INVALID_ARGS
	elseif region.flag then
		local name = region.official or region.name
		local flagFile = region.flag
		local size = options.size
		local tooltip = region[options.tooltip] or region.name
		local flag = string.format('<span class="%s" title="%s">[[%s|%s|%s]]</span>', CLASS_TOOLTIP, tooltip, flagFile, size, tooltip)
		return {flag}, ""
	elseif region.countries then
		local flags = {}
		for i, country in ipairs(region.countries) do
			table.insert(flags, p.getRegion(country).flags[1])
		end
		return flags, ""
	else
		return {""}, ""
	end
end

function p.Documentation(frame)
	return {
		getRegion = {
			params = {"code", "options"},
			returns = {
				"An object containing the region's name and flag(s), or <code>nil</code> if no region exists for the given code.",
				"An error category if no region exists for the given code.",
			},
		},
	}
end

function p.Schemas(frame)
	return {
		getRegion = {
			code = {
				required = true,
				type = "string",
				desc = "A region code from [[Module:Region/Data]]."
			},
			options = {
				type = "record",
				properties = {
					{
						name = "flagSize",
						type = "string",
						default = DEFAULT_FLAG_SIZE,
						desc = "The image size to use for the region's flag(s).",
					},
					{
						name = "flagTooltip",
						type = "string",
						default = "official",
						desc = "<code>name</code> or <code>official</code>. Determines which name is used as the flag's tooltip.",
					},
				},
			},
		},
		Data = {
			type = "record",
			required = true,
			properties = {
				{
					name = "regions",
					required = true,
					type = "map",
					desc = "A list of regions that Nintendo (or other Zelda-related companies) markets to.",
					keyPlaceholder = "code",
					keys = {
						type = "string",
						desc = "An {{Wp|ISO 3166-1 alpha-2}} country code, or a 3+ character code denoting a multi-country region forming a single market segment.",
					},
					values = {
						type = "record",
						properties = {
							{
								name = "name",
								required = true,
								type = "string",
								desc = "The name of the country or region.",
							},
							{
								name = "abbr",
								required = true,
								type = "string",
								desc = "Abbreviated name for the region, used by [[Template:Release]]. For countries, this should be the {{Wp|ISO 3166-1 alpha-3}} country code. For multi-country regions, use a 4+ character abbreviation, or else a 3-character abbreviation that is not a reserved ISO 3166-1 alpha-3 code.",
							},
							{
								name = "flag",
								type = "string",
								desc = "The file name of the region's flag",
							},
							{
								name = "official",
								type = "string",
								desc = "The official state name of the country, used as the flag's tooltip. Defaults to <code>name</code>.",
							},
							{
								name = "countries",
								type = "array",
								items = { type = "string" },
								desc = "For multi-country regions, a list of country codes that comprise the region.",
							},
						},
					},
				},
			},
		}
	}
end

function p.Data(frame)
	local utilsLayout = require("Module:UtilsLayout")
	local utilsTable = require("Module:UtilsTable")

	local countries = {}
	local multiCountryRegions = {}
	
	for code in pairs(Data.regions) do
		local region = p.getRegion(code)
		local row = {
			id = code,
			cells = {
				"<code>"..code.."</code>",
				table.concat(region.flags, " "),
				region.abbr,
				region.name,
			}
		}
		if code:len() == 2 then
			table.insert(countries, row)
		else
			table.insert(multiCountryRegions, row)
		end
	end
	countries = utilsTable.sortBy(countries, "id")
	multiCountryRegions = utilsTable.sortBy(multiCountryRegions, "id")
	
	
	local countriesTable = utilsLayout.table({
		caption = "Countries",
		sortable = {1, 3, 4},
		headers = {"{{Wp|ISO 3166-1 alpha-2|Code}}", "Flag", "Abbr.", "Name"},
		rows = countries,
	})
	local multiCountryRegionsTable = utilsLayout.table({
		caption = "Multi-Country Regions",
		sortable = {1, 3},
		headers = {"Code", "Flags", "Abbr.", "Name"},
		rows = multiCountryRegions,
	})

	local html = mw.html.create("div")
		:css({
			["display"] = "flex",
			["flex-wrap"] = "wrap",
			["gap"] = "1rem",
		})
		:wikitext(countriesTable)
		:wikitext(multiCountryRegionsTable)

	return tostring(html)
end

p.Templates = {
	["Flag"] = {
		purpose = "Displays a region's [[:Category:Flags|flag(s)]].",
		params = {
			[1] = {
				name = "code",
				required = true,
				type = "string",
				enum = p.enum(),
				desc = "A code representing a region. For countries, this is the {{Wp|ISO 3166-1 alpha-2}} code.",
			},
			[2] = {
				name = "size",
				type = "string",
				default = DEFAULT_FLAG_SIZE,
				desc = "An {{MediaWiki|Help:Images#Size_and_frame|image size}}."
			},
		},
	}
}

return p