Module:StormforgedController: Difference between revisions
From Against the Storm Official Wiki
(Created to serve a stormforged cornerstone template based on table templates) |
m (Added exclusion) |
||
Line 23: | Line 23: | ||
local ARG_NAME = "name" | local ARG_NAME = "name" | ||
local ARG_SEARCH = "search" | local ARG_SEARCH = "search" | ||
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" | ||
Line 94: | Line 95: | ||
end | end | ||
--- Takes a list of possible IDs and only loads the valid ones (Stormforged ones) to the member variable altardIDs. | --- Takes a list of possible IDs and only loads the valid ones (Stormforged ones) to the member variable altardIDs. 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 | ||
local function loadStormforgedIDs(newIDs) | ---@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 | for _, id in ipairs(newIDs) do | ||
if AltarEffectsData.isIDValid(id) then | if AltarEffectsData.isIDValid(id) and not excludeList[id] then | ||
table.insert(altarIDs, id) | table.insert(altarIDs, id) | ||
end | end | ||
Line 108: | Line 110: | ||
--- Requests the lists of IDs from both AltarEffects and Perks data models, applies some post-processing, and stores them in the member variables. | --- Requests the lists of IDs from both AltarEffects and Perks data models, applies some post-processing, and stores them in the member variables. | ||
--- | --- | ||
local function loadIDs(selectedID, searchName, searchTerm) | local function loadIDs(selectedID, searchName, searchTerm, excludeList) | ||
if not altarIDs or #altarIDs < 1 then | if not altarIDs or #altarIDs < 1 then | ||
Line 117: | Line 119: | ||
-- Load the selected ID | -- Load the selected ID | ||
if selectedID and selectedID ~= "" then | if selectedID and selectedID ~= "" then | ||
loadStormforgedIDs( { selectedID } ) | loadStormforgedIDs( { selectedID }, excludeList ) | ||
attemptedSearch = true | attemptedSearch = true | ||
end | end | ||
Line 124: | Line 126: | ||
if searchName and searchName ~= "" then | if searchName and searchName ~= "" then | ||
local newIDs = PerksData.getAllPerkIDsWhereName(searchName) | local newIDs = PerksData.getAllPerkIDsWhereName(searchName) | ||
loadStormforgedIDs(newIDs) | loadStormforgedIDs(newIDs, excludeList) | ||
attemptedSearch = true | attemptedSearch = true | ||
end | end | ||
Line 131: | Line 133: | ||
if searchTerm and searchTerm ~= "" then | if searchTerm and searchTerm ~= "" then | ||
local newIDs = PerksData.getAllPerkIDsWhereDescription(searchTerm) | local newIDs = PerksData.getAllPerkIDsWhereDescription(searchTerm) | ||
loadStormforgedIDs(newIDs) | loadStormforgedIDs(newIDs, excludeList) | ||
attemptedSearch = true | attemptedSearch = true | ||
end | end | ||
Line 150: | Line 152: | ||
end | end | ||
end | end | ||
---expandExclusions | |||
---@param exclusions string the list of ids, separated by commas | |||
---@return table the ids now as keys in the table and each value is `true` | |||
local function expandExclusions(exclusions) | |||
local excludeList = {} | |||
for idToExclude in string.gmatch(exclusions, "[^,]+") do | |||
excludeList[idToExclude] = true | |||
end | |||
return excludeList | |||
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 257: | Line 274: | ||
---@param skippingPrice table | ---@param skippingPrice table | ||
---@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, searchTerm, desiredCaption, skippingPrice) | local function renderTable(selectedID, searchName, searchTerm, excludeList, desiredCaption, skippingPrice) | ||
loadIDs(selectedID, searchName, searchTerm) | loadIDs(selectedID, searchName, searchTerm, excludeList) | ||
if #altarIDs < 1 then | if #altarIDs < 1 then | ||
Line 267: | Line 284: | ||
desiredCaption = resolveCaption(selectedID, searchName, searchTerm, desiredCaption) | desiredCaption = resolveCaption(selectedID, searchName, searchTerm, desiredCaption) | ||
return makeMarkupForTableStart(desiredCaption, skippingPrice) .. makeMarkupForTableRows(skippingPrice) .. makeMarkupForTableEnd() | return makeMarkupForTableStart(desiredCaption, skippingPrice) .. makeMarkupForTableRows(skippingPrice) .. "\n" .. makeMarkupForTableEnd() | ||
end | end | ||
Line 285: | Line 302: | ||
local searchName = frame.args[ARG_NAME] | local searchName = frame.args[ARG_NAME] | ||
local searchTerm = frame.args[ARG_SEARCH] | local searchTerm = frame.args[ARG_SEARCH] | ||
local exclusions = frame.args[ARGS_EXCLUDE_LIST] | |||
local desiredCaption = frame.args[ARG_CAPTION] | local desiredCaption = frame.args[ARG_CAPTION] | ||
local skippingPrice = frame.args[ARG_SKIP_PRICES] | local skippingPrice = frame.args[ARG_SKIP_PRICES] | ||
--TODO make displayOverride == DISPLAY_OPTION_LIST | --TODO make displayOverride == DISPLAY_OPTION_LIST | ||
local excludeList = {} | |||
if exclusions and exclusions ~= "" then | |||
excludeList = expandExclusions(exclusions) | |||
end | |||
currentFrame = frame | currentFrame = frame | ||
return renderTable(selectedID, searchName, searchTerm, desiredCaption, skippingPrice) | return renderTable(selectedID, searchName, searchTerm, excludeList, desiredCaption, skippingPrice) | ||
end | end | ||
Revision as of 15:04, 1 May 2024
Documentation for this module may be created at Module:StormforgedController/doc
--- --- Generated by EmmyLua(https://github.com/EmmyLua) --- Created by onken. --- DateTime: 4/29/2024 9:27 PM --- ---@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_SEARCH = "search" local ARGS_EXCLUDE_LIST = "exclude" local ARG_CAPTION = "caption" local ARG_SKIP_PRICES = "skip_prices" local ARG_SKIP_PRICES_FLAG_VALUE = "skip" --local DISPLAY_OPTION_TABLE = "table" local TEMPLATE_PARAMETER_ID = "id" local TEMPLATE_PARAMETER_DESC = "description" local TEMPLATE_PARAMETER_PRICE_META = "price_in_meta_resources" local TEMPLATE_PARAMETER_PRICE_VILL = "price_in_villagers" local TEMPLATE_PARAMETER_UPGRA_META = "price_for_upgrade_in_meta_resources" local TEMPLATE_PARAMETER_UPGRA_VILL = "price_for_upgrade_in_villagers" local TEMPLATE_CONTAINER_START = "StormforgedCornerstonesTable" local TEMPLATE_CONTAINER_SUFFIX_ROW = "/row" local TEMPLATE_CONTAINER_SUFFIX_END = "/end" local TEMPLATE_CONTAINER_SKIP_PRICES_VARIANT = "/SkipPrices" 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 = {} --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. --- ---@param list table the list of unique identifiers for which to look up names local function validateNames(list) for _, id in ipairs(list) 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 altardIDs. 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] then table.insert(altarIDs, id) 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 variables. --- local function loadIDs(selectedID, searchName, searchTerm, excludeList) if not altarIDs or #altarIDs < 1 then altarIDs = {} local attemptedSearch = false -- Load the selected ID if selectedID and selectedID ~= "" then loadStormforgedIDs( { selectedID }, 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 searchTerm and searchTerm ~= "" then local newIDs = PerksData.getAllPerkIDsWhereDescription(searchTerm) loadStormforgedIDs(newIDs, excludeList) attemptedSearch = true end -- Or, if no searching was done, show them all if not attemptedSearch then altarIDs = AltarEffectsData.getAllAltarIDs() end end 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. validateNames(altarIDs) --Alphabetize by name table.sort(altarIDs, compareNames) end end ---expandExclusions ---@param exclusions string the list of ids, separated by commas ---@return table the ids now as keys in the table and each value is `true` local function expandExclusions(exclusions) local excludeList = {} for idToExclude in string.gmatch(exclusions, "[^,]+") do excludeList[idToExclude] = true end return excludeList 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 selectedID string the first search parameter, an id ---@param searchName string the second search parameter, a name ---@param searchTerm string the third search parameter, a term ---@param desiredCaption string the caption requested, if any ---@return string an appropriate caption, or blank if it should be default local function resolveCaption(selectedID, searchName, searchTerm, desiredCaption) if desiredCaption and desiredCaption ~= "" then return desiredCaption end if selectedID and selectedID ~= "" then return "Stormforged Cornerstone with id '" .. selectedID .. "'" end if searchName and searchName ~= "" then return "Stormforged Cornerstones named '" .. searchName .. "'" end if searchTerm and searchTerm ~= "" then return "Stormforged Cornerstones mentioning '" .. searchTerm .. "'" end -- Delegate to the template for the default return "" 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 ---@return string the wiki markup to display, now longer local function makeMarkupForTableStart(desiredCaption, skippingPrice) local suffixIfSkipping = (skippingPrice == ARG_SKIP_PRICES_FLAG_VALUE and TEMPLATE_CONTAINER_SKIP_PRICES_VARIANT) or "" local startTemplate = TEMPLATE_CONTAINER_START .. suffixIfSkipping return currentFrame:expandTemplate{ title = startTemplate, args = { caption = desiredCaption, skip_prices = skippingPrice } } end --- Calls the view (other templates) to render a single row of the table with data based on the provided identifier. --- ---@param skippingPrice string the flag for skipping prices in the table, if any ---@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 to display, now longer local function makeMarkupPerRow(skippingPrice, id) local rowTemplate = TEMPLATE_CONTAINER_START .. TEMPLATE_CONTAINER_SUFFIX_ROW templateParameters = { [TEMPLATE_PARAMETER_ID] = id, [TEMPLATE_PARAMETER_DESC] = PerksData.getDescriptionByID(id) } if skippingPrice ~= ARG_SKIP_PRICES_FLAG_VALUE then templateParameters[TEMPLATE_PARAMETER_PRICE_META] = AltarEffectsData.getPriceInMetaResources(id) templateParameters[TEMPLATE_PARAMETER_PRICE_VILL] = AltarEffectsData.getPriceInVillagers(id) templateParameters[TEMPLATE_PARAMETER_UPGRA_META] = AltarEffectsData.getUpgradePriceInMetaResources(id) templateParameters[TEMPLATE_PARAMETER_UPGRA_VILL] = AltarEffectsData.getUpgradePriceInVillagers(id) else rowTemplate = rowTemplate .. TEMPLATE_CONTAINER_SKIP_PRICES_VARIANT end return currentFrame:expandTemplate{ title = rowTemplate, 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 ---@return string the wiki markup to display, now longer local function makeMarkupForTableRows(skippingPrice) local markup = "" for _, id in ipairs(altarIDs) do markup = markup .. makeMarkupPerRow(skippingPrice, id) end return markup end --- Calls the view (other templates) to render the end of the table. --- ---@return string the wiki markup to display, now longer local function makeMarkupForTableEnd() local endTemplate = TEMPLATE_CONTAINER_START .. TEMPLATE_CONTAINER_SUFFIX_END return currentFrame:expandTemplate{ title = endTemplate, 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 table ---@param skippingPrice table ---@return string the wiki markup assembled by the view (other templates) local function renderTable(selectedID, searchName, searchTerm, excludeList, desiredCaption, skippingPrice) loadIDs(selectedID, searchName, searchTerm, excludeList) if #altarIDs < 1 then return "No Stormforged Cornerstones found." end desiredCaption = resolveCaption(selectedID, searchName, searchTerm, desiredCaption) return makeMarkupForTableStart(desiredCaption, skippingPrice) .. makeMarkupForTableRows(skippingPrice) .. "\n" .. makeMarkupForTableEnd() 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) -- Extract template parameters local selectedID = frame.args[ARG_ID] local searchName = frame.args[ARG_NAME] local searchTerm = frame.args[ARG_SEARCH] local exclusions = frame.args[ARGS_EXCLUDE_LIST] local desiredCaption = frame.args[ARG_CAPTION] local skippingPrice = frame.args[ARG_SKIP_PRICES] --TODO make displayOverride == DISPLAY_OPTION_LIST local excludeList = {} if exclusions and exclusions ~= "" then excludeList = expandExclusions(exclusions) end currentFrame = frame return renderTable(selectedID, searchName, searchTerm, excludeList, desiredCaption, skippingPrice) end --endregion return StormforgedController