MatchZy Auto Tournament - Architecture¶
Bracket Generation System¶
Overview¶
The bracket generation system uses a unified interface pattern that makes it easy to add new tournament types. All generators implement the IBracketGenerator interface.
Structure¶
src/services/
├── bracketGenerators/
│ ├── index.ts # Central registry mapping tournament types to generators
│ └── types.ts # IBracketGenerator interface definition
├── swissBracketGenerator.ts # Custom Swiss system implementation
├── standardBracketGenerator.ts # Single/Double elimination & Round Robin (via brackets-manager library)
└── matchConfigBuilder.ts # Builds individual match configs (used by all generators)
How It Works¶
Technical Implementation Details
1. Interface (bracketGenerators/types.ts)
interface IBracketGenerator {
generate(tournament, getMatchesCallback): Promise<BracketMatch[] | BracketGeneratorResult>;
reset?(): void; // Optional state reset
}
2. Registry (bracketGenerators/index.ts)
Maps tournament types to their generators:
const bracketGenerators: Record<TournamentType, IBracketGenerator> = {
single_elimination: standardBracketGenerator,
double_elimination: standardBracketGenerator,
round_robin: standardBracketGenerator,
swiss: swissBracketGenerator,
};
3. Usage (tournamentService.ts)
Adding New Tournament Types¶
To add a new tournament type (e.g., group_stage):
- Create the generator (implements
IBracketGenerator):
// src/services/groupStageBracketGenerator.ts
export class GroupStageBracketGenerator implements IBracketGenerator {
async generate(tournament, getMatchesCallback) {
// Your custom logic here
}
}
export const groupStageBracketGenerator = new GroupStageBracketGenerator();
- Add to type definition:
// src/types/tournament.types.ts
export type TournamentType =
| 'single_elimination'
| 'double_elimination'
| 'round_robin'
| 'swiss'
| 'group_stage'; // Add here
- Register in the registry:
// src/services/bracketGenerators/index.ts
import { groupStageBracketGenerator } from '../groupStageBracketGenerator';
export const bracketGenerators: Record<TournamentType, IBracketGenerator> = {
// ... existing
group_stage: groupStageBracketGenerator,
};
That's it! The system will automatically use your generator when a tournament of that type is created.
Current Generators¶
Standard Bracket Generator¶
- File:
standardBracketGenerator.ts - Handles:
single_elimination,double_elimination,round_robin - Implementation: Wraps the
brackets-managerlibrary - Stateful: Yes (uses in-memory storage, needs reset)
Swiss Bracket Generator¶
- File:
swissBracketGenerator.ts - Handles:
swiss - Implementation: Custom pairing algorithm
- Stateful: No (direct DB operations)
Match Config Builder¶
File: matchConfigBuilder.ts
This is not a bracket generator - it builds individual match configurations:
- Team data
- Veto state
- Map selection
- Player counts
- Side selections
All bracket generators use this to create match configs.
Benefits of This Architecture¶
- Extensible: Add new tournament types without modifying existing code
- Type-safe: TypeScript ensures all generators implement the interface correctly
- Maintainable: Each generator is isolated in its own file
- Clear separation: Generator logic vs match config logic
- Easy to test: Mock the interface for unit tests
File Naming Convention¶
*BracketGenerator.ts- Generates bracket structurematchConfigBuilder.ts- Builds individual match configsbracketGenerators/- Interface and registry
Frontend Bracket Viewer¶
The React client ships with a vendored copy of brackets-viewer.js located at client/src/brackets-viewer/. We maintain a fork because the stock package does not yet expose the behaviours we rely on:
- Extended metadata ingestion (seed positions,
nextMatchIdwiring, parent match hints) - Reactive theming hooks to map into the Material UI design system
- Smooth
zoomToElementfocus when opening our match modal - Small UX tweaks (separated BoX labels, hover states, popover styling)
When updating to a newer upstream release:
- Pull the new source from the upstream repository.
- Re-run the build script from the upstream project to regenerate assets (SCSS → CSS, TypeScript → JS).
- Copy the distribution files back into
client/src/brackets-viewer/. - Re-apply local adjustments (search for
// MatchZycomments) and runnpm run lint. - Validate the bracket view for single elimination, double elimination, losers bracket transfers, and Swiss layouts.
Keeping the fork checked in ensures deterministic builds and avoids shipping multiple runtime bundles.