Module:Servebox: Difference between revisions

From Against the Storm Official Wiki
m (A bit of cleanup)
(Updated to use utility module Infobox)
Line 1: Line 1:
---
---
--- Module to create an infobox for displaying on a workshop's wiki page.
--- Module to create an infobox for a service building's wiki page.
---
---
--- Shows the facts from the data about the specified workshop in an easy-to-
--- Shows the facts from the data about the specified service building in an
--- read table, with a large icon, information, categories, and the flavor
--- easy-to-read table, with a large icon, information, categories, and the
--- text.
--- flavor text.
---
---
--- This should be invoked from Template:Shopbox with the parameter of the
--- This should be invoked from Template:Servebox with the parameter of the
--- workshop whose infobox should be shown. See the template documentation for
--- building whose infobox should be shown. See the template documentation for
--- more information about parameters and errors and to see examples.
--- more information about parameters and errors and to see examples.
---
---
Line 14: Line 14:




 
local Infobox = require("Module:Infobox")
local InstitutionsData = require("Module:InstitutionsData")
local InstitutionsData = require("Module:InstitutionsData")
local ResourceLink = require("Module:ResourceLink")




Line 22: Line 21:
--region Private constants
--region Private constants


-- External templates
local ARG_NAME = "name"
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 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.
-- Subheading for all the buildings from this template.
local BUILDING_CATEGORY = "Service Building"
local BUILDING_CATEGORY = "Service Building"


local INDEX_REQ_STACK_SIZE = "stackSize"
local INDEX_REQ_GOOD_ID = "goodID"
local BOLD = "'''"
local NBSP = " "
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
--endregion
Line 76: Line 33:


--region Private methods
--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


---
---
Line 142: Line 55:


-- Start the inner table
-- Start the inner table
local innerTable = wikiInfobox:tag("tr"):tag("td"):newline():tag("table"):css(CSS_INLINE_INFOBOX_INNER_TABLE)
local innerTable = wikiInfobox:tag("tr"):tag("td"):newline():tag("table"):css(Infobox.CSS_INNER_TABLE)
innerTable:newline()
innerTable:newline()


Line 149: Line 62:
-- Construction toolbar category.
-- Construction toolbar category.
if institutionCategory then
if institutionCategory then
local categoryIconFilename = ICON_FILENAMES_CATEGORIES[institutionCategory]
 
local categoryIconFilename = Infobox.ICON_FILENAMES_CATEGORIES[institutionCategory]
if categoryIconFilename ~= nil then
if categoryIconFilename ~= nil then
local categoryIconPart = "[[File:" .. categoryIconFilename .. "|" .. ICONSIZE_MED .. "|alt=".. institutionCategory .. "]]"
local categoryIconPart = "[[File:" .. categoryIconFilename .. "|" .. Infobox.ICONSIZE_MED .. "|alt=".. institutionCategory .. "]]"
innerTable:tag("tr"):css(CSS_INLINE_INFOBOX_TR_TOP_DIVIDER)
 
  :tag("th"):wikitext(TITLE_CATEGORY):done()
Infobox.buildStandardRow(innerTable, Infobox.CSS_TR_BORDER_TOP,
  :tag("td"):wikitext(categoryIconPart .. NBSP .. institutionCategory):done()
Infobox.TITLE_CATEGORY, categoryIconPart .. NBSP .. institutionCategory)
  :done():newline()
end
end
end
end
-- Expand recipes into a small table
-- Expand recipes into a small table
if institutionRecipesTable and #institutionRecipesTable > 0 then
if institutionRecipesTable and #institutionRecipesTable > 0 then
local recipesRows = mw.getCurrentFrame():expandTemplate{ title="Recipe", args={
local recipesRows = mw.getCurrentFrame():expandTemplate{ title="Recipe", args={
building=institutionName, display="list" } }
building=institutionName, display="list" } }
innerTable:tag("tr"):css(CSS_INLINE_INFOBOX_TR_BOTTOM_DIVIDER)
 
:tag("th"):wikitext(TITLE_RECIPES):done()
Infobox.buildStandardRow(innerTable, Infobox.CSS_TR_BORDER_BOT,
:newline()
Infobox.TITLE_RECIPES, recipesRows)
:tag("td"):wikitext(recipesRows):done()
:done():newline()
end
end
-- Since false is a valid value, have to directly check if it's nil.
-- Since false is a valid value, have to directly check if it's nil.
if institutionIsMovable ~= nil then
if institutionIsMovable ~= nil then
innerTable:tag("tr"):css(CSS_INLINE_INFOBOX_TR_TOP_DIVIDER)
 
  :tag("th"):wikitext(TITLE_MOVABLE):done()
Infobox.buildStandardRow(innerTable, Infobox.CSS_TR_BORDER_TOP,
  :tag("td"):wikitext( institutionIsMovable and "Yes" or "No" ):done()
Infobox.TITLE_MOVABLE, institutionIsMovable and "Yes" or "No")
  :done():newline()
