Module:Goodbox: Difference between revisions

From Against the Storm Official Wiki
m (added error check before displaying anything)
m (fixing wrong italics. keeping single quotes)
 
(15 intermediate revisions by the same user not shown)
Line 6: Line 6:
---
---
--- This should be invoked from Template:Goodbox with the parameter of the
--- This should be invoked from Template:Goodbox with the parameter of the
--- good whose infobox should be shown, for example, with {{PAGENAME}}.
--- good whose infobox should be shown. See the template documentation for
--- more information about parameters and errors and to see examples.
---
---
--- @module Goodbox
--- @module Goodbox
Line 13: Line 14:




local Infobox = require("Module:Infobox")
local GoodsData = require("Module:GoodsData")
local GoodsData = require("Module:GoodsData")
local StyleUtils = require("Module:StyleUtils")




Line 19: Line 22:
--region  Private constants
--region  Private constants


local ARG_GOOD_NAME = "name"
local ARGS = {
local ARG_GOOD_PURPOSE = "purpose"
["name"] = "name",
local ARG_GOOD_SPECIES_PREF = "species_preference"
["purpose"] = "purpose",
["species_preference"] = "species_preference",
}


local TITLE_ID = "ID"
--endregion
local TITLE_CATEGORY = "Inventory Category"
local TITLE_EATABLE = "Eatable"
local TITLE_BURNABLE = "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 NBSP = " "


local WIKIMARKUP_MED_ICON = "|32px|alt="
--region Private methods


local ICON_FILENAMES_CATEGORIES = {
---
["Building Materials"] = "Icon_UI_CategoryBuilding.png",
--- Builds using the provided wikiInfobox a few header items.
["Consumable Items"] = "Icon_UI_CategoryConsumable.png",
---
["Crafting Resources"] = "Icon_UI_CategoryCrafting.png",
---@param wikiInfobox table mw.html object into which we're building this
["Food"] = "Icon UI CategoryFood.png",
---@param goodName string the name of the good the infobox is about
["Fuel & Exploration"] = "Icon_UI_CategoryFuel.png",
---@return table the Mediawiki html object into which we've been adding things
["Trade Goods"] = "Icon_UI_CategoryTrade.png"
local function makeHeaderContent(wikiInfobox, goodName)
}


local CSS_INFOBOX_INLINE_STYLE_TABLE = {
-- Grab the data we'll use to populate this.
["float"] = "right",
local goodDescription = GoodsData.getGoodDescription(goodName)
["clear"] = "right",
local goodIconFilename = GoodsData.getGoodIcon(goodName)
["width"] = "256px",
["border"] = "1px solid #a2a9b1",
["border-spacing"] = "2px",
["margin"] = "0.5em 0 0.5em 1em"
}


local CSS_BOTTOM_BORDER_INLINE_STYLE = {
-- Start the header area
["border-bottom"] = "1px solid #a2a9b1"
local header = Infobox.startNewHeader(wikiInfobox)
}


--endregion
Infobox.makeTitle(header, goodName)
Infobox.makeFlavorText(header, goodDescription)
Infobox.makeTitleIcon(header, goodIconFilename)


return wikiInfobox
end




--region Private methods


---
---
Line 74: Line 64:
---@param wikiInfobox table mw.html object into which we're building this
---@param wikiInfobox table mw.html object into which we're building this
---@param goodName string the name of the good the infobox is about
---@param goodName string the name of the good the infobox is about
---@param purpose string the parameter provided to the template
---@param params table of strings, the parameter provided to the template
---@param speciesPref string the parameter provided to the template
---@return table the Mediawiki html object into which we've been adding things
function makeInnerTable(wikiInfobox, goodName, purpose, speciesPref)
local function makeInnerContent(wikiInfobox, goodName, params)


-- Grab the data we'll use to populate this.
-- Grab the data we'll use to populate this.
local goodID = GoodsData.getGoodID(goodName)
local goodCategory = GoodsData.getGoodCategory(goodName)
local goodCategory = GoodsData.getGoodCategory(goodName)
local goodIsEatable = GoodsData.isGoodEatable(goodName)
local goodIsEatable = GoodsData.isGoodEatable(goodName)
Line 85: Line 74:
local goodBurnTime = GoodsData.getGoodBurnTime(goodName)
local goodBurnTime = GoodsData.getGoodBurnTime(goodName)
local goodSellValue, goodBuyValue = GoodsData.getGoodValue(goodName)
local goodSellValue, goodBuyValue = GoodsData.getGoodValue(goodName)
local categoryIcon
local goodID = GoodsData.getGoodID(goodName)


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


