Skip to main content

MatchUps Overview

Overview

MatchUps are the fundamental competitive units in TODS, representing individual contests between participants. A matchUp can be a singles match, doubles match, or team match, and contains all information about the competition: participants, scores, schedule, officials, and outcome.

Key Concepts

Match Types: SINGLES, DOUBLES, TEAM
Match Status: TO_BE_PLAYED, IN_PROGRESS, COMPLETED, WALKOVER, DEFAULTED, etc.
Sides: The two competing participants (side1 and side2)
Position Assignments: How participants are placed in matchUps
Hydration: Adding contextual information from draw/event/tournament
Collection MatchUps: Individual matches within TEAM matchUps

MatchUp Types

SINGLES

A matchUp between two INDIVIDUAL participants:

type SinglesMatchUp = {
matchUpId: string;
matchUpType: 'SINGLES';
matchUpFormat: string; // e.g., 'SET3-S:6/TB7'
matchUpStatus: MatchUpStatus;
sides: [
{
sideNumber: 1,
participantId: string, // INDIVIDUAL participant
participant?: Participant
},
{
sideNumber: 2,
participantId: string,
participant?: Participant
}
];
score?: Score;
winningSide?: 1 | 2;
// ... additional attributes
};

DOUBLES

A matchUp between two PAIR participants:

type DoublesMatchUp = {
matchUpId: string;
matchUpType: 'DOUBLES';
matchUpFormat: string;
matchUpStatus: MatchUpStatus;
sides: [
{
sideNumber: 1,
participantId: string, // PAIR participant
participant?: PairParticipant
},
{
sideNumber: 2,
participantId: string,
participant?: PairParticipant
}
];
score?: Score;
winningSide?: 1 | 2;
};

TEAM

A matchUp between two TEAM participants, containing multiple collection matchUps:

type TeamMatchUp = {
matchUpId: string;
matchUpType: 'TEAM';
matchUpStatus: MatchUpStatus;
tieFormat: TieFormat; // Defines structure of team match
sides: [
{
sideNumber: 1,
participantId: string, // TEAM participant
lineUp?: IndividualParticipant[]
},
{
sideNumber: 2,
participantId: string,
lineUp?: IndividualParticipant[]
}
];
tieMatchUps?: CollectionMatchUp[]; // Individual matches within team match
score?: TeamScore;
winningSide?: 1 | 2;
};

See: Tie Format and Tie MatchUp for team match details.

MatchUp Status

MatchUps progress through various states:

Pre-Match Statuses

  • TO_BE_PLAYED - Match is scheduled but not started
  • BYE - One participant received a bye
  • WALKOVER - Opponent did not appear
  • DEFAULTED - Participant disqualified before starting

During Match

  • IN_PROGRESS - Match currently being played
  • SUSPENDED - Match temporarily halted
  • INTERRUPTED - Match paused (rain delay, etc.)

Post-Match

  • COMPLETED - Match finished with score
  • RETIRED - Participant withdrew during match
  • ABANDONED - Match canceled/voided
  • CANCELLED - Match will not be played
  • DEAD_RUBBER - Match outcome irrelevant to progression

Example Usage

const { matchUps } = tournamentEngine.allTournamentMatchUps({
matchUpFilters: {
matchUpStatuses: ['COMPLETED', 'RETIRED', 'DEFAULTED']
}
});

console.log(`${matchUps.length} finished matches`);

Retrieving MatchUps

Tournament-Wide

Get all matchUps across entire tournament:

const { matchUps } = tournamentEngine.allTournamentMatchUps({
inContext: true, // Add tournament/event/draw context (default)
nextMatchUps: true // Include winnerTo/loserTo information
});

// MatchUps are automatically returned with context
matchUps.forEach(matchUp => {
console.log(`${matchUp.tournamentName} - ${matchUp.eventName}`);
console.log(` ${matchUp.drawName} - Round ${matchUp.roundNumber}`);
});

Event-Specific

Get matchUps for a specific event:

const { matchUps } = tournamentEngine.allEventMatchUps({
eventId: 'singles-main',
inContext: true
});