end
end
if institutionIsEssential ~= nil then
if institutionIsEssential ~= nil then
innerTable:tag("tr"):css(CSS_INLINE_INFOBOX_TR_BOTTOM_DIVIDER)
 
  :tag("th"):wikitext(TITLE_ESSENTIAL):done()
Infobox.buildStandardRow(innerTable, Infobox.CSS_TR_BORDER_BOT,
  :tag("td"):wikitext( institutionIsEssential and "Yes" or "No" ):done()
Infobox.TITLE_ESSENTIAL, institutionIsEssential and "Yes" or "No" )
  :done():newline()
end
end
-- Combine sizes into one line
-- Combine sizes into one line
if institutionSizeX ~= nil and institutionSizeY ~= nil then
if institutionSizeX ~= nil and institutionSizeY ~= nil then
innerTable:tag("tr"):css(CSS_INLINE_INFOBOX_TR_TOP_DIVIDER)
 
  :tag("th"):wikitext(TITLE_SIZE):done()
Infobox.buildStandardRow(innerTable, Infobox.CSS_TR_BORDER_TOP,
  :tag("td"):wikitext(institutionSizeX .. " × " .. institutionSizeY):done()
Infobox.TITLE_SIZE, institutionSizeX .. " × " .. institutionSizeY)
  :done():newline()
end
end
if institutionWorkplaces then
if institutionWorkplaces then
innerTable:tag("tr"):css(CSS_INLINE_INFOBOX_TR_BOTTOM_DIVIDER)
 
  :tag("th"):wikitext(TITLE_WORKPLACES):done()
Infobox.buildStandardRow(innerTable, Infobox.CSS_TR_BORDER_BOT,
  :tag("td"):wikitext(institutionWorkplaces):done()
Infobox.TITLE_WORKPLACES, institutionWorkplaces)
  :done():newline()
end
end
if institutionConstructionTime then
if institutionConstructionTime then
innerTable:tag("tr"):css(CSS_INLINE_INFOBOX_TR_TOP_DIVIDER)
 
  :tag("th"):wikitext(TITLE_CONSTRUCTION_TIME):done()
Infobox.buildStandardRow(innerTable, Infobox.CSS_TR_BORDER_TOP,
  :tag("td"):wikitext(institutionConstructionTime):done()
Infobox.TITLE_CONSTRUCTION_TIME, institutionConstructionTime)
  :done():newline()
end
end
-- Need to build a separate table to display building materials
-- Need to build a separate table to display building materials
if institutionRequiredGoods then
if institutionRequiredGoods then
local requiredGoodsRows = tostring( writeRequiredGoodsRows(institutionRequiredGoods) )
 
innerTable:tag("tr"):css(CSS_INLINE_INFOBOX_TR_BOTTOM_DIVIDER)
local requiredGoodsRows = tostring( Infobox.writeRequiredGoodsRows(institutionRequiredGoods) )
:tag("th"):wikitext(TITLE_CONSTRUCTION_COST):done()
 
:newline()
Infobox.buildStandardRow(innerTable, Infobox.CSS_TR_BORDER_BOT,
:tag("td"):newline():wikitext(requiredGoodsRows):newline():done()
Infobox.TITLE_CONSTRUCTION_COST, requiredGoodsRows)
:done():newline()
end
end
if institutionID then
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()
innerTable:tag("tr"):css(Infobox.CSS_TR_BORDER_TOP):css(Infobox.CSS_TR_BORDER_BOT)
  :tag("th"):wikitext(Infobox.TITLE_ID):done()
  :tag("td"):wikitext(institutionID):done()
  :tag("td"):wikitext(institutionID):done()
  :done():newline()
  :done():newline()
Line 221: Line 128:
wikiInfobox:done():done():newline()
wikiInfobox:done():done():newline()
end
end


--endregion
--endregion
Line 234: Line 140:
--- @param frame table the template's calling context
--- @param frame table the template's calling context
--- @return string wiki markup for the box
--- @return string wiki markup for the box
function Servebox.infobox(frame)
function Servebox.renderServebox(frame)
-- Every institution must have a name.
-- Every institution must have a name.
local institutionName = frame.args["name"]
local institutionName = frame.args[ARG_NAME]
if not institutionName or institutionName == "" then
if not institutionName or institutionName == "" then
return "You must specify the name of the service building. See [[Template:Servebox]] for examples."
return "You must specify the name of the service building. See [[Template:Servebox]] for examples."
Line 253: Line 159:
local institutionIconFilename = InstitutionsData.getInstitutionIcon(institutionName)
local institutionIconFilename = InstitutionsData.getInstitutionIcon(institutionName)


-- Make the top of the infobox that every workshop has...
-- Make the top of the infobox that every service building has...
local wikiInfobox = mw.html.create("table"):css(CSS_INLINE_INFOBOX):newline()
local wikiInfobox = mw.html.create("table"):css(Infobox.CSS_MAIN):newline()
-- with a title...
-- with a title...
wikiInfobox:tag("tr")
wikiInfobox:tag("tr")
Line 268: Line 174:
  :tag("td"):wikitext("[[File:" .. institutionIconFilename .. "]]"):done()
  :tag("td"):wikitext("[[File:" .. institutionIconFilename .. "]]"):done()
  :done():newline()
  :done():newline()