-- Start with the things not provided by the data.
-- we'll reuse this to mark where separators are needed in the table
if purpose and purpose ~= "" then
local needsSeparator = false
innerTable:tag("tr")
 
:tag("th"):wikitext(toTitleCase(ARG_GOOD_PURPOSE)):done()
-- Start with the things from the parameters, if any
:tag("td"):wikitext(purpose):done()
for paramTitle, paramValue in pairs(params or {}) do
:done():newline()
if paramTitle ~= nil and paramValue ~= nil then
end
Infobox.makeInnerRow(innerTable, paramValue, false,
if speciesPref and speciesPref ~= "" then
Infobox.toTitleCase(paramTitle), paramValue)
innerTable:tag("tr"):css(CSS_BOTTOM_BORDER_INLINE_STYLE)
-- Require a separator if there were any parameters.
:tag("th"):wikitext(toTitleCase(ARG_GOOD_SPECIES_PREF)):done()
needsSeparator = true
:tag("td"):wikitext(speciesPref):done()
end
:done():newline()
end
end


-- Inventory category (this is the same as the subtitle for now)
needsSeparator = Infobox.makeInnerRow(innerTable, goodCategory, needsSeparator,
if goodCategory then
Infobox.TITLE_CATEGORY,
categoryIcon = "[[File:" .. ICON_FILENAMES_CATEGORIES[goodCategory] .. WIKIMARKUP_MED_ICON .. goodCategory .. "]]"
Infobox.makeCategoryIcon(goodCategory, true) .. StyleUtils.NBSP .. goodCategory)
innerTable:tag("tr"):css(CSS_BOTTOM_BORDER_INLINE_STYLE)
needsSeparator = Infobox.makeInnerRow(innerTable, goodIsEatable, needsSeparator,
:tag("th"):wikitext(TITLE_CATEGORY):done()
Infobox.TITLE_EATABLE, goodIsEatable and "Yes" or "No")
:tag("td"):wikitext(categoryIcon .. NBSP .. goodCategory):done()
needsSeparator = Infobox.makeInnerRow(innerTable, goodIsBurnable, needsSeparator,
:done():newline()
Infobox.TITLE_BURNABLE, goodIsBurnable and "Yes" or "No")
end
needsSeparator = Infobox.makeInnerRow(innerTable, goodIsBurnable and goodBurnTime,
-- Uses
needsSeparator, Infobox.TITLE_BURN_TIME, goodBurnTime)
if goodIsEatable then
 
innerTable:tag("tr")
needsSeparator = true
:tag("th"):wikitext(TITLE_EATABLE):done()
 
:tag("td"):wikitext(goodIsEatable and "Yes" or "No"):done()
needsSeparator = Infobox.makeInnerRow(innerTable, goodSellValue, needsSeparator,
:done():newline()
Infobox.TITLE_SELL_VALUE, Infobox.toTwoDecimalPlaces(goodSellValue) .. StyleUtils.NBSP .. StyleUtils.AMBER())
end
needsSeparator = Infobox.makeInnerRow(innerTable, goodBuyValue, needsSeparator,
if goodIsBurnable then
Infobox.TITLE_BUY_VALUE, Infobox.toTwoDecimalPlaces(goodBuyValue) .. StyleUtils.NBSP .. StyleUtils.AMBER())
innerTable:tag("tr")
 
:tag("th"):wikitext(TITLE_BURNABLE):done()
needsSeparator = true
:tag("td"):wikitext(goodIsBurnable and "Yes" or "No"):done()
 
:done():newline()
needsSeparator = Infobox.makeInnerRow(innerTable, goodID, needsSeparator,
end
Infobox.TITLE_ID, "'" .. goodID .. "'")
if goodIsBurnable and goodBurnTime then
 
innerTable:tag("tr"):css(CSS_BOTTOM_BORDER_INLINE_STYLE)
-- Close the inner table, and return it with the passed context
:tag("th"):wikitext(TITLE_BURN_TIME):done()
Infobox.endInnerTable(wikiInfobox, innerTable)
:tag("td"):wikitext(goodBurnTime):done()
:done():newline()
end
-- Trade values.
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"):css(CSS_BOTTOM_BORDER_INLINE_STYLE)
:tag("th"):wikitext(TITLE_BUY_VALUE):done()
:tag("td"):wikitext(toDecimal(goodBuyValue)):done()
:done():newline()
end
-- End with the ID.
if goodID then
innerTable:tag("tr")
:tag("th"):wikitext(TITLE_ID):done()
:tag("td"):wikitext("\'" .. goodID .. "\'"):done()
:done():newline()
end


