Module:Servebox
From Against the Storm Official Wiki
Documentation for this module may be created at Module:Servebox/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 Servebox local Servebox = {} local InstitutionsData = require("Module:InstitutionsData") local ResourceLink = require("Module:ResourceLink") --region Private constants -- External templates local TEMPLATE_RL_ICON = "med" -- Infobox header labels local TITLE_ID = "ID" local TITLE_CATEGORY = "Toolbar Category" local TITLE_SIZE = "Building Size" local TITLE_MOVABLE = "Movable" local TITLE_ESSENTIAL = "Initially Essential" local DELETE_ME_TOO = "Storage Capacity" local TITLE_CONSTRUCTION_TIME = "Construction Time" local TITLE_CONSTRUCTION_COST = "Construction Cost" local TITLE_WORKPLACES = "Workplaces" local TITLE_RECIPES = "Services" -- Subheading for all the buildings from this template. local BUILDING_CATEGORY = "Service Building" local INDEX_REQ_STACK_SIZE = "stackSize" local INDEX_REQ_GOOD_ID = "goodID" local BOLD = "'''" local NBSP = " " local ICONSIZE_MED = mw.getCurrentFrame():expandTemplate{ title="ImgM" } local CSS_INLINE_INFOBOX = { ["float"] = "right", ["clear"] = "right", ["width"] = "256px", ["border"] = "1px solid #a2a9b1", ["border-spacing"] = "3px", ["border-collapse"] = "collapse", ["margin"] = "0.5em 0 0.5em 1em" } local CSS_INLINE_INFOBOX_INNER_TABLE = { ["border-collapse"] = "collapse" } local CSS_INLINE_INFOBOX_TR_BOTTOM_DIVIDER = { ["border-bottom"] = "1px solid #a2a9b1" } local CSS_INLINE_INFOBOX_TR_TOP_DIVIDER = { ["border-top"] = "1px solid #a2a9b1" } -- Only one valid construction toolbar category for buildings from this -- template. local ICON_FILENAMES_CATEGORIES = { ["City Buildings"] = "Construct City Buildings.png" } --endregion --region Private methods --- --- A shortcut method that redirects to ResourceLink to build links to goods --- with their IDs from the tables of required goods. --- ---@param goodID string the ID of the good to link to ---@return string wikimarkup representing an icon and link local function resourceLink(goodID) return ResourceLink.resourceLinkWithID(goodID, TEMPLATE_RL_ICON) 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 local function 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(resourceLink(goodID)):done() :done():newline() end return requiredGoodsRows end --- --- Lays out the provided recipe IDs in a small list. --- ---@param recipes table of recipe IDs ---@return string wiki markup of a list of those IDs local function writeRecipesRows(recipes) if not recipes or #recipes == 0 then error("Cannot write content with provided table of recipes.") end local recipeRows = mw.html.create("ul") recipeRows:newline() for _, recipeID in ipairs(recipes) do -- Temporarily, just write the ID of the recipe. recipeRows:tag("li"):wikitext(recipeID):done():newline() end recipeRows:done() return recipeRows end --- --- Builds using the provided wikiInfobox a subtable to lay out headers and --- fields. --- ---@param wikiInfobox table mw.html object into which we're building this ---@param institutionName string the name of the good the infobox is about ---@return table the Mediawiki html object into which we've been adding things local function makeInnerTable(wikiInfobox, institutionName) -- Grab the data we'll use to populate this. local institutionID = InstitutionsData.getInstitutionID(institutionName) local institutionCategory = InstitutionsData.getInstitutionCategory(institutionName) local institutionSizeX, institutionSizeY = InstitutionsData.getInstitutionSize(institutionName) local institutionIsMovable = InstitutionsData.isInstitutionMovable(institutionName) local institutionIsEssential = InstitutionsData.isInstitutionInitiallyEssential(institutionName) local DELETE_ME = nil local institutionConstructionTime = InstitutionsData.getInstitutionConstructionTime(institutionName) local institutionWorkplaces = InstitutionsData.getInstitutionNumberOfWorkplaces(institutionName) local institutionRequiredGoods = InstitutionsData.getAllInstitutionRequiredGoods(institutionName) local institutionRecipesTable = InstitutionsData.getAllInstitutionRecipes(institutionName) -- Start the inner table local innerTable = wikiInfobox:tag("tr"):tag("td"):newline():tag("table"):css(CSS_INLINE_INFOBOX_INNER_TABLE) innerTable:newline() -- Additional parameters would go here. -- Construction toolbar category. if institutionCategory then local categoryIconFilename = ICON_FILENAMES_CATEGORIES[institutionCategory] if categoryIconFilename ~= nil then local categoryIconPart = "[[File:" .. categoryIconFilename .. "|" .. ICONSIZE_MED .. "|alt=".. institutionCategory .. "]]" innerTable:tag("tr"):css(CSS_INLINE_INFOBOX_TR_TOP_DIVIDER) :tag("th"):wikitext(TITLE_CATEGORY):done() :tag("td"):wikitext(categoryIconPart .. NBSP .. institutionCategory):done() :done():newline() end end -- Expand recipes into a small table if institutionRecipesTable and #institutionRecipesTable > 0 then local recipesRows = mw.getCurrentFrame():expandTemplate{ title="Recipe", args={ building=institutionName, display="list" } } innerTable:tag("tr"):css(CSS_INLINE_INFOBOX_TR_BOTTOM_DIVIDER) :tag("th"):wikitext(TITLE_RECIPES):done() :newline() :tag("td"):wikitext(recipesRows):done() :done():newline() end -- Since false is a valid value, have to directly check if it's nil. if institutionIsMovable ~= nil then innerTable:tag("tr"):css(CSS_INLINE_INFOBOX_TR_TOP_DIVIDER) :tag("th"):wikitext(TITLE_MOVABLE):done() :tag("td"):wikitext( institutionIsMovable and "Yes" or "No" ):done() :done():newline() end if institutionIsEssential ~= nil then innerTable:tag("tr"):css(CSS_INLINE_INFOBOX_TR_BOTTOM_DIVIDER) :tag("th"):wikitext(TITLE_ESSENTIAL):done() :tag("td"):wikitext( institutionIsEssential and "Yes" or "No" ):done() :done():newline() end -- Combine sizes into one line if institutionSizeX ~= nil and institutionSizeY ~= nil then innerTable:tag("tr"):css(CSS_INLINE_INFOBOX_TR_TOP_DIVIDER) :tag("th"):wikitext(TITLE_SIZE):done() :tag("td"):wikitext(institutionSizeX .. " × " .. institutionSizeY):done() :done():newline() end if institutionWorkplaces then innerTable:tag("tr"):css(CSS_INLINE_INFOBOX_TR_BOTTOM_DIVIDER) :tag("th"):wikitext(TITLE_WORKPLACES):done() :tag("td"):wikitext(institutionWorkplaces):done() :done():newline() end if institutionConstructionTime then innerTable:tag("tr"):css(CSS_INLINE_INFOBOX_TR_TOP_DIVIDER) :tag("th"):wikitext(TITLE_CONSTRUCTION_TIME):done() :tag("td"):wikitext(institutionConstructionTime):done() :done():newline() end -- Need to build a separate table to display building materials if institutionRequiredGoods then local requiredGoodsRows = tostring( writeRequiredGoodsRows(institutionRequiredGoods) ) innerTable:tag("tr"):css(CSS_INLINE_INFOBOX_TR_BOTTOM_DIVIDER) :tag("th"):wikitext(TITLE_CONSTRUCTION_COST):done() :newline() :tag("td"):newline():wikitext(requiredGoodsRows):newline():done() :done():newline() end if institutionID then innerTable:tag("tr"):css(CSS_INLINE_INFOBOX_TR_TOP_DIVIDER):css(CSS_INLINE_INFOBOX_TR_BOTTOM_DIVIDER) :tag("th"):wikitext(TITLE_ID):done() :tag("td"):wikitext(institutionID):done() :done():newline() end -- Close the table. innerTable:done():newline() -- Close the table cell and row the inner table is in. wikiInfobox:done():done():newline() end --endregion --region Public methods --- --- Creates an html table to display the data in a floating box. --- --- @param frame table the template's calling context --- @return string wiki markup for the box function Servebox.infobox(frame) -- Every institution must have a name. local institutionName = frame.args["name"] if not institutionName or institutionName == "" then return "You must specify the name of the service building. See [[Template:Servebox]] for examples." end -- Use this method here to check to see whether the provided name is valid. if not InstitutionsData.getAllDataForInstitution(institutionName) then return "Servebox can't find the specified service building: " .. institutionName .. "." end -- Additional template parameters would go here. -- Get the data to display. local institutionDescription = InstitutionsData.getInstitutionDescription(institutionName) local institutionIconFilename = InstitutionsData.getInstitutionIcon(institutionName) -- Make the top of the infobox that every workshop has... local wikiInfobox = mw.html.create("table"):css(CSS_INLINE_INFOBOX):newline() -- with a title... wikiInfobox:tag("tr") :tag("th"):wikitext(institutionName):done() :done():newline() -- and a subtitle, showing the functional category... wikiInfobox:tag("tr") :tag("td"):wikitext(BUILDING_CATEGORY):done() :done():newline() -- and a large icon. if institutionIconFilename then wikiInfobox:tag("tr") :tag("td"):wikitext("[[File:" .. institutionIconFilename .. "]]"):done() :done():newline() wikiInfobox:tag("tr"):css(CSS_INLINE_INFOBOX_TR_BOTTOM_DIVIDER) :tag("td"):wikitext(institutionName .. ", as seen in-game"):done() :done():newline() end makeInnerTable(wikiInfobox, institutionName) -- Finish with the flavor text. if institutionDescription then wikiInfobox:tag("tr"):css(CSS_INLINE_INFOBOX_TR_TOP_DIVIDER) :tag("td"):wikitext(institutionDescription):done() :done():newline() end return wikiInfobox end --endregion return Servebox