Module:PerkSearchResultsView

--- @module PerkSearchResultsView local PerkSearchResultsView = {}

local PerksData = require("Module:PerksData")

--region Private member variables

beginning = "" middle = "" ending = ""

local imgS = mw.getCurrentFrame:expandTemplate{ title = "ImgS" } local imgM = mw.getCurrentFrame:expandTemplate{ title = "ImgM" } local imgL = mw.getCurrentFrame:expandTemplate{ title = "ImgL" }

local amberIcon = mw.getCurrentFrame:expandTemplate{ title= "Amber" }

--endregion

--region Private constants

local PARAMETER_DISPLAY_OVERRIDE_LIST = "list"

-- wikitable classes for tables local CLASS_WIKITABLE_SORTABLE_COLLAPSIBLE = "wikitable sortable mw-collapsible" local CSS_TD_SHRINK_TO_FIT = "max-width: 20em" local CLASS_UNSORTABLE = "unsortable"

local RARITY_COLORS = { [PerksData.RARITY_UNCOMMON] = "#15cf00", [PerksData.RARITY_RARE] = "#015db9", [PerksData.RARITY_EPIC] = "#7f27b9", [PerksData.RARITY_LEGENDARY] = "#da6d00", [PerksData.NONE] = "#444444" }

local BORDER_SIZES = { [imgS] = "1.5px", [imgM] = "2px", [imgL] = "4px" }

-- Shortcut markup that's easier for Lua string concatenations local NBSP = " " local BLANK = "—"

--endregion

--region Private methods

--- --- Formats a standard link to a perk. Does not invoke the template, but it --- could be modified to do so in the future. --- ---@param perkName string the display name of the perk ---@param perkIcon string the filename for the icon ---@param iconSize string representing the desired size of the icon ---@param borderColor string the color of the border to put on the icon ---@return string an assembled link, with icon and text local function perkLink(perkName, perkIcon, iconSize, borderColor)

if not perkName or not perkIcon or not iconSize then error("Perk parameters cannot be nil.") end

local displayStyle = "display: inline-block;"

--- Set absolute height of border span to stop it being bigger than the image if iconSize == imgS then displayStyle = displayStyle .. "height: 18px;" end

local startBorderSpan = "" local endBorderSpan = " "

--- Hacky fix for weird image offset if iconSize == imgS then --- Add a second containing span to move the image into position startBorderSpan = startBorderSpan .. "" endBorderSpan = " " end

local iconPart = ""

local linkPart = NBSP .. "" .. perkName .. ""

return startBorderSpan .. iconPart .. endBorderSpan .. linkPart end

--- --- Creates a header row under the provided MediaWiki HTML table entity. --- ---@param tableNode table MediaWiki HTML table entity ---@param needsPriceColumn boolean if the table need to include a price column local function makeStandardPerkTableHeaderRow(tableNode, needsPriceColumn)

local row = tableNode:tag("tr")

row:tag("th"):wikitext("Perk"):done row:tag("th"):wikitext("Rarity"):done row:tag("th"):addClass(CLASS_UNSORTABLE):wikitext("Description"):done row:tag("th"):addClass(CLASS_UNSORTABLE):wikitext("Source(s)"):done if needsPriceColumn then row:tag("th"):wikitext("Price"):done end

row:done:newline end

--- --- Returns a standard MediaWiki HTML table entity created with standard --- display and interactivity classes. --- ---@return table standard MediaWiki HTML table entity local function startNewWikiTable

return mw.html.create("table"):addClass(CLASS_WIKITABLE_SORTABLE_COLLAPSIBLE):newline end

--- --- Makes the content of the name column under the provided HTML table row --- entity. --- ---@param htmlTableRow table MediaWiki HTML table row entity ---@param perkName string the name of the building ---@param perkIcon string the filename for the icon ---@param borderColor string the color of the border to put on the icon local function makeNameColumn(htmlTableRow, perkName, perkIcon, borderColor)

htmlTableRow:tag("td"):wikitext(perkLink(perkName, perkIcon, imgL, borderColor)):done:newline end

--- --- Makes the content of the name column under the provided HTML table row --- entity. --- ---@param htmlTableRow table MediaWiki HTML table row entity ---@param rarity string the rarity of the perk local function makeRarityColumn(htmlTableRow, rarity)

htmlTableRow:tag("td"):wikitext(rarity):done:newline end

--- --- Makes the content of the description column under the provided HTML table --- row node. --- ---@param htmlTableRow table MediaWiki HTML table row entity ---@param description string the long description local function makeDescriptionColumn(htmlTableRow, description)

htmlTableRow:tag("td"):cssText(CSS_TD_SHRINK_TO_FIT) :wikitext(description):done:newline end

--- --- Builds an unordered bulleted list based on the specified perk's sources. --- ---@param htmlTableRow table the MediaWiki html node we're building on ---@param isFromCornerstone boolean whether the perk is a Cornerstone ---@param isFromEvent boolean whether the perk is a reward from an Event ---@param isFromOrder boolean whether the perk is a reward from an Order ---@param isFromTrader boolean whether the perk is purchasable from a Trader local function makeSourcesColumn(htmlTableRow, isFromCornerstone, isFromEvent, isFromOrder, isFromTrader)

local td = htmlTableRow:tag("td") local list = td:tag("ul")

if isFromCornerstone then list:tag("li"):wikitext("as a Cornerstone"):done end if isFromEvent then list:tag("li"):wikitext("from Glade Event rewards"):done end if isFromOrder then list:tag("li"):wikitext("from Order rewards"):done end if isFromTrader then list:tag("li"):wikitext("purchased from a Trader"):done end

