Files
suaveplan/packages/gaming/games/game-server/src/enhanced/tournament/tournament-manager/tournament-standings.internal.md
2026-05-27 23:47:53 +01:00

2.7 KiB

tournament-standings.internal

Purpose

Pure helper utilities for the standings table inside a tournament: applying a win/loss outcome, marking participants eliminated, locating a match by id, and flipping a round to completed. Extracted from tournament-manager.ts to keep that file under the project's 300-line hard limit while preserving full behaviour through the public API.

The helpers are stateless and take their targets by reference so the manager retains exclusive ownership of mutability. They are covered indirectly via the manager's public surface tests rather than directly, which is the standard pattern for .internal.ts modules in this repo.

Features

  • applyStanding — write outcome + resort + re-rank in one call.
  • markEliminated — set eliminated = true by participant id.
  • findMatch — linear scan across rounds (small N).
  • markRoundCompleteIfDone — flip round completion idempotently.

Usage: Basic

import { applyStanding } from "./tournament-standings.internal.js";
applyStanding(standings, winner, loser, 3, 0);

Usage: Advanced

import {
    applyStanding,
    findMatch,
    markEliminated,
    markRoundCompleteIfDone,
} from "./tournament-standings.internal.js";

applyStanding(tournament.standings, winner, loser, winPoints, lossPoints);
markEliminated(tournament.standings, loser.id);
const next = findMatch(tournament.rounds, currentMatch.nextMatchId!);
markRoundCompleteIfDone(tournament.rounds, currentMatch);

API Reference

  • applyStanding(standings, winner, loser, winPoints, lossPoints): void
  • markEliminated(standings, id): void
  • findMatch(rounds, matchId): Match | null
  • markRoundCompleteIfDone(rounds, match): void

Implementation Notes

The standings sort is stable on points first, then wins, then losses ascending — the conventional Swiss-style ordering. Re-sorting after every outcome is O(N log N) per result; for typical bracket sizes (≤ 256 participants) this is well under a millisecond and avoids the bookkeeping complexity of an incremental order-statistic structure.

findMatch is a linear scan across all rounds. Bracket-size rounds grow logarithmically with participant count in single-elimination and linearly in round-robin, so the total match count stays small relative to typical scan budgets. A hot-path id-to-match index would be premature optimisation here and would force the manager to keep two structures in sync.

markRoundCompleteIfDone treats bye and completed as equivalent terminal states so a round consisting entirely of byes is reported as done immediately after start(), which keeps getStats().currentRound advancing through automatic walkovers without manual intervention.