4.8 KiB
game-server — matchmaking spec delta (Wave B-5a)
ADDED Requirements
Requirement: QueueManager primary-priority queue
QueueManager SHALL maintain an in-memory priority queue keyed by an
arbitrary string (typically a game mode or queue type) and prioritise
entries by a documented mix of premium bonus, wait-time bonus, and an
optional caller-supplied base offset.
Scenario: addToQueue accepts a valid request
- WHEN a caller invokes
addToQueue("ranked", {...validRequest}) - THEN the request is inserted into the queue and the queue's size grows by one
- AND the
game_server.matchmaking.queue_enqueue_totalcounter is incremented
Scenario: addToQueue rejects when the queue is at capacity
- GIVEN a
QueueManagerconfigured withmaxQueueSize: 1 - AND one request has been accepted
- WHEN a second request is submitted
- THEN
addToQueuethrowsGameServerError(GAME_SERVER.MATCHMAKING_QUEUE_FULL) - AND the
game_server.matchmaking.queue_reject_total{reason=full}counter is incremented
Scenario: findMatch atomically pops the top N entries
- GIVEN three queued players
- WHEN the caller invokes
findMatch("ranked", 2) - THEN the top two entries (by priority) are returned in order
- AND the queue's size shrinks by two
- AND the wait-time histogram is sampled twice
Requirement: SkillMatcher Elo-style closest-rating selection
SkillMatcher SHALL select the candidate closest in rating to the
seeker, widening the acceptance band proportional to the seeker's
waiting time and respecting a configurable hard ceiling.
Scenario: closest opponent is returned
- GIVEN a seeker rated 1500 and candidates rated 1400, 1510, 1700
- AND the configured
ratingRangeis 500 - WHEN the caller invokes
findMatch(seeker, candidates) - THEN the matcher returns the 1510-rated candidate
Scenario: rejection on a non-finite rating
- WHEN the caller submits a
SkillEntrywhose rating isNaN - THEN
findMatchthrowsGameServerError(GAME_SERVER.INVALID_SKILL_SCORE)
Requirement: SpectatorManager per-session cap
SpectatorManager SHALL enforce a configurable per-session spectator
cap and surface typed-error rejections on cap violation or duplicate
spectator registration.
Scenario: cap rejection
- GIVEN a
SpectatorManagerconfigured withmaxSpectatorsPerSession: 1 - AND one spectator has been added to session "s1"
- WHEN a second spectator is added to the same session
- THEN
addSpectatorthrowsGameServerError(GAME_SERVER.SPECTATOR_LIMIT_REACHED)
Scenario: duplicate spectator rejection
- GIVEN a spectator "alice" already attached to session "s1"
- WHEN
addSpectator("s1", "alice", perms)is invoked again - THEN the call throws
GameServerError(GAME_SERVER.INVALID_SPECTATOR_REQUEST)
Requirement: WinnerStaysOnManager streak tracking
WinnerStaysOnManager SHALL track the current champion, their
consecutive win streak, and a FIFO challenger queue, and expose an
isChampionRotationDue flag once the streak meets maxWinStreak.
Scenario: throne transfer
- GIVEN "alice" recorded as winner against "bob"
- WHEN the manager records "bob" as winner against "alice"
- THEN the champion becomes "bob" with
winStreak === 1 - AND "alice" is enqueued at the back of the challenger list
Requirement: MatchmakingEngine façade
MatchmakingEngine SHALL expose createMatch(players, criteria, algorithm) and createMatchFromQueue(queueKey, criteria, algorithm)
that pick the algorithm, validate inputs via Zod, mint a stable
matchId via an injected IdGenerator, and notify any registered
onMatchFound listener.
Scenario: quick algorithm matches FIFO
- GIVEN three queued players and
MatchCriteriaof{ minPlayers: 2, maxPlayers: 4 } - WHEN
createMatch(players, criteria, "quick")is invoked - THEN the engine returns a
Matchcontaining all three players
Scenario: skill-based algorithm uses the largest viable group
- GIVEN four players with ratings 1000, 1100, 1200, 2500
- AND
MatchCriteriaof{ minPlayers: 2, maxPlayers: 4, skillRange: 250 } - WHEN
createMatch(players, criteria, "skill-based")is invoked - THEN the engine returns the three rated 1000/1100/1200
Scenario: unknown algorithm rejection
- WHEN the caller passes
algorithm: "nuke" - THEN
createMatchthrowsGameServerError(GAME_SERVER.UNKNOWN_MATCHING_ALGORITHM)
Scenario: createMatchFromQueue restores on shortfall
- GIVEN a
QueueManagerwith one queued player andMatchCriteriaof{ minPlayers: 2, maxPlayers: 4 } - WHEN
createMatchFromQueue("ranked", criteria)is invoked - THEN the call returns
null - AND the queue's size remains 1