tods-competition-factory 7.6.0 → 7.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/esm/acquire/findStructure.mjs +4 -2
- package/dist/esm/acquire/structureMembers.mjs +11 -0
- package/dist/esm/assemblies/engines/scoring/ScoringEngine.mjs +82 -32
- package/dist/esm/assemblies/generators/drawDefinitions/autoSeeding.mjs +4 -2
- package/dist/esm/assemblies/generators/drawDefinitions/drawTypes/adHoc/drawMatic/drawMatic.mjs +1 -3
- package/dist/esm/assemblies/generators/drawDefinitions/drawTypes/adHoc/drawMatic/generateDrawMaticRound.mjs +5 -4
- package/dist/esm/assemblies/generators/drawDefinitions/drawTypes/adHoc/getAvailableMatchUpsCount.mjs +4 -3
- package/dist/esm/assemblies/generators/drawDefinitions/drawTypes/adHoc/swiss/generateSwissRound.mjs +3 -2
- package/dist/esm/assemblies/generators/drawDefinitions/drawTypes/generateVoluntaryConsolation.mjs +2 -1
- package/dist/esm/assemblies/generators/drawDefinitions/drawTypes/luckyDraw.mjs +3 -1
- package/dist/esm/assemblies/generators/drawDefinitions/generateAndPopulatePlayoffStructures.mjs +43 -15
- package/dist/esm/assemblies/generators/drawDefinitions/generateDrawDefinition/generateNewDrawDefinition.mjs +24 -0
- package/dist/esm/assemblies/generators/drawDefinitions/generateDrawDefinition/prepareStage.mjs +8 -3
- package/dist/esm/assemblies/generators/drawDefinitions/generateDrawDefinition/qualifyingGeneration.mjs +1 -0
- package/dist/esm/assemblies/generators/drawDefinitions/generateDrawDefinition/setUpDrawGeneration.mjs +2 -1
- package/dist/esm/assemblies/generators/drawDefinitions/generateDrawStructuresAndLinks.mjs +1 -1
- package/dist/esm/assemblies/generators/drawDefinitions/generateSeedingScaleItems.mjs +2 -0
- package/dist/esm/assemblies/generators/mocks/applyScenarioProfile.mjs +2 -2
- package/dist/esm/assemblies/generators/mocks/generateEventWithDraw.mjs +3 -2
- package/dist/esm/assemblies/generators/mocks/generateTournamentRecord.mjs +1 -1
- package/dist/esm/assemblies/generators/mocks/processLeagueProfiles.mjs +1 -1
- package/dist/esm/assemblies/generators/tournamentRecords/createTournamentRecord.mjs +16 -1
- package/dist/esm/functions/declaration/recordStore.mjs +1 -1
- package/dist/esm/functions/sorters/structureSort.mjs +15 -4
- package/dist/esm/mutate/drawDefinitions/addDrawDefinition.mjs +1 -1
- package/dist/esm/mutate/drawDefinitions/addDrawEntries.mjs +1 -1
- package/dist/esm/mutate/drawDefinitions/attachStructures.mjs +7 -3
- package/dist/esm/mutate/drawDefinitions/automatedPlayoffPositioning.mjs +3 -0
- package/dist/esm/mutate/drawDefinitions/automatedPositioning.mjs +19 -15
- package/dist/esm/mutate/drawDefinitions/entryGovernor/seedAssignment.mjs +1 -1
- package/dist/esm/mutate/drawDefinitions/luckyDrawAdvancement.mjs +10 -9
- package/dist/esm/mutate/drawDefinitions/matchUpGovernor/attemptToSetWinningSide.mjs +8 -2
- package/dist/esm/mutate/drawDefinitions/matchUpGovernor/noDownstreamDependencies.mjs +2 -0
- package/dist/esm/mutate/drawDefinitions/matchUpGovernor/placeQualifier.mjs +6 -4
- package/dist/esm/mutate/drawDefinitions/matchUpGovernor/recordSourceSideProvenance.mjs +37 -7
- package/dist/esm/mutate/drawDefinitions/matchUpGovernor/removeDoubleExit.mjs +85 -19
- package/dist/esm/mutate/drawDefinitions/matchUpGovernor/removeQualifier.mjs +42 -44
- package/dist/esm/mutate/drawDefinitions/matchUpGovernor/replaceQualifier.mjs +43 -45
- package/dist/esm/mutate/drawDefinitions/matchUpGovernor/unwindDualDoubleExit.mjs +1 -1
- package/dist/esm/mutate/drawDefinitions/modifyDrawDefinition.mjs +6 -5
- package/dist/esm/mutate/drawDefinitions/positionGovernor/addPositionActionTelemetry.mjs +1 -1
- package/dist/esm/mutate/drawDefinitions/positionGovernor/byePositioning/positionByes.mjs +11 -4
- package/dist/esm/mutate/drawDefinitions/positionGovernor/doubleExitAdvancement.mjs +238 -85
- package/dist/esm/mutate/drawDefinitions/positionGovernor/initializeSeedAssignments.mjs +2 -1
- package/dist/esm/mutate/drawDefinitions/positionGovernor/setPositionAssignments.mjs +3 -4
- package/dist/esm/mutate/drawDefinitions/positionPagePlayoff.mjs +49 -0
- package/dist/esm/mutate/drawDefinitions/pruneDrawDefinition.mjs +5 -2
- package/dist/esm/mutate/drawDefinitions/remapDrawDefinitionMatchUpIds.mjs +7 -5
- package/dist/esm/mutate/drawDefinitions/resetDrawDefinition.mjs +2 -1
- package/dist/esm/mutate/drawDefinitions/resetQualifyingStructure.mjs +12 -4
- package/dist/esm/mutate/drawDefinitions/structureGovernor/adHocRounds/checkRoundsArgs.mjs +2 -1
- package/dist/esm/mutate/drawDefinitions/structureGovernor/removeStructure.mjs +13 -4
- package/dist/esm/mutate/drawDefinitions/structureGovernor/renameStructures.mjs +2 -1
- package/dist/esm/mutate/events/deleteDrawDefinitions.mjs +1 -1
- package/dist/esm/mutate/events/modifyEvent.mjs +1 -2
- package/dist/esm/mutate/events/modifyEventPublishStatus.mjs +3 -1
- package/dist/esm/mutate/ladder/addLadderParticipant.mjs +4 -2
- package/dist/esm/mutate/ladder/applyLadderMovement.mjs +3 -2
- package/dist/esm/mutate/ladder/applyLapseConsequence.mjs +2 -1
- package/dist/esm/mutate/ladder/issueChallenge.mjs +5 -3
- package/dist/esm/mutate/ladder/mirrorStandingToScale.mjs +1 -1
- package/dist/esm/mutate/ladder/refreshLadderRatings.mjs +2 -1
- package/dist/esm/mutate/ladder/removeLadderParticipant.mjs +7 -19
- package/dist/esm/mutate/ladder/reportResult.mjs +5 -3
- package/dist/esm/mutate/ladder/respondToChallenge.mjs +4 -2
- package/dist/esm/mutate/matchUps/drawPositions/adHocPositionSwap.mjs +2 -1
- package/dist/esm/mutate/matchUps/drawPositions/assignDrawPositionBye.mjs +128 -15
- package/dist/esm/mutate/matchUps/drawPositions/assignMatchUpSideParticipant.mjs +3 -2
- package/dist/esm/mutate/matchUps/drawPositions/directLoser.mjs +10 -6
- package/dist/esm/mutate/matchUps/drawPositions/directParticipants.mjs +4 -3
- package/dist/esm/mutate/matchUps/drawPositions/drawPositionPlacement.mjs +54 -4
- package/dist/esm/mutate/matchUps/drawPositions/normalizeDrawPositions.mjs +1 -6
- package/dist/esm/mutate/matchUps/drawPositions/positionClear.mjs +146 -33
- package/dist/esm/mutate/matchUps/drawPositions/positionQualifiers.mjs +4 -3
- package/dist/esm/mutate/matchUps/drawPositions/positionUnseededParticipants.mjs +2 -1
- package/dist/esm/mutate/matchUps/drawPositions/propagateUnfillableLoserBye.mjs +10 -5
- package/dist/esm/mutate/matchUps/drawPositions/relabelLoserExit.mjs +113 -20
- package/dist/esm/mutate/matchUps/drawPositions/releaseAdvancedDrawPosition.mjs +21 -5
- package/dist/esm/mutate/matchUps/drawPositions/releaseLinkedWinnerAdvancement.mjs +44 -9
- package/dist/esm/mutate/matchUps/drawPositions/removeDirectedParticipants.mjs +21 -12
- package/dist/esm/mutate/matchUps/drawPositions/removeOnwardLoserPlacements.mjs +3 -3
- package/dist/esm/mutate/matchUps/drawPositions/removeSubsequentRoundsParticipant.mjs +35 -10
- package/dist/esm/mutate/matchUps/drawPositions/setMatchUpDrawPositions.mjs +61 -0
- package/dist/esm/mutate/matchUps/drawPositions/swapWinnerLoser.mjs +28 -10
- package/dist/esm/mutate/matchUps/lineUps/applyLineUps.mjs +2 -2
- package/dist/esm/mutate/matchUps/lineUps/assignTieMatchUpParticipant.mjs +3 -2
- package/dist/esm/mutate/matchUps/lineUps/replaceTieMatchUpParticipant.mjs +6 -3
- package/dist/esm/mutate/matchUps/matchUpStatus/applyWithdrawnExits.mjs +28 -3
- package/dist/esm/mutate/matchUps/matchUpStatus/reconcileDecider.mjs +7 -2
- package/dist/esm/mutate/matchUps/matchUpStatus/reconcileLinkAdvancements.mjs +37 -0
- package/dist/esm/mutate/matchUps/matchUpStatus/reconcileStaleExitOrigins.mjs +83 -6
- package/dist/esm/mutate/matchUps/matchUpStatus/setMatchUpState.mjs +13 -12
- package/dist/esm/mutate/matchUps/matchUpStatus/setMatchUpStatus.mjs +27 -15
- package/dist/esm/mutate/matchUps/matchUpStatus/settleRederivedDoubleExits.mjs +60 -3
- package/dist/esm/mutate/matchUps/matchUpStatus/sideExitProvenance.mjs +45 -11
- package/dist/esm/mutate/matchUps/outcome/decide.mjs +39 -7
- package/dist/esm/mutate/matchUps/outcome/direction.mjs +15 -0
- package/dist/esm/mutate/matchUps/outcome/refusals.mjs +3 -0
- package/dist/esm/mutate/matchUps/outcome/view.mjs +45 -26
- package/dist/esm/mutate/matchUps/resetScorecard.mjs +5 -8
- package/dist/esm/mutate/matchUps/schedule/clearMatchUpSchedule.mjs +1 -1
- package/dist/esm/mutate/matchUps/schedule/scheduleItems/scheduleItems.mjs +2 -2
- package/dist/esm/mutate/officiating/transitionEvaluationStatus.mjs +1 -1
- package/dist/esm/mutate/publishing/unPublishEvent.mjs +5 -3
- package/dist/esm/mutate/structures/removeRoundMatchUps.mjs +2 -1
- package/dist/esm/mutate/structures/setSubOrder.mjs +4 -3
- package/dist/esm/mutate/structures/updateParticipantResults.mjs +4 -3
- package/dist/esm/mutate/timeItems/publishOrderOfPlay.mjs +1 -0
- package/dist/esm/mutate/timeItems/publishParticipants.mjs +1 -0
- package/dist/esm/mutate/tournaments/migrateTournamentRecord.mjs +17 -4
- package/dist/esm/mutate/tournaments/setTournamentDates.mjs +1 -1
- package/dist/esm/mutate/venues/courtAvailability.mjs +1 -1
- package/dist/esm/package.json.mjs +1 -1
- package/dist/esm/query/drawDefinition/avoidance/getSwapOptions.mjs +4 -1
- package/dist/esm/query/drawDefinition/getByeCrossings.mjs +49 -0
- package/dist/esm/query/drawDefinition/getByesData.mjs +4 -3
- package/dist/esm/query/drawDefinition/getContainedStructures.mjs +5 -2
- package/dist/esm/query/drawDefinition/getDrawData.mjs +6 -2
- package/dist/esm/query/drawDefinition/getDrawInconsistencies.mjs +5 -4
- package/dist/esm/query/drawDefinition/getLuckyDrawRoundStatus.mjs +7 -5
- package/dist/esm/query/drawDefinition/getMatchUpFormatVariance.mjs +5 -4
- package/dist/esm/query/drawDefinition/getSourceRounds.mjs +1 -1
- package/dist/esm/query/drawDefinition/getStageDrawPositions.mjs +3 -3
- package/dist/esm/query/drawDefinition/getStructureCompleteness.mjs +5 -4
- package/dist/esm/query/drawDefinition/getStructureInconsistencies.mjs +105 -3
- package/dist/esm/query/drawDefinition/getUnearnedLinkAdvancements.mjs +44 -0
- package/dist/esm/query/drawDefinition/isActiveDownstream.mjs +27 -11
- package/dist/esm/query/drawDefinition/isLucky.mjs +5 -4
- package/dist/esm/query/drawDefinition/linkGetter.mjs +7 -8
- package/dist/esm/query/drawDefinition/matchUpActions/adHocMatchUpActions.mjs +3 -2
- package/dist/esm/query/drawDefinition/matchUpActions/collectionMatchUpActions.mjs +3 -3
- package/dist/esm/query/drawDefinition/matchUpActions/matchUpActions.mjs +9 -5
- package/dist/esm/query/drawDefinition/positionActions/getValidAlternatesAction.mjs +4 -1
- package/dist/esm/query/drawDefinition/positionActions/getValidLuckyLoserAction.mjs +4 -1
- package/dist/esm/query/drawDefinition/processAccessors.mjs +1 -1
- package/dist/esm/query/drawDefinition/seedGetter.mjs +2 -1
- package/dist/esm/query/drawDefinition/stageGetter.mjs +3 -2
- package/dist/esm/query/drawDefinitions/swiss/getSwissChart.mjs +2 -1
- package/dist/esm/query/drawDefinitions/swiss/getSwissStandings.mjs +2 -1
- package/dist/esm/query/event/extractEventInfo.mjs +3 -1
- package/dist/esm/query/event/getEventInconsistencies.mjs +5 -4
- package/dist/esm/query/ladder/getChallengeState.mjs +10 -2
- package/dist/esm/query/ladder/getLadderStanding.mjs +2 -1
- package/dist/esm/query/ladder/getLapses.mjs +6 -4
- package/dist/esm/query/ladder/getResultAttestation.mjs +3 -2
- package/dist/esm/query/ladder/resolveLadderContext.mjs +3 -1
- package/dist/esm/query/matchUp/addUpcomingMatchUps.mjs +2 -0
- package/dist/esm/query/matchUp/analyzeScore.mjs +1 -1
- package/dist/esm/query/matchUp/positionTargets.mjs +37 -14
- package/dist/esm/query/matchUp/retainScoreForFormat.mjs +1 -1
- package/dist/esm/query/matchUps/addGoesTo.mjs +14 -10
- package/dist/esm/query/matchUps/drawMatchUps.mjs +9 -7
- package/dist/esm/query/matchUps/getAllStructureMatchUps.mjs +2 -1
- package/dist/esm/query/matchUps/getDownstreamStructureIds.mjs +4 -1
- package/dist/esm/query/matchUps/getDrawPositionSides.mjs +6 -4
- package/dist/esm/query/matchUps/getMatchUpDependencies.mjs +12 -7
- package/dist/esm/query/matchUps/getMatchUpsMap.mjs +5 -2
- package/dist/esm/query/matchUps/getRoundContextProfile.mjs +2 -1
- package/dist/esm/query/matchUps/getTargetMatchUp.mjs +7 -1
- package/dist/esm/query/matchUps/scheduling/getMatchUpReadiness.mjs +12 -4
- package/dist/esm/query/matchUps/scheduling/getParticipantRest.mjs +39 -3
- package/dist/esm/query/matchUps/scheduling/getScheduledRoundsDetails.mjs +6 -2
- package/dist/esm/query/officiating/getMatchUpOfficialConflicts.mjs +1 -1
- package/dist/esm/query/officiating/getOfficialEligibility.mjs +1 -1
- package/dist/esm/query/participants/getParticipantEntries.mjs +4 -3
- package/dist/esm/query/participants/getParticipantSchedules.mjs +1 -1
- package/dist/esm/query/readModel/cast.mjs +2 -1
- package/dist/esm/query/readModel/progressionEdges.mjs +3 -2
- package/dist/esm/query/readModel/readModelRows.mjs +9 -2
- package/dist/esm/query/reports/recoveryTimeline.mjs +5 -5
- package/dist/esm/query/reports/wrappers/wrapCallTimingVarianceReport.mjs +2 -1
- package/dist/esm/query/reports/wrappers/wrapCompetitivenessReport.mjs +2 -1
- package/dist/esm/query/reports/wrappers/wrapMatchResultsReport.mjs +2 -1
- package/dist/esm/query/reports/wrappers/wrapMatchUpStatusReport.mjs +2 -1
- package/dist/esm/query/reports/wrappers/wrapParticipantResultsReport.mjs +4 -3
- package/dist/esm/query/reports/wrappers/wrapRecoveryTimeReport.mjs +1 -1
- package/dist/esm/query/scales/getAggregateTeamResults.mjs +1 -1
- package/dist/esm/query/structure/getStructureSeedAssignments.mjs +2 -1
- package/dist/esm/query/tournaments/analyzeDraws.mjs +4 -1
- package/dist/esm/query/tournaments/getTournamentInconsistencies.mjs +1 -1
- package/dist/esm/query/tournaments/getTournamentInfo.mjs +15 -2
- package/dist/esm/validators/scoring/mcpParser.mjs +37 -2
- package/dist/esm/validators/scoring/mcpValidator.mjs +132 -22
- package/dist/esm/validators/validatePlayoffGroups.mjs +1 -1
- package/dist/esm/validators/validateSchedulingProfile.mjs +7 -3
- package/dist/schema/tournament.schema.json +16 -1
- package/dist/tods-competition-factory.d.cts +309 -142
- package/dist/tods-competition-factory.d.mts +309 -142
- package/dist/tods-competition-factory.d.ts +309 -142
- package/dist/tods-competition-factory.development.cjs.js +3809 -2054
- package/dist/tods-competition-factory.development.cjs.js.map +1 -1
- package/dist/tods-competition-factory.production.cjs.min.js +1 -1
- package/dist/tods-competition-factory.production.cjs.min.js.map +1 -1
- package/package.json +27 -23
package/README.md
CHANGED
|
@@ -142,7 +142,7 @@ Full documentation with interactive examples: **[courthive.github.io/competition
|
|
|
142
142
|
|
|
143
143
|
## Testing
|
|
144
144
|
|
|
145
|
-
**15,
|
|
145
|
+
**15,800+ tests** covering draw generation and exit propagation, scheduling, scoring, participants and entries, team competition, publishing and embargo, ranking points and ratings, officiating and sanctioning.
|
|
146
146
|
|
|
147
147
|
Beyond conventional unit and integration tests, the suite includes relational property suites (do/undo, idempotence, monotonicity), agreement oracles, and an at-scale randomized sweep with delta-debugging for exit propagation — added because full branch coverage of a propagation guard proved compatible with hundreds of wrong answers.
|
|
148
148
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { checkRequiredParameters } from '../helpers/parameters/checkRequiredParameters.mjs';
|
|
2
2
|
import { firstClassOrExtension } from './firstClassOrExtension.mjs';
|
|
3
3
|
import { structureSort } from '../functions/sorters/structureSort.mjs';
|
|
4
|
+
import { structuresOf } from './structureMembers.mjs';
|
|
4
5
|
import { MISSING_DRAW_DEFINITION, MISSING_STRUCTURES, STRUCTURE_NOT_FOUND } from '../constants/errorConditionConstants.mjs';
|
|
5
6
|
import { STRUCTURE_ID, DRAW_DEFINITION } from '../constants/attributeConstants.mjs';
|
|
6
7
|
import { validStages, ITEM } from '../constants/drawDefinitionConstants.mjs';
|
|
@@ -13,13 +14,14 @@ function findStructure(params) {
|
|
|
13
14
|
const { drawDefinition, structureId } = params;
|
|
14
15
|
const { structures } = getDrawStructures({ drawDefinition });
|
|
15
16
|
const allStructures = structures?.flatMap((structure) => {
|
|
16
|
-
|
|
17
|
+
const contained = structuresOf(structure);
|
|
18
|
+
return contained ? [...contained].concat(structure) : structure;
|
|
17
19
|
});
|
|
18
20
|
const structure = allStructures?.find((structure) => structure.structureId === structureId);
|
|
19
21
|
if (!structure)
|
|
20
22
|
return { error: STRUCTURE_NOT_FOUND };
|
|
21
23
|
const containingStructure = structure.structureType === ITEM
|
|
22
|
-
? allStructures?.find((s) => s
|
|
24
|
+
? allStructures?.find((s) => structuresOf(s)?.some((s) => s.structureId === structureId))
|
|
23
25
|
: undefined;
|
|
24
26
|
return { structure, containingStructure };
|
|
25
27
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
function matchUpsOf(structure) {
|
|
2
|
+
return structure && 'matchUps' in structure ? structure.matchUps : undefined;
|
|
3
|
+
}
|
|
4
|
+
function positionAssignmentsOf(structure) {
|
|
5
|
+
return structure && 'positionAssignments' in structure ? structure.positionAssignments : undefined;
|
|
6
|
+
}
|
|
7
|
+
function structuresOf(structure) {
|
|
8
|
+
return structure && 'structures' in structure ? structure.structures : undefined;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { matchUpsOf, positionAssignmentsOf, structuresOf };
|
|
@@ -13,6 +13,25 @@ import { nowIso } from '../../../tools/clock.mjs';
|
|
|
13
13
|
import { addPoint, deriveServer, deriveServerBase, checkStandardSetWon, checkAndFinalizeMatch } from '../../../mutate/scoring/addPoint.mjs';
|
|
14
14
|
import { COMPLETED, TO_BE_PLAYED, IN_PROGRESS } from '../../../constants/matchUpStatusValues.mjs';
|
|
15
15
|
|
|
16
|
+
function deriveInitialLineUps(matchUp) {
|
|
17
|
+
const sides = (matchUp.sides ?? []).filter((side) => side.lineUp?.length);
|
|
18
|
+
if (!sides.length)
|
|
19
|
+
return undefined;
|
|
20
|
+
const lineUps = {};
|
|
21
|
+
for (const side of sides)
|
|
22
|
+
lineUps[side.sideNumber] = side.lineUp.map((tc) => ({ ...tc }));
|
|
23
|
+
const entries = matchUp.history?.entries;
|
|
24
|
+
const substitutions = entries
|
|
25
|
+
? entries.filter((e) => e.type === 'substitution').map((e) => e.data)
|
|
26
|
+
: (matchUp.history?.substitutions ?? []);
|
|
27
|
+
for (const sub of [...substitutions].reverse()) {
|
|
28
|
+
const lineUp = lineUps[sub.sideNumber];
|
|
29
|
+
const index = lineUp?.findIndex((tc) => tc.participantId === sub.inParticipantId) ?? -1;
|
|
30
|
+
if (index !== -1)
|
|
31
|
+
lineUp[index] = { ...lineUp[index], participantId: sub.outParticipantId };
|
|
32
|
+
}
|
|
33
|
+
return lineUps;
|
|
34
|
+
}
|
|
16
35
|
class ScoringEngine {
|
|
17
36
|
constructor(options = {}) {
|
|
18
37
|
this.pointMultipliers = [];
|
|
@@ -43,6 +62,7 @@ class ScoringEngine {
|
|
|
43
62
|
this.isDoubles = matchUp.matchUpType === 'DOUBLES';
|
|
44
63
|
this.redoStack = [];
|
|
45
64
|
this.initialScore = undefined;
|
|
65
|
+
this.initialLineUps = deriveInitialLineUps(matchUp);
|
|
46
66
|
this.cacheFormatStructure();
|
|
47
67
|
}
|
|
48
68
|
getState() {
|
|
@@ -53,18 +73,15 @@ class ScoringEngine {
|
|
|
53
73
|
const prevTotalGames = this.state.score.sets.reduce((sum, s) => sum + (s.side1Score || 0) + (s.side2Score || 0), 0);
|
|
54
74
|
const prevCompletedSets = this.state.score.sets.filter((s) => s.winningSide !== undefined).length;
|
|
55
75
|
const prevComplete = this.state.matchUpStatus === COMPLETED;
|
|
56
|
-
const
|
|
76
|
+
const activePlayers = this.activePlayersForPoint();
|
|
57
77
|
this.state = addPoint(this.state, options, {
|
|
58
78
|
pointMultipliers: this.pointMultipliers,
|
|
59
79
|
});
|
|
60
|
-
if (
|
|
80
|
+
if ((this.state.history?.points.length || 0) === pointIndex)
|
|
81
|
+
return;
|
|
82
|
+
if (activePlayers) {
|
|
61
83
|
const lastPoint = this.state.history.points[this.state.history.points.length - 1];
|
|
62
|
-
|
|
63
|
-
lastPoint.activePlayers = [activePlayersSnapshot.side1, activePlayersSnapshot.side2];
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
lastPoint.activePlayers = [activePlayersSnapshot.side1[0] || '', activePlayersSnapshot.side2[0] || ''];
|
|
67
|
-
}
|
|
84
|
+
lastPoint.activePlayers = activePlayers;
|
|
68
85
|
}
|
|
69
86
|
if (options.penaltyType) {
|
|
70
87
|
const lastPoint = this.state.history.points[this.state.history.points.length - 1];
|
|
@@ -393,6 +410,12 @@ class ScoringEngine {
|
|
|
393
410
|
hasLineUp() {
|
|
394
411
|
return this.state.sides.some((s) => s.lineUp && s.lineUp.length > 0);
|
|
395
412
|
}
|
|
413
|
+
activePlayersForPoint() {
|
|
414
|
+
if (!this.hasLineUp())
|
|
415
|
+
return undefined;
|
|
416
|
+
const { side1, side2 } = this.getActivePlayers();
|
|
417
|
+
return this.isDoubles ? [side1, side2] : [side1[0] || '', side2[0] || ''];
|
|
418
|
+
}
|
|
396
419
|
setPointMultipliers(multipliers) {
|
|
397
420
|
this.pointMultipliers = multipliers;
|
|
398
421
|
}
|
|
@@ -445,8 +468,14 @@ class ScoringEngine {
|
|
|
445
468
|
const point = this.state.history?.points[pointIndex];
|
|
446
469
|
if (point) {
|
|
447
470
|
Object.assign(point, metadata);
|
|
471
|
+
const entry = this.pointEntry(pointIndex);
|
|
472
|
+
if (entry)
|
|
473
|
+
Object.assign(entry.data, metadata);
|
|
448
474
|
}
|
|
449
475
|
}
|
|
476
|
+
pointEntry(pointIndex) {
|
|
477
|
+
return this.state.history?.entries?.find((e) => e.type === 'point' && e.pointIndex === pointIndex);
|
|
478
|
+
}
|
|
450
479
|
markHardBoundary(options) {
|
|
451
480
|
const set = this.state.score.sets[options.setIndex];
|
|
452
481
|
if (!set)
|
|
@@ -463,32 +492,32 @@ class ScoringEngine {
|
|
|
463
492
|
return;
|
|
464
493
|
const shouldRecalculate = options?.recalculate !== false;
|
|
465
494
|
const point = points[pointIndex];
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
if (
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
if (
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
if (
|
|
479
|
-
|
|
495
|
+
const entry = this.pointEntry(pointIndex);
|
|
496
|
+
const edits = Object.fromEntries(Object.entries(newData).filter(([, value]) => value !== undefined));
|
|
497
|
+
const pointEdits = { ...edits };
|
|
498
|
+
const entryEdits = { ...edits };
|
|
499
|
+
if (edits.winner !== undefined) {
|
|
500
|
+
pointEdits.winningSide = edits.winner + 1;
|
|
501
|
+
entryEdits.winningSide = undefined;
|
|
502
|
+
}
|
|
503
|
+
else if (edits.winningSide !== undefined) {
|
|
504
|
+
pointEdits.winner = edits.winningSide - 1;
|
|
505
|
+
entryEdits.winner = undefined;
|
|
506
|
+
}
|
|
507
|
+
if (edits.server !== undefined) {
|
|
508
|
+
pointEdits.serverSideNumber = edits.server + 1;
|
|
509
|
+
entryEdits.serverSideNumber = undefined;
|
|
510
|
+
}
|
|
511
|
+
else if (edits.serverSideNumber !== undefined) {
|
|
512
|
+
pointEdits.server = edits.serverSideNumber - 1;
|
|
513
|
+
entryEdits.server = undefined;
|
|
514
|
+
}
|
|
515
|
+
Object.assign(point, pointEdits);
|
|
516
|
+
if (entry)
|
|
517
|
+
Object.assign(entry.data, entryEdits);
|
|
480
518
|
if (!shouldRecalculate)
|
|
481
519
|
return;
|
|
482
520
|
const entries = this.state.history?.entries;
|
|
483
|
-
if (entries) {
|
|
484
|
-
const pointEntry = entries.find((e) => e.type === 'point' && e.pointIndex === pointIndex);
|
|
485
|
-
if (pointEntry) {
|
|
486
|
-
if (newData.winner !== undefined)
|
|
487
|
-
pointEntry.data.winner = newData.winner;
|
|
488
|
-
if (newData.server !== undefined)
|
|
489
|
-
pointEntry.data.server = newData.server;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
521
|
if (entries && entries.length > 0) {
|
|
493
522
|
this.rebuildFromEntries();
|
|
494
523
|
}
|
|
@@ -691,12 +720,19 @@ class ScoringEngine {
|
|
|
691
720
|
this.state = newState;
|
|
692
721
|
for (const entry of entries) {
|
|
693
722
|
switch (entry.type) {
|
|
694
|
-
case 'point':
|
|
723
|
+
case 'point': {
|
|
724
|
+
const activePlayers = this.activePlayersForPoint();
|
|
725
|
+
const pointCount = this.state.history?.points.length || 0;
|
|
695
726
|
this.state = addPoint(this.state, entry.data, {
|
|
696
727
|
pointMultipliers: this.pointMultipliers,
|
|
697
728
|
});
|
|
698
729
|
this.state.history.entries = newState.history.entries;
|
|
730
|
+
const points = this.state.history.points;
|
|
731
|
+
const played = points.length > pointCount ? points.at(-1) : undefined;
|
|
732
|
+
if (activePlayers && played)
|
|
733
|
+
played.activePlayers = activePlayers;
|
|
699
734
|
break;
|
|
735
|
+
}
|
|
700
736
|
case 'set':
|
|
701
737
|
this.applyAddSet(entry.data);
|
|
702
738
|
break;
|
|
@@ -759,6 +795,11 @@ class ScoringEngine {
|
|
|
759
795
|
matchUpId: this.matchUpId,
|
|
760
796
|
isDoubles: this.isDoubles,
|
|
761
797
|
});
|
|
798
|
+
for (const side of newState.sides) {
|
|
799
|
+
const lineUp = this.state.sides.find((s) => s.sideNumber === side.sideNumber)?.lineUp;
|
|
800
|
+
if (lineUp)
|
|
801
|
+
side.lineUp = lineUp.map((tc) => ({ ...tc }));
|
|
802
|
+
}
|
|
762
803
|
if (this.initialScore) {
|
|
763
804
|
this.applyInitialScore(newState, this.initialScore);
|
|
764
805
|
if (newState.matchUpStatus === TO_BE_PLAYED) {
|
|
@@ -766,15 +807,24 @@ class ScoringEngine {
|
|
|
766
807
|
}
|
|
767
808
|
}
|
|
768
809
|
for (const point of currentPoints) {
|
|
810
|
+
const pointCount = newState.history?.points.length || 0;
|
|
769
811
|
newState = addPoint(newState, {
|
|
770
812
|
winner: point.winner,
|
|
771
813
|
server: point.server,
|
|
772
814
|
timestamp: point.timestamp,
|
|
773
815
|
rallyLength: point.rallyLength,
|
|
774
816
|
result: point.result,
|
|
817
|
+
penaltyType: point.penaltyType,
|
|
818
|
+
penaltyPoint: point.penaltyPoint,
|
|
819
|
+
wrongSide: point.wrongSide,
|
|
820
|
+
wrongServer: point.wrongServer,
|
|
775
821
|
}, {
|
|
776
822
|
pointMultipliers: this.pointMultipliers,
|
|
777
823
|
});
|
|
824
|
+
const replayed = newState.history?.points ?? [];
|
|
825
|
+
const played = replayed.length > pointCount ? replayed.at(-1) : undefined;
|
|
826
|
+
if (point.activePlayers && played)
|
|
827
|
+
played.activePlayers = point.activePlayers;
|
|
778
828
|
}
|
|
779
829
|
this.state = newState;
|
|
780
830
|
}
|
|
@@ -25,14 +25,16 @@ function autoSeeding({ tournamentRecord, drawDefinition, policyDefinitions, scal
|
|
|
25
25
|
entries,
|
|
26
26
|
stage,
|
|
27
27
|
}).scaledEntries ?? [];
|
|
28
|
-
const
|
|
28
|
+
const seedingResult = generateSeedingScaleItems({
|
|
29
29
|
scaleAttributes,
|
|
30
30
|
scaledEntries,
|
|
31
31
|
stageEntries,
|
|
32
32
|
seedsCount,
|
|
33
33
|
scaleName,
|
|
34
34
|
});
|
|
35
|
-
|
|
35
|
+
if (seedingResult.error)
|
|
36
|
+
return seedingResult;
|
|
37
|
+
return { scaleItemsWithParticipantIds: seedingResult.scaleItemsWithParticipantIds };
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
export { autoSeeding };
|
package/dist/esm/assemblies/generators/drawDefinitions/drawTypes/adHoc/drawMatic/drawMatic.mjs
CHANGED
|
@@ -50,8 +50,6 @@ function drawMatic(params) {
|
|
|
50
50
|
return { ...SUCCESS, matchUps, roundResults };
|
|
51
51
|
}
|
|
52
52
|
function getAdHocStructure(params) {
|
|
53
|
-
if (params.structureId)
|
|
54
|
-
return params.structureId;
|
|
55
53
|
const drawDefinition = params.drawDefinition;
|
|
56
54
|
const targetStructure = drawDefinition?.structures
|
|
57
55
|
?.filter((structure) => structure.stageSequence === 1)
|
|
@@ -60,7 +58,7 @@ function getAdHocStructure(params) {
|
|
|
60
58
|
const structureIsAdHoc = isAdHoc({ structure });
|
|
61
59
|
return structureIsAdHoc && orderNumber > (stageOrder[targetStructure?.stage] || 1) ? structure : targetStructure;
|
|
62
60
|
}, undefined);
|
|
63
|
-
const structure = drawDefinition?.structures?.find((structure) => structure.structureId === targetStructure?.structureId);
|
|
61
|
+
const structure = drawDefinition?.structures?.find((structure) => structure.structureId === (params.structureId ?? targetStructure?.structureId));
|
|
64
62
|
if (!structure)
|
|
65
63
|
return { error: STRUCTURE_NOT_FOUND };
|
|
66
64
|
const structureIsAdHoc = isAdHoc({ structure });
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { getCompetitionPolicy } from '../../../../../../query/drawDefinition/competition/getCompetitionPolicy.mjs';
|
|
2
2
|
import { getCompetitionState } from '../../../../../../query/drawDefinition/competition/getCompetitionState.mjs';
|
|
3
3
|
import { buildIndividualIdsMap } from '../../../../../../query/participants/individualParticipantIds.mjs';
|
|
4
|
-
import { generateDynamicRatings } from '../../../../scales/generateDynamicRatings.mjs';
|
|
5
4
|
import { generateAdHocMatchUps } from '../generateAdHocMatchUps.mjs';
|
|
5
|
+
import { generateDynamicRatings } from '../../../../scales/generateDynamicRatings.mjs';
|
|
6
6
|
import { findStructure } from '../../../../../../acquire/findStructure.mjs';
|
|
7
|
+
import { matchUpsOf } from '../../../../../../acquire/structureMembers.mjs';
|
|
7
8
|
import { getPairingsData } from './getPairingsData.mjs';
|
|
8
9
|
import { getEncounters } from './getEncounters.mjs';
|
|
9
10
|
import { getPairings } from './getPairings.mjs';
|
|
@@ -27,7 +28,7 @@ function generateDrawMaticRound(params) {
|
|
|
27
28
|
return { error: MISSING_STRUCTURE };
|
|
28
29
|
if (!participantIds?.length)
|
|
29
30
|
return { error: MISSING_PARTICIPANT_IDS };
|
|
30
|
-
const consideredMatchUps = [...(iterationMatchUps ?? []), ...(structure
|
|
31
|
+
const consideredMatchUps = [...(iterationMatchUps ?? []), ...(matchUpsOf(structure) ?? [])];
|
|
31
32
|
const { encounters } = getEncounters({ matchUps: consideredMatchUps });
|
|
32
33
|
const tournamentParticipants = tournamentRecord?.participants ?? [];
|
|
33
34
|
let modifiedScaleValues = {};
|
|
@@ -43,10 +44,10 @@ function generateDrawMaticRound(params) {
|
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
else if (dynamicRatings) {
|
|
46
|
-
const roundNumbers = unique(structure?.
|
|
47
|
+
const roundNumbers = unique(matchUpsOf(structure)?.map(({ roundNumber }) => roundNumber) ?? []);
|
|
47
48
|
const lastRoundNumber = Math.max(...roundNumbers, 0);
|
|
48
49
|
if (lastRoundNumber) {
|
|
49
|
-
const matchUpIds = structure
|
|
50
|
+
const matchUpIds = matchUpsOf(structure)
|
|
50
51
|
?.filter(({ roundNumber }) => roundNumber === lastRoundNumber)
|
|
51
52
|
.map(({ matchUpId }) => matchUpId);
|
|
52
53
|
const result = generateDynamicRatings({
|
package/dist/esm/assemblies/generators/drawDefinitions/drawTypes/adHoc/getAvailableMatchUpsCount.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { checkRequiredParameters } from '../../../../../helpers/parameters/checkRequiredParameters.mjs';
|
|
2
|
+
import { matchUpsOf, structuresOf } from '../../../../../acquire/structureMembers.mjs';
|
|
2
3
|
import { MISSING_STRUCTURE_ID, STRUCTURE_NOT_FOUND, INVALID_STRUCTURE } from '../../../../../constants/errorConditionConstants.mjs';
|
|
3
4
|
import { STRUCTURE_SELECTED_STATUSES } from '../../../../../constants/entryStatusConstants.mjs';
|
|
4
5
|
import { ROUND_OUTCOME } from '../../../../../constants/drawDefinitionConstants.mjs';
|
|
@@ -16,13 +17,13 @@ function getAvailableMatchUpsCount(params) {
|
|
|
16
17
|
if (!structure)
|
|
17
18
|
return { error: STRUCTURE_NOT_FOUND };
|
|
18
19
|
let structureHasRoundPositions;
|
|
19
|
-
const existingMatchUps = structure
|
|
20
|
+
const existingMatchUps = matchUpsOf(structure) ?? [];
|
|
20
21
|
const lastRoundNumber = existingMatchUps?.reduce((roundNumber, matchUp) => {
|
|
21
22
|
if (matchUp.roundPosition)
|
|
22
23
|
structureHasRoundPositions = true;
|
|
23
24
|
return (matchUp?.roundNumber || 0) > roundNumber ? matchUp.roundNumber : roundNumber;
|
|
24
25
|
}, 0);
|
|
25
|
-
if (structure
|
|
26
|
+
if (structuresOf(structure) || structureHasRoundPositions || structure.finishingPosition === ROUND_OUTCOME) {
|
|
26
27
|
return { error: INVALID_STRUCTURE };
|
|
27
28
|
}
|
|
28
29
|
const selectedEntries = drawDefinition?.entries?.filter((entry) => {
|
|
@@ -31,7 +32,7 @@ function getAvailableMatchUpsCount(params) {
|
|
|
31
32
|
}) ?? [];
|
|
32
33
|
const roundMatchUpsCount = Math.floor(selectedEntries?.length / 2) || 1;
|
|
33
34
|
const targetRoundNumber = roundNumber ?? lastRoundNumber ?? 1;
|
|
34
|
-
const existingRoundMatchUps = structure
|
|
35
|
+
const existingRoundMatchUps = matchUpsOf(structure)?.filter((matchUp) => matchUp.roundNumber === targetRoundNumber)?.length ?? 0;
|
|
35
36
|
const maxRemaining = roundMatchUpsCount - existingRoundMatchUps;
|
|
36
37
|
const availableMatchUpsCount = maxRemaining > 0 ? maxRemaining : 0;
|
|
37
38
|
return { ...SUCCESS, availableMatchUpsCount, lastRoundNumber, roundMatchUpsCount };
|
package/dist/esm/assemblies/generators/drawDefinitions/drawTypes/adHoc/swiss/generateSwissRound.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import { getParticipantIds } from '../drawMatic/getParticipantIds.mjs';
|
|
|
7
7
|
import { generateAdHocMatchUps } from '../generateAdHocMatchUps.mjs';
|
|
8
8
|
import { getAdHocRatings } from '../drawMatic/getAdHocRatings.mjs';
|
|
9
9
|
import { generateSwissPairings } from './swissPairing.mjs';
|
|
10
|
+
import { positionAssignmentsOf, matchUpsOf } from '../../../../../../acquire/structureMembers.mjs';
|
|
10
11
|
import { findStructure } from '../../../../../../acquire/findStructure.mjs';
|
|
11
12
|
import { findExtension } from '../../../../../../acquire/findExtension.mjs';
|
|
12
13
|
import { WINNER, QUALIFYING } from '../../../../../../constants/drawDefinitionConstants.mjs';
|
|
@@ -28,7 +29,7 @@ function generateSwissRound(params) {
|
|
|
28
29
|
if (idsResult.error)
|
|
29
30
|
return idsResult;
|
|
30
31
|
const entryParticipantIds = idsResult.participantIds ?? [];
|
|
31
|
-
const positionParticipantIds = structure
|
|
32
|
+
const positionParticipantIds = positionAssignmentsOf(structure)
|
|
32
33
|
?.map((pa) => pa.participantId)
|
|
33
34
|
.filter((pid) => !!pid) ?? [];
|
|
34
35
|
const qualifierWinnerIds = getQualifierWinners({ drawDefinition, targetStructureId: structure.structureId });
|
|
@@ -63,7 +64,7 @@ function generateSwissRound(params) {
|
|
|
63
64
|
}
|
|
64
65
|
const swissPolicy = params.swissPolicy ??
|
|
65
66
|
findExtension({ element: drawDefinition, name: 'swissPolicy' })?.extension?.value;
|
|
66
|
-
const existingMatchUps = structure
|
|
67
|
+
const existingMatchUps = matchUpsOf(structure) ?? [];
|
|
67
68
|
const { participantIdPairings, byeParticipantId } = generateSwissPairings({
|
|
68
69
|
allowDraws: swissPolicy?.allowDraws,
|
|
69
70
|
matchUps: existingMatchUps,
|
package/dist/esm/assemblies/generators/drawDefinitions/drawTypes/generateVoluntaryConsolation.mjs
CHANGED
|
@@ -49,7 +49,8 @@ function generateVoluntaryConsolation(params) {
|
|
|
49
49
|
const structureCount = stageStructures.length;
|
|
50
50
|
if (structureCount > 1)
|
|
51
51
|
return { error: STAGE_SEQUENCE_LIMIT };
|
|
52
|
-
|
|
52
|
+
const existingMatchUps = getAllStructureMatchUps({ structure: stageStructures?.[0] }).matchUps;
|
|
53
|
+
if (existingMatchUps.length)
|
|
53
54
|
return { error: EXISTING_STRUCTURE };
|
|
54
55
|
const structureId = stageStructures?.[0]?.structureId;
|
|
55
56
|
Object.assign(params, definedAttributes({
|
|
@@ -70,7 +70,9 @@ function luckyRoundProfiles(drawSize) {
|
|
|
70
70
|
const intDrawSize = ensureInt(drawSize);
|
|
71
71
|
let participantsCount = intDrawSize % 2 ? intDrawSize + 1 : intDrawSize;
|
|
72
72
|
const preFeedRound = !!(Math.ceil(participantsCount / 2) % 2);
|
|
73
|
-
const rounds = [
|
|
73
|
+
const rounds = [
|
|
74
|
+
{ participantsCount, preFeedRound },
|
|
75
|
+
];
|
|
74
76
|
while (participantsCount > 2) {
|
|
75
77
|
const nextRound = Math.ceil(participantsCount / 2);
|
|
76
78
|
const nextIsFinal = nextRound === 1;
|
package/dist/esm/assemblies/generators/drawDefinitions/generateAndPopulatePlayoffStructures.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { generatePlayoffStructures } from './drawTypes/playoffStructures.mjs';
|
|
|
5
5
|
import { directParticipants } from '../../../mutate/matchUps/drawPositions/directParticipants.mjs';
|
|
6
6
|
import { resolveTieFormat } from '../../../query/hierarchical/tieFormats/resolveTieFormat.mjs';
|
|
7
7
|
import { getAllStructureMatchUps } from '../../../query/matchUps/getAllStructureMatchUps.mjs';
|
|
8
|
+
import { getSideDrawPosition } from '../../../query/matchUps/getDrawPositionSides.mjs';
|
|
8
9
|
import { isLuckyBasedDraw } from '../../../query/drawDefinition/isLuckyBasedDraw.mjs';
|
|
9
10
|
import { matchUpCompletion } from '../../../query/matchUp/checkMatchUpIsComplete.mjs';
|
|
10
11
|
import { processPlayoffGroups } from './drawTypes/processPlayoffGroups.mjs';
|
|
@@ -14,6 +15,7 @@ import { getAllDrawMatchUps } from '../../../query/matchUps/drawMatchUps.mjs';
|
|
|
14
15
|
import { positionTargets } from '../../../query/matchUp/positionTargets.mjs';
|
|
15
16
|
import { getMatchUpId } from '../../../functions/global/extractors.mjs';
|
|
16
17
|
import { pushGlobalLog } from '../../../functions/global/globalLog.mjs';
|
|
18
|
+
import { structuresOf } from '../../../acquire/structureMembers.mjs';
|
|
17
19
|
import { findStructure } from '../../../acquire/findStructure.mjs';
|
|
18
20
|
import { addGoesTo } from '../../../query/matchUps/addGoesTo.mjs';
|
|
19
21
|
import { generateTieMatchUps } from './tieMatchUps.mjs';
|
|
@@ -162,7 +164,7 @@ function generateAndPopulatePlayoffStructures(params) {
|
|
|
162
164
|
});
|
|
163
165
|
}
|
|
164
166
|
}
|
|
165
|
-
advanceCompletedMatchUps({
|
|
167
|
+
const advanced = advanceCompletedMatchUps({
|
|
166
168
|
inContextDrawMatchUps,
|
|
167
169
|
sourceStructureId,
|
|
168
170
|
tournamentRecord,
|
|
@@ -171,13 +173,17 @@ function generateAndPopulatePlayoffStructures(params) {
|
|
|
171
173
|
structure,
|
|
172
174
|
event,
|
|
173
175
|
});
|
|
174
|
-
|
|
176
|
+
if (advanced?.error)
|
|
177
|
+
return decorateResult({ result: advanced, stack });
|
|
178
|
+
const byesAdvanced = advanceByeMatchUps({
|
|
175
179
|
inContextDrawMatchUps,
|
|
176
180
|
sourceStructureId,
|
|
177
181
|
tournamentRecord,
|
|
178
182
|
drawDefinition,
|
|
179
183
|
event,
|
|
180
184
|
});
|
|
185
|
+
if (byesAdvanced?.error)
|
|
186
|
+
return decorateResult({ result: byesAdvanced, stack });
|
|
181
187
|
const matchUpModifications = buildMatchUpModifications({
|
|
182
188
|
inContextDrawMatchUps,
|
|
183
189
|
sourceStructureId,
|
|
@@ -187,6 +193,8 @@ function generateAndPopulatePlayoffStructures(params) {
|
|
|
187
193
|
params,
|
|
188
194
|
stack,
|
|
189
195
|
});
|
|
196
|
+
if (!Array.isArray(matchUpModifications))
|
|
197
|
+
return decorateResult({ result: matchUpModifications, stack });
|
|
190
198
|
return {
|
|
191
199
|
structures: newStructures,
|
|
192
200
|
matchUpModifications,
|
|
@@ -212,7 +220,7 @@ function resolvePlayoffParams(params, stack) {
|
|
|
212
220
|
if (!structure) {
|
|
213
221
|
return { error: true, earlyReturn: decorateResult({ result: { error: STRUCTURE_NOT_FOUND }, stack }) };
|
|
214
222
|
}
|
|
215
|
-
if (structure.structureType === CONTAINER || structure
|
|
223
|
+
if (structure.structureType === CONTAINER || structuresOf(structure)) {
|
|
216
224
|
return {
|
|
217
225
|
error: true,
|
|
218
226
|
earlyReturn: generateAndPopulateRRplayoffStructures({
|
|
@@ -291,7 +299,7 @@ function generatePositionBasedPlayoffs({ sourceStructureId, tournamentRecord, dr
|
|
|
291
299
|
inContext: true,
|
|
292
300
|
drawDefinition,
|
|
293
301
|
});
|
|
294
|
-
advanceCompletedMatchUps({
|
|
302
|
+
const advanced = advanceCompletedMatchUps({
|
|
295
303
|
inContextDrawMatchUps,
|
|
296
304
|
sourceStructureId,
|
|
297
305
|
tournamentRecord,
|
|
@@ -300,13 +308,17 @@ function generatePositionBasedPlayoffs({ sourceStructureId, tournamentRecord, dr
|
|
|
300
308
|
structure,
|
|
301
309
|
event,
|
|
302
310
|
});
|
|
303
|
-
|
|
311
|
+
if (advanced?.error)
|
|
312
|
+
return decorateResult({ result: advanced, stack });
|
|
313
|
+
const byesAdvanced = advanceByeMatchUps({
|
|
304
314
|
inContextDrawMatchUps,
|
|
305
315
|
sourceStructureId,
|
|
306
316
|
tournamentRecord,
|
|
307
317
|
drawDefinition,
|
|
308
318
|
event,
|
|
309
319
|
});
|
|
320
|
+
if (byesAdvanced?.error)
|
|
321
|
+
return decorateResult({ result: byesAdvanced, stack });
|
|
310
322
|
return {
|
|
311
323
|
structures: playoffStructures,
|
|
312
324
|
links: playoffLinks,
|
|
@@ -337,13 +349,15 @@ function computePlayoffDrawSize({ finishingPositionsCount, isLuckyDraw, roundNum
|
|
|
337
349
|
}
|
|
338
350
|
function advanceCompletedMatchUps({ inContextDrawMatchUps, sourceStructureId, tournamentRecord, drawDefinition, matchUpsMap, structure, event, }) {
|
|
339
351
|
const completedMatchUps = inContextDrawMatchUps?.filter((matchUp) => matchUpCompletion(matchUp) && matchUp.structureId === sourceStructureId);
|
|
340
|
-
|
|
352
|
+
for (const matchUp of completedMatchUps ?? []) {
|
|
341
353
|
const { matchUpId, score, winningSide } = matchUp;
|
|
342
354
|
const targetData = positionTargets({
|
|
343
355
|
inContextDrawMatchUps,
|
|
344
356
|
drawDefinition,
|
|
345
357
|
matchUpId,
|
|
346
358
|
});
|
|
359
|
+
if (targetData.error)
|
|
360
|
+
return targetData;
|
|
347
361
|
const result = directParticipants({
|
|
348
362
|
inContextDrawMatchUps,
|
|
349
363
|
tournamentRecord,
|
|
@@ -359,21 +373,31 @@ function advanceCompletedMatchUps({ inContextDrawMatchUps, sourceStructureId, to
|
|
|
359
373
|
});
|
|
360
374
|
if (result.error)
|
|
361
375
|
pushGlobalLog({ method: 'generateAndPopulatePlayoffStructures', error: result.error });
|
|
362
|
-
}
|
|
376
|
+
}
|
|
377
|
+
return undefined;
|
|
363
378
|
}
|
|
364
|
-
function advanceByeMatchUps({ inContextDrawMatchUps, sourceStructureId, tournamentRecord, drawDefinition, event }) {
|
|
379
|
+
function advanceByeMatchUps({ inContextDrawMatchUps, sourceStructureId, tournamentRecord, drawDefinition, event, }) {
|
|
365
380
|
const byeMatchUps = inContextDrawMatchUps?.filter((matchUp) => matchUp.matchUpStatus === BYE && matchUp.structureId === sourceStructureId);
|
|
366
|
-
|
|
381
|
+
for (const matchUp of byeMatchUps ?? []) {
|
|
367
382
|
const { matchUpId } = matchUp;
|
|
368
383
|
const targetData = positionTargets({
|
|
369
384
|
inContextDrawMatchUps,
|
|
370
385
|
drawDefinition,
|
|
371
386
|
matchUpId,
|
|
372
387
|
});
|
|
388
|
+
if (targetData.error)
|
|
389
|
+
return targetData;
|
|
373
390
|
const { targetLinks: { loserTargetLink }, targetMatchUps: { loserMatchUpDrawPositionIndex, loserMatchUp }, } = targetData;
|
|
374
|
-
if (loserTargetLink && loserMatchUp) {
|
|
391
|
+
if (loserTargetLink && loserMatchUp?.drawPositions && loserMatchUpDrawPositionIndex !== undefined) {
|
|
375
392
|
const targetStructureId = loserTargetLink.target.structureId;
|
|
376
|
-
const targetDrawPosition =
|
|
393
|
+
const targetDrawPosition = getSideDrawPosition({
|
|
394
|
+
sideNumber: loserMatchUpDrawPositionIndex + 1,
|
|
395
|
+
structureId: targetStructureId,
|
|
396
|
+
matchUp: loserMatchUp,
|
|
397
|
+
drawDefinition,
|
|
398
|
+
});
|
|
399
|
+
if (!targetDrawPosition)
|
|
400
|
+
continue;
|
|
377
401
|
const result = assignDrawPositionBye({
|
|
378
402
|
drawPosition: targetDrawPosition,
|
|
379
403
|
structureId: targetStructureId,
|
|
@@ -384,15 +408,19 @@ function advanceByeMatchUps({ inContextDrawMatchUps, sourceStructureId, tourname
|
|
|
384
408
|
if (result.error)
|
|
385
409
|
pushGlobalLog({ method: 'generateAndPopulatePlayoffStructures', error: result.error });
|
|
386
410
|
}
|
|
387
|
-
}
|
|
411
|
+
}
|
|
412
|
+
return undefined;
|
|
388
413
|
}
|
|
389
414
|
function buildMatchUpModifications({ inContextDrawMatchUps, sourceStructureId, tournamentRecord, drawDefinition, matchUpsMap, params, stack, }) {
|
|
390
415
|
const matchUpModifications = [];
|
|
391
|
-
const
|
|
416
|
+
const goesTo = addGoesTo({
|
|
392
417
|
inContextDrawMatchUps,
|
|
393
418
|
drawDefinition,
|
|
394
419
|
matchUpsMap,
|
|
395
|
-
})
|
|
420
|
+
});
|
|
421
|
+
if (goesTo.error)
|
|
422
|
+
return goesTo;
|
|
423
|
+
const goesToMap = goesTo.goesToMap;
|
|
396
424
|
const { structure: sourceStructure } = findStructure({
|
|
397
425
|
drawDefinition: params.drawDefinition,
|
|
398
426
|
structureId: sourceStructureId,
|
|
@@ -427,4 +455,4 @@ function buildMatchUpModifications({ inContextDrawMatchUps, sourceStructureId, t
|
|
|
427
455
|
return matchUpModifications;
|
|
428
456
|
}
|
|
429
457
|
|
|
430
|
-
export { generateAndPopulatePlayoffStructures };
|
|
458
|
+
export { advanceByeMatchUps, generateAndPopulatePlayoffStructures };
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import { generateDrawTypeAndModifyDrawDefinition } from '../generateDrawTypeAndModifyDrawDefinition.mjs';
|
|
2
2
|
import { generateQualifyingLink } from '../links/generateQualifyingLink.mjs';
|
|
3
3
|
import { addDrawEntry } from '../../../../mutate/drawDefinitions/entryGovernor/addDrawEntries.mjs';
|
|
4
|
+
import { getQualifiersCount } from '../../../../query/drawDefinition/getQualifiersCount.mjs';
|
|
4
5
|
import { isLuckyBasedDraw } from '../../../../query/drawDefinition/isLuckyBasedDraw.mjs';
|
|
5
6
|
import structureTemplate from '../../templates/structureTemplate.mjs';
|
|
7
|
+
import { getStageEntries } from '../../../../query/drawDefinition/stageGetter.mjs';
|
|
8
|
+
import { decorateResult } from '../../../../functions/global/decorateResult.mjs';
|
|
6
9
|
import { isAdHocType } from '../../../../query/drawDefinition/isAdHocType.mjs';
|
|
7
10
|
import { constantToString } from '../../../../tools/strings.mjs';
|
|
8
11
|
import { generateAdHoc } from './generateAdHoc.mjs';
|
|
9
12
|
import { prepareStage } from './prepareStage.mjs';
|
|
10
13
|
import { ensureInt } from '../../../../tools/ensureInt.mjs';
|
|
14
|
+
import { DIRECT_ENTRY_STATUSES } from '../../../../constants/entryStatusConstants.mjs';
|
|
15
|
+
import { INSUFFICIENT_DRAW_POSITIONS } from '../../../../constants/errorConditionConstants.mjs';
|
|
11
16
|
import { MAIN, QUALIFYING, POSITION } from '../../../../constants/drawDefinitionConstants.mjs';
|
|
12
17
|
import { WITHDRAWN } from '../../../../constants/entryStatusValues.mjs';
|
|
13
18
|
|
|
@@ -60,6 +65,9 @@ function generateNewDrawDefinition(params) {
|
|
|
60
65
|
drawDefinition.links ??= [];
|
|
61
66
|
drawDefinition.links.push(link);
|
|
62
67
|
}
|
|
68
|
+
const fitResult = checkMainFits({ ...params, drawDefinition, mainStructureId });
|
|
69
|
+
if (fitResult.error)
|
|
70
|
+
return fitResult;
|
|
63
71
|
const seedsCount = isLuckyBasedDraw(drawType) ? 0 : ensureInt(params.seedsCount ?? 0);
|
|
64
72
|
const structureResult = prepareStage({
|
|
65
73
|
...params,
|
|
@@ -112,5 +120,21 @@ function addEntries(params) {
|
|
|
112
120
|
}
|
|
113
121
|
return { error: undefined };
|
|
114
122
|
}
|
|
123
|
+
function checkMainFits(params) {
|
|
124
|
+
const { drawDefinition, mainStructureId, qualifyingOnly, drawSize, drawType, qualifiersCount } = params;
|
|
125
|
+
if (!drawDefinition || !mainStructureId || qualifyingOnly || !drawSize || isAdHocType(drawType))
|
|
126
|
+
return {};
|
|
127
|
+
const stageScope = { stage: MAIN, stageSequence: 1, drawDefinition };
|
|
128
|
+
const directEntries = getStageEntries({ ...stageScope, entryStatuses: DIRECT_ENTRY_STATUSES });
|
|
129
|
+
const derivedQualifiersCount = getQualifiersCount({ ...stageScope, structureId: mainStructureId }).qualifiersCount;
|
|
130
|
+
const reservedQualifiersCount = derivedQualifiersCount || qualifiersCount || 0;
|
|
131
|
+
if (directEntries.length + reservedQualifiersCount <= drawSize)
|
|
132
|
+
return {};
|
|
133
|
+
return decorateResult({
|
|
134
|
+
context: { drawSize, directEntriesCount: directEntries.length, qualifiersCount: reservedQualifiersCount },
|
|
135
|
+
result: { error: INSUFFICIENT_DRAW_POSITIONS },
|
|
136
|
+
stack: 'generateNewDrawDefinition',
|
|
137
|
+
});
|
|
138
|
+
}
|
|
115
139
|
|
|
116
140
|
export { generateNewDrawDefinition };
|