Skip to main content

Competition Profile

drawDefinition.competitionProfile is a first-class, versioned configuration attribute. It describes the competition format; matchUps, scores and applied-round provenance live separately. It is separate from competitionFormat, which describes how a sport is played.

Configure a rotating-partner draw​

Create an AD_HOC doubles draw with no matchUps, then set its profile:

const result = tournamentEngine.setCompetitionProfile({
drawId,
competitionProfile: {
version: 1,
format: 'MEXICANO',
entrantScope: 'INDIVIDUAL',
matchUpType: 'DOUBLES',
scoring: { combinedPointTotal: 32 },
standings: { metric: 'SIDE_POINTS', attribution: 'EACH_INDIVIDUAL' },
pairing: {
seed: baseSeed,
algorithmVersion: 1,
groupBy: 'ADJACENT_STANDINGS',
partners: 'FIRST_FOURTH_SECOND_THIRD',
},
completion: { kind: 'ROUND_COUNT', rounds: 7 },
},
});

For Americano, use format: 'AMERICANO', pairing: { seed, algorithmVersion: 1 } and completion: { kind: 'PARTNERSHIP_COVERAGE' }. Store the Americano generator's seedUsed or Mexicano's baseSeed. Seeds must be safe integers; combined point totals and round counts must be positive safe integers. Version and pairing algorithm version are currently 1.

Tie resolution belongs to the governing scoring policy, rather than the profile. Profiles store configuration; individual admission and round application use the APIs below. Manual/live fixed-total scoring and individual standings use the historical contracts saved with applied rounds.

Read, change and remove​

const { competitionProfile } = tournamentEngine.getCompetitionProfile({ drawId });
const result = tournamentEngine.removeCompetitionProfile({ drawId });

Queries and writes copy profile data, so changing caller objects does not change the record. An absent profile returns success with an undefined profile. Mutations emit the ordinary draw modification notice and the containing tournament record can be saved by its consumer. The attribute is first-class in every schema write mode; no extension migration is involved.

Once any matchUps exist in the draw or its nested structures, attaching, changing or removing the profile returns EXISTING_MATCHUPS. Reapplying an identical profile is an idempotent success. This protects already-generated rounds from being reinterpreted. Future correction and configuration-amendment workflows require their own explicit contracts.

Ladder configuration and state​

A LADDER draw accepts { version: 1, format: 'LADDER' }. This identifies its format without changing existing ladder policy resolution. Challenge eligibility, movement and validation rules remain in the inherited ladder policy.

Rank standings are stored in structure position assignments; rating standings are derived from participant rating scales. Challenges and result attestations use matchUps and their timeItems, while dated participant scale items preserve standing history. Neither those records nor mutable standings belong in a policy or this configuration attribute. A later ladder normalization can add explicit configuration fields without copying its existing state here.

Governing scoring policy​

getRotatingPartnerScoringPolicy({ drawId, structureId?, selectedVariant? }) returns the resolved contract, scoringPolicy and selectionLocked. It reads the existing scoring policy's rotatingPartners.AMERICANO or rotatingPartners.MEXICANO section. Policy precedence is structure → draw → event → tournament; a nearer scoring policy replaces the whole scoring policy, rather than merging nested fields. Missing format rules use the engine default; malformed rules fail.

const policyDefinitions = {
scoring: {
rotatingPartners: {
AMERICANO: {
defaultVariant: { tieResolution: 'ALLOW' },
permittedVariants: [{ tieResolution: 'ALLOW' }, { tieResolution: 'DECIDING_POINT' }],
permittedPointTotals: [24, 32],
},
},
},
};
tournamentEngine.attachPolicies({ drawId, policyDefinitions });
const result = tournamentEngine.getRotatingPartnerScoringPolicy({ drawId });

A singleton permitted list locks the organizer's choice. Otherwise the selected variant must match one of the permitted variants exactly. WIN_BY_MARGIN requires a safe-integer winningMargin of at least two; other variants prohibit a margin. Point totals must be positive safe integers and, when restricted, belong to permittedPointTotals.

