Module:MysteriesData: Difference between revisions
From Against the Storm Official Wiki
m (changing a few return values) |
(Refactored the data loading, now also skips mysteries marked for deletion) |
||
Line 18: | Line 18: | ||
local JSON_DATA_PAGE_1 = "Template:Simple_Seasonal_Effects_json" | local JSON_DATA_PAGE_1 = "Template:Simple_Seasonal_Effects_json" | ||
local JSON_DATA_PAGE_2 = "Template:Conditional_Seasonal_Effects_json" | local JSON_DATA_PAGE_2 = "Template:Conditional_Seasonal_Effects_json" | ||
local ID_PREFIX_TO_SKIP = "_TO DELETE" | |||
-- Keys in both | -- Keys in both | ||
Line 84: | Line 86: | ||
--region Private methods | --region Private methods | ||
--- This method uses the member variables mysteriesData and listOfIDs | |||
--- | |||
---@param dataTable table the data table to loop through | |||
local function saveRecordsByKey(dataTable) | |||
-- Store the mysteries by their ID, but also create a simple array of all IDs since we're already looping over them all. | |||
local i = #listOfIDs + 1 | |||
for _, record in ipairs(dataTable) do | |||
local mysteryID = record[KEY_ID] | |||
-- Validate the id | |||
if not mysteryID or mysteryID == "" then | |||
error(ERROR_MESSAGE_OBJECT_MISSING_KEY_ID) | |||
else | |||
-- Skip the records that the devs have marked for deletion | |||
if string.sub(mysteryID, 1, #ID_PREFIX_TO_SKIP) ~= ID_PREFIX_TO_SKIP then | |||
-- Validate that there are no duplicate IDs in the final table. | |||
if mysteriesData[mysteryID] ~= nil then | |||
error(ERROR_MESSAGE_UNEXPECTED_DUPLICATE_ID_ON_MERGE .. "\n id=" .. mysteryID) | |||
else | |||
-- Promote the id field to be the key. | |||
mysteriesData[mysteryID] = record | |||
listOfIDs[i] = mysteryID | |||
i = i + 1 | |||
end | |||
end | |||
end | |||
end | |||
end | |||
--- Checks whether the Mysteries data has been loaded yet. If not, handles that and the post-processing necessary. | --- Checks whether the Mysteries data has been loaded yet. If not, handles that and the post-processing necessary. | ||
Line 95: | Line 126: | ||
listOfIDs = {} | listOfIDs = {} | ||
saveRecordsByKey(JsonUtils.convertJSONToLuaTable(JSON_DATA_PAGE_1)) | |||
saveRecordsByKey(JsonUtils.convertJSONToLuaTable(JSON_DATA_PAGE_2)) | |||
end | end | ||
end | end |
Revision as of 19:31, 6 July 2024
Documentation for this module may be created at Module:MysteriesData/doc
--- --- ---@module MysteriesData local MysteriesData = {} --region Dependencies local JsonUtils = require("Module:JsonUtils") --endregion --region Private constants local JSON_DATA_PAGE_1 = "Template:Simple_Seasonal_Effects_json" local JSON_DATA_PAGE_2 = "Template:Conditional_Seasonal_Effects_json" local ID_PREFIX_TO_SKIP = "_TO DELETE" -- Keys in both local KEY_ID = "id" local KEY_DISPLAY_NAME = "displayName" local KEY_DESCRIPTION = "description" local KEY_ICON = "icon" local KEY_DIFFICULTY_COST = "difficultyCost" local KEY_COST_LABEL = "costLabel" local KEY_HOSTILITY_LEVEL = "hostilityLevel" local KEY_SEASON = "season" -- Keys in Simple Seasonal Effects local KEY_STACKS_WITH_HOSTILITY = "stacksWithHostility" local KEY_STACKS_WITH_YEAR = "stacksWithYear" local KEY_REMOVE_AFTER_YEAR = "removeAfterYear" local KEY_EFFECT_ID = "effectId" local KEY_IN_CUSTOM_MODE = "isInCustomMode" -- Keys in Conditional Seasonal Effects local KEY_VILLAGER_PERK_ID = "villagerPerkId" local KEY_CONDITIONS = "conditions" -- Keys in subtable local KEY_CONDITIONS_CATEGORY_ID = "categoryId" local KEY_CONDITIONS_CATEGORY_NAME = "categoryDisplayName" local KEY_CONDITIONS_AMOUNT = "amount" local IS_VALID_KEY = { [KEY_ID] = true, [KEY_DISPLAY_NAME] = true, [KEY_DESCRIPTION] = true, [KEY_ICON] = true, [KEY_DIFFICULTY_COST] = true, [KEY_COST_LABEL] = true, [KEY_HOSTILITY_LEVEL] = true, [KEY_SEASON] = true, [KEY_STACKS_WITH_HOSTILITY] = true, [KEY_STACKS_WITH_YEAR] = true, [KEY_REMOVE_AFTER_YEAR] = true, [KEY_EFFECT_ID] = true, [KEY_IN_CUSTOM_MODE] = true, [KEY_VILLAGER_PERK_ID] = true, [KEY_CONDITIONS] = true, } local IS_VALID_CONDITIONS_KEY = { [KEY_CONDITIONS_CATEGORY_ID] = true, [KEY_CONDITIONS_CATEGORY_NAME] = true, [KEY_CONDITIONS_AMOUNT] = true, } local ERROR_MESSAGE_ID_MISSING = "MysteriesData requires the unique identifier for a Forest Mystery to get its data. Double-check what was passed as a parameter, because it was either missing, nil, or blank." local ERROR_MESSAGE_UNEXPECTED_DUPLICATE_ID_ON_MERGE = "MysteriesData attempted to merge the two JSON data tables, however it found two records with the same id." local ERROR_MESSAGE_OBJECT_MISSING_KEY_ID = "MysteriesData discovered a record in the data that did not contain the required field named 'id' required to index the data. Double-check that the data has not been modified from how it was originally supplied by the developers." --endregion --region Private member variables local mysteriesData local listOfIDs --endregion --region Private methods --- This method uses the member variables mysteriesData and listOfIDs --- ---@param dataTable table the data table to loop through local function saveRecordsByKey(dataTable) -- Store the mysteries by their ID, but also create a simple array of all IDs since we're already looping over them all. local i = #listOfIDs + 1 for _, record in ipairs(dataTable) do local mysteryID = record[KEY_ID] -- Validate the id if not mysteryID or mysteryID == "" then error(ERROR_MESSAGE_OBJECT_MISSING_KEY_ID) else -- Skip the records that the devs have marked for deletion if string.sub(mysteryID, 1, #ID_PREFIX_TO_SKIP) ~= ID_PREFIX_TO_SKIP then -- Validate that there are no duplicate IDs in the final table. if mysteriesData[mysteryID] ~= nil then error(ERROR_MESSAGE_UNEXPECTED_DUPLICATE_ID_ON_MERGE .. "\n id=" .. mysteryID) else -- Promote the id field to be the key. mysteriesData[mysteryID] = record listOfIDs[i] = mysteryID i = i + 1 end end end end end --- Checks whether the Mysteries data has been loaded yet. If not, handles that and the post-processing necessary. --- local function loadData() -- This function gets called any time the data could need to be loaded. Just return as quickly as possible if it's already loaded. if not mysteriesData then mysteriesData = {} listOfIDs = {} saveRecordsByKey(JsonUtils.convertJSONToLuaTable(JSON_DATA_PAGE_1)) saveRecordsByKey(JsonUtils.convertJSONToLuaTable(JSON_DATA_PAGE_2)) end end --- Retrieves exactly one mystery table from the data. --- Throws an error if the parameter is missing, nil, or empty. --- Retrieving data from outside this class should be done via the public getter methods, not by getting the entire record, so this is local. --- ---@param mysteryID string the unique identifier of a Mystery ---@return table the whole table row for that Mystery local function getRecordWhereID(mysteryID) if not mysteryID or "" == mysteryID then error(ERROR_MESSAGE_ID_MISSING) else loadData() return mysteriesData[mysteryID] end end --- Retrieves the specified field from the specified mystery. --- Standardizes the calls from simple getters. --- Retrieving data from outside this class should be done via the public getter methods, not by getting the entire record, so this is local. --- ---@param mysteryID string the unique identifier of a Mystery ---@param fieldName string the desired constant field name ---@return any the value of the field--type is not known by this method local function getFieldWhereID(mysteryID, fieldName) if not IS_VALID_KEY[fieldName] then return nil end local record = getRecordWhereID(mysteryID) if not record then return nil else return record[fieldName] or nil end end --- Retrieves the specified condition from the specified mystery. --- Standardizes the calls from simple getters. --- Retrieving data from outside this class should be done via the public getter methods, not by getting the entire record, so this is local. --- ---@param mysteryID string the unique identifier of a Mystery ---@param conditionIndex number the index of the desired condition ---@return table the desired condition local function getConditionWhereID(mysteryID, conditionIndex) local conditions = getFieldWhereID(mysteryID, KEY_CONDITIONS) if not conditions then return nil else return conditions[conditionIndex] or nil end end --- Retrieves the specified condition from the specified mystery. --- Standardizes the calls from simple getters. --- Retrieving data from outside this class should be done via the public getter methods, not by getting the entire record, so this is local. --- ---@param mysteryID string the unique identifier of a Mystery ---@param conditionIndex number the index of the desired condition ---@param fieldName string the desired constant field name ---@return table the desired condition local function getFieldFromConditionWhereID(mysteryID, conditionIndex, fieldName) if not IS_VALID_CONDITIONS_KEY[fieldName] then return nil end local condition = getConditionWhereID(mysteryID, conditionIndex) if not condition then return nil else return condition[fieldName] or nil end end --endregion --region Public methods ---isIDValid ---@param mysteryID string a unique identifier ---@return boolean true if there is a record with the specified identifier function MysteriesData.isIDValid(mysteryID) local record = getRecordWhereID(mysteryID) if not record then return false else return true end end ---getName ---@param mysteryID string the unique identifier of a mystery ---@return string the name of the mystery function MysteriesData.getName(mysteryID) return getFieldWhereID(mysteryID, KEY_DISPLAY_NAME) end ---getDescription ---@param mysteryID string the unique identifier of a mystery ---@return string the description of the mystery function MysteriesData.getDescription(mysteryID) return getFieldWhereID(mysteryID, KEY_DESCRIPTION) end ---getIcon ---@param mysteryID string the unique identifier of a mystery ---@return string the icon of the mystery function MysteriesData.getIcon(mysteryID) return getFieldWhereID(mysteryID, KEY_ICON) end ---getCostDifficulty ---@param mysteryID string the unique identifier of a mystery ---@return number the difficulty cost of the mystery function MysteriesData.getCostDifficulty(mysteryID) return getFieldWhereID(mysteryID, KEY_DIFFICULTY_COST) end ---getCostLabel ---@param mysteryID string the unique identifier of a mystery ---@return string the label of the cost of the mystery function MysteriesData.getCostLabel(mysteryID) return getFieldWhereID(mysteryID, KEY_COST_LABEL) end ---getHostilityLevel ---@param mysteryID string the unique identifier of a mystery ---@return number the hostility level when the mystery kicks in function MysteriesData.getHostilityLevel(mysteryID) return getFieldWhereID(mysteryID, KEY_HOSTILITY_LEVEL) end ---getSeason ---@param mysteryID string the unique identifier of a mystery ---@return number the season when the mystery is in effect function MysteriesData.getSeason(mysteryID) return getFieldWhereID(mysteryID, KEY_SEASON) end ---isStacksWithHostility ---@param mysteryID string the unique identifier of a mystery ---@return boolean true if the mystery gets worse with higher hostility function MysteriesData.isStacksWithHostility(mysteryID) return getFieldWhereID(mysteryID, KEY_STACKS_WITH_HOSTILITY) or false end ---isStacksWithYear ---@param mysteryID string the unique identifier of a mystery ---@return boolean true if the mystery gets worse with each year function MysteriesData.isStacksWithYear(mysteryID) return getFieldWhereID(mysteryID, KEY_STACKS_WITH_YEAR) or false end ---isRemovedAfterYear ---@param mysteryID string the unique identifier of a mystery ---@return boolean true if the mystery is removed after one year function MysteriesData.isRemovedAfterYear(mysteryID) return getFieldWhereID(mysteryID, KEY_REMOVE_AFTER_YEAR) or false end ---getEffectID ---@param mysteryID string the unique identifier of a mystery ---@return string the identifier of the effect applied to the settlement function MysteriesData.getEffectID(mysteryID) return getFieldWhereID(mysteryID, KEY_EFFECT_ID) end ---isInCustomMode ---@param mysteryID string the unique identifier of a mystery ---@return boolean true if the mystery is available in custom mode function MysteriesData.isInCustomMode(mysteryID) return getFieldWhereID(mysteryID, KEY_IN_CUSTOM_MODE) or false end ---getVillagerPerkID ---@param mysteryID string the unique identifier of a mystery ---@return string the identifier of the effect applied to each villager function MysteriesData.getVillagerPerkID(mysteryID) return getFieldWhereID(mysteryID, KEY_VILLAGER_PERK_ID) end ---getNumberOfConditions ---@param mysteryID string the unique identifier of a mystery ---@return number how many conditions for the specified mystery function MysteriesData.getNumberOfConditions(mysteryID) local conditions = getFieldWhereID(mysteryID, KEY_CONDITIONS) if not conditions then return 0 else return #conditions end end ---getCategoryIDForCondition ---@param mysteryID string the unique identifier of a mystery ---@param conditionIndex number the index of the desired condition ---@return string the identifier of the category of the condition function MysteriesData.getCategoryIDForCondition(mysteryID, conditionIndex) return getFieldFromConditionWhereID(mysteryID, conditionIndex, KEY_CONDITIONS_CATEGORY_ID) end ---getCategoryNameForCondition ---@param mysteryID string the unique identifier of a mystery ---@param conditionIndex number the index of the desired condition ---@return string the name of the category of the condition function MysteriesData.getCategoryNameForCondition(mysteryID, conditionIndex) return getFieldFromConditionWhereID(mysteryID, conditionIndex, KEY_CONDITIONS_CATEGORY_ID) end ---getAmountForCondition ---@param mysteryID string the unique identifier of a mystery ---@param conditionIndex number the index of the desired condition ---@return number the number required to meet the condition function MysteriesData.getAmountForCondition(mysteryID, conditionIndex) return getFieldFromConditionWhereID(mysteryID, conditionIndex, KEY_CONDITIONS_AMOUNT) end function MysteriesData.getAllMysteryIDs() loadData() return listOfIDs end --endregion return MysteriesData