Module:Buildings table: Difference between revisions
From Beyond These Stars Official Wiki
changed column order in table; added fallback to vector icon when portrait icon doesn't exist |
m now uses the parent args, not the template invoke's args |
||
| (One intermediate revision by the same user not shown) | |||
| Line 2: | Line 2: | ||
Test in Scribunto console with: | Test in Scribunto console with: | ||
=p.render() | =p.render() | ||
=p.render( { args = { Category = "Construction" } } ) | |||
]]-- | ]]-- | ||
local p = {} | local p = {} | ||
| Line 12: | Line 13: | ||
--#region html | --#region MARK: html builders | ||
---@diagnostic disable-next-line: duplicate-doc-alias | ---@diagnostic disable-next-line: duplicate-doc-alias | ||
| Line 73: | Line 74: | ||
local file_name = resolve_icon_file_name(building) | local file_name = resolve_icon_file_name(building) | ||
if not file_name then return "" end | if not file_name then return "" end | ||
local icon_size = | local icon_size = LARGE_ICON_SIZE -- width instead of typical height because vectors and portraits are different and comingled | ||
local name = building.display_name | local name = building.display_name | ||
local link_attr = "link=" .. building.display_name | local link_attr = "link=" .. building.display_name | ||
| Line 168: | Line 169: | ||
local function render_tech_prerequisite(building) | local function render_tech_prerequisite(building) | ||
if not building.tech_tree_previous or building.tech_tree_previous == "" then return "" end | if not building.tech_tree_previous or building.tech_tree_previous == "" then return "" end | ||
local prerequisite_name = Building_Data_Module. | local prerequisite_name = Building_Data_Module.get_name_by_id(building.tech_tree_previous) | ||
if not prerequisite_name then return "" end | if not prerequisite_name then return "" end | ||
return "[[" .. prerequisite_name .. "]]" | return "[[" .. prerequisite_name .. "]]" | ||
| Line 216: | Line 217: | ||
--- `#invoke` entry point. | --- `#invoke` entry point. Checks for an optional argument to filter the query. | ||
---@param frame table Scribunto frame from `#invoke`. | ---@param frame table Scribunto frame from `#invoke`. | ||
---@return string wikitext table wikitext code | ---@return string wikitext table wikitext code | ||
function p.render(frame) | function p.render(frame) | ||
local buildings = Building_Data_Module.get_all_buildings() | local args = frame:getParent().args | ||
---@type string|nil | |||
local maybe_category = args[Building_Data_Module.FILTERS.CATEGORY] or args[string.lower(Building_Data_Module.FILTERS.CATEGORY)] | |||
local buildings | |||
if maybe_category and maybe_category ~= "" then | |||
buildings = Building_Data_Module.get_buildings_by_category(maybe_category) | |||
else | |||
buildings = Building_Data_Module.get_all_buildings() | |||
end | |||
if #buildings == 0 then return "" end | if #buildings == 0 then return "" end | ||
local wikitext = build_table(buildings) | local wikitext = build_table(buildings) | ||
Latest revision as of 01:55, 30 September 2026
Documentation for this module may be created at Module:Buildings table/doc
--[[
Test in Scribunto console with:
=p.render()
=p.render( { args = { Category = "Construction" } } )
]]--
local p = {}
local Building_Data_Module = require("Module:Building_data")
local Resource_Data_Module = require("Module:Resource_data")
--#region MARK: html builders
---@diagnostic disable-next-line: duplicate-doc-alias
---@alias HtmlNode table
local TOP_LEVEL_CLASS = "bts-table-buildings"
local TABLE_CLASS = "wikitable sortable"
local UNSORTABLE_CLASS = "unsortable"
local RESOURCE_LIST_CLASS = "bts-resource-list"
local RESOURCE_ICON_CLASS = "bts-resource-icon"
local LARGE_ICON_SIZE = "96px"
local SMALL_ICON_SIZE = "32px"
local TEXT_IS_POWERED = "Yes [[File:Resource_Power.png|32px|Power]]"
local TEXT_IS_NOT_POWERED = "No"
--- Adds the header row to the provided html node.
---@param wikitable HtmlNode wikitable
---@param buildings Building[]
local function add_header_row(wikitable, buildings)
local header = wikitable:tag("tr")
header:tag("th"):addClass(UNSORTABLE_CLASS):wikitext("Icon")
header:tag("th"):wikitext("Name")
header:tag("th"):wikitext("Category")
header:tag("th"):wikitext("Workers")
header:tag("th"):wikitext("Production")
header:tag("th"):wikitext("Req. Power?")
header:tag("th"):addClass(UNSORTABLE_CLASS):wikitext("Construction Costs")
header:tag("th"):wikitext("Tech Prerequisite")
end
--- Resolves a file name for the icon for the building.
---@param building Building
---@return string|nil file_name
local function resolve_icon_file_name(building)
if building and building.portrait_icon then
local portrait_file_name = "File:" .. building.portrait_icon .. ".png"
return portrait_file_name
end
if building and building.icon then
local vector_file_name = "File:" .. building.icon .. ".png"
return vector_file_name
end
return nil
end
--- Renders markup for an icon for the building.
---@param building Building
---@return string wikitext
local function render_icon(building)
if not building or not building.icon then return "" end
local file_name = resolve_icon_file_name(building)
if not file_name then return "" end
local icon_size = LARGE_ICON_SIZE -- width instead of typical height because vectors and portraits are different and comingled
local name = building.display_name
local link_attr = "link=" .. building.display_name
return "[[" .. file_name .. "|" .. icon_size .. "|" .. name .. "|" .. link_attr .. "]]"
end
--- Adds an icon for a resource to the provided html table row.
---@param tr HtmlNode tr
---@param resource ResourceRecord
local function add_resource_icon(tr, resource)
local icon_markup = ""
if resource and resource.icon then
local file_name = "File:" .. resource.icon .. ".png"
local icon_size = "x" .. SMALL_ICON_SIZE
local name = resource.display_name
local link_attr = "link=" .. resource.display_name
icon_markup = "[[" .. file_name .. "|" .. icon_size .. "|" .. name .. "|" .. link_attr .. "]]"
end
tr:tag("td"):tag("span"):addClass(RESOURCE_ICON_CLASS):wikitext(icon_markup)
end
--- Adds a link for a resource to the provided html table row.
---@param tr HtmlNode tr
---@param resource ResourceRecord
local function add_resource_link(tr, resource)
local link_markup = ""
if resource and resource.display_name then
link_markup = "[[" .. resource.display_name .. "]]"
end
tr:tag("td"):wikitext(link_markup)
end
--- Builds an inner list of produced resources.
---@param building Building
---@return HtmlNode node
local function build_produced_resources(building)
local tbl = mw.html.create("table"):addClass(RESOURCE_LIST_CLASS)
if not building or not building.tasks or #building.tasks == 0 then return tbl end
for _, task in ipairs(building.tasks) do
for _, output_io in ipairs(task.outputs) do
local resource = Resource_Data_Module.get_resource(output_io.resource)
local tr = tbl:tag("tr")
add_resource_icon(tr, resource)
add_resource_link(tr, resource)
end
end
return tbl
end
--- Renders a statement about whether the given building requires power.
---@param building Building
---@return string wikitext
local function render_powered(building)
if not building or not building.tasks or #building.tasks == 0 then return TEXT_IS_NOT_POWERED end
for _, task in ipairs(building.tasks) do
for _, input_io in ipairs(task.inputs) do
if input_io.resource == Resource_Data_Module.POWER_RESOURCE_NAME then
return TEXT_IS_POWERED
end
end
end
return TEXT_IS_NOT_POWERED
end
--- Builds an inner list of construction resources.
---@param building Building
---@return HtmlNode node
local function build_construction_resources(building)
local tbl = mw.html.create("table"):addClass(RESOURCE_LIST_CLASS)
if not building.construction_resources or building.construction_resources == {} then return tbl end
for _, pair in ipairs(building.construction_resources) do
local tr = tbl:tag("tr")
tr:tag("td"):wikitext(pair.amount)
local resource_record = Resource_Data_Module.get_resource(pair.name)
add_resource_icon(tr, resource_record)
add_resource_link(tr, resource_record)
end
return tbl
end
--- Renders a link to the prerequisite building in the tech tree for the given building.
---@param building Building
---@return string wikitext
local function render_tech_prerequisite(building)
if not building.tech_tree_previous or building.tech_tree_previous == "" then return "" end
local prerequisite_name = Building_Data_Module.get_name_by_id(building.tech_tree_previous)
if not prerequisite_name then return "" end
return "[[" .. prerequisite_name .. "]]"
end
--- Adds a row to the provided html node.
---@param building Building
---@return HtmlNode row
local function build_row(building)
local row = mw.html.create("tr")
row:tag("td"):wikitext(render_icon(building))
row:tag("td"):wikitext("[[" .. building.display_name .. "]]")
if building.category and building.category ~= "" then
row:tag("td"):wikitext("[[:Category:" .. building.category .. " Buildings" .. "|" .. building.category .. "]]")
else
row:tag("td"):wikitext("")
end
row:tag("td"):wikitext(building.max_peeps or "")
row:tag("td"):node(build_produced_resources(building))
row:tag("td"):wikitext(render_powered(building))
row:tag("td"):node(build_construction_resources(building))
row:tag("td"):wikitext(render_tech_prerequisite(building))
return row
end
--- Builds a table of buildings.
---@param buildings Building[]
---@return string wikitext
local function build_table(buildings)
---@type HtmlNode
local div = mw.html.create("div")
div:addClass(TOP_LEVEL_CLASS)
local wikitable = div:tag("table"):addClass(TABLE_CLASS)
add_header_row(wikitable, buildings)
for _, building in ipairs(buildings) do
wikitable:node(build_row(building))
end
return tostring(div)
end
--#endregion
--- `#invoke` entry point. Checks for an optional argument to filter the query.
---@param frame table Scribunto frame from `#invoke`.
---@return string wikitext table wikitext code
function p.render(frame)
local args = frame:getParent().args
---@type string|nil
local maybe_category = args[Building_Data_Module.FILTERS.CATEGORY] or args[string.lower(Building_Data_Module.FILTERS.CATEGORY)]
local buildings
if maybe_category and maybe_category ~= "" then
buildings = Building_Data_Module.get_buildings_by_category(maybe_category)
else
buildings = Building_Data_Module.get_all_buildings()
end
if #buildings == 0 then return "" end
local wikitext = build_table(buildings)
return wikitext
end
return p


