Module:Shopbox

From Against the Storm Official Wiki
Revision as of 16:55, 10 November 2023 by Aeredor (talk | contribs) (fixing typos)

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

---
-- Module to create infobox for displaying on a workshop's wiki page.
--
-- @module Shopbox
local Shopbox = {}

---
-- Dependencies
---
local RecipeData = require("Module:RecipeData")

---
-- Constants
---
local ARG_WORKSHOP_NAME = "name"

local INDEX_WORKSHOP_ID = 1
local INDEX_WORKSHOP_NAME = 2
local INDEX_WORKSHOP_DESCRIPTION = 3
local INDEX_WORKSHOP_CATEGORY = 4
local INDEX_WORKSHOP_SIZE_X = 5
local INDEX_WORKSHOP_SIZE_Y = 6
local INDEX_WORKSHOP_CITY_SCORE = 7
local INDEX_WORKSHOP_MOVABLE = 8
local INDEX_WORKSHOP_INITIALLY_ESSENTIAL = 9
local INDEX_WORKSHOP_STORAGE = 10
local INDEX_WORKSHOP_CONSTRUCTION_TIME = 11
local INDEX_WORKSHOP_REQUIRED_GOODS = 12
local INDEX_WORKSHOP_WORKPLACES = 13
local INDEX_WORKSHOP_RECIPES = 14

local TITLE_ID = "ID"
local TITLE_CATEGORY = "Toolbar Category"
local TITLE_SIZE = "Building Footprint"
local TITLE_MOVABLE = "Movable"
local TITLE_ESSENTIAL = "Initially Essential"
local TITLE_STORAGE_CAPACITY = "Storage Capacity"
local TITLE_CONSTRUCTION_TIME = "Construction Time"
local TITLE_CONSTRUCTION_COST = "Construction Cost"
local TITLE_WORKPLACES = "Workplaces"
local TITLE_RECIPES = "Recipes"

local VALUE_TYPE = "Production Building"

local BOLD = "'''"
local NBSP = " "

local WIKI_MED_ICON_MARKUP = "|32px|alt="

local categoryIcons = {
	["Food Production"] = "Construct Food Production.png",
	["Industry"] = "Construct Industry.png"
}

local CSS_INFOBOX_INLINE_STYLE_TABLE = { 
	["float"] = "right", 
	["clear"] = "right", 
	["width"] = "256px", 
	["border"] = "1px solid #a2a9b1", 
	["border-spacing"] = "3px",
	["margin"] = "0.5em 0 0.5em 1em"
}



---
-- Member variable: Workshop
-- 
local workshop



