Skip to content
Merged
Changes from 5 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
839a15c
Add initial draft with storage+fetch
mbergen Mar 1, 2026
b14ef39
Remove header css
mbergen Mar 1, 2026
e10fa9f
Rank alignment
mbergen Mar 1, 2026
ebd8133
tabs not spaces
mbergen Mar 1, 2026
072e405
Merge branch 'main' into vrsstandings
mbergen Mar 8, 2026
cbb3be6
Apply suggestion from review
mbergen Mar 11, 2026
1af0f2d
Update VRSStandings.lua
mbergen Mar 11, 2026
6a510cf
Remove "Remove before release"
mbergen Mar 12, 2026
589846d
Merge branch 'main' into vrsstandings
mbergen Mar 20, 2026
e8fe014
updating vrsstandings functionality (#7279)
MischiefCS Mar 20, 2026
9e98299
Update lua/wikis/counterstrike/VRSStandings.lua
MischiefCS Mar 22, 2026
6b0ba46
Update lua/wikis/counterstrike/MainPageLayout/data.lua
MischiefCS Mar 22, 2026
2198172
Apply suggestions from code review
MischiefCS Mar 22, 2026
d00dd11
resolving errors, functionality and adding two more data types
MischiefCS Mar 22, 2026
2bd7c15
Merge branch 'main' into vrsstandings
MischiefCS Mar 23, 2026
5846f99
Merge branch 'main' into vrsstandings
MischiefCS Mar 23, 2026
af674b2
Apply suggestions from code review
MischiefCS Mar 24, 2026
867bee8
fixing trailing commas in code review
MischiefCS Mar 24, 2026
1e6d1cf
resolving review
MischiefCS Mar 24, 2026
26a6471
distributing code over two modules for widget and data
MischiefCS Mar 26, 2026
d55b25b
Merge branch 'main' into vrsstandings
ElectricalBoy Mar 27, 2026
108ab4b
removing mainpage sizing & allowing custom filter name for subregion
MischiefCS Mar 27, 2026
378627c
Merge branch 'main' into vrsstandings
MischiefCS Mar 27, 2026
765d76e
responding to review comments
MischiefCS Mar 30, 2026
33115ff
resolving review comments
MischiefCS Mar 31, 2026
e20aba6
Merge branch 'main' into vrsstandings
MischiefCS Mar 31, 2026
a3be70b
Apply suggestions from code review
mbergen Apr 1, 2026
f944191
Fix comma, quotes
mbergen Apr 1, 2026
6829887
Split up getStandings
mbergen Apr 1, 2026
bba70db
Remove unused value
mbergen Apr 1, 2026
514a261
Merge branch 'main' into vrsstandings
mbergen Apr 1, 2026
11cf0b9
Merge branch 'main' into vrsstandings
mbergen Apr 14, 2026
eea9b6f
Per review
mbergen Apr 14, 2026
14168db
Fix indentation
mbergen Apr 14, 2026
abcb5c0
Linter
mbergen Apr 14, 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
215 changes: 215 additions & 0 deletions lua/wikis/counterstrike/VRSStandings.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
---
-- @Liquipedia
-- page=Module:Widget/VRSStandings.lua
Comment thread
MischiefCS marked this conversation as resolved.
Outdated
--
-- Please see https://github.com/Liquipedia/Lua-Modules to contribute
--

local Lua = require('Module:Lua')

local Array = Lua.import('Module:Array')
local Class = Lua.import('Module:Class')
local Date = Lua.import('Module:Date/Ext')
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 Opponent = Lua.import('Module:Opponent')
local PlayerDisplay = Lua.import('Module:Player/Display')
local OpponentDisplay = Lua.import('Module:OpponentDisplay')
Comment thread
MischiefCS marked this conversation as resolved.
Outdated
local Table = Lua.import('Module:Table')

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

local Condition = Lua.import('Module:Condition')
local BooleanOperator = Condition.BooleanOperator
local Comparator = Condition.Comparator


local DATAPOINT_TYPE = 'vrs_ranking'

---@class VRSStandings: Widget
---@operator call(table): VRSStandings
---@field props table<string|number, string>
local VRSStandings = Class.new(Widget)
VRSStandings.defaultProps = {
title = 'VRS Standings',
}

---@return Widget?
function VRSStandings:render()
Comment thread
mbergen marked this conversation as resolved.
Outdated
local standings, settings = self:_parse()

local headerRow = TableWidgets.TableHeader{children = {
TableWidgets.Row{children = WidgetUtil.collect(
TableWidgets.CellHeader{children = 'Rank'},
TableWidgets.CellHeader{children = 'Points'},
TableWidgets.CellHeader{children = 'Team'},
TableWidgets.CellHeader{children = 'Roster'}
)}
}}

local title = HtmlWidgets.Div {
children = {
HtmlWidgets.Div {
children = {
HtmlWidgets.B { children = 'Unofficial VRS' },
HtmlWidgets.Span { children = 'Last updated: ' .. settings.updated }
},
classes = { 'ranking-table__top-row-text' }
},
HtmlWidgets.Div {
children = {
HtmlWidgets.Span { children = 'Data by Liquipedia' },
},
classes = { 'ranking-table__top-row-logo-container' }
}
},
classes = { 'ranking-table__top-row' },
}

return TableWidgets.Table{
title = title,
sortable = false,
columns = WidgetUtil.collect(
{
align = 'right',
sortType = 'number'
},
{
align = 'right',
sortType = 'number',
},
{
align = 'left'
},
{
align = 'left'
}
),
children = {
headerRow,
TableWidgets.TableBody{children = Array.map(standings, VRSStandings._row)}
},
}
end

---@private
---@return {place: number, points: number, opponent: standardOpponent}[]
---@return {title: string, updated: string, shouldStore: boolean, shouldFetch: boolean}
function VRSStandings:_parse()
local props = self.props
local settings = {
title = props.title,
updated = Date.toYmdInUtc(Date.parseIsoDate(props.updated) or os.date('%F')),
Comment thread
mbergen marked this conversation as resolved.
Outdated
shouldFetch = Logic.readBool(props.shouldFetch),
fetchLimit = tonumber(props.fetchLimit)
}

---@type {points: number, opponent: standardOpponent}[]
Comment thread
MischiefCS marked this conversation as resolved.
Outdated
local standings = {}

if settings.shouldFetch then
standings = self._fetch(settings.updated, settings.fetchLimit)
else
Table.iter.forEachPair(self.props, function(key, value)
if not string.match(key, '^%d+$') then
return
end

local data = Json.parse(value)
local opponent = Opponent.readOpponentArgs(Table.merge(data, {
type = Opponent.team,
}))

-- Remove template from data to not confuse it with first player
data[1] = nil
opponent.players = Array.map(Array.range(1, 5), FnUtil.curry(Opponent.readPlayerArgs, data))

table.insert(standings, {
place = tonumber(key),
points = tonumber(data.points),
opponent = opponent
})
end)

self._store(settings.updated, standings)
end

Array.sortInPlaceBy(standings, Operator.property('place'))

return standings, settings
end

---@private
---@param standing {place: number, points: number, opponent: standardOpponent}
---@return Widget
function VRSStandings._row(standing)
return TableWidgets.Row{children = WidgetUtil.collect(
TableWidgets.Cell{
children = standing.place,
},
TableWidgets.Cell{
children = MathUtil.formatRounded{value = standing.points, precision = 1}
},
TableWidgets.Cell{
children = OpponentDisplay.InlineTeamContainer{
template = standing.opponent.template
}
},
TableWidgets.Cell{
children = Array.map(standing.opponent.players, function(player)
return HtmlWidgets.Span{
css = {
display = "inline-block",
width = "160px"
},
children = PlayerDisplay.InlinePlayer({player = player})
}
end),
}
)}
end

---@private
---@param updated string
---@param standings {place: number, points: number, opponent: standardOpponent}[]
function VRSStandings._store(updated, standings)
if Lpdb.isStorageDisabled() then
return
end
local dataPoint = Lpdb.DataPoint:new{
objectname = 'vrs_' .. updated,
type = DATAPOINT_TYPE,
name = 'Inofficial VRS (' .. updated .. ')',
Comment thread
MischiefCS marked this conversation as resolved.
Outdated
date = updated,
extradata = standings
}
dataPoint:save()
end

---@private
---@param updated string
---@param fetchLimit integer
---@return {place: number, points: number, opponent: standardOpponent}[]
function VRSStandings._fetch(updated, fetchLimit)
local data = mw.ext.LiquipediaDB.lpdb('datapoint', {
conditions = Condition.Tree(BooleanOperator.all):add{
Condition.Node(Condition.ColumnName('type'), Comparator.eq, DATAPOINT_TYPE),
Condition.Node(Condition.ColumnName('date'), Comparator.eq, updated),
Condition.Node(Condition.ColumnName('namespace'), Comparator.eq, 2), -- TODO: Remove before release
Comment thread
mbergen marked this conversation as resolved.
Outdated
}:toString(),
query = 'extradata',
Comment thread
MischiefCS marked this conversation as resolved.
Outdated
limit = 1,
})

assert(data[1], 'No VRS data found')
return Array.sub(data[1].extradata, 1, fetchLimit)
end

return VRSStandings
Loading