Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
e7d24a7
add dates
Eetwalt May 5, 2026
8b6b113
add tests
Eetwalt May 5, 2026
0d878b7
include tournament start and end date
Eetwalt May 5, 2026
cd844db
update order of former and inactive
Eetwalt May 6, 2026
084bc2e
clean up
Eetwalt May 6, 2026
f5bf37f
fix query
Eetwalt May 6, 2026
66ea5ad
chore: update visual snapshots
Eetwalt May 6, 2026
f20c294
batch queries
Eetwalt May 6, 2026
d560c35
sure
Eetwalt May 6, 2026
5db32e0
Merge branch 'main' into tp-dates
Eetwalt May 11, 2026
3a6b98b
move test to main spec
Eetwalt May 11, 2026
ab307c0
specs v2
Eetwalt May 7, 2026
cb6d710
revised spec
Eetwalt May 8, 2026
0ee2b87
small tweaks
Eetwalt May 8, 2026
36e3cc4
chore: update visual snapshots
Eetwalt May 8, 2026
baadc76
scaffold teamcard legacy wrapper
Eetwalt May 11, 2026
71cd863
parse qualifier for teamcard legacy
Eetwalt May 11, 2026
98b171c
mapPlayer basic field mapping
Eetwalt May 11, 2026
6565e7e
mapPlayer status, dnp, trophies, dates
Eetwalt May 11, 2026
bca3c92
source group status and default-dnp rules
Eetwalt May 11, 2026
52a626f
mapCoach with role default, type=staff, status
Eetwalt May 11, 2026
310c612
enumerate players and coaches with tN tabs and dedup
Eetwalt May 11, 2026
af05e52
mapCard combines team identity, qualifier, notes, players
Eetwalt May 11, 2026
429e803
fold toggle entries
Eetwalt May 11, 2026
ff06b69
partition stash entries and surface malformed structure
Eetwalt May 11, 2026
6a38663
assemble TP args and render via controller pipeline
Eetwalt May 11, 2026
49aeebf
confirm preprocessCard hook test
Eetwalt May 11, 2026
0b23377
integration golden test for teamcard legacy
Eetwalt May 11, 2026
1347e7b
fix integration golden test with contenders card
Eetwalt May 11, 2026
a583c87
cover remaining spec gaps and groupings test
Eetwalt May 11, 2026
383d84c
remove unused imports from TeamCard/Legacy
Eetwalt May 11, 2026
e9a40ac
annotate private helpers in TeamCard/Legacy
Eetwalt May 11, 2026
87ef527
use Logic.isEmpty in TeamCard/Legacy normalizeKey
Eetwalt May 11, 2026
db86147
share explicit played/result read in TeamCard/Legacy mapPlayer
Eetwalt May 11, 2026
f2e653b
render TeamCard/Legacy notes via HtmlWidgets
Eetwalt May 11, 2026
1a1400f
retab TeamCard/Legacy to match commons convention
Eetwalt May 11, 2026
363e386
drop teamcard legacy design doc
Eetwalt May 11, 2026
f60f3df
chore: update visual snapshots
Eetwalt May 11, 2026
0bed8a2
remove test
Eetwalt May 12, 2026
4f18c40
extract fromargs from fromtemplate to reduce duplication
Eetwalt May 12, 2026
4455663
no formerdnpdefault
Eetwalt May 12, 2026
e027f8f
unused
Eetwalt May 12, 2026
960fd8a
line too long
Eetwalt May 12, 2026
bd0925a
duplicate tbd template
Eetwalt May 12, 2026
4299244
call fromTemplate directly and correct annotation
Eetwalt May 12, 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
15 changes: 15 additions & 0 deletions lua/definitions/mw.lua
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,21 @@ function mw.language:formatDate(format, timestamp, localTime)
return day or ''
end
return os.date(outFormat, ostimeWrapper(timestamp)) --[[@as string]]
elseif format == 'Y-m-d' then
if not timestamp then
return os.date('!%Y-%m-%d') --[[@as string]]
end
if type(timestamp) == 'string' and string.sub(timestamp, 1, 1) == '@' then
local seconds = tonumber(string.sub(timestamp, 2))
if not seconds then return '' end
return os.date('!%Y-%m-%d', seconds) --[[@as string]]
end
if type(timestamp) == 'string' then
local year, month, day = parseDateString(timestamp)
if not year then return '' end
return year .. '-' .. month .. '-' .. day
end
return os.date('!%Y-%m-%d', ostimeWrapper(timestamp)) --[[@as string]]
end
return ''
end
Expand Down
Binary file modified lua/spec/snapshots/dota2 rankings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added lua/spec/snapshots/teamcard_legacy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
335 changes: 335 additions & 0 deletions lua/spec/team_participant_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -635,5 +635,340 @@ describe('Team Participant', function()

end)