Draw-Specific

Get matchUps from a specific draw:

const { matchUps } = tournamentEngine.allDrawMatchUps({
drawId: 'draw-123',
inContext: true
});

With Filters

Filter matchUps by various criteria:

const { matchUps } = tournamentEngine.allTournamentMatchUps({
matchUpFilters: {
matchUpStatuses: ['COMPLETED'],
matchUpTypes: ['SINGLES', 'DOUBLES'],
roundNumbers: [1, 2],
hasWinningSide: true
},
contextFilters: {
scheduledDate: '2024-06-15',
venueIds: ['venue-123'],
courtIds: ['court-1', 'court-2']
}
});

See: MatchUp Filtering for comprehensive filtering options.

MatchUp Sides

Each matchUp has two sides representing the competing participants:

{
matchUpId: 'match-123',
sides: [
{
sideNumber: 1,
participantId: 'player-1',
participant: { // Added when inContext: true
participantType: 'INDIVIDUAL',
person: { standardFamilyName: 'Federer' }
}
},
{
sideNumber: 2,
participantId: 'player-2',
participant: {
participantType: 'INDIVIDUAL',
person: { standardFamilyName: 'Nadal' }
}
}
]
}

Winning Side

After completion, winningSide indicates the victor:

if (matchUp.matchUpStatus === 'COMPLETED') {
const winner = matchUp.sides.find(s => s.sideNumber === matchUp.winningSide);
const loser = matchUp.sides.find(s => s.sideNumber !== matchUp.winningSide);
console.log(`Winner: ${winner.participant.person.standardFamilyName}`);
}

Scores

MatchUp scores follow TODS score structure:

{
matchUpId: 'match-123',
score: {
sets: [
{
setNumber: 1,
side1Score: 6,
side2Score: 4,
winningSide: 1
},
{
setNumber: 2,
side1Score: 7,
side2Score: 6,
side1TiebreakScore: 7,
side2TiebreakScore: 5,
winningSide: 1
}
],
scoreStringSide1: '6-4 7-6(7)',
scoreStringSide2: '4-6 6-7(5)'
},
winningSide: 1
}

Setting Scores

tournamentEngine.setMatchUpStatus({
matchUpId: 'match-123',
drawId: 'draw-456',
outcome: {
score: {
sets: [
{ side1Score: 6, side2Score: 4, winningSide: 1 },
{ side1Score: 6, side2Score: 3, winningSide: 1 }
]
},
winningSide: 1
}
});

Scheduling Information

MatchUps include comprehensive scheduling details:

{
matchUpId: 'match-123',
schedule: {
scheduledDate: '2024-06-15',
scheduledTime: '14:00',
venueId: 'venue-123',
courtId: 'court-5',
courtName: 'Court 5',
startTime: '2024-06-15T14:05:00Z',
endTime: '2024-06-15T15:45:00Z'
},
// Additional context when inContext: true
venueName: 'Stadium',
courtOrder: 2 // Order of play on this court
}

Scheduling MatchUps

tournamentEngine.addMatchUpScheduleItems({
matchUpId: 'match-123',
drawId: 'draw-456',
schedule: {
scheduledDate: '2024-06-15',
scheduledTime: '14:00',
venueId: 'venue-123',
courtId: 'court-5'
}
});

See: Scheduling Overview for detailed scheduling workflows.

Officials and Check-In

Assigning Officials

// Assign referee
tournamentEngine.addMatchUpOfficial({
matchUpId: 'match-123',
drawId: 'draw-456',
participantId: 'official-789',
officialType: 'REFEREE'
});

Participant Check-In

Track participant availability:

// Check in participants
tournamentEngine.checkInParticipant({
matchUpId: 'match-123',
participantId: 'player-1'
});

// Both participants checked in?
if (matchUp.sides.every(side => side.checkInState === 'CHECKED_IN')) {
console.log('Match ready to start');
}

Next MatchUps (Winner/Loser Progression)

When nextMatchUps: true, each matchUp includes progression information:

