Module:StormforgedController: Difference between revisions

From Against the Storm Official Wiki
m (forgot to remove a TODO comment that's all)
(Enabled selecting multiple ids instead of just one)
Line 126: Line 126:
--- Requests the lists of IDs from both AltarEffects and Perks data models, applies some post-processing, and stores them in the member variable.
--- Requests the lists of IDs from both AltarEffects and Perks data models, applies some post-processing, and stores them in the member variable.
---
---
---@param selectedID string the id of the cornerstone to include
---@param selectList table list of ids of the cornerstone to include
---@param searchName string search term to look in cornerstone names
---@param searchName string search term to look in cornerstone names
---@param searchDesc string search term to look in cornerstone descriptions
---@param searchDesc string search term to look in cornerstone descriptions
---@param regularID string the id of the cornerstone that gets upgraded to a Stormforged version
---@param regularID string the id of the cornerstone that gets upgraded to a Stormforged version
---@param excludeList table list of ids
---@param excludeList table list of ids
local function loadIDs(selectedID, searchName, searchDesc, regularID, excludeList)
local function loadIDs(selectList, searchName, searchDesc, regularID, excludeList)


     altarIDs = {}
     altarIDs = {}
Line 137: Line 137:
     local attemptedSearch = false
     local attemptedSearch = false


     -- Load the selected ID
     -- Load the selected IDs
     if selectedID and selectedID ~= "" then
     if selectList then
         loadStormforgedIDs( { selectedID }, excludeList )
         loadStormforgedIDs(selectList, excludeList)
         attemptedSearch = true
         attemptedSearch = true
     end
     end
Line 170: Line 170:


     if #altarIDs > 0 then
     if #altarIDs > 0 then
         -- Remove all IDs that aren't for Stormforged Cornerstones--there were probably extra pulled from PerksData if there were search terms.
         -- Remove all IDs that aren't for Stormforged Cornerstones--there will be extra regular Perks pulled from PerksData whenever there are search terms.
         validateNamesFromIDs()
         validateNamesFromIDs()
         --Alphabetize by name
         --Alphabetize by name
Line 177: Line 177:
end
end


---expandIDList
---@param stringOfIDs string the list of ids, separated by commas
---@param isFlags boolean true if the list should be made of keys and values of true, false if the list should be an array
---@return table the ids now as a table
local function expandIDList(stringOfIDs, isFlags)


---expandExclusions
     local list = {}
---@param exclusions string the list of ids, separated by commas
     for id in string.gmatch(stringOfIDs, "[^%s,][^,]+[^%s,]") do
---@return table the ids now as keys in the table and each value is `true`
         if isFlags then
local function expandExclusions(exclusions)
            list[id] = true
 
        else
     local excludeList = {}
            table.insert(list, id)
     for idToExclude in string.gmatch(exclusions, "[^,]+") do
        end
         excludeList[idToExclude] = true
     end
     end


     return excludeList
     return list
end
end


Line 196: Line 200:
--- If no caption was specified and also none of those filtering parameters, then leave it up to the template by returning a blank caption.
--- If no caption was specified and also none of those filtering parameters, then leave it up to the template by returning a blank caption.
---
---
---@param selectedID string the first search parameter, an id
---@param selectedList table list of ids of the cornerstone to include
---@param searchName string the second search parameter, a name
---@param searchName string the second search parameter, a name
---@param searchDesc string the third search parameter, a term in a description
---@param searchDesc string the third search parameter, a term in a description
Line 202: Line 206:
---@param desiredCaption string the caption requested, if any
---@param desiredCaption string the caption requested, if any
---@return string an appropriate caption, or blank if it should be default
---@return string an appropriate caption, or blank if it should be default
local function resolveCaption(selectedID, searchName, searchDesc, regularID, desiredCaption)
local function resolveCaption(selectedList, searchName, searchDesc, regularID, desiredCaption)


     if desiredCaption and desiredCaption ~= "" then
     if desiredCaption and desiredCaption ~= "" then
Line 208: Line 212:
     end
     end


     if selectedID and selectedID ~= "" then
     if selectedList and #selectedList > 1 then
         return "Stormforged Cornerstone with id '" .. selectedID .. "'"
        return #selectedList .. " selected Stormforged Cornerstones"
    else
        -- Don't have to check for empty; that's already handled before this with a "None found" message.
         return "Stormforged Cornerstone with id '" .. selectedList[1] .. "'"
     end
     end
     -- Do this first since mentioning could also imply name, but not the other way around.
     -- Do this first since mentioning could also imply name, but not the other way around.
Line 216: Line 223:
     end
     end
     if searchName and searchName ~= "" then
     if searchName and searchName ~= "" then
         return "Stormforged Cornerstones named '" .. searchName .. "'"
         return "Stormforged Cornerstones mentioning '" .. searchName .. "'"
     end
     end
     if regularID and regularID ~= "" then
     if regularID and regularID ~= "" then
Line 326: Line 333:
--- Calls several methods to build pieces of the table's markup based on the author's requests.
--- Calls several methods to build pieces of the table's markup based on the author's requests.
---
---
---@param selectedID string the id of the cornerstone to include
---@param searchName string search term to look in cornerstone names
---@param searchDesc string search term to look in cornerstone descriptions
---@param regularID string the id of the cornerstone that gets upgraded to a Stormforged version
---@param excludeList table list of ids
---@param desiredCaption string override the table caption
---@param desiredCaption string override the table caption
---@param skippingPrice string flag if some columns should be skipped
---@param skippingPrice string flag if some columns should be skipped
---@param showingRegular string flag if columns should be added
---@param showingRegular string flag if columns should be added
---@return string the wiki markup assembled by the view (other templates)
---@return string the wiki markup assembled by the view (other templates)
local function renderTable(selectedID, searchName, searchDesc, regularID, excludeList, desiredCaption, skippingPrice, showingRegular)
local function renderTable(desiredCaption, skippingPrice, showingRegular)
 
    loadIDs(selectedID, searchName, searchDesc, regularID, excludeList)
    if #altarIDs < 1 then
        return "No matching Stormforged Cornerstones found."
    end
 
    desiredCaption = resolveCaption(selectedID, searchName, searchDesc, regularID, desiredCaption)


     local startMarkup = makeMarkupForTableStart(desiredCaption, skippingPrice, showingRegular)
     local startMarkup = makeMarkupForTableStart(desiredCaption, skippingPrice, showingRegular)
Line 378: Line 373:


---renderList
---renderList
---@param selectedID string the id of the cornerstone to include
---@param searchName string search term to look in cornerstone names
---@param searchDesc string search term to look in cornerstone descriptions
---@param regularID string the id of the cornerstone that gets upgraded to a Stormforged version
---@param excludeList table list of ids
---@param listType string the type of list to create
---@param listType string the type of list to create
---@return string the wiki markup assembled by the view (other templates)
---@return string the wiki markup assembled by the view (other templates)
local function renderList(selectedID, searchName, searchDesc, regularID, excludeList, listType)
local function renderList(listType)
 
    loadIDs(selectedID, searchName, searchDesc, regularID, excludeList)
    if #altarIDs < 1 then
        return "No matching Stormforged Cornerstones found."
    end


     return makeMarkupForListItems(listType)
     return makeMarkupForListItems(listType)
Line 424: Line 409:


---renderInline
---renderInline
---@param selectedID string the id of the cornerstone to include
---@param searchName string search term to look in cornerstone names
---@param searchDesc string search term to look in cornerstone descriptions
---@param regularID string the id of the cornerstone that gets upgraded to a Stormforged version
---@param excludeList table list of ids
---@return string the wiki markup assembled by the view (other templates)
---@return string the wiki markup assembled by the view (other templates)
local function renderInlineLinks(selectedID, searchName, searchDesc, regularID, excludeList)
local function renderInlineLinks()
 
    loadIDs(selectedID, searchName, searchDesc, regularID, excludeList)
    if #altarIDs < 1 then
        return "No matching Stormforged Cornerstones found."
    end


     return makeMarkupForInlineLinks()
     return makeMarkupForInlineLinks()
Line 452: Line 427:


     -- Selection parameters
     -- Selection parameters
     local selectedID = frame.args[ARG_ID]
     local inclusions = frame.args[ARG_ID]
     local searchName = frame.args[ARG_NAME]
     local searchName = frame.args[ARG_NAME]
     local searchDesc = frame.args[ARG_DESCRIPTION]
     local searchDesc = frame.args[ARG_DESCRIPTION]
Line 465: Line 440:
     local listType = frame.args[ARG_LIST_TYPE]
     local listType = frame.args[ARG_LIST_TYPE]


    currentFrame = frame
    local selectList = {}
    if inclusions and inclusions ~= "" then
        selectList = expandIDList(inclusions, false)
    end
     local excludeList = {}
     local excludeList = {}
     if exclusions and exclusions ~= "" then
     if exclusions and exclusions ~= "" then
         excludeList = expandExclusions(exclusions)
         excludeList = expandIDList(exclusions, true)
     end
     end


     currentFrame = frame
     desiredCaption = resolveCaption(selectList, searchName, searchDesc, regularID, desiredCaption)
 
    loadIDs(selectList, searchName, searchDesc, regularID, excludeList)
    if #altarIDs < 1 then
        return "No matching Stormforged Cornerstones found."
    end


     if displayOverride == ARG_DISPLAY_OVERRIDE_OPTION_LIST then
     if displayOverride == ARG_DISPLAY_OVERRIDE_OPTION_LIST then
         return renderList(selectedID, searchName, searchDesc, regularID, excludeList, listType)
         return renderList(listType)
     end
     end
     if displayOverride == ARG_DISPLAY_OVERRIDE_OPTION_INLINE then
     if displayOverride == ARG_DISPLAY_OVERRIDE_OPTION_INLINE then
         return renderInlineLinks(selectedID, searchName, searchDesc, regularID, excludeList)
         return renderInlineLinks()
     end
     end
 
     return renderTable(desiredCaption, skippingPrice, showingRegular)
     return renderTable(selectedID, searchName, searchDesc, regularID, excludeList, desiredCaption, skippingPrice, showingRegular)


end
end

Revision as of 21:34, 2 May 2024

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

---
--- Serves the Stormforged Cornerstones template by capturing input and using it to control the display of data.
---
---@module StormforgedController
local StormforgedController = {}



--region Dependencies

local AltarEffectsData = require("Module:AltarEffectsData")
local PerksData = require("Module:PerksData")

--endregion



--region Private constants

local ARG_ID = "id"
local ARG_NAME = "name"
local ARG_DESCRIPTION = "description"
local ARG_UPGRADABLE_ID = "upgrades_from_id"
local ARGS_EXCLUDE_LIST = "exclude"
local ARG_CAPTION = "caption"
local ARG_SKIP_PRICES = "skip_prices"
local ARG_SKIP_PRICES_FLAG_VALUE = "skip"
local ARG_SHOW_REGULAR = "show_regular"
local ARG_SHOW_REGULAR_FLAG_VALUE = "show"
local ARG_DISPLAY_OVERRIDE = "display"
local ARG_DISPLAY_OVERRIDE_OPTION_LIST = "list"
local ARG_DISPLAY_OVERRIDE_OPTION_INLINE = "inline"
local ARG_LIST_TYPE = "list_type"

local TEMPLATE_PARAMETER_CAPTION = "caption"
local TEMPLATE_PARAMETER_SKIP_PRICES = "skip_prices"
local TEMPLATE_PARAMETER_ID = "id"
local TEMPLATE_PARAMETER_DESC = "description"
local TEMPLATE_PARAMETER_PRICE_META = "price_in_meta_resources"
local TEMPLATE_PARAMETER_PRICE_VILLAGER = "price_in_villagers"
local TEMPLATE_PARAMETER_UPGRADE_META = "price_for_upgrade_in_meta_resources"
local TEMPLATE_PARAMETER_UPGRADE_VILLAGER = "price_for_upgrade_in_villagers"
local TEMPLATE_PARAMETER_SHOW_REGULAR = "show_regular"
local TEMPLATE_PARAMETER_UPGRADE_FROM = "upgrades_from"
local TEMPLATE_PARAMETER_LIST_TYPE = "list_type"
local TEMPLATE_PARAMETER_ICON_SIZE = "icon_size"
local TEMPLATE_PARAMETER_ICON_SIZE_DEFAULT = "none"

local TEMPLATE_TABLE_BASE = "StormforgedCornerstonesTable"
local TEMPLATE_TABLE_SUFFIX_ROW = "/row"
local TEMPLATE_TABLE_SUFFIX_END = "/end"
local TEMPLATE_TABLE_SKIP_PRICES_VARIANT = "/SkipPrices"
local TEMPLATE_LIST_ITEM = "StormforgedCornerstonesList/item"
local TEMPLATE_INLINE_LINK = "pl"

local ERROR_PREFIX_NAME_NOT_FOUND = "StormforgedController attempted to retrieve the display name of a Stormforged Cornerstones, but it was not found. Double-check that the data is up-to-date and loaded correctly:"

--endregion



--region Private member variables

local currentFrame = {}
local altarIDs = {}
local isIDAlreadyAdded = {}

--endregion



--region Private methods

--- Helper comparison function to give to table.sort to sort the perk names alphabetically that correspond to the identifiers of Stormforged Cornerstones.
---
---@param altarID1 string the identifier of a Stormforged Cornerstone
---@param altarID2 string the identifier of a Stormforged Cornerstone
---@return boolean to sort the corresponding display names alphabetically
local function compareNames(altarID1, altarID2)

    local name1 = PerksData.getNameByID(altarID1)
    local name2 = PerksData.getNameByID(altarID2)

    if not name1 then
        error(ERROR_PREFIX_NAME_NOT_FOUND .. " id=" .. altarID1 .. ".")
    end
    if not name2 then
        error(ERROR_PREFIX_NAME_NOT_FOUND .. " id=" .. altarID2 .. ".")

    end

    return name1 < name2
end

--- Runs through the list of perk IDs and checks that a name exists for each one. If not, it throws an error identifying the offending ID.
---
--- Works from the member variable altarIDs
---
local function validateNamesFromIDs()

    for _, id in ipairs(altarIDs) do

       --Validate the names. This should never happen, but this is here to save hours of troubleshooting.
        local name = PerksData.getNameByID(id)
        if not name then
            error(ERROR_PREFIX_NAME_NOT_FOUND .. "id=" .. id)
        end
    end
end

--- Takes a list of possible IDs and only loads the valid ones (Stormforged ones) to the member variable altarIDs. Skips all ids present in the exclude list.
---
---@param newIDs table a list of possible IDs to add to main list
---@param excludeList table where keys are ids to skip and the values are `true`
local function loadStormforgedIDs(newIDs, excludeList)

    for _, id in ipairs(newIDs) do
        if AltarEffectsData.isIDValid(id) and not excludeList[id] and not isIDAlreadyAdded[id] then

            table.insert(altarIDs, id)
            isIDAlreadyAdded[id] = true
        end
    end
end

--- Requests the lists of IDs from both AltarEffects and Perks data models, applies some post-processing, and stores them in the member variable.
---
---@param selectList table list of ids of the cornerstone to include
---@param searchName string search term to look in cornerstone names
---@param searchDesc string search term to look in cornerstone descriptions
---@param regularID string the id of the cornerstone that gets upgraded to a Stormforged version
---@param excludeList table list of ids
local function loadIDs(selectList, searchName, searchDesc, regularID, excludeList)

    altarIDs = {}
    isIDAlreadyAdded = {}
    local attemptedSearch = false

    -- Load the selected IDs
    if selectList then
        loadStormforgedIDs(selectList, excludeList)
        attemptedSearch = true
    end

    -- Add any name matches
    if searchName and searchName ~= "" then
        local newIDs = PerksData.getAllPerkIDsWhereName(searchName)
        loadStormforgedIDs(newIDs, excludeList)
        attemptedSearch = true
    end

    -- Add any description matches
    if searchDesc and searchDesc ~= "" then
        local newIDs = PerksData.getAllPerkIDsWhereDescription(searchDesc)
        loadStormforgedIDs(newIDs, excludeList)
        attemptedSearch = true
    end

    -- Add any upgrade matches
    if regularID and regularID ~= "" then
        loadStormforgedIDs({ AltarEffectsData.getUpgradeWhereRegularID(regularID) }, excludeList)
        attemptedSearch = true
    end

    -- Or, if no searching was even attempted (regardless of result), show them all
    if not attemptedSearch then
        local newIDs = AltarEffectsData.getAllAltarIDs()
        loadStormforgedIDs(newIDs, excludeList)
    end

    if #altarIDs > 0 then
        -- Remove all IDs that aren't for Stormforged Cornerstones--there will be extra regular Perks pulled from PerksData whenever there are search terms.
        validateNamesFromIDs()
        --Alphabetize by name
        table.sort(altarIDs, compareNames)
    end
end

---expandIDList
---@param stringOfIDs string the list of ids, separated by commas
---@param isFlags boolean true if the list should be made of keys and values of true, false if the list should be an array
---@return table the ids now as a table
local function expandIDList(stringOfIDs, isFlags)

    local list = {}
    for id in string.gmatch(stringOfIDs, "[^%s,][^,]+[^%s,]") do
        if isFlags then
            list[id] = true
        else
            table.insert(list, id)
        end
    end

    return list
end


--- Ensures that if a caption is not defined, there is a suitable fallback in case the author has specified an id, name, or search term to use, so readers know what they're looking at.
---
--- If no caption was specified and also none of those filtering parameters, then leave it up to the template by returning a blank caption.
---
---@param selectedList table list of ids of the cornerstone to include
---@param searchName string the second search parameter, a name
---@param searchDesc string the third search parameter, a term in a description
---@param regularID string the id of the cornerstone that gets upgraded to a Stormforged version
---@param desiredCaption string the caption requested, if any
---@return string an appropriate caption, or blank if it should be default
local function resolveCaption(selectedList, searchName, searchDesc, regularID, desiredCaption)

    if desiredCaption and desiredCaption ~= "" then
        return desiredCaption
    end

    if selectedList and #selectedList > 1 then
        return #selectedList .. " selected Stormforged Cornerstones"
    else
        -- Don't have to check for empty; that's already handled before this with a "None found" message.
        return "Stormforged Cornerstone with id '" .. selectedList[1] .. "'"
    end
    -- Do this first since mentioning could also imply name, but not the other way around.
    if searchDesc and searchDesc ~= "" then
        return "Stormforged Cornerstones mentioning '" .. searchDesc .. "'"
    end
    if searchName and searchName ~= "" then
        return "Stormforged Cornerstones mentioning '" .. searchName .. "'"
    end
    if regularID and regularID ~= "" then
        return "Stormforged Cornerstone upgraded from '" .. regularID .. "'"
    end

    -- Delegate to the template for the default
    return ""
end

---resolveStartTemplate
---@param skippingPrice string the flag deciding whether to skip some columns
---@return string the template name to use
local function resolveTableStartTemplate(skippingPrice)

    local suffixIfSkipping = (skippingPrice == ARG_SKIP_PRICES_FLAG_VALUE and TEMPLATE_TABLE_SKIP_PRICES_VARIANT) or ""

    return TEMPLATE_TABLE_BASE .. suffixIfSkipping
end

---resolveRowTemplate
---@param skippingPrice string the flag deciding whether to skip some columns
---@return string the template name to use
local function resolveTableRowTemplate(skippingPrice)

    local suffixIfSkipping = (skippingPrice == ARG_SKIP_PRICES_FLAG_VALUE and TEMPLATE_TABLE_SKIP_PRICES_VARIANT) or ""

    return TEMPLATE_TABLE_BASE .. TEMPLATE_TABLE_SUFFIX_ROW .. suffixIfSkipping
end

---resolveEndTemplate
---@return string the template name to use
local function resolveTableEndTemplate()

    return TEMPLATE_TABLE_BASE .. TEMPLATE_TABLE_SUFFIX_END
end

--- Calls the view (other templates) to render the beginning of the table.
---
---@param desiredCaption string the caption for the table, if any
---@param skippingPrice string the flag for skipping prices in the table, if any
---@param showingRegular string flag if columns should be added
---@return string the wiki markup assembled by the view (other templates)
local function makeMarkupForTableStart(desiredCaption, skippingPrice, showingRegular)

    local templateParameters = {
        [TEMPLATE_PARAMETER_CAPTION] = desiredCaption,
        [TEMPLATE_PARAMETER_SKIP_PRICES] = skippingPrice,
        [TEMPLATE_PARAMETER_SHOW_REGULAR] = showingRegular
    }

    return currentFrame:expandTemplate{ title = resolveTableStartTemplate(skippingPrice), args = templateParameters }
end

--- Calls the view (other templates) to render a single row of the table with data based on the provided identifier.
---
---@param id string the unique identifier of a Stormforged Cornerstone to use to add data to a new table row
---@param skippingPrice string the flag for skipping prices in the table, if any
---@param showingRegular string flag if columns should be added
---@return string the wiki markup assembled by the view (other templates)
local function makeMarkupPerRow(id, skippingPrice, showingRegular)

    local templateParameters = {
        [TEMPLATE_PARAMETER_ID] = id,
        [TEMPLATE_PARAMETER_DESC] = PerksData.getDescriptionByID(id),
        [TEMPLATE_PARAMETER_SHOW_REGULAR] = showingRegular
    }

    -- If showing this column, we need this data for all rows, since the author may have searched for other names or descriptions.
    if showingRegular == ARG_SHOW_REGULAR_FLAG_VALUE then
        templateParameters[TEMPLATE_PARAMETER_UPGRADE_FROM] = AltarEffectsData.getRegularVersionEffectID(id)
    end

    if skippingPrice ~= ARG_SKIP_PRICES_FLAG_VALUE then
        templateParameters[TEMPLATE_PARAMETER_PRICE_META] = AltarEffectsData.getPriceInMetaResources(id)
        templateParameters[TEMPLATE_PARAMETER_PRICE_VILLAGER] = AltarEffectsData.getPriceInVillagers(id)
        templateParameters[TEMPLATE_PARAMETER_UPGRADE_META] = AltarEffectsData.getUpgradePriceInMetaResources(id)
        templateParameters[TEMPLATE_PARAMETER_UPGRADE_VILLAGER] = AltarEffectsData.getUpgradePriceInVillagers(id)
    end

    return currentFrame:expandTemplate{ title = resolveTableRowTemplate(skippingPrice), args = templateParameters }
end

--- Handles assembling the rows for all of the IDs in the member variable list altarIDs.
---
---@param skippingPrice string the flag for skipping prices in the table, if any
---@param showingRegular string flag if columns should be added
---@return string the wiki markup assembled by the view (other templates)
local function makeMarkupForTableRows(skippingPrice, showingRegular)

    local markup = ""
    for _, id in ipairs(altarIDs) do
        markup = markup .. makeMarkupPerRow(id, skippingPrice, showingRegular)
    end

    return markup
end

--- Calls the view (other templates) to render the end of the table.
---
---@return string the wiki markup assembled by the view (other templates)
local function makeMarkupForTableEnd()

    return currentFrame:expandTemplate{ title = resolveTableEndTemplate(), args = {} }
end

---Calls the view (other templates) to render the content and appends it to the wiki markup string that will replace this controller's template.
---
--- Calls several methods to build pieces of the table's markup based on the author's requests.
---
---@param desiredCaption string override the table caption
---@param skippingPrice string flag if some columns should be skipped
---@param showingRegular string flag if columns should be added
---@return string the wiki markup assembled by the view (other templates)
local function renderTable(desiredCaption, skippingPrice, showingRegular)

    local startMarkup = makeMarkupForTableStart(desiredCaption, skippingPrice, showingRegular)
    local rowsMarkup =  makeMarkupForTableRows(skippingPrice, showingRegular)

    return startMarkup .. rowsMarkup .. makeMarkupForTableEnd()
end

---makeMarkupPerListITem
---@param id string the id of the cornerstone to display
---@param listType string the type of list to create
---@return string the wiki markup assembled by the view (other templates)
local function makeMarkupPerListItem(id, listType)

    local templateParameters = {
        [TEMPLATE_PARAMETER_ID] = id,
        [TEMPLATE_PARAMETER_LIST_TYPE] = listType
    }

    return currentFrame:expandTemplate{ title = TEMPLATE_LIST_ITEM, args = templateParameters }
end

---makeMarkupForListItems
---@param listType string the type of list to create
---@return string the wiki markup assembled by the view (other templates)
local function makeMarkupForListItems(listType)

    local markup = ""
    for _, id in ipairs(altarIDs) do
        markup = markup .. makeMarkupPerListItem(id, listType)
    end

    return markup
end

---renderList
---@param listType string the type of list to create
---@return string the wiki markup assembled by the view (other templates)
local function renderList(listType)

    return makeMarkupForListItems(listType)
end

---makeMarkupPerLink
---@param id string the id of the cornerstone to display
---@return string the wiki markup assembled by the view (other templates)
local function makeMarkupPerLink(id)

    local templateParameters = {
        [TEMPLATE_PARAMETER_ID] = id,
        [TEMPLATE_PARAMETER_ICON_SIZE] = TEMPLATE_PARAMETER_ICON_SIZE_DEFAULT
    }

    return currentFrame:expandTemplate{ title = TEMPLATE_INLINE_LINK, args = templateParameters }
end

---makeMarkupForInlineLinks
---@return string the wiki markup assembled by the view (other templates)
local function makeMarkupForInlineLinks()

    local markup = ""
    for i, id in ipairs(altarIDs) do
        if i > 1 then
            markup = markup .. ", "
        end
        markup = markup .. makeMarkupPerLink(id)
    end

    return markup
end

---renderInline
---@return string the wiki markup assembled by the view (other templates)
local function renderInlineLinks()

    return makeMarkupForInlineLinks()
end

--endregion



--region Public methods

---main
---@param frame table the MediaWiki frame provided by the template call
---@return string wiki markup to display
function StormforgedController.main(frame)

    -- Selection parameters
    local inclusions = frame.args[ARG_ID]
    local searchName = frame.args[ARG_NAME]
    local searchDesc = frame.args[ARG_DESCRIPTION]
    local regularID = frame.args[ARG_UPGRADABLE_ID]
    local exclusions = frame.args[ARGS_EXCLUDE_LIST]

    -- Display parameters
    local displayOverride = frame.args[ARG_DISPLAY_OVERRIDE]
    local desiredCaption = frame.args[ARG_CAPTION]
    local skippingPrice = frame.args[ARG_SKIP_PRICES]
    local showingRegular = frame.args[ARG_SHOW_REGULAR]
    local listType = frame.args[ARG_LIST_TYPE]

    currentFrame = frame

    local selectList = {}
    if inclusions and inclusions ~= "" then
        selectList = expandIDList(inclusions, false)
    end
    local excludeList = {}
    if exclusions and exclusions ~= "" then
        excludeList = expandIDList(exclusions, true)
    end

    desiredCaption = resolveCaption(selectList, searchName, searchDesc, regularID, desiredCaption)

    loadIDs(selectList, searchName, searchDesc, regularID, excludeList)
    if #altarIDs < 1 then
        return "No matching Stormforged Cornerstones found."
    end

    if displayOverride == ARG_DISPLAY_OVERRIDE_OPTION_LIST then
        return renderList(listType)
    end
    if displayOverride == ARG_DISPLAY_OVERRIDE_OPTION_INLINE then
        return renderInlineLinks()
    end
    return renderTable(desiredCaption, skippingPrice, showingRegular)

end

--endregion

return StormforgedController