Module:Value

From Zelda Wiki, the Zelda encyclopedia
Jump to navigation Jump to search
This is the main module for the following templates:
local p = {}
local h = {}
local Data = mw.loadData("Module:Value/Data")

local Franchise = require("Module:Franchise")
local Term = require("Module:Term")
local utilsArg = require("Module:UtilsArg")
local utilsString = require("Module:UtilsString")
local utilsTable = require("Module:UtilsTable")

function p.Enum(frame)
	local kind = frame.args[1]
	if not kind then
		error("Value kind required")
	end
	local templateName = mw.title.new(frame:getParent():getTitle()).baseText
	local args, err = utilsArg.parse(frame:getParent().args, p.Templates[templateName])
	local categories = err and err.categoryText or ""
	
	if err and err.args["value"] then
		local utilsError = require("Module:UtilsError")
		return utilsError.error(string.format("Invalid %s", kind)), categories
	end
	
	args.game = args.game or frame.args.game
	local link = string.format("[[%s#%s|%s]]", kind, args.value, args.value)
	local value = h.printValue("Enum", kind, args, link)
	return value, categories
end

function p.Number(frame)
	local kind = frame.args[1]
	if not kind then
		error("Value kind required")
	end
	local args, err = utilsArg.parse(frame:getParent().args, p.Templates[kind])
	local categories = err and err.categoryText or ""
	
	-- [[Template:Rupee]] passes the game as a template parameter, whereas for [[Template:Mon]] the game is passed in #invoke since the game is implicitly BotW
	args.game = args.game or frame.args.game
	args.value = args.value or ""
	
	local text = args.value
	if not args.format then
		local numValue = args.value:gsub(",", "")
		numValue = tonumber(numValue)
		local term = Term.printTerm(kind, args.game, {
			link = true,
			plural = numValue ~= 1,
			allowSingular = true,
		})
		text = args.value .. " "..term
	end

	local value = h.printValue("Number", kind, args, text)
	return value, categories
end

function h.printValue(type, kind, args, text)
	local file = h.getIconFile(type, kind, args)
	local icon
	if file and args.format then
		icon = string.format("[[%s|24x24px|link= %s]]", file, kind)
	elseif file then
		icon = string.format("[[%s|24x24px]]", file)
	end
	
	local kindId = utilsString.kebabCase(kind)
	local gameId = utilsString.kebabCase(args.game)
	local valueId = utilsString.kebabCase(args.value)
	local html = mw.html.create("div")
		:addClass("zw-value")
		:addClass(string.format("zw-value--%s", kindId))
		:addClass(string.format("zw-value--%s-%s", kindId, gameId))
	if type == "Enum" then
		html:addClass(string.format("zw-value--%s-%s-%s", kindId, gameId, valueId))
	end
	if icon then
		html:tag("span")
			:addClass("zw-value__icon")
			:wikitext(icon)
	end
	html:tag("span")
		:addClass("zw-value__text")
		:wikitext(text)
		
	local styles = mw.getCurrentFrame():extensionTag({
		name = "templatestyles",
		args = { src = "Module:Value/Styles.css" },
	})

	return styles..tostring(html)
end
function h.getIconFile(type, kind, args)
	local data = Data.kinds[kind] and Data.kinds[kind][args.game]
	if type == "Enum" then
		data = data and data[args.value]
	end
	return data and data.icon
end

function p.ListIcons(frame)
	local utilsLayout = require("Module:UtilsLayout")

	local kind = frame.args[1] 
	local data = Data.kinds[kind]
	
	local columns = {"Wikitext", "Output", "Game"}
	local dataRows = {}
	for i, game in ipairs(Franchise.enumGames()) do
		local icon = data[game] and data[game].icon
		if icon then
			local gameLink = Franchise.link(game)
			local input = string.format("{{%s|%s|100}}", kind, game)
			local output = mw.getCurrentFrame():preprocess(input)
			table.insert(dataRows, {
				"<pre>"..input.."</pre>",
				output,
				gameLink,
			})
		end
	end
	local wikitable = utilsLayout.table({
		headers = columns,
		rows = dataRows,
	})
	return wikitable
end

function p.Schemas(frame)
	return {
		Data = {
			type = "record",
			required = true,
			properties = {
				{
					name = "kinds",
					required = true,
					type = "map",
					keyPlaceholder = "valueKind",
					keys = { type = "string" },
					values = {
						type = "map",
						keyPlaceholder = "game",
						keys = { type = "string" },
						values = {
							oneOf = {
								{
									_tabName = "Number Value",
									type = "record",
									properties = {
										{
											name = "icon",
											required = true,
											type = "string",
											desc = "A full icon filename, with the <code>File:</code> prefix.",
										}
									}
								},
								{
									_tabName = "String Value",
									type = "map",
									keys = { type = "string" },
									keyPlaceholder = "string",
									values = {
										type = "record",
										properties = {
											{
												name = "icon",
												required = true,
												type = "string",
												desc = "A full icon filename, with the <code>File:</code> prefix.",
											}
										}
									},
								},
							},
						},
					}
				}
			}
		}
	}