---
-- Creates an html table to display the data in a floating box.
--
-- @param frame the template's calling context
-- @return wiki markup for the box
function Shopbox.infobox(frame)
	
	-- Every workshop must have a name.
	local name = frame.args[ARG_WORKSHOP_NAME]
	
	if not name or name == "" then
		error("You must specify the name of the building in the Shopbox template.")
	end
	
	-- Custom parameters
	
	-- Retrieve the actual data for the workshop.
	workshop = RecipeData.getAllDataForWorkshop(name)
	
	if not workshop then
		return "No building found for infobox."
	end
	
	local workshopID = workshop[INDEX_WORKSHOP_ID]
	local workshopDescription = workshop[INDEX_WORKSHOP_DESCRIPTION]
	local workshopCategory = workshop[INDEX_WORKSHOP_CATEGORY]
	local workshopSizeX = workshop[INDEX_WORKSHOP_SIZE_X]
	local workshopSizeY = workshop[INDEX_WORKSHOP_SIZE_Y]
	local workshopIsMovable = workshop[INDEX_WORKSHOP_MOVABLE]
	local workshopIsEssential = workshop[INDEX_WORKSHOP_INITIALLY_ESSENTIAL]
	local workshopStorageCap = workshop[INDEX_WORKSHOP_STORAGE]
	local workshopConstructionTime = workshop[INDEX_WORKSHOP_CONSTRUCTION_TIME]
	local workshopConstructionGoods = workshop[INDEX_WORKSHOP_REQUIRED_GOODS]
	local workshopWorkplaces = workshop[INDEX_WORKSHOP_WORKPLACES]
	local workshopRecipes = workshop[INDEX_WORKSHOP_RECIPES]
	
	local _, workshopIconFilename = RecipeData.getWorkshopNameAndIcon(workshopID)
	
	-- Make the top of the infobox that every item has.
	wikiInfobox = mw.html.create("table"):css( CSS_INFOBOX_INLINE_STYLE_TABLE ):newline()
	
	-- Title of infobox.
	if name then
		wikiInfobox:tag("tr"):tag("td"):wikitext(name):done():done():newline()
	end
	
	-- Subtitle for category.
	wikiInfobox:tag("tr"):tag("td"):wikitext(VALUE_TYPE):done():done():newline()
	
	-- Large icon of infobox.
	if workshopIconFilename then
		wikiInfobox:tag("tr"):tag("td"):wikitext("[[File:" .. workshopIconFilename .. ".png]]"):done():done():newline()
		wikiInfobox:tag("tr"):tag("td"):wikitext(name .. " icon as seen in-game"):done():done():newline()
	end
	
	-- Data fields of the infobox with labels and values
	local innerTable = wikiInfobox:tag("tr"):tag("td"):tag("table")
	innerTable:newline()
	
	-- Data provided by the CSV
	if workshopCategory then
		local catIcon = "[[File:" .. categoryIcons[workshopCategory] .. WIKI_MED_ICON_MARKUP .. workshopCategory .. "]]"
		innerTable:tag("tr"):tag("th"):wikitext(TITLE_CATEGORY):done()
			:tag("td"):wikitext(catIcon .. NBSP .. workshopCategory):done():done():newline()
	end
	if workshopSizeX and workshopSizeY then
		innerTable:tag("tr"):tag("th"):wikitext(TITLE_SIZE):done()
			:tag("td"):wikitext(workshopSizeX .. " × " .. workshopSizeY):done():done():newline()
	end
	if workshopIsMovable then
		local isMovable = workshopIsMovable == "TRUE"
		innerTable:tag("tr"):tag("th"):wikitext(TITLE_MOVABLE):done()
			:tag("td"):wikitext( isMovable and "Yes" or "No" ):done():done():newline()
	end
	if workshopIsEssential then
		local isEssential = workshopIsEssential == "TRUE"
		innerTable:tag("tr"):tag("th"):wikitext(TITLE_ESSENTIAL):done()
			:tag("td"):wikitext( isEssential and "Yes" or "No" ):done():done():newline()
	end
	if workshopStorageCap then
		innerTable:tag("tr"):tag("th"):wikitext(TITLE_STORAGE_CAPACITY):done()
			:tag("td"):wikitext(workshopStorageCap):done():done():newline()
	end
	if workshopWorkplaces then
		innerTable:tag("tr"):tag("th"):wikitext(TITLE_WORKPLACES):done()
			:tag("td"):wikitext(countWorkplaces(workshopWorkplaces)):done():done():newline()
	end
	if workshopConstructionTime then
		innerTable:tag("tr"):tag("th"):wikitext(TITLE_CONSTRUCTION_TIME):done()
			:tag("td"):wikitext(workshopConstructionTime):done():done():newline()
	end
	
	-- Need to build a separate table to display building materials
	if workshopConstructionGoods then
		local matsTable = tostring(writeRequiredGoodsRows(workshopConstructionGoods))
		innerTable:tag("tr"):tag("th"):wikitext(TITLE_CONSTRUCTION_COST):done()
			:newline()
			:tag("td"):newline():wikitext(matsTable):newline():done():done():newline()
	end
	
	wikiInfobox:newline()
	
	if workshopDescription then
		wikiInfobox:tag("tr"):tag("td"):wikitext(workshopDescription):done():done():newline()
	end
	
	return wikiInfobox
end



---
-- Steps through the provided workplace list and counts non-empty strings
--
-- @param workshopWorkplaces the list of workplaces from the workshop data
-- @return the number of non-empty strings
function countWorkplaces(workshopWorkplaces)
	
	local count = 0
	
	for _, place in ipairs(workshopWorkplaces) do
		if place ~= "" then
			count = count + 1
		end
	end
	
	return count
end



---
-- Lays out an inner, no-styling table to display construction goods.
-- 
-- @param 
function writeRequiredGoodsRows(requiredGoods)
	
	local matsTable =  mw.html.create("table")
	matsTable:newline()
	
	for _, matsGroup in ipairs(requiredGoods) do
		
		-- Skip empty groups
		if #matsGroup > 0 then
		
			local stackSize = matsGroup[1]
			local materialID = matsGroup[2]
			
			matsTable:tag("tr")
				:tag("td"):wikitext(BOLD .. stackSize .. BOLD):done()
				:tag("td"):wikitext(writeConstructionMatsCellContent(materialID)):done()
			:done():newline()
		end
	end
	
	return matsTable
end



---
-- Formats the information about the construction material with an icon and its
-- display name
--
-- @param materialID the good whose icon and name to show
-- @return formatted string of wiki markup
function writeConstructionMatsCellContent(materialID)
	
	local matName, matIconFilename = RecipeData.getGoodNameAndIcon(materialID)
	
	local iconMarkup = "[[File:" .. matIconFilename .. ".png" .. WIKI_MED_ICON_MARKUP .. matName .. "|link=" .. matName .. "]]"
		local linkMarkup = "[[" .. matName .. "]]"
		
	return iconMarkup .. NBSP .. linkMarkup
end



function toDecimal(value)
	
	return string.format(PATTERN_FORMAT_TWO_DECIMALS, value)
end



return Shopbox