Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
5f761e7
use anyOf
ElectricalBoy Oct 11, 2025
eddce8b
parseCommaSeparatedString
ElectricalBoy Oct 11, 2025
6f5bb23
code conciseness
ElectricalBoy Oct 11, 2025
0961861
remove redundant comma
ElectricalBoy Feb 26, 2026
e0dd11a
commaSeparatedString
ElectricalBoy Feb 26, 2026
0dcacef
clean up condition building
ElectricalBoy Feb 26, 2026
85533eb
use MGUMatch for processing
ElectricalBoy Feb 26, 2026
6788ea4
type conciseness
ElectricalBoy Feb 26, 2026
5a8be95
type annotation
ElectricalBoy Feb 26, 2026
54a3e64
use standardOpponent
ElectricalBoy Feb 26, 2026
af0145f
extract matchtable style to separate file
ElectricalBoy Feb 26, 2026
1c7ef27
use new table
ElectricalBoy Feb 26, 2026
9aee526
use formatPercentage
ElectricalBoy Feb 26, 2026
4b72bed
isDefaultTimestamp
ElectricalBoy Feb 26, 2026
c32b5e9
clean up stats
ElectricalBoy Feb 26, 2026
f205f91
clean up build
ElectricalBoy Feb 26, 2026
583b0dd
update custom
ElectricalBoy Feb 26, 2026
29b75d2
adjust access modifier
ElectricalBoy Feb 26, 2026
cdbd0f3
use html entity over code
ElectricalBoy Feb 26, 2026
e798df4
slice buildRows
ElectricalBoy Feb 26, 2026
975e459
clean up GameTable
ElectricalBoy Feb 26, 2026
65962e1
type anno
ElectricalBoy Feb 26, 2026
4e9b5db
use isMain
ElectricalBoy Feb 26, 2026
73eb2fa
rewrite charactergametable
ElectricalBoy Feb 26, 2026
b417220
lint
ElectricalBoy Feb 26, 2026
a791e16
adjust matchpage usage
ElectricalBoy Feb 27, 2026
78606f2
missing return
ElectricalBoy Feb 28, 2026
ba44966
indentation
ElectricalBoy Feb 28, 2026
fdd1c5f
add missing length display
ElectricalBoy Feb 28, 2026
b7f519c
restore notplayed filter
ElectricalBoy Feb 28, 2026
7fadf23
use compact date as default
ElectricalBoy Feb 28, 2026
4ea8e6a
make length sortable
ElectricalBoy Feb 28, 2026
571ba4f
add patch display
ElectricalBoy Feb 28, 2026
75d02d8
adjust background setting
ElectricalBoy Feb 28, 2026
7151906
fix character table mode
ElectricalBoy Feb 28, 2026
f8dd786
adjust deadlock custom
ElectricalBoy Feb 28, 2026
18232dd
adjust dota2 custom
ElectricalBoy Feb 28, 2026
a26efe2
add character table custom to commons
ElectricalBoy Feb 28, 2026
0c69469
type annotation
ElectricalBoy Feb 28, 2026
9a7eaff
update val custom type annotations
ElectricalBoy Feb 28, 2026
b3d5831
organize imports
ElectricalBoy Feb 28, 2026
7928d96
type anno
ElectricalBoy Feb 28, 2026
c1f298a
update val custom impl
ElectricalBoy Feb 28, 2026
c83510f
adjust column config
ElectricalBoy Feb 28, 2026
b151994
move date default to constructor
ElectricalBoy Feb 28, 2026
b47e4fe
formatRounded
ElectricalBoy Feb 28, 2026
85d432b
remove unused import
ElectricalBoy Feb 28, 2026
a13b174
add hover support
ElectricalBoy Feb 28, 2026
d427677
short button in character table
ElectricalBoy Feb 28, 2026
3f175ac
grayscale for bans
ElectricalBoy Feb 28, 2026
30f3472
use mixin
ElectricalBoy Mar 1, 2026
885b389
remove unused args
ElectricalBoy Mar 1, 2026
de7207c
cleanup
ElectricalBoy Mar 11, 2026
e857c7a
suppress sorting in matchpage
ElectricalBoy Mar 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
176 changes: 97 additions & 79 deletions lua/wikis/commons/GameTable.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,143 +9,161 @@ local Lua = require('Module:Lua')

local Array = Lua.import('Module:Array')
local Class = Lua.import('Module:Class')
local DateExt = Lua.import('Module:Date/Ext')
local Game = Lua.import('Module:Game')
local Logic = Lua.import('Module:Logic')
local Operator = Lua.import('Module:Operator')
local VodLink = Lua.import('Module:VodLink')

local MatchTable = Lua.import('Module:MatchTable')

local NOT_PLAYED = 'notplayed'
local SCORE_CONCAT = ' : '
local HtmlWidgets = Lua.import('Module:Widget/Html/All')
local TableWidgets = Lua.import('Module:Widget/Table2/All')
local WidgetUtil = Lua.import('Module:Widget/Util')

---@class GameTableMatch: MatchTableMatch
---@field games match2game[]
local NOT_PLAYED = 'notplayed'
local SCORE_CONCAT = ' : '

---@class GameTable: MatchTable
---@field countGames number
---@operator call(table): GameTable
---@field countGames integer
local GameTable = Class.new(MatchTable, function (self)
self.countGames = 0
end)

---@param game match2game
---@return match2game?
function GameTable:gameFromRecord(game)
if self.countGames == self.config.limit then return nil end
if game.status == NOT_PLAYED or Logic.isEmpty(game.winner) then
return nil
end

return game
end

