Module:Armor/Query
Jump to navigation
Jump to search
This is the main module for the following templates:
local p = {}
local h = {}
local DataTable = require("Module:Data Table")
local Term = require("Module:Term")
local utilsArg = require("Module:UtilsArg")
local utilsCargo = require("Module:UtilsCargo")
local utilsString = require("Module:UtilsString")
local utilsTable = require("Module:UtilsTable")
local CATEGORY_INVALID_ARGS = "[[Category:"..require("Module:Constants/category/invalidArgs").."]]"
function h.err(errMsg, warnMsg)
local utilsError = require("Module:UtilsError")
return utilsError.error(errMsg, warnMsg)
end
function h.warn(warnMsg, ...)
local utilsError = require("Module:UtilsError")
utilsError.warn(string.format(warnMsg, ...))
end
function p.ArmorList(frame)
local args, err = utilsArg.parse(frame:getParent().args, p.Templates["Armor List"])
local categories = err and err.categoryText or ""
if not args.game then
return err.categoryText
end
local armorData = utilsCargo.query("Armor=Sets, ArmorLevels=Levels", "Sets.armorSet=armorSet, Sets.bodyPart=bodyPart, Levels.armor=armor, Levels.level=level, Levels.defense=defense, Levels.materials=materials, Levels.sellable=sellable, Levels.sellPrice=sellPrice, Levels.description=description", {
join = "Levels.armor = Sets.armor, Levels.game = Sets.game",
where = utilsCargo.allOf({
["Levels.game"] = args.game,
}),
limit = 1000,
})
categories = categories..utilsCargo.categoryQuerying()
armorData = utilsTable.sortBy(armorData, function(armor)
local sortKey = armor.armor..(armor.level or "")
if armor.armorSet and armor.armorSet ~= "" then
sortKey = armor.armorSet..h.bodyPartSortKey(armor.bodyPart)..sortKey
end
return sortKey
end)
local columns = {"Armor Set [Term]", "Body Part", "Armor [Nowrap][Rowspan][Image:Icon:144x144px][Term]", "Level", string.format("Defense [Defense:%s:-]", args.game), "Sell Price [Rupees]", "Description [Transcript]"}
local rows = utilsTable.map(armorData, function(armor)
return {
cells = {
armor.armorSet or "N/A",
armor.bodyPart or "",
armor.armor or "",
armor.level or "",
armor.defense or "",
armor.sellable == "1" and (armor.sellPrice or "") or "N/A",
armor.description or "",
}
}
end)
local categories2 = h.annotateTable(rows, columns, args.notes)
categories = categories..categories2
local dataTable = DataTable.printTable(rows, {
game = args.game,
columns = columns,
}, function (tableArgs)
for i, row in ipairs(tableArgs.rows) do
row.cells[1].rowspan = row.cells[3].rowspan
row.cells[2].rowspan = row.cells[3].rowspan
row.cells[1].skip = row.cells[3].skip
row.cells[2].skip = row.cells[3].skip
end
return tableArgs
end)
return dataTable, categories
end
function p.ArmorLevels(frame)
local args, err = utilsArg.parse(frame:getParent().args, p.Templates["Armor Levels"])
local categories = err and err.categoryText or ""
if err then
return categories
end
local data = utilsCargo.query("ArmorLevels", "level, defense, materials, sellPrice, sellable, description", {
where = utilsCargo.allOf({
game = args.game,
armor = args.armor,
}),
orderBy = "level",
})
if #data == 0 then
categories = categories..CATEGORY_INVALID_ARGS
h.warn("No armor named <code>%s</code> is stored at [[Data:Armor/%s]].", args.armor, args.game)
return categories
end
if #data == 1 then
categories = categories..CATEGORY_INVALID_ARGS
h.warn("This template is for upgradeable armor only — <code>%s</code> has only one level stored at [[Data:Armor/%s]].", args.armor, args.game)
return categories
end
local rows = utilsTable.map(data, function(armor)
return {
cells = {
armor.level or "",
armor.defense or "",
armor.level and (armor.materials or "") or "N/A",
armor.sellable == "1" and (armor.sellPrice or "") or "N/A",
armor.description or "",
}
}
end)
local dataTable = DataTable.printTable(rows, {
game = args.game,
sortable = false,
columns = {"Level", string.format("Defense [Defense:%s:-]", args.game), "Materials [Amounts]", "Sell Price [Rupees]", "Description [Transcript]"}
})
return dataTable, categories
end
function p.ArmorSetPieces(frame)
local args, err = utilsArg.parse(frame:getParent().args, p.Templates["Armor Set Pieces"])
local categories = err and err.categoryText or ""
if err then
return categories
end
local armorSetPieces = utilsCargo.query("ArmorLevels=Levels, Armor=Sets", "Sets.armor=armor, Sets.armorSet=armorSet, Sets.bodyPart=bodyPart, Levels.level=level, Levels.defense=defense, Levels.materials=materials, Levels.sellable=sellable, Levels.sellPrice=sellPrice", {
join = "Levels.armor = Sets.armor, Levels.game = Sets.game",
where = utilsCargo.allOf({
["Levels.game"] = args.game,
["Sets.armorSet"] = args.armorSet,
}),
})
categories = categories..utilsCargo.categoryQuerying()
if #armorSetPieces == 0 then
categories = categories..CATEGORY_INVALID_ARGS
return h.err("Data not found", string.format("No such armor set <code>%s</code> is stored at [[Data:Armor/%s]].", args.armorSet, args.game)), categories
end
local isUpgradeable = utilsTable.find(armorSetPieces, "level")
-- Sort armor by slot, then by name, then by level
armorSetPieces = utilsTable.sortBy(armorSetPieces, function(armor)
return h.bodyPartSortKey(armor.bodyPart)..armor.armor..(armor.level or "")
end)
local rows = utilsTable.map(armorSetPieces, function(armor)
if isUpgradeable then
return {
cells = {
armor.armor or "",
armor.level or "",
armor.defense or "",
armor.level and (armor.materials or "") or "N/A",
armor.sellable == "1" and (armor.sellPrice or "") or "N/A",
}
}
else
return {
cells = {
armor.armor or "",
armor.defense or "",
armor.sellable == "1" and (armor.sellPrice or "") or "N/A",
}
}
end
end)
local columns
if isUpgradeable then
columns = {"Armor [Rowspan][Image:Icon:144x144px][Term]", "Level", string.format("Defense [Defense:%s:-]", args.game), "Materials [Amounts]", "Sell Price [Rupees]"}
else
columns = {"Armor [Image:Icon:144x144px][Term]", string.format("Defense [Defense:%s:-]", args.game), "Sell Price [Rupees]"}
end
local dataTable = DataTable.printTable(rows, {
game = args.game,
sortable = false,
columns = columns
})
return dataTable, categories
end
function p.MaterialArmors(frame)
local args, err = utilsArg.parse(frame:getParent().args, p.Templates["Material Armors"])
local categories = err and err.categoryText or ""
if err then
return categories
end
local material = args.material
local armorRows = utilsCargo.query("ArmorLevels", "armor, level, materials", {
where = "game = '"..args.game.."' AND materials LIKE '%"..utilsCargo.escape(material).."%'",
orderBy = "armor, level"
})
categories = categories .. utilsCargo.categoryQuerying()
-- Do an exact match on the material name as the SQL query above will return rows containing "Giant Ancient Core" for material "Ancient Row"
-- At the same time, compute the total of this material that is required to upgrade everything
local totalAmountRequired = 0
armorRows = utilsTable.filter(armorRows, function(armorRow)
local materials = utilsString.split(armorRow.materials)
armorRow.materialAmounts = {}
for i, armorMaterial in ipairs(materials) do
local amount = string.match(armorMaterial, "^(%d+)%s+")
local materialName = string.gsub(armorMaterial, "^(%d+)%s+", "")
if materialName == material then
totalAmountRequired = totalAmountRequired + tonumber(amount)
return true
end
end
end)
if #armorRows == 0 then
categories = categories..CATEGORY_INVALID_ARGS
return h.err("Data not found", string.format("No upgrade data exists for material <code>%s</code> on page [[Data:Armor/%s]]", material, args.game)), categories
end
local tableRows = utilsTable.map(armorRows, function(armorRow)
return {
cells = {
armorRow.armor,
armorRow.level,
armorRow.materials,
}
}
end)
local dataTable = DataTable.printTable(tableRows, {
game = args.game,
columns = {"Armor [Rowspan][Image:Icon:144x144px][Term]", "Level", "Materials [Amounts]"},
sortable = false,
})
local plural = Term.plural(material, args.game)
local totalRequired = string.format("'''Total %s required:''' %d", plural, totalAmountRequired)
local result = dataTable.."<div>"..totalRequired.."</div>"
return result, categories
end
function h.bodyPartSortKey(bodyPart)
if bodyPart == "Head" then
return "1"
elseif bodyPart == "Chest" then
return "2"
elseif bodyPart == "Legs" then
return "3"
else
return "4"
end
end
function h.annotateTable(rows, columns, notes)
if not notes then
return
end
local categories = ""
local addedNotes = {}
for i, row in ipairs(rows) do
columns = DataTable.extractColumnTags(columns)
local categories = ""
for j, note in ipairs(notes) do
local matchesRow = utilsTable.includes(row.cells, note.row)
local columnIndex = utilsTable.findIndex(columns, function(column)
return column == note.column
end)
if matchesRow and columnIndex then
row.cells[columnIndex] = row.cells[columnIndex]..note.note
end
if not columnIndex then
h.warn("No such column <code>%s</code>", note.row)
categories = categories..CATEGORY_INVALID_ARGS
end
if matchesRow then
table.insert(addedNotes, j)
end
end
end
local unmatchedNotes = utilsTable.difference(utilsTable.keys(notes), addedNotes)
for i, noteIndex in ipairs(unmatchedNotes) do
h.warn("No row <code>%s</code> found for note %d", notes[noteIndex].row, noteIndex)
categories = categories..CATEGORY_INVALID_ARGS
end
return categories
end
p.Templates = {
["Armor List"] = {
format = "block",
paramOrder = {1, "note", "row", "column"},
repeatedGroup = {
name = "notes",
params = {"note", "row", "column"},
},
params = {
[1] = {
name = "game",
inline = true,
required = true,
trim = true,
nilIfEmpty = true,
type = "string",
desc = "A game code from [[Data:Franchise]].",
},
note = {
name = "note",
type = "wikitext",
desc = "An annotation to add to a table cell.",
},
row = {
type = "string",
desc = "The name of the armor identifying the row to add the annotation to.",
},
column = {
type = "string",
desc = "The name of the column identifying the cell to add the annotation to.",
},
},
},
["Armor Levels"] = {
params = {
[1] = {
name = "game",
required = true,
type = "string",
desc = "A game code from [[Data:Franchise]].",
},
[2] = {
name = "armor",
required = true,
type = "wiki-page-name",
desc = "A wiki page name referring to a particular piece of [[Armor]] as named in <code>game</code>.",
},
},
},
["Armor Set Pieces"] = {
params = {
[1] = {
name = "game",
required = true,
type = "string",
desc = "A game code from [[Data:Franchise]].",
},
[2] = {
name = "armorSet",
required = true,
type = "wiki-page-name",
desc = "A wiki page name referring to a particular [[Armor Set]] as named in <code>game</code>.",
},
},
},
["Material Armors"] = {
params = {
[1] = {
name = "game",
required = true,
type = "string",
desc = "A game code from [[Data:Franchise]].",
},
[2] = {
name = "material",
required = true,
type = "wiki-page-name",
desc = "A wiki page name referring to a particular [[Material]] as named in <code>game</code>.",
},
},
},
}
return p