Module:Goodbox: Difference between revisions

From Against the Storm Official Wiki
(Was displaying blank purpose and species preference when they were not provided)
(adding food icon to inventory category for recognition)
Line 43: Line 43:


local BR = "<br />"
local BR = "<br />"
local NBSP = "&nbsp;"


local CSS_INFOBOX_INLINE_STYLE_TABLE = {  
local CSS_INFOBOX_INLINE_STYLE_TABLE = {  
Line 51: Line 52:
["border-spacing"] = "2px"
["border-spacing"] = "2px"
}
}
local categoryIcons = {
["Food"] = "Icon UI CategoryFood.png"
}


---
---
Line 131: Line 138:
-- Data provided by the CSV
-- Data provided by the CSV
if goodCategory then
if goodCategory then
local catIcon = "[[File:" .. categoryIcons[goodCategory] .. "|32px]]"
innerTable:tag("tr"):tag("th"):wikitext(TITLE_CATEGORY):done()
innerTable:tag("tr"):tag("th"):wikitext(TITLE_CATEGORY):done()
:tag("td"):wikitext(goodCategory):done():done():newline()
:tag("td"):wikitext(catIcon .. NBSP .. goodCategory):done():done():newline()
end
end
-- Eatable is superfluous when the category is food.
-- Eatable is superfluous when the category is food.

Revision as of 16:34, 10 November 2023

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

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

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

---
-- Constants
---
local ARG_GOOD_NAME = "name"
local ARG_GOOD_PURPOSE = "purpose"
local ARG_GOOD_SPECIES_PREF = "species_preference"

local INDEX_GOOD_ID = 1
local INDEX_GOOD_NAME = 2
local INDEX_GOOD_DESCRIPTION = 3
local INDEX_GOOD_CATEGORY = 4
local INDEX_GOOD_EATABLE = 5
local INDEX_GOOD_CAN_BE_BURNED = 6
local INDEX_GOOD_BURNING_TIME = 7
local INDEX_GOOD_TRADING_SELL_VALUE = 8
local INDEX_GOOD_TRADING_BUY_VALUE = 9
local INDEX_GOOD_ICON_FILENAME = 10

local TITLE_ID = "ID"
local TITLE_CATEGORY = "Inventory Category"
local TITLE_TYPE = "ID Type"
local TITLE_EATABLE = "Is eatable?"
local TITLE_BURNABLE = "Is burnable?"
local TITLE_BURN_TIME = "Fuel burn time"
local TITLE_SELL_VALUE = "Value when sold"
local TITLE_BUY_VALUE = "Price when bought"

local PATTERN_CAPTURE_BEGINNING_WITHIN_BRACKETS = "^%[(.-)%]"
local PATTERN_CAPTURE_BEGINNING_AFTER_UNDERSCORE = "^_(.-)%s"
local PATTERN_CAPTURE_FIRST_WORD = "^(%w-)%s"
local PATTERN_FORMAT_TWO_DECIMALS = "%1.2f"

local BR = "<br />"
local NBSP = "&nbsp;"

local CSS_INFOBOX_INLINE_STYLE_TABLE = { 
	["float"] = "right", 
	["clear"] = "right", 
	["width"] = "256px", 
	["border"] = "1px solid #a2a9b1", 
	["border-spacing"] = "2px"
}

local categoryIcons = {
	["Food"] = "Icon UI CategoryFood.png"
}



---
-- Member variable: Good
-- 
-- 
local good



