Module:AltarEffectsData

From Against the Storm Official Wiki

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

--- Serves data on Stormforged Cornerstones for the Forsaken Altar. Does not replace the use of PerksData for the icons, display names, descriptions, and more for these Cornerstones. Provides Forsaken Altar prices and defines the relationship to the regular version of the Cornerstone that the game uses to determine whether the Stormforged Cornerstone will be an upgrade (and therefore priced differently.)
---
---@module AltarEffectsData
local AltarEffectsData = {}



--region Dependencies

local JsonUtils = require("Module:JsonUtils")

--endregion



--region Private constants

local JSON_DATA_PAGE = "Template:Altar_Effects_json"

local ERROR_MESSAGE_ID_MISSING = "AltarEffectsData requires the unique identifier for a Cornerstone to get its data. Double-check what was passed as a parameter, because it was either missing, nil, or blank."
local ERROR_MESSAGE_OBJECT_MISSING_KEY_ID = "AltarEffectsData discovered a record in the data that did not contain the required field named `upgradedEffect`. This record is missing the necessary key-value pair that is used to index the data. Double-check that the data has not been modified from how it was originally supplied by the developers."
local ERROR_MESSAGE_EMPTY_LIST_OF_IDS = "AltarEffectsData attempted to build a list of the unique identifiers, but failed. Double-check the data was loaded correctly."

local KEY_PRICE_IN_VILLAGERS = "villagersPrice"
local KEY_UPGRADE_PRICE_IN_VILLAGERS = "villagersPriceUpgrade"
local KEY_PRICE_IN_META_RESOURCES = "metaValuePrice"
local KEY_UPGRADE_PRICE_IN_META_RESOURCES = "metaValuePriceUpgrade"
local KEY_CORNERSTONE_REGULAR_VERSION = "regularEffect"
local KEY_ALTAR_CORNERSTONE_ID = "upgradedEffect"

--endregion



--region Private member variables

local altarData
local listOfIDs
local mapOfUpgrades

--endregion



--region Private methods

--- Extracts all the unique identifiers into a separate list, and ensures this is only done once.
---
------ Works on and stores in the member variable.
---
local function buildMapOfUpgrades()

    if not mapOfUpgrades or #mapOfUpgrades < 1 then
        mapOfUpgrades = {}
        for upgradedID, _ in pairs(altarData) do
            -- Some are nil, and that's okay.
            local regularID = AltarEffectsData.getRegularVersionEffectID(upgradedID)
            if regularID and regularID ~= "" then
                mapOfUpgrades[regularID] = upgradedID
            end
        end
    end

    return mapOfUpgrades
end

--- Extracts all the unique identifiers into a separate list, and ensures this is only done once.
---
--- Works on and stores in the member variable.
---
local function buildListOfIDs()

    if not listOfIDs or #listOfIDs < 1 then
        listOfIDs = {}
        for id, _ in pairs(altarData) do
            table.insert(listOfIDs, id)
        end
    end

    -- This should never happen, but detecting a problem here could prevent hours of debugging.
    if not listOfIDs or #listOfIDs < 1 then
        error(ERROR_MESSAGE_EMPTY_LIST_OF_IDS)
    end
end

--- Simplifies looking up tables. Transforms a table containing tables, as we typically get from JSON. The parameter is expected to contain tables, each of which has a key that is the unique identifier of that table. Refer to the method body for the constant used. This identifier will be promoted to be the key for its record, rather than an index.
---
---@param tableOfTables table the data containing records, each with a field that is a unique identifier that should be promoted to be the key for each record
---@return table of tables, with new unique identifier keys
local function promoteKeys(tableOfTables)

    for i, record in ipairs(tableOfTables) do
        local key = record[KEY_ALTAR_CORNERSTONE_ID]
        if not key or "" == key then
            error(ERROR_MESSAGE_OBJECT_MISSING_KEY_ID)
        end
        tableOfTables[key] = record
        tableOfTables[i] = nil
    end

    return tableOfTables
