Schedule Governor
The Schedule Governor provides methods for assigning dates, times, venues, and courts to tournament matchUps. It supports manual assignment, automated scheduling, and hybrid approaches for tournaments ranging from simple club events to complex multi-day professional circuits.
import { scheduleGovernor } from 'tods-competition-factory';
See Scheduling Overview, Automated Scheduling, Pro Scheduling, and Scheduling Policy for comprehensive scheduling concepts.
Overview
Scheduling operates through Time Items attached to matchUps, providing:
- Audit trail: Complete scheduling history including modifications
- No orphaned schedules: Automatic cleanup when draws deleted
- Flexible queries: Schedules derived on-demand from matchUp timeItems
- Granular control: Each matchUp independently tracks its scheduling state
Scheduling Approaches
- Manual Methods: Direct assignment of dates, times, venues, courts
- Automated Methods: Algorithm-driven scheduling using Garman formula or grid scheduling
- Hybrid Methods: Combination of manual pre-assignments with automated scheduling
- Bulk Operations: Efficient scheduling of multiple matchUps simultaneously
Prerequisites
Automated scheduling requires:
- Venues and Courts: Define tournament venues with court specifications
- Date Availability: Specify when courts are available (dates, times, bookings)
- Scheduling Policy: Average match times, recovery periods, daily limits
- MatchUp Formats: Assign scoring formats to events/matchUps
Manual Scheduling Methods
addMatchUpScheduledDate
Assigns a scheduled date to a matchUp.
engine.addMatchUpScheduledDate({
matchUpId, // required
drawId, // required
scheduledDate, // required - ISO date string (YYYY-MM-DD)
disableNotice, // optional boolean - suppress notifications
});
Example:
engine.addMatchUpScheduledDate({
matchUpId: 'match-123',
drawId: 'draw-456',
scheduledDate: '2024-06-15',
});
addMatchUpScheduledTime
Assigns a scheduled time to a matchUp.
engine.addMatchUpScheduledTime({
matchUpId, // required
drawId, // required
scheduledTime, // required - time string (HH:mm)
disableNotice, // optional boolean - suppress notifications
});
Example:
engine.addMatchUpScheduledTime({
matchUpId: 'match-123',
drawId: 'draw-456',
scheduledTime: '14:30',
});
assignMatchUpVenue
Assigns a venue to a matchUp.
engine.assignMatchUpVenue({
matchUpId, // required
drawId, // required
venueId, // required
disableNotice, // optional boolean - suppress notifications
});
Example:
engine.assignMatchUpVenue({
matchUpId: 'match-123',
drawId: 'draw-456',
venueId: 'venue-789',
});
assignMatchUpCourt
Assigns a specific court to a matchUp.
engine.assignMatchUpCourt({
matchUpId, // required
drawId, // required
courtId, // required
courtDayDate, // optional - date string for multi-day scheduling
disableNotice, // optional boolean - suppress notifications
});
Example:
engine.assignMatchUpCourt({
matchUpId: 'match-123',
drawId: 'draw-456',
courtId: 'court-1',
courtDayDate: '2024-06-15',
});
Automated Scheduling Methods
scheduleMatchUps
Auto-schedules matchUps on a given date using the Garman formula for optimal court utilization. Intelligently assigns courts and times based on court availability, match duration estimates, recovery times, and participant daily limits.
engine.scheduleMatchUps({
scheduleDate, // required - ISO date string (YYYY-MM-DD)
matchUpIds, // required - array of matchUpIds to schedule
// Venue selection
venueIds, // optional - defaults to all venues
// Scheduling parameters
periodLength, // optional - scheduling block size in minutes (default: 30)
averageMatchUpMinutes, // optional - average match duration (default: 90)
recoveryMinutes, // optional - recovery time between matches (default: 0)
// Time constraints
startTime, // optional - schedule start time (HH:mm)
endTime, // optional - schedule end time (HH:mm)
// Limits and policies
matchUpDailyLimits, // optional - SINGLES, DOUBLES, total limits
checkPotentialRequestConflicts, // optional boolean (default: true)
// Execution control
dryRun, // optional boolean - preview without changes
});
Period Length: Scheduling Block Size
The periodLength parameter controls the granularity of scheduling blocks:
- 15 minutes: Fine-grained scheduling for short-format matches
- 30 minutes (default): Standard scheduling for most tournaments
- 60 minutes: Coarse scheduling for long-format matches
Smaller period lengths provide more precise start times but may reduce court utilization. Larger periods improve grouping but reduce precision.
See: Automated Scheduling - Period Length for detailed explanation.
Examples
Basic Scheduling:
engine.scheduleMatchUps({
scheduleDate: '2024-06-15',
matchUpIds: ['match-1', 'match-2', 'match-3'],
});
Custom Parameters:
engine.scheduleMatchUps({
scheduleDate: '2024-06-15',
matchUpIds,
venueIds: ['venue-1'],
periodLength: 30,
averageMatchUpMinutes: 90,
recoveryMinutes: 60,
startTime: '08:00',
endTime: '18:00',
matchUpDailyLimits: {
SINGLES: 2,
DOUBLES: 1,
total: 2,
},
});
Dry Run Preview:
const result = engine.scheduleMatchUps({
scheduleDate: '2024-06-15',
matchUpIds,
dryRun: true, // Preview without making changes
});
console.log('Would schedule:', result.scheduledMatchUpIds);
console.log('Would not fit:', result.noTimeMatchUpIds);
See: Automated Scheduling Concepts for algorithm details.
scheduleProfileRounds
Auto-schedules all rounds specified in a scheduling profile across multiple days and venues. Uses a pre-defined profile that maps rounds to specific dates and venues.
engine.scheduleProfileRounds({
// Scheduling parameters
periodLength, // optional - scheduling block size (default: 30)
// Date selection
scheduleDates, // optional - specific dates to schedule
clearScheduleDates, // optional - boolean or array of dates to clear first
// Execution control
dryRun, // optional boolean - preview without changes
pro, // optional boolean - use grid scheduling instead of Garman
checkPotentialRequestConflicts, // optional boolean (default: true)
});
Returns:
{
(scheduledDates, // array - dates where matchUps were scheduled
scheduledMatchUpIds, // array - matchUpIds that were scheduled
noTimeMatchUpIds, // array - matchUps that couldn't fit
overLimitMatchUpIds, // array - matchUps exceeding participant limits
requestConflicts); // array - participant request conflicts
}
Examples
Schedule All Profile Dates:
const result = engine.scheduleProfileRounds({
periodLength: 30,
});
console.log('Scheduled dates:', result.scheduledDates);
console.log('No time for:', result.noTimeMatchUpIds.length, 'matchUps');
Schedule Specific Dates:
engine.scheduleProfileRounds({
scheduleDates: ['2024-06-15', '2024-06-16'],
periodLength: 30,
});
Clear and Reschedule:
engine.scheduleProfileRounds({
clearScheduleDates: true, // Clear all dates
periodLength: 30,
});
// Or clear specific dates
engine.scheduleProfileRounds({
clearScheduleDates: ['2024-06-15', '2024-06-16'],
scheduleDates: ['2024-06-15', '2024-06-16'],
periodLength: 30,
});
Dry Run Preview:
const result = engine.scheduleProfileRounds({
dryRun: true,
});
console.log('Would schedule:', result.scheduledMatchUpIds.length, 'matchUps');
console.log('Request conflicts:', result.requestConflicts);
Professional Grid Scheduling:
engine.scheduleProfileRounds({
pro: true, // Use grid scheduling
periodLength: 30,
});
SINGLES and DOUBLES matchUps are scheduled automatically. TEAM matchUps require manual court allocation using allocateTeamMatchUpCourts().
See: Scheduling Profile and Pro Scheduling for details.
Bulk Operations
bulkScheduleTournamentMatchUps
Efficiently schedules multiple matchUps with identical or varying schedule details.
engine.bulkScheduleTournamentMatchUps({
// When all matchUps have same schedule
matchUpIds, // array of matchUpIds
schedule, // schedule object { scheduledDate, scheduledTime, venueId, courtId }
// When matchUps have different schedules
matchUpDetails, // array of { matchUpId, schedule }
// Validation and control
checkChronology, // optional boolean - warn on scheduling errors
errorOnAnachronism, // optional boolean - throw error on chronological errors
removePriorValues, // optional boolean - clear existing scheduling timeItems
});
Examples
Same Schedule for All:
const schedule = {
scheduledDate: '2024-06-15',
scheduledTime: '08:00',
venueId: 'venue-1',
};
engine.bulkScheduleTournamentMatchUps({
matchUpIds: ['match-1', 'match-2', 'match-3'],
schedule,
});
Different Schedules:
const matchUpDetails = [
{
matchUpId: 'match-1',
schedule: {
scheduledDate: '2024-06-15',
scheduledTime: '08:00',
venueId: 'venue-1',
courtId: 'court-1',
},
},
{
matchUpId: 'match-2',
schedule: {
scheduledDate: '2024-06-15',
scheduledTime: '09:30',
venueId: 'venue-1',
courtId: 'court-2',
},
},
];
engine.bulkScheduleTournamentMatchUps({
matchUpDetails,
checkChronology: true,
errorOnAnachronism: true,
});
Replace All Schedules:
engine.bulkScheduleTournamentMatchUps({
matchUpIds,
schedule,
removePriorValues: true, // Clear previous scheduling
});
bulkRescheduleMatchUps
Shifts scheduled matchUps by a specified number of days and/or minutes. Useful for weather delays or venue changes.
const {
rescheduled, // array of inContext matchUps that were rescheduled
notRescheduled, // array of inContext matchUps that were NOT rescheduled
allRescheduled, // boolean - true if all matchUps rescheduled
dryRun, // boolean - indicates if this was a dry run
} = engine.bulkRescheduleMatchUps({
matchUpIds, // required - array of matchUpIds to reschedule
scheduleChange: {
daysChange: number, // number of days +/- to shift
minutesChange: number, // number of minutes +/- to shift
},
dryRun, // optional boolean - preview without changes
});
Examples
Delay by One Day:
const result = engine.bulkRescheduleMatchUps({
matchUpIds: ['match-1', 'match-2'],
scheduleChange: {
daysChange: 1, // Move forward one day
},
});
console.log('Rescheduled:', result.rescheduled.length);
console.log('Failed:', result.notRescheduled.length);
Shift Start Times:
engine.bulkRescheduleMatchUps({
matchUpIds,
scheduleChange: {
minutesChange: 30, // Start 30 minutes later
},
});
Weather Delay:
// Rain delay - move all to next day, 2 hours earlier start
engine.bulkRescheduleMatchUps({
matchUpIds,
scheduleChange: {
daysChange: 1,
minutesChange: -120, // 2 hours earlier
},
});
Dry Run Preview:
const result = engine.bulkRescheduleMatchUps({
matchUpIds,
scheduleChange: { daysChange: 1 },
dryRun: true,
});
console.log('Would reschedule:', result.rescheduled.length);
console.log('Would fail:', result.notRescheduled.length);
bulkUpdatePublishedEventIds
Returns filtered array of publishedEventIds from all eventIds included in a bulk matchUp status update. Useful for determining which events need re-publishing after bulk scoring.
const { publishedEventIds } = engine.bulkUpdatePublishedEventIds({
outcomes, // array of matchUp outcomes
});
// Re-publish affected events
publishedEventIds.forEach((eventId) => {
engine.publishEvent({ eventId });
});
Use Case: After bulk scoring at end of day, identify and republish only the affected published events rather than all events.
Clearing and Removing Schedules
clearMatchUpSchedule
Clears schedule information from a specific matchUp.
engine.clearMatchUpSchedule({
matchUpId, // required
drawId, // optional - optimizes lookup, triggers draw modification notice
scheduleAttributes, // optional - array of specific attributes to clear
});
Examples
Clear All Schedule Attributes:
engine.clearMatchUpSchedule({
matchUpId: 'match-123',
drawId: 'draw-456',
});
Clear Specific Attributes:
import { scheduleConstants } from 'tods-competition-factory';
engine.clearMatchUpSchedule({
matchUpId: 'match-123',
scheduleAttributes: [scheduleConstants.SCHEDULED_TIME, scheduleConstants.SCHEDULED_DATE],
});
clearScheduledMatchUps
Clears schedules from multiple matchUps based on criteria.
engine.clearScheduledMatchUps({
scheduledDates, // optional - array of dates to clear
venueIds, // optional - array of venueIds to clear
scheduleAttributes, // optional - which attributes to clear
ignoreMatchUpStatuses, // optional - matchUp statuses to skip
});
Examples
Clear Specific Date:
engine.clearScheduledMatchUps({
scheduledDates: ['2024-06-15'],
});
Clear Specific Venue:
engine.clearScheduledMatchUps({
venueIds: ['venue-1'],
});
Clear Only Times (Keep Dates):
import { scheduleConstants } from 'tods-competition-factory';
engine.clearScheduledMatchUps({
scheduledDates: ['2024-06-15'],
scheduleAttributes: [scheduleConstants.SCHEDULED_TIME],
});
Skip Completed MatchUps:
import { matchUpStatusConstants } from 'tods-competition-factory';
engine.clearScheduledMatchUps({
scheduledDates: ['2024-06-15'],
ignoreMatchUpStatuses: [
matchUpStatusConstants.COMPLETED,
matchUpStatusConstants.RETIRED,
matchUpStatusConstants.DEFAULTED,
],
});
Schedule Modifications
matchUpScheduleChange
Swaps the schedule details of two scheduled matchUps. Useful for manual adjustments in schedule grid interfaces.
engine.matchUpScheduleChange({
courtDayDate, // required - date string
sourceMatchUpContextIds, // required - source matchUp context
targetMatchUpContextIds, // required - target matchUp context
sourceCourtId, // optional - source court
targetCourtId, // optional - target court
});
Example:
engine.matchUpScheduleChange({
courtDayDate: '2024-06-15',
sourceMatchUpContextIds: {
tournamentId: 'tournament-1',
drawId: 'draw-1',
matchUpId: 'match-1',
},
targetMatchUpContextIds: {
tournamentId: 'tournament-1',
drawId: 'draw-1',
matchUpId: 'match-2',
},
sourceCourtId: 'court-1',
targetCourtId: 'court-2',
});
Use Case: Drag-and-drop schedule interfaces where matchUps are swapped between time slots or courts.
reorderUpcomingMatchUps
Reorders upcoming matchUps on a court, affecting their order of play.
engine.reorderUpcomingMatchUps({
matchUpContextIds, // required - array of matchUp context objects
firstToLast, // optional boolean - direction of reorder
});
Example:
const matchUpContextIds = [
{ tournamentId: 't1', drawId: 'd1', matchUpId: 'm1' },
{ tournamentId: 't1', drawId: 'd1', matchUpId: 'm2' },
{ tournamentId: 't1', drawId: 'd1', matchUpId: 'm3' },
];
engine.reorderUpcomingMatchUps({
matchUpContextIds,
firstToLast: true, // Move first to last
});
removeMatchUpCourtAssignment
Removes court assignment from a matchUp while preserving other schedule details.
engine.removeMatchUpCourtAssignment({
tournamentId, // optional - for multi-tournament scenarios
courtDayDate, // required - date string
matchUpId, // required
drawId, // required
});
Example:
engine.removeMatchUpCourtAssignment({
courtDayDate: '2024-06-15',
matchUpId: 'match-123',
drawId: 'draw-456',
});
Use Case: Remove court assignment while keeping date/time (e.g., court becomes unavailable, need to reassign).
Team Match Scheduling
allocateTeamMatchUpCourts
Allocates courts to individual matchUps within a TEAM matchUp (tie). Used for team competitions where multiple singles/doubles matches occur simultaneously.
engine.allocateTeamMatchUpCourts({
matchUpId, // required - team matchUp ID
drawId, // required
courtIds, // required - array of courtIds to allocate
removePriorValues, // optional boolean - clear previous allocations
});
Example:
// Team match with 4 singles and 2 doubles
engine.allocateTeamMatchUpCourts({
matchUpId: 'team-match-1',
drawId: 'draw-456',
courtIds: ['court-1', 'court-2', 'court-3', 'court-4'],
});
Use Case: Davis Cup or Fed Cup style ties where multiple matches play simultaneously on different courts.
Scheduling Profile Management
setSchedulingProfile
Stores a scheduling profile that defines which rounds are scheduled on which dates and venues. Used by scheduleProfileRounds().
engine.setSchedulingProfile({
schedulingProfile, // required - profile object
});
Profile Structure:
const schedulingProfile = [
{
scheduleDate: '2024-06-15',
venues: [
{
venueId: 'venue-1',
rounds: [
{
drawId: 'draw-1',
structureId: 'structure-1',
roundNumber: 1,
},
{
drawId: 'draw-2',
structureId: 'structure-2',
roundNumber: 1,
},
],
},
],
},
{
scheduleDate: '2024-06-16',
venues: [
{
venueId: 'venue-1',
rounds: [
{
drawId: 'draw-1',
structureId: 'structure-1',
roundNumber: 2,
},
],
},
],
},
];
engine.setSchedulingProfile({ schedulingProfile });
See: Scheduling Profile Concepts for detailed profile structure and creation.
Related Documentation
- Scheduling Overview - Core scheduling concepts
- Automated Scheduling - Algorithm details and Garman formula
- Pro Scheduling - Grid scheduling for professional tournaments
- Scheduling Profile - Multi-day scheduling profiles
- Scheduling Conflicts - Conflict detection and resolution
- Scheduling Policy - Policy configuration
- Venues and Courts - Venue setup and court availability
- Time Items - How schedules are stored