The engine default permits ALLOW, DECIDING_POINT, and WIN_BY_MARGIN with margin two, defaulting to ALLOW. This query validates and previews configuration; use the persistence mutation below to save a selection. Neither method changes manual/live scoring yet. Resolved rules must be captured when applying a round. Separate deciding phases remain open work; inline extra-point attribution and individual standings are supported by the rotating-partner tally policy.

Persisting the scoring choice​

Call setRotatingPartnerScoring({ drawId, selectedVariant? }) before generating matchUps. Omitting selectedVariant saves the approved policy default. The mutation stores the choice in competitionProfile.scoring.selectedVariant; point total and selected variant together define the resolved match contract. Direct profile writes validate these choices against the governing policy.

getRotatingPartnerScoringContract({ drawId }) reads that saved contract without consulting current policies. It refuses an unconfigured profile. This is the query historical scoring must use; the policy query remains the preview of current governing rules. Changing inherited policies cannot rewrite the saved contract. Repeating an identical write succeeds without effect; changing or removing the profile is refused once any matchUps exist. The new mutation also respects DRAWS locks.

The draw-level match contract is captured in each applied round. Future-round amendments, separate deciding phases and tally rules remain outstanding.

Individual entrants and partnership sides​

For a configured Americano or Mexicano draw, pass drawId to addEventEntries to enter individual competitors into its doubles event as UNGROUPED (or explicitly UNPAIRED) and into the rotating draw with an accepted status. DIRECT_ACCEPTANCE belongs only to the rotating draw, never the doubles event. Standard doubles entry behavior remains unchanged when no rotating draw is targeted. Gender/category checks remain in force. An invalid mixed batch is refused before event or draw entry writes; PAIRs, unknown IDs and non-competitor roles are refused. checkValidEntries recognizes the individual roster only in the targeted rotating draw. Event validation uses the existing ungrouped-status convention. Ordinary draws cannot accept these individuals as doubles competitors; existing loose, ungrouped AD_HOC entries remain supported. Deleting the rotating draw retains valid ungrouped event entries. Remove its individual draw entries before removing its competitionProfile.

Match sides remain PAIR participants. addAdHocMatchUps accepts partnerships outside the draw entry list when each has two distinct individual entrants. It requires positive logical round numbers and refuses any individual appearing twice within a round, including matchUps already inserted. Repeating people across different rounds is permitted. These insertion guards also apply to the atomic round API below.

Preview and apply a round​

const preview = tournamentEngine.getRotatingPartnerRoundPreview({
drawId,
structureId, // optional when the draw has exactly one structure
roundNumber: 1,
});
if (!preview.error) {
const result = tournamentEngine.generateRotatingPartnerRound({
drawId,
structureId: preview.structureId,
roundNumber: 1,
requestId, // unique application identifier; retain for retries
expectedPairings: preview.round,
expectedScoringContract: preview.scoringContract,
});
}

Preview creates no participants or matchUps. Application recomputes the preview, refuses changed approved pairings or scoring rules and stages PAIR creation and match insertion before committing. Existing partnerships are reused; new participants and matchUps have IDs derived from the draw, request and round for server/client replay. Successful retries with the same request return the stored round without additional writes. Changed request arguments, removed matches or edited PAIR membership are refused.

Applied provenance lives in drawDefinition.competitionRounds, separate from configuration. Each round record captures side memberships, matchUp IDs, algorithm version, base/round seeds and scoring/tally contracts. The frozen roster is stored once in drawDefinition.competitionRoster; Mexicano records also capture the source standings snapshot and round cutoff. No freshness token is persisted. Do not edit PAIR memberships after application.

Americano supports sequential application of its complete saved rotation. Mexicano starts from zero points and uses authoritative individual standings for subsequent rounds. Every prior result must be settled under its saved tally contract before the next Mexicano round can be previewed. The roster must stay fixed after application. The round API honours DRAWS locks and participant locks when adding PAIRs. Court allocation uses existing scheduling methods. Each matchUp carries a fixed-total matchUpFormat derived from the saved round scoring contract. Applied round formats cannot be changed through matchUp, structure, draw or event scope. Scheduling edits and unrelated PAIR additions do not invalidate approved pairings.

Individual standings and tally policies are documented in Rotating Partner Pairing.