Module:Buildings table

From Beyond These Stars Official Wiki
Revision as of 02:58, 24 September 2026 by Aeredor (talk | contribs) (Created to serve a complete building table or individual rows)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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

--[[
Test in Scribunto console with:
=p.render()
]]--
local p = {}



local Building_Data_Module = require("Module:Building_data")
local Resource_Data_Module = require("Module:Resource_data")



--#region html building helper functions

---@diagnostic disable-next-line: duplicate-doc-alias
---@alias HtmlNode table

local TABLE_CLASS = "bts-table-buildings"

local RESOURCE_LIST_CLASS = "bts-resource-list"
local RESOURCE_ICON_CLASS = "bts-resource-icon"

local SMALL_ICON_SIZE = "32px"

local TEXT_IS_POWERED = "Yes"
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"):wikitext("Name")
  header:tag("th"):wikitext("Category")
  header:tag("th"):wikitext("Construction Resources")
  header:tag("th"):wikitext("Tech Prerequisite")
  header:tag("th"):wikitext("Workers")
  header:tag("th"):wikitext("Production")
  header:tag("th"):wikitext("Powered?")
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 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_building_by_id(building.tech_tree_previous)
  if not prerequisite_name then return "" end
  return "[[" .. prerequisite_name .. "]]"
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



--- 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("[[" .. building.display_name .. "]]")
  row:tag("td"):wikitext("[[Category:" .. building.category .. " Buildings" .. "|" .. building.category .. "]]")
  row:tag("td"):node(build_construction_resources(building))
  row:tag("td"):wikitext(render_tech_prerequisite(building))
  row:tag("td"):wikitext(building.max_peeps)
  row:tag("td"):node(build_produced_resources(building))
  row:tag("td"):wikitext(render_powered(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(TABLE_CLASS)
  local wikitable = div:tag("table"):addClass(TABLE_CLASS .. "-table")
  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 for just one table row, assumes a surrounding table
---@param frame table Scribunto frame from `#invoke`.
---@return string wikitext table row wikitext code
function p.render_row(frame)
  local args = frame.args or {}
  local building_name = args[1] or args.page_name or mw.title.getCurrentTitle().fullText
  local building = Building_Data_Module.get_building(building_name)
  if not building then return "" end
  local row = build_row(building)
  return tostring(row)
end



--- `#invoke` entry point.
---@param frame table Scribunto frame from `#invoke`.
---@return string wikitext table wikitext code
function p.render(frame)
  local buildings = Building_Data_Module.get_all_buildings()
  if #buildings == 0 then return "" end
  local wikitext = build_table(buildings)
  return wikitext
end



return p