end

function h.enumParams(args)
	local singular = args.singular
	local plural = args.plural
	local game = args.game
	
	local enum = game and utilsTable.keys(Data.kinds[singular][game])
	if enum then
		table.sort(enum)
	end
	local params = {
		{
			name = "value",
			required = true,
			type = "string",
			desc = string.format("An %s name. Case-sensitive.", singular),
			enum = enum,
		},
	}
	if not game then
		table.insert(params, 1, {
			name = "game",
			required = true,
			type = "string",
			desc = "A game abbreviation.",
			enum = Franchise.enumGames(),
		})
	end
	
	return params
end

function h.numberParams(args)
	local singular = args.singular
	local plural = args.plural
	local hasGameParam = args.hasGameParam
	local params = {
		{
			name = "value",
			required = true,
			type = "string",
			desc = string.format("A numerical value in %s units.", singular),
		},
		{
			name = "format",
			type = "boolean",
			desc = string.format('If set to <code>-</code>, the "[[%s|%s]]" text is removed and the %s article is linked in the icon instead. For use in large data tables.', singular, plural, singular)
		},
	}
	if hasGameParam ~= false then
		table.insert(params, 1, {
			name = "game",
			required = true,
			type = "string",
			desc = "A game abbreviation.",
			enum = Franchise.enumGames(),
		})
	end
	return params
end 

p.Templates = {
	["Defense"] = {
		desc = "Displays Defense values.",
		purpose = "Displaying [[Defense]] values of [[Armor]] in {{BotW}} and potentially other games in the future.",
		categories = {"Value templates"},
		params = h.numberParams({
			singular = "Defense",
			plural = "Defense",
		}),
		examples = {
			{"BotW", "10"},
			{"BotW", "10", "-"},
			{"BotW", ""},
		},
	},
	["HW Element"] = {
		categories = {"Value templates"},
		params = h.enumParams({
			singular = "Element",
			plural = "Elements",
			game = "HW",
		})
	},
	["Mon"] = {
		description = "Displays amounts in Mon.",
		purpose = "Displays [[Mon]] values, similar to [[Template:Rupee]].",
		categories = {"Value templates"},
		params = h.numberParams({
			singular = "Mon",
			plural = "Mon",
			hasGameParam = false,
		}),
		examples = {
			{"0"},
			{"1"},
			{"1,000"},
			{""},
		},
	},
	["Poe"] = {
		description = "Displays amounts in Poes.",
		purpose = "Displays [[Poe]] values, similar to [[Template:Rupee]].",
		categories = {"Value templates"},
		params = h.numberParams({
			singular = "Poe",
			plural = "Poes",
			hasGameParam = false,
		}),
		examples = {
			{"0"},
			{"1"},
			{"1,000"},
			{""},
		},
	},
	["Bubbul Gem"] = {
		description = "Displays amounts in Bubbul Gems.",
		purpose = "Displays [[Bubbul Gem]] values, similar to [[Template:Rupee]].",
		categories = {"Value templates"},
		params = h.numberParams({
			singular = "Bubbul Gem",
			plural = "Bubbul Gems",
			hasGameParam = false,
		}),
		examples = {
			{"0"},
			{"1"},
			{"5"},
			{""},
		},
	},
	["Pony Point"] = {
		description = "Displays amounts in Pony Points.",
		purpose = "Displays [[Pony Point]] values, similar to [[Template:Rupee]].",
		categories = {"Value templates"},
		params = h.numberParams({
			singular = "Pony Point",
			plural = "Pony Points",
			hasGameParam = false,
		}),
		examples = {
			{"0"},
			{"1"},
			{"1000"},
			{""},
		},
	},
	["Rupee"] = {
		description = "Displays amounts in Rupees.",
		purpose = "Displays [[Rupee]] values.",
		categories = {"Value templates"},
		params = h.numberParams({
			singular = "Rupee",
			plural = "Rupees",
			hasGameParam = true,
		})
	},
	["Zonaite"] = {
		description = "Displays amounts in Zonaite.",
		purpose = "Displays [[Zonaite]] values, similar to [[Template:Rupee]].",
		categories = {"Value templates"},
		params = h.numberParams({
			singular = "Zonaite",
			plural = "Zonaites",
			hasGameParam = false,
		}),
		examples = {
			{"0"},
			{"1"},
			{"1,000"},
			{""},
		},
	},
}

return p