Module:PerkSearchController

--- --- Module for searching data on perks and displaying results --- --- @module PerkSearchController local PerkSearchController = {}

local PerkSearchResultsView = require("Module:PerkSearchResultsView")

local PerksData = require("Module:PerksData")

--region Private member variables

--endregion

--region Private constants

--endregion

--region Private methods

--- --- Takes two lists and returns the union of the two. --- ---@param list1 table a flat table (list of values) ---@param list2 table another flat table ---@return table a similarly flat table consisting of the values of both lists local function findUnion(list1, list2)

local unionList = {}

-- Have to check before adding them to not add duplicates. local checkList = {} for _, value in ipairs(list2) do		table.insert(unionList, value) checkList[value] = true end

for _, value in ipairs(list1) do		if not checkList[value] then table.insert(unionList, value) checkList[value] = true end end

return unionList end

--- --- Runs through the provided list of IDs and returns true if any are from --- a Trader. --- ---@param perkIDsList table list of perkIDs ---@return boolean whether any in the list are from a Trader local function isAnyFromTrader(perkIDsList)

-- Should never be nil at runtime. if not perkIDsList then error("Invalid list of perk IDs.") end

for _, perkID in ipairs(perkIDsList) do

if PerksData.isFromTraderByID(perkID) then return true end end

return false end

--- --- Searches through perks for matches in descriptions and names and returns --- the results of both merged into one list. --- ---@param searchTerm string the terms to search for ---@return table a list of perk IDs that match local function searchAllNamesAndDescriptions(searchTerm)

local listFromSearchingNames = PerksData.getAllPerkIDsWhereName(searchTerm) local listFromSearchingDescriptions = PerksData.getAllPerkIDsWhereDescription(searchTerm)

return findUnion(listFromSearchingDescriptions, listFromSearchingNames) end

--- --- Loops through a list of IDs and filters out any that don't match the --- specified source. --- ---@param listOfIDs table list of perk IDs ---@param source string the type of source to filter ---@return table the same list, but fewer items local function filterAllSources(listOfIDs, source)

-- Should never be nil at runtime. if not source then error("Invalid parameter for source.") end

local newList = {} -- Remove any that do not have the specified source. for _, perkID in ipairs(listOfIDs) do

if PerksData.isAnySource(perkID, source) then table.insert(newList, perkID) end end

return newList end

--- --- Loops through a list of IDs and filters out any that don't match the --- specified rarity. --- ---@param listOfIDs table list of perk IDs ---@param rarity string a rarity constant to filter ---@return table the same list, but fewer items local function filterAllRarities(listOfIDs, rarity)

-- Should never be nil at runtime. if not rarity then error("Invalid parameter for rarity.") end

local newList = {} -- Remove any that do not have the specified rarity. for _, perkID in ipairs(listOfIDs) do

if PerksData.isRarityMatchByID(perkID, rarity) then table.insert(newList, perkID) end end

return newList end

--- --- Main engine converting the list of IDs into calls to the View to render --- rows (or whatever based on list override). --- ---@param perkList table list of perk IDs ---@param displayOverride string how to display, if not default ---@param hasLastColumn boolean whether to write the last column local function buildRowsForPerks(perkList, displayOverride, hasLastColumn)

for _, perkID in ipairs(perkList or {}) do

local perkName = PerksData.getNameByID(perkID) local description = PerksData.getDescriptionByID(perkID) local iconFilename = PerksData.getIconByID(perkID) local rarity = PerksData.getRarityByID(perkID) local price = PerksData.getPriceByID(perkID)

local sourceCornerstone = PerksData.isFromCornerstoneByID(perkID) local sourceEvent = PerksData.isFromEventByID(perkID) local sourceOrder = PerksData.isFromOrderByID(perkID) local sourceTrader = PerksData.isFromTraderByID(perkID)

PerkSearchResultsView.addRowForPerk(displayOverride, perkName,				description, iconFilename, rarity, price,				sourceCornerstone, sourceEvent, sourceOrder, sourceTrader, hasLastColumn) end end

--- --- Organizes a list of IDs to send to the build method. Calls the View's --- setup, builds, and end. --- ---@param perkID string a single perk's ID ---@param displayOverride string how to display, if not default local function renderFromID(perkID, displayOverride)

local perkName = PerksData.getNameByID(perkID)

if not perkName then return "No perk found with ID " .. perkID .. "."	end

local isFromTrader = PerksData.isFromTraderByID(perkID)

PerkSearchResultsView.startViewForPerk(perkName, displayOverride, isFromTrader)

buildRowsForPerks( { perkID }, displayOverride, isFromTrader)

return PerkSearchResultsView.endView(displayOverride) end

--- --- Organizes a list of IDs to send to the build method. Calls the View's --- setup, builds, and end. --- ---@param perkName string the name of a Perk ---@param displayOverride string how to display, if not default local function renderFromName(perkName, displayOverride)

local perkIDsList = PerksData.getAllPerkIDsByName(perkName)

if not perkIDsList or #perkIDsList == 0 then return "No perk found with name " .. perkName .. "."	end

local numPerks = #perkIDsList local isFromTrader = isAnyFromTrader(perkIDsList)

PerkSearchResultsView.startViewForName(perkName, displayOverride, numPerks, isFromTrader)

buildRowsForPerks(perkIDsList, displayOverride, isFromTrader)

return PerkSearchResultsView.endView(displayOverride) end

--- --- Organizes a list of IDs to send to the build method. Calls the View's --- setup, builds, and end. --- ---@param searchTerm string the text to search from all perks ---@param source string the type of source to filter, if any ---@param rarity string a rarity constant to filter, if any ---@param displayOverride string how to display, if not default ---@return table local function renderSearch(searchTerm, source, rarity, displayOverride)

local starterList = searchAllNamesAndDescriptions(searchTerm)

local filteredList = starterList if source ~= nil then filteredList = filterAllSources(filteredList, source) end if rarity ~= nil then filteredList = filterAllRarities(filteredList, rarity) end

if not filteredList or #filteredList == 0 then return "No perk found with specified search criteria." end

local numPerks = #filteredList local isFromTrader = isAnyFromTrader(filteredList)

PerkSearchResultsView.startViewForSearchResults(searchTerm, source, rarity, displayOverride, numPerks, isFromTrader)

buildRowsForPerks(filteredList, displayOverride, isFromTrader)

return PerkSearchResultsView.endView(displayOverride) end

--endregion

--region Public methods

--- --- Main method invoked from the template. --- ---@param frame table the MediaWiki calling context ---@return string long wiki markup with the results function PerkSearchController.search(frame)

-- Extract the template parameters. local perkID = frame.args.id or frame.args[1] local name = frame.args.name local searchTerm = frame.args.search local source = frame.args.source local rarity = frame.args.rarity local displayOverride = frame.args.display

-- Convert empty strings on these only to nil if source == "" then source = nil end if rarity == "" then rarity = nil end

if perkID and perkID ~= "" then return renderFromID(perkID, displayOverride) else if name and name ~= "" then return renderFromName(name, displayOverride) else if searchTerm and searchTerm ~= "" then return renderSearch(searchTerm, source, rarity, displayOverride) else return "Unknown parameter in Perk Search template." end end end end

--endregion

return PerkSearchController