Module:Infobox

--- --- 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") local StyleUtils = require("Module:StyleUtils")

--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 = "Category" Infobox.TITLE_SIZE = "Size" Infobox.TITLE_EATABLE = "Eatable" Infobox.TITLE_BURNABLE = "Burnable" Infobox.TITLE_BURN_TIME = "Burn time" Infobox.TITLE_MOVABLE = "Movable" Infobox.TITLE_ESSENTIAL = "Essential" Infobox.TITLE_STORAGE_CAPACITY = "Storage" Infobox.TITLE_FARMING_AREA = "Farming Area" Infobox.TITLE_GATHERING_AREA = "Gather Range" Infobox.TITLE_CONSTRUCTION_TIME = "Build Time" Infobox.TITLE_CONSTRUCTION_COST = "Build Cost" Infobox.TITLE_SELL_VALUE = "Sell value" Infobox.TITLE_BUY_VALUE = "Buy price" 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 Private methods

--- --- Adds a separator if needed. --- ---@param row table html table row we're building ---@param needsSeparator boolean whether we need a separator ---@return boolean whether we still need a separator local function trySeparator(row, needsSeparator)

if needsSeparator then StyleUtils.styleInfoboxSeparator(row) needsSeparator = false end

return needsSeparator end

--- --- Shortcut method to populate the provided row with a header and a value. --- ---@param htmlRow table the html table row we're populating ---@param header string header text ---@param value string value text ---@return table the same htmlTable local function populateStandardRow(htmlRow, header, value)

htmlRow:tag("th"):wikitext(header):done :tag("td"):wikitext(value):done :done:newline

return htmlRow end

--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

--- --- A shortcut method for looking up an icon and assigning its wiki markup. --- ---@param category string the category of the icon to make ---@return string the wiki markup for the icon function Infobox.makeCategoryIcon(category)

return "" end

--- --- A shortcut method for making a standard title. --- ---@param parentNode table the html node to add to ---@param title string the title to write ---@return table the title node added function Infobox.makeTitle(parentNode, title)

local p = parentNode:tag("p") StyleUtils.styleInfoboxTitle(p)

p:wikitext(title):done:newline

return p end

--- --- A shortcut method for adding a description as flavor text. --- ---@param parentNode table the html node to add to ---@param description string the description to write out ---@return table the title node added function Infobox.makeFlavorText(parentNode, description)

local p = parentNode:tag("p") StyleUtils.styleInfoboxFlavorText(p)

p:wikitext(description):done:newline

return p end

--- --- A shortcut method for adding a large icon to the header. --- ---@param parentNode table the html node to add to ---@param iconFilename string the icon to use ---@return table the title node added function Infobox.makeTitleIcon(parentNode, iconFilename)

local div = parentNode:tag("div") StyleUtils.styleInfoboxTitleIcon(div)

div:wikitext(""):done:newline

return div end

--- --- A shortcut method to make a table row based on the provided check, also --- checks to see whether it needs to add a separator. --- ---@param parentNode table the html node to add to ---@param check boolean whether the row can be added ---@param needsSeparator boolean whether the row needs a separator before it ---@param header string the header of the row ---@param value string the value of the row ---@return boolean whether the next row still needs a separator before it function Infobox.makeInnerRow(parentNode, check, needsSeparator, header, value)

local row if check ~= nil and check ~= "" then

row = parentNode:tag("tr") needsSeparator = trySeparator(row, needsSeparator)

populateStandardRow(row, header, value) end

return needsSeparator end

--- TODO DELETE THIS because we're not doing inline css anymore --- 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 ---@return table the same htmlTable 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

--- --- Starts off a new infobox. --- --- @return table the html node created function Infobox.startNewInfobox

local wikiInfobox = mw.html.create("div") StyleUtils.styleInfobox(wikiInfobox)

wikiInfobox:newline

return wikiInfobox end

--- --- Creates a standard way of displaying the top content of the infobox and --- returns the HTML node. Styles consistently. --- ---@param wikiInfobox table the overall context this is added to ---@return table the html node created function Infobox.startNewHeader(wikiInfobox)

local header = wikiInfobox:tag("div") StyleUtils.styleInfoboxHeader(header)

header:newline

return header end

--- --- Finalizes the standard top content --- ---@param wikiInfobox table the overall context ---@param header table the header content to add to the outer context function Infobox.endInnerTable(wikiInfobox, header)

header:done:newline

return wikiInfobox end

--- --- Creates a standard way of displaying rows of headers and values and --- returns the HTML node. Styles consistently. --- ---@param wikiInfobox table the overall context this is added to ---@return table the html node created function Infobox.startNewInnerTable(wikiInfobox)

local innerTable = wikiInfobox:tag("table") innerTable = StyleUtils.styleInfoboxInnerTable(innerTable)

innerTable:newline

return innerTable end

--- --- Finalizes the standard inner display of headers and values. --- ---@param wikiInfobox table the overall context ---@param innerTable table the inner content to add to the outer context function Infobox.endInnerTable(wikiInfobox, innerTable)

innerTable:done:newline

return wikiInfobox end

--endregion

return Infobox