Module:PatchObject
From Liquipedia Stormgate Wiki
Documentation for this module may be created at Module:PatchObject/doc
local Array = require('Module:Array')
local Class = require('Module:Class')
local DateExt = require('Module:Date/Ext')
local Faction = require('Module:Faction')
local Logic = require('Module:Logic')
local Page = require('Module:Page')
local String = require('Module:StringUtils')
local Table = require('Module:Table')
local Variables = require('Module:Variables')
local MAX_QUERY_AFFECTED = 25
local PATCH_OBJECT_TYPES = {
buff = '<i class="fas fa-plus forest-green-text" title="Buff" size="110%"></i> ',
nerf = '<i class="fas fa-minus cinnabar-text" title="Nerf" size="110%"></i> ',
change = '<i class="fas fa-question bright-sun-text" title="Change" size="110%"></i> ',
fix = '<i class="fas fa-wrench sapphire-text" title="Fix" size="110%"></i> ',
}
local PatchObject = {}
---@param args table?
---@return Html?
function PatchObject.run(args)
if Table.isEmpty(args) then return end
---@cast args -nil
local patchType = (args.type or ''):lower()
assert(PATCH_OBJECT_TYPES[patchType], 'Invalid type "' .. (args.type or '') .. '"')
assert(args.text, 'No text specified')
if not Logic.readBool(args.nostorage) and Logic.readBoolOrNil(Variables.varDefault('disable_LPDB_storage')) ~= false then
PatchObject._store(args, patchType)
end
return PatchObject._display(patchType, args.text)
end
---@param args any
---@param patchType any
function PatchObject._store(args, patchType)
args.patch = Logic.emptyOr(args.patch, mw.title.getCurrentTitle().prefixedText)
assert(args.affected1, 'No "affected1" specified')
local patchObject = (tonumber(Variables.varDefault('patchObject')) or 0) + 1
Variables.varDefine('patchObject', patchObject)
local extradata = {patchtype = patchType, text = args.text}
for key, affectedPage in Table.iter.pairsByPrefix(args, 'affected') do
extradata[key] = Page.pageifyLink(affectedPage)
end
mw.ext.LiquipediaDB.lpdb_datapoint('patchObject_' .. patchObject, {
type = 'patchObject',
name = args.patch:gsub(' ','_'),
information = Faction.read(args.faction) or ((args.faction or ''):lower() == 'map' and 'map') or Faction.defaultFaction,
extradata = mw.ext.LiquipediaDB.lpdb_create_json(extradata),
})
end
---@param patchType string
---@param text string
---@return string
function PatchObject._display(patchType, text)
return PATCH_OBJECT_TYPES[patchType] .. text
end
---@param args table?
---@return Html?
function PatchObject.retrieve(args)
args = args or {}
local patchObjects = mw.ext.LiquipediaDB.lpdb('datapoint', {
conditions = PatchObject._buildConditions(args),
limit = 5000,
})
if Table.isEmpty(patchObjects) then return end
local groupedByPatch
_, groupedByPatch = Array.groupBy(patchObjects, function(item) return item.name end)
for patch, data in pairs(groupedByPatch) do
data.date = PatchObject._FetchPatchDate(patch)
end
local display = mw.html.create('table')
:css('text-align', 'center')
:css('min-width', '68%')
:addClass('wikitable wikitable-stripped wikitable-bordered collapsible')
:node(PatchObject._header())
for patch, data in Table.iter.spairs(groupedByPatch, PatchObject._sortPatches) do
display:node(PatchObject._row(patch, data))
end
return mw.html.create('div')
:addClass('table-responsive')
:node(display)
end
---@param args table
---@return string
function PatchObject._buildConditions(args)
local conditions = {
'[[type::patchObject]]',
'[[name::!]]',
}
if args.patch then
table.insert(conditions, '[[name::' .. args.patch:gsub(' ', '_') .. ']]')
end
if args.faction then
table.insert(conditions, '[[information::' .. (Faction.read(args.faction) or args.faction) .. ']]')
if not args.page then
return table.concat(conditions, ' AND ')
end
end
local affectedPage = args.page or mw.title.getCurrentTitle().prefixedText:gsub(' ', '_')
local affectedConditions = Array.map(Array.range(1, MAX_QUERY_AFFECTED), function(affectedIndex)
return '[[extradata_affected' .. affectedIndex .. '::' .. affectedPage .. ']]'
end)
table.insert(conditions, '(' .. table.concat(affectedConditions, ' OR ') .. ')')
return table.concat(conditions, ' AND ')
end
---@param pageName string
---@return string
function PatchObject._FetchPatchDate(pageName)
local patch = mw.ext.LiquipediaDB.lpdb('datapoint', {
conditions = '[[type::patch]] AND [[pagename::' .. pageName .. ']]',
limit = 1,
})[1] or {}
return Logic.emptyOr(patch.date or DateExt.defaultDateTime)
end
---@return Html
function PatchObject._header()
return mw.html.create()
:tag('tr')
:tag('th'):attr('colspan', 3):wikitext('Balance Patch History'):done()
:done()
:tag('tr')
:addClass('wiki-backgroundcolor-light')
:css('font-weight', 'bold')
:tag('td'):css('width', '200px'):wikitext('Patch'):done()
:tag('td'):css('width', '92px'):wikitext('Release'):done()
:tag('td'):wikitext('Balance Changes')
:allDone()
end
---@param patch string
---@param data table
---@return Html
function PatchObject._row(patch, data)
local date = Table.extract(data, 'date')
local patch = '[[' .. patch .. '|' .. PatchObject._getPatchName(patch) .. ']]'
local row = mw.html.create('tr')
:tag('td'):wikitext(patch):done()
:tag('td'):wikitext(date ~= DateExt.defaultDateTime and date:sub(1, 10) or ''):done()
local changes = mw.html.create('ul')
local objectsByType = Array.groupBy(data, function(item) return item.extradata.patchtype end)
Array.forEach(objectsByType, function(group)
Array.forEach(group, function(patchObject)
changes:tag('li'):node(PatchObject._display(patchObject.extradata.patchtype, patchObject.extradata.text))
end)
end)
return row:tag('td')
:css('text-align', 'left')
:node(changes)
:done()
end
---@param patchPage string
---@return string
function PatchObject._getPatchName(patchPage)
local patch = mw.ext.LiquipediaDB.lpdb('datapoint', {
conditions = '[[type::patch]] AND [[pagename::' .. patchPage .. ']]',
limit = 1,
})[1] or {}
return String.nilIfEmpty(patch.name) or patchPage:gsub('_', ' ')
end
---@param tbl table
---@param key1 string
---@param key2 string
---@return boolean
function PatchObject._sortPatches(tbl, key1, key2)
return tbl[key1].date > tbl[key2].date
end
return Class.export(PatchObject)