Module:BuildingLink: Difference between revisions

From Against the Storm Official Wiki
(copied over appropriate updates to ResourceLink here)
(Updated to new data model!)
 
(25 intermediate revisions by the same user not shown)
Line 1: Line 1:
-------------------------------------------------------------------------------
--- @module BuildingLink
-- Renders the {{Building_link}} template
local BuildingLink = {}
--
 
-- Takes an argument, the name of the building. Optionally, accepts a second
 
-- argument, "med" or "large" or "huge" to render an icon when the link is
 
-- used outside of in-line with text.
--region Dependencies
-------------------------------------------------------------------------------
 
local BuildingDataProxy = require("Module:BuildingDataProxy")
 
local VIEW_TEMPLATE = "Building_link/view"
 
--endregion
 
 
 
--region Private constants
 
local VALID_SIZE = {
["none"] = true,
["small"] = true,
["medium"] = true,
["large"] = true,
["huge"] = true,
}
 
local VALID_PLURAL = {
["s"] = true,
["es"] = true,
}
 
--endregion
 
 
 
--region Private methods
 
---tryData retrieves the icon from the provided building interface. Based on the interface, if name is nil or there is no icon, this method will return nil
---
---@param name string the display name of a building
---@param buildingInterface table a data module require'd and passed in
---@return string the filename of the icon, if any is found
local function tryData(name, buildingInterface)
 
local buildingID = buildingInterface.getID(name)
 
return buildingInterface.getIcon(buildingID)
end


local BuildingLink = {}


local BuildingData = require("Module:BuildingData") -- lookup table for buildings
 
---validateBuildingName attempts to find in each of the data modules the name specified. If the name is not found, an error is thrown. If the name is found in one of the data modules, it will return the icon filename. So we return that as proof the building was found (and to use it, of course).
---
---@param name string the display name of a building
---@return string the filename of the icon for that building
local function validateBuildingName(name)
 
local id = BuildingDataProxy.getID(name)
if not id then
error("No building found with name: " .. name .. ". Please see the template documentation for how to use the parameters")
end
 
local validatedIcon = BuildingDataProxy.getIcon(id)
if not validatedIcon then
error("Could not validate building with name: " .. name .. ". Please see the template documentation for how to use the parameters")
end
return validatedIcon
end
 
--endregion






-------------------------------------------------------------------------------
--region Public methods
-- Constants
-------------------------------------------------------------------------------
local TEMPLATE_IMGSMALL = "ImgS"
local TEMPLATE_IMGMED = "ImgM"
local TEMPLATE_IMGLARGE = "ImgL"
local TEMPLATE_IMGHUGE = "ImgH"


local REPLACEMENT_FILENAME = "Question_mark.png"
---main
--- Extracts parameters, validates the building by getting its icon, and then sends the data to the view template for rendering.
---
--- @param frame table the template's context, with arguments
--- @return string wiki markup
function BuildingLink.main(frame)


local name = frame.args.name
local iconSize = frame.args.size
local display = frame.args.display
local needsPlural


if not name or name == "" then
error("You must specify a building. Please see the template documentation for how to use the parameters")
end


-------------------------------------------------------------------------------
-- Initialize the array of unnamed parameters, up to 3, so several may be nil.
-- Main rendering function
local parent = frame:getParent()
-- uses ResourceData lookup function, parses the result and handles errors
if parent then
-- with default values, then assembles a final string to return to the wiki
local parameterStack = { parent.args[1], parent.args[2], parent.args[3], }
-------------------------------------------------------------------------------
-- Then empty the stack and try to assign them as our variables.
function BuildingLink.renderLink(frame)
for _, nextParameter in ipairs(parameterStack) do
local argBuildingName = frame.args.building
if nextParameter and nextParameter ~= "" then
local argBuildingIconSize = frame.args.iconsize
-- Prioritize setting the name first.
if not name or name == "" then
if not argBuildingName then
name = nextParameter
return "Building_Link Error: no building given"
else
-- These could happen in either order, because their valid values are non-overlapping
if (not iconSize or iconSize == "") and VALID_SIZE[nextParameter] then
iconSize = nextParameter
else
if not needsPlural and VALID_PLURAL[nextParameter] then
needsPlural = nextParameter
end
end
end
end
end
end
end
 
-- get the data about the building and then adopt the provided name
-- Validate the name before we continue any further.
-- in case we need to look it up again
validatedIcon = validateBuildingName(name)
local tableData = BuildingData.getData(argBuildingName)
 
if not tableData then
-- Handle default icon size.
return "Building_Link Error: " .. argBuildingName .." not found"
if not iconSize or iconSize == "" or not VALID_SIZE[iconSize] then
iconSize = "none"
end
end
local strPageName = tableData.page
 
-- if looking up the provided resource name returned no page, then render an error
-- The only valid value for mustBePlural is "s," so then make on check to see if name ends in a way that we need to add "es" at the end instead of just "s". For names that end in "y", we swap out the last character for "ies" instead. (This will require one-time setup for redirect pages.)
if not strPageName then
if needsPlural == "s" or needsPlural == "es" then
return "Building_Link Error: " .. argBuildingName .." not found"
if string.match(name,"y$") then
name = string.sub(name,1,-2) .. "ies"
needsPlural = nil -- unset now, since it's incorporated into the name itself
else
local needsSyllable = string.match(name,"[sxz]$") or string.match(name,"sh$") or string.match(name,"ch$")
needsPlural = needsSyllable and "es" or "s"
end
else
needsPlural = nil
end
end