list:done td:done end

--- --- Adds a table cell containing the price and the amber icon --- ---@param htmlTableRow table the Mediawiki HTML node we're building on ---@param price number value in amber local function makePriceColumn(htmlTableRow, price)

htmlTableRow:tag("td"):wikitext(price .. NBSP .. amberIcon):done end

--endregion

--region Public methods

--- --- Initializes the table, populates the caption, and writes and header row, --- all appropriate for a table focusing on one perk. --- --- The default is a wikitable output. With the displayOverride flag, this --- method will instead make a list. --- ---@param perkName string the name of the perk this table is built for ---@param displayOverride string a flag for the output type if not the default ---@param needsPriceColumn boolean whether this perk needs a price column function PerkSearchResultsView.startViewForPerk(perkName, displayOverride, needsPriceColumn)

-- These should never be nil at runtime. if not perkName then error("Parameter is invalid for perk name.") end

local newNode if displayOverride == PARAMETER_DISPLAY_OVERRIDE_LIST then newNode = mw.html.create("ul") else newNode = startNewWikiTable newNode:tag("caption"):wikitext("Perk: " .. perkName .. "."):done:newline

makeStandardPerkTableHeaderRow(newNode, needsPriceColumn) end

beginning = newNode -- Return value is not used by the Controller, but for debugging. return newNode end

--- --- Initializes the table, populates the caption, and writes and header row, --- all appropriate for a table focusing on one perk. --- --- The default is a wikitable output. With the displayOverride flag, this --- method will instead make a list. --- ---@param perkName string the name of the perk this table is built for ---@param displayOverride string a flag for the output type if not the default ---@param numPerks number of perks that will be shown ---@param needsPriceColumn boolean whether this perk needs a price column function PerkSearchResultsView.startViewForName(perkName, displayOverride, numPerks, needsPriceColumn)

-- These should never be nil at runtime. if not perkName then error("Parameter is invalid for perk name.") end if not numPerks then error("Parameter is invalid for number of perks.") end

local number = tonumber(numPerks) if not number then error("Number of perks could not be converted to a number: " .. numPerks) end

local newNode if displayOverride == PARAMETER_DISPLAY_OVERRIDE_LIST then newNode = mw.html.create("ul") else newNode = startNewWikiTable newNode:tag("caption"):wikitext(number .. " perks named " .. perkName .. "."):done:newline

makeStandardPerkTableHeaderRow(newNode, needsPriceColumn) end

beginning = newNode -- Return value is not used by the Controller, but for debugging. return newNode end

function PerkSearchResultsView.startViewForSearchResults(searchTerm, source, rarity,														 displayOverride, numPerks, needsPriceColumn)

-- These should never be nil at runtime if not searchTerm then error("Parameter is invalid for search term.") end if not numPerks then error("Parameter is invalid for number of perks.") end

local number = tonumber(numPerks) if not number then error("Number of perks could not be converted to a number: " .. numPerks) end

local newNode if displayOverride == PARAMETER_DISPLAY_OVERRIDE_LIST then newNode = mw.html.create("ul") else local header = number .. NBSP if rarity then header = header .. rarity .. NBSP end header = header .. "Perks mentioning '" .. searchTerm .. "'"		if source then header = header .. " from " .. source end header = header .. "."

newNode = startNewWikiTable newNode:tag("caption"):wikitext(header):done:newline

makeStandardPerkTableHeaderRow(newNode, needsPriceColumn) end

beginning = newNode -- Return value is not used by the Controller, but for debugging. return newNode end

--- --- Adds a new row to the content being built. This is typically called from a --- Controller that knows how many rows to add. PerkSearchResultsView maintains --- the output in-progress while rows are added, so that layout and formatting --- can be owned by this module instead of the Controller. --- ---@param displayOverride string a flag for the output type if not the default ---@param perkName string the name of the perk ---@param description string the flavor text description ---@param iconFilename string the icon of the perk ---@param rarity string the rarity ---@param price number price of the perk at a trader ---@param isFromCornerstone boolean whether this perk is earned as a Cornerstone ---@param isFromEvent boolean whether this perk is rewarded from an event ---@param isFromOrder boolean whether this perk is earned from an Order ---@param isFromTrader boolean whether this perk is purchasable ---@param hasLastColumn boolean whether to render the last column (regardless of isFromTrader) function PerkSearchResultsView.addRowForPerk(displayOverride, perkName,											 description, iconFilename, rarity, price,											 isFromCornerstone, isFromEvent, isFromOrder, isFromTrader,											 hasLastColumn)

local newNode if displayOverride == PARAMETER_DISPLAY_OVERRIDE_LIST then -- List version. newNode = mw.html.create("li"):wikitext(perkLink(perkName, iconFilename, imgS, RARITY_COLORS[rarity])) else -- Table version. newNode = mw.html.create("tr"):newline makeNameColumn(newNode, perkName, iconFilename, RARITY_COLORS[rarity]) makeRarityColumn(newNode, rarity) makeDescriptionColumn(newNode, description) makeSourcesColumn(newNode, isFromCornerstone, isFromEvent, isFromOrder, isFromTrader) if hasLastColumn then if isFromTrader then makePriceColumn(newNode, price) else newNode:tag("td"):wikitext(BLANK):done end end end

newNode:done middle = middle .. tostring(newNode)

return newNode end

--- --- Wraps up anything outstanding for the view, then returns the entire --- MediaWiki entity originally started in the respective method. --- ---@return string the HTML markup of the completed view function PerkSearchResultsView.endView

beginning:node(middle) beginning:done

middle = ""

return beginning end

--endregion

return PerkSearchResultsView