Module:WorkshopsData2

From Against the Storm Official Wiki
Revision as of 18:17, 20 October 2024 by Aeredor (talk | contribs) (Created as next version where the data is loaded from json instead of separate csvs for buildings and recipes)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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

--- @module WorkshopsData
local WorkshopsData = {}



--region Dependencies

local DATA_MODULE = "Module:WorkshopsData/Workshops.json"

local JsonUtils = require("Module:JsonUtils")

-- Some dependencies are loaded lazily
local GoodsData

--endregion



--region Private member variables

--- Main data table, like this: table[ID] = table containing data for that ID
local workshopsTable

--- Supporting table, list of names table[i] = name.
local workshopsNames

--- Lookup map. Built once and reused on all subsequent calls within this
--- session, like this: table[displayName] = workshopID
local mapNamesToIDs

--- Lookup map. Built once and reused on all subsequent calls within this
--- session, like this: table[recipeID] = { workshopName1, workshopName2, ... }
local mapRecipeIDsToWorkshopNames

--endregion



--region Private constants

local INDEX_CATEGORY = "category"
local INDEX_CITY_SCORE = "cityScore"
local INDEX_CONSTRUCTION_TIME = "constructionTime"
local INDEX_DESCRIPTION = "description"
local INDEX_NAME = "displayName"
local INDEX_ID = "id"
local INDEX_IS_ESSENTIAL = "initiallyEssential"
local INDEX_IS_MOVABLE = "movable"
local INDEX_RECIPES = "recipes"

local INDEX_RECIPE_GRADE = "grade"

local INDEX_RECIPE_INGREDIENTS = "ingredients"
local INDEX_RECIPE_INGREDIENT_AMOUNT = "amount"
local INDEX_RECIPE_INGREDIENT_ID = "name"

local INDEX_RECIPE_PRODUCT = "product"
local INDEX_RECIPE_PRODUCT_AMOUNT = "amount"
local INDEX_RECIPE_PRODUCT_ID = "name"

local INDEX_RECIPE_TIME = "productionTime"

local INDEX_CONSTRUCTION_GOODS = "requiredGoods"

local INDEX_CONSTRUCTION_GOODS_AMOUNT = "amount"
local INDEX_CONSTRUCTION_GOODS_ID = "name"

local INDEX_SIZE_X = "sizeX"
local INDEX_SIZE_Y = "sizeY"
local INDEX_STORAGE_CAP = "storage"

local INDEX_WORKPLACES = "workplaces"

--endregion



--region Private methods

local function load()
	if not workshopsTable then
		-- Utility module loads the data from JSON.
		workshopsTable = JsonUtils.convertJSONToLuaTable(DATA_MODULE)
	end
	--return workshopsTable if debugging
end

---findID loops through the table to find the id, then returns the record
---@param id string the ID
---@return table the record with that ID, or nil if not found
local function findID(id)
	load()
	for _, workshop in ipairs(workshopsTable) do
		if workshop[INDEX_ID] == id then
			return workshop
		end
	end
	return nil
end

---findName loops through the table to find the name, then returns the record
---@param name string the display name
---@return table the record with that name, or nil if not found
local function findName(name)
	load()
	for _, workshop in ipairs(workshopsTable) do
		if workshop[INDEX_NAME] == name then
			return workshop
		end
	end
	return nil
end

--endregion



--region Public methods

--- DEPRECATED --- DO NOT USE ---
---@deprecated
function WorkshopsData.getAllWorkshopRecipes(displayName)

	if not displayName or displayName == "" then
		error("Parameter is nil or empty for display name.")
	end

	load()

	local id = mapNamesToIDs[displayName]
	if not id then
		return nil
	end

	local workshop = workshopsTable[id]
	if not workshop then
		return nil
	end

	return workshop[INDEX_RECIPES]
end



--- DEPRECATED --- DO NOT USE ---
---@deprecated
function WorkshopsData.getWorkshopIcon(displayName)

	if not displayName or displayName == "" then
		error("Parameter is nil or empty for display name.")
	end

	load()

	local id = mapNamesToIDs[displayName]
	if not id then
		return nil
	end

	-- the base string of the icon is the ID. It has to be not nil to
	-- concatenate
	return id .. "_icon.png"
end