---
-- 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 Goodbox.infobox(frame)
	
	-- Every good must have a name.
	local name = frame.args[ARG_GOOD_NAME]
	
	if not name or name == "" then
		error("You must specify the name of the good in the Goodbox template.")
	end
	
	-- Every Good should have a purpose.
	local purpose = frame.args[ARG_GOOD_PURPOSE]
	-- Specific parameters, may or may not be present.
	local speciesPref = frame.args[ARG_GOOD_SPECIES_PREF]
	
	-- Retrieve the actual data for the good.
	good = GoodsData.getAllDataForGood(name)
	
	if not good then
		return "No good found for infobox."
	end
	
	local goodID = good[INDEX_GOOD_ID]
	local goodName = good[INDEX_GOOD_NAME]
	local goodDescription = good[INDEX_GOOD_DESCRIPTION]
	local goodCategory = good[INDEX_GOOD_CATEGORY]
	local goodIsEatable = good[INDEX_GOOD_EATABLE]
	local goodIsBurnable = good[INDEX_GOOD_CAN_BE_BURNED]
	local goodBurnTime = good[INDEX_GOOD_BURNING_TIME]
	local goodSellValue = good[INDEX_GOOD_TRADING_SELL_VALUE]
	local goodBuyValue = good[INDEX_GOOD_TRADING_BUY_VALUE]
	local goodIconFilename = good[INDEX_GOOD_ICON_FILENAME]
	
	local goodType = extractType(goodID)
	
	-- Make the top of the infobox that every item has.
	wikiInfobox = mw.html.create("table"):css( CSS_INFOBOX_INLINE_STYLE_TABLE )
	
	-- Title of infobox.
	if name then
		wikiInfobox:tag("tr"):tag("td"):wikitext(name):done():done():newline()
	end
	-- Subtitle for category.
	if goodCategory then
		wikiInfobox:tag("tr"):tag("td"):wikitext(goodCategory):done():done():newline()
	end
	-- Large icon of infobox.
	if goodIconFilename then
		wikiInfobox:tag("tr"):tag("td"):wikitext("[[File:" .. goodIconFilename .. ".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()
	
	if purpose and purpose ~= "" then
		innerTable:tag("tr"):tag("th"):wikitext(toTitleCase(ARG_GOOD_PURPOSE)):done()
			:tag("td"):wikitext(purpose):done():done():newline()
	end
	if speciesPref and speciesPref ~= "" then
		innerTable:tag("tr"):tag("th"):wikitext(toTitleCase(ARG_GOOD_SPECIES_PREF)):done()
			:tag("td"):wikitext(speciesPref):done():done():newline()
	end
	
	-- Data provided by the CSV
	if goodCategory then
		local catIcon = "[[File:" .. categoryIcons[goodCategory] .. "|32px]]"
		innerTable:tag("tr"):tag("th"):wikitext(TITLE_CATEGORY):done()
			:tag("td"):wikitext(catIcon .. NBSP .. goodCategory):done():done():newline()
	end
	-- Eatable is superfluous when the category is food.
	--if goodIsEatable then
	--	innerTable:tag("tr"):tag("th"):wikitext(TITLE_EATABLE):done()
	--		:tag("td"):wikitext(goodIsEatable):done():done():newline()
	--end
	-- Burnable is superfluous but we can use it to determine whether to show
	-- how long the fuel burns.
	-- if goodIsBurnable then
		-- innerTable:tag("tr"):tag("th"):wikitext(TITLE_BURNABLE):done()
			-- :tag("td"):wikitext(goodIsBurnable):done():done():newline()
	-- end
	if goodIsBurnable == "True" and goodBurnTime then
		innerTable:tag("tr"):tag("th"):wikitext(TITLE_BURN_TIME):done()
			:tag("td"):wikitext(goodBurnTime):done():done():newline()
	end
	if goodSellValue then
		innerTable:tag("tr"):tag("th"):wikitext(TITLE_SELL_VALUE):done()
			:tag("td"):wikitext(toDecimal(goodSellValue)):done():done():newline()
	end
	if goodBuyValue then
		innerTable:tag("tr"):tag("th"):wikitext(TITLE_BUY_VALUE):done()
			:tag("td"):wikitext(toDecimal(goodBuyValue)):done():done():newline()
	end
	if goodID then
		innerTable:tag("tr"):tag("th"):wikitext(TITLE_ID):done()
			:tag("td"):wikitext("\"" .. goodID .. "\""):done():done():newline()
	end
	
	innerTable:done()
	wikiInfobox:done():done():newline()
	
	if goodDescription then
		wikiInfobox:tag("tr"):tag("td"):wikitext(goodDescription):done():done():newline()
	end
	
	return wikiInfobox
end



---
-- Extracts the beginning of the ID into the type of good. For example, when 
-- ID = [Vessel] Pottery, the type is Vessel.
--
-- @param goodID the ID of the good from the data
-- @return the type of good
function extractType(goodID)
	
	local typecode = goodID:match(PATTERN_CAPTURE_BEGINNING_WITHIN_BRACKETS)
	
	if not typecode then
		typecode = goodID:match(PATTERN_CAPTURE_BEGINNING_AFTER_UNDERSCORE)
	end
	
	if not typecode then
		typecode = goodID:match(PATTERN_CAPTURE_FIRST_WORD)
	end
	
	return typecode
end



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



---
-- Capitalizes the first character of each word.
--
-- @param title the title to capitalize
-- @return the title once capitalized
function toTitleCase(title)
	
	local newTitle = title:gsub("(%a)([%w_']*)", function(first, rest)
			return first:upper() .. rest:lower()
		end)
	
	newTitle, _ = newTitle:gsub("_", " ")
	
	return newTitle
end



return Goodbox