Tournament Generation
The generateTournamentRecord method is the primary tool for creating complete tournament structures for testing. It can generate everything from simple tournaments to complex multi-event, multi-venue competitions.
Basic Syntax
const {
tournamentRecord, // The complete tournament object
eventIds, // Array of generated event IDs
drawIds, // Array of generated draw IDs
venueIds, // Array of generated venue IDs
} = mocksEngine.generateTournamentRecord(options);
Complete Options Reference
interface GenerateTournamentRecordOptions {
// Tournament Properties
startDate?: string; // ISO date string (default: today)
endDate?: string; // ISO date string (default: startDate + 6 days)
tournamentAttributes?: object; // Additional tournament properties
tournamentExtensions?: array; // Extensions to attach to tournament
tournamentId?: string; // Override generated ID
// Convenience
setState?: boolean; // Auto-load into tournamentEngine (default: false)
// Participants
participantsProfile?: {
// See Participant Generation docs
participantsCount?: number; // Default: 32
participantType?: string; // 'INDIVIDUAL', 'PAIR', 'TEAM'
sex?: string; // 'MALE', 'FEMALE'
// ... see participantsProfile section
};
// Draws
drawProfiles?: array; // Array of draw configurations
eventProfiles?: array; // Array of event configurations
// Venues
venueProfiles?: array; // Array of venue configurations
// Scheduling
schedulingProfile?: array; // Scheduling directives
autoSchedule?: boolean; // Auto-schedule using profile
// Match Completion
completeAllMatchUps?: boolean; // Complete all generated matchUps
randomWinningSide?: boolean; // Random winners (default: false = side 1 wins)
matchUpStatusProfile?: object; // Control matchUp status distribution
// IDs
uuids?: array; // Pre-defined UUIDs for entities
// Policies
policyDefinitions?: object; // Attach policy definitions
}
Tournament Properties
In the TODS data model:
- Persons have
sex- A biological attribute (MALE/FEMALE) stored inperson.sex - Events have
gender- A competition category attribute (MALE/FEMALE/MIXED/ANY) stored inevent.gender
Use participantsProfile.sex to generate participants with specific person sex attributes. Use event.gender or drawProfile.gender to categorize the competition.
Basic Properties
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
startDate: '2024-06-01',
endDate: '2024-06-07',
tournamentAttributes: {
tournamentName: 'Summer Championships',
tournamentRank: 'GOLD',
indoorOutdoor: 'OUTDOOR',
},
});
Custom Tournament ID
const tournamentId = 'my-custom-id';
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
tournamentId,
drawProfiles: [{ drawSize: 16 }],
});
console.log(tournamentRecord.tournamentId); // 'my-custom-id'
Auto-Loading with setState
For convenience, automatically load the generated tournament into the engine:
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [{ drawSize: 16 }],
setState: true, // Automatically calls tournamentEngine.setState(tournamentRecord)
});
// Tournament is already loaded - no need to call setState manually
const { matchUps } = tournamentEngine.allTournamentMatchUps();
This is especially useful in test setup where you want to immediately work with the tournament:
beforeEach(() => {
mocksEngine.generateTournamentRecord({
drawProfiles: [{ drawSize: 32 }],
venueProfiles: [{ courtsCount: 8 }],
setState: true, // Ready to use tournamentEngine immediately
});
});
test('can schedule matches', () => {
// tournamentEngine already has the tournament loaded
const { matchUps } = tournamentEngine.allTournamentMatchUps();
// ... test scheduling
});
Tournament Extensions
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
tournamentExtensions: [
{
name: 'customData',
value: { region: 'Southwest', tier: 1 },
},
],
});
Using drawProfiles
Draw profiles define the structure of draws within events. Each profile creates a separate event with a single draw.
Each drawProfile can include its own participantsProfile to generate participants specifically for that draw, overriding or extending the tournament-level participantsProfile. This is useful when you need different participant demographics for different events.
Basic Draw
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{ drawSize: 32 }, // Creates 32-draw single elimination singles event
],
});
Multiple Draws
const { tournamentRecord, drawIds, eventIds } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{ drawSize: 32, eventType: 'SINGLES' },
{ drawSize: 16, eventType: 'DOUBLES' },
{ drawSize: 8, eventType: 'SINGLES', drawType: 'ROUND_ROBIN' },
],
});
console.log(eventIds.length); // 3 events
console.log(drawIds.length); // 3 draws
Draw Types
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{ drawSize: 16, drawType: 'SINGLE_ELIMINATION' }, // Default
{ drawSize: 16, drawType: 'ROUND_ROBIN' },
{ drawSize: 16, drawType: 'COMPASS' },
{ drawSize: 16, drawType: 'FEED_IN_CHAMPIONSHIP' },
{ drawSize: 16, drawType: 'FIRST_MATCH_LOSER_CONSOLATION' },
{ drawSize: 16, drawType: 'ROUND_ROBIN_WITH_PLAYOFF' },
],
});
Event Types
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{ drawSize: 32, eventType: 'SINGLES' }, // Default
{ drawSize: 16, eventType: 'DOUBLES' },
{ drawSize: 4, eventType: 'TEAM' },
],
});
Seeding
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{
drawSize: 32,
seedsCount: 8, // Top 8 participants will be seeded
},
],
});
BYEs
Create draws with fewer participants than positions:
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{
drawSize: 32,
participantsCount: 28, // Creates 4 BYEs
},
],
});
MatchUp Format
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{
drawSize: 16,
matchUpFormat: 'SET3-S:6/TB7',
},
],
});
Unique Participants
Force generation of unique participants for each draw:
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{ drawSize: 16, uniqueParticipants: true },
{ drawSize: 16, uniqueParticipants: true },
],
});
// Each draw will have completely different participants
Draw-Specific Participant Profiles
Each drawProfile can include its own participantsProfile to generate participants with specific demographics:
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{
drawSize: 32,
eventType: 'SINGLES',
gender: 'FEMALE', // Event gender category
participantsProfile: {
sex: 'FEMALE', // Person sex - generates female participants
category: {
categoryName: 'U18',
ageCategoryCode: 'U18',
},
scaleAllParticipants: true, // All get ratings
},
},
{
drawSize: 16,
eventType: 'DOUBLES',
gender: 'MALE', // Event gender category
participantsProfile: {
sex: 'MALE', // Person sex - generates male participants
nationalityCodes: ['USA', 'CAN', 'MEX'], // North American players
},
},
],
});
This creates two separate participant pools - one for each event. Draw-level participantsProfile properties override tournament-level settings:
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
// Tournament-level (applies to all draws by default)
participantsProfile: {
participantsCount: 100,
sex: 'FEMALE',
},
drawProfiles: [
{
drawSize: 32,
// Uses tournament-level participantsProfile (FEMALE)
},
{
drawSize: 16,
participantsProfile: {
sex: 'MALE', // Overrides tournament-level to create MALE participants
},
},
],
});
Preventing Draw Generation
Create events without generating the draw structure:
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{
drawSize: 32,
generate: false, // Creates event with entries, but no draw
},
],
});
Using eventProfiles
Event profiles allow more complex event configurations with multiple draws per event.
Like drawProfile, each eventProfile can include its own participantsProfile to generate participants specifically for that event. This applies to all draws within the event unless a draw overrides it with its own participantsProfile.
Basic Event Profile
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
eventProfiles: [
{
eventName: 'U18 Singles',
eventType: 'SINGLES',
category: { ageCategoryCode: 'U18' },
drawProfiles: [{ drawSize: 32 }],
},
],
});
Draw with Qualifying Structure
In the Tennis Open Data Standards (TODS), qualifying is a stage within a draw, not a separate draw. A drawDefinition describes how participants move between structures (QUALIFYING → MAIN). Use qualifyingProfiles to create qualifying structures within a single draw.
Do NOT create separate draws with stage: 'QUALIFYING' - this violates the TODS structure where draws describe participant progression between stages.
Use qualifyingProfiles to create qualifying structures within a single draw:
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{
drawSize: 32,
drawName: 'Singles Championship',
qualifiersCount: 8, // 8 positions for qualifiers in main draw
qualifyingProfiles: [
{
roundTarget: 1, // Which round of main draw qualifiers enter
structureProfiles: [
{
stageSequence: 1,
drawSize: 16, // 16 players compete for 8 qualifying spots
seedsCount: 4,
},
],
},
],
},
],
});
Multiple Draws in One Event
For truly separate competitions (not qualifying):
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
eventProfiles: [
{
eventName: 'Championships',
eventType: 'SINGLES',
drawProfiles: [
{ drawSize: 32, drawName: 'U18 Draw' },
{ drawSize: 16, drawName: 'U16 Draw' },
],
},
],
});
Event Properties
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
eventProfiles: [
{
eventName: "Women's Doubles",
eventType: 'DOUBLES',
gender: 'FEMALE',
category: {
ageCategoryCode: 'OPEN',
categoryName: 'Open',
},
matchUpFormat: 'SET3-S:6/TB7-F:TB10',
surfaceCategory: 'CLAY',
ballType: 'REGULAR_DUTY',
drawProfiles: [{ drawSize: 16 }],
},
],
});
Event Extensions
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
eventProfiles: [
{
eventName: 'Singles',
eventExtensions: [
{
name: 'prizeMoney',
value: { currency: 'USD', total: 50000 },
},
],
drawProfiles: [{ drawSize: 32 }],
},
],
});
Event-Level Participant Profiles
Each eventProfile can include a participantsProfile that applies to all draws within that event:
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
eventProfiles: [
{
eventName: 'Women\'s Championship',
eventType: 'SINGLES',
gender: 'FEMALE',
// Event-level participantsProfile
participantsProfile: {
sex: 'FEMALE',
participantsCount: 128,
category: {
categoryName: 'Open',
ratingType: 'WTN',
},
scaleAllParticipants: true,
},
drawProfiles: [
{
drawSize: 64,
drawName: 'Singles Championship',
qualifiersCount: 16, // 16 qualifying positions
qualifyingProfiles: [
{
roundTarget: 1,
structureProfiles: [
{
stageSequence: 1,
drawSize: 32, // 32 players compete for 16 spots
seedsCount: 8,
},
],
},
],
},
],
},
],
});
Participant Profile Hierarchy
The participant generation follows this priority order:
- Draw-level
participantsProfile(highest priority) - Event-level
participantsProfile - Tournament-level
participantsProfile(lowest priority)
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
// Tournament-level (default for all)
participantsProfile: {
participantsCount: 200,
nationalityCodes: ['USA', 'CAN'],
},
eventProfiles: [
{
eventName: 'International Singles',
// Event-level (overrides tournament-level for this event)
participantsProfile: {
nationalityCodes: ['GBR', 'FRA', 'ESP'], // Overrides tournament-level
sex: 'FEMALE', // Adds to tournament-level
},
drawProfiles: [
{
drawSize: 32,
// Uses event-level participantsProfile
},
{
drawSize: 16,
// Draw-level (overrides both)
participantsProfile: {
nationalityCodes: ['JPN', 'CHN', 'KOR'], // Asian players only
},
},
],
},
],
});
Event with Playoff Structures
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{
drawSize: 16,
drawType: 'SINGLE_ELIMINATION',
withPlayoffs: {
roundProfiles: [{ 3: 1 }, { 4: 1 }], // Create playoffs from rounds 3 and 4
playoffPositions: [3, 4], // For 3rd/4th place
playoffAttributes: {
'0-3': { name: 'Bronze', abbreviation: 'B' },
'0-4': { name: 'Gold', abbreviation: 'G' },
},
},
},
],
});
Completing MatchUps
Complete All Matches
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [{ drawSize: 16 }],
completeAllMatchUps: true,
randomWinningSide: true, // Random winners, otherwise side 1 always wins
});
Complete Specific Matches
Using outcomes in draw profiles:
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{
drawSize: 16,
outcomes: [
{
roundNumber: 1,
roundPosition: 1,
scoreString: '6-4 6-2',
winningSide: 1,
},
{
roundNumber: 1,
roundPosition: 2,
scoreString: '7-6(3) 3-6 6-3',
winningSide: 2,
},
],
},
],
});
Complete by Draw Positions
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{
drawSize: 16,
outcomes: [
{
drawPositions: [1, 2], // Match between positions 1 and 2
scoreString: '6-4 6-2',
winningSide: 1,
},
],
},
],
});
Match Status Variations
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{
drawSize: 16,
outcomes: [
{ roundNumber: 1, roundPosition: 1, matchUpStatus: 'COMPLETED', winningSide: 1 },
{ roundNumber: 1, roundPosition: 2, matchUpStatus: 'RETIRED', winningSide: 1 },
{ roundNumber: 1, roundPosition: 3, matchUpStatus: 'WALKOVER', winningSide: 2 },
{ roundNumber: 1, roundPosition: 4, matchUpStatus: 'DEFAULTED', winningSide: 1 },
],
},
],
});
Completion Goal
Complete a specific number of matches:
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{
drawSize: 32,
completionGoal: 10, // Complete first 10 matchUps
},
],
});
Match Status Distribution
Control the distribution of match statuses across completed matches:
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [{ drawSize: 16 }],
completeAllMatchUps: true,
matchUpStatusProfile: {
COMPLETED: 80, // 80% completed normally
RETIRED: 10, // 10% retirements
WALKOVER: 5, // 5% walkovers
DEFAULTED: 5, // 5% defaults
},
});
ID Prefixes
Match ID Prefixes
Create readable matchUp IDs for easier debugging:
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{
drawSize: 8,
idPrefix: 'match',
},
],
});
// MatchUp IDs will be: match-1-1, match-1-2, match-1-3, match-1-4
// match-2-1, match-2-2
// match-3-1
Participant ID Prefixes
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
participantsProfile: {
participantsCount: 32,
idPrefix: 'player',
},
drawProfiles: [{ drawSize: 16 }],
});
// Participant IDs will be: player-I-0, player-I-1, etc. (I = Individual)
Policy Definitions
Attach policies to tournaments, events, or specific draws. Like participantsProfile, policies can be scoped at multiple levels.
policyDefinitions can be specified at three levels with the following priority:
- Draw-level (within drawProfile) - highest priority, applies only to that draw
- Event-level (within eventProfile) - applies to all draws in that event
- Tournament-level (root level) - applies to all draws unless overridden
This allows you to specify different policies for different events or draws within the same tournament.
Tournament-Level Policies
Policies applied at the tournament level affect all events and draws:
import POLICY_SCHEDULING_DEFAULT from '@Fixtures/policies/POLICY_SCHEDULING_DEFAULT';
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
policyDefinitions: POLICY_SCHEDULING_DEFAULT,
drawProfiles: [{ drawSize: 16 }],
});
Event-Level Policies
Policies applied to an event affect all draws within that event:
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
eventProfiles: [
{
eventName: 'Singles',
policyDefinitions: {
scoring: {
/* scoring policy */
},
avoidance: {
/* avoidance policy */
},
},
drawProfiles: [{ drawSize: 32 }],
},
],
});
Draw-Level Policies
Policies applied to a specific draw override event and tournament-level policies:
import { POLICY_SEEDING_ITF, POLICY_SEEDING_USTA } from '@Fixtures/policies/seeding';
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
// Tournament-level default
policyDefinitions: POLICY_SEEDING_USTA,
drawProfiles: [
{
drawSize: 32,
drawName: 'Professional Draw',
// Draw-level override
policyDefinitions: POLICY_SEEDING_ITF, // This draw uses ITF seeding
},
{
drawSize: 16,
drawName: 'Amateur Draw',
// Uses tournament-level USTA seeding
},
],
});
Complex Examples
Multi-Event Tournament with Qualifying
const { tournamentRecord, eventIds } = mocksEngine.generateTournamentRecord({
startDate: '2024-06-01',
endDate: '2024-06-14',
participantsProfile: {
participantsCount: 128,
sex: 'MALE',
},
eventProfiles: [
{
eventName: "Men's Singles",
eventType: 'SINGLES',
gender: 'MALE',
drawProfiles: [
{
drawSize: 64,
drawName: 'Singles Championship',
seedsCount: 16,
qualifiersCount: 8, // 8 qualifier positions in main draw
qualifyingProfiles: [
{
roundTarget: 1,
structureProfiles: [
{
stageSequence: 1,
drawSize: 16, // 16 players for 8 qualifying spots
seedsCount: 4,
},
],
},
],
},
],
},
{
eventName: "Men's Doubles",
eventType: 'DOUBLES',
gender: 'MALE',
drawProfiles: [
{
drawSize: 32,
seedsCount: 8,
},
],
},
],
venueProfiles: [
{
venueName: 'Championship Courts',
courtsCount: 12,
},
],
});
Round Robin with Playoffs
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{
drawSize: 16,
drawType: 'ROUND_ROBIN_WITH_PLAYOFF',
seedsCount: 4,
},
],
completeAllMatchUps: true,
});
Team Event with Tie Format
const { tournamentRecord } = mocksEngine.generateTournamentRecord({
drawProfiles: [
{
drawSize: 8,
eventType: 'TEAM',
tieFormat: {
collectionDefinitions: [
{
collectionName: 'Singles',
matchUpType: 'SINGLES',
matchUpCount: 3,
matchUpFormat: 'SET3-S:6/TB7',
},
{
collectionName: 'Doubles',
matchUpType: 'DOUBLES',
matchUpCount: 1,
matchUpFormat: 'SET3-S:6/TB7',
},
],
},
},
],
});
Tips and Best Practices
- Start with drawProfiles for simple scenarios, use eventProfiles for complex multi-draw events
- Use idPrefix during development for easier debugging
- Set completeAllMatchUps when testing post-match logic
- Use unique participants when testing cross-event conflicts
- Specify matchUpFormat when testing format-specific logic
- Leverage outcomes to set up specific match scenarios
- Use completionGoal to test partial tournament completion
Next Steps
- Participant Generation - Individual, pairs and teams
- Outcome Generation - Generating match results
- Advanced Patterns - Best practices and common patterns