describe('TeamParticipants player dates', function()
local TeamParticipantsRepository
local Variables
local PageVariableNamespace
local LpdbQuery

before_each(function()
Variables = require('Module:Variables')
Variables.varDefine('tournament_startdate', '2024-01-01')
Variables.varDefine('tournament_enddate', '2024-12-31')
PageVariableNamespace = require('Module:PageVariableNamespace')
TeamParticipantsRepository = require('Module:TeamParticipants/Repository')
LpdbQuery = stub(mw.ext.LiquipediaDB, 'lpdb', function() return {} end)
end)

after_each(function()
LpdbQuery:revert()
Variables.varDefine('tournament_startdate')
Variables.varDefine('tournament_enddate')
end)

describe('getPlayersDates', function()
it('skips players with no pageName or TBD without querying', function()
local result = TeamParticipantsRepository.getPlayersDates(
{
{pageName = nil, extradata = {}},
{pageName = 'TBD', extradata = {}},
},
{'Team Liquid'}
)
assert.are_same({}, result)
assert.stub(LpdbQuery).called(0)
end)

it('returns explicit dates without querying LPDB when both are set for all players', function()
local result = TeamParticipantsRepository.getPlayersDates(
{
{pageName = 'Alexis', extradata = {joinDate = '2024-03-01', leaveDate = '2024-09-01'}},
},
{'Team Liquid'}
)
assert.are_equal('2024-03-01', result['Alexis'].joinDate)
assert.are_equal('2024-09-01', result['Alexis'].leaveDate)
assert.stub(LpdbQuery).called(0)
end)

it('fetches joinDate from active transfer for active player', function()
LpdbQuery:revert()
LpdbQuery = stub(mw.ext.LiquipediaDB, 'lpdb', function()
return {{date = '2024-03-15', player = 'Alexis'}}
end)

local result = TeamParticipantsRepository.getPlayersDates(
{{pageName = 'Alexis', extradata = {}}},
{'Team Liquid'}
)
assert.are_equal('2024-03-15', result['Alexis'].joinDate)
assert.is_nil(result['Alexis'].leaveDate)
end)

it('falls back to activeAlt when active query returns nothing', function()
local callCount = 0
LpdbQuery:revert()
LpdbQuery = stub(mw.ext.LiquipediaDB, 'lpdb', function()
callCount = callCount + 1
if callCount == 2 then
return {{date = '2024-04-01', player = 'Alexis'}}
end
return {}
end)

local result = TeamParticipantsRepository.getPlayersDates(
{{pageName = 'Alexis', extradata = {}}},
{'Team Liquid'}
)
assert.are_equal('2024-04-01', result['Alexis'].joinDate)
assert.are_equal(2, callCount)
end)

it('fetches joinDate and leaveDate for former player', function()
local callCount = 0
LpdbQuery:revert()
LpdbQuery = stub(mw.ext.LiquipediaDB, 'lpdb', function()
callCount = callCount + 1
if callCount == 1 then
return {{date = '2024-02-01', player = 'Alexis'}} -- active → joinDate
elseif callCount == 3 then
return {{date = '2024-08-15', player = 'Alexis'}} -- former → leaveDate
end
return {}
end)

local result = TeamParticipantsRepository.getPlayersDates(
{{pageName = 'Alexis', extradata = {status = 'former'}}},
{'Team Liquid'}
)
assert.are_equal('2024-02-01', result['Alexis'].joinDate)
assert.are_equal('2024-08-15', result['Alexis'].leaveDate)
end)

it('falls back to inactive query when former returns nothing for former player', function()
local callCount = 0
LpdbQuery:revert()
LpdbQuery = stub(mw.ext.LiquipediaDB, 'lpdb', function()
callCount = callCount + 1
if callCount == 4 then
return {{date = '2024-09-30', player = 'Alexis'}} -- inactive → leaveDate
end
return {}
end)

local result = TeamParticipantsRepository.getPlayersDates(
{{pageName = 'Alexis', extradata = {status = 'former'}}},
{'Team Liquid'}
)
assert.is_nil(result['Alexis'].joinDate)
assert.are_equal('2024-09-30', result['Alexis'].leaveDate)
assert.are_equal(4, callCount) -- active, activeAlt, former, inactive
end)

it('explicit joinDate takes precedence over LPDB result', function()
LpdbQuery:revert()
LpdbQuery = stub(mw.ext.LiquipediaDB, 'lpdb', function()
return {{date = '2024-03-15', player = 'Alexis'}}
end)

local result = TeamParticipantsRepository.getPlayersDates(
{{pageName = 'Alexis', extradata = {joinDate = '2023-01-01'}}},
{'Team Liquid'}
)
assert.are_equal('2023-01-01', result['Alexis'].joinDate)
end)

it('queries against the team-template columns, not display-name columns', function()
local capturedConditions
LpdbQuery:revert()
LpdbQuery = stub(mw.ext.LiquipediaDB, 'lpdb', function(_, options)
capturedConditions = options.conditions
return {}
end)

TeamParticipantsRepository.getPlayersDates(
{{pageName = 'Alexis', extradata = {}}},
{'team liquid'}
)

assert.is_truthy(capturedConditions:find('toteamtemplate', 1, true))
assert.is_truthy(capturedConditions:find('fromteamtemplate', 1, true))
assert.is_nil(capturedConditions:find('[[toteam::', 1, true))
assert.is_nil(capturedConditions:find('[[fromteam::', 1, true))
end)

it('batches multiple players into a single query per status', function()
local callCount = 0
local capturedConditions = {}
LpdbQuery:revert()
LpdbQuery = stub(mw.ext.LiquipediaDB, 'lpdb', function(_, options)
callCount = callCount + 1
table.insert(capturedConditions, options.conditions)
if callCount == 1 then
return {{date = '2024-03-15', player = 'Alexis'}}
elseif callCount == 2 then
return {{date = '2024-04-20', player = 'Bob'}}
end
return {}
end)

local result = TeamParticipantsRepository.getPlayersDates(
{
{pageName = 'Alexis', extradata = {}},
{pageName = 'Bob', extradata = {}},
},
{'Team Liquid'}
)

assert.are_equal('2024-03-15', result['Alexis'].joinDate)
assert.are_equal('2024-04-20', result['Bob'].joinDate)
-- 2 queries total (active + activeAlt) for 2 players, not 4 (one per player per status)
assert.are_equal(2, callCount)
assert.is_truthy(capturedConditions[1]:find('Alexis', 1, true))
assert.is_truthy(capturedConditions[1]:find('Bob', 1, true))
-- Second query (activeAlt) should only ask about Bob since Alexis already resolved
assert.is_nil(capturedConditions[2]:find('"Alexis"', 1, true))
assert.is_truthy(capturedConditions[2]:find('Bob', 1, true))
end)

it('picks the latest transfer per player when multiple rows are returned', function()
LpdbQuery:revert()
LpdbQuery = stub(mw.ext.LiquipediaDB, 'lpdb', function()
return {
{date = '2024-05-01', player = 'Alexis'},
{date = '2024-03-01', player = 'Alexis'},
{date = '2024-04-01', player = 'Bob'},
}
end)

local result = TeamParticipantsRepository.getPlayersDates(
{
{pageName = 'Alexis', extradata = {}},
{pageName = 'Bob', extradata = {}},
},
{'Team Liquid'}
)
assert.are_equal('2024-05-01', result['Alexis'].joinDate)
assert.are_equal('2024-04-01', result['Bob'].joinDate)
end)

it('matches transfers under either underscore or space variant of the page name', function()
LpdbQuery:revert()
LpdbQuery = stub(mw.ext.LiquipediaDB, 'lpdb', function()
return {{date = '2024-06-01', player = 'Some Player'}}
end)

local result = TeamParticipantsRepository.getPlayersDates(
{{pageName = 'Some_Player', extradata = {}}},
{'Team Liquid'}
)
assert.are_equal('2024-06-01', result['Some_Player'].joinDate)
end)

it('only queries former/inactive for players whose status is former', function()
local capturedConditions = {}
LpdbQuery:revert()
LpdbQuery = stub(mw.ext.LiquipediaDB, 'lpdb', function(_, options)
table.insert(capturedConditions, options.conditions)
return {}
end)

TeamParticipantsRepository.getPlayersDates(
{
{pageName = 'Active', extradata = {}},
{pageName = 'Former', extradata = {status = 'former'}},
},
{'Team Liquid'}
)

-- 4 calls total: active, activeAlt (both players), former, inactive (only former player)
assert.are_equal(4, #capturedConditions)
assert.is_truthy(capturedConditions[1]:find('Active', 1, true))
assert.is_truthy(capturedConditions[1]:find('Former', 1, true))
-- Latter two queries should only mention 'Former'
assert.is_nil(capturedConditions[3]:find('"Active"', 1, true))
assert.is_truthy(capturedConditions[3]:find('Former', 1, true))
end)
end)

describe('setPageVars', function()
it('writes joindate and leavedate to global vars under team prefixes', function()
local TeamTemplateMock = require('wikis.commons.Mock.TeamTemplate')
TeamTemplateMock.setUp()
local globalVars = PageVariableNamespace()

TeamParticipantsRepository.setPageVars({
aliases = {'team liquid'},
opponent = {
players = {{
pageName = 'Alexis',
flag = 'us',
displayName = 'alexis',
faction = nil,
apiId = nil,
extradata = {
type = 'player',
joinDate = '2024-03-15',
leaveDate = nil,
},
}},
},
})

assert.are_equal('2024-03-15', globalVars:get('Team Liquid_p1joindate'))
assert.is_nil(globalVars:get('Team Liquid_p1leavedate'))
TeamTemplateMock.tearDown()
end)

it('writes both joindate and leavedate for former player', function()
local TeamTemplateMock = require('wikis.commons.Mock.TeamTemplate')
TeamTemplateMock.setUp()
local globalVars = PageVariableNamespace()

TeamParticipantsRepository.setPageVars({
aliases = {'team liquid'},
opponent = {
players = {{
pageName = 'Alexis',
flag = 'us',
displayName = 'alexis',
faction = nil,
apiId = nil,
extradata = {
type = 'player',
status = 'former',
joinDate = '2024-02-01',
leaveDate = '2024-08-15',
},
}},
},
})

assert.are_equal('2024-02-01', globalVars:get('Team Liquid_p1joindate'))
assert.are_equal('2024-08-15', globalVars:get('Team Liquid_p1leavedate'))
TeamTemplateMock.tearDown()
end)
end)

describe('parsePlayer date input', function()
it('stores explicit joindate from wiki input in extradata', function()
local TeamParticipantsWikiParser = require('Module:TeamParticipants/Parse/Wiki')
local player = TeamParticipantsWikiParser.parsePlayer{'Alexis', joindate = '2024-03-01'}
assert.are_equal('2024-03-01', player.extradata.joinDate)
assert.is_nil(player.extradata.leaveDate)
end)

it('stores explicit leavedate from wiki input in extradata', function()
local TeamParticipantsWikiParser = require('Module:TeamParticipants/Parse/Wiki')
local player = TeamParticipantsWikiParser.parsePlayer{'Alexis', leavedate = '2024-09-01'}
assert.is_nil(player.extradata.joinDate)
assert.are_equal('2024-09-01', player.extradata.leaveDate)
end)

it('stores nothing for missing date input', function()
local TeamParticipantsWikiParser = require('Module:TeamParticipants/Parse/Wiki')
local player = TeamParticipantsWikiParser.parsePlayer{'Alexis'}
assert.is_nil(player.extradata.joinDate)
assert.is_nil(player.extradata.leaveDate)
end)

it('treats empty string date input as nil', function()
local TeamParticipantsWikiParser = require('Module:TeamParticipants/Parse/Wiki')
local player = TeamParticipantsWikiParser.parsePlayer{'Alexis', joindate = ''}
assert.is_nil(player.extradata.joinDate)
end)
end)
end)


end)
Loading
Loading