-- Close the table.
return wikiInfobox
innerTable:done()
-- Close the table cell and row the inner table is in.
wikiInfobox:done():done():newline()
end
end


Line 166: Line 127:


---
---
--- Creates an html html and wiki markup to display the data in an infobox.
--- Creates an html and wiki markup to display the data in an infobox.
---
---
--- @param frame table from template's calling context
--- @param frame table from template's calling context
--- @return string of html and wiki markup
--- @return string of html and wiki markup
function Goodbox.infobox(frame)
function Goodbox.renderGoodbox(frame)


-- Every good must have a name.
-- Every good must have a name.
local goodName = frame.args[ARG_GOOD_NAME]
local goodName = frame.args[ARGS.name]
if not goodName or goodName == "" then
if not goodName or goodName == "" then
return "You must specify the name of the good. See [[Template:Goodbox]] for examples."
return "You must specify the name of the good. See [[Template:Goodbox]] for examples."
end
end


-- Use this method not to store the data but to check to see whether the
-- Use this method here to check to see whether the provided name is valid.
-- provided name was valid.
if not GoodsData.getGoodID(goodName) then
if not GoodsData.getGoodName(goodName) then
return "Goodbox can't find the specified good: " .. goodName .. "."
return "Infobox can't find the specified good: " .. goodName .. "."
end
end


-- Additional template parameters, may or may not be present
-- Additional template parameters, may or may not be present.
local purpose = frame.args[ARG_GOOD_PURPOSE]
local purpose = frame.args[ARGS.purpose]
local speciesPref = frame.args[ARG_GOOD_SPECIES_PREF]
local speciesPref = frame.args[ARGS.species_preference]


-- Get the data.
local wikiInfobox = Infobox.startNewInfobox()
local goodDescription = GoodsData.getGoodDescription(goodName)
makeHeaderContent(wikiInfobox, goodName)
local goodCategory = GoodsData.getGoodCategory(goodName)
makeInnerContent(wikiInfobox, goodName,
local goodIconFilename = GoodsData.getGoodIcon(goodName)
{ [ARGS.purpose] = purpose, [ARGS.species_preference] = speciesPref })
 
-- Make the top of the infobox that every item has.
wikiInfobox = mw.html.create("table"):css(CSS_INFOBOX_INLINE_STYLE_TABLE)
-- with a title
wikiInfobox:tag("tr")
:tag("td"):wikitext(goodName):done()
:done():newline()
-- and a subtitle, showing the category
if goodCategory then
wikiInfobox:tag("tr")
:tag("td"):wikitext(goodCategory):done()
:done():newline()
end
-- and a large icon.
if goodIconFilename then
wikiInfobox:tag("tr")
:tag("td"):wikitext("[[File:" .. goodIconFilename .. "]]"):done()
:done():newline()
wikiInfobox:tag("tr"):css(CSS_BOTTOM_BORDER_INLINE_STYLE)
:tag("td"):wikitext(goodName .. ", as seen in-game"):done()
:done():newline()
end
 
makeInnerTable(wikiInfobox, goodName, purpose, speciesPref)
 
-- Finish with the flavor text.
if goodDescription then
wikiInfobox:tag("tr")
:tag("td"):wikitext(goodDescription):done()
:done():newline()
end


return wikiInfobox
return wikiInfobox
end
end


 
--endregion
 
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
return Goodbox

Latest revision as of 18:19, 24 December 2023

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

---
--- Module to create an infobox for displaying on a good's wiki page.
---
--- Shows the facts from the data about the specified good in an easy-to-read
--- table, with a large icon, information, categories, and the flavor text.
---
--- This should be invoked from Template:Goodbox with the parameter of the
--- good whose infobox should be shown. See the template documentation for
--- more information about parameters and errors and to see examples.
---
--- @module Goodbox
local Goodbox = {}



local Infobox = require("Module:Infobox")
local GoodsData = require("Module:GoodsData")
local StyleUtils = require("Module:StyleUtils")



--region  Private constants

local ARGS = {
	["name"] = "name",
	["purpose"] = "purpose",
	["species_preference"] = "species_preference",
}

--endregion



--region Private methods

