Draws Governor
Some methods on this page are candidates for removal from production engine exports at the 8.0.0 boundary. Their implementation references have moved: addGoesTo, allPlayoffPositionsFilled, generateDrawStructuresAndLinks, getDrawDefinitionTimeItem, getDrawStructures, getDrawTypeCoercion, getPositionsPlayedOff, getSeedingThresholds, hasLuckyRounds, updateTeamLineUp. Existing 7.x routes remain available; final decisions and external-integrator confirmations are tracked in the transition index.
import { drawsGovernor } from 'tods-competition-factory';
addAdHocMatchUps
Adds matchUps generated by generateAdHocMatchUps to specified structure within an AD_HOC drawDefinition.
engine.addAdHocMatchUps({
structureId, // optional if there is only one structure in drawDefinition
matchUps,
drawId,
});
addDrawDefinitionTimeItem
Adds a time item to a drawDefinition.
engine.addDrawDefinitionTimeItem({
drawId, // required
timeItem, // required - time item object
itemType, // required - time item type
});
Purpose: Attach time-based metadata to draws.
addFinishingRounds
Adds finishing rounds to an existing structure for placement matchUps.
engine.addFinishingRounds({
drawId, // required
structureId, // required
finishingPositions, // required - array of positions to play off
});
Purpose: Add placement matchUps for specific finishing positions.
addGoesTo
8.0.0 engine-removal candidate. This 7.x route remains available pending review. The full reference has moved to addGoesTo. Package-export status is a separate decision. Use migrateTournamentRecord for stored edges, addDrawDefinition for new draws, or getDrawData for read-only projection; see the full migration guidance.
adHocPositionSwap
Swaps participant assignments in two unscored matchUps that are part of the same roundNumber in and AD_HOC structure.
This method and one of the two participantIds are returned in validActions by positionActions which calls adHocMatchUpActions, meaning this method is not normally called directly.
engine.adHocPositionSwap({
participantIds,
structureId,
roundNumber,
drawId,
});
addLinkedConsolationStructure
Generates a consolation structure of any draw type and attaches it to an existing draw with LOSER links from specified source rounds. The consolation structure is created using the factory's standard generator pipeline, so it supports all draw types (AD_HOC, SINGLE_ELIMINATION, LUCKY_DRAW, ROUND_ROBIN, FEED_IN, etc.).
engine.addLinkedConsolationStructure({
drawId,
structureId, // optional - main structure to link from; auto-resolved if omitted
structureType, // optional - defaults to AD_HOC; any valid draw type (SINGLE_ELIMINATION, LUCKY_DRAW, ROUND_ROBIN, etc.)
structureName, // optional - defaults to 'Consolation'
drawSize, // optional - defaults to 2
matchUpFormat, // optional - scoring format for consolation matchUps
matchUpType, // optional - SINGLES, DOUBLES, TEAM; defaults to draw's matchUpType
links: [
// required - LOSER link definitions from main to consolation
{ sourceRoundNumber: 1, targetRoundNumber: 1 },
{ sourceRoundNumber: 2, targetRoundNumber: 1 },
{ sourceRoundNumber: 3, targetRoundNumber: 1 },
],
});
Use generateConsolationStructure to generate the consolation structure without attaching it. This is useful in client/server architectures where the structure must be generated locally and attached via an execution queue.
addPlayoffStructures
Adds playoff structures to an existing drawDefinition. This method creates PLAY_OFF structures linked via LOSER links from the specified source structure.
engine.addPlayoffStructures({
drawId,
structureId,
roundNumbers: [3], // required if no playoffPositions - source roundNumbers which will feed target structures, e.g. [1, 2]
roundProfiles, // optional - source roundNumbers as Object.keys with depth as Object.values, e.g. [{ 1: 2}, {2: 1}]
playoffPositions: [3, 4], // required if not provided roundNumbers
playoffAttributes, // optional - mapping of exitProfile or finishingPositionRange to structure names (see Finishing Positions concept)
exitProfileLimit, // limit playoff rounds generated by the attributes present in playoffAttributes
playoffStructureNameBase, // optional - base word for default playoff naming, e.g. 'Playoff'
roundLimit: 2, // optional - cap the rounds of each generated structure, e.g. a consolation that plays two rounds
roundLimits: { 1: 1 }, // optional - per SOURCE roundNumber cap; overrides roundLimit for that structure
playoffGroups, // optional - [{ finishingPositions, drawType, structureName }]; an unbuildable drawType refuses the call and nothing is added
});
// example use of playoffAttributes - will generated playoff structure from 2nd round with structureName: 'BRONZE'
const playoffAttributes = {
'0-2': { name: 'BRONZE', abbreviation: 'B' },
};
For multi-level playoff trees (e.g., COMPASS topologies), use the withPlayoffs parameter on generateDrawDefinition instead of chaining multiple addPlayoffStructures calls. The withPlayoffs.roundPlayoffs field supports recursive nesting, building the entire tree in a single call. See Custom Playoff Topologies.
addQualifyingStructure
engine.addQualifyingStructure({
targetStructureId, // required: structure for which participants will qualify
qualifyingPositions, // optional: specify the # of qualifyingPositions
qualifyingRoundNumber, // optional: determine qualifyingPositions by # of matchUps in specified round; does not apply to ROUND_ROBIN
structureOptions, // optional: specific to ROUND_ROBIN generation
structureName, // optional
roundTarget, // optional: round of the target structure the qualifiers enter; defaults to 1. See getAvailableQualifyingTargets
drawSize,
drawType, // optional: defaults to SINGLE_ELIMINATION
drawId, // required: draw within which target structure appears
});
Refused with QUALIFYING_CAPACITY_EXCEEDED when the qualifiers this structure produces, added to those every other qualifying structure already sends into the same round, exceed the drawPositions that round has.
addVoluntaryConsolationStage
Modifies the entryProfile for a draw to allow { entryStage: VOLUNTARY_CONSOLATION }
engine.addVoluntaryConsolationStage({
drawSize,
drawId,
});
addVoluntaryConsolationStructure
Generates a new structure within a drawDefinition if any draw entries are present for { entryStage: VOLUNTARY_CONSOLATION }.
engine.addVoluntaryConsolationStructure({
structureAbbreviation, // optional
structureName, // optional - defaults to 'VOLUNTARY_CONSOLATION'
drawId,
});
allPlayoffPositionsFilled
8.0.0 engine-removal candidate. This 7.x route remains available pending review. The full reference has moved to allPlayoffPositionsFilled. Package-export status is a separate decision.
alternateDrawPositionAssignment
Replaces an existing drawPosition assignment with an alternateParticipantId. This method is included in validActions for positionActions
engine.alternateDrawPositionAssignment({
alternateParticipantId,
drawPosition,
structureId,
drawId,
});
assignDrawPosition
Low level function normally called by higher order convenience functions.
engine.assignDrawPosition({
participantId, // optional - if assigning position to a participant
drawPosition,
structureId,
qualifier, // optional boolean, if assigning a space for a qualifier
drawId,
bye, // optional boolean, if assigning a bye
});
Idempotent for the same position. Re-asserting a participant at the drawPosition it
already occupies is a no-op success — not an error — so a bulk re-sync or retry that
re-pushes an already-positioned draw (e.g. an integration re-sending its full position set)
does not fail or roll back. Assigning the participant to a different position still
returns EXISTING_PARTICIPANT_DRAW_POSITION_ASSIGNMENT; moving a placed participant
requires clearing the source (or a swap) first.
assignDrawPositionBye
engine.assignDrawPositionBye({
structureId,
drawId,
});
attachQualifyingStructure
engine.attachQualifyingStructure({
structure, // required: structure object; see `generateQualifyingStructure`
drawId, // required: id of drawDedfinition to which structure will be attached
link, // required
});
Refused with QUALIFYING_CAPACITY_EXCEEDED (7.8.0) when the qualifiers this structure produces, added to those every other qualifying structure already sends into the same round, exceed the drawPositions that round has. The round is link.target.roundNumber (default 1); getAvailableQualifyingTargets reports each round's structuralCapacity, the limit applied here.
automatedPlayoffPositioning
For Round Robin structures, uses Round Robin Tallies to position participants in playoff structure(s).
engine.automatedPlayoffPositioning({
structureId: mainStructure.structureId,
provisionalPositioning, // optional boolean, defaults to false; when true will honor provisionalOrder if no groupOrder is found in tallyResults
applyPositioning, // optional boolean, defaults to true; when false will return positioning but not apply it to playoff structures
drawId,
});
automatedPositioning
Positions participants in a draw structure. See examples: Draw Operations, Basic Rollback.
See Policies.
engine.automatedPositioning({ drawId, structureId });
Since 7.7.0 anything positioning refuses is returned as a real { error } — INSUFFICIENT_DRAW_POSITIONS,
NO_DRAW_POSITIONS_AVAILABLE_FOR_QUALIFIERS, LUCKY_DRAW_BYE_LIMIT, … — where it used to be decorated
into a success. Re-running on a positioned structure succeeds and returns the existing assignments;
automatedPlayoffPositioning returns no entry for AD_HOC playoff structures. Qualifiers are placed in
the structure and refused, not partially placed, when they do not fit; later-round qualifiers are placed
before first-round ones; a standalone PAGE_PLAYOFF positions both entry structures.
The structure's size is read from the structure, so drawSize need not be passed. Until this was fixed, positioning
without it placed unseeded entrants in entry order, the same for every seed. When every outstanding qualifier
enters round one, unseeded entrants are placed before the qualifier positions; see
Anonymous qualifier placement.
Positioning a draw generated before its entries
A MAIN generated with no entries places nothing, qualifier positions included: they are placed when the draw is
positioned. automatedPositioning then places the entries present, the qualifier positions and the BYEs. With
seedsCount, a structure that nobody is placed in and that has no seeds yet is seeded first, from the entries present
now and within the seeding policy; seeds chosen when the draw was generated are kept.
const { positionAssignments, seedAssignments } = engine.automatedPositioning({
seedingScaleName, // optional - the seeding scale; defaults to the event's category name, age category or eventId
seedByRanking, // optional boolean - with no seeding, seed by the event category's ranking
enforcePolicyLimits, // optional - defaults to true: the seeding policy caps seedsCount for the entries present
applyPositioning: false, // optional - compute without applying: see setPositionAssignments
seedsCount, // optional - seeds to choose when the structure has none
structureId,
drawId,
});
Positioning is random: a client computes it with applyPositioning: false and sends the result, seeds included, with
setPositionAssignments, so the client and the server apply the same draw.
autoSeeding
Only generates seeding. To apply engine.setParticipantScaleItems({ scaleItemsWithParticipantIds }.
:::. See examples: Using Factory autoSeeding(), Seeding from Rankings, Event Type Alignment.
const { scaleItemsWithParticipantIds } = engine.autoSeeding({
policyDefinitions, // seeding policyDefinition determines the # of seeds for given participantsCount/drawSize
scaleAttributes, // { scaleType, scaleName, eventType, accessor }
scaleName, // Optional - defaults to scaleAttributes.scaleName
drawSize, // Optional - defaults to calculation based on # of entries
eventId, // required - necessary for resolving entries
drawId, // Optional - will use flight.drawEntries or drawDefinition.entries rather than event.entries
stage, // Optional - filters entries by specified stage
scaleSortMethod, // Optional - user defined sorting method
sortDescending, // Optional - defaults to false
});
engine.setParticipantScaleItems({
scaleItemsWithParticipantIds,
});
checkValidEntries
Validates entry participant types and event gender constraints. By default, eventId validates the event's
entries; supplying drawId validates that draw's entries instead. consideredEntries overrides either
source, including when it is an empty array. A supplied draw also determines which format-specific
admission rules apply: accepted individuals are eligible only in a configured rotating-partner draw.
const { valid, error, invalidParticipantIds } = engine.checkValidEntries({
eventId, // required unless drawId identifies the event
drawId, // optional - use this draw's entries and admission rules
consideredEntries, // optional - explicit entries to validate instead
enforceGender, // optional - override the applicable gender-enforcement policy
});
drawMatic
Automated draw positioning system that intelligently assigns participants to draw positions. See DrawMatic for full documentation.
const result = engine.drawMatic({
drawId, // required
structureId, // optional - specific structure
policyDefinitions, // optional - positioning policies
useExistingAdjustments, // optional boolean - preserve manual adjustments
participants, // optional - override participant data
});
Purpose: AI-driven draw positioning for optimal tournament structure.
generateAdHocMatchUps
Generates adhoc matchUps for custom tournament structures.
const { matchUps } = engine.generateAdHocMatchUps({
participants, // required - array of participant IDs
matchUpsPerFlight, // optional - matchUps per round
uuids, // optional - specific matchUp IDs
});
Purpose: Create custom matchUp structures outside standard draw types.
generateAdHocRounds
Generates multiple rounds of adhoc matchUps.
const { rounds } = engine.generateAdHocRounds({
participants, // required
roundsCount, // required - number of rounds
});
Purpose: Create multi-round custom structures.
generateAndPopulatePlayoffStructures
Generates and automatically populates playoff structures in one operation.
engine.generateAndPopulatePlayoffStructures({
drawId, // required
structureId, // required
roundNumbers, // required - source rounds for playoffs
playoffAttributes, // optional
});
Purpose: Automate playoff structure creation and population.
generateDrawDefinition
Generates a complete draw definition from parameters.
const { drawDefinition } = engine.generateDrawDefinition({
drawSize, // required
drawType, // required - SINGLE_ELIMINATION, etc.
seedsCount, // optional
drawName, // optional
entries, // optional
matchUpFormat, // optional
automated, // optional boolean - auto-position participants
});
Purpose: Core draw generation method.
Since 7.7.0 a draw whose direct entries and reserved qualifiers exceed its drawSize is refused with
{ error: INSUFFICIENT_DRAW_POSITIONS, context } (it used to return a draw with nobody positioned), a
draw's qualifiersCount reserves no positions in the qualifying structure, and a round link that cannot
be read is reported as an error rather than thrown. A malformed drawName is refused by modifyDrawDefinition
as { error } rather than read as success.
With the drawId of a draw already in the event (adding qualifying to a generated main), the draw is built on a
copy and the record is left as it was: commit the result with
addDrawDefinition({ drawDefinition, allowReplacement: true }), which announces it. Until 2026-10 the stored draw was
changed in place, unannounced, whether or not the commit followed.
generateDrawMaticRound
Generates positioning for a specific round using the drawMatic algorithm.
engine.generateDrawMaticRound({
drawId, // required
structureId, // required
roundNumber, // required
policyDefinitions, // optional
});
Purpose: AI positioning for specific draw rounds.
generateDrawStructuresAndLinks
8.0.0 engine-removal candidate. This 7.x route remains available pending review. The full reference has moved to generateDrawStructuresAndLinks. Package-export status is a separate decision.
generateDrawTypeAndModifyDrawDefinition
Modifies an existing draw to change its type/structure.
engine.generateDrawTypeAndModifyDrawDefinition({
drawId, // required
drawType, // required - new draw type
drawSize, // optional
});
Purpose: Convert draw to different format.
On a draw stored in the event the matchUps it adds are announced as ADD_MATCHUPS, with MODIFY_DRAW_DEFINITION;
modifyOriginal: false works on a copy and sends nothing.
generateQualifyingStructure
Generates a qualifying structure for a main draw.
const { structure } = engine.generateQualifyingStructure({
drawSize, // required
qualifyingPositions, // required
structureName, // optional
});
Purpose: Create qualifying rounds for tournaments.
generateVoluntaryConsolation
Generates a voluntary consolation draw structure.
const { structure } = engine.generateVoluntaryConsolation({
drawId, // required
drawSize, // required
structureName, // optional
});
Purpose: Create consolation draws for eliminated players.
deleteAdHocMatchUps
const result = engine.deleteAdHocMatchUps({
structureId, // optional optimization - structureId of structure from which matchUps are being deleted
matchUpIds, // array of matchUpIds identifying matchUps to be deleted
drawId, // required - drawId of drawDefinition in which target structure is found
});
luckyLoserDrawPositionAssignment
Replaces an existing drawPosition assignment with a luckyLoserParticipantId. This method is included in validActions for positionActions
engine.luckyLoserDrawPositionAssignment({
luckyLoserParticipantId,
drawPosition,
structureId,
drawId,
});
getAssignedParticipantIds
Returns all participant IDs assigned to positions in a draw.
const { participantIds } = engine.getAssignedParticipantIds({
drawId, // required
structureId, // optional - specific structure
});
Purpose: Get all participants currently in draw.
getAvailableMatchUpsCount
Returns count of available matchUps that can be scheduled.
const { count } = engine.getAvailableMatchUpsCount({
drawId, // required
});
Purpose: Determine scheduling capacity.
getAvailablePlayoffProfiles
Returns available playoff configurations based on draw structure.
const { profiles } = engine.getAvailablePlayoffProfiles({
drawId, // required
structureId, // required
});
Purpose: Get playoff options for structure.
In a TEAM draw only TEAM matchUps are read: a dual's tieMatchUps share its round, structure and drawPositions, and are never counted as the round's matchUps (7.8.0; a FIRST_MATCH_LOSER_CONSOLATION round 2 was offered with a finishing range inflated by the rubbers, or not offered at all).
getAvailableQualifyingTargets
The rounds of a structure that qualifying structures may feed, and how much room each has. Several qualifying structures may feed the same round as long as the qualifiers they produce, in aggregate, do not exceed the drawPositions that round has; attachQualifyingStructure enforces that rule. The rest of the numbers describe the placement state so a client can show "already fed by Qualifying (16)" and clamp its offer. Clamp on remainingCapacity, not structuralCapacity: a position holding a participant or a BYE is not room, so a main whose positions are all filled has none, and a qualifier already placed counts once, against the promise it fulfils.
const { valid, targets } = engine.getAvailableQualifyingTargets({
drawId, // required
structureId, // required: the structure to be fed, usually MAIN
});
// valid: the isValidForQualifying answer — false when the structure is itself fed by losers
// targets: one entry per round that qualifiers can enter (round 1, and any feed round not fed by a LOSER link)
// [
// {
// roundNumber: 1,
// drawPositionsCount: 64, // positions that enter the structure in this round
// unfilledPositionsCount: 16, // of those, positions with no participant and no bye
// qualifierPositionsCount: 16, // of those, positions marked `qualifier` (reserved, with or without a link)
// unplacedDirectEntriesCount: 0, // round 1 only: direct entries in the draw not yet positioned
// placedQualifiersCount: 0, // of those, positions holding a participant who entered through qualifying
// owedQualifiers: 16, // the larger of promised and reserved, less those placed: each still needs an open position
// feedingStructures: [{ structureId, structureName: 'Qualifying', qualifiersCount: 16, placeholder: false }],
// promisedQualifiers: 16, // qualifiers already sent here by real qualifying structures
// reservedQualifiers: 0, // qualifiers a placeholder link reserves; a real structure consumes them
// structuralCapacity: 48, // drawPositionsCount - promisedQualifiers: what attach will accept
// remainingCapacity: 0, // unfilled - owed - unplaced direct entries: the room a new qualifying has today
// },
// ]
getDrawDefinitionTimeItem
8.0.0 engine-removal candidate. This 7.x route remains available pending review. The full reference has moved to getDrawDefinitionTimeItem. Package-export status is a separate decision.
getDrawParticipantRepresentativeIds
Returns representative participant IDs for team draws.
const { representativeIds } = engine.getDrawParticipantRepresentativeIds({
drawId, // required
participantId, // required
});
Purpose: Get team representatives in team competitions.
getDrawStructures
8.0.0 engine-removal candidate. This 7.x route remains available pending review. The full reference has moved to getDrawStructures. Package-export status is a separate decision.
getDrawTypeCoercion
8.0.0 engine-removal candidate. This 7.x route remains available pending review. The full reference has moved to getDrawTypeCoercion. Package-export status is a separate decision.
getEligibleVoluntaryConsolationParticipants
Returns participants eligible for voluntary consolation.
const { participants } = engine.getEligibleVoluntaryConsolationParticipants({
drawId, // required
});
Purpose: Find participants for consolation draws.
getFeedInQualifyingPositions
Returns the qualifier counts a FEED_IN (staggered entry) qualifying structure of drawSize positions can
produce: every count that divides drawSize at least twice over.
const { qualifyingPositions } = engine.getFeedInQualifyingPositions({
drawSize, // required
});
// drawSize 12 => [1, 2, 3, 4, 6]; 13 => [1]; 10 => [1, 2, 5]
Purpose: Offer only valid qualifier counts when a qualifying structure is FEED_IN.
getMatchUpsMap
Returns a map of matchUps indexed by matchUpId.
const { matchUpsMap } = engine.getMatchUpsMap({
drawId, // required
});
Purpose: Quick matchUp lookup by ID.
getParticipantIdFinishingPositions
Returns finishing positions for all participants in draw.
const { participantResults } = engine.getParticipantIdFinishingPositions({
drawId, // required
});
Purpose: Get final standings from draw.
getPositionAssignments
Returns position assignments for a structure.
const { positionAssignments } = engine.getPositionAssignments({
drawId, // required
structureId, // required
});
Purpose: Get participant-to-position mappings.
getPositionsPlayedOff
8.0.0 engine-removal candidate. This 7.x route remains available pending review. The full reference has moved to getPositionsPlayedOff. Package-export status is a separate decision.
getRandomQualifierList
Generates randomized list of qualifiers.
const { qualifiers } = engine.getRandomQualifierList({
qualifyingCount, // required
participantIds, // required
});
Purpose: Random selection for qualifying positions.
getSeedingThresholds
8.0.0 engine-removal candidate. This 7.x route remains available pending review. The full reference has moved to getSeedingThresholds. Package-export status is a separate decision.
getSeedsCount
Returns the number of seeds for a draw.
const { seedsCount } = engine.getSeedsCount({
drawId, // required
policyDefinitions, // optional
});
Purpose: Get seed count from draw or policy.
getStructureSeedAssignments
Returns seed assignments for a structure.
const { seedAssignments } = engine.getStructureSeedAssignments({
drawId, // required
structureId, // required
});
Purpose: Get seeding information for structure.
getTeamLineUp
Returns the lineup for a team matchUp.
const { lineup } = engine.getTeamLineUp({
drawId, // required
matchUpId, // required
});
Purpose: Get team member assignments for matchUp.
getValidGroupSizes
Returns valid group size options for round robin draws.
const { groupSizes } = engine.getValidGroupSizes({
drawSize, // required
});
Purpose: Determine valid round robin configurations.
isAdHoc
Checks if a structure is adhoc format.
const { isAdHoc } = engine.isAdHoc({
drawId, // required
structureId, // required
});
Returns: Boolean indicating adhoc structure.
isAdHoc asks about a structure — does it carry bracket geometry. isAdHocType and isLadder
ask about a drawType string. Reach for the one whose input you actually hold.
isAdHocType
Whether a drawType has the AD_HOC structure shape: matchUps carrying neither roundPosition
nor drawPosition, so nothing is derived from bracket geometry. AD_HOC, SWISS and — since
7.0.0 — LADDER.
const isAdHoc = engine.isAdHocType({ drawType }); // AD_HOC | SWISS | LADDER -> true
Also callable directly, which is how the factory's own generators use it:
import { governors } from 'tods-competition-factory';
governors.drawsGovernor.isAdHocType(drawType); // a bare string is accepted too
Returns: boolean.
This is the predicate that decides whether a draw needs a drawSize, whether stage capacity
applies, and whether rounds generate without an explicit roundsCount. A ladder qualifies on that
definition and gets all of it for free, which is why LADDER joined the set rather than being
special-cased.
isLadder
Whether a drawType is specifically LADDER.
const isLadder = engine.isLadder({ drawType });
Returns: boolean.
Use this rather than isAdHocType wherever the difference matters. A ladder shares the AD_HOC
structure shape but not its meaning: an AD_HOC draw's positionAssignments are a roster,
while a ladder's are an ordered standing and drawPosition is read as rank. Code that treats
the two alike will render a ladder's standing as though the order were arbitrary.
isCompletedStructure
Checks if a structure has all matchUps completed.
const { isCompleted } = engine.isCompletedStructure({
drawId, // required
structureId, // required
});
Returns: Boolean indicating structure completion.
isValidForQualifying
Checks if a structure can have qualifying added.
const { valid } = engine.isValidForQualifying({
drawId, // required
structureId, // required
});
Purpose: Validate qualifying structure eligibility.
modifyDrawDefinition
engine.modifyDrawDefinition({
drawUpdates: { policyDefinitions: { ...policies } },
drawName: 'League Play',
drawId,
});
modifySeedAssignment
Change the display representation of a seedNumber for a specified participantId. This method is included in validActions for positionActions.
The rationale for seedValue is to be able to, for instance, represent the fifth through the eighth seed as 5-8, or simply as 5. When there are no restrictions on seed positioning seedValue allows assigning seeding to arbitrary participants.
engine.modifySeedAssignment({
participantId,
structureId,
seedValue, // display representation such as '5-8'
drawId,
});
modifyDrawName
Changes the name of a draw.
engine.modifyDrawName({
drawId, // required
drawName, // required - new name
});
Purpose: Update draw display name.
positionActions
Returns available positioning actions for a draw position. The returned validActions array contains action objects with type, method, and payload properties that can be dispatched to perform the action.
const {
validActions, // array of action objects
isActiveDrawPosition, // boolean — position has active (scored) matchUps
hasPositionAssigned, // boolean — position has a participant or bye assigned
isDrawPosition, // boolean — position exists in the structure
isByePosition, // boolean — position is assigned a bye
} = engine.positionActions({
drawPosition, // required — the draw position number
structureId, // required — target structure
drawId, // required — resolved to drawDefinition by engine
policyDefinitions, // optional — override position action policies
provisionalPositioning, // optional boolean — honor provisional order from tallies
returnParticipants, // optional boolean — defaults to true; include participant objects in actions
restrictAdHocRoundParticipants, // deprecated, no effect — a participant already in the round is never offered
tournamentParticipants, // optional — pre-fetched participants array (optimization)
inContextDrawMatchUps, // optional — pre-fetched inContext matchUps (optimization)
matchUpsMap, // optional — pre-fetched matchUps map (optimization)
matchUpId, // optional — for AD_HOC structures, the target matchUp
event, // optional — resolved by engine
});
Purpose: Get valid participant assignment operations.
pruneDrawDefinition
Removes empty or unused structures from a draw.
engine.pruneDrawDefinition({
drawId, // required
});
Purpose: Clean up draw by removing unused structures.
A round robin draw is never listed as prunable by analyzeDraws and is returned unchanged here (7.7.0).
findDrawDefinition
Finds a draw definition by drawId within the current tournament record.
const { drawDefinition, event } = engine.findDrawDefinition({
drawId, // required — the drawId to find
});
publicFindDrawDefinition
Finds a draw definition with privacy policies applied.
const { drawDefinition } = engine.publicFindDrawDefinition({
drawId, // required
policyDefinitions, // optional
});
Purpose: Get draw data for public APIs.
qualifierDrawPositionAssignment
Places a qualifier (qualifyingParticipantId) at a drawPosition. This method is included in validActions for positionActions.
A seat reserved for a qualifier carries qualifier: true, and placing the qualifier there keeps the flag: it marks the participant as a qualifier, for example to show a 'Q' beside the name. See the qualifier flag.
engine.qualifierDrawPositionAssignment({
qualifyingParticipantId,
drawPosition,
structureId,
drawId,
});
qualifierProgression
Handles progression of qualifiers from qualifying to main draw.
engine.qualifierProgression({
drawId, // required
structureId, // optional - target structure
});
Purpose: Move qualifiers to main draw after qualifying completes.
removeDrawPositionAssignment
Clear draw position and optionally replace with a BYE, change entryStatus, or decompose a PAIR participant into UNGROUPED participants (DOUBLES only).
Clearing a position removes its qualifier flag along with the participant or BYE.
engine.removeDrawPositionAssignment({
drawDefinition,
structureId,
drawPosition,
replaceWithBye, // optional
entryStatus, // optional - change the entryStatus of the removed participant
destroyPair, // optional - decompose PAIR participant into UNGROUPED participants
});
removeDrawEntries
Removes participantIds from drawDefinition.entries (if generated) as well as any relevent flightProfile.flights.
engine.removeDrawEntries({
autoEntryPositions, // optional - keeps entries ordered by entryStage/entryStatus and auto-increments
participantIds
eventId,
stages, // optional array of stages to consider, e.g. [VOLUNTARY_CONSOLATION]
drawId,
});
removeRoundMatchUps
const {
deltedMatchUpsCount, // number
roundRemoved, // boolean
success, // boolean
error, // if any
} = engine.removeRoundMatchUps({
removeCompletedMatchUps, // optional boolean - whether to remove completed matchUps
roundNumber, // required - roundNumber to remove
structureId, // required
drawId, // required
});
AD_HOC structures only. For an elimination or round robin structure the result is NOT_IMPLEMENTED (it was success with nothing removed before 7.8.0); a round of an elimination structure is part of its shape, see pruneDrawDefinition.
removeStructure
Removes targeted drawDefinition.structure and all other child structures along with all associated drawDefinition.links.
const { removedMatchUpIds } = engine.removeStructure({
structureId,
drawId,
});
removeSeededParticipant
Removes a seeded participant from draw and adjusts seeding.
engine.removeSeededParticipant({
drawId, // required
structureId, // required
participantId, // required
});
Purpose: Remove participant and rebalance seeds.
renameStructures
engine.renameStructures({
structureDetails: [{ structureId, structureName }],
drawId,
});
repairMalformedLinks
Repairs every malformed entry of drawDefinition.links, or removes what cannot be repaired, and reports which. These are the link findings of getDrawInconsistencies: LINK_MISSING_SOURCE_ROUND, DANGLING_LINK and INVALID_LINK. A draw with such a link refuses every outcome, and an entry that is not an object makes the draw's readers throw. A link out of a round robin that names finishingPositions is never malformed, labelled POSITION or WINNER, and the repair never touches it: see Rounds and finishing positions.
const { repaired, removed, unlinkedStructureIds } = engine.repairMalformedLinks({
drawId, // required
force, // optional - proceed although participants arrived through a link the repair changes
});
What happens to each entry:
| condition | action | reason |
|---|---|---|
not an object (null, a string, an array) | removed | NOT_A_LINK |
source or target structure not in the draw | removed | DANGLING_LINK |
WINNER/LOSER link with no source.roundNumber, exactly one round fits | source.roundNumber restored | (in repaired) |
WINNER/LOSER link with no source.roundNumber, several rounds fit | removed, with candidates | AMBIGUOUS_SOURCE_ROUND |
WINNER/LOSER link with no source.roundNumber, no round fits | removed | NO_SOURCE_ROUND |
How the round is found, by the reasoning the factory uses to derive a source round from a structure:
WINNER: the source structure's final round. The winners of every earlier round advance within the structure.LOSER: the source round whose matchUp count equals the number of positions the link supplies to its target round: the target round's fed positions (2·m(T) − m(T−1)) less those the round's other links supply. A round another well-formed link of the same type already directs from the same structure is not a candidate. Two malformed links that would be restored to the same round are both removed.
Measured over every generated draw type that carries WINNER or LOSER links (draw sizes 4 to 64, fresh and completed, qualifying and added playoff structures): 556 of 556 links stripped of their round one at a time were restored to the round generation wrote. Rounds become ambiguous when several malformed links compete for rounds with equal matchUp counts, such as DOUBLE_ELIMINATION Main rounds 3 and 4 when both of their LOSER links are malformed.
Refusals, before any write. The call is refused with DRAW_POSITION_ASSIGNED, and the draw is left unchanged, when a participant ARRIVED through a link the repair would change: the participant holds a position the link supplies in its target and has a decided matchUp in its source. context.arrived names them, and context.repaired / context.removed show what the repair would have done. Pass force: true to proceed.
The repair is composed on a copy first, so an error leaves the record as it was, without a rollback. On success, the stored winnerMatchUpId / loserMatchUpId of the changed links are cleared and rebuilt with addGoesTo (once no malformed link remains). A removed link's edges are cleared, as removeStructure clears them, and finishingPositionRange is left as it is.
Removing the only link into a structure leaves it unlinked, which getDrawData refuses. Such structures are listed in unlinkedStructureIds; tools.repairDrawLinks can then add a link and report how much it had to guess.
repairMalformedLink
Repairs or removes ONE malformed link, chosen by its structures. sourceRoundNumber is the operator's answer where repairMalformedLinks found no round or several: it must be a round of the source structure that no other link of the same type directs. Otherwise the round is inferred as for repairMalformedLinks. Returns the same report, and refuses in the same cases.
const { repaired, removed } = engine.repairMalformedLink({
drawId, // required
sourceStructureId, // sourceStructureId and/or targetStructureId required
targetStructureId,
linkType, // optional - where the two structures are joined by more than one link
sourceRoundNumber, // optional - the round to restore
force, // optional
});
The selection must match exactly one malformed link (INVALID_VALUES otherwise). If other malformed links remain in the draw, the edges are rebuilt once they are repaired.
resetDrawDefinition
Resets a drawDefinition to its initial state. For all matchUps: removes scores, extensions, and notes; restores drawPositions for rounds beyond round 1 (removes progressed positions). For structures that are not QUALIFYING or MAIN stageSequence 1: clears participant positionAssignments (preserving byes) and seed assignments. Optionally removes scheduling timeItems.
engine.resetDrawDefinition({
drawId, // required — resolved to drawDefinition by engine
removeScheduling, // optional boolean — also remove scheduling timeItems (date, time, court, venue)
});
resetQualifyingStructure
engine.resetQualifyingStructure({ structureId, drawId });
A round robin qualifying structure is read through its groups (7.7.0): the reset is refused when a group
matchUp holds a score, every group matchUp is notified, and the container is emptied. The same reading
applies to removeStructure, getTournamentInfo, generateVoluntaryConsolation and draw generation
after a round robin qualifying-only draw, which no longer deletes the qualifying structure.
--
resetVoluntaryConsolationStructure
engine.resetVoluntaryConsolationStructure({
resetEntries, // optional - remove all { entryStage: VOLUNTARY_CONSOLATION }
drawId,
});
resetQualifyingStructure (with options)
engine.resetQualifyingStructure({
drawId,
structureId,
});
setDrawParticipantRepresentativeIds
Set the participantIds of participants in the draw who are representing players by observing the creation of the draw.
engine.setDrawParticipantRepresentativeIds({
representativeParticipantIds,
drawId,
});
setPositionAssignments
Intended to be used in conjunction with automatedPlayoffPositioning in deployments where a client instance gets the positioning which is then set on both the client and the server, to ensure that both client and server are identical. If automatedPlayoffPositioning is invoked on both client and server independently then it is likely that the positioning on client and server will be different.
// executed only on the client
const { structurePositionAssignments } = engine.automatedPlayoffPositioning({
applyPositioning: false, // instructs factory engine to only return values, not apply them
structureId,
drawId,
});
// executed on both client and server
result = engine.setPositionAssignments({
structurePositionAssignments,
drawId,
});
Since 7.7.0 a qualifier in the submitted assignments is placed in the structure's assignments (the caller's array is left as given); before, the qualifier branch marked the submitted array and the engine reported success with no qualifier in the structure.
Each entry of structurePositionAssignments may carry seedAssignments, as returned by automatedPositioning
with applyPositioning: false; they replace the structure's seeds before its positions are set, so a structure seeded
when it was positioned is replayed whole.
const { positionAssignments, seedAssignments } = engine.automatedPositioning({
applyPositioning: false,
seedsCount,
structureId,
drawId,
});
engine.setPositionAssignments({
structurePositionAssignments: [{ structureId, positionAssignments, seedAssignments }],
drawId,
});
setSubOrder
Used to order ROUND_ROBIN participants when finishing position ties cannot be broken algorithmically. Assigns a subOrder value to a participant within a structure by drawPosition.
engine.setSubOrder({
drawPosition: 1,
subOrder: 2,
structureId,
drawId,
});
setStructureOrder
Sets the display order of structures within a draw.
engine.setStructureOrder({
drawId, // required
structureId, // required
orderNumber, // required - new order position
});
Purpose: Control structure display sequence.
shiftAdHocRounds
Move roundNumber to targetRoundNumber.
tournamentEngine.shiftAdHocRounds({
targetRoundNumber,
roundNumber,
structureId,
drawId,
});
swapAdHocRounds
Swap roundNumbers. Must provide an array of two valid roundNumbers.
tournamentEngine.swapAdHocRounds({
roundNumbers: [2, 4],
structureId,
drawId,
});
swapDrawPositionAssignments
Swaps the participantIds of two drawPositions. A placed qualifier's qualifier flag travels with it to its new position, including when it is swapped with a BYE; two unfilled qualifier seats are not swapped (there is nothing to move).
engine.swapDrawPositionAssignments({
drawPositions,
structureId,
drawId,
});
updateTeamLineUp
8.0.0 engine-removal candidate. This 7.x route remains available pending review. The full reference has moved to updateTeamLineUp. Package-export status is a separate decision.
withdrawParticipantAtDrawPosition
Thin wrapper around removeDrawPositionAssignment. This method is included in validActions for positionActions.
engine.withdrawParticipantAtDrawPosition({
entryStatus = WITHDRAWN,
replaceWithBye, // optional
drawDefinition,
drawPosition,
structureId,
destroyPair, // optional - decompose PAIR participant into UNPAIRED participants
});
luckyDrawAdvancement
Advances participants from a completed round into the next round of a LUCKY_DRAW. For pre-feed rounds, advances all winners plus the selected lucky loser. For non-pre-feed rounds, advances all winners without loser selection.
Works by assigning virtual drawPositions to next-round matchUps and creating corresponding positionAssignment entries, enabling the standard scoring flow for those matchUps.
Every check runs before anything is written; on error the draw is unchanged. That includes the losers not selected
as lucky losers: when a LOSER link from the round targets a structure that does not exist, the call returns
INVALID_VALUES and advances no one.
engine.luckyDrawAdvancement({
roundNumber, // required — round number that has just completed
drawId, // required — resolved to drawDefinition by engine
structureId, // optional — target structure within the draw
participantId, // optional — the selected lucky loser (required for pre-feed rounds)
});
hasLuckyRounds
8.0.0 engine-removal candidate. This 7.x route remains available pending review. The full reference has moved to hasLuckyRounds. Package-export status is a separate decision.
getLuckyDrawRoundStatus
Returns detailed status for each round of a LUCKY_DRAW, including completion state, advancing winners, eligible losers with margin data, and whether the round needs a lucky loser selection.
const { rounds, consolidationLinks } = engine.getLuckyDrawRoundStatus({
drawId, // required
structureId, // optional — defaults to first LUCKY_DRAW structure
});
Returns: rounds is an array of round info objects containing roundNumber, isComplete, isPreFeedRound, needsLuckySelection, advancingWinners, and eligibleLosers (with margin/ratio data for ranking losers). consolidationLinks describes any LOSER links from the structure.
addDrawDefinitionExtension
Adds an extension (custom metadata) to a drawDefinition.
engine.addDrawDefinitionExtension({
extension, // required — { name, value } extension object
drawId, // resolved via engine context
creationTime, // optional boolean — stamp creation time on extension
});
getRotatingPartnerRoundPreview
Returns individual side memberships, the saved scoring contract and seed for the next logical round without creating participants. See Competition Profile.
const preview = engine.getRotatingPartnerRoundPreview({ drawId, structureId, roundNumber });
generateRotatingPartnerRound
Atomically reuses/creates PAIR participants, inserts matchUps and saves applied-round provenance. Pass the approved preview pairings, scoring contract and a unique request ID; repeating the same successful request is idempotent. Americano rotation and all Mexicano rounds are supported. Later Mexicano rounds require every earlier result to be resolved and retain the source standings snapshot.
const result = engine.generateRotatingPartnerRound({
drawId,
structureId, // optional for a single-structure draw
roundNumber,
requestId,
expectedPairings: preview.round,
expectedScoringContract: preview.scoringContract,
});
Ordinary doubles draw admission
addDrawEntries refuses accepted INDIVIDUAL entrants in ordinary DOUBLES events with INVALID_ENTRIES, without changing the record. Submit PAIR participant IDs for playable entrants. Individual placeholders may use UNGROUPED or UNPAIRED; they are not accepted doubles competitors. Rotating-partner draws explicitly configured by competitionProfile are the exception: their draw-level roster accepts individuals while event-level entries remain ungrouped.
This adds a refusal to the public API. Consumers that previously submitted individuals as DIRECT_ACCEPTANCE must create/select a PAIR or use an ungrouped status. TMX's unified entries overlay offers “Add to draw” only for accepted or qualifying selections, excluding the ungrouped segment.