Module:Infobox

From Against the Storm Official Wiki
Revision as of 02:24, 29 November 2023 by Aeredor (talk | contribs) (fixed missing camps icon)

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

---
--- Module to create an infobox for displaying on a workshop's wiki page.
---
--- Shows the facts from the data about the specified workshop in an easy-to-
--- read table, with a large icon, information, categories, and the flavor
--- text.
---
--- This should be invoked from Template:Shopbox with the parameter of the
--- workshop whose infobox should be shown. See the template documentation for
--- more information about parameters and errors and to see examples.
---
--- @module Infobox
local Infobox = {}



local GoodsData = require("Module:GoodsData")



--region Private constants

local RESOURCE_LINK_TEMPLATE = "rl"
local RESOURCE_LINK_ICONSIZE = "med"

local INDEX_REQ_STACK_SIZE= "stackSize"
local INDEX_REQ_GOOD_ID = "goodID"

local BOLD = "'''"

local PATTERN_FORMAT_TWO_DECIMALS = "%1.2f"
local PATTERN_CAPTURE_FIRST_LETTER_IN_WORD = "(%a)([%w]*)"

--endregion



--region Public constants

-- Infobox header labels
Infobox.TITLE_ID = "ID"
Infobox.TITLE_CATEGORY = "Toolbar Category"
Infobox.TITLE_SIZE = "Building Size"
Infobox.TITLE_EATABLE = "Eatable"
Infobox.TITLE_BURNABLE = "Burnable"
Infobox.TITLE_BURN_TIME = "Fuel burn time"
Infobox.TITLE_MOVABLE = "Movable"
Infobox.TITLE_ESSENTIAL = "Initially Essential"
Infobox.TITLE_STORAGE = "Storage Capacity"
Infobox.TITLE_FARMING_AREA = "Farming Area"
Infobox.TITLE_GATHERING_AREA = "Gathering Area"
Infobox.TITLE_CONSTRUCTION_TIME = "Construction Time"
Infobox.TITLE_CONSTRUCTION_COST = "Construction Cost"
Infobox.TITLE_SELL_VALUE = "Value when sold"
Infobox.TITLE_BUY_VALUE = "Price when bought"
Infobox.TITLE_WORKPLACES = "Workplaces"
Infobox.TITLE_RECIPES = "Recipes"

Infobox.ICONSIZE_MED = mw.getCurrentFrame():expandTemplate{ title="ImgM" }

-- Infobox styling
Infobox.CSS_MAIN = {
	["float"] = "right",
	["clear"] = "right",
	["width"] = "256px",
	["border"] = "1px solid #a2a9b1",
	["border-spacing"] = "3px",
	["border-collapse"] = "collapse",
	["margin"] = "0.5em 0 0.5em 1em"
}

Infobox.CSS_INNER_TABLE = {
	["border-collapse"] = "collapse"
}

Infobox.CSS_TR_BORDER_BOT = {
	["border-bottom"] = "1px solid #a2a9b1"
}

Infobox.CSS_TR_BORDER_TOP = {
	["border-top"] = "1px solid #a2a9b1"
}

-- Infobox icons
Infobox.ICON_FILENAMES_CATEGORIES = {
	-- Buildings
	["Camps"] = "Construct Camps.png",
	["City Buildings"] = "Construct City Buildings.png",
	["Food Production"] = "Construct Food Production.png",
	["Industry"] = "Construct Industry.png",
	-- Goods
	["Building Materials"]	= "Icon_UI_CategoryBuilding.png",
	["Consumable Items"]	= "Icon_UI_CategoryConsumable.png",
	["Crafting Resources"]	= "Icon_UI_CategoryCrafting.png",
	["Food"]				= "Icon UI CategoryFood.png",
	["Fuel & Exploration"]	= "Icon_UI_CategoryFuel.png",
	["Trade Goods"]			= "Icon_UI_CategoryTrade.png"
}

--endregion



--region Public methods

---
--- Shortcut string to reformat numbers with two decimals.
---
---@param value number whole or with a fractional part
---@return string reformatted to force two decimal places
function Infobox.toTwoDecimalPlaces(value)

	return string.format(PATTERN_FORMAT_TWO_DECIMALS, value)
end



---
--- Capitalizes the first character of each word to "Make It Title Case." Also
--- converts any underscores to spaces.
---
--- @param title string to capitalize
--- @return string capitalized with title case
function Infobox.toTitleCase(title)

	title = title:gsub("_", " ")

	local newTitle = title:gsub(PATTERN_CAPTURE_FIRST_LETTER_IN_WORD, function(firstLetter, rest)
		return firstLetter:upper() .. rest:lower()
	end)

	return newTitle
end



---
--- A shortcut method for making resource links.
---
---@param goodID string the ID of the good to link to
---@return string wikimarkup representing an icon and link
function Infobox.resourceLink(goodID)

	local goodName = GoodsData.getGoodNameByID(goodID)

	return mw.getCurrentFrame():expandTemplate{ title=RESOURCE_LINK_TEMPLATE, args={
		resource=goodName, iconsize= RESOURCE_LINK_ICONSIZE } }
end



---
--- Shortcut method to build a standard row with a header and a value.
---
---@param htmlNode table the MediaWiki HTML entity to build on
---@param cssInline string inline style to apply
---@param header string header text
---@param value string value text
function Infobox.buildStandardRow(htmlNode, cssInline, header, value)

	htmlNode:tag("tr"):css(cssInline)
			  :tag("th"):wikitext(header):done()
			  :tag("td"):wikitext(value):done()
			  :done():newline()

	return htmlNode
end



---
--- Lays out an inner, no-styling table to display construction goods with
--- their stack sizes.
---
--- @param requiredGoods table of required goods, with stack sizes and IDs
--- @return string wikimarkup for a table of required goods to insert in other markup
function Infobox.writeRequiredGoodsRows(requiredGoods)

	if not requiredGoods or #requiredGoods == 0 then
		error("Cannot write content with provided table of required goods.")
	end

	local requiredGoodsRows =  mw.html.create("table")
	requiredGoodsRows:newline()

	for _, requiredGroup in ipairs(requiredGoods) do

		local stackSize = requiredGroup[INDEX_REQ_STACK_SIZE]
		local goodID = requiredGroup[INDEX_REQ_GOOD_ID]

		requiredGoodsRows:tag("tr")
				:tag("td"):wikitext(BOLD .. stackSize .. BOLD):done()
				:tag("td"):wikitext(Infobox.resourceLink(goodID)):done()
			:done():newline()
	end

	return requiredGoodsRows
end

--endregion

return Infobox