const { matchUps } = tournamentEngine.allDrawMatchUps({
drawId: 'draw-123',
nextMatchUps: true
});

matchUps.forEach(matchUp => {
if (matchUp.winnerTo) {
console.log(`Winner advances to matchUp ${matchUp.winnerTo.matchUpId}`);
console.log(` Round ${matchUp.winnerTo.roundNumber}`);
}
if (matchUp.loserTo) {
console.log(`Loser feeds to matchUp ${matchUp.loserTo.matchUpId}`);
console.log(` Consolation Round ${matchUp.loserTo.roundNumber}`);
}
});

Collection MatchUps (TEAM Matches)

TEAM matchUps contain collection matchUps (individual matches):

const teamMatchUp = {
matchUpId: 'team-match-123',
matchUpType: 'TEAM',
tieMatchUps: [
{
matchUpId: 'singles-1',
matchUpType: 'SINGLES',
collectionId: 'singles-collection',
collectionPosition: 1
},
{
matchUpId: 'singles-2',
matchUpType: 'SINGLES',
collectionId: 'singles-collection',
collectionPosition: 2
},
{
matchUpId: 'doubles-1',
matchUpType: 'DOUBLES',
collectionId: 'doubles-collection',
collectionPosition: 1
}
]
};

// Access individual matches
teamMatchUp.tieMatchUps.forEach(tieMatchUp => {
console.log(`${tieMatchUp.matchUpType} Match ${tieMatchUp.collectionPosition}`);
});

MatchUp Actions

Get available actions for a matchUp:

const { validActions } = tournamentEngine.matchUpActions({
matchUpId: 'match-123',
drawId: 'draw-456'
});

validActions.forEach(action => {
console.log(`Available: ${action.type}`);
// - SCORE: Can enter score
// - SCHEDULE: Can set schedule
// - ASSIGN_OFFICIAL: Can assign referee
// - etc.
});

See: Actions for complete action documentation.

Common Use Cases

Display Order of Play

const { matchUps } = tournamentEngine.allTournamentMatchUps({
contextFilters: {
scheduledDate: '2024-06-15',
venueIds: ['main-stadium']
},
matchUpFilters: {
matchUpStatuses: ['TO_BE_PLAYED', 'IN_PROGRESS']
}
});

// Group by court
const byCourt = matchUps.reduce((acc, matchUp) => {
const courtId = matchUp.schedule?.courtId || 'unscheduled';
if (!acc[courtId]) acc[courtId] = [];
acc[courtId].push(matchUp);
return acc;
}, {});

// Display
Object.entries(byCourt).forEach(([courtId, matches]) => {
console.log(`\n${matches[0]?.courtName || 'Unscheduled'}:`);
matches.forEach(m => {
console.log(` ${m.schedule.scheduledTime} - ${m.roundName}`);
});
});

Results Feed

const { matchUps } = tournamentEngine.allTournamentMatchUps({
matchUpFilters: {
matchUpStatuses: ['COMPLETED']
}
});

// Sort by completion time
matchUps
.sort((a, b) =>
new Date(b.schedule?.endTime || 0) - new Date(a.schedule?.endTime || 0)
)
.slice(0, 10) // Latest 10 results
.forEach(matchUp => {
const winner = matchUp.sides.find(s => s.sideNumber === matchUp.winningSide);
const loser = matchUp.sides.find(s => s.sideNumber !== matchUp.winningSide);
console.log(`${winner.participant.person.standardFamilyName} d. ${loser.participant.person.standardFamilyName}`);
console.log(` ${matchUp.score.scoreStringSide1}`);
});

Live Matches

const { matchUps } = tournamentEngine.allTournamentMatchUps({
matchUpFilters: {
matchUpStatuses: ['IN_PROGRESS']
}
});

console.log(`${matchUps.length} matches in progress`);
matchUps.forEach(matchUp => {
console.log(`${matchUp.courtName}: ${matchUp.roundName}`);
matchUp.sides.forEach(side => {
console.log(` ${side.participant.person.standardFamilyName}`);
});
});