Tournament Engine
Relevant source files
The following files were used as context for generating this wiki page:
The Tournament Engine is the core state management system for handling poker tournaments. It is implemented as a singleton class, TournamentEngine, responsible for the entire lifecycle of a tournament, from creation and player registration to blind level progression, table management, and prize distribution. The engine is designed to be decoupled from the UI, with its state and methods exposed to React components through the useTournament hook and TournamentProvider.
This system manages various tournament types, including regular, turbo, heads-up, and bounty tournaments, each with configurable structures. It handles all logical operations such as creating tables, balancing players across tables as they are eliminated, advancing blind levels on a timer, and determining the final winner.
Sources: lib/tournament-engine.ts, hooks/use-tournament.tsx, components/tournament-lobby.tsx:28-91
Architecture
The engine's architecture is centered around the TournamentEngine singleton, which ensures a single instance manages all tournament states. A React Context, TournamentProvider, holds the state of the currently active tournament and provides it to the component tree. The useTournament hook is the primary interface for UI components to interact with the tournament engine's state and methods.
Sources: lib/tournament-engine.ts:7-13, hooks/use-tournament.tsx:16-20
This diagram illustrates the architectural flow from the singleton engine to the UI components.
Core Data Structures
The engine relies on a set of well-defined types to manage tournament state. These are defined in types/tournament.ts.
Sources: types/tournament.ts
Data Model ER Diagram
The following diagram shows the relationships between the main data structures.
Sources: types/tournament.ts:1-80
TournamentConfig
This interface defines the static configuration for a tournament. It is set once upon creation.
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier for the tournament. |
name | string | Display name of the tournament. |
buyIn | number | Cost to enter the tournament (contributes to prize pool). |
entryFee | number | Additional fee for the tournament. |
startingChips | number | The number of chips each player starts with. |
maxPlayers | number | Maximum number of players allowed. |
minPlayers | number | Minimum players required to start. |
playersPerTable | number | The number of players seated at each table. |
blindStructure | BlindLevel[] | An array defining the blind levels. |
prizePoolPercentages | number[] | Payout structure, e.g., [50, 30, 20]. |
tournamentType | TournamentType | Type of tournament (e.g., regular, turbo, bounty). |
bountyAmount | number | (Optional) Chip value for eliminating a player in bounty tournaments. |
rebuyConfig | RebuyConfig | (Optional) Configuration for rebuys. |
addOnConfig | AddOnConfig | (Optional) Configuration for add-ons. |
Sources: types/tournament.ts:18-35, components/tournament-lobby.tsx:28-91
TournamentState
This interface represents the dynamic state of a running tournament. It is updated throughout the tournament's lifecycle.
| Property | Type | Description |
|---|---|---|
config | TournamentConfig | The tournament's static configuration. |
phase | TournamentPhase | The current phase of the tournament (e.g., registration, running). |
currentBlindLevel | number | Index of the current blind level in the blindStructure array. |
blindLevelTimeRemaining | number | Seconds remaining until the next blind level. |
totalPrizePool | number | The total prize pool, including buy-ins, rebuys, and add-ons. |
registeredPlayers | TournamentPlayer[] | List of all players who have registered. |
tables | TournamentTable[] | The active tables in the tournament. |
remainingPlayers | number | The number of players still in the tournament. |
Sources: types/tournament.ts:56-72
Tournament Lifecycle
A tournament progresses through several distinct phases, managed by the phase property in TournamentState.
This flowchart shows the typical lifecycle of a tournament.
1. Registration
- Phase:
registration - The tournament is created and players can register.
- The
registerPlayermethod adds a player toregisteredPlayers, updatestotalPrizePool, and incrementstotalPlayers. - Registration is blocked if the tournament is full or has already started.
Sources: lib/tournament-engine.ts:124-153
2. Start Tournament
- Phase:
running - Triggered by
startTournamentonceminPlayersis met. - Players are shuffled and assigned to tables via
createTablesAndAssignPlayers. - The blind timer starts.
Sources: lib/tournament-engine.ts:156-173
3. Running & Blind Progression
- Phase:
runningorbreak - The
useTournamenthook sets up an interval that callstournamentEngine.updateTimerevery second. updateTimerdecrementsblindLevelTimeRemaining. When it reaches zero,advanceBlindLevelis called.advanceBlindLevelincrementscurrentBlindLevel, resets the timer, and handles transitions into and out of break periods.
Sources: hooks/use-tournament.tsx:23-35, lib/tournament-engine.ts:622-642, lib/tournament-engine.ts:282-323
4. Player Elimination & Table Management
- When a player is eliminated,
eliminatePlayeris called. - This method marks the player as eliminated, removes them from their table, and decrements
remainingPlayers. - After an elimination,
balanceTablesis called to ensure tables have a roughly equal number of players. If necessary, it will consolidate players onto fewer tables. - When the number of remaining players is less than or equal to
playersPerTable,createFinalTableis called.
Sources: lib/tournament-engine.ts:430-478, lib/tournament-engine.ts:481-522
5. Completion
- Phase:
completed - When
remainingPlayersbecomes 1,completeTournamentis called. - The final player is declared the winner.
- Prizes are calculated based on
prizePoolPercentagesand assigned to the top-finishing players.
Sources: lib/tournament-engine.ts:592-616
Core Engine Methods
The TournamentEngine class provides several methods to manage the tournament state.
| Method | Description | Source File |
|---|---|---|
createTournament(config) | Initializes a new tournament with the given configuration and adds it to the internal map. | lib/tournament-engine.ts:100-121 |
registerPlayer(id, name) | Registers a new player for a tournament during the registration phase. | lib/tournament-engine.ts:124-153 |
startTournament(id) | Starts the tournament, creates tables, and assigns players. | lib/tournament-engine.ts:156-173 |
eliminatePlayer(id, eliminatorId?) | Marks a player as eliminated, handles bounties, and triggers table balancing. | lib/tournament-engine.ts:430-478 |
advanceBlindLevel(id) | Moves the tournament to the next blind level or break period. | lib/tournament-engine.ts:282-323 |
updateTimer(id, delta) | Decrements the blind/break timer and triggers level advancement when time is up. | lib/tournament-engine.ts:622-642 |
balanceTables(tournament) | Moves players between tables to keep player counts even. | lib/tournament-engine.ts:481-522 |
completeTournament(tournament) | Finalizes the tournament, identifies the winner, and calculates prize distribution. | lib/tournament-engine.ts:592-616 |
processRebuy(id, playerId) | Processes a rebuy for a player if the tournament configuration allows it. | lib/tournament-engine.ts:325-364 |
processAddOn(id, playerId) | Processes an add-on for a player during the designated add-on break. | lib/tournament-engine.ts:366-403 |
Blind Structures
The engine provides static methods to generate different blind structures based on the tournament type. These structures define the progression of blinds, antes, and level durations.
Sources: lib/tournament-engine.ts:15-98
Example: Default Blind Structure
// lib/tournament-engine.ts:15-40
static getDefaultBlindStructure(): BlindLevel[] {
return [
{ level: 1, smallBlind: 25, bigBlind: 50, ante: 0, duration: 600 }, // 10 min
{ level: 2, smallBlind: 50, bigBlind: 100, ante: 0, duration: 600 },
{ level: 3, smallBlind: 75, bigBlind: 150, ante: 25, duration: 600 },
// ... more levels
{ level: 5, smallBlind: 0, bigBlind: 0, duration: 900, isBreak: true, breakDuration: 900 }, // 15-min break
// ... more levels
]
}
The engine also defines getTurboBlindStructure (5-minute levels) and getHeadsUpBlindStructure (5-minute levels, smaller increments). These are used in the TournamentLobby component to configure new tournaments.
Sources: lib/tournament-engine.ts:42-98, components/tournament-lobby.tsx:37, 50, 63
UI Integration via useTournament Hook
The useTournament hook is the bridge between the React UI and the TournamentEngine. It provides components with the current tournament state and functions to dispatch actions.
Player Registration Flow
This sequence diagram shows how a player registers for a tournament from the TournamentLobby.
Displaying Live Data
Components like TournamentTableInfo and TournamentStructure use the useTournament hook to get live data and display it to the user.
TournamentTableInfodisplays the current blinds, time until the next level, and remaining players.TournamentStructureshows the full blind schedule and highlights the current level.
Sources: components/tournament-table-info.tsx:8-10, components/tournament-structure.tsx:11
Conclusion
The Tournament Engine is a robust and well-structured module that serves as the backbone for all tournament-style gameplay. Its singleton design ensures a centralized and consistent state, while the separation of logic from the UI via the useTournament hook promotes clean, maintainable code. The engine's flexibility in handling different tournament configurations, blind structures, and lifecycle events makes it a critical and powerful component of the application.