Difference between revisions of "Module:DM Fusion display"
(Removing the last snake case) |
(Fixed (yet another) sorting issue regarding pairs (yet again fixed by using ipairs). Fixed combinations for a same Fusion not being grouped if all of them had no description) |
||
(2 intermediate revisions by the same user not shown) | |||
Line 137: | Line 137: | ||
-- The attributes that should be returned | -- The attributes that should be returned | ||
local required_attributes = { | local required_attributes = { | ||
− | "Fusion Material 1", "Fusion Material 2", "Fusion result", "Description", "Columns", | + | "Fusion Material 1", "Fusion Material 2", "Fusion result", "Description", "Columns", -- Attributes about the Fusion combination |
− | "Fusion Material 1.English name = English name 1", "Fusion Material 1.Level = Level 1", "Fusion Material 1.Card number = Card number 1", -- Attributes about each card listed as Material 1 | + | "Fusion Material 1.English name = English name 1", "Fusion Material 1.Level = Level 1", "Fusion Material 1.Card number = Card number 1", "Fusion Material 1.Card type = Card type 1", -- Attributes about each card listed as Material 1 |
− | "Fusion Material 2.English name = English name 2", "Fusion Material 2.Level = Level 2", "Fusion Material 2.Card number = Card number 2", -- Attributes about each card listed as Material 2 | + | "Fusion Material 2.English name = English name 2", "Fusion Material 2.Level = Level 2", "Fusion Material 2.Card number = Card number 2", "Fusion Material 2.Card type = Card type 2", -- Attributes about each card listed as Material 2 |
− | "Fusion result.English name = English name 3", "Fusion result.Level = Level 3", "Fusion result.Card number = Card number 3", -- Attributes about each card listed as Result | + | "Fusion result.English name = English name 3", "Fusion result.Level = Level 3", "Fusion result.Card number = Card number 3", "Fusion result.Card type = Card type 3", -- Attributes about each card listed as Result |
− | "Fusion result = Fusion Material 3" | + | "Fusion result = Fusion Material 3" -- Small hack to help iterate below |
} | } | ||
local query = mw.smw.ask( conditions .. "|?" .. table.concat(required_attributes, "|?")) or {} | local query = mw.smw.ask( conditions .. "|?" .. table.concat(required_attributes, "|?")) or {} | ||
+ | local nonMonsterOffset | ||
-- Iterates over both Fusion Material lists, and adds each card to the table | -- Iterates over both Fusion Material lists, and adds each card to the table | ||
Line 154: | Line 155: | ||
levels = toTable(combination["Level " .. combi_index]) | levels = toTable(combination["Level " .. combi_index]) | ||
numbers = toTable(combination["Card number " .. combi_index]) | numbers = toTable(combination["Card number " .. combi_index]) | ||
+ | types = toTable(combination["Card type " .. combi_index]) | ||
− | for i, fm in | + | -- Since non-Monsters don't have Levels, the properties get returned with some lines missing for Monster-specific properties (e.g. Level) |
+ | -- This variable is used to offset that | ||
+ | nonMonsterOffset = 0 | ||
+ | |||
+ | for i, fm in ipairs(materials) do | ||
fm = unlink(fm) | fm = unlink(fm) | ||
if not CARD_INFO[fm] then | if not CARD_INFO[fm] then | ||
CARD_INFO[fm] = { | CARD_INFO[fm] = { | ||
["name"] = en_names[i], | ["name"] = en_names[i], | ||
− | ["level"] = levels[i], | + | ["level"] = levels[i-nonMonsterOffset], |
["number"] = numbers[i] | ["number"] = numbers[i] | ||
} | } | ||
+ | end | ||
+ | if unlink(types[i]) ~= 'Monster Card' then | ||
+ | nonMonsterOffset = nonMonsterOffset + 1 | ||
+ | CARD_INFO[fm]["level"] = nil | ||
end | end | ||
end | end | ||
Line 262: | Line 272: | ||
currentTable = fillTableForFusionResult(currentTable, mats1, mats2, columns, combination_exceptions) | currentTable = fillTableForFusionResult(currentTable, mats1, mats2, columns, combination_exceptions) | ||
− | previousDescription = description | + | previousDescription = description |
end | end | ||
end | end | ||
Line 269: | Line 279: | ||
-- @description Creates the table to be displayed for Fusion Material monsters | -- @description Creates the table to be displayed for Fusion Material monsters | ||
local function createFusionMaterialTable() | local function createFusionMaterialTable() | ||
− | local previousDescription, currentTable | + | local previousDescription, previousResult, currentTable |
-- Creates tables/rows for each combination found | -- Creates tables/rows for each combination found | ||
Line 276: | Line 286: | ||
combination[1], combination["Fusion Material 1"], combination["Fusion Material 2"], combination["Fusion result"], combination["Description"], combination["Columns"] or 1 | combination[1], combination["Fusion Material 1"], combination["Fusion Material 2"], combination["Fusion result"], combination["Description"], combination["Columns"] or 1 | ||
local cur_combi_exceptions = {} | local cur_combi_exceptions = {} | ||
− | + | ||
− | |||
-- MW attributes don't return a table if there is only 1 value. Converting both to tables to facilitate future processing | -- MW attributes don't return a table if there is only 1 value. Converting both to tables to facilitate future processing | ||
mats1 = toTable(mats1) | mats1 = toTable(mats1) | ||
Line 293: | Line 302: | ||
-- Creates a new table on the first itteration, and when a description changes | -- Creates a new table on the first itteration, and when a description changes | ||
− | if not currentTable or description ~= previousDescription then | + | if not currentTable or description ~= previousDescription or result ~= previousResult then |
+ | mw.log(result .. ": " .. (description or 'nil') .. " " .. (previousDescription or 'nil')) | ||
currentTable = _fusionDisplay:tag("table"):attr("class", "wikitable") | currentTable = _fusionDisplay:tag("table"):attr("class", "wikitable") | ||
currentTable:tag("ul"):tag("li"):wikitext(formatCardDisplay(unlink(result)) .. (description and (" (" .. description .. ')') or '')) | currentTable:tag("ul"):tag("li"):wikitext(formatCardDisplay(unlink(result)) .. (description and (" (" .. description .. ')') or '')) | ||
Line 302: | Line 312: | ||
currentTable = fillTableForFusionMaterial(currentTable, mats, columns, excepts) | currentTable = fillTableForFusionMaterial(currentTable, mats, columns, excepts) | ||
− | previousDescription = description or | + | previousDescription = description |
+ | previousResult = result or previousResult | ||
end | end | ||
end | end | ||
Line 331: | Line 342: | ||
_fusionDisplay = HTML() | _fusionDisplay = HTML() | ||
− | _pageName = _args[1] or " | + | _pageName = _args[1] or "Mavelus (FMR)" |
end | end | ||
Latest revision as of 00:05, 22 May 2024
-- <pre>
-- @name DM Fusion display
-- @description A module used to display Fusion combinations in their respective card articles
-- @author [[User:JustGian]]
-- @contact [[User talk:JustGian]]
----------------
-- Load modules:
----------------
local DATA = require( 'Module:Data' );
local UTIL = require( 'Module:Util' );
--------------------
-- Module variables:
--------------------
-- Parser state:
local
PAGENAME,
NAMESPACE,
_frame,
_args,
_fusionDisplay,
_pageName,
_combinationsQuery,
_exceptionsQuery
;
-- Stores properties for cards to avoid making a new query each time they are needed
local CARD_INFO = {}
---------------------
-- Utility functions:
---------------------
-- mw functions:
local HTML = mw.html.create;
--------------------
-- Module functions:
--------------------
--# Local functions
--[[Doc
@function U unlink
@description (From Module:Card type) If a string is passed, unlinks
and returns the page name (not the label, unless «getLabel»).
If a table is passed, unlinks every instance of it
and returns the table with the page names for each respective entry.
@parameter {*} v Any value to unlink.
@parameter {boolean} getLabel Makes the function return the label instead.
@return {*} The unlinked value.
]]
local function unlink( v, getLabel )
local function __unlink( v, getLabel )
return UTIL.trim( v ) and (getLabel and v:match( '%[%[:?.-|(.-)]]' ) or v:match( '%[%[:?(.-)[|%]]' )) or UTIL.trim( v );
end
if type( v ) == 'string' then
return __unlink( v, getLabel );
elseif type( v ) == 'table' then
local t = {};
for key, value in ipairs( v ) do
table.insert( t, __unlink( value, getLabel ) );
end
return t;
else
return v; -- @@@ error()
end
end
-- @name toTable
-- @description Receives an object, and converts it to a table containing itself, unless it is already a table
local function toTable(obj)
return type(obj) == "table" and obj or { obj }
end
-- @name formatCardDisplay
-- @description Receives a card page name and returns the expected string to be displayed
local function formatCardDisplay(card)
attr = CARD_INFO[card]
return string.format("#%s: %s\"[[%s|%s]]\"", attr["number"], attr["level"] and ( attr["level"] .. " [[File:CG Star.svg|15px|alt=|class=noviewer]] " ) or '', card, attr["name"])
end
-- @name fillTableForFusionResult
-- @description Appends the row with the materials of the current combination to a table belonging to a Fusion Result section
local function fillTableForFusionResult( currentTable, mats1, mats2, columns, mats_exceptions )
local matsRow = currentTable:tag("tr")
local mat1Cell = matsRow:tag("td"):tag("ul")
local mat2Cell = matsRow:tag("td"):tag("div"):attr("style", "column-width: 13em; column-count: " .. columns):tag("ul")
-- Prints the first cell
for _, card in ipairs(mats1) do
card = unlink(card)
mat1Cell:tag("li"):wikitext(formatCardDisplay(card))
end
-- The second cell also includes the "except with" addition
for _, card in ipairs(mats2) do
card = unlink(card)
mat2Cell:tag("li"):wikitext(formatCardDisplay(card) .. (mats_exceptions[card] and string.format(" (except with \"[[%s|%s]]\")", mats_exceptions[card], CARD_INFO[mats_exceptions[card]]["name"]) or ''))
end
return currentTable
end
-- @name fillTableForFusionMaterial
-- @description Appends the row with the materials of the current combination to a table belonging to a Fusion Material section
local function fillTableForFusionMaterial( currentTable, mats, columns, excepts )
local matsRow = currentTable:tag("tr"):tag("td"):tag("div"):attr("style", "column-width: 13em; column-count: " .. columns):tag("ul")
-- Print other materials, but don't include those present in the exceptions table
for _, card in ipairs(mats) do
if not excepts[card] then
card = unlink(card)
matsRow:tag("li"):wikitext(formatCardDisplay(card))
end
end
return currentTable
end
-- @name runCombinationExceptionsQuery
-- @description Gets the combinations exceptions for a query of combinatigons
local function runCombinationExceptionsQuery()
local fusion_ids = {}
for _, combination in ipairs(_combinationsQuery) do
table.insert(fusion_ids, unlink(combination[1]))
end
local query = mw.smw.ask( string.format("[[For Fusion::%s]] |?Fusion Material exception 1 |?Fusion Material exception 2 |?For Fusion", table.concat(fusion_ids, "||")) ) or {}
return query
end
-- @name processCombinationsQuery
-- @description Gets the required attributes for a Fusion query by running the provided conditions.
-- By running the query only once, the module saves a considerable amount of time that would be spent querying each card's name every time it is required
local function processCombinationsQuery(conditions)
-- The attributes that should be returned
local required_attributes = {
"Fusion Material 1", "Fusion Material 2", "Fusion result", "Description", "Columns", -- Attributes about the Fusion combination
"Fusion Material 1.English name = English name 1", "Fusion Material 1.Level = Level 1", "Fusion Material 1.Card number = Card number 1", "Fusion Material 1.Card type = Card type 1", -- Attributes about each card listed as Material 1
"Fusion Material 2.English name = English name 2", "Fusion Material 2.Level = Level 2", "Fusion Material 2.Card number = Card number 2", "Fusion Material 2.Card type = Card type 2", -- Attributes about each card listed as Material 2
"Fusion result.English name = English name 3", "Fusion result.Level = Level 3", "Fusion result.Card number = Card number 3", "Fusion result.Card type = Card type 3", -- Attributes about each card listed as Result
"Fusion result = Fusion Material 3" -- Small hack to help iterate below
}
local query = mw.smw.ask( conditions .. "|?" .. table.concat(required_attributes, "|?")) or {}
local nonMonsterOffset
-- Iterates over both Fusion Material lists, and adds each card to the table
for _, combination in ipairs(query) do
for combi_index = 1,3 do
-- MW doesn't return multiple-valued properties as tables, so we convert them here
materials = toTable(combination["Fusion Material " .. combi_index])
en_names = toTable(combination["English name " .. combi_index])
levels = toTable(combination["Level " .. combi_index])
numbers = toTable(combination["Card number " .. combi_index])
types = toTable(combination["Card type " .. combi_index])
-- Since non-Monsters don't have Levels, the properties get returned with some lines missing for Monster-specific properties (e.g. Level)
-- This variable is used to offset that
nonMonsterOffset = 0
for i, fm in ipairs(materials) do
fm = unlink(fm)
if not CARD_INFO[fm] then
CARD_INFO[fm] = {
["name"] = en_names[i],
["level"] = levels[i-nonMonsterOffset],
["number"] = numbers[i]
}
end
if unlink(types[i]) ~= 'Monster Card' then
nonMonsterOffset = nonMonsterOffset + 1
CARD_INFO[fm]["level"] = nil
end
end
end
end
return query
end
-- @name setListsForFusionMaterialDisplay
-- @description Creates the material and exception lists for a Fusion Material display
local function setListsForFusionMaterialDisplay(mats1, mats2)
local materialIndex, mats
local excepts = {}
-- Checks to which of the two lists should be displayed (if a card belongs to Materials 2, display Materials 1)
for _, mat in ipairs(mats1) do
if unlink(mat) == _pageName then
materialIndex = 2
break
end
end
-- Also checks the second list to see if the material is present there
if materialIndex then
for _, mat in ipairs(mats2) do
if unlink(mat) == _pageName then
materialIndex = materialIndex + 1
break
end
end
else
materialIndex = 1
end
-- Assigns correct material and exception list, based on the index found
-- Index 3 means that it was found in both lists
if materialIndex == 1 or materialIndex == 3 then
mats = mats1
for _, combi_ex in ipairs(_exceptionsQuery) do
if unlink(combi_ex["Fusion Material exception 1"]) == _pageName then
excepts[combi_ex["Fusion Material exception 2"]] = true
end
end
end
if materialIndex == 2 or materialIndex == 3 then
if not mats then mats = mats2
else
-- Joins both tables
for _, m2 in ipairs(mats2) do
if unlink(m2) ~= _pageName then -- Don't include the same article twice
table.insert(mats, m2)
end
end
end
for _, combi_ex in ipairs(_exceptionsQuery) do
if unlink(combi_ex["Fusion Material exception 2"]) == _pageName then
excepts[combi_ex["Fusion Material exception 1"]] = true
end
end
end
return mats, excepts
end
-- @name createFusionResultTable
-- @description Creates the table to be displayed for Fusion Result monsters
local function createFusionResultTable()
local previousDescription, currentTable
-- Creates tables/rows for each combination found
for _, combination in ipairs(_combinationsQuery) do
local combi_id, mats1, mats2, description, columns = combination[1], combination["Fusion Material 1"], combination["Fusion Material 2"], combination["Description"], combination["Columns"] or 1
local combination_exceptions = {}
-- MW attributes don't return a table if there is only 1 value. Converting both to tables to facilitate future processing
mats1 = toTable(mats1)
mats2 = toTable(mats2)
for _, combi_ex in ipairs(_exceptionsQuery) do
if combi_ex["For Fusion"] == combi_id then
combination_exceptions[unlink(combi_ex["Fusion Material exception 1"])] = unlink(combi_ex["Fusion Material exception 2"])
end
end
-- Creates a new table on the first itteration, and when a description changes
if not currentTable or description ~= previousDescription then
currentTable = _fusionDisplay:tag("table"):attr("class", "wikitable")
currentTable:tag("ul"):tag("li"):wikitext(description or '')
local header = currentTable:tag("tr")
header:tag("th"):attr("scope", "col"):wikitext("Material 1")
header:tag("th"):attr("scope", "col"):wikitext("Material 2")
end
-- Appends materials to the table
currentTable = fillTableForFusionResult(currentTable, mats1, mats2, columns, combination_exceptions)
previousDescription = description
end
end
-- @name createFusionMaterialTable
-- @description Creates the table to be displayed for Fusion Material monsters
local function createFusionMaterialTable()
local previousDescription, previousResult, currentTable
-- Creates tables/rows for each combination found
for _, combination in ipairs(_combinationsQuery) do
local combi_id, mats1, mats2, result, description, columns =
combination[1], combination["Fusion Material 1"], combination["Fusion Material 2"], combination["Fusion result"], combination["Description"], combination["Columns"] or 1
local cur_combi_exceptions = {}
-- MW attributes don't return a table if there is only 1 value. Converting both to tables to facilitate future processing
mats1 = toTable(mats1)
mats2 = toTable(mats2)
-- Build the materials and exceptions lists
local mats, excepts = setListsForFusionMaterialDisplay(mats1, mats2)
-- Dynamically calculate the number of columns
if #mats > 17 then
columns = 3
elseif #mats > 8 then
columns = 2
end
-- Creates a new table on the first itteration, and when a description changes
if not currentTable or description ~= previousDescription or result ~= previousResult then
mw.log(result .. ": " .. (description or 'nil') .. " " .. (previousDescription or 'nil'))
currentTable = _fusionDisplay:tag("table"):attr("class", "wikitable")
currentTable:tag("ul"):tag("li"):wikitext(formatCardDisplay(unlink(result)) .. (description and (" (" .. description .. ')') or ''))
currentTable:tag("tr"):tag("th"):attr("scope", "col"):wikitext("Materials")
end
-- Appends materials to the table
currentTable = fillTableForFusionMaterial(currentTable, mats, columns, excepts)
previousDescription = description
previousResult = result or previousResult
end
end
-- @name getCombinationsAndExceptionsForFusionResult
-- @description Gets the materials combinations and exceptions that result in this card
local function getCombinationsAndExceptionsForFusionResult()
_combinationsQuery = processCombinationsQuery( string.format("[[Fusion result::%s]]", _pageName ) ) or {}
_exceptionsQuery = runCombinationExceptionsQuery()
end
-- @name getCombinationsAndExceptionsForFusionMaterial
-- @description Gets the materials combinations and exceptions that this card is a material of
local function getCombinationsAndExceptionsForFusionMaterial()
_combinationsQuery = processCombinationsQuery( string.format("<q>[[Fusion Material 1::%s]] OR [[Fusion Material 2::%s]]</q>|sort = Fusion result.Card number", _pageName, _pageName ) ) or {}
_exceptionsQuery = runCombinationExceptionsQuery()
end
-- @name initParams
-- @description Sets values for all parameters accessible from the current context
local function initParams( frame )
_frame = frame;
_args = UTIL.getArgs( frame, {
trim = true,
removeBlanks = true,
parentOnly = true
} );
_fusionDisplay = HTML()
_pageName = _args[1] or "Mavelus (FMR)"
end
-- @name fusionResult
-- @description Generates the material lists for a given Fusion result. To be called through #invoke.
local function fusionResult( frame )
initParams(frame)
getCombinationsAndExceptionsForFusionResult()
createFusionResultTable()
return tostring(_fusionDisplay)
end
-- @name fusionMaterial
-- @description Generates the list of other materials and Fusion result for a given material. To be called through #invoke.
local function fusionMaterial( frame )
initParams(frame)
getCombinationsAndExceptionsForFusionMaterial()
createFusionMaterialTable()
return tostring(_fusionDisplay)
end
----------
-- Return:
----------
-- @exports
return {
['fusionResult'] = fusionResult,
['fusionMaterial'] = fusionMaterial
};
-- </pre>