Module:MysteriesData: Difference between revisions

From Against the Storm Official Wiki
(Created to serve forest mysteries data)
 
(Basics are ready)
Line 20: Line 20:


-- Keys in both
-- Keys in both
local KEY_ID = "id"
local KEY_DISPLAY_NAME = "displayName"
local KEY_DISPLAY_NAME = "displayName"
local KEY_DESCRIPTION = "description"
local KEY_DESCRIPTION = "description"
Line 42: Line 43:


local IS_VALID_KEY = {
local IS_VALID_KEY = {
    [KEY_ID] = true,
     [KEY_DISPLAY_NAME] = true,
     [KEY_DISPLAY_NAME] = true,
     [KEY_DESCRIPTION] = true,
     [KEY_DESCRIPTION] = true,
Line 74: Line 76:


local mysteriesData
local mysteriesData
local listOfIDs


--endregion
--endregion
Line 85: Line 88:
local function loadData()
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
     if not mysteriesData then
        mysteriesData = {}
        listOfIDs = {}
         local data1 = JsonUtils.convertJSONToLuaTable(JSON_DATA_PAGE_1)
         local data1 = JsonUtils.convertJSONToLuaTable(JSON_DATA_PAGE_1)
         local data2 = JsonUtils.convertJSONToLuaTable(JSON_DATA_PAGE_2)
         local data2 = JsonUtils.convertJSONToLuaTable(JSON_DATA_PAGE_2)


         for mysteryID, mysteryRecord in pairs(data2) do
        -- Store the mysteries by their ID, but also create a simple array of all IDs since we're already looping over them all.
             -- Validate that there are no duplicate IDs in the two tables.
        local i = 1
         for _, record1 in ipairs(data1) do
            local mysteryID = record1[KEY_ID]
            mysteriesData[mysteryID] = record1
            listOfIDs[i] = mysteryID
            i = i + 1
        end
 
        for _, record2 in ipairs(data2) do
            local mysteryID = record2[KEY_ID]
             -- Validate that there are no duplicate IDs in the final table.
             if nil ~= mysteriesData[mysteryID] then
             if nil ~= mysteriesData[mysteryID] then
                 error(ERROR_MESSAGE_UNEXPECTED_DUPLICATE_ID_ON_MERGE)
                 error(ERROR_MESSAGE_UNEXPECTED_DUPLICATE_ID_ON_MERGE .. "\n id=" .. mysteryID)
             else
             else
                 -- Combine.
                 mysteriesData[mysteryID] = record2
                 data1[mysteryID] = mysteryRecord
                 listOfIDs[i] = mysteryID
                i = i + 1
             end
             end
         end
         end
        mysteriesData = data1
     end
     end
end
end
Line 315: Line 332:
--endregion
--endregion


return AltarEffectsData
return MysteriesData

Revision as of 23:37, 5 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"

-- 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."

--endregion



--region Private member variables

local mysteriesData
local listOfIDs

--endregion



--region Private methods

--- 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 = {}

        local data1 = JsonUtils.convertJSONToLuaTable(JSON_DATA_PAGE_1)
        local data2 = JsonUtils.convertJSONToLuaTable(JSON_DATA_PAGE_2)

        -- 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 = 1
        for _, record1 in ipairs(data1) do
            local mysteryID = record1[KEY_ID]
            mysteriesData[mysteryID] = record1
            listOfIDs[i] = mysteryID
            i = i + 1
        end

        for _, record2 in ipairs(data2) do
            local mysteryID = record2[KEY_ID]
            -- Validate that there are no duplicate IDs in the final table.
            if nil ~= mysteriesData[mysteryID] then
                error(ERROR_MESSAGE_UNEXPECTED_DUPLICATE_ID_ON_MERGE .. "\n id=" .. mysteryID)
            else
                mysteriesData[mysteryID] = record2
                listOfIDs[i] = mysteryID
                i = i + 1
            end
        end
    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)
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)
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)
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)
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

---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

--endregion

return MysteriesData