---
--- Builds using the provided wikiInfobox a few header items.
---
---@param wikiInfobox table mw.html object into which we're building this
---@param goodName 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 makeHeaderContent(wikiInfobox, goodName)

	-- Grab the data we'll use to populate this.
	local goodDescription = GoodsData.getGoodDescription(goodName)
	local goodIconFilename = GoodsData.getGoodIcon(goodName)

	-- Start the header area
	local header = Infobox.startNewHeader(wikiInfobox)

	Infobox.makeTitle(header, goodName)
	Infobox.makeFlavorText(header, goodDescription)
	Infobox.makeTitleIcon(header, goodIconFilename)

	return wikiInfobox
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 goodName string the name of the good the infobox is about
---@param params table of strings, the parameter provided to the template
---@return table the Mediawiki html object into which we've been adding things
 local function makeInnerContent(wikiInfobox, goodName, params)

	-- Grab the data we'll use to populate this.
	local goodCategory = GoodsData.getGoodCategory(goodName)
	local goodIsEatable = GoodsData.isGoodEatable(goodName)
	local goodIsBurnable = GoodsData.isGoodBurnable(goodName)
	local goodBurnTime = GoodsData.getGoodBurnTime(goodName)
	local goodSellValue, goodBuyValue = GoodsData.getGoodValue(goodName)
	local goodID = GoodsData.getGoodID(goodName)

	-- Start the inner table
	local innerTable = Infobox.startNewInnerTable(wikiInfobox)

	-- we'll reuse this to mark where separators are needed in the table
	local needsSeparator = false

	-- Start with the things from the parameters, if any
	for paramTitle, paramValue in pairs(params or {}) do
		if paramTitle ~= nil and paramValue ~= nil then
			Infobox.makeInnerRow(innerTable, paramValue, false,
					Infobox.toTitleCase(paramTitle), paramValue)
			-- Require a separator if there were any parameters.
			needsSeparator = true
		end
	end

	needsSeparator = Infobox.makeInnerRow(innerTable, goodCategory, needsSeparator,
			Infobox.TITLE_CATEGORY,
			Infobox.makeCategoryIcon(goodCategory, true) .. StyleUtils.NBSP .. goodCategory)
	needsSeparator = Infobox.makeInnerRow(innerTable, goodIsEatable, needsSeparator,
			Infobox.TITLE_EATABLE, goodIsEatable and "Yes" or "No")
	needsSeparator = Infobox.makeInnerRow(innerTable, goodIsBurnable, needsSeparator,
			Infobox.TITLE_BURNABLE, goodIsBurnable and "Yes" or "No")
	needsSeparator = Infobox.makeInnerRow(innerTable, goodIsBurnable and goodBurnTime,
			needsSeparator, Infobox.TITLE_BURN_TIME, goodBurnTime)

	needsSeparator = true

	needsSeparator = Infobox.makeInnerRow(innerTable, goodSellValue, needsSeparator,
			Infobox.TITLE_SELL_VALUE, Infobox.toTwoDecimalPlaces(goodSellValue) .. StyleUtils.NBSP .. StyleUtils.AMBER())
	needsSeparator = Infobox.makeInnerRow(innerTable, goodBuyValue, needsSeparator,
			Infobox.TITLE_BUY_VALUE, Infobox.toTwoDecimalPlaces(goodBuyValue) .. StyleUtils.NBSP .. StyleUtils.AMBER())

	needsSeparator = true

	needsSeparator = Infobox.makeInnerRow(innerTable, goodID, needsSeparator,
			Infobox.TITLE_ID, "'" .. goodID .. "'")

	-- Close the inner table, and return it with the passed context
	Infobox.endInnerTable(wikiInfobox, innerTable)

	return wikiInfobox
end

--endregion



--region Public methods

---
--- Creates an html and wiki markup to display the data in an infobox.
---
--- @param frame table from template's calling context
--- @return string of html and wiki markup
function Goodbox.renderGoodbox(frame)

	-- Every good must have a name.
	local goodName = frame.args[ARGS.name]
	if not goodName or goodName == "" then
		return "You must specify the name of the good. See [[Template:Goodbox]] for examples."
	end

	-- Use this method here to check to see whether the provided name is valid.
	if not GoodsData.getGoodID(goodName) then
		return "Goodbox can't find the specified good: " .. goodName .. "."
	end

	-- Additional template parameters, may or may not be present.
	local purpose = frame.args[ARGS.purpose]
	local speciesPref = frame.args[ARGS.species_preference]

	local wikiInfobox = Infobox.startNewInfobox()
	makeHeaderContent(wikiInfobox, goodName)
	makeInnerContent(wikiInfobox, goodName,
			{ [ARGS.purpose] = purpose, [ARGS.species_preference] = speciesPref })

	return wikiInfobox
end

--endregion

return Goodbox