end

--- Checks whether the Altar Effects data has been loaded yet. If not, handles that and the post-processing necessary.
---
local function loadData()

    if not altarData then
        altarData = JsonUtils.convertJSONToLuaTable(JSON_DATA_PAGE)
    end
    altarData = promoteKeys(altarData)
end

--- Retrieves exactly one effect table from the data.
---
--- Throws an error if the parameter is missing, nil, or empty.
---
--- Retrieving data should be done via the public getter methods, not by getting the entire table.
---
---@param effectID string the unique identifier of a Stormforged Cornerstone
---@return table the whole table row for that Cornerstone
local function getRecord(effectID)

    if not effectID or "" == effectID then
        error(ERROR_MESSAGE_ID_MISSING)
    else
        loadData()
        return altarData[effectID]
    end
end

--endregion



--region Public methods

---isIDValid
---@param effectID string the unique identifier of a Stormforged Cornerstone
---@return boolean true if there is a record with the specified identifier
function AltarEffectsData.isIDValid(effectID)

    if not effectID or "" == effectID then
        return false
    else
        local record = getRecord(effectID)
        return record ~= nil
    end
end

---getRegularVersionEffectID
---@param effectID string the unique identifier of a Stormforged Cornerstone
---@return string the unique identifier of a regular Cornerstone
function AltarEffectsData.getRegularVersionEffectID(effectID)

    local record = getRecord(effectID)
    return AltarEffectsData.isIDValid(effectID) and record[KEY_CORNERSTONE_REGULAR_VERSION] or nil
end

---getPriceInMetaResources
---@param effectID string the unique identifier of a Stormforged Cornerstone
---@return number the price to purchase the Cornerstone
function AltarEffectsData.getPriceInMetaResources(effectID)

    local record = getRecord(effectID)
    return AltarEffectsData.isIDValid(effectID) and record[KEY_PRICE_IN_META_RESOURCES] or nil
end

---getPriceInVillagers
---@param effectID string the unique identifier of a Stormforged Cornerstone
---@return number the price to purchase the Cornerstone
function AltarEffectsData.getPriceInVillagers(effectID)

    local record = getRecord(effectID)
    return AltarEffectsData.isIDValid(effectID) and record[KEY_PRICE_IN_VILLAGERS] or nil
end

---getUpgradePriceInMetaResources
---@param effectID string the unique identifier of a Stormforged Cornerstone
---@return number the price to purchase the upgrade to the regular version of the Cornerstone
function AltarEffectsData.getUpgradePriceInMetaResources(effectID)

    local record = getRecord(effectID)
    return AltarEffectsData.isIDValid(effectID) and record[KEY_UPGRADE_PRICE_IN_META_RESOURCES] or nil
end

---getUpgradePriceInVillagers
---@param effectID string the unique identifier of a Stormforged Cornerstone
---@return number the price to purchase the upgrade to the regular version of the Cornerstone
function AltarEffectsData.getUpgradePriceInVillagers(effectID)

    local record = getRecord(effectID)
    return AltarEffectsData.isIDValid(effectID) and record[KEY_UPGRADE_PRICE_IN_VILLAGERS] or nil
end

---getUpgradeWhereRegularID
---@param regularID string id of a regular Cornerstone
---@return string the id of the Stormforged Cornerstone that is the upgraded version of the specified regular Cornerstone, if any
function AltarEffectsData.getUpgradeWhereRegularID(regularID)

    loadData()
    buildMapOfUpgrades()

    return mapOfUpgrades[regularID]
end

---getAllAltarIDs
---@return table a flat table containing all the unique identifiers for Stormforged Cornerstones
function AltarEffectsData.getAllAltarIDs()

    loadData()
    buildListOfIDs()
    return listOfIDs
end

--endregion

return AltarEffectsData