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 | ---@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( | local function loadIDs(selectList, searchName, searchDesc, regularID, excludeList) | ||
altarIDs = {} | altarIDs = {} | ||
Line 137: | Line 137: | ||
local attemptedSearch = false | local attemptedSearch = false | ||
-- Load the selected | -- Load the selected IDs | ||
if | if selectList then | ||
loadStormforgedIDs( | 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 | -- 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) | |||
local list = {} | |||
for id in string.gmatch(stringOfIDs, "[^%s,][^,]+[^%s,]") do | |||
if isFlags then | |||
list[id] = true | |||
else | |||
local | table.insert(list, id) | ||
for | end | ||
end | end | ||
return | 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 | ---@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( | 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 | if selectedList and #selectedList > 1 then | ||
return "Stormforged Cornerstone with id '" .. | 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 | 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 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( | local function renderTable(desiredCaption, skippingPrice, showingRegular) | ||
local startMarkup = makeMarkupForTableStart(desiredCaption, skippingPrice, showingRegular) | local startMarkup = makeMarkupForTableStart(desiredCaption, skippingPrice, showingRegular) | ||
Line 378: | Line 373: | ||
---renderList | ---renderList | ||
---@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( | local function renderList(listType) | ||
return makeMarkupForListItems(listType) | return makeMarkupForListItems(listType) | ||
Line 424: | Line 409: | ||
---renderInline | ---renderInline | ||
---@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( | local function renderInlineLinks() | ||
return makeMarkupForInlineLinks() | return makeMarkupForInlineLinks() | ||
Line 452: | Line 427: | ||
-- Selection parameters | -- Selection parameters | ||
local | 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 = | excludeList = expandIDList(exclusions, true) | ||
end | 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 | if displayOverride == ARG_DISPLAY_OVERRIDE_OPTION_LIST then | ||
return renderList( | return renderList(listType) | ||
end | end | ||
if displayOverride == ARG_DISPLAY_OVERRIDE_OPTION_INLINE then | if displayOverride == ARG_DISPLAY_OVERRIDE_OPTION_INLINE then | ||
return renderInlineLinks( | return renderInlineLinks() | ||
end | end | ||
return renderTable(desiredCaption, skippingPrice, showingRegular) | |||
return renderTable( | |||
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