From a33cf6ff064a39d843781e69f5d4ec5dbad43dde Mon Sep 17 00:00:00 2001 From: hjpalpha <75081997+hjpalpha@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:46:31 +0900 Subject: [PATCH 01/38] Import from Commons Co-authored-by: SyntacticSalt --- .../commons/PlayerTournamentAppearances.lua | 341 ++++++++++++++++++ 1 file changed, 341 insertions(+) create mode 100644 lua/wikis/commons/PlayerTournamentAppearances.lua diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua new file mode 100644 index 00000000000..ae5cf87649f --- /dev/null +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -0,0 +1,341 @@ +local Abbreviation = require('Module:Abbreviation') +local Arguments = require('Module:Arguments') +local Array = require('Module:Array') +local Class = require('Module:Class') +local Condition = require('Module:Condition') +local DateExt = require('Module:Date/Ext') +local Flags = require('Module:Flags') +local LeagueIcon = require('Module:LeagueIcon') +local Logic = require('Module:Logic') +local Lpdb = require('Module:Lpdb') +local Operator = require('Module:Operator') +local Placement = require('Module:Placement') +local String = require('Module:StringUtils') +local Table = require('Module:Table') +local Team = require('Module:Team') + +local FACTION + +local Lua = require('Module:Lua') + +local Opponent = Lua.import('Module:Opponent/Custom') + +local ConditionTree = Condition.Tree +local ConditionNode = Condition.Node +local Comparator = Condition.Comparator +local BooleanOperator = Condition.BooleanOperator +local ColumnName = Condition.ColumnName + +local ICON_HEADER_TYPES = {'icons', 'icon'} +local DEFAULT_TIERTYPES = {'General', 'School', ''} + +local Appearances = Class.new(function(self, frame) self:init(frame) end) + +function Appearances.run(frame) + return Appearances(frame):create():build() +end + +function Appearances:init(frame) + local args = Arguments.getArgs(frame) + + self.plainArgs = args + + assert(args.series or args.pages or args.conditions, 'Either "series", "pages" or "conditions" input has to be specified') + + self.config = { + prefix = args.prefix or 'p', + displayIconInsteadOfShortName = Table.includes(ICON_HEADER_TYPES, args.headerType), + displayFactionColumn = Logic.readBool(args.displayFactionColumn), + showPlacementInsteadOfTeam = Logic.readBool(args.showPlacementInsteadOfTeam), + limit = tonumber(args.limit), + isFormQuery = Logic.readBool(args.query), + restrictToPlayersParticipatingIn = args.playerspage, + restrictToFirstPrizePool = Logic.readBool(args.restrictToFirstPrizePool), + } + + self.args = { + conditions = args.conditions, + tierTypes = Appearances._readCommaSep(args.tierTypes) or DEFAULT_TIERTYPES, + tiers = Appearances._readCommaSep(args.tiers), + startDate = Logic.nilIfEmpty(args.sdate), + endDate = Logic.nilIfEmpty(args.edate), + pages = Appearances._readCommaSep(args.pages), + series = args.series and + Array.extractValues(Table.filterByKey(args, function(key) return key:find('^series%d-$') end)) + or nil, + } + + return self +end + +function Appearances._readCommaSep(input) + return input and Array.map(mw.text.split(input, ','), String.trim) + or nil +end + +function Appearances:create() + self.tournaments = mw.ext.LiquipediaDB.lpdb('tournament', { + conditions = self.args.conditions or self:_buildConditions(), + limit = 5000, + order = 'enddate asc', + query = 'pagename, name, shortname, icon, icondark', + }) + + if Table.isEmpty(self.tournaments) then + return self + end + + local pageNames = Array.map(self.tournaments, Operator.property('pagename')) + self.players = self:_fetchPlayers(pageNames) + + return self +end + +function Appearances:_buildConditions() + local args = self.args + + local conditions = ConditionTree(BooleanOperator.all) + :add{ConditionNode(ColumnName('enddate'), Comparator.gt, DateExt.defaultDate)} + + Appearances._buildOrConditionsFromArray(conditions, {'finished', ''}, 'status') + Appearances._buildOrConditionsFromArray(conditions, args.tiers, 'liquipediatier') + Appearances._buildOrConditionsFromArray(conditions, args.tierTypes, 'liquipediatiertype') + + if Table.isNotEmpty(args.series) then + Appearances._buildOrConditionsFromArray(conditions, args.series, 'seriespage', 'extradata_series2', true) + else + args.pages = Array.map(args.pages, function(page) return (page:gsub(' ', '_')) end) + Appearances._buildOrConditionsFromArray(conditions, args.pages, 'pagename') + end + + if args.startDate then + conditions:add{ConditionNode(ColumnName('startdate'), Comparator.ge, args.startDate)} + end + + if args.endDate then + conditions:add{ConditionNode(ColumnName('enddate'), Comparator.le, args.endDate)} + end + + return conditions:toString() +end + +function Appearances:_fetchPlayers(pageNames) + local players = {} + + Lpdb.executeMassQuery('placement', { + conditions = self:_placementConditions(pageNames), + limit = 1000, + order = 'date asc', + query = 'opponentplayers, opponenttype, pagename, date, placement, opponenttemplate', + }, function(placement) + for prefix, playerPage in Table.iter.pairsByPrefix(placement.opponentplayers or {}, self.config.prefix) do + if not players[playerPage] then + players[playerPage] = { + link = playerPage, + appearances = 0, + placementSum = 0, + results = {}, + } + end + + players[playerPage].appearances = players[playerPage].appearances + 1 + players[playerPage].flag = Logic.emptyOr(placement.opponentplayers[prefix .. 'flag'], players[playerPage].flag) + players[playerPage].name = Logic.emptyOr(placement.opponentplayers[prefix .. 'dn'], players[playerPage].name) + players[playerPage].faction = Logic.emptyOr(placement.opponentplayers[prefix .. 'faction'], players[playerPage].faction) + players[playerPage].results[placement.pagename] = { + placement = placement.placement, + date = placement.date, + team = placement.opponenttype == Opponent.team and placement.opponenttemplate + or placement.opponentplayers[prefix .. 'template'] + or placement.opponentplayers[prefix .. 'team'], + } + local placementParts = mw.text.split(string.lower(placement.placement or ''), '-', true) + players[playerPage].placementSum = players[playerPage].placementSum + (tonumber(placementParts[1]) or 1000) + end + end) + + local playersArray = Array.extractValues(players) + + if self.config.restrictToPlayersParticipatingIn then + playersArray = Array.filter(playersArray, function(player) + return player.results[self.config.restrictToPlayersParticipatingIn] + end) + end + + table.sort(playersArray, function(a, b) + if a.appearances ~= b.appearances then + return a.appearances > b.appearances + end + if a.placementSum ~= b.placementSum then + return a.placementSum < b.placementSum + end + return a.link < b.link + end) + + return playersArray +end + +function Appearances:_placementConditions(pageNames) + local conditions = ConditionTree(BooleanOperator.all) + :add{ConditionNode(ColumnName('opponentplayers'), Comparator.neq, '')} + :add{ConditionNode(ColumnName('opponentplayers'), Comparator.neq, '[]')} + :add{ConditionNode(ColumnName('opponentname'), Comparator.neq, 'TBD')} + :add{ConditionNode(ColumnName('opponentname'), Comparator.neq, 'Definitions')} + :add{ConditionNode(ColumnName('opponentname'), Comparator.neq, '')} + :add{ConditionNode(ColumnName('mode'), Comparator.neq, 'award_individual')} + + Appearances._buildOrConditionsFromArray(conditions, pageNames, 'pagename') + + if self.config.restrictToFirstPrizePool then + conditions:add{ConditionNode(ColumnName('prizepoolindex'), Comparator.eq, 1)} + end + + return conditions:toString() +end + +function Appearances._buildOrConditionsFromArray(parent, arr, key, key2, toUnderScore) + if Table.isEmpty(arr) then return end + + local orConditions = ConditionTree(BooleanOperator.any) + for _, value in ipairs(arr) do + orConditions:add{ConditionNode(ColumnName(key), Comparator.eq, value)} + if key2 then + orConditions:add{ConditionNode(ColumnName(key2), Comparator.eq, value)} + end + local underScoreValue = value:gsub(' ', '_') + if toUnderScore then + orConditions:add{ConditionNode(ColumnName(key), Comparator.eq, underScoreValue)} + end + if key2 and toUnderScore then + orConditions:add{ConditionNode(ColumnName(key2), Comparator.eq, underScoreValue)} + end + end + + parent:add(orConditions) +end + +function Appearances:build() + if not self.players then return 'No results found.' end + + local display = mw.html.create('table') + :addClass('wikitable sortable wikitable-striped') + :css('text-align', 'center') + :css('margin', '0') + :node(self:_header()) + + local limit = math.min(self.config.limit or #self.players, #self.players) + + for playerIndex = 1, limit do + display:node(self:_row(playerIndex)) + end + + if self.config.restrictToPlayersParticipatingIn and not self.config.isFormQuery then + display:node(self:_buildQueryLink()) + end + + return mw.html.create('div') + :addClass('table-responsive') + :css('margin-bottom', '10px') + :node(display) +end + +function Appearances:_header() + local header = mw.html.create('tr') + :tag('th'):done() + + if self.config.displayFactionColumn then + FACTION = require('Module:Faction') + header:tag('th') + end + + header + :tag('th'):wikitext('Player'):done() + :tag('th'):wikitext(Abbreviation.make{text = 'TA.', title = 'Total appearances'}) + + for _, tournament in ipairs(self.tournaments) do + if self.config.displayIconInsteadOfShortName then + header:tag('th'):node(LeagueIcon.display{ + icon = tournament.icon, + iconDark = tournament.icondark, + link = tournament.pagename, + name = tournament.name, + options = {noTemplate = true}, + }) + else + header:tag('th'):wikitext('[[' .. tournament.pagename .. '|' .. Logic.emptyOr( + tournament.shortname, + tournament.name, + (tournament.pagename:gsub('_', ' ')) + ) .. ']]') + end + end + + return header +end + +function Appearances:_row(playerIndex) + local player = self.players[playerIndex] + + local row = mw.html.create('tr') + :tag('td'):wikitext(Flags.Icon{flag = player.flag}):done() + + if self.config.displayFactionColumn then + row:tag('td'):wikitext(FACTION.Icon{faction = player.faction}) + end + + row + :tag('td'):css('text-align', 'left'):wikitext('[[' .. player.link .. '|' .. player.name .. ']]'):done() + :tag('td'):wikitext(player.appearances) + + for _, tournament in ipairs(self.tournaments) do + local result = player.results[tournament.pagename] + local cell = row:tag('td') + + if self.config.showPlacementInsteadOfTeam then + -- Default to empty string to use data-sort-value + Placement._placement{parent = cell, placement = (result or {}).placement or ''} + elseif result then + cell + :attr('data-sort-value', result.team) + :wikitext(result.team and Team.icon(nil, result.team, result.date) or nil) + + if tonumber(result.placement) == 1 then + cell:addClass('tournament-highlighted-bg') + end + end + end + + return row +end + +function Appearances:_buildQueryLink() + local queryTable = { + ['PTAdev[series]'] = self.plainArgs.series or '', + ['PTAdev[pages]'] = self.plainArgs.pages or '', + ['PTAdev[tiers]'] = self.plainArgs.tiers or '', + ['PTAdev[limit]'] = self.plainArgs.limit or '', + ['PTAdev[playerspage]'] = self.plainArgs.playerspage or '', + ['PTAdev[query]'] = 'true', + } + + self:_toQuerySubTable(queryTable, 'pages') + self:_toQuerySubTable(queryTable, 'tiers') + + local queryString = tostring(mw.uri.fullUrl('Special:RunQuery/Player_tournament_appearances')) .. '?pfRunQueryFormName=Player+tournament+appearances&' .. mw.uri.buildQueryString(queryTable) .. '&wpRunQuery=Run+query' + + return mw.html.create('tr') + :tag('th') + :attr('colspan', #self.tournaments + 3 + (self.config.displayFactionColumn and 1 or 0)) + :css('font-size', 'small') + :wikitext('[' .. queryString .. ' Click here to modify this table]') + :done() +end + +function Appearances:_toQuerySubTable(queryTable, key) + local prefix = 'PTAdev[' .. key .. ']' + for index, value in ipairs(self.args[key] or {''}) do + queryTable[prefix .. '[' .. index .. ']'] = value + end +end + +return Appearances From 0dead47e6c2dab7a6aa627d5006afedbf23dfdab Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:47:39 +0900 Subject: [PATCH 02/38] deploy header --- lua/wikis/commons/PlayerTournamentAppearances.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index ae5cf87649f..77e21b86f40 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -1,3 +1,10 @@ +--- +-- @Liquipedia +-- page=Module:PlayerTournamentAppearances +-- +-- Please see https://github.com/Liquipedia/Lua-Modules to contribute +-- + local Abbreviation = require('Module:Abbreviation') local Arguments = require('Module:Arguments') local Array = require('Module:Array') From a1c95948c2c9e4ae472ebe44b02a76b731230f70 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:51:41 +0900 Subject: [PATCH 03/38] use Lua.import --- .../commons/PlayerTournamentAppearances.lua | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 77e21b86f40..25ef7c63854 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -5,25 +5,25 @@ -- Please see https://github.com/Liquipedia/Lua-Modules to contribute -- -local Abbreviation = require('Module:Abbreviation') -local Arguments = require('Module:Arguments') -local Array = require('Module:Array') -local Class = require('Module:Class') -local Condition = require('Module:Condition') -local DateExt = require('Module:Date/Ext') -local Flags = require('Module:Flags') -local LeagueIcon = require('Module:LeagueIcon') -local Logic = require('Module:Logic') -local Lpdb = require('Module:Lpdb') -local Operator = require('Module:Operator') -local Placement = require('Module:Placement') -local String = require('Module:StringUtils') -local Table = require('Module:Table') -local Team = require('Module:Team') +local Lua = require('Module:Lua') -local FACTION +local Abbreviation = Lua.import('Module:Abbreviation') +local Arguments = Lua.import('Module:Arguments') +local Array = Lua.import('Module:Array') +local Class = Lua.import('Module:Class') +local Condition = Lua.import('Module:Condition') +local DateExt = Lua.import('Module:Date/Ext') +local Flags = Lua.import('Module:Flags') +local LeagueIcon = Lua.import('Module:LeagueIcon') +local Logic = Lua.import('Module:Logic') +local Lpdb = Lua.import('Module:Lpdb') +local Operator = Lua.import('Module:Operator') +local Placement = Lua.import('Module:Placement') +local String = Lua.import('Module:StringUtils') +local Table = Lua.import('Module:Table') +local Team = Lua.import('Module:Team') -local Lua = require('Module:Lua') +local FACTION local Opponent = Lua.import('Module:Opponent/Custom') @@ -251,7 +251,7 @@ function Appearances:_header() :tag('th'):done() if self.config.displayFactionColumn then - FACTION = require('Module:Faction') + FACTION = Lua.import('Module:Faction') header:tag('th') end From e71e90c5e411158b94f55792d6f1c46b0501329b Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:57:29 +0900 Subject: [PATCH 04/38] type annotations --- .../commons/PlayerTournamentAppearances.lua | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 25ef7c63854..d0e9c7ae647 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -36,12 +36,18 @@ local ColumnName = Condition.ColumnName local ICON_HEADER_TYPES = {'icons', 'icon'} local DEFAULT_TIERTYPES = {'General', 'School', ''} +---@class PlayerTournamentAppearances: BaseClass +---@operator call(Frame): PlayerTournamentAppearances local Appearances = Class.new(function(self, frame) self:init(frame) end) +---@param frame Frame +---@return string|Html function Appearances.run(frame) return Appearances(frame):create():build() end +---@param frame Frame +---@return self function Appearances:init(frame) local args = Arguments.getArgs(frame) @@ -75,11 +81,14 @@ function Appearances:init(frame) return self end +---@param input string? +---@return string[]? function Appearances._readCommaSep(input) return input and Array.map(mw.text.split(input, ','), String.trim) or nil end +---@return self function Appearances:create() self.tournaments = mw.ext.LiquipediaDB.lpdb('tournament', { conditions = self.args.conditions or self:_buildConditions(), @@ -98,6 +107,7 @@ function Appearances:create() return self end +---@return string function Appearances:_buildConditions() local args = self.args @@ -182,6 +192,8 @@ function Appearances:_fetchPlayers(pageNames) return playersArray end +---@param pageNames string[] +---@return string function Appearances:_placementConditions(pageNames) local conditions = ConditionTree(BooleanOperator.all) :add{ConditionNode(ColumnName('opponentplayers'), Comparator.neq, '')} @@ -200,6 +212,11 @@ function Appearances:_placementConditions(pageNames) return conditions:toString() end +---@param parent ConditionTree +---@param arr string[] +---@param key string +---@param key2 string? +---@param toUnderScore boolean? function Appearances._buildOrConditionsFromArray(parent, arr, key, key2, toUnderScore) if Table.isEmpty(arr) then return end @@ -221,6 +238,7 @@ function Appearances._buildOrConditionsFromArray(parent, arr, key, key2, toUnder parent:add(orConditions) end +---@return string|Html function Appearances:build() if not self.players then return 'No results found.' end @@ -246,6 +264,8 @@ function Appearances:build() :node(display) end +---@private +---@return Html function Appearances:_header() local header = mw.html.create('tr') :tag('th'):done() @@ -280,6 +300,9 @@ function Appearances:_header() return header end +---@private +---@param playerIndex integer +---@return Html function Appearances:_row(playerIndex) local player = self.players[playerIndex] @@ -315,6 +338,8 @@ function Appearances:_row(playerIndex) return row end +---@private +---@return Html function Appearances:_buildQueryLink() local queryTable = { ['PTAdev[series]'] = self.plainArgs.series or '', @@ -338,6 +363,9 @@ function Appearances:_buildQueryLink() :done() end +---@private +---@param queryTable table +---@param key string function Appearances:_toQuerySubTable(queryTable, key) local prefix = 'PTAdev[' .. key .. ']' for index, value in ipairs(self.args[key] or {''}) do From fa7295ad7e2205085f6bd090261cf5e8c2eb063c Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:59:32 +0900 Subject: [PATCH 05/38] clean up import --- lua/wikis/commons/PlayerTournamentAppearances.lua | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index d0e9c7ae647..80db46a93db 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -13,20 +13,18 @@ local Array = Lua.import('Module:Array') local Class = Lua.import('Module:Class') local Condition = Lua.import('Module:Condition') local DateExt = Lua.import('Module:Date/Ext') +local Faction = Lua.import('Module:Faction') local Flags = Lua.import('Module:Flags') local LeagueIcon = Lua.import('Module:LeagueIcon') local Logic = Lua.import('Module:Logic') local Lpdb = Lua.import('Module:Lpdb') local Operator = Lua.import('Module:Operator') +local Opponent = Lua.import('Module:Opponent/Custom') local Placement = Lua.import('Module:Placement') local String = Lua.import('Module:StringUtils') local Table = Lua.import('Module:Table') local Team = Lua.import('Module:Team') -local FACTION - -local Opponent = Lua.import('Module:Opponent/Custom') - local ConditionTree = Condition.Tree local ConditionNode = Condition.Node local Comparator = Condition.Comparator @@ -271,7 +269,6 @@ function Appearances:_header() :tag('th'):done() if self.config.displayFactionColumn then - FACTION = Lua.import('Module:Faction') header:tag('th') end @@ -310,7 +307,7 @@ function Appearances:_row(playerIndex) :tag('td'):wikitext(Flags.Icon{flag = player.flag}):done() if self.config.displayFactionColumn then - row:tag('td'):wikitext(FACTION.Icon{faction = player.faction}) + row:tag('td'):wikitext(Faction.Icon{faction = player.faction}) end row From 8bd41063d5f66deedc1d3fdd8600e67e7074cd63 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:02:15 +0900 Subject: [PATCH 06/38] kick redundant helper function --- lua/wikis/commons/PlayerTournamentAppearances.lua | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 80db46a93db..c226814f082 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -21,7 +21,6 @@ local Lpdb = Lua.import('Module:Lpdb') local Operator = Lua.import('Module:Operator') local Opponent = Lua.import('Module:Opponent/Custom') local Placement = Lua.import('Module:Placement') -local String = Lua.import('Module:StringUtils') local Table = Lua.import('Module:Table') local Team = Lua.import('Module:Team') @@ -66,11 +65,11 @@ function Appearances:init(frame) self.args = { conditions = args.conditions, - tierTypes = Appearances._readCommaSep(args.tierTypes) or DEFAULT_TIERTYPES, - tiers = Appearances._readCommaSep(args.tiers), + tierTypes = Logic.emptyOr(Array.parseCommaSeparatedString(args.tierTypes), DEFAULT_TIERTYPES), + tiers = Array.parseCommaSeparatedString(args.tiers), startDate = Logic.nilIfEmpty(args.sdate), endDate = Logic.nilIfEmpty(args.edate), - pages = Appearances._readCommaSep(args.pages), + pages = Array.parseCommaSeparatedString(args.pages), series = args.series and Array.extractValues(Table.filterByKey(args, function(key) return key:find('^series%d-$') end)) or nil, @@ -79,13 +78,6 @@ function Appearances:init(frame) return self end ----@param input string? ----@return string[]? -function Appearances._readCommaSep(input) - return input and Array.map(mw.text.split(input, ','), String.trim) - or nil -end - ---@return self function Appearances:create() self.tournaments = mw.ext.LiquipediaDB.lpdb('tournament', { From cf5799447575b9243bdaf240b7b91646f0722f05 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:10:47 +0900 Subject: [PATCH 07/38] clean up condition building --- .../commons/PlayerTournamentAppearances.lua | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index c226814f082..75cdfd5e2b1 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -20,6 +20,7 @@ local Logic = Lua.import('Module:Logic') local Lpdb = Lua.import('Module:Lpdb') local Operator = Lua.import('Module:Operator') local Opponent = Lua.import('Module:Opponent/Custom') +local Page = Lua.import('Module:Page') local Placement = Lua.import('Module:Placement') local Table = Lua.import('Module:Table') local Team = Lua.import('Module:Team') @@ -29,6 +30,7 @@ local ConditionNode = Condition.Node local Comparator = Condition.Comparator local BooleanOperator = Condition.BooleanOperator local ColumnName = Condition.ColumnName +local ConditionUtil = Condition.Util local ICON_HEADER_TYPES = {'icons', 'icon'} local DEFAULT_TIERTYPES = {'General', 'School', ''} @@ -70,9 +72,10 @@ function Appearances:init(frame) startDate = Logic.nilIfEmpty(args.sdate), endDate = Logic.nilIfEmpty(args.edate), pages = Array.parseCommaSeparatedString(args.pages), - series = args.series and - Array.extractValues(Table.filterByKey(args, function(key) return key:find('^series%d-$') end)) - or nil, + series = args.series and Array.map( + Array.extractValues(Table.filterByKey(args, function(key) return key:find('^series%d-$') end)), + Page.pageifyLink + ) or nil, } return self @@ -81,7 +84,7 @@ end ---@return self function Appearances:create() self.tournaments = mw.ext.LiquipediaDB.lpdb('tournament', { - conditions = self.args.conditions or self:_buildConditions(), + conditions = tostring(self.args.conditions or self:_buildConditions()), limit = 5000, order = 'enddate asc', query = 'pagename, name, shortname, icon, icondark', @@ -97,33 +100,35 @@ function Appearances:create() return self end ----@return string +---@return ConditionTree function Appearances:_buildConditions() local args = self.args local conditions = ConditionTree(BooleanOperator.all) :add{ConditionNode(ColumnName('enddate'), Comparator.gt, DateExt.defaultDate)} - Appearances._buildOrConditionsFromArray(conditions, {'finished', ''}, 'status') - Appearances._buildOrConditionsFromArray(conditions, args.tiers, 'liquipediatier') - Appearances._buildOrConditionsFromArray(conditions, args.tierTypes, 'liquipediatiertype') + conditions:add(ConditionUtil.anyOf(ColumnName('status'), {'finished', ''})) + conditions:add(ConditionUtil.anyOf(ColumnName('liquipediatier'), args.tiers)) + conditions:add(ConditionUtil.anyOf(ColumnName('liquipediatiertype'), args.tierTypes)) if Table.isNotEmpty(args.series) then - Appearances._buildOrConditionsFromArray(conditions, args.series, 'seriespage', 'extradata_series2', true) + conditions:add{ + ConditionUtil.anyOf(ColumnName('seriespage'), args.series), + ConditionUtil.anyOf(ColumnName('series2', 'extradata'), args.series), + } else - args.pages = Array.map(args.pages, function(page) return (page:gsub(' ', '_')) end) - Appearances._buildOrConditionsFromArray(conditions, args.pages, 'pagename') + conditions:add(ConditionUtil.anyOf(ColumnName('pagename'), Array.map(args.pages, Page.pageifyLink))) end if args.startDate then - conditions:add{ConditionNode(ColumnName('startdate'), Comparator.ge, args.startDate)} + conditions:add(ConditionNode(ColumnName('startdate'), Comparator.ge, args.startDate)) end if args.endDate then - conditions:add{ConditionNode(ColumnName('enddate'), Comparator.le, args.endDate)} + conditions:add(ConditionNode(ColumnName('enddate'), Comparator.le, args.endDate)) end - return conditions:toString() + return conditions end function Appearances:_fetchPlayers(pageNames) From 47e04ccb864d709279979732b381d802d65a7f94 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:11:52 +0900 Subject: [PATCH 08/38] type annotations --- lua/wikis/commons/PlayerTournamentAppearances.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 75cdfd5e2b1..6662f91edb6 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -100,6 +100,7 @@ function Appearances:create() return self end +---@private ---@return ConditionTree function Appearances:_buildConditions() local args = self.args @@ -131,6 +132,9 @@ function Appearances:_buildConditions() return conditions end +---@private +---@param pageNames string[] +---@return table[] function Appearances:_fetchPlayers(pageNames) local players = {} @@ -187,6 +191,7 @@ function Appearances:_fetchPlayers(pageNames) return playersArray end +---@private ---@param pageNames string[] ---@return string function Appearances:_placementConditions(pageNames) @@ -207,6 +212,7 @@ function Appearances:_placementConditions(pageNames) return conditions:toString() end +---@private ---@param parent ConditionTree ---@param arr string[] ---@param key string From 5f59ca843a807fb218c6e0c77ba64a1fd28b203b Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:13:58 +0900 Subject: [PATCH 09/38] allow both string and condition node for query --- lua/wikis/commons/Tournament.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/wikis/commons/Tournament.lua b/lua/wikis/commons/Tournament.lua index caf2eb2b469..3edd630390e 100644 --- a/lua/wikis/commons/Tournament.lua +++ b/lua/wikis/commons/Tournament.lua @@ -47,7 +47,7 @@ local TOURNAMENT_PHASE = { ---@field extradata table ---@field isHighlighted fun(self: StandardTournament, options?: table): boolean ----@param conditions ConditionTree? +---@param conditions string|AbstractConditionNode? ---@param filterTournament fun(tournament: StandardTournament): boolean ---@return StandardTournament[] function Tournament.getAllTournaments(conditions, filterTournament) @@ -55,7 +55,7 @@ function Tournament.getAllTournaments(conditions, filterTournament) Lpdb.executeMassQuery( 'tournament', { - conditions = conditions and conditions:toString() or nil, + conditions = tostring(conditions), order = 'sortdate desc', limit = 1000, }, From eca7221f82ef8f77cc7dc155171ed41e81fda636 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:14:59 +0900 Subject: [PATCH 10/38] make filterTournament function optional --- lua/wikis/commons/Tournament.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/wikis/commons/Tournament.lua b/lua/wikis/commons/Tournament.lua index 3edd630390e..1a6cc752e5e 100644 --- a/lua/wikis/commons/Tournament.lua +++ b/lua/wikis/commons/Tournament.lua @@ -48,7 +48,7 @@ local TOURNAMENT_PHASE = { ---@field isHighlighted fun(self: StandardTournament, options?: table): boolean ---@param conditions string|AbstractConditionNode? ----@param filterTournament fun(tournament: StandardTournament): boolean +---@param filterTournament? fun(tournament: StandardTournament): boolean ---@return StandardTournament[] function Tournament.getAllTournaments(conditions, filterTournament) local tournaments = {} From 09a4903782fe03f19f8d6e1f34305ea70293b88e Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:16:07 +0900 Subject: [PATCH 11/38] use StandardTournament --- lua/wikis/commons/PlayerTournamentAppearances.lua | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 6662f91edb6..32544f2035c 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -24,6 +24,7 @@ local Page = Lua.import('Module:Page') local Placement = Lua.import('Module:Placement') local Table = Lua.import('Module:Table') local Team = Lua.import('Module:Team') +local Tournament = Lua.import('Module:Tournament') local ConditionTree = Condition.Tree local ConditionNode = Condition.Node @@ -37,6 +38,7 @@ local DEFAULT_TIERTYPES = {'General', 'School', ''} ---@class PlayerTournamentAppearances: BaseClass ---@operator call(Frame): PlayerTournamentAppearances +---@field tournaments StandardTournament[] local Appearances = Class.new(function(self, frame) self:init(frame) end) ---@param frame Frame @@ -83,12 +85,7 @@ end ---@return self function Appearances:create() - self.tournaments = mw.ext.LiquipediaDB.lpdb('tournament', { - conditions = tostring(self.args.conditions or self:_buildConditions()), - limit = 5000, - order = 'enddate asc', - query = 'pagename, name, shortname, icon, icondark', - }) + self.tournaments = Tournament.getAllTournaments(self.args.conditions or self:_buildConditions()) if Table.isEmpty(self.tournaments) then return self From bab513103db2f9a8b5171b748a44554664cc0146 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:19:51 +0900 Subject: [PATCH 12/38] clean up condition building --- .../commons/PlayerTournamentAppearances.lua | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 32544f2035c..2fbd26b586b 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -190,23 +190,20 @@ end ---@private ---@param pageNames string[] ----@return string +---@return ConditionTree function Appearances:_placementConditions(pageNames) - local conditions = ConditionTree(BooleanOperator.all) - :add{ConditionNode(ColumnName('opponentplayers'), Comparator.neq, '')} - :add{ConditionNode(ColumnName('opponentplayers'), Comparator.neq, '[]')} - :add{ConditionNode(ColumnName('opponentname'), Comparator.neq, 'TBD')} - :add{ConditionNode(ColumnName('opponentname'), Comparator.neq, 'Definitions')} - :add{ConditionNode(ColumnName('opponentname'), Comparator.neq, '')} - :add{ConditionNode(ColumnName('mode'), Comparator.neq, 'award_individual')} - - Appearances._buildOrConditionsFromArray(conditions, pageNames, 'pagename') + local conditions = ConditionTree(BooleanOperator.all):add{ + ConditionUtil.noneOf(ColumnName('opponentplayers'), {'', '[]'}), + ConditionUtil.noneOf(ColumnName('opponentname'), {'TBD', 'Definitions', ''}), + ConditionNode(ColumnName('mode'), Comparator.neq, 'award_individual'), + ConditionUtil.anyOf(ColumnName('pagename'), pageNames) + } if self.config.restrictToFirstPrizePool then - conditions:add{ConditionNode(ColumnName('prizepoolindex'), Comparator.eq, 1)} + conditions:add(ConditionNode(ColumnName('prizepoolindex'), Comparator.eq, 1)) end - return conditions:toString() + return conditions end ---@private From 6d9b0dee45fb60f4255c68a30664471acddb7da8 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:20:07 +0900 Subject: [PATCH 13/38] remove unused helper function --- .../commons/PlayerTournamentAppearances.lua | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 2fbd26b586b..36f80546c9e 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -206,33 +206,6 @@ function Appearances:_placementConditions(pageNames) return conditions end ----@private ----@param parent ConditionTree ----@param arr string[] ----@param key string ----@param key2 string? ----@param toUnderScore boolean? -function Appearances._buildOrConditionsFromArray(parent, arr, key, key2, toUnderScore) - if Table.isEmpty(arr) then return end - - local orConditions = ConditionTree(BooleanOperator.any) - for _, value in ipairs(arr) do - orConditions:add{ConditionNode(ColumnName(key), Comparator.eq, value)} - if key2 then - orConditions:add{ConditionNode(ColumnName(key2), Comparator.eq, value)} - end - local underScoreValue = value:gsub(' ', '_') - if toUnderScore then - orConditions:add{ConditionNode(ColumnName(key), Comparator.eq, underScoreValue)} - end - if key2 and toUnderScore then - orConditions:add{ConditionNode(ColumnName(key2), Comparator.eq, underScoreValue)} - end - end - - parent:add(orConditions) -end - ---@return string|Html function Appearances:build() if not self.players then return 'No results found.' end From cbdbeb91ea6dc4c2cddbfb99b6c7063a658dedcc Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:21:04 +0900 Subject: [PATCH 14/38] update key --- lua/wikis/commons/PlayerTournamentAppearances.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 36f80546c9e..7eebc12a03f 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -91,7 +91,7 @@ function Appearances:create() return self end - local pageNames = Array.map(self.tournaments, Operator.property('pagename')) + local pageNames = Array.map(self.tournaments, Operator.property('pageName')) self.players = self:_fetchPlayers(pageNames) return self From dc21c58e4532c708afd9a737d525c63d1adffcac Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:22:41 +0900 Subject: [PATCH 15/38] fix lpdb field name --- lua/wikis/commons/PlayerTournamentAppearances.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 7eebc12a03f..85d386ebefc 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -196,7 +196,7 @@ function Appearances:_placementConditions(pageNames) ConditionUtil.noneOf(ColumnName('opponentplayers'), {'', '[]'}), ConditionUtil.noneOf(ColumnName('opponentname'), {'TBD', 'Definitions', ''}), ConditionNode(ColumnName('mode'), Comparator.neq, 'award_individual'), - ConditionUtil.anyOf(ColumnName('pagename'), pageNames) + ConditionUtil.anyOf(ColumnName('parent'), pageNames) } if self.config.restrictToFirstPrizePool then From c8effea83701cd51f9937a5b6f84e472f605ca23 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:40:04 +0900 Subject: [PATCH 16/38] clean up player query --- .../commons/PlayerTournamentAppearances.lua | 72 +++++++++++-------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 85d386ebefc..8dff3016fba 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -15,6 +15,7 @@ local Condition = Lua.import('Module:Condition') local DateExt = Lua.import('Module:Date/Ext') local Faction = Lua.import('Module:Faction') local Flags = Lua.import('Module:Flags') +local FnUtil = Lua.import('Module:FnUtil') local LeagueIcon = Lua.import('Module:LeagueIcon') local Logic = Lua.import('Module:Logic') local Lpdb = Lua.import('Module:Lpdb') @@ -133,59 +134,68 @@ end ---@param pageNames string[] ---@return table[] function Appearances:_fetchPlayers(pageNames) + ---@type table local players = {} Lpdb.executeMassQuery('placement', { conditions = self:_placementConditions(pageNames), limit = 1000, order = 'date asc', - query = 'opponentplayers, opponenttype, pagename, date, placement, opponenttemplate', + query = 'opponentplayers, opponenttype, opponentname, parent, date, placement, opponenttemplate', }, function(placement) - for prefix, playerPage in Table.iter.pairsByPrefix(placement.opponentplayers or {}, self.config.prefix) do - if not players[playerPage] then - players[playerPage] = { - link = playerPage, - appearances = 0, - placementSum = 0, - results = {}, - } + local opponent = Opponent.fromLpdbStruct(placement) + Array.forEach(opponent.players, function (player, playerIndex) + if Opponent.playerIsTbd(player) then + return end + local pageName = player.pageName + ---@cast pageName -nil + if not players[pageName] then + players[pageName] = player + player.extradata = player.extradata or {} + player.extradata.appearances = 0 + player.extradata.placementSum = 0 + player.extradata.results = {} + end + + local extradata = players[pageName].extradata --[[ @as table ]] - players[playerPage].appearances = players[playerPage].appearances + 1 - players[playerPage].flag = Logic.emptyOr(placement.opponentplayers[prefix .. 'flag'], players[playerPage].flag) - players[playerPage].name = Logic.emptyOr(placement.opponentplayers[prefix .. 'dn'], players[playerPage].name) - players[playerPage].faction = Logic.emptyOr(placement.opponentplayers[prefix .. 'faction'], players[playerPage].faction) - players[playerPage].results[placement.pagename] = { + extradata.appearances = extradata.appearances + 1 + extradata.results[placement.parent] = { placement = placement.placement, date = placement.date, - team = placement.opponenttype == Opponent.team and placement.opponenttemplate - or placement.opponentplayers[prefix .. 'template'] - or placement.opponentplayers[prefix .. 'team'], + team = placement.opponenttype == Opponent.team and placement.opponenttemplate or player.team } - local placementParts = mw.text.split(string.lower(placement.placement or ''), '-', true) - players[playerPage].placementSum = players[playerPage].placementSum + (tonumber(placementParts[1]) or 1000) - end + local rawPlacement = Placement.raw(placement.placement) + extradata.placementSum = extradata.placementSum + (tonumber(rawPlacement.placement[1]) or 1000) + end) end) local playersArray = Array.extractValues(players) if self.config.restrictToPlayersParticipatingIn then playersArray = Array.filter(playersArray, function(player) - return player.results[self.config.restrictToPlayersParticipatingIn] + return player.extradata.results[self.config.restrictToPlayersParticipatingIn] end) end - table.sort(playersArray, function(a, b) - if a.appearances ~= b.appearances then - return a.appearances > b.appearances - end - if a.placementSum ~= b.placementSum then - return a.placementSum < b.placementSum + return Array.sortBy( + playersArray, + FnUtil.identity, + ---@param a standardPlayer + ---@param b standardPlayer + ---@return boolean + function (a, b) + local aData = a.extradata or {} + local bData = b.extradata or {} + if aData.appearances ~= bData.appearances then + return aData.appearances > bData.appearances + elseif aData.placementSum ~= bData.placementSum then + return aData.placementSum < bData.placementSum + end + return a.pageName < b.pageName end - return a.link < b.link - end) - - return playersArray + ) end ---@private From 1eedb899e9180ac4ca15f4c030c51a4bd0a59a66 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:40:34 +0900 Subject: [PATCH 17/38] clean up unused param --- lua/wikis/commons/PlayerTournamentAppearances.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 8dff3016fba..be7bfda26cd 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -58,7 +58,6 @@ function Appearances:init(frame) assert(args.series or args.pages or args.conditions, 'Either "series", "pages" or "conditions" input has to be specified') self.config = { - prefix = args.prefix or 'p', displayIconInsteadOfShortName = Table.includes(ICON_HEADER_TYPES, args.headerType), displayFactionColumn = Logic.readBool(args.displayFactionColumn), showPlacementInsteadOfTeam = Logic.readBool(args.showPlacementInsteadOfTeam), From e57e86ce4be1ebae4cea394166bb17b13c7e50c9 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:44:24 +0900 Subject: [PATCH 18/38] refactor header --- .../commons/PlayerTournamentAppearances.lua | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index be7bfda26cd..8d9a312a2da 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -34,6 +34,8 @@ local BooleanOperator = Condition.BooleanOperator local ColumnName = Condition.ColumnName local ConditionUtil = Condition.Util +local TournamentTitle = Lua.import('Module:Widget/Tournament/Title') + local ICON_HEADER_TYPES = {'icons', 'icon'} local DEFAULT_TIERTYPES = {'General', 'School', ''} @@ -256,21 +258,7 @@ function Appearances:_header() :tag('th'):wikitext(Abbreviation.make{text = 'TA.', title = 'Total appearances'}) for _, tournament in ipairs(self.tournaments) do - if self.config.displayIconInsteadOfShortName then - header:tag('th'):node(LeagueIcon.display{ - icon = tournament.icon, - iconDark = tournament.icondark, - link = tournament.pagename, - name = tournament.name, - options = {noTemplate = true}, - }) - else - header:tag('th'):wikitext('[[' .. tournament.pagename .. '|' .. Logic.emptyOr( - tournament.shortname, - tournament.name, - (tournament.pagename:gsub('_', ' ')) - ) .. ']]') - end + header:tag('th'):node(TournamentTitle{tournament = tournament}) end return header From 7a9f0b135df312d0c8f8b43751f53cd76ed97354 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 13:15:00 +0900 Subject: [PATCH 19/38] finish rest --- .../commons/PlayerTournamentAppearances.lua | 38 ++++++++----------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 8d9a312a2da..894fb296944 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -13,18 +13,17 @@ local Array = Lua.import('Module:Array') local Class = Lua.import('Module:Class') local Condition = Lua.import('Module:Condition') local DateExt = Lua.import('Module:Date/Ext') -local Faction = Lua.import('Module:Faction') local Flags = Lua.import('Module:Flags') local FnUtil = Lua.import('Module:FnUtil') -local LeagueIcon = Lua.import('Module:LeagueIcon') local Logic = Lua.import('Module:Logic') local Lpdb = Lua.import('Module:Lpdb') local Operator = Lua.import('Module:Operator') local Opponent = Lua.import('Module:Opponent/Custom') +local OpponentDisplay = Lua.import('Module:OpponentDisplay/Custom') local Page = Lua.import('Module:Page') local Placement = Lua.import('Module:Placement') +local PlayerDisplay = Lua.import('Module:Player/Display/Custom') local Table = Lua.import('Module:Table') -local Team = Lua.import('Module:Team') local Tournament = Lua.import('Module:Tournament') local ConditionTree = Condition.Tree @@ -36,7 +35,6 @@ local ConditionUtil = Condition.Util local TournamentTitle = Lua.import('Module:Widget/Tournament/Title') -local ICON_HEADER_TYPES = {'icons', 'icon'} local DEFAULT_TIERTYPES = {'General', 'School', ''} ---@class PlayerTournamentAppearances: BaseClass @@ -60,8 +58,6 @@ function Appearances:init(frame) assert(args.series or args.pages or args.conditions, 'Either "series", "pages" or "conditions" input has to be specified') self.config = { - displayIconInsteadOfShortName = Table.includes(ICON_HEADER_TYPES, args.headerType), - displayFactionColumn = Logic.readBool(args.displayFactionColumn), showPlacementInsteadOfTeam = Logic.readBool(args.showPlacementInsteadOfTeam), limit = tonumber(args.limit), isFormQuery = Logic.readBool(args.query), @@ -112,10 +108,10 @@ function Appearances:_buildConditions() conditions:add(ConditionUtil.anyOf(ColumnName('liquipediatiertype'), args.tierTypes)) if Table.isNotEmpty(args.series) then - conditions:add{ + conditions:add(ConditionTree(BooleanOperator.any):add{ ConditionUtil.anyOf(ColumnName('seriespage'), args.series), ConditionUtil.anyOf(ColumnName('series2', 'extradata'), args.series), - } + }) else conditions:add(ConditionUtil.anyOf(ColumnName('pagename'), Array.map(args.pages, Page.pageifyLink))) end @@ -133,13 +129,13 @@ end ---@private ---@param pageNames string[] ----@return table[] +---@return standardPlayer[] function Appearances:_fetchPlayers(pageNames) ---@type table local players = {} Lpdb.executeMassQuery('placement', { - conditions = self:_placementConditions(pageNames), + conditions = tostring(self:_placementConditions(pageNames)), limit = 1000, order = 'date asc', query = 'opponentplayers, opponenttype, opponentname, parent, date, placement, opponenttemplate', @@ -249,10 +245,6 @@ function Appearances:_header() local header = mw.html.create('tr') :tag('th'):done() - if self.config.displayFactionColumn then - header:tag('th') - end - header :tag('th'):wikitext('Player'):done() :tag('th'):wikitext(Abbreviation.make{text = 'TA.', title = 'Total appearances'}) @@ -273,16 +265,14 @@ function Appearances:_row(playerIndex) local row = mw.html.create('tr') :tag('td'):wikitext(Flags.Icon{flag = player.flag}):done() - if self.config.displayFactionColumn then - row:tag('td'):wikitext(Faction.Icon{faction = player.faction}) - end - row - :tag('td'):css('text-align', 'left'):wikitext('[[' .. player.link .. '|' .. player.name .. ']]'):done() - :tag('td'):wikitext(player.appearances) + :tag('td'):css('text-align', 'left'):node(PlayerDisplay.InlinePlayer{ + player = player, showFlag = false + }):done() + :tag('td'):wikitext(player.extradata.appearances) for _, tournament in ipairs(self.tournaments) do - local result = player.results[tournament.pagename] + local result = player.extradata.results[tournament.pageName] local cell = row:tag('td') if self.config.showPlacementInsteadOfTeam then @@ -291,7 +281,9 @@ function Appearances:_row(playerIndex) elseif result then cell :attr('data-sort-value', result.team) - :wikitext(result.team and Team.icon(nil, result.team, result.date) or nil) + :node(result.team and OpponentDisplay.InlineTeamContainer{ + template = result.team, date = result.date, style = 'icon' + } or nil) if tonumber(result.placement) == 1 then cell:addClass('tournament-highlighted-bg') @@ -321,7 +313,7 @@ function Appearances:_buildQueryLink() return mw.html.create('tr') :tag('th') - :attr('colspan', #self.tournaments + 3 + (self.config.displayFactionColumn and 1 or 0)) + :attr('colspan', #self.tournaments + 3) :css('font-size', 'small') :wikitext('[' .. queryString .. ' Click here to modify this table]') :done() From 24d997d5cad93837130019b2d55f061a33c15d8b Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 13:17:48 +0900 Subject: [PATCH 20/38] reverse order --- lua/wikis/commons/PlayerTournamentAppearances.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 894fb296944..4ac924d1380 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -83,7 +83,7 @@ end ---@return self function Appearances:create() - self.tournaments = Tournament.getAllTournaments(self.args.conditions or self:_buildConditions()) + self.tournaments = Array.reverse(Tournament.getAllTournaments(self.args.conditions or self:_buildConditions())) if Table.isEmpty(self.tournaments) then return self From 57622e652eec0887cb973936cdeb33c9a9d1f5e8 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 13:20:56 +0900 Subject: [PATCH 21/38] clean up query link --- .../commons/PlayerTournamentAppearances.lua | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 4ac924d1380..7ff91ba59da 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -298,18 +298,17 @@ end ---@return Html function Appearances:_buildQueryLink() local queryTable = { - ['PTAdev[series]'] = self.plainArgs.series or '', - ['PTAdev[pages]'] = self.plainArgs.pages or '', - ['PTAdev[tiers]'] = self.plainArgs.tiers or '', - ['PTAdev[limit]'] = self.plainArgs.limit or '', - ['PTAdev[playerspage]'] = self.plainArgs.playerspage or '', - ['PTAdev[query]'] = 'true', + ['PTA[series]'] = self.plainArgs.series or '', + ['PTA[pages]'] = table.concat(self.args.pages, ','), + ['PTA[tiers]'] = self.plainArgs.tiers, + ['PTA[limit]'] = self.plainArgs.limit or '', + ['PTA[playerspage]'] = self.plainArgs.playerspage or '', + ['PTA[query]'] = 'true', + pfRunQueryFormName = 'Player tournament appearances', + wpRunQuery = 'Run query', } - self:_toQuerySubTable(queryTable, 'pages') - self:_toQuerySubTable(queryTable, 'tiers') - - local queryString = tostring(mw.uri.fullUrl('Special:RunQuery/Player_tournament_appearances')) .. '?pfRunQueryFormName=Player+tournament+appearances&' .. mw.uri.buildQueryString(queryTable) .. '&wpRunQuery=Run+query' + local queryString = tostring(mw.uri.fullUrl('Special:RunQuery/Player_tournament_appearances', queryTable)) return mw.html.create('tr') :tag('th') @@ -319,14 +318,4 @@ function Appearances:_buildQueryLink() :done() end ----@private ----@param queryTable table ----@param key string -function Appearances:_toQuerySubTable(queryTable, key) - local prefix = 'PTAdev[' .. key .. ']' - for index, value in ipairs(self.args[key] or {''}) do - queryTable[prefix .. '[' .. index .. ']'] = value - end -end - return Appearances From 9b08e029ca60a48019802158e11f5f4087404440 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 13:39:28 +0900 Subject: [PATCH 22/38] use DataTable widget --- .../commons/PlayerTournamentAppearances.lua | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 7ff91ba59da..16c8f5a89c6 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -33,7 +33,9 @@ local BooleanOperator = Condition.BooleanOperator local ColumnName = Condition.ColumnName local ConditionUtil = Condition.Util +local DataTable = Lua.import('Module:Widget/Basic/DataTable') local TournamentTitle = Lua.import('Module:Widget/Tournament/Title') +local WidgetUtil = Lua.import('Module:Widget/Util') local DEFAULT_TIERTYPES = {'General', 'School', ''} @@ -43,7 +45,7 @@ local DEFAULT_TIERTYPES = {'General', 'School', ''} local Appearances = Class.new(function(self, frame) self:init(frame) end) ---@param frame Frame ----@return string|Html +---@return string|Widget function Appearances.run(frame) return Appearances(frame):create():build() end @@ -213,30 +215,26 @@ function Appearances:_placementConditions(pageNames) return conditions end ----@return string|Html +---@return string|Widget function Appearances:build() if not self.players then return 'No results found.' end - local display = mw.html.create('table') - :addClass('wikitable sortable wikitable-striped') - :css('text-align', 'center') - :css('margin', '0') - :node(self:_header()) - local limit = math.min(self.config.limit or #self.players, #self.players) - for playerIndex = 1, limit do - display:node(self:_row(playerIndex)) - end - - if self.config.restrictToPlayersParticipatingIn and not self.config.isFormQuery then - display:node(self:_buildQueryLink()) - end - - return mw.html.create('div') - :addClass('table-responsive') - :css('margin-bottom', '10px') - :node(display) + return DataTable{ + classes = {'wikitable-striped'}, + sortable = true, + css = {['margin-bottom'] = '10px'}, + tableCss = { + ['text-align'] = 'center', + margin = 0, + }, + children = WidgetUtil.collect( + self:_header(), + Array.map(Array.range(1, limit), FnUtil.curry(Appearances._row, self)), + (self.config.restrictToPlayersParticipatingIn and not self.config.isFormQuery) and self:_buildQueryLink() or nil + ) + } end ---@private From 7080e06356c48eda5a07d6d106686a0dbc0dacae Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 13:51:39 +0900 Subject: [PATCH 23/38] use widget for header --- .../commons/PlayerTournamentAppearances.lua | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 16c8f5a89c6..5a835510765 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -34,7 +34,10 @@ local ColumnName = Condition.ColumnName local ConditionUtil = Condition.Util local DataTable = Lua.import('Module:Widget/Basic/DataTable') +local HtmlWidgets = Lua.import('Module:Widget/Html/All') local TournamentTitle = Lua.import('Module:Widget/Tournament/Title') +local Th = HtmlWidgets.Th +local Tr = HtmlWidgets.Tr local WidgetUtil = Lua.import('Module:Widget/Util') local DEFAULT_TIERTYPES = {'General', 'School', ''} @@ -238,20 +241,16 @@ function Appearances:build() end ---@private ----@return Html +---@return Widget function Appearances:_header() - local header = mw.html.create('tr') - :tag('th'):done() - - header - :tag('th'):wikitext('Player'):done() - :tag('th'):wikitext(Abbreviation.make{text = 'TA.', title = 'Total appearances'}) - - for _, tournament in ipairs(self.tournaments) do - header:tag('th'):node(TournamentTitle{tournament = tournament}) - end - - return header + return Tr{children = WidgetUtil.collect( + Th{}, + Th{children = 'Player'}, + Th{children = HtmlWidgets.Abbr{children = 'TA.', title = 'Total appearances'}}, + Array.map(self.tournaments, function (tournament) + return Th{children = TournamentTitle{tournament = tournament}} + end) + )} end ---@private From a5fa6fabb46a20abe2a290363e016e0a8381c850 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 13:52:00 +0900 Subject: [PATCH 24/38] Array.forEach --- lua/wikis/commons/PlayerTournamentAppearances.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 5a835510765..401f494908f 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -268,7 +268,7 @@ function Appearances:_row(playerIndex) }):done() :tag('td'):wikitext(player.extradata.appearances) - for _, tournament in ipairs(self.tournaments) do + Array.forEach(self.tournaments, function (tournament) local result = player.extradata.results[tournament.pageName] local cell = row:tag('td') @@ -286,7 +286,7 @@ function Appearances:_row(playerIndex) cell:addClass('tournament-highlighted-bg') end end - end + end) return row end From d98247d2bca31a0f2f6866956595eaa24408a630 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 13:54:34 +0900 Subject: [PATCH 25/38] use widget for footer --- .../commons/PlayerTournamentAppearances.lua | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 401f494908f..2b32b80bfa1 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -35,6 +35,7 @@ local ConditionUtil = Condition.Util local DataTable = Lua.import('Module:Widget/Basic/DataTable') local HtmlWidgets = Lua.import('Module:Widget/Html/All') +local LinkWidget = Lua.import('Module:Widget/Basic/Link') local TournamentTitle = Lua.import('Module:Widget/Tournament/Title') local Th = HtmlWidgets.Th local Tr = HtmlWidgets.Tr @@ -292,7 +293,7 @@ function Appearances:_row(playerIndex) end ---@private ----@return Html +---@return Widget function Appearances:_buildQueryLink() local queryTable = { ['PTA[series]'] = self.plainArgs.series or '', @@ -305,14 +306,15 @@ function Appearances:_buildQueryLink() wpRunQuery = 'Run query', } - local queryString = tostring(mw.uri.fullUrl('Special:RunQuery/Player_tournament_appearances', queryTable)) - - return mw.html.create('tr') - :tag('th') - :attr('colspan', #self.tournaments + 3) - :css('font-size', 'small') - :wikitext('[' .. queryString .. ' Click here to modify this table]') - :done() + return Tr{children = Th{ + attributes = {colspan = #self.tournaments + 3}, + css = {['font-size'] = 'small'}, + children = LinkWidget{ + link = tostring(mw.uri.fullUrl('Special:RunQuery/Player_tournament_appearances', queryTable)), + children = 'Click here to modify this table', + linktype = 'external', + } + }} end return Appearances From 59e6a2b0da6e250ad190e2104b55ba9be395a696 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 13:55:07 +0900 Subject: [PATCH 26/38] remove unused import --- lua/wikis/commons/PlayerTournamentAppearances.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 2b32b80bfa1..22bab75cd5e 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -7,7 +7,6 @@ local Lua = require('Module:Lua') -local Abbreviation = Lua.import('Module:Abbreviation') local Arguments = Lua.import('Module:Arguments') local Array = Lua.import('Module:Array') local Class = Lua.import('Module:Class') From e266ef9fea81fc0ffbb1cbbf130f2230536e7404 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 13:57:46 +0900 Subject: [PATCH 27/38] underscore --- lua/wikis/commons/PlayerTournamentAppearances.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 22bab75cd5e..af4bf36c733 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -309,7 +309,7 @@ function Appearances:_buildQueryLink() attributes = {colspan = #self.tournaments + 3}, css = {['font-size'] = 'small'}, children = LinkWidget{ - link = tostring(mw.uri.fullUrl('Special:RunQuery/Player_tournament_appearances', queryTable)), + link = tostring(mw.uri.fullUrl('Special:RunQuery/Player tournament appearances', queryTable)), children = 'Click here to modify this table', linktype = 'external', } From 70b7ac879b057bd85bcd4f5a118549fb854c7231 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 13:58:59 +0900 Subject: [PATCH 28/38] add form existence check --- lua/wikis/commons/PlayerTournamentAppearances.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index af4bf36c733..d1258bbca5d 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -41,6 +41,7 @@ local Tr = HtmlWidgets.Tr local WidgetUtil = Lua.import('Module:Widget/Util') local DEFAULT_TIERTYPES = {'General', 'School', ''} +local FORM_NAME = 'Player tournament appearances' ---@class PlayerTournamentAppearances: BaseClass ---@operator call(Frame): PlayerTournamentAppearances @@ -292,8 +293,11 @@ function Appearances:_row(playerIndex) end ---@private ----@return Widget +---@return Widget? function Appearances:_buildQueryLink() + if not Page.exists('Form:' .. FORM_NAME) then + return + end local queryTable = { ['PTA[series]'] = self.plainArgs.series or '', ['PTA[pages]'] = table.concat(self.args.pages, ','), @@ -301,7 +305,7 @@ function Appearances:_buildQueryLink() ['PTA[limit]'] = self.plainArgs.limit or '', ['PTA[playerspage]'] = self.plainArgs.playerspage or '', ['PTA[query]'] = 'true', - pfRunQueryFormName = 'Player tournament appearances', + pfRunQueryFormName = FORM_NAME, wpRunQuery = 'Run query', } @@ -309,7 +313,7 @@ function Appearances:_buildQueryLink() attributes = {colspan = #self.tournaments + 3}, css = {['font-size'] = 'small'}, children = LinkWidget{ - link = tostring(mw.uri.fullUrl('Special:RunQuery/Player tournament appearances', queryTable)), + link = tostring(mw.uri.fullUrl('Special:RunQuery/' .. FORM_NAME, queryTable)), children = 'Click here to modify this table', linktype = 'external', } From 435951998f3347559ab59ceb86f9dca034ef6c74 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 14:01:14 +0900 Subject: [PATCH 29/38] cleaning --- lua/wikis/commons/PlayerTournamentAppearances.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index d1258bbca5d..545efbed5a5 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -145,9 +145,9 @@ function Appearances:_fetchPlayers(pageNames) limit = 1000, order = 'date asc', query = 'opponentplayers, opponenttype, opponentname, parent, date, placement, opponenttemplate', - }, function(placement) + }, function (placement) local opponent = Opponent.fromLpdbStruct(placement) - Array.forEach(opponent.players, function (player, playerIndex) + Array.forEach(opponent.players, function (player) if Opponent.playerIsTbd(player) then return end From bfcd5f52a0169d6d6d5c85aa0686321bb412595a Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 14:05:10 +0900 Subject: [PATCH 30/38] store shortname in standardtournament --- lua/wikis/commons/MatchGroup/Util.lua | 3 +++ lua/wikis/commons/Tournament.lua | 3 +++ 2 files changed, 6 insertions(+) diff --git a/lua/wikis/commons/MatchGroup/Util.lua b/lua/wikis/commons/MatchGroup/Util.lua index c48ec414700..21a3e75b87d 100644 --- a/lua/wikis/commons/MatchGroup/Util.lua +++ b/lua/wikis/commons/MatchGroup/Util.lua @@ -278,6 +278,7 @@ MatchGroupUtil.types.Game = TypeUtil.struct({ ---@field resultType string? ---@field section string? ---@field series string? +---@field shortname string? ---@field status MatchStatus ---@field stream table ---@field tickername string? @@ -313,6 +314,7 @@ MatchGroupUtil.types.Match = TypeUtil.struct({ resultType = 'string?', section = 'string?', series = 'string?', + shortname = 'string?', status = MatchGroupUtil.types.Status, stream = 'table', tickername = 'string?', @@ -587,6 +589,7 @@ function MatchGroupUtil.matchFromRecord(record) resultType = nilIfEmpty(record.resulttype), section = nilIfEmpty(record.section), series = nilIfEmpty(record.series), + shortname = nilIfEmpty(record.shortname), status = nilIfEmpty(record.status), stream = Json.parseIfString(record.stream) or {}, tickername = record.tickername, diff --git a/lua/wikis/commons/Tournament.lua b/lua/wikis/commons/Tournament.lua index 1a6cc752e5e..7b1c2a42a25 100644 --- a/lua/wikis/commons/Tournament.lua +++ b/lua/wikis/commons/Tournament.lua @@ -27,6 +27,7 @@ local TOURNAMENT_PHASE = { ---@class StandardTournamentPartial ---@field displayName string +---@field shortName string? ---@field fullName string ---@field pageName string ---@field icon string? @@ -101,6 +102,7 @@ function Tournament.partialTournamentFromMatch(match) ---@type StandardTournamentPartial return { displayName = Logic.emptyOr(match.tickername, match.tournament) or (match.parent or ''):gsub('_', ' '), + shortName = match.shortname, fullName = match.tournament, pageName = match.parent, liquipediaTier = Tier.toIdentifier(match.liquipediatier), @@ -122,6 +124,7 @@ function Tournament.tournamentFromRecord(record) local tournament = { displayName = Logic.emptyOr(record.tickername, record.name) or record.pagename:gsub('_', ' '), + shortName = Logic.nilIfEmpty(record.shortname), fullName = record.name, pageName = record.pagename, startDate = startDate, From 79a278cba31bde29d10d26b93d6b026ef1540ab3 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 14:07:36 +0900 Subject: [PATCH 31/38] use shortname --- lua/wikis/commons/PlayerTournamentAppearances.lua | 4 +++- lua/wikis/commons/Widget/Tournament/Title.lua | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 545efbed5a5..f67173460ef 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -249,7 +249,9 @@ function Appearances:_header() Th{children = 'Player'}, Th{children = HtmlWidgets.Abbr{children = 'TA.', title = 'Total appearances'}}, Array.map(self.tournaments, function (tournament) - return Th{children = TournamentTitle{tournament = tournament}} + return Th{children = TournamentTitle{ + tournament = tournament, useShortName = true + }} end) )} end diff --git a/lua/wikis/commons/Widget/Tournament/Title.lua b/lua/wikis/commons/Widget/Tournament/Title.lua index 7ada66e830b..95846cf763f 100644 --- a/lua/wikis/commons/Widget/Tournament/Title.lua +++ b/lua/wikis/commons/Widget/Tournament/Title.lua @@ -19,6 +19,7 @@ local Link = Lua.import('Module:Widget/Basic/Link') ---@class TournamentTitleProps ---@field tournament StandardTournamentPartial ---@field displayGameIcon boolean? +---@field useShortName boolean? ---@class TournamentTitleWidget: Widget ---@operator call(TournamentTitleProps): TournamentTitleWidget @@ -56,9 +57,7 @@ function TournamentTitleWidget:render() children = { Link{ link = tournament.pageName, - children = { - tournament.displayName, - }, + children = self.props.useShortName and tournament.shortName or tournament.displayName, }, } } From 1981ab452f13bb05072f4caf82568bf9826dbce6 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 14:15:41 +0900 Subject: [PATCH 32/38] use Logic.readBool --- lua/wikis/commons/Widget/Tournament/Title.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lua/wikis/commons/Widget/Tournament/Title.lua b/lua/wikis/commons/Widget/Tournament/Title.lua index 95846cf763f..23e81605b04 100644 --- a/lua/wikis/commons/Widget/Tournament/Title.lua +++ b/lua/wikis/commons/Widget/Tournament/Title.lua @@ -10,6 +10,7 @@ local Lua = require('Module:Lua') local Class = Lua.import('Module:Class') local Game = Lua.import('Module:Game') local LeagueIcon = Lua.import('Module:LeagueIcon') +local Logic = Lua.import('Module:Logic') local WidgetUtil = Lua.import('Module:Widget/Util') local Widget = Lua.import('Module:Widget') @@ -57,7 +58,7 @@ function TournamentTitleWidget:render() children = { Link{ link = tournament.pageName, - children = self.props.useShortName and tournament.shortName or tournament.displayName, + children = Logic.readBool(self.props.useShortName) and tournament.shortName or tournament.displayName, }, } } From 41b01db19e8c946dea75fc68f7e5fb5528a70af9 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 14:22:00 +0900 Subject: [PATCH 33/38] lint --- lua/wikis/commons/PlayerTournamentAppearances.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index f67173460ef..224a45f904f 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -61,7 +61,10 @@ function Appearances:init(frame) self.plainArgs = args - assert(args.series or args.pages or args.conditions, 'Either "series", "pages" or "conditions" input has to be specified') + assert( + args.series or args.pages or args.conditions, + 'Either "series", "pages" or "conditions" input has to be specified' + ) self.config = { showPlacementInsteadOfTeam = Logic.readBool(args.showPlacementInsteadOfTeam), From 6711dd0912d33c2485acffca69dc209253bfd439 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Tue, 10 Feb 2026 16:03:02 +0900 Subject: [PATCH 34/38] nil check --- lua/wikis/commons/Tournament.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/wikis/commons/Tournament.lua b/lua/wikis/commons/Tournament.lua index 7b1c2a42a25..9409bb30ed6 100644 --- a/lua/wikis/commons/Tournament.lua +++ b/lua/wikis/commons/Tournament.lua @@ -56,7 +56,7 @@ function Tournament.getAllTournaments(conditions, filterTournament) Lpdb.executeMassQuery( 'tournament', { - conditions = tostring(conditions), + conditions = conditions and tostring(conditions), order = 'sortdate desc', limit = 1000, }, From d3a995b3b703851ee7c1d1880243ba5c5d5b1630 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Wed, 25 Feb 2026 10:20:10 +0900 Subject: [PATCH 35/38] add classes when there is no context --- lua/wikis/commons/Widget/Table2/Cell.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/wikis/commons/Widget/Table2/Cell.lua b/lua/wikis/commons/Widget/Table2/Cell.lua index ddf6036748b..2b5bd267f50 100644 --- a/lua/wikis/commons/Widget/Table2/Cell.lua +++ b/lua/wikis/commons/Widget/Table2/Cell.lua @@ -53,6 +53,7 @@ function Table2Cell:render() props.shrink, props.attributes ), + classes = props.classes, children = props.children, } end From 56ede867738e4239c9570790747e7db68edf0031 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Wed, 25 Feb 2026 10:20:21 +0900 Subject: [PATCH 36/38] use table2 --- .../commons/PlayerTournamentAppearances.lua | 102 +++++++++--------- 1 file changed, 53 insertions(+), 49 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 224a45f904f..52ccc48c59d 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -35,6 +35,7 @@ local ConditionUtil = Condition.Util local DataTable = Lua.import('Module:Widget/Basic/DataTable') local HtmlWidgets = Lua.import('Module:Widget/Html/All') local LinkWidget = Lua.import('Module:Widget/Basic/Link') +local TableWidgets = Lua.import('Module:Widget/Table2/All') local TournamentTitle = Lua.import('Module:Widget/Tournament/Title') local Th = HtmlWidgets.Th local Tr = HtmlWidgets.Tr @@ -228,35 +229,33 @@ function Appearances:build() local limit = math.min(self.config.limit or #self.players, #self.players) - return DataTable{ - classes = {'wikitable-striped'}, + return TableWidgets.Table{ sortable = true, - css = {['margin-bottom'] = '10px'}, - tableCss = { - ['text-align'] = 'center', - margin = 0, - }, children = WidgetUtil.collect( self:_header(), - Array.map(Array.range(1, limit), FnUtil.curry(Appearances._row, self)), - (self.config.restrictToPlayersParticipatingIn and not self.config.isFormQuery) and self:_buildQueryLink() or nil - ) + TableWidgets.TableBody{ + children = Array.map(Array.range(1, limit), FnUtil.curry(Appearances._row, self)) + } + ), + footer = self:_buildQueryLink() } end ---@private ---@return Widget function Appearances:_header() - return Tr{children = WidgetUtil.collect( - Th{}, - Th{children = 'Player'}, - Th{children = HtmlWidgets.Abbr{children = 'TA.', title = 'Total appearances'}}, - Array.map(self.tournaments, function (tournament) - return Th{children = TournamentTitle{ - tournament = tournament, useShortName = true - }} - end) - )} + return TableWidgets.TableHeader{children = { + TableWidgets.Row{children = WidgetUtil.collect( + TableWidgets.CellHeader{}, + TableWidgets.CellHeader{children = 'Player'}, + TableWidgets.CellHeader{children = HtmlWidgets.Abbr{children = 'TA.', title = 'Total appearances'}}, + Array.map(self.tournaments, function (tournament) + return TableWidgets.CellHeader{children = TournamentTitle{ + tournament = tournament, useShortName = true + }} + end) + )} + }} end ---@private @@ -265,42 +264,47 @@ end function Appearances:_row(playerIndex) local player = self.players[playerIndex] - local row = mw.html.create('tr') - :tag('td'):wikitext(Flags.Icon{flag = player.flag}):done() - - row - :tag('td'):css('text-align', 'left'):node(PlayerDisplay.InlinePlayer{ + return TableWidgets.Row{children = WidgetUtil.collect( + TableWidgets.Cell{children = Flags.Icon{flag = player.flag}}, + TableWidgets.Cell{children = PlayerDisplay.InlinePlayer{ player = player, showFlag = false - }):done() - :tag('td'):wikitext(player.extradata.appearances) - - Array.forEach(self.tournaments, function (tournament) - local result = player.extradata.results[tournament.pageName] - local cell = row:tag('td') - - if self.config.showPlacementInsteadOfTeam then - -- Default to empty string to use data-sort-value - Placement._placement{parent = cell, placement = (result or {}).placement or ''} - elseif result then - cell - :attr('data-sort-value', result.team) - :node(result.team and OpponentDisplay.InlineTeamContainer{ - template = result.team, date = result.date, style = 'icon' - } or nil) - - if tonumber(result.placement) == 1 then - cell:addClass('tournament-highlighted-bg') + }}, + TableWidgets.Cell{children = player.extradata.appearances}, + Array.map(self.tournaments, function (tournament) + local result = player.extradata.results[tournament.pageName] or {} + if self.config.showPlacementInsteadOfTeam then + local rawPlacement = Placement.raw(result.placement or '') + return TableWidgets.Cell{ + attributes = { + ['data-sort-value'] = rawPlacement.sort + }, + classes = {rawPlacement.backgroundClass}, + children = HtmlWidgets.B{ + classes = not rawPlacement.blackText and {'placement-text'} or nil, + children = rawPlacement.display + } + } + elseif Logic.isNotEmpty(result) then + return TableWidgets.Cell{ + align = 'center', + classes = tonumber(result.placement) == 1 and {'tournament-highlighted-bg'} or nil, + attributes = {['data-sort-value'] = result.team}, + children = result.team and OpponentDisplay.InlineTeamContainer{ + template = result.team, date = result.date, style = 'icon' + } or nil + } end - end - end) - - return row + return TableWidgets.Cell{} + end) + )} end ---@private ---@return Widget? function Appearances:_buildQueryLink() - if not Page.exists('Form:' .. FORM_NAME) then + if not self.config.restrictToPlayersParticipatingIn or self.config.isFormQuery then + return + elseif not Page.exists('Form:' .. FORM_NAME) then return end local queryTable = { From eb5f3261ebc2d3d2b7b96b6210f051f83653cad9 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Wed, 25 Feb 2026 10:27:03 +0900 Subject: [PATCH 37/38] cleanup --- .../commons/PlayerTournamentAppearances.lua | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index 52ccc48c59d..cf2f5aef755 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -32,13 +32,10 @@ local BooleanOperator = Condition.BooleanOperator local ColumnName = Condition.ColumnName local ConditionUtil = Condition.Util -local DataTable = Lua.import('Module:Widget/Basic/DataTable') local HtmlWidgets = Lua.import('Module:Widget/Html/All') local LinkWidget = Lua.import('Module:Widget/Basic/Link') local TableWidgets = Lua.import('Module:Widget/Table2/All') local TournamentTitle = Lua.import('Module:Widget/Tournament/Title') -local Th = HtmlWidgets.Th -local Tr = HtmlWidgets.Tr local WidgetUtil = Lua.import('Module:Widget/Util') local DEFAULT_TIERTYPES = {'General', 'School', ''} @@ -318,15 +315,11 @@ function Appearances:_buildQueryLink() wpRunQuery = 'Run query', } - return Tr{children = Th{ - attributes = {colspan = #self.tournaments + 3}, - css = {['font-size'] = 'small'}, - children = LinkWidget{ - link = tostring(mw.uri.fullUrl('Special:RunQuery/' .. FORM_NAME, queryTable)), - children = 'Click here to modify this table', - linktype = 'external', - } - }} + return LinkWidget{ + link = tostring(mw.uri.fullUrl('Special:RunQuery/' .. FORM_NAME, queryTable)), + children = 'Click here to modify this table', + linktype = 'external', + } end return Appearances From 5010b6fe276f7e54dfa2733776f2c89404b07341 Mon Sep 17 00:00:00 2001 From: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com> Date: Wed, 25 Feb 2026 22:20:13 +0900 Subject: [PATCH 38/38] use placement badge --- lua/wikis/commons/PlayerTournamentAppearances.lua | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lua/wikis/commons/PlayerTournamentAppearances.lua b/lua/wikis/commons/PlayerTournamentAppearances.lua index cf2f5aef755..2cc21452cfa 100644 --- a/lua/wikis/commons/PlayerTournamentAppearances.lua +++ b/lua/wikis/commons/PlayerTournamentAppearances.lua @@ -276,10 +276,7 @@ function Appearances:_row(playerIndex) ['data-sort-value'] = rawPlacement.sort }, classes = {rawPlacement.backgroundClass}, - children = HtmlWidgets.B{ - classes = not rawPlacement.blackText and {'placement-text'} or nil, - children = rawPlacement.display - } + children = Placement.renderInWidget{placement = result.placement} } elseif Logic.isNotEmpty(result) then return TableWidgets.Cell{