Module:FarmsData: Difference between revisions
From Against the Storm Official Wiki
m Homestead has 4 recipes |
added function to get all IDs; removed outdated comment at top |
||
| Line 1: | Line 1: | ||
--- @module FarmsData | --- @module FarmsData | ||
local FarmsData = {} | local FarmsData = {} | ||
| Line 112: | Line 5: | ||
--region Dependencies | --region Dependencies | ||
local DATA_TEMPLATE_NAME = "Template:Farms_csv" | |||
local CsvUtils = require("Module:CsvUtils") | local CsvUtils = require("Module:CsvUtils") | ||
| Line 141: | Line 36: | ||
--region Private constants | --region Private constants | ||
local INDEX_ID = "id" | local INDEX_ID = "id" | ||
| Line 1,035: | Line 928: | ||
--region Public Building interface | --region Public Building interface | ||
-- getID(displayName) | |||
-- getCategory | -- getCategory | ||
-- getCityScore | -- getCityScore | ||
| Line 1,046: | Line 940: | ||
-- getSize (as "X x Y") | -- getSize (as "X x Y") | ||
-- getStorage | -- getStorage | ||
function FarmsData.getID(displayName) | |||
load() | |||
return mapNamesToIDs[displayName] | |||
end | |||
function FarmsData.getCategory(id) | function FarmsData.getCategory(id) | ||
Revision as of 20:26, 14 October 2024
Documentation for this module may be created at Module:FarmsData/doc
--- @module FarmsData
local FarmsData = {}
--region Dependencies
local DATA_TEMPLATE_NAME = "Template:Farms_csv"
local CsvUtils = require("Module:CsvUtils")
-- Some dependencies are loaded lazily
local GoodsData
--endregion
--region Private member variables
--- Main data tables, like this: table[ID] = table containing data for that ID
local farmsTable
--- Supporting table, list of names table[i] = name.
local farmsNames
--- Lookup map. Built once and reused on subsequent calls within this session,
--- like this: table[display name] = farmID
local mapNamesToIDs
--- Lookup map. Built once and reused on subsequent calls within this session,
--- like this: table[goodID] = { farmName1, farmName2, ... }
local mapRecipeGoodIDsToFarmNames
--endregion
--region Private constants
local INDEX_ID = "id"
local INDEX_NAME = "displayName"
local INDEX_DESCRIPTION = "description"
local INDEX_CATEGORY = "category"
local INDEX_SIZE_X = "sizeX"
local INDEX_SIZE_Y = "sizeY"
local INDEX_CITY_SCORE = "cityScore"
local INDEX_MOVABLE = "movable"
local INDEX_INITIALLY_ESSENTIAL = "initiallyEssential"
local INDEX_AREA = "area"
local INDEX_STORAGE = "storage"
local INDEX_CONSTRUCTION_TIME = "constructionTime"
local INDEX_REQUIRED_GOODS = "requiredGoods" -- table
local INDEX_WORKPLACES = "workplaces" -- table
local INDEX_RECIPES = "recipes" -- table
local INDEX_CONSTRUCTION_GOODS_STACK_SIZE = "stackSize"
local INDEX_CONSTRUCTION_GOODS_GOOD_ID = "goodID"
local INDEX_RECIPE_STACK_SIZE = "stackSize"
local INDEX_RECIPE_GOOD_ID = "goodID"
local INDEX_RECIPE_GRADE = "grade"
local INDEX_RECIPE_PLANTING_TIME = "plantingTime"
local INDEX_RECIPE_HARVESTING_TIME = "harvestingTime"
local PATTERN_SPLIT_STACK_AND_ID = "(%d+)%s([%[%]%s%a]+)"
local PATTERN_CAPTURE_END_NUMBER = "Grade(%d)"
--endregion
--region Private methods
---
--- Creates a new subtable containing the construction goods required for the
--- specified farm.
---
--- @param originalFarm table farm data record from which to make subtable
--- @param farmsHeaderLookup table header lookup built from the CSV data
--- @return table subtable with the required construction goods
local function makeRequiredGoodsSubtable(originalFarm, farmsHeaderLookup)
-- A constant we'll need only within this function.
local REQ_GOOD_HEADER_BASE_STRING = "requiredGood"
-- Copy the originals directly into a subtable.
local requiredIndex1 = farmsHeaderLookup[REQ_GOOD_HEADER_BASE_STRING .. "1"]
local requiredIndex2 = farmsHeaderLookup[REQ_GOOD_HEADER_BASE_STRING .. "2"]
local requiredIndex3 = farmsHeaderLookup[REQ_GOOD_HEADER_BASE_STRING .. "3"]
local number1, id1 = originalFarm[requiredIndex1]:match(PATTERN_SPLIT_STACK_AND_ID)
local number2, id2 = originalFarm[requiredIndex2]:match(PATTERN_SPLIT_STACK_AND_ID)
local number3, id3 = originalFarm[requiredIndex3]:match(PATTERN_SPLIT_STACK_AND_ID)
-- don't add subtables that would just contain nils
local requiredGoods = {
number1 and id1 and { [INDEX_CONSTRUCTION_GOODS_STACK_SIZE] = tonumber(number1), [INDEX_CONSTRUCTION_GOODS_GOOD_ID] = id1 } or nil,
number2 and id2 and { [INDEX_CONSTRUCTION_GOODS_STACK_SIZE] = tonumber(number2), [INDEX_CONSTRUCTION_GOODS_GOOD_ID] = id2 } or nil,
number3 and id3 and { [INDEX_CONSTRUCTION_GOODS_STACK_SIZE] = tonumber(number3), [INDEX_CONSTRUCTION_GOODS_GOOD_ID] = id3 } or nil
}
return requiredGoods
end
---
--- Creates a new subtable containing the workplaces available in the specified
--- farm.
---
--- @param originalFarm table farm data record from which to make subtable
--- @param farmsHeaderLookup table header lookup built from the CSV data
--- @return table subtable with the workplaces
local function makeWorkplacesSubtable(originalFarm, farmsHeaderLookup)
-- A constant we'll need only within this function.
local WORKPLACE_HEADER_BASE_STRING = "workplace"
-- Copy the originals directly into a subtable.
local workplaceIndex1 = farmsHeaderLookup[WORKPLACE_HEADER_BASE_STRING .. "1"]
local workplaceIndex2 = farmsHeaderLookup[WORKPLACE_HEADER_BASE_STRING .. "2"]
local workplaceIndex3 = farmsHeaderLookup[WORKPLACE_HEADER_BASE_STRING .. "3"]
local workplaceIndex4 = farmsHeaderLookup[WORKPLACE_HEADER_BASE_STRING .. "4"]
local workplace1 = originalFarm[workplaceIndex1]
local workplace2 = originalFarm[workplaceIndex2]
local workplace3 = originalFarm[workplaceIndex3]
local workplace4 = originalFarm[workplaceIndex4]
-- if it's not an empty string, then save that to the table, otherwise nil
local workplaces = {
(workplace1 ~= "" and workplace1) or nil,
(workplace2 ~= "" and workplace2) or nil,
(workplace3 ~= "" and workplace3) or nil,
(workplace4 ~= "" and workplace4) or nil
}
return workplaces
end
---
--- Creates a new subtable containing the recipes available in the specified
--- farm.
---
--- @param farmName string the display name of the farm
--- @param originalFarm table farm data record from which to make subtable
--- @param farmsHeaderLookup table header lookup built from the CSV data
--- @return table subtable with the recipe IDs
local function makeRecipesSubtable(farmName, originalFarm, farmsHeaderLookup)
-- A constant we'll need only within this function.
local MAX_RECIPES = 4
local LOOKUP_RECIPE_BASE_STRING = "recipe"
local LOOKUP_GOOD_BASE_STRING = "Good"
local LOOKUP_GRADE_BASE_STRING = "Grade"
local LOOKUP_PLANTING_TIME_BASE_STRING = "PlantingTime"
local LOOKUP_HARVESTING_TIME_BASE_STRING = "HarvestTime"
if not mapRecipeGoodIDsToFarmNames then
mapRecipeGoodIDsToFarmNames = {}
end
-- Copy the originals directly into a subtable.
local recipes = {}
for i = 1, MAX_RECIPES do
-- A subtable for this recipe
newRecipe = {}
local originalGoodIndex = farmsHeaderLookup[LOOKUP_RECIPE_BASE_STRING .. i
.. LOOKUP_GOOD_BASE_STRING]
local originalGradeIndex = farmsHeaderLookup[LOOKUP_RECIPE_BASE_STRING .. i
.. LOOKUP_GRADE_BASE_STRING]
local originalPlantingTimeIndex = farmsHeaderLookup[LOOKUP_RECIPE_BASE_STRING .. i
.. LOOKUP_PLANTING_TIME_BASE_STRING]
local originalHarvestingTimeIndex = farmsHeaderLookup[LOOKUP_RECIPE_BASE_STRING .. i
.. LOOKUP_HARVESTING_TIME_BASE_STRING]
local originalStackSize, originalGoodID = originalFarm[originalGoodIndex]:match(PATTERN_SPLIT_STACK_AND_ID)
-- Skip blank recipes.
if originalGoodID and originalGoodID ~= "" then
newRecipe[INDEX_RECIPE_GOOD_ID] = originalGoodID
newRecipe[INDEX_RECIPE_STACK_SIZE] = tonumber(originalStackSize)
newRecipe[INDEX_RECIPE_GRADE] = tonumber(originalFarm[originalGradeIndex]:match(PATTERN_CAPTURE_END_NUMBER))
newRecipe[INDEX_RECIPE_PLANTING_TIME] = tonumber(originalFarm[originalPlantingTimeIndex])
newRecipe[INDEX_RECIPE_HARVESTING_TIME] = tonumber(originalFarm[originalHarvestingTimeIndex])
table.insert(recipes,newRecipe)
if not mapRecipeGoodIDsToFarmNames[originalGoodID] then
mapRecipeGoodIDsToFarmNames[originalGoodID] = {}
end
table.insert(mapRecipeGoodIDsToFarmNames[originalGoodID], farmName)
end
end
return recipes
end
---
--- Transforms the originalFarmsTable returned from CSV processing to be
--- more conducive to member functions looking up data. Converts text strings
--- into subtables. Converts header row into field keys on every record and
--- stores records by id rather than arbitrary integer.
---
--- @param originalFarmsTable table of CSV-based data, with header row, data rows
--- @param farmsHeaderLookup table lookup table of headers to get indexes
--- @return table better structured with IDs as keys
local function restructureFarmsTable(originalFarmsTable, farmsHeaderLookup)
-- A few constants we need only in this function.
local DATA_ROWS = 2
local INDEX_ORIGINAL_ID = 1
local INDEX_ORIGINAL_NAME = 2
local INDEX_ORIGINAL_DESCRIPTION = 3
local INDEX_ORIGINAL_CATEGORY = 4
local INDEX_ORIGINAL_SIZE_X = 5
local INDEX_ORIGINAL_SIZE_Y = 6
-- Required goods are indexes 7, 8, 9
local INDEX_ORIGINAL_CONSTRUCTION_TIME = 10
local INDEX_ORIGINAL_CITY_SCORE = 11
local INDEX_ORIGINAL_MOVABLE = 12
local INDEX_ORIGINAL_ESSENTIAL = 13
local INDEX_ORIGINAL_AREA = 14
local INDEX_ORIGINAL_STORAGE = 15
mapNamesToIDs = {}
farmsNames = {}
local newFarmsTable = {}
for _, originalFarm in ipairs(originalFarmsTable[DATA_ROWS]) do
-- Copy over the content, mapping unhelpful indexes into headers keys.
local newFarm = {}
newFarm[INDEX_ID] = originalFarm[INDEX_ORIGINAL_ID]
newFarm[INDEX_NAME] = originalFarm[INDEX_ORIGINAL_NAME]
newFarm[INDEX_DESCRIPTION] = originalFarm[INDEX_ORIGINAL_DESCRIPTION]
newFarm[INDEX_CATEGORY] = originalFarm[INDEX_ORIGINAL_CATEGORY]
newFarm[INDEX_SIZE_X] = tonumber(originalFarm[INDEX_ORIGINAL_SIZE_X])
newFarm[INDEX_SIZE_Y] = tonumber(originalFarm[INDEX_ORIGINAL_SIZE_Y])
newFarm[INDEX_CITY_SCORE] = tonumber(originalFarm[INDEX_ORIGINAL_CITY_SCORE])
newFarm[INDEX_MOVABLE] = originalFarm[INDEX_ORIGINAL_MOVABLE] == "True"
newFarm[INDEX_INITIALLY_ESSENTIAL] = originalFarm[INDEX_ORIGINAL_ESSENTIAL] == "True"
newFarm[INDEX_AREA] = tonumber(originalFarm[INDEX_ORIGINAL_AREA])
newFarm[INDEX_STORAGE] = tonumber(originalFarm[INDEX_ORIGINAL_STORAGE])
newFarm[INDEX_CONSTRUCTION_TIME] = tonumber(originalFarm[INDEX_ORIGINAL_CONSTRUCTION_TIME])
newFarm[INDEX_REQUIRED_GOODS] = makeRequiredGoodsSubtable(originalFarm, farmsHeaderLookup)
newFarm[INDEX_WORKPLACES] = makeWorkplacesSubtable(originalFarm, farmsHeaderLookup)
newFarm[INDEX_RECIPES] = makeRecipesSubtable(newFarm[INDEX_NAME], originalFarm, farmsHeaderLookup)
newFarmsTable[ newFarm[INDEX_ID] ] = newFarm
table.insert(farmsNames, newFarm[INDEX_NAME])
-- Also populate the map for looking up IDs with display names
mapNamesToIDs[ newFarm[INDEX_NAME] ] = newFarm[INDEX_ID]
end
return newFarmsTable
end
---
--- Data loader function that uses the utility module and restructures the data
--- to be easier to access for invoking methods and later method calls. This
--- method is automatically called by all public member functions if the main
--- data table has not yet been populated in the current session.
local function loadData()
-- Utility module retrieves the data as basic, flat lua tables.
local originalFarmsTable, farmsHeaderLookup = CsvUtils.extractTables(DATA_TEMPLATE_NAME)
-- Now restructure to be more conducive.
farmsTable = restructureFarmsTable(originalFarmsTable, farmsHeaderLookup)
end
local function load()
if not farmsTable then
loadData()
end
end
---
--- Uses the display name, which people are more familiar with, to find the
--- encoded ID of the farm. Useful for retrieving the data that is
--- indexed by ID.
---
--- Returns nil if the farm with the specified name is not found.
---
--- @param displayName string plain-language name of the farm to find
--- @return string ID of the farm found, or nil if not found
local function findFarmIDByName(displayName)
-- At runtime, this should never be nil or empty, so throw an error.
if not displayName or displayName == "" then
error("Parameter is nil or empty for the farm's name: " .. displayName .. ".")
end
if not farmsTable then
loadData()
end
return mapNamesToIDs[displayName]
end
--endregion
--region Public methods
--- Retrieve the whole table of data for the specified farm. Instead of
--- this, you should probably be calling the individual getter methods.
---
--- Throws an error if called with nil or empty string. Returns nil if the
--- specified farm cannot be found.
---
--- @param farmID string ID of the farm
--- @return table containing the data with key-value pairs, or nil if not found
function FarmsData.getAllDataForFarmByID(farmID)
-- At runtime, this should never be nil or empty.
if not farmID or farmID == "" then
error("Parameter is nil or empty for the farm's ID.")
end
if not farmsTable then
loadData()
end
return farmsTable[farmID]
end
--- Retrieve the whole table of data for the specified farm. Instead of
--- this, you should probably be calling the individual getter methods.
---
--- Throws an error if called with nil or empty string. Returns nil if the
--- specified farm cannot be found.
---
--- @param displayName string plain language name of the farm
--- @return table containing the data with key-value pairs, or nil if not found
function FarmsData.getAllDataForFarm(displayName)
-- At runtime, this should never be nil or empty.
if not displayName or displayName == "" then
error("Parameter is nil or empty for the farm's name.")
end
if not farmsTable then
loadData()
end
local farmID = findFarmIDByName(displayName)
if not farmID then
return nil
end
return farmsTable[farmID]
end
---
--- Retrieves the ID for the farm specified by its plain language
--- display name.
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@return string the ID of the specified farm
function FarmsData.getFarmID(displayName)
local farm = FarmsData.getAllDataForFarm(displayName)
if not farm then
return nil
end
return farm[INDEX_ID]
end
---
--- Retrieves the description for the farm specified by its plain
--- language display name.
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@return string the in-game description of the specified farm
function FarmsData.getFarmDescription(displayName)
local farm = FarmsData.getAllDataForFarm(displayName)
if not farm then
return nil
end
return farm[INDEX_DESCRIPTION]
end
---
--- Retrieves the construction toolbar category for the farm specified
--- by its plain language display name.
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@return string the category of the specified farm
function FarmsData.getFarmCategory(displayName)
local farm = FarmsData.getAllDataForFarm(displayName)
if not farm then
return nil
end
return farm[INDEX_CATEGORY]
end
---
--- Retrieves the 2x2 size for the farm specified by its plain language
--- display name.
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@return number the X-size of the farm
---@return number the Y-size of the farm
function FarmsData.getFarmSize(displayName)
local farm = FarmsData.getAllDataForFarm(displayName)
if not farm then
return nil
end
return farm[INDEX_SIZE_X], farm[INDEX_SIZE_Y]
end
---
--- Retrieves the goods required for construction for the farm specified
--- by its plain language display name, in a table that looks like this:
---
--- ["requiredGoods"] = {
--- [1] = { ["stackSize"] = 99, ["goodID"] = "good1_ID" },
--- [2] = { ["stackSize"] = 99, ["goodID"] = "good2_ID" },
--- [3] = { ... } or missing if fewer
--- }
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@return table of required goods
function FarmsData.getAllFarmRequiredGoods(displayName)
local farm = FarmsData.getAllDataForFarm(displayName)
if not farm then
return nil
end
return farm[INDEX_REQUIRED_GOODS]
end
---
--- Retrieves the specified required construction good for the farm
--- specified by its plain language display name.
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@param requirementIndex number which construction good to retrieve
---@return string the ID of the good that is required, or nil if none
---@return number the stack size of that good, or nil if none
function FarmsData.getFarmRequiredGood(displayName, requirementIndex)
local requiredGoods = FarmsData.getAllFarmRequiredGoods(displayName)
if not requiredGoods then
return nil
end
local requirement = requiredGoods[requirementIndex]
if not requirement then
return nil
end
return requirement[INDEX_CONSTRUCTION_GOODS_GOOD_ID], requirement[INDEX_CONSTRUCTION_GOODS_STACK_SIZE]
end
---
--- Retrieves the construction time for the farm specified by its plain
--- language display name.
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@return number of seconds it takes to construct the farm
function FarmsData.getFarmConstructionTime(displayName)
local farm = FarmsData.getAllDataForFarm(displayName)
if not farm then
return nil
end
return farm[INDEX_CONSTRUCTION_TIME]
end
---
--- Retrieves the city score awarded for the farm specified by its plain
--- language display name.
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@return number of points for city score from having the farm
function FarmsData.getFarmCityScore(displayName)
local farm = FarmsData.getAllDataForFarm(displayName)
if not farm then
return nil
end
return farm[INDEX_CITY_SCORE]
end
---
--- Retrieves whether the farm specified by its plain language display
--- name can be moved, at any cost.
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@return boolean of whether the farm can be moved
function FarmsData.isFarmMovable(displayName)
local farm = FarmsData.getAllDataForFarm(displayName)
if not farm then
return nil
end
return farm[INDEX_MOVABLE]
end
---
--- Retrieves whether the farm specified by its plain language display
--- name has an essential starting blueprint for a new game profile.
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@return boolean of whether the farm's blueprint is essential
function FarmsData.isFarmInitiallyEssential(displayName)
local farm = FarmsData.getAllDataForFarm(displayName)
if not farm then
return nil
end
return farm[INDEX_INITIALLY_ESSENTIAL]
end
---
--- Retrieves the gathering area for the farm specified by its plain
--- language display name.
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@return number of tiles of gathering radius
function FarmsData.getFarmArea(displayName)
local farm = FarmsData.getAllDataForFarm(displayName)
if not farm then
return nil
end
return farm[INDEX_AREA]
end
---
--- Retrieves the storage capacity of the farm specified by its plain
--- language display name.
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@return number of storage capacity at the farm
function FarmsData.getFarmStorage(displayName)
local farm = FarmsData.getAllDataForFarm(displayName)
if not farm then
return nil
end
return farm[INDEX_STORAGE]
end
---
--- Retrieves the table of workplaces for the farm specified by its
--- plain language display name.
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@return table of workplaces
function FarmsData.getAllFarmWorkplaces(displayName)
local farm = FarmsData.getAllDataForFarm(displayName)
if not farm then
return nil
end
return farm[INDEX_WORKPLACES]
end
---
--- Retrieves the number of workplaces for the farm specified by its
--- plain language display name.
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@return number of workplaces
function FarmsData.getFarmNumberOfWorkplaces(displayName)
local farm = FarmsData.getAllDataForFarm(displayName)
if not farm then
return nil
end
return #farm[INDEX_WORKPLACES]
end
---
--- Retrieves the table of recipes for the farm specified by its
--- plain language display name, in a table that looks like this:
---
--- ["recipes"] = {
--- [1] = "recipe1_ID",
--- [2] = "recipe2_ID",
--- [3] = "recipe3_ID",
--- [4] = ... or missing if fewer
--- }
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@return table of recipe IDs
function FarmsData.getAllFarmRecipes(displayName)
local farm = FarmsData.getAllDataForFarm(displayName)
if not farm then
return nil
end
return farm[INDEX_RECIPES]
end
---
--- Retrieves the number of recipes for the farm specified by its
--- plain language display name, in a table that looks like this:
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@return number of recipe at the farm
function FarmsData.getFarmNumberOfRecipes(displayName)
local farm = FarmsData.getAllDataForFarm(displayName)
if not farm then
return 0
end
recipes = farm[INDEX_RECIPES]
if not recipes then
return 0
end
return #recipes
end
---
--- Retrieves the product's ID and the stack size produced by the specified
--- recipe at the farm specified by its plain language display name.
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@param recipeIndex number the index of the recipe ID
---@return string the ID of the good produced by the specified recipe
---@return number the stack size produced by the specified recipe
function FarmsData.getFarmRecipeProduct(displayName, recipeIndex)
local recipes = FarmsData.getAllFarmRecipes(displayName)
if not recipes then
return nil
end
local recipe = recipes[recipeIndex]
if not recipe then
return nil
end
return recipe[INDEX_RECIPE_GOOD_ID], recipe[INDEX_RECIPE_STACK_SIZE]
end
---
--- Retrieves the other stats for specified recipe at the farm specified by
--- its plain language display name: the efficiency grade and the planting and
--- harvesting times.
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@param recipeIndex number the index of the recipe ID
---@return number of stars, the grade of the specified recipe
---@return number of seconds for planting
---@return number of seconds for harvesting
function FarmsData.getFarmRecipeStats(displayName, recipeIndex)
local recipes = FarmsData.getAllFarmRecipes(displayName)
if not recipes then
return nil
end
local recipe = recipes[recipeIndex]
if not recipe then
return nil
end
return recipe[INDEX_RECIPE_GRADE], recipe[INDEX_RECIPE_PLANTING_TIME], recipe[INDEX_RECIPE_HARVESTING_TIME]
end
---
--- Retrieves the icon filename for the farm specified by its plain
--- language display name.
---
--- Returns nil if the farm named was not found.
---
---@param displayName string the plain language name of the farm
---@return string the farm's icon filename, including the extension
function FarmsData.getFarmIcon(displayName)
local farm = FarmsData.getAllDataForFarm(displayName)
if not farm then
return nil
end
-- the base string of the icon is the ID. It has to be not nil to
-- concatenate
if farm[INDEX_ID] then
return farm[INDEX_ID] .. "_icon.png"
else
return nil
end
end
---
--- Retrieves the plain language display name for the farm specified by
--- its ID.
---
--- Returns nil if the farm named was not found.
---
---@param farmID string the ID of the farm
---@return string the farm's name as seen in-game
function FarmsData.getFarmNameByID(farmID)
local farm = FarmsData.getAllDataForFarmByID(farmID)
if not farm then
return nil
end
return farm[INDEX_NAME]
end
---
--- Retrieves the icon filename for the the farm specified by its ID.
---
--- Returns nil if the farm named was not found.
---
---@param farmID string the ID of the farm
---@return string the farm's icon filename, including the extension
function FarmsData.getFarmIconByID(farmID)
local farm = FarmsData.getAllDataForFarmByID(farmID)
if not farm then
return nil
end
-- the base string of the icon is the ID. It has to be not nil to
-- concatenate
if farm[INDEX_ID] then
return farm[INDEX_ID] .. "_icon.png"
else
return nil
end
end
---
--- Retrieve all display names of farms that have a recipe that produces the
--- specified product ID.
---
---@param productID string the ID of the good to produce
---@return table of farm names that produce the specified good
function FarmsData.getFarmNamesWithRecipeProductID(productID)
-- At runtime, this should never be nil or empty.
if not productID or productID == "" then
error("Parameter is nil or empty for product ID.")
end
if not farmsTable then
loadData()
end
return mapRecipeGoodIDsToFarmNames[productID]
end
---
--- Retrieves the name of the farm at the specified index.
---
---@param index number index
---@return string name of the building at the specified index
function FarmsData.getFarmNameFromDatabase(index)
if not index then
return nil
end
if not farmsTable then
loadData()
end
return farmsNames[index]
end
---
--- Returns the number of buildings that can be retrieved from this
--- module's database.
---
---@return number of records
function FarmsData.getNumberOfFarmsInDatabase()
if not farmsTable then
loadData()
end
return #farmsNames
end
--endregion
--region Public Building interface
-- getID(displayName)
-- getCategory
-- getCityScore
-- getConstructionCosts (as [goodName] = stack size)
-- getConstructionTime
-- getDescription
-- getIcon
-- isMovable
-- getName
-- getNumberOfWorkplaces
-- getSize (as "X x Y")
-- getStorage
function FarmsData.getID(displayName)
load()
return mapNamesToIDs[displayName]
end
function FarmsData.getCategory(id)
load()
return farmsTable[id] ~= nil and farmsTable[id][INDEX_CATEGORY]
end
function FarmsData.getCityScore(id)
load()
return farmsTable[id] ~= nil and farmsTable[id][INDEX_CITY_SCORE]
end
function FarmsData.getConstructionCosts(id)
load()
GoodsData = require("Module:GoodsData")
farm = farmsTable[id]
if not farm then
return false
end
local constructionCosts = {}
for _, stacks in ipairs(farm[INDEX_REQUIRED_GOODS]) do
local goodName = GoodsData.getGoodNameByID(stacks[INDEX_CONSTRUCTION_GOODS_GOOD_ID])
constructionCosts[goodName] = stacks[INDEX_CONSTRUCTION_GOODS_STACK_SIZE]
end
return constructionCosts
end
function FarmsData.getConstructionTime(id)
load()
return farmsTable[id] ~= nil and farmsTable[id][INDEX_CONSTRUCTION_TIME]
end
function FarmsData.getDescription(id)
load()
return farmsTable[id] ~= nil and farmsTable[id][INDEX_DESCRIPTION]
end
function FarmsData.getIcon(id)
load()
return farmsTable[id] ~= nil and id .. "_icon.png"
end
function FarmsData.isMovable(id)
load()
return farmsTable[id] ~= nil and farmsTable[id][INDEX_MOVABLE]
end
function FarmsData.getName(id)
load()
return farmsTable[id] ~= nil and farmsTable[id][INDEX_NAME]
end
function FarmsData.getNumberOfWorkplaces(id)
load()
return farmsTable[id] ~= nil and #farmsTable[id][INDEX_WORKPLACES]
end
function FarmsData.getSize(id)
load()
farm = farmsTable[id]
if not farm then
return false
end
return farm[INDEX_SIZE_X] .. " × " .. farm[INDEX_SIZE_Y]
end
function FarmsData.getStorage(id)
load()
return farmsTable[id] ~= nil and farmsTable[id][INDEX_STORAGE]
end
return FarmsData