---@param record table
---@return GameTableMatch?
---@param record match2
---@return MatchTableMatch?
function GameTable:matchFromRecord(record)
if self.countGames == self.config.limit then return nil end
if self.countGames >= self.config.limit then return nil end
local matchRecord = MatchTable.matchFromRecord(self, record)
---@cast matchRecord GameTableMatch
if Logic.isEmpty(record.match2games) then
if not matchRecord then
return
elseif Logic.isEmpty(record.match2games) then
return nil
end

matchRecord.games = {}
--order games from last played to first
Array.forEach(Array.reverse(record.match2games), function (game)
local gameRecord = self:gameFromRecord(game)
if gameRecord then self.countGames = self.countGames + 1 end
table.insert(matchRecord.games, gameRecord)
matchRecord.games = Array.filter(matchRecord.games, function (game)
return self:filterGame(game)
end)

self.countGames = self.countGames + #matchRecord.games

return matchRecord
end

---@param game MatchGroupUtilGame
---@return boolean
function GameTable:filterGame(game)
return game.status ~= NOT_PLAYED and Logic.isNotEmpty(game.winner)
end

---@param vod string?
---@return Html?
---@return Widget?
function GameTable:_displayGameVod(vod)
if not self.config.showVod then return end

local vodNode = mw.html.create('td')
if Logic.isEmpty(vod) then
return vodNode:wikitext('')
if not self.config.showVod then
return
elseif Logic.isEmpty(vod) then
return TableWidgets.Cell{}
end
---@cast vod -nil
return vodNode:node(VodLink.display{vod = vod})
return TableWidgets.Cell{children = VodLink.display{vod = vod}}
end

---@param result MatchTableMatchResult
---@param game match2game
---@param game MatchGroupUtilGame
---@return Html?
function GameTable:_displayGameScore(result, game)
local scores = Array.map(game.opponents, Operator.property('score'))
local toScore = function(opponentRecord)
local isWinner = opponentRecord.id == tonumber(game.winner)
local score = scores[opponentRecord.id] or (isWinner and 1) or 0
return mw.html.create(isWinner and 'b' or nil)
:wikitext(score)
local indexes = result.flipped and {2, 1} or {1, 2}

---@param opponentIndex integer
---@return Widget
local toScore = function(opponentIndex)
local isWinner = opponentIndex == tonumber(game.winner)
local score = scores[opponentIndex] or (isWinner and 1) or 0
return HtmlWidgets.Span{
css = {['font-weight'] = isWinner and 'bold' or nil},
children = score
}
end

return mw.html.create('td')
:addClass('match-table-score')
:node(toScore(result.opponent))
:node(SCORE_CONCAT)
:node(toScore(result.vs))
return TableWidgets.Cell{children = {
toScore(indexes[1]),
SCORE_CONCAT,
toScore(indexes[2]),
}}
end

---@param game match2game
---@param game MatchGroupUtilGame
---@return Html?
function GameTable:_displayGameIconForGame(game)
if not self.config.displayGameIcons then return end

return mw.html.create('td')
:node(Game.icon{game = game.game})
return TableWidgets.Cell{
children = Game.icon{game = game.game}
}
end

---@param match GameTableMatch
---@param game match2game
---@return Html?
---@param match MatchTableMatch
---@param game MatchGroupUtilGame
---@return Widget|Widget[]?
function GameTable:displayGame(match, game)
if not self.config.showResult then
return
elseif Logic.isEmpty(match.result.vs) then
return self:nonStandardMatch(match)
end

return mw.html.create()
:node(self.config.showOpponent and self:_displayOpponent(match.result.opponent, true) or nil)
:node(self:_displayGameScore(match.result, game))
:node(self:_displayOpponent(match.result.vs):css('text-align', 'left'))
return WidgetUtil.collect(
self.config.showOpponent and self:_displayOpponent(match.result.opponent, true) or nil,
self:_displayGameScore(match.result, game),
self:_displayOpponent(match.result.vs)
)
end

---@param match GameTableMatch
---@param game match2game
---@return Html?
---@param match MatchTableMatch
---@param game MatchGroupUtilGame
---@return Widget
function GameTable:gameRow(match, game)
local winner = match.result.opponent.id == tonumber(game.winner) and 1 or 2

return mw.html.create('tr')
:addClass(self:_getBackgroundClass(winner))
:node(self:_displayDate(match))
:node(self:_displayTier(match))
:node(self:_displayType(match))
:node(self:_displayGameIconForGame(game))
:node(self:_displayIcon(match))
:node(self:_displayTournament(match))
:node(self:displayGame(match, game))
:node(self:_displayGameVod(game.vod))
:node(self:_displayMatchPage(match))
local indexes = match.result.flipped and {2, 1} or {1, 2}
local winner = indexes[game.winner]

return TableWidgets.Row{
classes = {self:getBackgroundClass(winner)},
children = WidgetUtil.collect(
self:_displayDate(match),
self:displayTier(match),
self:_displayType(match),
self:_displayGameIconForGame(game),
self:_displayIcon(match),
self:_displayTournament(match),
self:displayGame(match, game),
self:_displayGameVod(game.vod),
self:_displayMatchPage(match)
)
}
end

---@param match GameTableMatch
---@return Html?
function GameTable:matchRow(match)
local display = mw.html.create()

Array.forEach(match.games, function(game)
display:node(self:gameRow(match, game))
---@return Widget[]
function GameTable:buildRows()
---@type Widget[]
local rows = {}

local currentYear = math.huge
Array.forEach(self.matches, function(match)
local year = DateExt.getYearOf(match.date)
if self.config.showYearHeaders and year ~= currentYear then
currentYear = year
table.insert(rows, self:_yearRow(year))
end
Array.extendWith(rows, Array.reverse(
Array.map(match.games, function (game)
return self:gameRow(match, game)
end)
))
end)

return display
return rows
end

return GameTable
Loading
Loading