Skip to main content

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

Sex vs Gender

In the TODS data model:

  • Persons have sex - A biological attribute (MALE/FEMALE) stored in person.sex
  • Events have gender - A competition category attribute (MALE/FEMALE/MIXED/ANY) stored in event.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.

Scoped Participant Generation

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.

Event-Level Participant Profiles

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

Qualifying as a Stage

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:

  1. Draw-level participantsProfile (highest priority)
  2. Event-level participantsProfile
  3. 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.

Policy Definition Hierarchy

policyDefinitions can be specified at three levels with the following priority:

  1. Draw-level (within drawProfile) - highest priority, applies only to that draw
  2. Event-level (within eventProfile) - applies to all draws in that event
  3. 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

  1. Start with drawProfiles for simple scenarios, use eventProfiles for complex multi-draw events
  2. Use idPrefix during development for easier debugging
  3. Set completeAllMatchUps when testing post-match logic
  4. Use unique participants when testing cross-event conflicts
  5. Specify matchUpFormat when testing format-specific logic
  6. Leverage outcomes to set up specific match scenarios
  7. Use completionGoal to test partial tournament completion

Next Steps