From df9ceeb0cc0a268afe36450d19680e1bca7a3fe3 Mon Sep 17 00:00:00 2001 From: hjpalpha Date: Wed, 22 Apr 2026 17:17:39 +0200 Subject: [PATCH 01/18] feat: FactionMapStats --- lua/wikis/commons/FactionMapStatistics.lua | 427 +++++++++++++++++++++ 1 file changed, 427 insertions(+) create mode 100644 lua/wikis/commons/FactionMapStatistics.lua diff --git a/lua/wikis/commons/FactionMapStatistics.lua b/lua/wikis/commons/FactionMapStatistics.lua new file mode 100644 index 00000000000..68a09902513 --- /dev/null +++ b/lua/wikis/commons/FactionMapStatistics.lua @@ -0,0 +1,427 @@ +--- +-- @Liquipedia +-- page=Module:FactionMapStatistics +-- +-- Please see https://github.com/Liquipedia/Lua-Modules to contribute +-- + +local Lua = require('Module:Lua') + +local Arguments = Lua.import('Module:Arguments') +local Array = Lua.import('Module:Array') +local DateExt = Lua.import('Module:Date/Ext') +local Faction = Lua.import('Module:Faction') +local FnUtil = Lua.import('Module:FnUtil') +local Json = Lua.import('Module:Json') +local Logic = Lua.import('Module:Logic') +local Lpdb = Lua.import('Module:Lpdb') +local MathUtil = Lua.import('Module:MathUtil') +local Operator = Lua.import('Module:Operator') +local Page = Lua.import('Module:Page') +local Table = Lua.import('Module:Table') + +local Condition = Lua.import('Module:Condition') +local ConditionTree = Condition.Tree +local ConditionNode = Condition.Node +local Comparator = Condition.Comparator +local BooleanOperator = Condition.BooleanOperator +local ColumnName = Condition.ColumnName +local ConditionUtil = Condition.Util + +local Link = Lua.import('Module:Widget/Basic/Link') +local HtmlWidgets = Lua.import('Module:Widget/Html/All') +local TableWidgets = Lua.import('Module:Widget/Table2/All') +local WidgetUtil = Lua.import('Module:Widget/Util') + +local DEFAULT_MAP_NAME = 'Unknown' +local SUM_ABBR = HtmlWidgets.Abbr{title = 'Sum of', children = 'Σ'} +local NUMBER_OF_ABBR = HtmlWidgets.Abbr{title = 'Number of', children = '#'} + +local MapStatistics = {} + +---@param frame Frame +---@return Widget? +function MapStatistics.run(frame) + local args = Arguments.getArgs(frame) + + local matchUps = MapStatistics._getMatchups() + local mapsData = MapStatistics._fetchData(args, matchUps) + if Logic.isEmpty(mapsData) then + return + end + ---@cast mapsData -nil + + if args.mode == 'mapStats' then + Array.forEach(mapsData, MapStatistics._store) + end + + return TableWidgets.Table{ + sortable = true, + columns = WidgetUtil.collect( + {align = 'left'}, + Array.rep({align = 'right'}, 1 + 4 * #matchUps.vs + #matchUps.mirrors) + ), + children = { + MapStatistics._header(matchUps), + TableWidgets.TableBody{ + children = Array.map(mapsData, FnUtil.curry(MapStatistics._row, matchUps)) + } + } + } +end + +---@return {vs: string[], mirrors: string[]} +function MapStatistics._getMatchups() + local vs = {} + local done = {} + + ---@param faction1 string + ---@param faction2 string + ---@return boolean + local alreadyDone = function(faction1, faction2) + if done[faction1 .. ',' .. faction2] then + return true + end + done[faction1 .. ',' .. faction2] = true + if done[faction2 .. ',' .. faction1] then + return true + end + done[faction2 .. ',' .. faction1] = true + return false + end + + --- this loop is only wanted/needed so that each faction is on the left at least once... + Array.forEach(Faction.coreFactions, function(faction, factionIndex) + local nextFaction = Faction.coreFactions[factionIndex + 1] or Faction.coreFactions[1] + if faction == nextFaction or alreadyDone(faction, nextFaction) then + return + end + table.insert(vs, faction .. ',' .. nextFaction) + end) + + Array.forEach(Faction.coreFactions, function(faction1) + Array.forEach(Faction.coreFactions, function(faction2) + if not alreadyDone(faction1, faction2) then + table.insert(vs, faction1 .. ',' .. faction2) + end + end) + end) + + return { + vs = vs, + mirrors = Table.copy(Faction.coreFactions), -- copy to remove the metatable which breaks some stuff + } +end + +---@param args table +---@param matchUps {vs: string[], mirrors: string[]} +---@return {map: string, mapDisplayName: string?, total: integer, +---vs: table, mirrors: table}[]? +function MapStatistics._fetchData(args, matchUps) + ---@param gameData match2game? + ---@return {map: string, mapDisplayName: string?, total: integer, + ---vs: table, mirrors: table}? + local makeInitialMapData = function(gameData) + return { + map = (gameData or {}).map or 'total', + mapDisplayName = ((gameData or {}).extradata or {}).displayname, + total = 0, + vs = Table.map(matchUps.vs, function(index, key) return key, {w = 0, l = 0} end), + mirrors = Table.map(matchUps.mirrors, function(index, key) return key, 0 end), + } + end + + ---@param gameData match2game + ---@return boolean + local isValidGame = function(gameData) + local map = gameData.map + return map ~= 'skip' + and (map or ''):lower() ~= 'submatch' + and #gameData.opponents == 2 + and Array.all(gameData.opponents, function(opponent) + return opponent.status == 'S' + end) + end + + local data = {total = makeInitialMapData()} + + ---@param map string + ---@param faction1 string + ---@param faction2 string + ---@param winnerScore integer + ---@param loserScore integer + local apply = function(map, faction1, faction2, winnerScore, loserScore) + if faction1 == faction2 then + data[map].mirrors[faction1] = data[map].mirrors[faction1] + winnerScore + loserScore + data[map].total = data[map].total + winnerScore + loserScore + return + end + + local matchUp = faction1 .. ',' .. faction2 + if not data[map].vs[matchUp] then + matchUp = faction2 .. ',' .. faction1 + winnerScore, loserScore = loserScore, winnerScore + end + + data[map].vs[matchUp].w = data[map].vs[matchUp].w + winnerScore + data[map].vs[matchUp].l = data[map].vs[matchUp].l + loserScore + data[map].total = data[map].total + winnerScore + loserScore + end + + Lpdb.executeMassQuery('match2game', { + conditions = MapStatistics._buildConditions(args), + query = 'map, extradata, opponents, winner', + }, function(gameData) + if not isValidGame(gameData) then + return + end + + local map = gameData.map + + if Logic.isEmpty(map) or string.lower(map) == 'tbd' then + map = DEFAULT_MAP_NAME + end + data[map] = data[map] or makeInitialMapData(gameData) + + local winnerFaction = gameData.extradata.winnerfaction + if not Table.includes(Faction.coreFactions, winnerFaction) then + return + end + + local loserFaction = gameData.extradata.loserfaction + if not Table.includes(Faction.coreFactions, loserFaction) then + return + end + + local winnerIndex = tonumber(gameData.winner) or 0 + local loserIndex = 3 - winnerIndex + local winnerScore = gameData.opponents[winnerIndex].score or 0 + local loserScore = gameData.opponents[loserIndex].score or 0 + + apply(map, winnerFaction, loserFaction, winnerScore, loserScore) + apply('total', winnerFaction, loserFaction, winnerScore, loserScore) + end) + + local total = Table.extract(data, 'total') + local unknown = Table.extract(data, DEFAULT_MAP_NAME) + local mapsData = Array.extractValues(data) + + return Array.appendWith( + mapsData, + Logic.nilOr(Logic.readBoolOrNil(args.unknown), true) and unknown or nil, + #mapsData > 1 and total or nil + ) +end + +---@param args table +---@return string +function MapStatistics._buildConditions(args) + local conditions = ConditionTree(BooleanOperator.all):add{ + ConditionNode(ColumnName('status'), Comparator.eq, ''), + ConditionNode(ColumnName('mode'), Comparator.eq, '1v1'), + } + + local startDate = DateExt.readTimestamp(args.sdate) + if startDate then + conditions:add(ConditionNode(ColumnName('date'), Comparator.ge, startDate)) + end + local endDate = DateExt.readTimestamp(args.edate) + if endDate then + conditions:add(ConditionNode(ColumnName('date'), Comparator.le, endDate)) + end + + local mapsInput = args.maps or args.map + or args.mode == 'mapStats' and mw.title.getCurrentTitle().text + or nil + local maps = Array.parseCommaSeparatedString(mapsInput) + maps = Array.filter(maps, function(map) return map ~= 'TBD' end) + if Logic.isNotEmpty(maps) then + conditions:add(ConditionUtil.anyOf(ColumnName('map'), maps)) + end + + local parents = Array.parseCommaSeparatedString(args.parents or args.parent) + if Logic.isNotEmpty(parents) then + conditions:add(ConditionUtil.anyOf(ColumnName('parent'), Array.map(parents, Page.pageifyLink))) + end + + local tournaments = MapStatistics._getTournaments(args) + if Logic.isNotEmpty(tournaments) then + ---@cast tournaments -nil + conditions:add(ConditionUtil.anyOf(ColumnName('pagename'), Array.map(tournaments, Page.pageifyLink))) + end + + return tostring(conditions) +end + +---@param mapData {map: string, mapDisplayName: string?, total: integer, +---vs: table, mirrors: table} +function MapStatistics._store(mapData) + if Lpdb.isStorageDisabled() or mapData.map == 'Unknown' then + return + end + + local ratios = {} + for key, winData in pairs(mapData.vs) do + local factions = Array.parseCommaSeparatedString(key) + local total = winData.w + winData.l + local ratio = total ~= 0 and (winData.w / total) or nil + ratios[factions[1] .. factions[2]] = ratio + ratios[factions[2] .. factions[1]] = ratio and (1 - ratio) or nil + end + + mw.ext.LiquipediaDB.lpdb_datapoint( + 'map_winrates_' .. mapData.map, + { + name = mapData.map, + type = 'map_winrates', + extradata = Json.stringify(ratios), + } + ) +end + +---@param args table +---@return string[]? +function MapStatistics._getTournaments(args) + ---@param series string? + ---@return string[]? + local fromSeries = function(series) + if Logic.isEmpty(series) then + return + end + local tournaments = mw.ext.LiquipediaDB.lpdb('tournament', { + conditions = tostring(ConditionNode(ColumnName('seriespage'), Comparator.eq, Page.pagifyLink(series))), + query = 'pagename', + limit = 5000 + }) + return Array.map(tournaments, Operator.property('pagename')) + end + + return Logic.nilIfEmpty(Array.parseCommaSeparatedString(args.tournaments or args.tournament)) + or Logic.nilIfEmpty(fromSeries(args.series)) + or args.mode == 'tournamentStats' and {mw.title.getCurrentTitle().text} + or nil +end + +---@param matchUps {vs: string[], mirrors: string[]} +---@return Widget +function MapStatistics._header(matchUps) + ---@param key string + ---@return Widget + local makeFactionHeader = function(key) + local factions = Array.parseCommaSeparatedString(key) + + return TableWidgets.CellHeader{ + colspan = 4, + align = 'center', + children = { + Faction.Icon{faction = factions[1]}, + ' vs. ', + Faction.Icon{faction = factions[2]}, + }, + } + end + + ---@param key string + ---@return Widget[] + local makeMatchUpHeader = function(key) + local factions = Array.parseCommaSeparatedString(key) + return { + TableWidgets.CellHeader{children = SUM_ABBR}, + TableWidgets.CellHeader{children = Faction.Icon{faction = factions[1]}}, + TableWidgets.CellHeader{children = Faction.Icon{faction = factions[2]}}, + TableWidgets.CellHeader{ + children = { + Faction.Icon{faction = factions[1]}, + '%' + } + }, + } + end + + return TableWidgets.TableHeader{ + children = { + TableWidgets.Row{ + children = WidgetUtil.collect( + TableWidgets.CellHeader{children = '', colspan = 2}, + Array.map(matchUps.vs, makeFactionHeader), + TableWidgets.CellHeader{children = 'Mirrors', align = 'center', colspan = #matchUps.mirrors} + ) + }, + TableWidgets.Row{ + children = WidgetUtil.collect( + TableWidgets.CellHeader{children = 'Map'}, + TableWidgets.CellHeader{children = NUMBER_OF_ABBR}, + Array.flatMap(matchUps.vs, makeMatchUpHeader), + Array.map(matchUps.mirrors, function(faction) + return TableWidgets.CellHeader{children = Faction.Icon{faction = faction}} + end) + ) + } + }, + } +end + +---@param matchUps {vs: string[], mirrors: string[]} +---@param mapData {map: string, mapDisplayName: string?, total: integer, +---vs: table, mirrors: table} +---@return Widget? +function MapStatistics._row(matchUps, mapData) + if Logic.isEmpty(mapData) then + return + end + + ---@param input integer|string + ---@return integer|string + local dashIfZero = function(input) + return input == 0 and '-' or input + end + + ---@param matchUpData {w: integer, l: integer} + ---@return string + local getPercentage = function(matchUpData) + local total = matchUpData.w + matchUpData.l + if total == 0 then + return '-' + end + local percentage = 100 * matchUpData.w / (total) + return MathUtil.formatRounded{precision = 1, value = percentage} + end + + ---@return Renderable[]|Renderable + local makeMapCell = function() + if mapData.map == DEFAULT_MAP_NAME then + return DEFAULT_MAP_NAME + end + if mapData.map == 'total' then + return { + 'Total Sum (', + SUM_ABBR, + ')' + } + end + return Link{link = mapData.map, children = mapData.mapDisplayName} + end + + return TableWidgets.Row{ + children = WidgetUtil.collect( + TableWidgets.Cell{ + children = makeMapCell() + }, + TableWidgets.Cell{children = dashIfZero(mapData.total)}, + Array.flatMap(matchUps.vs, function(key) + local matchUpData = mapData.vs[key] + return { + TableWidgets.Cell{children = dashIfZero(matchUpData.w + matchUpData.l)}, + TableWidgets.Cell{children = dashIfZero(matchUpData.w)}, + TableWidgets.Cell{children = dashIfZero(matchUpData.l)}, + TableWidgets.Cell{children = getPercentage(matchUpData)}, + } + end), + Array.map(matchUps.mirrors, function(faction) + return TableWidgets.Cell{children = dashIfZero(mapData.mirrors[faction])} + end) + ) + } +end + +return MapStatistics From 5ce43b7ec5b83f3dea9f3404389675047ed71991 Mon Sep 17 00:00:00 2001 From: hjpalpha Date: Sun, 26 Apr 2026 11:13:47 +0200 Subject: [PATCH 02/18] rename & extract some stuff that can be reused for the other module(s) --- .../Map.lua} | 32 +++----------- .../FactionStatistics/MatchupDisplay.lua | 44 +++++++++++++++++++ 2 files changed, 49 insertions(+), 27 deletions(-) rename lua/wikis/commons/{FactionMapStatistics.lua => FactionStatistics/Map.lua} (92%) create mode 100644 lua/wikis/commons/FactionStatistics/MatchupDisplay.lua diff --git a/lua/wikis/commons/FactionMapStatistics.lua b/lua/wikis/commons/FactionStatistics/Map.lua similarity index 92% rename from lua/wikis/commons/FactionMapStatistics.lua rename to lua/wikis/commons/FactionStatistics/Map.lua index 68a09902513..73426108f98 100644 --- a/lua/wikis/commons/FactionMapStatistics.lua +++ b/lua/wikis/commons/FactionStatistics/Map.lua @@ -1,6 +1,6 @@ --- -- @Liquipedia --- page=Module:FactionMapStatistics +-- page=Module:FactionStatistics/Map -- -- Please see https://github.com/Liquipedia/Lua-Modules to contribute -- @@ -11,6 +11,7 @@ local Arguments = Lua.import('Module:Arguments') local Array = Lua.import('Module:Array') local DateExt = Lua.import('Module:Date/Ext') local Faction = Lua.import('Module:Faction') +local MatchupDisplay = Lua.import('FactionStatistics/MatchupDisplay') local FnUtil = Lua.import('Module:FnUtil') local Json = Lua.import('Module:Json') local Logic = Lua.import('Module:Logic') @@ -370,23 +371,6 @@ function MapStatistics._row(matchUps, mapData) return end - ---@param input integer|string - ---@return integer|string - local dashIfZero = function(input) - return input == 0 and '-' or input - end - - ---@param matchUpData {w: integer, l: integer} - ---@return string - local getPercentage = function(matchUpData) - local total = matchUpData.w + matchUpData.l - if total == 0 then - return '-' - end - local percentage = 100 * matchUpData.w / (total) - return MathUtil.formatRounded{precision = 1, value = percentage} - end - ---@return Renderable[]|Renderable local makeMapCell = function() if mapData.map == DEFAULT_MAP_NAME then @@ -407,18 +391,12 @@ function MapStatistics._row(matchUps, mapData) TableWidgets.Cell{ children = makeMapCell() }, - TableWidgets.Cell{children = dashIfZero(mapData.total)}, + TableWidgets.Cell{children = MatchupDisplay.dashIfZero(mapData.total)}, Array.flatMap(matchUps.vs, function(key) - local matchUpData = mapData.vs[key] - return { - TableWidgets.Cell{children = dashIfZero(matchUpData.w + matchUpData.l)}, - TableWidgets.Cell{children = dashIfZero(matchUpData.w)}, - TableWidgets.Cell{children = dashIfZero(matchUpData.l)}, - TableWidgets.Cell{children = getPercentage(matchUpData)}, - } + return MatchupDisplay.display(mapData.vs[key]) end), Array.map(matchUps.mirrors, function(faction) - return TableWidgets.Cell{children = dashIfZero(mapData.mirrors[faction])} + return TableWidgets.Cell{children = MatchupDisplay.dashIfZero(mapData.mirrors[faction])} end) ) } diff --git a/lua/wikis/commons/FactionStatistics/MatchupDisplay.lua b/lua/wikis/commons/FactionStatistics/MatchupDisplay.lua new file mode 100644 index 00000000000..0e08807026f --- /dev/null +++ b/lua/wikis/commons/FactionStatistics/MatchupDisplay.lua @@ -0,0 +1,44 @@ +--- +-- @Liquipedia +-- page=Module:FactionStatistics/MatchupDisplay +-- +-- Please see https://github.com/Liquipedia/Lua-Modules to contribute +-- + +local Lua = require('Module:Lua') + +local MathUtil = Lua.import('Module:MathUtil') + +local TableWidgets = Lua.import('Module:Widget/Table2/All') + +local MatchupDisplay = {} + +---@param matchupData {w: number, l: number} +---@return Widget[] +function MatchupDisplay.display(matchupData) + local total = matchupData.w + matchupData.l + + ---@return string + local getPercentage = function() + if total == 0 then + return '-' + end + local percentage = 100 * matchupData.w / (total) + return MathUtil.formatRounded{precision = 1, value = percentage} + end + + return { + TableWidgets.Cell{children = MatchupDisplay.dashIfZero(total)}, + TableWidgets.Cell{children = MatchupDisplay.dashIfZero(matchupData.w)}, + TableWidgets.Cell{children = MatchupDisplay.dashIfZero(matchupData.l)}, + TableWidgets.Cell{children = getPercentage()}, + } +end + +---@param input integer|string +---@return integer|string +function MatchupDisplay.dashIfZero(input) + return input == 0 and '-' or input +end + +return MatchupDisplay \ No newline at end of file From 1a506f5bf38597a3cde297a187323dce4e1b1ff4 Mon Sep 17 00:00:00 2001 From: hjpalpha Date: Sun, 26 Apr 2026 13:15:33 +0200 Subject: [PATCH 03/18] start on player stats --- lua/wikis/commons/FactionStatistics/Map.lua | 1 - .../commons/FactionStatistics/Player.lua | 404 ++++++++++++++++++ 2 files changed, 404 insertions(+), 1 deletion(-) create mode 100644 lua/wikis/commons/FactionStatistics/Player.lua diff --git a/lua/wikis/commons/FactionStatistics/Map.lua b/lua/wikis/commons/FactionStatistics/Map.lua index 73426108f98..be751d95711 100644 --- a/lua/wikis/commons/FactionStatistics/Map.lua +++ b/lua/wikis/commons/FactionStatistics/Map.lua @@ -16,7 +16,6 @@ local FnUtil = Lua.import('Module:FnUtil') local Json = Lua.import('Module:Json') local Logic = Lua.import('Module:Logic') local Lpdb = Lua.import('Module:Lpdb') -local MathUtil = Lua.import('Module:MathUtil') local Operator = Lua.import('Module:Operator') local Page = Lua.import('Module:Page') local Table = Lua.import('Module:Table') diff --git a/lua/wikis/commons/FactionStatistics/Player.lua b/lua/wikis/commons/FactionStatistics/Player.lua new file mode 100644 index 00000000000..9c5e84cf84a --- /dev/null +++ b/lua/wikis/commons/FactionStatistics/Player.lua @@ -0,0 +1,404 @@ +--- +-- @Liquipedia +-- page=Module:FactionStatistics/Player +-- +-- Please see https://github.com/Liquipedia/Lua-Modules to contribute +-- + +local Lua = require('Module:Lua') + +local Arguments = Lua.import('Module:Arguments') +local Array = Lua.import('Module:Array') +local Class = Lua.import('Module:Class') +local DateExt = Lua.import('Module:Date/Ext') +local Faction = Lua.import('Module:Faction') +local Logic = Lua.import('Module:Logic') +local Lpdb = Lua.import('Module:Lpdb') +local MatchupDisplay = Lua.import('Module:FactionStatistics/MatchupDisplay') +local Opponent = Lua.import('Module:Opponent/Custom') +local Page = Lua.import('Module:Page') +local String = Lua.import('Module:String/Utils') +local Table = Lua.import('Module:Table') + +local Condition = Lua.import('Module:Condition') +local ConditionTree = Condition.Tree +local ConditionNode = Condition.Node +local Comparator = Condition.Comparator +local BooleanOperator = Condition.BooleanOperator +local ColumnName = Condition.ColumnName +local ConditionUtil = Condition.Util + +local Box = Lua.import('Module:Widget/Basic/Box') +local HtmlWidgets = Lua.import('Module:Widget/Html/All') +local TableWidgets = Lua.import('Module:Widget/Table2/All') +local WidgetUtil = Lua.import('Module:Widget/Util') + +local DEFAULT_TIERS = {1, 2} +local DEFAULT_TIER_TYPE = 'Unset' +local SUM_ABBR = HtmlWidgets.Abbr{title = 'Sum of', children = 'Σ'} + +---@class StormgatePlayerMatchupStatistics +---@operator call(table): StormgatePlayerMatchupStatistics +---@field args table +---@field matchIds string[] +---@field player string +---@field versus string? +---@field byFaction table +---@field byType {online: {w: integer, l: integer}, offline: {w: integer, l: integer}} +---@field byBestof table +---@field byOpponentType table +---@field byMap table> +---@field total {w: integer, l: integer} +local PlayerStatistics = Class.new(function(self, args) self:init(args) end) + +---@param frame Frame +---@return Widget|string +function PlayerStatistics.run(frame) + local args = Arguments.getArgs(frame) + + return PlayerStatistics(args):query():create() +end + +---@param args table +---@return self +function PlayerStatistics:init(args) + self.args = args + assert(args.player, 'No player specified') + self.player = Page.pageifyLink(self.args.player) + + if Logic.isNotEmpty(self.args.versus) then + self.versus = Page.pageifyLink(self.args.versus) + end + + return self +end + +---@return self +function PlayerStatistics:query() + self:_getMatchData() + if Logic.isEmpty(self.matchIds) then return self end + self:_getMapData() + + return self +end + +function PlayerStatistics:_getMatchData() + self.matchIds = {} + + self.byFaction = Table.map(Faction.knownFactions, function(_, faction) return faction, {w = 0, l = 0} end) + self.byType = {online = {w = 0, l = 0}, offline = {w = 0, l = 0}} + self.byBestof = {} + self.byOpponentType = {} + self.total = {w = 0, l = 0} + + ---@param opponents table[] + ---@param winner integer? + ---@return boolean + local shouldExclude = function(opponents, winner) + return winner ~= 1 and winner ~= 2 + or not opponents[1] + or not opponents[1] + or #opponents ~= 2 + or Array.any(opponents, function(opponent) + return opponent.status and opponent.status ~= 'S' + end) + end + + Lpdb.executeMassQuery('match2', { + conditions = self:_getMatchConditions(), + query = 'match2id, bestof, match2opponents, winner, type', + }, function (record) + local winner = tonumber(record.winner) + local opponents = record.match2opponents + + if shouldExclude(opponents, winner) then return end + + table.insert(self.matchIds, record.match2id) + + local side = (opponents[1].name == self.player or Array.any(opponents[1].match2players or {}, function(playerObj) + return playerObj.name == self.player + end)) and 1 or 2 + + local vsSide = 3 - side + local result = side == winner and 'w' or 'l' + + self.total[result] = self.total[result] + 1 + + local eventType = string.lower(record.type or '') == 'offline' and 'offline' or 'online' + self.byType[eventType][result] = self.byType[eventType][result] + 1 + + local opponentType = opponents[vsSide].type + self.byOpponentType[opponentType] = self.byOpponentType[opponentType] or {w = 0, l = 0} + self.byOpponentType[opponentType][result] = self.byOpponentType[opponentType][result] + 1 + + local bestof = tostring(tonumber(record.bestof) or -1) + self.byBestof[bestof] = self.byBestof[bestof] or {w = 0, l = 0} + self.byBestof[bestof][result] = self.byBestof[bestof][result] + 1 + + if Array.any(opponents, function(opponent) return opponent.type ~= Opponent.solo end) then return end + + local vsFaction = Logic.emptyOr( + (((opponents[vsSide].match2players or {})[1] or {}).extradata or {}).faction, + Faction.defaultFaction + ) + if vsFaction == Faction.defaultFaction then return end + + self.byFaction[vsFaction][result] = self.byFaction[vsFaction][result] + 1 + end) +end + +---@return string +function PlayerStatistics:_getMatchConditions() + local args = self.args + + local tiers = Array.map(Array.parseCommaSeparatedString(args.tiers), function(num) + return tonumber(num) + end) + tiers = Logic.nilIfEmpty(tiers) or DEFAULT_TIERS + + local tierTypes = Array.parseCommaSeparatedString(args.tiers or '!Qualifier') + tierTypes = Array.map(tierTypes, function(tierType) + return tierType == DEFAULT_TIER_TYPE and '' or tierType + end) + + local conditions = ConditionTree(BooleanOperator.all):add{ + ConditionNode(ColumnName('finished'), Comparator.eq, 1), -- only finished matches + ConditionNode(ColumnName('winner'), Comparator.neq, ''), -- expect a winner + ConditionNode(ColumnName('status'), Comparator.neq, 'notplayed'), -- i.e. ignore not played matches + ConditionNode(ColumnName('date'), Comparator.neq, DateExt.defaultDate), --i.e. wrongly set up + ConditionUtil.anyOf(ColumnName('liquipediatier'), tiers), + ConditionUtil.anyOf(ColumnName('liquipediatiertype'), tierTypes), + } + + local startDate = DateExt.readTimestamp(args.sdate) + if startDate then + conditions:add(ConditionNode(ColumnName('date'), Comparator.ge, startDate)) + end + + local endDate = DateExt.readTimestamp(args.edate) + if endDate then + conditions:add(ConditionNode(ColumnName('date'), Comparator.le, endDate)) + end + + if self.versus then + conditions:add{ + ConditionNode(ColumnName('opponent'), Comparator.eq, self.player), + ConditionNode(ColumnName('opponent'), Comparator.eq, self.versus), + } + elseif Logic.readBool(args.onlySolo) then + conditions:add(ConditionNode(ColumnName('opponent'), Comparator.eq, self.player)) + else + conditions:add(ConditionNode(ColumnName('player'), Comparator.eq, self.player)) + end + + return tostring(conditions) +end + +function PlayerStatistics:_getMapData() + local player = self.player + + ---@return table + local newEmptyData = function() + return Table.map(Array.append(Faction.knownFactions, 'total'), function(index, key) + return key, {w = 0, l = 0} + end) + end + local byMap = {total = newEmptyData()} + + ---@param opponent table + ---@return boolean + local hasNonScoreStatusOrInvalidNumberOfPlayers = function(opponent) + return opponent.status and opponent.status ~= 'S' + or #opponent.players ~= 1 + end + + ---@param opponents table[] + ---@param winner integer? + ---@return string? + ---@return string? + local getResult = function(opponents, winner) + if Array.any(opponents, hasNonScoreStatusOrInvalidNumberOfPlayers) then + return + end + + local player1 = opponents[1].players[1].player + local faction1 = opponents[1].players[1].faction + local player2 = opponents[2].players[1].player + local faction2 = opponents[2].players[1].faction + + if player == player1 and winner == 1 then + return 'w', faction2 + elseif player == player2 and winner == 2 then + return 'w', faction1 + elseif player == player1 and winner == 2 then + return 'l', faction2 + elseif player == player2 and winner == 1 then + return 'l', faction1 + end + end + + ---@param record match2game + local processGame = function(record) + local result, vsFaction = getResult(record.opponents, tonumber(record.winner)) + if not result then return end + + byMap.total.total[result] = byMap.total.total[result] + 1 + + if vsFaction and vsFaction ~= Faction.defaultFaction then + byMap.total[vsFaction][result] = byMap.total[vsFaction][result] + 1 + end + + local map = Logic.nilIfEmpty(record.map) + if not map then + return + end + + byMap[map] = byMap[map] or newEmptyData() + byMap[map].total[result] = byMap[map].total[result] + 1 + + if vsFaction and vsFaction ~= Faction.defaultFaction then + byMap[map][vsFaction][result] = byMap[map][vsFaction][result] + 1 + end + end + + Lpdb.executeMassQuery('match2game', { + conditions = self:_getMapConditions(), + query = 'map, extradata, opponents, winner', + }, processGame) + + self.byMap = byMap +end + +---@return string +function PlayerStatistics:_getMapConditions() + ---@param opponent string + ---@return ConditionTree + local toOpponentCondition = function(opponent) + return ConditionTree(BooleanOperator.any):add{ + ConditionNode(ColumnName('opponent1', 'extradata'), Comparator.eq, opponent), + ConditionNode(ColumnName('opponent2', 'extradata'), Comparator.eq, opponent), + } + end + + local conditions = ConditionTree(BooleanOperator.all):add{ + ConditionNode(ColumnName('winner'), Comparator.neq, ''), -- expect a winner + ConditionNode(ColumnName('status'), Comparator.neq, 'notplayed'), -- i.e. ignore not played maps + ConditionNode(ColumnName('date'), Comparator.neq, DateExt.defaultDate), --i.e. wrongly set up + toOpponentCondition(self.player), + ConditionUtil.anyOf(ColumnName('match2id'), self.matchIds), + self.versus and toOpponentCondition(self.versus) or nil, + } + + return tostring(conditions) +end + +---@return Widget|string +function PlayerStatistics:create() + if Logic.isEmpty(self.matchIds) then + return 'No data found' + end + + return Box{ + children = { + self:_matchesPerFaction(), + self:_matchesPerType(), + self:_matchesPerOpponentType(), + self:_matchesPerBestof(), + self:_gamesPerMapAndFaction() + }, + } +end + +---@return Widget +function PlayerStatistics:_matchesPerFaction() + local display = function(key) + return { + 'vs. ', + key == 'total' and 'All' or Faction.Icon{faction = key}, + } + end + local order = Array.extend('total', Faction.knownFactions) + return PlayerStatistics._simpleTable(self.byFaction, display, order, 'Matches per Faction') +end + +---@return Widget +function PlayerStatistics:_matchesPerType() + local order = {'offline', 'online'} + return PlayerStatistics._simpleTable(self.byType, String.upperCaseFirst, order, 'Matches per Environment') +end + +---@return Widget +function PlayerStatistics:_matchesPerOpponentType() + local order = { + Opponent.solo, + Opponent.team, + Opponent.duo, + Opponent.trio, + Opponent.quad, + } + return PlayerStatistics._simpleTable(self.byOpponentType, String.upperCaseFirst, order, 'Matches per Opponent-Type') +end + +---@return Widget +function PlayerStatistics:_matchesPerBestof() + local display = function(key) + if key == '-1' then + return 'Unknown' + end + return HtmlWidgets.Abbr{title = 'Best of ' .. key, children = key} + end + local order = Array.extractKeys(self.byBestof) + Array.sortInPlaceBy(order, tonumber, function(a, b) + return b == -1 or (a ~= -1 and a < b) + end) + return PlayerStatistics._simpleTable(self.byBestof, display, order, 'Matches per Environment') +end + +---@return Widget +function PlayerStatistics:_gamesPerMapAndFaction() +end + +---@param data table +---@param display fun(string): Renderable +---@param order string[] +---@param title string +---@return Widget +function PlayerStatistics._simpleTable(data, display, order, title) + local rows = Array.map(order, function(key) + local matchupData = data[key] + if (matchupData.w + matchupData.l) == 0 then return end + return TableWidgets.Row{ + children = WidgetUtil.collect( + TableWidgets.Cell{children = display(key)}, + MatchupDisplay.display(matchupData) + ) + } + end) + + return TableWidgets.Table{ + sortable = false, + title = title, + columns = WidgetUtil.collect( + {align = 'left'}, + Array.rep({align = 'right'}, 4) + ), + children = { + PlayerStatistics._header(), + TableWidgets.TableBody{children = rows}, + }, + } +end + +---@return Widget +function PlayerStatistics._header() + return TableWidgets.Row{ + children = { + TableWidgets.CellHeader{children = SUM_ABBR}, + TableWidgets.CellHeader{children = 'W'}, + TableWidgets.CellHeader{children = 'L'}, + TableWidgets.CellHeader{children = '%'}, + } + } +end + +return PlayerStatistics From cf35a64c4c56acfe228eb98288af1e9d4df279f0 Mon Sep 17 00:00:00 2001 From: hjpalpha Date: Sun, 26 Apr 2026 13:26:33 +0200 Subject: [PATCH 04/18] fix import --- lua/wikis/commons/FactionStatistics/Map.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/wikis/commons/FactionStatistics/Map.lua b/lua/wikis/commons/FactionStatistics/Map.lua index be751d95711..e010c3b12ec 100644 --- a/lua/wikis/commons/FactionStatistics/Map.lua +++ b/lua/wikis/commons/FactionStatistics/Map.lua @@ -11,7 +11,7 @@ local Arguments = Lua.import('Module:Arguments') local Array = Lua.import('Module:Array') local DateExt = Lua.import('Module:Date/Ext') local Faction = Lua.import('Module:Faction') -local MatchupDisplay = Lua.import('FactionStatistics/MatchupDisplay') +local MatchupDisplay = Lua.import('Module:FactionStatistics/MatchupDisplay') local FnUtil = Lua.import('Module:FnUtil') local Json = Lua.import('Module:Json') local Logic = Lua.import('Module:Logic') From e61d54febf54571939fead53188f5bd3cb31dd85 Mon Sep 17 00:00:00 2001 From: hjpalpha Date: Sun, 26 Apr 2026 13:30:06 +0200 Subject: [PATCH 05/18] sort --- lua/wikis/commons/FactionStatistics/Map.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/wikis/commons/FactionStatistics/Map.lua b/lua/wikis/commons/FactionStatistics/Map.lua index e010c3b12ec..8fff78142c9 100644 --- a/lua/wikis/commons/FactionStatistics/Map.lua +++ b/lua/wikis/commons/FactionStatistics/Map.lua @@ -205,6 +205,7 @@ function MapStatistics._fetchData(args, matchUps) local total = Table.extract(data, 'total') local unknown = Table.extract(data, DEFAULT_MAP_NAME) local mapsData = Array.extractValues(data) + Array.sortInPlaceBy(mapsData, Operator.property('map')) return Array.appendWith( mapsData, From a20934b90268948022b74a1812f2710e1667a6cf Mon Sep 17 00:00:00 2001 From: hjpalpha Date: Sun, 26 Apr 2026 14:01:08 +0200 Subject: [PATCH 06/18] fixerino --- .../commons/FactionStatistics/Player.lua | 58 ++++++++++--------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/lua/wikis/commons/FactionStatistics/Player.lua b/lua/wikis/commons/FactionStatistics/Player.lua index 9c5e84cf84a..991c9a9bf62 100644 --- a/lua/wikis/commons/FactionStatistics/Player.lua +++ b/lua/wikis/commons/FactionStatistics/Player.lua @@ -17,7 +17,7 @@ local Lpdb = Lua.import('Module:Lpdb') local MatchupDisplay = Lua.import('Module:FactionStatistics/MatchupDisplay') local Opponent = Lua.import('Module:Opponent/Custom') local Page = Lua.import('Module:Page') -local String = Lua.import('Module:String/Utils') +local String = Lua.import('Module:StringUtils') local Table = Lua.import('Module:Table') local Condition = Lua.import('Module:Condition') @@ -85,11 +85,10 @@ end function PlayerStatistics:_getMatchData() self.matchIds = {} - self.byFaction = Table.map(Faction.knownFactions, function(_, faction) return faction, {w = 0, l = 0} end) + self.byFaction = PlayerStatistics._newEmptyFactionData() self.byType = {online = {w = 0, l = 0}, offline = {w = 0, l = 0}} self.byBestof = {} self.byOpponentType = {} - self.total = {w = 0, l = 0} ---@param opponents table[] ---@param winner integer? @@ -122,8 +121,6 @@ function PlayerStatistics:_getMatchData() local vsSide = 3 - side local result = side == winner and 'w' or 'l' - self.total[result] = self.total[result] + 1 - local eventType = string.lower(record.type or '') == 'offline' and 'offline' or 'online' self.byType[eventType][result] = self.byType[eventType][result] + 1 @@ -137,6 +134,8 @@ function PlayerStatistics:_getMatchData() if Array.any(opponents, function(opponent) return opponent.type ~= Opponent.solo end) then return end + self.byFaction.total[result] = self.byFaction.total[result] + 1 + local vsFaction = Logic.emptyOr( (((opponents[vsSide].match2players or {})[1] or {}).extradata or {}).faction, Faction.defaultFaction @@ -194,16 +193,17 @@ function PlayerStatistics:_getMatchConditions() return tostring(conditions) end +---@return table +function PlayerStatistics._newEmptyFactionData() + return Table.map(Array.append(Faction.knownFactions, 'total'), function(index, key) + return key, {w = 0, l = 0} + end) +end + function PlayerStatistics:_getMapData() local player = self.player - ---@return table - local newEmptyData = function() - return Table.map(Array.append(Faction.knownFactions, 'total'), function(index, key) - return key, {w = 0, l = 0} - end) - end - local byMap = {total = newEmptyData()} + local byMap = {total = PlayerStatistics._newEmptyFactionData()} ---@param opponent table ---@return boolean @@ -253,7 +253,7 @@ function PlayerStatistics:_getMapData() return end - byMap[map] = byMap[map] or newEmptyData() + byMap[map] = byMap[map] or PlayerStatistics._newEmptyFactionData() byMap[map].total[result] = byMap[map].total[result] + 1 if vsFaction and vsFaction ~= Faction.defaultFaction then @@ -317,7 +317,11 @@ function PlayerStatistics:_matchesPerFaction() key == 'total' and 'All' or Faction.Icon{faction = key}, } end - local order = Array.extend('total', Faction.knownFactions) + + -- can not use Array.extend due to the metatable ... see #7433 + local order = {'total'} + Array.forEach(Faction.knownFactions, function(faction) table.insert(order, faction) end) + return PlayerStatistics._simpleTable(self.byFaction, display, order, 'Matches per Faction') end @@ -345,7 +349,7 @@ function PlayerStatistics:_matchesPerBestof() if key == '-1' then return 'Unknown' end - return HtmlWidgets.Abbr{title = 'Best of ' .. key, children = key} + return HtmlWidgets.Abbr{title = 'Best of ' .. key, children = 'Bo' .. key} end local order = Array.extractKeys(self.byBestof) Array.sortInPlaceBy(order, tonumber, function(a, b) @@ -354,10 +358,6 @@ function PlayerStatistics:_matchesPerBestof() return PlayerStatistics._simpleTable(self.byBestof, display, order, 'Matches per Environment') end ----@return Widget -function PlayerStatistics:_gamesPerMapAndFaction() -end - ---@param data table ---@param display fun(string): Renderable ---@param order string[] @@ -366,7 +366,7 @@ end function PlayerStatistics._simpleTable(data, display, order, title) local rows = Array.map(order, function(key) local matchupData = data[key] - if (matchupData.w + matchupData.l) == 0 then return end + if not matchupData or (matchupData.w + matchupData.l == 0) then return end return TableWidgets.Row{ children = WidgetUtil.collect( TableWidgets.Cell{children = display(key)}, @@ -377,28 +377,34 @@ function PlayerStatistics._simpleTable(data, display, order, title) return TableWidgets.Table{ sortable = false, - title = title, + caption = title, columns = WidgetUtil.collect( {align = 'left'}, Array.rep({align = 'right'}, 4) ), children = { - PlayerStatistics._header(), + PlayerStatistics._header(true), TableWidgets.TableBody{children = rows}, }, } end +---@param emptyCell boolean? ---@return Widget -function PlayerStatistics._header() +function PlayerStatistics._header(emptyCell) return TableWidgets.Row{ - children = { + children = WidgetUtil.collect( + emptyCell and TableWidgets.CellHeader{children = ''} or nil, TableWidgets.CellHeader{children = SUM_ABBR}, TableWidgets.CellHeader{children = 'W'}, TableWidgets.CellHeader{children = 'L'}, - TableWidgets.CellHeader{children = '%'}, - } + TableWidgets.CellHeader{children = '%'} + ) } end +---@return Widget +function PlayerStatistics:_gamesPerMapAndFaction() +end + return PlayerStatistics From 9ba3e841996d0e346acca7c32b564ea6f47da182 Mon Sep 17 00:00:00 2001 From: hjpalpha Date: Sun, 26 Apr 2026 15:21:21 +0200 Subject: [PATCH 07/18] display for map stats for players --- .../commons/FactionStatistics/Player.lua | 98 ++++++++++++++++--- 1 file changed, 82 insertions(+), 16 deletions(-) diff --git a/lua/wikis/commons/FactionStatistics/Player.lua b/lua/wikis/commons/FactionStatistics/Player.lua index 991c9a9bf62..1a0ed0cdc5e 100644 --- a/lua/wikis/commons/FactionStatistics/Player.lua +++ b/lua/wikis/commons/FactionStatistics/Player.lua @@ -12,6 +12,7 @@ local Array = Lua.import('Module:Array') local Class = Lua.import('Module:Class') local DateExt = Lua.import('Module:Date/Ext') local Faction = Lua.import('Module:Faction') +local FnUtil = Lua.import('Module:FnUtil') local Logic = Lua.import('Module:Logic') local Lpdb = Lua.import('Module:Lpdb') local MatchupDisplay = Lua.import('Module:FactionStatistics/MatchupDisplay') @@ -30,6 +31,7 @@ local ConditionUtil = Condition.Util local Box = Lua.import('Module:Widget/Basic/Box') local HtmlWidgets = Lua.import('Module:Widget/Html/All') +local Link = Lua.import('Module:Widget/Basic/Link') local TableWidgets = Lua.import('Module:Widget/Table2/All') local WidgetUtil = Lua.import('Module:Widget/Util') @@ -299,6 +301,7 @@ function PlayerStatistics:create() end return Box{ + paddingBottom = '1rem', children = { self:_matchesPerFaction(), self:_matchesPerType(), @@ -318,13 +321,20 @@ function PlayerStatistics:_matchesPerFaction() } end - -- can not use Array.extend due to the metatable ... see #7433 - local order = {'total'} - Array.forEach(Faction.knownFactions, function(faction) table.insert(order, faction) end) + local order = PlayerStatistics._getFactionOrder() return PlayerStatistics._simpleTable(self.byFaction, display, order, 'Matches per Faction') end +-- can not use Array.extend due to the metatable ... see #7433 +-- once #7433 is fixed this function becomes obsolete via `Array.extend({'total'}, Faction.knownFactions)` +---@return string[] +function PlayerStatistics._getFactionOrder() + local order = {'total'} + Array.forEach(Faction.knownFactions, function(faction) table.insert(order, faction) end) + return order +end + ---@return Widget function PlayerStatistics:_matchesPerType() local order = {'offline', 'online'} @@ -383,28 +393,84 @@ function PlayerStatistics._simpleTable(data, display, order, title) Array.rep({align = 'right'}, 4) ), children = { - PlayerStatistics._header(true), + TableWidgets.Row{children = PlayerStatistics._headerCells(true)}, TableWidgets.TableBody{children = rows}, }, } end ----@param emptyCell boolean? ----@return Widget -function PlayerStatistics._header(emptyCell) - return TableWidgets.Row{ - children = WidgetUtil.collect( - emptyCell and TableWidgets.CellHeader{children = ''} or nil, - TableWidgets.CellHeader{children = SUM_ABBR}, - TableWidgets.CellHeader{children = 'W'}, - TableWidgets.CellHeader{children = 'L'}, - TableWidgets.CellHeader{children = '%'} - ) - } +---@param emptyCell boolean +---@return Widget[] +function PlayerStatistics._headerCells(emptyCell) + return WidgetUtil.collect( + emptyCell and TableWidgets.CellHeader{children = ''} or nil, + TableWidgets.CellHeader{children = SUM_ABBR}, + TableWidgets.CellHeader{children = 'W'}, + TableWidgets.CellHeader{children = 'L'}, + TableWidgets.CellHeader{children = '%'} + ) end ---@return Widget function PlayerStatistics:_gamesPerMapAndFaction() + local factionOrder = Array.filter(PlayerStatistics._getFactionOrder(), function (key) + local data = self.byMap.total[key] + return data.w + data.l > 0 + end) + + ---@param key string + ---@return Widget + local factionHeader = function(key) + local display = key == 'total' and 'vs. All' or { + 'vs. ', + Faction.Icon{faction = key}, + } + return TableWidgets.CellHeader{children = display, colspan = 4, align = 'center'} + end + + local header = { + TableWidgets.Row{ + children = WidgetUtil.collect( + TableWidgets.CellHeader{children = 'Maps', rowspan = 2, align = 'center'}, + Array.map(factionOrder, factionHeader) + ) + }, + TableWidgets.Row{ + children = Array.flatMap(Array.range(1, #factionOrder), FnUtil.curry(PlayerStatistics._headerCells, false)) + }, + } + + ---@param rowData table + ---@param mapDisplay Renderable + ---@return Widget + local makeRow = function(rowData, mapDisplay) + return TableWidgets.Row{ + children = WidgetUtil.collect( + TableWidgets.Cell{children = mapDisplay}, + Array.flatMap(factionOrder, function(key) + return MatchupDisplay.display(rowData[key]) + end) + ) + } + end + + local rows = {makeRow(Table.extract(self.byMap, 'total'), 'Overall')} + for map, rowData in Table.iter.spairs(self.byMap) do + table.insert(rows, makeRow(rowData, Link{link = map})) + end + + return TableWidgets.Table{ + sortable = false, + caption = 'Map statistics', + columns = WidgetUtil.collect( + {align = 'left'}, + Array.rep({align = 'right'}, 4 * #factionOrder) + ), + children = WidgetUtil.collect( + header, + TableWidgets.TableBody{children = rows} + ), + } end return PlayerStatistics From e3ec959308d94b00c0bc4d4a89f32bb048f67901 Mon Sep 17 00:00:00 2001 From: hjpalpha Date: Wed, 29 Apr 2026 08:21:37 +0200 Subject: [PATCH 08/18] adjust input params --- lua/wikis/commons/FactionStatistics/Map.lua | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/lua/wikis/commons/FactionStatistics/Map.lua b/lua/wikis/commons/FactionStatistics/Map.lua index 8fff78142c9..13b0c7d28e6 100644 --- a/lua/wikis/commons/FactionStatistics/Map.lua +++ b/lua/wikis/commons/FactionStatistics/Map.lua @@ -231,16 +231,21 @@ function MapStatistics._buildConditions(args) conditions:add(ConditionNode(ColumnName('date'), Comparator.le, endDate)) end - local mapsInput = args.maps or args.map - or args.mode == 'mapStats' and mw.title.getCurrentTitle().text - or nil - local maps = Array.parseCommaSeparatedString(mapsInput) + ---@type string[] + local maps = Logic.nilIfEmpty(Array.mapIndexes(function(index) + return Logic.nilIfEmpty(args['map' .. index]) + end)) + or args.mode == 'mapStats' and {mw.title.getCurrentTitle().text} + or {} + maps = Array.filter(maps, function(map) return map ~= 'TBD' end) if Logic.isNotEmpty(maps) then conditions:add(ConditionUtil.anyOf(ColumnName('map'), maps)) end - local parents = Array.parseCommaSeparatedString(args.parents or args.parent) + local parents = Array.mapIndexes(function(index) + return Logic.nilIfEmpty(args['parent' .. index]) + end) if Logic.isNotEmpty(parents) then conditions:add(ConditionUtil.anyOf(ColumnName('parent'), Array.map(parents, Page.pageifyLink))) end @@ -297,7 +302,11 @@ function MapStatistics._getTournaments(args) return Array.map(tournaments, Operator.property('pagename')) end - return Logic.nilIfEmpty(Array.parseCommaSeparatedString(args.tournaments or args.tournament)) + local tournaments = Logic.nilIfEmpty(Array.mapIndexes(function(index) + return Logic.nilIfEmpty(args['tournament' .. index]) + end)) + + return tournaments or Logic.nilIfEmpty(fromSeries(args.series)) or args.mode == 'tournamentStats' and {mw.title.getCurrentTitle().text} or nil From 6063e2272e1554b3a76af8d0d07bb57481ae08e6 Mon Sep 17 00:00:00 2001 From: hjpalpha Date: Wed, 29 Apr 2026 11:42:27 +0200 Subject: [PATCH 09/18] as per review --- lua/wikis/commons/FactionStatistics/Map.lua | 53 +++++++++---------- .../FactionStatistics/MatchupDisplay.lua | 4 +- .../commons/FactionStatistics/Player.lua | 13 +++++ 3 files changed, 41 insertions(+), 29 deletions(-) diff --git a/lua/wikis/commons/FactionStatistics/Map.lua b/lua/wikis/commons/FactionStatistics/Map.lua index 13b0c7d28e6..12591297aa8 100644 --- a/lua/wikis/commons/FactionStatistics/Map.lua +++ b/lua/wikis/commons/FactionStatistics/Map.lua @@ -13,7 +13,6 @@ local DateExt = Lua.import('Module:Date/Ext') local Faction = Lua.import('Module:Faction') local MatchupDisplay = Lua.import('Module:FactionStatistics/MatchupDisplay') local FnUtil = Lua.import('Module:FnUtil') -local Json = Lua.import('Module:Json') local Logic = Lua.import('Module:Logic') local Lpdb = Lua.import('Module:Lpdb') local Operator = Lua.import('Module:Operator') @@ -70,6 +69,7 @@ function MapStatistics.run(frame) } end +---@private ---@return {vs: string[], mirrors: string[]} function MapStatistics._getMatchups() local vs = {} @@ -113,6 +113,7 @@ function MapStatistics._getMatchups() } end +---@private ---@param args table ---@param matchUps {vs: string[], mirrors: string[]} ---@return {map: string, mapDisplayName: string?, total: integer, @@ -214,6 +215,7 @@ function MapStatistics._fetchData(args, matchUps) ) end +---@private ---@param args table ---@return string function MapStatistics._buildConditions(args) @@ -239,26 +241,20 @@ function MapStatistics._buildConditions(args) or {} maps = Array.filter(maps, function(map) return map ~= 'TBD' end) - if Logic.isNotEmpty(maps) then - conditions:add(ConditionUtil.anyOf(ColumnName('map'), maps)) - end + conditions:add(ConditionUtil.anyOf(ColumnName('map'), maps)) local parents = Array.mapIndexes(function(index) return Logic.nilIfEmpty(args['parent' .. index]) end) - if Logic.isNotEmpty(parents) then - conditions:add(ConditionUtil.anyOf(ColumnName('parent'), Array.map(parents, Page.pageifyLink))) - end + conditions:add(ConditionUtil.anyOf(ColumnName('parent'), Array.map(parents, Page.pageifyLink))) - local tournaments = MapStatistics._getTournaments(args) - if Logic.isNotEmpty(tournaments) then - ---@cast tournaments -nil - conditions:add(ConditionUtil.anyOf(ColumnName('pagename'), Array.map(tournaments, Page.pageifyLink))) - end + local tournaments = Array.map(MapStatistics._getTournaments(args), Page.pageifyLink) + conditions:add(ConditionUtil.anyOf(ColumnName('pagename'), tournaments)) return tostring(conditions) end +---@private ---@param mapData {map: string, mapDisplayName: string?, total: integer, ---vs: table, mirrors: table} function MapStatistics._store(mapData) @@ -275,18 +271,18 @@ function MapStatistics._store(mapData) ratios[factions[2] .. factions[1]] = ratio and (1 - ratio) or nil end - mw.ext.LiquipediaDB.lpdb_datapoint( - 'map_winrates_' .. mapData.map, - { - name = mapData.map, - type = 'map_winrates', - extradata = Json.stringify(ratios), - } - ) + local dataPoint = Lpdb.DataPoint:new{ + objectname = 'map_winrates_' .. mapData.map, + type = 'map_winrates', + name = mapData.map, + extradata = ratios, + } + dataPoint:save() end +---@private ---@param args table ----@return string[]? +---@return string[] function MapStatistics._getTournaments(args) ---@param series string? ---@return string[]? @@ -302,16 +298,18 @@ function MapStatistics._getTournaments(args) return Array.map(tournaments, Operator.property('pagename')) end - local tournaments = Logic.nilIfEmpty(Array.mapIndexes(function(index) + local tournaments = Array.mapIndexes(function(index) return Logic.nilIfEmpty(args['tournament' .. index]) - end)) + end) - return tournaments - or Logic.nilIfEmpty(fromSeries(args.series)) - or args.mode == 'tournamentStats' and {mw.title.getCurrentTitle().text} - or nil + return Logic.emptyOr( + tournaments, + fromSeries(args.series), + args.mode == 'tournamentStats' and {mw.title.getCurrentTitle().text} or {} + ) --[[@as string[] ]] end +---@private ---@param matchUps {vs: string[], mirrors: string[]} ---@return Widget function MapStatistics._header(matchUps) @@ -371,6 +369,7 @@ function MapStatistics._header(matchUps) } end +---@private ---@param matchUps {vs: string[], mirrors: string[]} ---@param mapData {map: string, mapDisplayName: string?, total: integer, ---vs: table, mirrors: table} diff --git a/lua/wikis/commons/FactionStatistics/MatchupDisplay.lua b/lua/wikis/commons/FactionStatistics/MatchupDisplay.lua index 0e08807026f..6f5cb3450f8 100644 --- a/lua/wikis/commons/FactionStatistics/MatchupDisplay.lua +++ b/lua/wikis/commons/FactionStatistics/MatchupDisplay.lua @@ -24,7 +24,7 @@ function MatchupDisplay.display(matchupData) return '-' end local percentage = 100 * matchupData.w / (total) - return MathUtil.formatRounded{precision = 1, value = percentage} + return MathUtil.formatPercentage(percentage, 1) end return { @@ -41,4 +41,4 @@ function MatchupDisplay.dashIfZero(input) return input == 0 and '-' or input end -return MatchupDisplay \ No newline at end of file +return MatchupDisplay diff --git a/lua/wikis/commons/FactionStatistics/Player.lua b/lua/wikis/commons/FactionStatistics/Player.lua index 1a0ed0cdc5e..5009e17fc88 100644 --- a/lua/wikis/commons/FactionStatistics/Player.lua +++ b/lua/wikis/commons/FactionStatistics/Player.lua @@ -84,6 +84,7 @@ function PlayerStatistics:query() return self end +---@private function PlayerStatistics:_getMatchData() self.matchIds = {} @@ -148,6 +149,7 @@ function PlayerStatistics:_getMatchData() end) end +---@private ---@return string function PlayerStatistics:_getMatchConditions() local args = self.args @@ -195,6 +197,7 @@ function PlayerStatistics:_getMatchConditions() return tostring(conditions) end +---@private ---@return table function PlayerStatistics._newEmptyFactionData() return Table.map(Array.append(Faction.knownFactions, 'total'), function(index, key) @@ -202,6 +205,7 @@ function PlayerStatistics._newEmptyFactionData() end) end +---@private function PlayerStatistics:_getMapData() local player = self.player @@ -271,6 +275,7 @@ function PlayerStatistics:_getMapData() self.byMap = byMap end +---@private ---@return string function PlayerStatistics:_getMapConditions() ---@param opponent string @@ -312,6 +317,7 @@ function PlayerStatistics:create() } end +---@private ---@return Widget function PlayerStatistics:_matchesPerFaction() local display = function(key) @@ -328,6 +334,7 @@ end -- can not use Array.extend due to the metatable ... see #7433 -- once #7433 is fixed this function becomes obsolete via `Array.extend({'total'}, Faction.knownFactions)` +---@private ---@return string[] function PlayerStatistics._getFactionOrder() local order = {'total'} @@ -335,12 +342,14 @@ function PlayerStatistics._getFactionOrder() return order end +---@private ---@return Widget function PlayerStatistics:_matchesPerType() local order = {'offline', 'online'} return PlayerStatistics._simpleTable(self.byType, String.upperCaseFirst, order, 'Matches per Environment') end +---@private ---@return Widget function PlayerStatistics:_matchesPerOpponentType() local order = { @@ -353,6 +362,7 @@ function PlayerStatistics:_matchesPerOpponentType() return PlayerStatistics._simpleTable(self.byOpponentType, String.upperCaseFirst, order, 'Matches per Opponent-Type') end +---@private ---@return Widget function PlayerStatistics:_matchesPerBestof() local display = function(key) @@ -368,6 +378,7 @@ function PlayerStatistics:_matchesPerBestof() return PlayerStatistics._simpleTable(self.byBestof, display, order, 'Matches per Environment') end +---@private ---@param data table ---@param display fun(string): Renderable ---@param order string[] @@ -399,6 +410,7 @@ function PlayerStatistics._simpleTable(data, display, order, title) } end +---@private ---@param emptyCell boolean ---@return Widget[] function PlayerStatistics._headerCells(emptyCell) @@ -411,6 +423,7 @@ function PlayerStatistics._headerCells(emptyCell) ) end +---@private ---@return Widget function PlayerStatistics:_gamesPerMapAndFaction() local factionOrder = Array.filter(PlayerStatistics._getFactionOrder(), function (key) From 16d1955a340cdde1f8956ca67bf985eb881cb6e7 Mon Sep 17 00:00:00 2001 From: hjpalpha Date: Wed, 29 Apr 2026 11:51:24 +0200 Subject: [PATCH 10/18] as per review --- lua/wikis/commons/FactionStatistics/Player.lua | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lua/wikis/commons/FactionStatistics/Player.lua b/lua/wikis/commons/FactionStatistics/Player.lua index 5009e17fc88..76ffca4f408 100644 --- a/lua/wikis/commons/FactionStatistics/Player.lua +++ b/lua/wikis/commons/FactionStatistics/Player.lua @@ -16,6 +16,7 @@ local FnUtil = Lua.import('Module:FnUtil') local Logic = Lua.import('Module:Logic') local Lpdb = Lua.import('Module:Lpdb') local MatchupDisplay = Lua.import('Module:FactionStatistics/MatchupDisplay') +local MatchGroupUtil = Lua.import('Module:MatchGroup/Util/Custom') local Opponent = Lua.import('Module:Opponent/Custom') local Page = Lua.import('Module:Page') local String = Lua.import('Module:StringUtils') @@ -93,7 +94,7 @@ function PlayerStatistics:_getMatchData() self.byBestof = {} self.byOpponentType = {} - ---@param opponents table[] + ---@param opponents standardOpponent[] ---@param winner integer? ---@return boolean local shouldExclude = function(opponents, winner) @@ -102,7 +103,7 @@ function PlayerStatistics:_getMatchData() or not opponents[1] or #opponents ~= 2 or Array.any(opponents, function(opponent) - return opponent.status and opponent.status ~= 'S' + return opponent.status and opponent.status ~= 'S' or false end) end @@ -110,15 +111,16 @@ function PlayerStatistics:_getMatchData() conditions = self:_getMatchConditions(), query = 'match2id, bestof, match2opponents, winner, type', }, function (record) + ---@type standardOpponent[] + local opponents = Array.map(record.match2opponents, FnUtil.curry(MatchGroupUtil.opponentFromRecord, record)) local winner = tonumber(record.winner) - local opponents = record.match2opponents if shouldExclude(opponents, winner) then return end table.insert(self.matchIds, record.match2id) - local side = (opponents[1].name == self.player or Array.any(opponents[1].match2players or {}, function(playerObj) - return playerObj.name == self.player + local side = (opponents[1].name == self.player or Array.any(opponents[1].players or {}, function(playerObj) + return playerObj.pageName == self.player end)) and 1 or 2 local vsSide = 3 - side @@ -140,7 +142,7 @@ function PlayerStatistics:_getMatchData() self.byFaction.total[result] = self.byFaction.total[result] + 1 local vsFaction = Logic.emptyOr( - (((opponents[vsSide].match2players or {})[1] or {}).extradata or {}).faction, + (((opponents[vsSide].players or {})[1] or {}).extradata or {}).faction, Faction.defaultFaction ) if vsFaction == Faction.defaultFaction then return end From 71d76af2c0b75ec87cb4f2b2e5a6f18452615157 Mon Sep 17 00:00:00 2001 From: hjpalpha <75081997+hjpalpha@users.noreply.github.com> Date: Thu, 30 Apr 2026 04:28:19 +0200 Subject: [PATCH 11/18] Apply suggestions from code review Co-authored-by: hjpalpha <75081997+hjpalpha@users.noreply.github.com> Co-authored-by: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> --- lua/wikis/commons/FactionStatistics/Player.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lua/wikis/commons/FactionStatistics/Player.lua b/lua/wikis/commons/FactionStatistics/Player.lua index 76ffca4f408..e72cb9fd57b 100644 --- a/lua/wikis/commons/FactionStatistics/Player.lua +++ b/lua/wikis/commons/FactionStatistics/Player.lua @@ -142,7 +142,7 @@ function PlayerStatistics:_getMatchData() self.byFaction.total[result] = self.byFaction.total[result] + 1 local vsFaction = Logic.emptyOr( - (((opponents[vsSide].players or {})[1] or {}).extradata or {}).faction, + ((opponents[vsSide].players or {})[1] or {}).faction, Faction.defaultFaction ) if vsFaction == Faction.defaultFaction then return end @@ -159,7 +159,7 @@ function PlayerStatistics:_getMatchConditions() local tiers = Array.map(Array.parseCommaSeparatedString(args.tiers), function(num) return tonumber(num) end) - tiers = Logic.nilIfEmpty(tiers) or DEFAULT_TIERS + tiers = Logic.emptyOr(tiers, DEFAULT_TIERS) --[[@as integer[] ]] local tierTypes = Array.parseCommaSeparatedString(args.tiers or '!Qualifier') tierTypes = Array.map(tierTypes, function(tierType) @@ -209,6 +209,10 @@ end ---@private function PlayerStatistics:_getMapData() + if Logic.isEmpty(self.matchIds) then + return + end + local player = self.player local byMap = {total = PlayerStatistics._newEmptyFactionData()} From 1b4b067f698a8393b3346d63aa76e4e3ae423e1d Mon Sep 17 00:00:00 2001 From: hjpalpha Date: Thu, 30 Apr 2026 07:26:15 +0200 Subject: [PATCH 12/18] as per review --- lua/wikis/commons/FactionStatistics/Player.lua | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lua/wikis/commons/FactionStatistics/Player.lua b/lua/wikis/commons/FactionStatistics/Player.lua index e72cb9fd57b..80825b7fb2c 100644 --- a/lua/wikis/commons/FactionStatistics/Player.lua +++ b/lua/wikis/commons/FactionStatistics/Player.lua @@ -21,6 +21,7 @@ local Opponent = Lua.import('Module:Opponent/Custom') local Page = Lua.import('Module:Page') local String = Lua.import('Module:StringUtils') local Table = Lua.import('Module:Table') +local Tier = Lua.import('Module:Tier/Utils') local Condition = Lua.import('Module:Condition') local ConditionTree = Condition.Tree @@ -156,10 +157,8 @@ end function PlayerStatistics:_getMatchConditions() local args = self.args - local tiers = Array.map(Array.parseCommaSeparatedString(args.tiers), function(num) - return tonumber(num) - end) - tiers = Logic.emptyOr(tiers, DEFAULT_TIERS) --[[@as integer[] ]] + local tiers = Array.map(Array.parseCommaSeparatedString(args.tiers), Tier.toIdentifier) + tiers = Logic.emptyOr(tiers, DEFAULT_TIERS) --[[@as integer[] ]] local tierTypes = Array.parseCommaSeparatedString(args.tiers or '!Qualifier') tierTypes = Array.map(tierTypes, function(tierType) From fb3eff8407edd8aced4f1b5443404fabacdcbad6 Mon Sep 17 00:00:00 2001 From: hjpalpha <75081997+hjpalpha@users.noreply.github.com> Date: Thu, 14 May 2026 14:23:23 +0000 Subject: [PATCH 13/18] chore: update visual snapshots --- lua/spec/snapshots/dota2 rankings.png | Bin 81986 -> 81976 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lua/spec/snapshots/dota2 rankings.png b/lua/spec/snapshots/dota2 rankings.png index e61cb14992eacd988c8c02d268744d07659bc1ff..74a37ff5e3a4fa6f0b6b61053520399ee9fa838b 100644 GIT binary patch delta 34198 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 Date: Thu, 14 May 2026 16:27:23 +0200 Subject: [PATCH 14/18] use v3 html widgets --- lua/wikis/commons/FactionStatistics/Map.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lua/wikis/commons/FactionStatistics/Map.lua b/lua/wikis/commons/FactionStatistics/Map.lua index 12591297aa8..60aff144d3a 100644 --- a/lua/wikis/commons/FactionStatistics/Map.lua +++ b/lua/wikis/commons/FactionStatistics/Map.lua @@ -28,18 +28,18 @@ local ColumnName = Condition.ColumnName local ConditionUtil = Condition.Util local Link = Lua.import('Module:Widget/Basic/Link') -local HtmlWidgets = Lua.import('Module:Widget/Html/All') +local Html = Lua.import('Module:Widget/Html') local TableWidgets = Lua.import('Module:Widget/Table2/All') local WidgetUtil = Lua.import('Module:Widget/Util') local DEFAULT_MAP_NAME = 'Unknown' -local SUM_ABBR = HtmlWidgets.Abbr{title = 'Sum of', children = 'Σ'} -local NUMBER_OF_ABBR = HtmlWidgets.Abbr{title = 'Number of', children = '#'} +local SUM_ABBR = Html.Abbr{title = 'Sum of', children = 'Σ'} +local NUMBER_OF_ABBR = Html.Abbr{title = 'Number of', children = '#'} local MapStatistics = {} ---@param frame Frame ----@return Widget? +---@return VNode? function MapStatistics.run(frame) local args = Arguments.getArgs(frame) @@ -311,10 +311,10 @@ end ---@private ---@param matchUps {vs: string[], mirrors: string[]} ----@return Widget +---@return VNode function MapStatistics._header(matchUps) ---@param key string - ---@return Widget + ---@return VNode local makeFactionHeader = function(key) local factions = Array.parseCommaSeparatedString(key) @@ -330,7 +330,7 @@ function MapStatistics._header(matchUps) end ---@param key string - ---@return Widget[] + ---@return VNode[] local makeMatchUpHeader = function(key) local factions = Array.parseCommaSeparatedString(key) return { @@ -373,7 +373,7 @@ end ---@param matchUps {vs: string[], mirrors: string[]} ---@param mapData {map: string, mapDisplayName: string?, total: integer, ---vs: table, mirrors: table} ----@return Widget? +---@return VNode? function MapStatistics._row(matchUps, mapData) if Logic.isEmpty(mapData) then return From 24d9ebe6b031c91a0c81d8c7eb4a7455ea1e2704 Mon Sep 17 00:00:00 2001 From: hjpalpha <75081997+hjpalpha@users.noreply.github.com> Date: Thu, 14 May 2026 14:30:16 +0000 Subject: [PATCH 15/18] chore: update visual snapshots --- lua/spec/snapshots/dota2 rankings.png | Bin 81976 -> 81986 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lua/spec/snapshots/dota2 rankings.png b/lua/spec/snapshots/dota2 rankings.png index 74a37ff5e3a4fa6f0b6b61053520399ee9fa838b..e61cb14992eacd988c8c02d268744d07659bc1ff 100644 GIT binary patch delta 34283 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 Date: Thu, 14 May 2026 17:40:11 +0200 Subject: [PATCH 16/18] fallback to factions if corefactions is empty --- lua/wikis/commons/FactionStatistics/Map.lua | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lua/wikis/commons/FactionStatistics/Map.lua b/lua/wikis/commons/FactionStatistics/Map.lua index 60aff144d3a..da183559cc3 100644 --- a/lua/wikis/commons/FactionStatistics/Map.lua +++ b/lua/wikis/commons/FactionStatistics/Map.lua @@ -35,6 +35,7 @@ local WidgetUtil = Lua.import('Module:Widget/Util') local DEFAULT_MAP_NAME = 'Unknown' local SUM_ABBR = Html.Abbr{title = 'Sum of', children = 'Σ'} local NUMBER_OF_ABBR = Html.Abbr{title = 'Number of', children = '#'} +local FACTIONS = Logic.nilIfEmpty(Faction.coreFactions) or Faction.factions local MapStatistics = {} @@ -91,16 +92,16 @@ function MapStatistics._getMatchups() end --- this loop is only wanted/needed so that each faction is on the left at least once... - Array.forEach(Faction.coreFactions, function(faction, factionIndex) - local nextFaction = Faction.coreFactions[factionIndex + 1] or Faction.coreFactions[1] + Array.forEach(FACTIONS, function(faction, factionIndex) + local nextFaction = FACTIONS[factionIndex + 1] or FACTIONS[1] if faction == nextFaction or alreadyDone(faction, nextFaction) then return end table.insert(vs, faction .. ',' .. nextFaction) end) - Array.forEach(Faction.coreFactions, function(faction1) - Array.forEach(Faction.coreFactions, function(faction2) + Array.forEach(FACTIONS, function(faction1) + Array.forEach(FACTIONS, function(faction2) if not alreadyDone(faction1, faction2) then table.insert(vs, faction1 .. ',' .. faction2) end @@ -109,7 +110,7 @@ function MapStatistics._getMatchups() return { vs = vs, - mirrors = Table.copy(Faction.coreFactions), -- copy to remove the metatable which breaks some stuff + mirrors = Table.copy(FACTIONS), -- copy to remove the metatable which breaks some stuff } end @@ -185,12 +186,12 @@ function MapStatistics._fetchData(args, matchUps) data[map] = data[map] or makeInitialMapData(gameData) local winnerFaction = gameData.extradata.winnerfaction - if not Table.includes(Faction.coreFactions, winnerFaction) then + if not Table.includes(FACTIONS, winnerFaction) then return end local loserFaction = gameData.extradata.loserfaction - if not Table.includes(Faction.coreFactions, loserFaction) then + if not Table.includes(FACTIONS, loserFaction) then return end From aed7e4bd2cde2c70c4669aa74077b7372abce33f Mon Sep 17 00:00:00 2001 From: hjpalpha Date: Thu, 14 May 2026 17:46:13 +0200 Subject: [PATCH 17/18] option to restrict on game for maps stats --- lua/wikis/commons/FactionStatistics/Map.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lua/wikis/commons/FactionStatistics/Map.lua b/lua/wikis/commons/FactionStatistics/Map.lua index da183559cc3..08a8bdfe196 100644 --- a/lua/wikis/commons/FactionStatistics/Map.lua +++ b/lua/wikis/commons/FactionStatistics/Map.lua @@ -13,6 +13,7 @@ local DateExt = Lua.import('Module:Date/Ext') local Faction = Lua.import('Module:Faction') local MatchupDisplay = Lua.import('Module:FactionStatistics/MatchupDisplay') local FnUtil = Lua.import('Module:FnUtil') +local Game = Lua.import('Module:Game') local Logic = Lua.import('Module:Logic') local Lpdb = Lua.import('Module:Lpdb') local Operator = Lua.import('Module:Operator') @@ -252,6 +253,11 @@ function MapStatistics._buildConditions(args) local tournaments = Array.map(MapStatistics._getTournaments(args), Page.pageifyLink) conditions:add(ConditionUtil.anyOf(ColumnName('pagename'), tournaments)) + local game = Game.toIdentifier{game = args.game, useDefault = false} + if game then + conditions:add(ConditionNode(ColumnName('game'), Comparator.eq, game)) + end + return tostring(conditions) end From ebdc77aa99462b6b423da03bbbd521ee049eb761 Mon Sep 17 00:00:00 2001 From: hjpalpha Date: Thu, 14 May 2026 17:48:47 +0200 Subject: [PATCH 18/18] option to filter for game for player stats too --- lua/wikis/commons/FactionStatistics/Player.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lua/wikis/commons/FactionStatistics/Player.lua b/lua/wikis/commons/FactionStatistics/Player.lua index 80825b7fb2c..b83b365e5c5 100644 --- a/lua/wikis/commons/FactionStatistics/Player.lua +++ b/lua/wikis/commons/FactionStatistics/Player.lua @@ -13,6 +13,7 @@ local Class = Lua.import('Module:Class') local DateExt = Lua.import('Module:Date/Ext') local Faction = Lua.import('Module:Faction') local FnUtil = Lua.import('Module:FnUtil') +local Game = Lua.import('Module:Game') local Logic = Lua.import('Module:Logic') local Lpdb = Lua.import('Module:Lpdb') local MatchupDisplay = Lua.import('Module:FactionStatistics/MatchupDisplay') @@ -195,6 +196,11 @@ function PlayerStatistics:_getMatchConditions() conditions:add(ConditionNode(ColumnName('player'), Comparator.eq, self.player)) end + local game = Game.toIdentifier{game = args.game, useDefault = false} + if game then + conditions:add(ConditionNode(ColumnName('game'), Comparator.eq, game)) + end + return tostring(conditions) end