wikiInfobox:tag("tr"):css(CSS_INLINE_INFOBOX_TR_BOTTOM_DIVIDER)
wikiInfobox:tag("tr"):css(Infobox.CSS_TR_BORDER_BOT)
  :tag("td"):wikitext(institutionName .. ", as seen in-game"):done()
  :tag("td"):wikitext(institutionName .. ", as seen in-game"):done()
  :done():newline()
  :done():newline()
Line 277: Line 183:
-- Finish with the flavor text.
-- Finish with the flavor text.
if institutionDescription then
if institutionDescription then
wikiInfobox:tag("tr"):css(CSS_INLINE_INFOBOX_TR_TOP_DIVIDER)
wikiInfobox:tag("tr"):css(Infobox.CSS_TR_BORDER_TOP)
  :tag("td"):wikitext(institutionDescription):done()
  :tag("td"):wikitext(institutionDescription):done()
  :done():newline()
  :done():newline()

Revision as of 01:05, 28 November 2023

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

---
--- Module to create an infobox for a service building's wiki page.
---
--- Shows the facts from the data about the specified service building in an
--- easy-to-read table, with a large icon, information, categories, and the
--- flavor text.
---
--- This should be invoked from Template:Servebox with the parameter of the
--- building 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 Infobox = require("Module:Infobox")
local InstitutionsData = require("Module:InstitutionsData")



--region Private constants

local ARG_NAME = "name"

-- Subheading for all the buildings from this template.
local BUILDING_CATEGORY = "Service Building"

local NBSP = " "

--endregion



--region Private methods

---
--- 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 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(Infobox.CSS_INNER_TABLE)
	innerTable:newline()

	-- Additional parameters would go here.

	-- Construction toolbar category.
	if institutionCategory then

		local categoryIconFilename = Infobox.ICON_FILENAMES_CATEGORIES[institutionCategory]
		if categoryIconFilename ~= nil then
			local categoryIconPart = "[[File:" .. categoryIconFilename .. "|" .. Infobox.ICONSIZE_MED .. "|alt=".. institutionCategory .. "]]"

			Infobox.buildStandardRow(innerTable, Infobox.CSS_TR_BORDER_TOP,
					Infobox.TITLE_CATEGORY, categoryIconPart .. NBSP .. institutionCategory)
		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"	} }

		Infobox.buildStandardRow(innerTable, Infobox.CSS_TR_BORDER_BOT,
				Infobox.TITLE_RECIPES, recipesRows)
	end
	-- Since false is a valid value, have to directly check if it's nil.
	if institutionIsMovable ~= nil then

		Infobox.buildStandardRow(innerTable, Infobox.CSS_TR_BORDER_TOP,
				Infobox.TITLE_MOVABLE, institutionIsMovable and "Yes" or "No")
	end
	if institutionIsEssential ~= nil then

		Infobox.buildStandardRow(innerTable, Infobox.CSS_TR_BORDER_BOT,
				Infobox.TITLE_ESSENTIAL, institutionIsEssential and "Yes" or "No" )
	end
	-- Combine sizes into one line
	if institutionSizeX ~= nil and institutionSizeY ~= nil then

		Infobox.buildStandardRow(innerTable, Infobox.CSS_TR_BORDER_TOP,
				Infobox.TITLE_SIZE, institutionSizeX .. " × " .. institutionSizeY)
	end
	if institutionWorkplaces then

		Infobox.buildStandardRow(innerTable, Infobox.CSS_TR_BORDER_BOT,
				Infobox.TITLE_WORKPLACES, institutionWorkplaces)
	end
	if institutionConstructionTime then

		Infobox.buildStandardRow(innerTable, Infobox.CSS_TR_BORDER_TOP,
				Infobox.TITLE_CONSTRUCTION_TIME, institutionConstructionTime)
	end
	-- Need to build a separate table to display building materials
	if institutionRequiredGoods then

		local requiredGoodsRows = tostring( Infobox.writeRequiredGoodsRows(institutionRequiredGoods) )

		Infobox.buildStandardRow(innerTable, Infobox.CSS_TR_BORDER_BOT,
				Infobox.TITLE_CONSTRUCTION_COST, requiredGoodsRows)
	end
	if institutionID then

		innerTable:tag("tr"):css(Infobox.CSS_TR_BORDER_TOP):css(Infobox.CSS_TR_BORDER_BOT)
				  :tag("th"):wikitext(Infobox.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.renderServebox(frame)
	
	-- Every institution must have a name.
	local institutionName = frame.args[ARG_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 service building has...
	local wikiInfobox = mw.html.create("table"):css(Infobox.CSS_MAIN):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(Infobox.CSS_TR_BORDER_BOT)
				   :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(Infobox.CSS_TR_BORDER_TOP)
				   :tag("td"):wikitext(institutionDescription):done()
				   :done():newline()
	end
	
	return wikiInfobox
end

--endregion

return Servebox