Module:Buildingbox2: Difference between revisions
From Against the Storm Official Wiki
(WIP rendering specializations now just outputs one string. also comma separated for readability) |
(Updated to work with building interface, support for service buildings, farms, camps, and collectors) |
||
Line 9: | Line 9: | ||
--region Dependencies | --region Dependencies | ||
--Some dependencies in this module are loaded lazily | --Some dependencies in this module are loaded lazily, but we want them scoped to the entire module, not their local functions | ||
local WorkshopsData | |||
local | local InstitutionsData | ||
local FarmsData | |||
local CampsData | |||
local CollectorsData | |||
local ViewTemplate = "Template:Infobox" | local ViewTemplate = "Template:Infobox" | ||
Line 21: | Line 24: | ||
--region Private constants | --region Private constants | ||
local | local ARG_NAME = "name" | ||
local PARAM_TITLE = "title" | local PARAM_TITLE = "title" | ||
Line 27: | Line 30: | ||
local PARAM_DESCRIPTION = "description" | local PARAM_DESCRIPTION = "description" | ||
local PARAM_SPECIALIZATION = "specialization" | local PARAM_SPECIALIZATION = "specialization" | ||
local PARAM_ICON_FILENAME = "iconfilename" | |||
local PARAM_MOVABLE = "movable" | |||
local PARAM_WORKPLACES = "workplaces" | |||
local PARAM_STORAGE = "storage" | |||
local PARAM_RECIPES = "recipes" | |||
local PARAM_CONSTRUCTION_COST = "construction" | |||
local PARAM_CITY_SCORE = "cityscore" | |||
local PARAM_CONSTRUCTION_TIME = "constructiontime" | |||
local PARAM_CONSTRUCTION_SIZE = "constructionsize" | |||
local PARAM_ID = "id" | |||
--endregion | --endregion | ||
Line 34: | Line 47: | ||
--region Private methods | --region Private methods | ||
---renderSpecializations takes the ID of a building and looks up its specializations, calls external view templates to convert those specializations into usable content strings for display, and returns those strings | ---renderSpecializations takes the ID of a building and looks up its specializations, calls external view templates to convert those specializations into usable content strings for display, and returns those strings concatenated together for display by the calling scope. | ||
---@param id string the unique ID of the building | ---@param id string the unique ID of the building | ||
---@return | ---@return string a content string ready for display | ||
function | local function renderSpecializations(id) | ||
local SpecializationsData = mw.loadData("Module:SpecializationsData") | local SpecializationsData = mw.loadData("Module:SpecializationsData") | ||
Line 50: | Line 63: | ||
local concatenatedStrings = "" | local concatenatedStrings = "" | ||
for | for _, specIndex in ipairs(listOfSpecializationsAtBuilding) do | ||
-- Specialization link first | |||
local specData = SpecializationsData.specializations[specIndex] | local specData = SpecializationsData.specializations[specIndex] | ||
local specializationString = frame:expandTemplate{ | local specializationString = frame:expandTemplate{ | ||
title = "Specialization", | title = "Specialization", | ||
Line 63: | Line 76: | ||
}, } | }, } | ||
-- Species link second, but just the icon | |||
local species = specData[SpecializationsData.SPECIES] | local species = specData[SpecializationsData.SPECIES] | ||
local speciesString = frame:expandTemplate{ | local speciesString = frame:expandTemplate{ | ||
title = "Species", | title = "Species", | ||
Line 74: | Line 87: | ||
}, } | }, } | ||
-- Separate entries with | -- Separate multiple entries with line break | ||
if #concatenatedStrings > 1 then | if #concatenatedStrings > 1 then | ||
concatenatedStrings = concatenatedStrings .. "<br />" | concatenatedStrings = concatenatedStrings .. "<br />" | ||
Line 91: | Line 104: | ||
function | -- Building interface: | ||
-- getCategory | |||
-- getCityScore | |||
-- getConstructionCosts (as [goodName] = stack size) | |||
-- getConstructionTime | |||
-- getDescription | |||
-- getIcon | |||
-- isMovable | |||
-- getName | |||
-- getNumberOfWorkplaces | |||
-- getSize (as "X x Y") | |||
-- getStorage | |||
local function buildViewParameters(id, buildingInterface, subtitlePrefix) | |||
local frame = mw.getCurrentFrame() | |||
local viewParameters = {} | |||
viewParameters[PARAM_TITLE] = buildingInterface.getName(id) | |||
viewParameters[PARAM_SUBTITLE] = subtitlePrefix .. " (" .. buildingInterface.getCategory(id) .. ")" | |||
viewParameters[PARAM_DESCRIPTION] = buildingInterface.getDescription(id) | |||
viewParameters[PARAM_SPECIALIZATION] = renderSpecializations(id) | |||
viewParameters[PARAM_ICON_FILENAME] = buildingInterface.getIcon(id) | |||
viewParameters[PARAM_MOVABLE] = buildingInterface.isMovable(id) and "true" | |||
viewParameters[PARAM_WORKPLACES] = buildingInterface.getNumberOfWorkplaces(id) | |||
viewParameters[PARAM_RECIPES] = frame:expandTemplate{ title = "Recipe", args = { ["building"] = buildingInterface.getName(id), ["display"] = "list", }, } | |||
viewParameters[PARAM_STORAGE] = buildingInterface.getStorage(id) | |||
viewParameters[PARAM_CONSTRUCTION_COST] = frame:expandTemplate{ title = "Construction", args = buildingInterface.getConstructionCosts(id) } | |||
viewParameters[PARAM_CITY_SCORE] = buildingInterface.getCityScore(id) | |||
viewParameters[PARAM_CONSTRUCTION_TIME] = buildingInterface.getConstructionTime(id) | |||
viewParameters[PARAM_CONSTRUCTION_SIZE] = buildingInterface.getSize(id) | |||
viewParameters[PARAM_ID] = id | |||
return viewParameters | |||
end | |||
local function tryWorkshopsData(name) | |||
WorkshopsData = require("Module:WorkshopsData") | |||
local | local id = WorkshopsData.getWorkshopID(name) | ||
if not | if not id then | ||
return false | |||
else | |||
return buildViewParameters(id, WorkshopsData, "Production Building") | |||
end | |||
end | |||
local function tryInstitutionsData(name) | |||
InstitutionsData = require("Module:InstitutionsData") | |||
local id = InstitutionsData.getInstitutionID(name) | |||
if not id then | |||
return false | return false | ||
else | |||
return buildViewParameters(id, InstitutionsData, "Service Building") | |||
end | end | ||
end | |||
local function tryFarmsData(name) | |||
FarmsData = require("Module:FarmsData") | |||
local id = FarmsData.getFarmID(name) | |||
if not id then | |||
return false | |||
else | |||
return buildViewParameters(id, FarmsData, "Farm") | |||
end | |||
end | |||
local function tryCampsData(name) | |||
CampsData = require("Module:CampsData") | |||
return | local id = CampsData.getCampID(name) | ||
if not id then | |||
return false | |||
else | |||
return buildViewParameters(id, CampsData, "Gathering Camp") | |||
end | |||
end | end | ||
local function tryCollectorsData(name) | |||
CollectorsData = require("Module:CollectorsData") | |||
local id = CollectorsData.getCollectorID(name) | |||
if not id then | |||
return false | |||
else | |||
return buildViewParameters(id, CollectorsData, "Extraction Building") | |||
end | |||
end | |||
--- For calling from another template, like Infobox. Handles data only, does not interface with the Buildingbox view. | --- For calling from another template, like Infobox. Handles data only, does not interface with the Buildingbox view. | ||
---@param | ---@param name string the name of the building about which to retrieve data | ||
---@return table the essential data about the building extracted | ---@return table the essential data about the building extracted | ||
function | local function findBoxType(name) | ||
-- Lazy-load of external data, since it's expensive. Start with the most likely so that most pages load as fast as possible. | -- Lazy-load of external data, since it's expensive. Start with the most likely so that most pages load as fast as possible. | ||
local viewParameters = tryWorkshopsData( | local viewParameters = tryWorkshopsData(name) | ||
if not viewParameters then | if not viewParameters then | ||
viewParameters = tryInstitutionsData( | viewParameters = tryInstitutionsData(name) | ||
if not viewParameters then | if not viewParameters then | ||
viewParameters = tryFarmsData( | viewParameters = tryFarmsData(name) | ||
if not viewParameters then | if not viewParameters then | ||
viewParameters = tryCollectorsData( | viewParameters = tryCollectorsData(name) | ||
if not viewParameters then | if not viewParameters then | ||
viewParameters = tryCampsData( | viewParameters = tryCampsData(name) | ||
if not viewParameters then | if not viewParameters then | ||
return("No building found with | return("No building found with name: " .. name .. ".") | ||
end | end | ||
end | end | ||
end | end | ||
end | end | ||
end | end | ||
Line 162: | Line 229: | ||
end | end | ||
--endregion | |||
--region Public methods | |||
--- For calling from Template:Buildingbox. After handling the frame, forwards control to the primary method, compileBoxData, then calls the view template with the compiled box data. Does not interface with any data modules. | --- For calling from Template:Buildingbox. After handling the frame, forwards control to the primary method, compileBoxData, then calls the view template with the compiled box data. Does not interface with any data modules. | ||
Line 170: | Line 241: | ||
function Buildingbox2.main(frame) | function Buildingbox2.main(frame) | ||
local | local name = frame.args[ARG_NAME] | ||
if not | if not name then | ||
error("You must specify the | error("You must specify the name of the building. Please see the template documentation for how to use the parameters.") | ||
end | end | ||
local viewParameters = | local viewParameters = findBoxType(name) | ||
-- Return the message if it's a string, otherwise proceed because it's a table. | |||
if type(viewParameters) == "string" then | |||
return viewParameters | |||
end | |||
return frame:expandTemplate{ title = ViewTemplate, args = viewParameters } | return frame:expandTemplate{ title = ViewTemplate, args = viewParameters } |
Latest revision as of 02:50, 9 October 2024
Documentation for this module may be created at Module:Buildingbox2/doc
--- --- Retrieves data for the specified building, resource, perk, etc. and sends the data over to the view, another template. --- --- @module Buildingbox2 local Buildingbox2 = {} --region Dependencies --Some dependencies in this module are loaded lazily, but we want them scoped to the entire module, not their local functions local WorkshopsData local InstitutionsData local FarmsData local CampsData local CollectorsData local ViewTemplate = "Template:Infobox" --endregion --region Private constants local ARG_NAME = "name" local PARAM_TITLE = "title" local PARAM_SUBTITLE = "subtitle" local PARAM_DESCRIPTION = "description" local PARAM_SPECIALIZATION = "specialization" local PARAM_ICON_FILENAME = "iconfilename" local PARAM_MOVABLE = "movable" local PARAM_WORKPLACES = "workplaces" local PARAM_STORAGE = "storage" local PARAM_RECIPES = "recipes" local PARAM_CONSTRUCTION_COST = "construction" local PARAM_CITY_SCORE = "cityscore" local PARAM_CONSTRUCTION_TIME = "constructiontime" local PARAM_CONSTRUCTION_SIZE = "constructionsize" local PARAM_ID = "id" --endregion --region Private methods ---renderSpecializations takes the ID of a building and looks up its specializations, calls external view templates to convert those specializations into usable content strings for display, and returns those strings concatenated together for display by the calling scope. ---@param id string the unique ID of the building ---@return string a content string ready for display local function renderSpecializations(id) local SpecializationsData = mw.loadData("Module:SpecializationsData") local SpeciesData = mw.loadData("Module:SpeciesData") local frame = mw.getCurrentFrame() local listOfSpecializationsAtBuilding = SpecializationsData.buildingSpecializations[id] if not listOfSpecializationsAtBuilding then return nil end local concatenatedStrings = "" for _, specIndex in ipairs(listOfSpecializationsAtBuilding) do -- Specialization link first local specData = SpecializationsData.specializations[specIndex] local specializationString = frame:expandTemplate{ title = "Specialization", args = { ["iconfilename"] = specData[SpecializationsData.ICON_FILENAME], ["name"] = specData[SpecializationsData.NAME], ["type"] = specData[SpecializationsData.IS_COMFORTABLE] and "Comfort" or "Proficiency", ["size"] = "small", }, } -- Species link second, but just the icon local species = specData[SpecializationsData.SPECIES] local speciesString = frame:expandTemplate{ title = "Species", args = { ["iconfilename"] = SpeciesData.species[species][SpeciesData.ICON_FILENAME] .. ".png", ["name"] = SpeciesData.species[species][SpeciesData.NAME], ["size"] = "small", [1] = "notext", }, } -- Separate multiple entries with line break if #concatenatedStrings > 1 then concatenatedStrings = concatenatedStrings .. "<br />" end concatenatedStrings = concatenatedStrings .. specializationString .. " " .. speciesString end if #concatenatedStrings < 1 then return "None" end return concatenatedStrings end -- Building interface: -- getCategory -- getCityScore -- getConstructionCosts (as [goodName] = stack size) -- getConstructionTime -- getDescription -- getIcon -- isMovable -- getName -- getNumberOfWorkplaces -- getSize (as "X x Y") -- getStorage local function buildViewParameters(id, buildingInterface, subtitlePrefix) local frame = mw.getCurrentFrame() local viewParameters = {} viewParameters[PARAM_TITLE] = buildingInterface.getName(id) viewParameters[PARAM_SUBTITLE] = subtitlePrefix .. " (" .. buildingInterface.getCategory(id) .. ")" viewParameters[PARAM_DESCRIPTION] = buildingInterface.getDescription(id) viewParameters[PARAM_SPECIALIZATION] = renderSpecializations(id) viewParameters[PARAM_ICON_FILENAME] = buildingInterface.getIcon(id) viewParameters[PARAM_MOVABLE] = buildingInterface.isMovable(id) and "true" viewParameters[PARAM_WORKPLACES] = buildingInterface.getNumberOfWorkplaces(id) viewParameters[PARAM_RECIPES] = frame:expandTemplate{ title = "Recipe", args = { ["building"] = buildingInterface.getName(id), ["display"] = "list", }, } viewParameters[PARAM_STORAGE] = buildingInterface.getStorage(id) viewParameters[PARAM_CONSTRUCTION_COST] = frame:expandTemplate{ title = "Construction", args = buildingInterface.getConstructionCosts(id) } viewParameters[PARAM_CITY_SCORE] = buildingInterface.getCityScore(id) viewParameters[PARAM_CONSTRUCTION_TIME] = buildingInterface.getConstructionTime(id) viewParameters[PARAM_CONSTRUCTION_SIZE] = buildingInterface.getSize(id) viewParameters[PARAM_ID] = id return viewParameters end local function tryWorkshopsData(name) WorkshopsData = require("Module:WorkshopsData") local id = WorkshopsData.getWorkshopID(name) if not id then return false else return buildViewParameters(id, WorkshopsData, "Production Building") end end local function tryInstitutionsData(name) InstitutionsData = require("Module:InstitutionsData") local id = InstitutionsData.getInstitutionID(name) if not id then return false else return buildViewParameters(id, InstitutionsData, "Service Building") end end local function tryFarmsData(name) FarmsData = require("Module:FarmsData") local id = FarmsData.getFarmID(name) if not id then return false else return buildViewParameters(id, FarmsData, "Farm") end end local function tryCampsData(name) CampsData = require("Module:CampsData") local id = CampsData.getCampID(name) if not id then return false else return buildViewParameters(id, CampsData, "Gathering Camp") end end local function tryCollectorsData(name) CollectorsData = require("Module:CollectorsData") local id = CollectorsData.getCollectorID(name) if not id then return false else return buildViewParameters(id, CollectorsData, "Extraction Building") end end --- For calling from another template, like Infobox. Handles data only, does not interface with the Buildingbox view. ---@param name string the name of the building about which to retrieve data ---@return table the essential data about the building extracted local function findBoxType(name) -- Lazy-load of external data, since it's expensive. Start with the most likely so that most pages load as fast as possible. local viewParameters = tryWorkshopsData(name) if not viewParameters then viewParameters = tryInstitutionsData(name) if not viewParameters then viewParameters = tryFarmsData(name) if not viewParameters then viewParameters = tryCollectorsData(name) if not viewParameters then viewParameters = tryCampsData(name) if not viewParameters then return("No building found with name: " .. name .. ".") end end end end end return viewParameters end --endregion --region Public methods --- For calling from Template:Buildingbox. After handling the frame, forwards control to the primary method, compileBoxData, then calls the view template with the compiled box data. Does not interface with any data modules. --- ---@param frame table the calling template's context ---@return string wiki markup, constructed with the template view function Buildingbox2.main(frame) local name = frame.args[ARG_NAME] if not name then error("You must specify the name of the building. Please see the template documentation for how to use the parameters.") end local viewParameters = findBoxType(name) -- Return the message if it's a string, otherwise proceed because it's a table. if type(viewParameters) == "string" then return viewParameters end return frame:expandTemplate{ title = ViewTemplate, args = viewParameters } end --endregion return Buildingbox2