--- DEPRECATED --- DO NOT USE ---
---@deprecated
function WorkshopsData.getWorkshopNamesWithRecipeID(recipeID)

	-- At runtime, this should never be nil or empty.
	if not recipeID or recipeID == "" then
		error("Parameter is nil or empty for product ID.")
	end

	load()

	return mapRecipeIDsToWorkshopNames[recipeID]
end

--endregion



--region Public building interface

-- getID(displayName)
-- getCategory(id)
-- getCityScore(id)
-- getConstructionCosts(id) -- returns { [goodName] = stack size }
-- getConstructionTime(id)
-- getDescription(id)
-- getIcon(id)
-- isMovable(id)
-- getName(id)
-- getNumberOfWorkplaces(id)
-- getSize(id) -- returns string "X x Y"
-- getStorage(id)

---getID finds the specified name and returns the associated ID
---@param name string the display name
---@return string the ID, or nil if not found
function WorkshopsData.getID(name)
	local workshop = findName(name)
	if workshop then
		return workshop[INDEX_ID]
	else
		return nil
	end
end

---getCategory from an ID
---@param id string the ID
---@return string the category, or nil if not found
function WorkshopsData.getCategory(id)
	local workshop = findID(id)
	if workshop then
		return workshop[INDEX_CATEGORY]
	else
		return nil
	end
end

---getCityScore from an ID
---@param id string the ID
---@return number the city score, or nil if not found
function WorkshopsData.getCityScore(id)
	local workshop = findID(id)
	if workshop then
		return workshop[INDEX_CITY_SCORE]
	else
		return nil
	end
end

---getConstructionCosts in the form of an array of short tables describing goods required for construction.
---	example = {
---		[1] = {
---			["amount"] = 5,
---			["name"] = "[Mat Processed] Planks", -- note that this is NOT a name, but an ID
---		},
---		[2] = {
---			["amount"] = 2,
---			["name"] = "[Mat Processed] Bricks", -- note that this is NOT a name, but an ID
---		},
---	}
---@param id string the ID
---@return table an array of tables with amount and ID
function WorkshopsData.getConstructionCosts(id)
	local workshop = findID(id)
	if workshop then
		return workshop[INDEX_CONSTRUCTION_GOODS]
	else
		return nil
	end
end

---getConstructionTime from an ID
---@param id string the ID
---@return number the number of seconds, or nil if not found
function WorkshopsData.getConstructionTime(id)
	local workshop = findID(id)
	if workshop then
		return workshop[INDEX_CONSTRUCTION_TIME]
	else
		return nil
	end
end

---getDescription from an ID
---@param id string the ID
---@return string the description including sprite markup, or nil if not found
function WorkshopsData.getDescription(id)
	local workshop = findID(id)
	if workshop then
		return workshop[INDEX_DESCRIPTION]
	else
		return nil
	end
end

---getIcon from an ID
---@param id string the ID
---@return string the icon filename, or nil if not found
function WorkshopsData.getIcon(id)
	local workshop = findID(id)
	if workshop then
		return id .. "_icon.png"
	else
		return nil
	end
end

---isMovable from an ID
---@param id string the ID
---@return boolean true if the building can be moved, false if not (or nil if not found)
function WorkshopsData.isMovable(id)
	local workshop = findID(id)
	if workshop then
		return workshop[INDEX_IS_MOVABLE]
	else
		return nil
	end
end

---getName from an ID
---@param id string the ID
---@return string the name, or nil if not found
function WorkshopsData.getName(id)
	local workshop = findID(id)
	if workshop then
		return workshop[INDEX_NAME]
	else
		return nil
	end
end

---getNumberOfWorkplaces from an ID
---@param id string the ID
---@return number how many worker slots, or nil if not found
function WorkshopsData.getNumberOfWorkplaces(id)
	local workshop = findID(id)
	if workshop then
		return workshop[INDEX_WORKPLACES]
	else
		return nil
	end
end

---getSize from an ID
---@param id string the ID
---@return string as x-by-y, or nil if not found
function WorkshopsData.getSize(id)
	local workshop = findID(id)
	if workshop then
		return workshop[INDEX_SIZE_X] .. " × " .. workshop[INDEX_SIZE_Y]
	else
		return nil
	end
end

---getStorage from an ID
---@param id string the ID
---@return number the storage capacity, or nil if not found
function WorkshopsData.getStorage(id)
	local workshop = findID(id)
	if workshop then
		return workshop[INDEX_STORAGE_CAP]
	else
		return nil
	end
end

--endregion

return WorkshopsData