Module:StormforgedController: Difference between revisions
From Against the Storm Official Wiki
m Added exclusion |
finished refactoring for list and inline display versions |
||
| (14 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
--- | --- | ||
--- | --- Serves the Stormforged Cornerstones template by capturing input and using it to control the display of data. | ||
--- | --- | ||
---@module StormforgedController | ---@module StormforgedController | ||
| Line 13: | Line 11: | ||
local AltarEffectsData = require("Module:AltarEffectsData") | local AltarEffectsData = require("Module:AltarEffectsData") | ||
local PerksData = require("Module:PerksData") | local PerksData = require("Module:PerksData") | ||
local ControllerUtilities = require("Module:ControllerUtilities") | |||
--endregion | --endregion | ||
| Line 20: | Line 20: | ||
--region Private constants | --region Private constants | ||
local | local ARG_ID_LIST = "id" | ||
local ARG_NAME = "name" | local ARG_NAME = "name" | ||
local | local ARG_DESCRIPTION = "description" | ||
local ARG_UPGRADABLE_ID = "upgrades_from_id" | |||
local ARGS_EXCLUDE_LIST = "exclude" | local ARGS_EXCLUDE_LIST = "exclude" | ||
local ARG_CAPTION = "caption" | local ARG_CAPTION = "caption" | ||
local ARG_SKIP_PRICES = "skip_prices" | local ARG_SKIP_PRICES = "skip_prices" | ||
local | local ARG_SKIP_FLAG_VALUE = "skip" | ||
local ARG_SHOW_ID = "show_id" | |||
local ARG_SHOW_DESCRIPTION = "show_description" | |||
local ARG_SHOW_REGULAR = "show_regular" | |||
local ARG_SHOW_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_ID = | local TEMPLATE_PARAMETER_CAPTION = ARG_CAPTION | ||
local TEMPLATE_PARAMETER_DESC = | local TEMPLATE_PARAMETER_ID = ARG_ID_LIST | ||
local TEMPLATE_PARAMETER_DESC = ARG_DESCRIPTION | |||
local TEMPLATE_PARAMETER_PRICE_META = "price_in_meta_resources" | local TEMPLATE_PARAMETER_PRICE_META = "price_in_meta_resources" | ||
local | local TEMPLATE_PARAMETER_PRICE_VILLAGER = "price_in_villagers" | ||
local | local TEMPLATE_PARAMETER_UPGRADE_META = "price_for_upgrade_in_meta_resources" | ||
local | local TEMPLATE_PARAMETER_UPGRADE_VILLAGER = "price_for_upgrade_in_villagers" | ||
local TEMPLATE_PARAMETER_SHOW_ID = ARG_SHOW_ID | |||
local | local TEMPLATE_PARAMETER_UPGRADE_FROM = "upgrades_from" | ||
local | local TEMPLATE_PARAMETER_LIST_TYPE = ARG_LIST_TYPE | ||
local | local TEMPLATE_PARAMETER_ICON_SIZE = "icon_size" | ||
local | local TEMPLATE_PARAMETER_ICON_SIZE_DEFAULT = "none" | ||
local | 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" | |||
--endregion | --endregion | ||
| Line 51: | Line 64: | ||
local currentFrame = {} | local currentFrame = {} | ||
local altarIDs = {} | local altarIDs = {} | ||
local isIDAlreadyAdded = {} | |||
--endregion | --endregion | ||
| Line 59: | Line 74: | ||
--region Private methods | --region Private methods | ||
--- | --- 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() | |||
local function | |||
for _, id in ipairs( | for _, id in ipairs(altarIDs) do | ||
--Validate the names. This should never happen, but this is here to save hours of troubleshooting. | --Validate the names. This should never happen, but this is here to save hours of troubleshooting. | ||
| Line 95: | Line 90: | ||
end | end | ||
--- Takes a list of possible IDs and only loads the valid ones (Stormforged ones) to the member variable | --- 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 newIDs table a list of possible IDs to add to main list | ||
| Line 102: | Line 97: | ||
for _, id in ipairs(newIDs) do | for _, id in ipairs(newIDs) do | ||
if AltarEffectsData.isIDValid(id) and not excludeList[id] then | if AltarEffectsData.isIDValid(id) and not excludeList[id] and not isIDAlreadyAdded[id] then | ||
table.insert(altarIDs, id) | table.insert(altarIDs, id) | ||
isIDAlreadyAdded[id] = true | |||
end | end | ||
end | 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 | --- Requests the desired lists of IDs from both AltarEffects and Perks data models, applies some post-processing, and stores them in the member variable altarIDs. | ||
--- | --- | ||
local function loadIDs( | ---@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) | |||
-- It should always be true, but it can be blank. | |||
if #selectList > 0 then | |||
attemptedSearch = true | attemptedSearch = true | ||
end | end | ||
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 | 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 | 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, PerksData.compareNames) | |||
end | end | ||
end | 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. | --- 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. | ||
| Line 172: | Line 165: | ||
--- 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 | ---@param desiredCaption string the caption requested, if any | ||
---@param selectList 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 | ---@param searchDesc string the third search parameter, a term in a description | ||
---@param | ---@param regularID string the id of the cornerstone that gets upgraded to a Stormforged version | ||
---@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( | local function resolveCaption(desiredCaption, selectList, searchName, searchDesc, regularID) | ||
-- No matter what, if the author provided a caption, use that. | |||
if desiredCaption and desiredCaption ~= "" then | if desiredCaption and desiredCaption ~= "" then | ||
return desiredCaption | return desiredCaption | ||
end | end | ||
-- If no selection, delegate to template. | |||
local addedToText = false | |||
desiredCaption = "" .. #altarIDs .. " Stormforged Cornerstones" | |||
if selectList and #selectList > 0 then | |||
if #selectList == 1 then | |||
desiredCaption = desiredCaption .. " with ID '" .. selectList[1] .. "'" | |||
else | |||
desiredCaption = desiredCaption .. " with selected IDs" | |||
end | |||
addedToText = true | |||
end | end | ||
if searchName and searchName ~= "" then | if searchName and searchName ~= "" then | ||
if addedToText then | |||
desiredCaption = desiredCaption .. " and" | |||
end | |||
desiredCaption = desiredCaption .. " named '" .. searchName .. "'" | |||
addedToText = true | |||
end | |||
if searchDesc and searchDesc ~= "" then | |||
if addedToText then | |||
desiredCaption = desiredCaption .. " and" | |||
end | |||
desiredCaption = desiredCaption .. " mentioning '" .. searchDesc .. "'" | |||
addedToText = true | |||
end | end | ||
if | |||
if regularID and regularID ~= "" then | |||
if addedToText then | |||
desiredCaption = desiredCaption .. " and" | |||
end | |||
desiredCaption = desiredCaption .. " upgraded from '" .. regularID .. "'" | |||
addedToText = true | |||
end | end | ||
-- Delegate to the template for the default | if excludeList and #excludeList > 0 then | ||
return "" | desiredCaption = desiredCaption .. " (with exclusions)" | ||
addedToText = true | |||
end | |||
if addedToText then | |||
return desiredCaption | |||
else | |||
-- Delegate to the template for the default | |||
return "" | |||
end | |||
end | |||
---resolveStartTemplate | |||
---@param isSkippingPrices boolean true if skipping variant should be used | |||
---@return string the template name to use | |||
local function resolveTableStartTemplate(isSkippingPrices) | |||
local suffixIfSkipping = (isSkippingPrices and TEMPLATE_TABLE_SKIP_PRICES_VARIANT) or "" | |||
return TEMPLATE_TABLE_BASE .. suffixIfSkipping | |||
end | |||
---resolveRowTemplate | |||
---@param isSkippingPrices boolean true if skipping variant should be used | |||
---@return string the template name to use | |||
local function resolveTableRowTemplate(isSkippingPrices) | |||
local suffixIfSkipping = (isSkippingPrices 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 | end | ||
| Line 200: | Line 259: | ||
--- | --- | ||
---@param desiredCaption string the caption for the table, if any | ---@param desiredCaption string the caption for the table, if any | ||
---@param | ---@param isSkippingPrices boolean true if skipping variant should be used | ||
---@return string the wiki markup | ---@param argsForTableTemplate table a set of arguments ready to pass through to the called template | ||
local function makeMarkupForTableStart(desiredCaption, | ---@return string the wiki markup assembled by the view (other templates) | ||
local function makeMarkupForTableStart(desiredCaption, isSkippingPrices, argsForTableTemplate) | |||
argsForTableTemplate[TEMPLATE_PARAMETER_CAPTION] = desiredCaption | |||
return currentFrame:expandTemplate{ | return currentFrame:expandTemplate{ title = resolveTableStartTemplate(isSkippingPrices), args = argsForTableTemplate } | ||
end | end | ||
--- Calls the view (other templates) to render a single row of the table with data based on the provided identifier. | --- 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 id string the unique identifier of a Stormforged Cornerstone to use to add data to a new table row | ||
---@return string the wiki markup | ---@param isSkippingPrices boolean true if skipping variant should be used | ||
local function makeMarkupPerRow( | ---@param argsForTableTemplate table a set of arguments ready to pass through to the called template | ||
---@return string the wiki markup assembled by the view (other templates) | |||
local function makeMarkupPerRow(id, isSkippingPrices, argsForTableTemplate) | |||
argsForTableTemplate[TEMPLATE_PARAMETER_ID] = id | |||
argsForTableTemplate[TEMPLATE_PARAMETER_DESC] = PerksData.getDescriptionByID(id) | |||
argsForTableTemplate[TEMPLATE_PARAMETER_UPGRADE_FROM] = AltarEffectsData.getRegularVersionEffectID(id) | |||
-- This is default, but adds a lot of extra template overhead if it's not needed, so only add it if necessary. | |||
if not isSkippingPrices then | |||
argsForTableTemplate[TEMPLATE_PARAMETER_PRICE_META] = AltarEffectsData.getPriceInMetaResources(id) | |||
argsForTableTemplate[TEMPLATE_PARAMETER_PRICE_VILLAGER] = AltarEffectsData.getPriceInVillagers(id) | |||
argsForTableTemplate[TEMPLATE_PARAMETER_UPGRADE_META] = AltarEffectsData.getUpgradePriceInMetaResources(id) | |||
argsForTableTemplate[TEMPLATE_PARAMETER_UPGRADE_VILLAGER] = AltarEffectsData.getUpgradePriceInVillagers(id) | |||
end | end | ||
return currentFrame:expandTemplate{ | return currentFrame:expandTemplate{ title = resolveTableRowTemplate(isSkippingPrices), args = argsForTableTemplate } | ||
end | end | ||
--- Handles assembling the rows for all of the IDs in the member variable list altarIDs. | --- Handles assembling the rows for all of the IDs in the member variable list altarIDs. | ||
--- | --- | ||
---@param | ---@param isSkippingPrices boolean true if skipping variant should be used | ||
---@return string the wiki markup | ---@param argsForTableTemplate table a set of arguments ready to pass through to the called template | ||
local function makeMarkupForTableRows( | ---@return string the wiki markup assembled by the view (other templates) | ||
local function makeMarkupForTableRows(isSkippingPrices, argsForTableTemplate) | |||
local markup = "" | local markup = "" | ||
for _, id in ipairs(altarIDs) do | for _, id in ipairs(altarIDs) do | ||
markup = markup .. makeMarkupPerRow( | markup = markup .. makeMarkupPerRow(id, isSkippingPrices, argsForTableTemplate) | ||
end | end | ||
| Line 257: | Line 310: | ||
--- Calls the view (other templates) to render the end of the table. | --- Calls the view (other templates) to render the end of the table. | ||
--- | --- | ||
---@return string the wiki markup | ---@return string the wiki markup assembled by the view (other templates) | ||
local function makeMarkupForTableEnd() | local function makeMarkupForTableEnd() | ||
return currentFrame:expandTemplate{ title = resolveTableEndTemplate(), args = {} } | |||
return currentFrame:expandTemplate{ | |||
end | end | ||
| Line 271: | Line 320: | ||
--- 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 desiredCaption table | ---@param desiredCaption string override the table caption | ||
---@param | ---@param isSkippingPrices boolean true if skipping variant should be used | ||
---@param argsForTableTemplate table a set of arguments ready to pass through to the called template | |||
---@return string the wiki markup assembled by the view (other templates) | |||
local function renderTable(desiredCaption, isSkippingPrices, argsForTableTemplate) | |||
local startMarkup = makeMarkupForTableStart(desiredCaption, isSkippingPrices, argsForTableTemplate) | |||
local rowsMarkup = makeMarkupForTableRows(isSkippingPrices, argsForTableTemplate) | |||
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 | |||
---@param isShowingID boolean true when needing to show the ID column | |||
---@return string the wiki markup assembled by the view (other templates) | |||
local function makeMarkupPerListItem(id, listType, isShowingID) | |||
local templateParameters = { | |||
[TEMPLATE_PARAMETER_ID] = id, | |||
[TEMPLATE_PARAMETER_LIST_TYPE] = listType, | |||
[TEMPLATE_PARAMETER_SHOW_ID] = isShowingID and ARG_SHOW_FLAG_VALUE | |||
} | |||
return currentFrame:expandTemplate{ title = TEMPLATE_LIST_ITEM, args = templateParameters } | |||
end | |||
---makeMarkupForListItems | |||
---@param listType string the type of list to create | |||
---@param isShowingID boolean true when needing to show the ID column | |||
---@return string the wiki markup assembled by the view (other templates) | |||
local function makeMarkupForListItems(listType, isShowingID) | |||
local markup = "" | |||
for _, id in ipairs(altarIDs) do | |||
markup = markup .. makeMarkupPerListItem(id, listType, isShowingID) | |||
end | |||
return markup | |||
end | |||
---renderList | |||
---@param listType string the type of list to create | |||
---@param isShowingID boolean true when needing to show the ID column | |||
---@return string the wiki markup assembled by the view (other templates) | |||
local function renderList(listType, isShowingID) | |||
return makeMarkupForListItems(listType, isShowingID) | |||
end | |||
---makeMarkupPerLink | |||
---@param id string the id of the cornerstone to display | |||
---@param isShowingID boolean true when needing to show the ID column | |||
---@return string the wiki markup assembled by the view (other templates) | ---@return string the wiki markup assembled by the view (other templates) | ||
local function | local function makeMarkupPerLink(id, isShowingID) | ||
local templateParameters = { | |||
[TEMPLATE_PARAMETER_ID] = id, | |||
[TEMPLATE_PARAMETER_ICON_SIZE] = TEMPLATE_PARAMETER_ICON_SIZE_DEFAULT, | |||
} | |||
local link = currentFrame:expandTemplate{ title = TEMPLATE_INLINE_LINK, args = templateParameters } | |||
if isShowingID then | |||
return link .. " ('" .. id .. "')" | |||
else | |||
return link | |||
end | |||
end | |||
---makeMarkupForInlineLinks | |||
---@param isShowingID boolean true when needing to show the ID column | |||
---@return string the wiki markup assembled by the view (other templates) | |||
local function makeMarkupForInlineLinks(isShowingID) | |||
if | local markup = "" | ||
for i, id in ipairs(altarIDs) do | |||
if i > 1 then | |||
markup = markup .. ", " | |||
end | |||
markup = markup .. makeMarkupPerLink(id, isShowingID) | |||
end | end | ||
return markup | |||
end | |||
---renderInline | |||
---@param isShowingID boolean true when needing to show the ID column | |||
---@return string the wiki markup assembled by the view (other templates) | |||
local function renderInlineLinks(isShowingID) | |||
return | return makeMarkupForInlineLinks(isShowingID) | ||
end | end | ||
| Line 298: | Line 426: | ||
function StormforgedController.main(frame) | function StormforgedController.main(frame) | ||
-- | -- Selection parameters | ||
local | local selectList = ControllerUtilities.expandCommaSeparatedStringsIntoTable(frame.args[ARG_ID_LIST], false) | ||
local excludeList = ControllerUtilities.expandCommaSeparatedStringsIntoTable(frame.args[ARGS_EXCLUDE_LIST], true) | |||
local searchName = frame.args[ARG_NAME] | local searchName = frame.args[ARG_NAME] | ||
local | local searchDesc = frame.args[ARG_DESCRIPTION] | ||
local | local regularID = frame.args[ARG_UPGRADABLE_ID] | ||
-- Display parameters | |||
local desiredCaption = frame.args[ARG_CAPTION] | local desiredCaption = frame.args[ARG_CAPTION] | ||
local | local displayOverride = frame.args[ARG_DISPLAY_OVERRIDE] | ||
local listType = frame.args[ARG_LIST_TYPE] | |||
local isSkippingPrices = ARG_SKIP_FLAG_VALUE == frame.args[ARG_SKIP_PRICES] | |||
local isShowingID = ARG_SHOW_FLAG_VALUE == frame.args[ARG_SHOW_ID] | |||
-- | -- For clarity, copy each value instead of reusing the whole args table. | ||
local argumentsToPassThroughToTable = { | |||
[ARG_SKIP_PRICES] = frame.args[ARG_SKIP_PRICES], | |||
[ARG_SHOW_ID] = frame.args[ARG_SHOW_ID], | |||
[ARG_SHOW_DESCRIPTION] = frame.args[ARG_SHOW_DESCRIPTION], | |||
[ARG_SHOW_REGULAR] = frame.args[ARG_SHOW_REGULAR] | |||
} | |||
currentFrame = frame | |||
if | |||
loadIDs(selectList, searchName, searchDesc, regularID, excludeList) | |||
if #altarIDs < 1 then | |||
return "No matching Stormforged Cornerstones found." | |||
end | end | ||
if displayOverride == ARG_DISPLAY_OVERRIDE_OPTION_LIST then | |||
return | return renderList(listType, isShowingID) | ||
end | |||
if displayOverride == ARG_DISPLAY_OVERRIDE_OPTION_INLINE then | |||
return renderInlineLinks(isShowingID) | |||
end | |||
-- Default display is table. | |||
desiredCaption = resolveCaption(desiredCaption, selectList, searchName, searchDesc, regularID) | |||
return renderTable(desiredCaption, isSkippingPrices, argumentsToPassThroughToTable) | |||
end | end | ||
Latest revision as of 03:38, 5 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")
local ControllerUtilities = require("Module:ControllerUtilities")
--endregion
--region Private constants
local ARG_ID_LIST = "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_FLAG_VALUE = "skip"
local ARG_SHOW_ID = "show_id"
local ARG_SHOW_DESCRIPTION = "show_description"
local ARG_SHOW_REGULAR = "show_regular"
local ARG_SHOW_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 = ARG_CAPTION
local TEMPLATE_PARAMETER_ID = ARG_ID_LIST
local TEMPLATE_PARAMETER_DESC = ARG_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_ID = ARG_SHOW_ID
local TEMPLATE_PARAMETER_UPGRADE_FROM = "upgrades_from"
local TEMPLATE_PARAMETER_LIST_TYPE = ARG_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"
--endregion
--region Private member variables
local currentFrame = {}
local altarIDs = {}
local isIDAlreadyAdded = {}
--endregion
--region Private methods
--- 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 desired lists of IDs from both AltarEffects and Perks data models, applies some post-processing, and stores them in the member variable altarIDs.
---
---@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)
-- It should always be true, but it can be blank.
if #selectList > 0 then
attemptedSearch = true
end
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, PerksData.compareNames)
end
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 desiredCaption string the caption requested, if any
---@param selectList 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
---@return string an appropriate caption, or blank if it should be default
local function resolveCaption(desiredCaption, selectList, searchName, searchDesc, regularID)
-- No matter what, if the author provided a caption, use that.
if desiredCaption and desiredCaption ~= "" then
return desiredCaption
end
-- If no selection, delegate to template.
local addedToText = false
desiredCaption = "" .. #altarIDs .. " Stormforged Cornerstones"
if selectList and #selectList > 0 then
if #selectList == 1 then
desiredCaption = desiredCaption .. " with ID '" .. selectList[1] .. "'"
else
desiredCaption = desiredCaption .. " with selected IDs"
end
addedToText = true
end
if searchName and searchName ~= "" then
if addedToText then
desiredCaption = desiredCaption .. " and"
end
desiredCaption = desiredCaption .. " named '" .. searchName .. "'"
addedToText = true
end
if searchDesc and searchDesc ~= "" then
if addedToText then
desiredCaption = desiredCaption .. " and"
end
desiredCaption = desiredCaption .. " mentioning '" .. searchDesc .. "'"
addedToText = true
end
if regularID and regularID ~= "" then
if addedToText then
desiredCaption = desiredCaption .. " and"
end
desiredCaption = desiredCaption .. " upgraded from '" .. regularID .. "'"
addedToText = true
end
if excludeList and #excludeList > 0 then
desiredCaption = desiredCaption .. " (with exclusions)"
addedToText = true
end
if addedToText then
return desiredCaption
else
-- Delegate to the template for the default
return ""
end
end
---resolveStartTemplate
---@param isSkippingPrices boolean true if skipping variant should be used
---@return string the template name to use
local function resolveTableStartTemplate(isSkippingPrices)
local suffixIfSkipping = (isSkippingPrices and TEMPLATE_TABLE_SKIP_PRICES_VARIANT) or ""
return TEMPLATE_TABLE_BASE .. suffixIfSkipping
end
---resolveRowTemplate
---@param isSkippingPrices boolean true if skipping variant should be used
---@return string the template name to use
local function resolveTableRowTemplate(isSkippingPrices)
local suffixIfSkipping = (isSkippingPrices 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 isSkippingPrices boolean true if skipping variant should be used
---@param argsForTableTemplate table a set of arguments ready to pass through to the called template
---@return string the wiki markup assembled by the view (other templates)
local function makeMarkupForTableStart(desiredCaption, isSkippingPrices, argsForTableTemplate)
argsForTableTemplate[TEMPLATE_PARAMETER_CAPTION] = desiredCaption
return currentFrame:expandTemplate{ title = resolveTableStartTemplate(isSkippingPrices), args = argsForTableTemplate }
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 isSkippingPrices boolean true if skipping variant should be used
---@param argsForTableTemplate table a set of arguments ready to pass through to the called template
---@return string the wiki markup assembled by the view (other templates)
local function makeMarkupPerRow(id, isSkippingPrices, argsForTableTemplate)
argsForTableTemplate[TEMPLATE_PARAMETER_ID] = id
argsForTableTemplate[TEMPLATE_PARAMETER_DESC] = PerksData.getDescriptionByID(id)
argsForTableTemplate[TEMPLATE_PARAMETER_UPGRADE_FROM] = AltarEffectsData.getRegularVersionEffectID(id)
-- This is default, but adds a lot of extra template overhead if it's not needed, so only add it if necessary.
if not isSkippingPrices then
argsForTableTemplate[TEMPLATE_PARAMETER_PRICE_META] = AltarEffectsData.getPriceInMetaResources(id)
argsForTableTemplate[TEMPLATE_PARAMETER_PRICE_VILLAGER] = AltarEffectsData.getPriceInVillagers(id)
argsForTableTemplate[TEMPLATE_PARAMETER_UPGRADE_META] = AltarEffectsData.getUpgradePriceInMetaResources(id)
argsForTableTemplate[TEMPLATE_PARAMETER_UPGRADE_VILLAGER] = AltarEffectsData.getUpgradePriceInVillagers(id)
end
return currentFrame:expandTemplate{ title = resolveTableRowTemplate(isSkippingPrices), args = argsForTableTemplate }
end
--- Handles assembling the rows for all of the IDs in the member variable list altarIDs.
---
---@param isSkippingPrices boolean true if skipping variant should be used
---@param argsForTableTemplate table a set of arguments ready to pass through to the called template
---@return string the wiki markup assembled by the view (other templates)
local function makeMarkupForTableRows(isSkippingPrices, argsForTableTemplate)
local markup = ""
for _, id in ipairs(altarIDs) do
markup = markup .. makeMarkupPerRow(id, isSkippingPrices, argsForTableTemplate)
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 isSkippingPrices boolean true if skipping variant should be used
---@param argsForTableTemplate table a set of arguments ready to pass through to the called template
---@return string the wiki markup assembled by the view (other templates)
local function renderTable(desiredCaption, isSkippingPrices, argsForTableTemplate)
local startMarkup = makeMarkupForTableStart(desiredCaption, isSkippingPrices, argsForTableTemplate)
local rowsMarkup = makeMarkupForTableRows(isSkippingPrices, argsForTableTemplate)
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
---@param isShowingID boolean true when needing to show the ID column
---@return string the wiki markup assembled by the view (other templates)
local function makeMarkupPerListItem(id, listType, isShowingID)
local templateParameters = {
[TEMPLATE_PARAMETER_ID] = id,
[TEMPLATE_PARAMETER_LIST_TYPE] = listType,
[TEMPLATE_PARAMETER_SHOW_ID] = isShowingID and ARG_SHOW_FLAG_VALUE
}
return currentFrame:expandTemplate{ title = TEMPLATE_LIST_ITEM, args = templateParameters }
end
---makeMarkupForListItems
---@param listType string the type of list to create
---@param isShowingID boolean true when needing to show the ID column
---@return string the wiki markup assembled by the view (other templates)
local function makeMarkupForListItems(listType, isShowingID)
local markup = ""
for _, id in ipairs(altarIDs) do
markup = markup .. makeMarkupPerListItem(id, listType, isShowingID)
end
return markup
end
---renderList
---@param listType string the type of list to create
---@param isShowingID boolean true when needing to show the ID column
---@return string the wiki markup assembled by the view (other templates)
local function renderList(listType, isShowingID)
return makeMarkupForListItems(listType, isShowingID)
end
---makeMarkupPerLink
---@param id string the id of the cornerstone to display
---@param isShowingID boolean true when needing to show the ID column
---@return string the wiki markup assembled by the view (other templates)
local function makeMarkupPerLink(id, isShowingID)
local templateParameters = {
[TEMPLATE_PARAMETER_ID] = id,
[TEMPLATE_PARAMETER_ICON_SIZE] = TEMPLATE_PARAMETER_ICON_SIZE_DEFAULT,
}
local link = currentFrame:expandTemplate{ title = TEMPLATE_INLINE_LINK, args = templateParameters }
if isShowingID then
return link .. " ('" .. id .. "')"
else
return link
end
end
---makeMarkupForInlineLinks
---@param isShowingID boolean true when needing to show the ID column
---@return string the wiki markup assembled by the view (other templates)
local function makeMarkupForInlineLinks(isShowingID)
local markup = ""
for i, id in ipairs(altarIDs) do
if i > 1 then
markup = markup .. ", "
end
markup = markup .. makeMarkupPerLink(id, isShowingID)
end
return markup
end
---renderInline
---@param isShowingID boolean true when needing to show the ID column
---@return string the wiki markup assembled by the view (other templates)
local function renderInlineLinks(isShowingID)
return makeMarkupForInlineLinks(isShowingID)
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 selectList = ControllerUtilities.expandCommaSeparatedStringsIntoTable(frame.args[ARG_ID_LIST], false)
local excludeList = ControllerUtilities.expandCommaSeparatedStringsIntoTable(frame.args[ARGS_EXCLUDE_LIST], true)
local searchName = frame.args[ARG_NAME]
local searchDesc = frame.args[ARG_DESCRIPTION]
local regularID = frame.args[ARG_UPGRADABLE_ID]
-- Display parameters
local desiredCaption = frame.args[ARG_CAPTION]
local displayOverride = frame.args[ARG_DISPLAY_OVERRIDE]
local listType = frame.args[ARG_LIST_TYPE]
local isSkippingPrices = ARG_SKIP_FLAG_VALUE == frame.args[ARG_SKIP_PRICES]
local isShowingID = ARG_SHOW_FLAG_VALUE == frame.args[ARG_SHOW_ID]
-- For clarity, copy each value instead of reusing the whole args table.
local argumentsToPassThroughToTable = {
[ARG_SKIP_PRICES] = frame.args[ARG_SKIP_PRICES],
[ARG_SHOW_ID] = frame.args[ARG_SHOW_ID],
[ARG_SHOW_DESCRIPTION] = frame.args[ARG_SHOW_DESCRIPTION],
[ARG_SHOW_REGULAR] = frame.args[ARG_SHOW_REGULAR]
}
currentFrame = frame
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, isShowingID)
end
if displayOverride == ARG_DISPLAY_OVERRIDE_OPTION_INLINE then
return renderInlineLinks(isShowingID)
end
-- Default display is table.
desiredCaption = resolveCaption(desiredCaption, selectList, searchName, searchDesc, regularID)
return renderTable(desiredCaption, isSkippingPrices, argumentsToPassThroughToTable)
end
--endregion
return StormforgedController