-- if the icon filename didn't exist, then show a default but subtle question mark icon instead
-- The args to pass to the view.
-- this will help people with troubleshooting, instead of just showing no icon then editors
viewParameters = {
-- wonder what went wrong
["name"] = name,
local strIconFilename = tableData.iconfile or REPLACEMENT_FILENAME
["plural"] = needsPlural,
["iconfilename"] = validatedIcon,
-- use the established templates for image sizes, with the default being
["iconsize"] = iconSize,
-- no icon for buildings
["display"] = display,
local switchIconSize = {
}
["med"] = frame:expandTemplate{title=TEMPLATE_IMGMED},
 
["large"] = frame:expandTemplate{title=TEMPLATE_IMGLARGE},
return frame:expandTemplate{
["huge"] = frame:expandTemplate{title=TEMPLATE_IMGHUGE}
title = VIEW_TEMPLATE,
args = viewParameters,
}
}
-- if it's not in the switch, then skip the file part and just return the link
local strIconSize = switchIconSize[argBuildingIconSize]
if not strIconSize then
return "[[" .. strPageName .. "]]"
end
-- combine the string parts to return to the page
local strFilePart = string.format("[[File:%s|%s|link=%s|alt=%s|%s]]", strIconFilename, strIconSize, strPageName, strPageName, strPageName)
-- combine the file part with the link part
return strFilePart .. " [[" .. strPageName .. "]]"
end
end
--endregion


return BuildingLink
return BuildingLink

Latest revision as of 01:43, 30 October 2024

Documentation for this module may be created at Module:BuildingLink/doc

--- @module BuildingLink
local BuildingLink = {}



--region Dependencies

local BuildingDataProxy = require("Module:BuildingDataProxy")

local VIEW_TEMPLATE = "Building_link/view"

--endregion



--region Private constants

local VALID_SIZE = {
	["none"] = true,
	["small"] = true,
	["medium"] = true,
	["large"] = true,
	["huge"] = true,
}

local VALID_PLURAL = {
	["s"] = true,
	["es"] = true,
}

--endregion



--region Private methods

---tryData retrieves the icon from the provided building interface. Based on the interface, if name is nil or there is no icon, this method will return nil
---
---@param name string the display name of a building
---@param buildingInterface table a data module require'd and passed in
---@return string the filename of the icon, if any is found
local function tryData(name, buildingInterface)

	local buildingID = buildingInterface.getID(name)

	return buildingInterface.getIcon(buildingID)
end



---validateBuildingName attempts to find in each of the data modules the name specified. If the name is not found, an error is thrown. If the name is found in one of the data modules, it will return the icon filename. So we return that as proof the building was found (and to use it, of course).
---
---@param name string the display name of a building
---@return string the filename of the icon for that building
local function validateBuildingName(name)

	local id = BuildingDataProxy.getID(name)
	if not id then
		error("No building found with name: " .. name .. ". Please see the template documentation for how to use the parameters")
	end

	local validatedIcon = BuildingDataProxy.getIcon(id)
	if not validatedIcon then
		error("Could not validate building with name: " .. name .. ". Please see the template documentation for how to use the parameters")
	end
	return validatedIcon
end

--endregion



--region Public methods

---main
--- Extracts parameters, validates the building by getting its icon, and then sends the data to the view template for rendering.
---
--- @param frame table the template's context, with arguments
--- @return string wiki markup
function BuildingLink.main(frame)

	local name = frame.args.name
	local iconSize = frame.args.size
	local display = frame.args.display
	local needsPlural

	if not name or name == "" then
		error("You must specify a building. Please see the template documentation for how to use the parameters")
	end

	-- Initialize the array of unnamed parameters, up to 3, so several may be nil.
	local parent = frame:getParent()
	if parent then
		local parameterStack = { parent.args[1], parent.args[2], parent.args[3], }
		-- Then empty the stack and try to assign them as our variables.
		for _, nextParameter in ipairs(parameterStack) do
			if nextParameter and nextParameter ~= "" then
				-- Prioritize setting the name first.
				if not name or name == "" then
					name = nextParameter
				else
					-- These could happen in either order, because their valid values are non-overlapping
					if (not iconSize or iconSize == "") and VALID_SIZE[nextParameter] then
						iconSize = nextParameter
					else
						if not needsPlural and VALID_PLURAL[nextParameter] then
							needsPlural = nextParameter
						end
					end
				end
			end
		end
	end

	-- Validate the name before we continue any further.
	validatedIcon = validateBuildingName(name)

	-- Handle default icon size.
	if not iconSize or iconSize == "" or not VALID_SIZE[iconSize] then
		iconSize = "none"
	end

	-- The only valid value for mustBePlural is "s," so then make on check to see if name ends in a way that we need to add "es" at the end instead of just "s". For names that end in "y", we swap out the last character for "ies" instead. (This will require one-time setup for redirect pages.)
	if needsPlural == "s" or needsPlural == "es" then
		if string.match(name,"y$") then
			name = string.sub(name,1,-2) .. "ies"
			needsPlural = nil -- unset now, since it's incorporated into the name itself
		else
			local needsSyllable = string.match(name,"[sxz]$") or string.match(name,"sh$") or string.match(name,"ch$")
			needsPlural = needsSyllable and "es" or "s"
		end
	else
		needsPlural = nil
	end

	-- The args to pass to the view.
	viewParameters = {
		["name"] = name,
		["plural"] = needsPlural,
		["iconfilename"] = validatedIcon,
		["iconsize"] = iconSize,
		["display"] = display,
	}

	return frame:expandTemplate{
		title = VIEW_TEMPLATE,
		args = viewParameters,
	}
end

--endregion

return BuildingLink