tods-competition-factory 7.2.0 → 7.3.1
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/assemblies/generators/mocks/processLeagueProfiles.mjs +2 -1
- package/dist/esm/assemblies/governors/scoreGovernor/index.mjs +2 -1
- package/dist/esm/assemblies/governors/scoreGovernor/query.mjs +2 -1
- package/dist/esm/constants/matchUpStatusConstants.mjs +1 -1
- package/dist/esm/fixtures/policies/POLICY_PROGRESSION_DEFAULT.mjs +1 -1
- package/dist/esm/mutate/drawDefinitions/matchUpGovernor/{matchUpStatusCodes.mjs → recordSourceSideProvenance.mjs} +3 -14
- package/dist/esm/mutate/drawDefinitions/matchUpGovernor/removeDoubleExit.mjs +10 -9
- package/dist/esm/mutate/drawDefinitions/positionGovernor/doubleExitAdvancement.mjs +259 -61
- package/dist/esm/mutate/matchUps/drawPositions/assignDrawPositionBye.mjs +7 -11
- package/dist/esm/mutate/matchUps/drawPositions/directParticipants.mjs +1 -0
- package/dist/esm/mutate/matchUps/drawPositions/drawPositionPlacement.mjs +26 -25
- package/dist/esm/mutate/matchUps/drawPositions/positionClear.mjs +27 -4
- package/dist/esm/mutate/matchUps/drawPositions/progressExitStatus.mjs +20 -13
- package/dist/esm/mutate/matchUps/drawPositions/propagateUnfillableLoserBye.mjs +22 -8
- package/dist/esm/mutate/matchUps/drawPositions/propagatesByeOnDoubleExit.mjs +5 -0
- package/dist/esm/mutate/matchUps/drawPositions/releaseAdvancedDrawPosition.mjs +22 -1
- package/dist/esm/mutate/matchUps/drawPositions/removeDirectedParticipants.mjs +5 -4
- package/dist/esm/mutate/matchUps/drawPositions/removeSubsequentRoundsParticipant.mjs +4 -3
- package/dist/esm/mutate/matchUps/matchUpStatus/applyWithdrawnExits.mjs +1 -0
- package/dist/esm/mutate/matchUps/matchUpStatus/reconcileDecider.mjs +101 -0
- package/dist/esm/mutate/matchUps/matchUpStatus/reconcileStaleExitOrigins.mjs +65 -0
- package/dist/esm/mutate/matchUps/matchUpStatus/setMatchUpStatus.mjs +50 -16
- package/dist/esm/mutate/matchUps/matchUpStatus/sideExitProvenance.mjs +94 -45
- package/dist/esm/mutate/matchUps/matchUpStatus/sideStatusCodes.mjs +36 -0
- package/dist/esm/mutate/matchUps/score/modifyMatchUpScore.mjs +16 -0
- package/dist/esm/package.json.mjs +1 -1
- package/dist/esm/query/drawDefinition/getStructureInconsistencies.mjs +67 -6
- package/dist/esm/query/matchUp/analyzeMatchUp.mjs +29 -2
- package/dist/esm/query/matchUp/checkSetIsComplete.mjs +2 -1
- package/dist/esm/query/matchUp/getComplement.mjs +19 -1
- package/dist/esm/query/matchUp/retainScoreForFormat.mjs +57 -0
- package/dist/esm/query/matchUps/getDrawPositionSides.mjs +11 -1
- package/dist/esm/validators/validateMatchUpScore.mjs +9 -4
- package/dist/tods-competition-factory.d.cts +58 -22
- package/dist/tods-competition-factory.d.mts +58 -22
- package/dist/tods-competition-factory.d.ts +58 -22
- package/dist/tods-competition-factory.development.cjs.js +1310 -614
- 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 +28 -26
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
|
-
**13,
|
|
145
|
+
**13,700+ 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
|
|
|
@@ -6,13 +6,14 @@ import { isNumeric } from '../../../tools/math.mjs';
|
|
|
6
6
|
import { ANY, MALE, OTHER, MIXED, FEMALE } from '../../../constants/genderConstants.mjs';
|
|
7
7
|
import tieFormatDefaults from '../templates/tieFormatDefaults.mjs';
|
|
8
8
|
import { AD_HOC, DOUBLE_ROUND_ROBIN, MAIN } from '../../../constants/drawDefinitionConstants.mjs';
|
|
9
|
+
import '../../../helpers/keyValueScore/constants.mjs';
|
|
9
10
|
import '../../../mutate/matchUps/schedule/byeScheduling.mjs';
|
|
10
11
|
import { TEAM } from '../../../constants/participantConstants.mjs';
|
|
11
12
|
import { DIRECT_ACCEPTANCE } from '../../../constants/entryStatusValues.mjs';
|
|
12
13
|
import { UUID } from '../../../tools/UUID.mjs';
|
|
13
|
-
import '../../../helpers/keyValueScore/constants.mjs';
|
|
14
14
|
import { COMPETITOR } from '../../../constants/participantRoleValues.mjs';
|
|
15
15
|
import '../../../types/tournamentTypes.mjs';
|
|
16
|
+
import '../../../mutate/matchUps/matchUpStatus/sideStatusCodes.mjs';
|
|
16
17
|
import '../../../query/drawDefinition/predictDrawCompetitiveBands.mjs';
|
|
17
18
|
import { generateDrawDefinition } from '../drawDefinitions/generateDrawDefinition/generateDrawDefinition.mjs';
|
|
18
19
|
import { addParticipants } from '../../../mutate/participants/addParticipants.mjs';
|
|
@@ -23,9 +23,9 @@ export { deduceMatchUpFormat } from '../../../query/scoring/deduceMatchUpFormat.
|
|
|
23
23
|
export { generateScoreString } from '../../generators/matchUps/generateScoreString.mjs';
|
|
24
24
|
export { generateTieMatchUpScore } from '../../generators/tieMatchUpScore/generateTieMatchUpScore.mjs';
|
|
25
25
|
export { getEpisodes } from '../../../query/scoring/getEpisodes.mjs';
|
|
26
|
+
export { getMaxSetScore, getSetComplement, getTiebreakComplement } from '../../../query/matchUp/getComplement.mjs';
|
|
26
27
|
export { getScore } from '../../../query/scoring/getScore.mjs';
|
|
27
28
|
export { getScoreboard } from '../../../query/scoring/getScoreboard.mjs';
|
|
28
|
-
export { getSetComplement, getTiebreakComplement } from '../../../query/matchUp/getComplement.mjs';
|
|
29
29
|
export { getWinner } from '../../../query/scoring/getWinner.mjs';
|
|
30
30
|
export { inferServeSide } from '../../../mutate/scoring/serveSideCalculator.mjs';
|
|
31
31
|
export { isComplete } from '../../../query/scoring/isComplete.mjs';
|
|
@@ -34,6 +34,7 @@ export { keyValueScore } from '../../../helpers/keyValueScore/keyValueScore.mjs'
|
|
|
34
34
|
export { parse as parseMatchUpFormat } from '../../../helpers/matchUpFormatCode/parse.mjs';
|
|
35
35
|
export { parseScoreString } from '../../../tools/parseScoreString.mjs';
|
|
36
36
|
export { resolvePointValue } from '../../../mutate/scoring/resolvePointValue.mjs';
|
|
37
|
+
export { retainScoreForFormat } from '../../../query/matchUp/retainScoreForFormat.mjs';
|
|
37
38
|
export { reverseScore } from '../../generators/score/reverseScore.mjs';
|
|
38
39
|
export { stringify as stringifyMatchUpFormat } from '../../../helpers/matchUpFormatCode/stringify.mjs';
|
|
39
40
|
export { toStatObjects } from '../../../query/scoring/statistics/toStatObjects.mjs';
|
|
@@ -2,7 +2,8 @@ export { validateMatchUpScore, validateSetScore } from '../../../validators/vali
|
|
|
2
2
|
export { isValidMatchUpFormat } from '../../../validators/isValidMatchUpFormat.mjs';
|
|
3
3
|
export { validateTieFormat } from '../../../validators/validateTieFormat.mjs';
|
|
4
4
|
export { validateScore } from '../../../validators/validateScore.mjs';
|
|
5
|
-
export { getSetComplement, getTiebreakComplement } from '../../../query/matchUp/getComplement.mjs';
|
|
5
|
+
export { getMaxSetScore, getSetComplement, getTiebreakComplement } from '../../../query/matchUp/getComplement.mjs';
|
|
6
|
+
export { retainScoreForFormat } from '../../../query/matchUp/retainScoreForFormat.mjs';
|
|
6
7
|
export { checkScoreHasValue } from '../../../query/matchUp/checkScoreHasValue.mjs';
|
|
7
8
|
export { checkSetIsComplete } from '../../../query/matchUp/checkSetIsComplete.mjs';
|
|
8
9
|
export { analyzeScore } from '../../../query/matchUp/analyzeScore.mjs';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ABANDONED, AWAITING_RESULT, CANCELLED, CHALLENGED, DEAD_RUBBER, IN_PROGRESS, INCOMPLETE, NOT_PLAYED, SUSPENDED, TO_BE_PLAYED, COMPLETED, DEFAULTED, DOUBLE_WALKOVER, DOUBLE_DEFAULT, RETIRED, WALKOVER, BYE } from './matchUpStatusValues.mjs';
|
|
2
2
|
|
|
3
3
|
const recoveryTimeRequiredMatchUpStatuses = [
|
|
4
4
|
AWAITING_RESULT,
|
|
@@ -2,7 +2,7 @@ import { POLICY_TYPE_PROGRESSION } from '../../constants/policyConstants.mjs';
|
|
|
2
2
|
|
|
3
3
|
const POLICY_PROGRESSION_DEFAULT = {
|
|
4
4
|
[POLICY_TYPE_PROGRESSION]: {
|
|
5
|
-
doubleExitPropagateBye:
|
|
5
|
+
doubleExitPropagateBye: true,
|
|
6
6
|
autoPlaceQualifiers: false,
|
|
7
7
|
autoReplaceQualifiers: false,
|
|
8
8
|
autoRemoveQualifiers: false,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { mergeSideExitProvenance, producedExitStatus } from '../../matchUps/matchUpStatus/sideExitProvenance.mjs';
|
|
2
2
|
import { getPairedPreviousMatchUp } from '../../../query/matchUps/getPairedPreviousMatchup.mjs';
|
|
3
3
|
import { definedAttributes } from '../../../tools/definedAttributes.mjs';
|
|
4
4
|
import { TO_BE_PLAYED } from '../../../constants/matchUpStatusValues.mjs';
|
|
5
5
|
|
|
6
|
-
function
|
|
6
|
+
function recordSourceSideProvenance({ inContextDrawMatchUps, sourceMatchUpStatus, sourceMatchUpId, matchUpsMap, matchUp, }) {
|
|
7
7
|
const sourceMatchUp = inContextDrawMatchUps.find((matchUp) => matchUp.matchUpId === sourceMatchUpId);
|
|
8
8
|
const { pairedPreviousMatchUp } = getPairedPreviousMatchUp({
|
|
9
9
|
structureId: sourceMatchUp?.structureId,
|
|
@@ -18,17 +18,6 @@ function updateMatchUpStatusCodes({ inContextDrawMatchUps, sourceMatchUpStatus,
|
|
|
18
18
|
(sourceMatchUp?.roundPosition < pairedMatchUp?.roundPosition && 1) || 2
|
|
19
19
|
:
|
|
20
20
|
(sourceMatchUp.structureId === pairedMatchUp?.structureId && 2) || 1;
|
|
21
|
-
matchUp.matchUpStatusCodes = (matchUp.matchUpStatusCodes ?? []).map((code) => {
|
|
22
|
-
const value = typeof code === 'object' && code !== null ? code : { code: code ?? undefined };
|
|
23
|
-
if (value.sideNumber === sourceSideNumber) {
|
|
24
|
-
return {
|
|
25
|
-
...value,
|
|
26
|
-
matchUpStatus: producedExitStatus(sourceMatchUpStatus),
|
|
27
|
-
previousMatchUpStatus: sourceMatchUpStatus,
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
return value;
|
|
31
|
-
});
|
|
32
21
|
if (sourceMatchUpStatus && sourceMatchUpStatus !== TO_BE_PLAYED) {
|
|
33
22
|
mergeSideExitProvenance({
|
|
34
23
|
matchUp,
|
|
@@ -44,4 +33,4 @@ function updateMatchUpStatusCodes({ inContextDrawMatchUps, sourceMatchUpStatus,
|
|
|
44
33
|
}
|
|
45
34
|
}
|
|
46
35
|
|
|
47
|
-
export {
|
|
36
|
+
export { recordSourceSideProvenance };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { withdrawByeClaim, withdrawByeClaimsFrom, byeClaimSurvives,
|
|
1
|
+
import { withdrawByeClaim, withdrawByeClaimsFrom, byeClaimSurvives, getSideExitProvenance, retainPolicyCodes, setSideExitProvenance, retainForeignProvenance, deriveExitStateFromProvenance } from '../../matchUps/matchUpStatus/sideExitProvenance.mjs';
|
|
2
2
|
import { removeDirectedBye, removeDirectedWinner } from '../../matchUps/drawPositions/removeDirectedParticipants.mjs';
|
|
3
|
+
import { propagatesByeOnDoubleExit } from '../../matchUps/drawPositions/propagatesByeOnDoubleExit.mjs';
|
|
3
4
|
import { getPairedPreviousMatchUp } from '../../../query/matchUps/getPairedPreviousMatchup.mjs';
|
|
4
5
|
import { modifyMatchUpScore } from '../../matchUps/score/modifyMatchUpScore.mjs';
|
|
5
6
|
import { decorateResult } from '../../../functions/global/decorateResult.mjs';
|
|
@@ -98,7 +99,7 @@ function removeDoubleExit(params) {
|
|
|
98
99
|
if (anotherClaimSurvives) {
|
|
99
100
|
return decorateResult({ result: { ...SUCCESS }, stack });
|
|
100
101
|
}
|
|
101
|
-
if (appliedPolicies
|
|
102
|
+
if (propagatesByeOnDoubleExit(appliedPolicies) || byePropagatedToLoserMatchUp) {
|
|
102
103
|
removeDirectedBye({
|
|
103
104
|
drawPosition: loserTargetDrawPosition,
|
|
104
105
|
targetLink: loserTargetLink,
|
|
@@ -133,7 +134,7 @@ function removeDoubleExit(params) {
|
|
|
133
134
|
return decorateResult({ result: { ...SUCCESS }, stack });
|
|
134
135
|
}
|
|
135
136
|
function carriesWithdrawnOrigin(matchUp, withdrawnSourceIds) {
|
|
136
|
-
const provenance =
|
|
137
|
+
const provenance = getSideExitProvenance({ matchUp });
|
|
137
138
|
if (!provenance)
|
|
138
139
|
return false;
|
|
139
140
|
return [1, 2].some((sideNumber) => {
|
|
@@ -170,7 +171,7 @@ function withdrawExitFromByeChain({ inContextDrawMatchUps, withdrawnSourceIds, d
|
|
|
170
171
|
keyColors,
|
|
171
172
|
});
|
|
172
173
|
const result = modifyMatchUpScore({
|
|
173
|
-
matchUpStatusCodes:
|
|
174
|
+
matchUpStatusCodes: retainPolicyCodes(noContextTargetMatchUp),
|
|
174
175
|
removeWinningSide: unwound.winningSide === undefined,
|
|
175
176
|
matchUpStatus: unwound.matchUpStatus,
|
|
176
177
|
matchUpId: fromMatchUp.matchUpId,
|
|
@@ -308,7 +309,7 @@ function conditionallyRemoveDrawPosition(params) {
|
|
|
308
309
|
if (result.error)
|
|
309
310
|
return decorateResult({ result, stack });
|
|
310
311
|
const carriesSomethingOfThisCascade = carriesWithdrawnOrigin(noContextTargetMatchUp, withdrawnSourceIds);
|
|
311
|
-
const holdsProvenance = !!
|
|
312
|
+
const holdsProvenance = !!getSideExitProvenance({ matchUp: noContextTargetMatchUp });
|
|
312
313
|
if (holdsProvenance && !carriesSomethingOfThisCascade) {
|
|
313
314
|
pushGlobalLog({
|
|
314
315
|
method: stack,
|
|
@@ -329,7 +330,7 @@ function conditionallyRemoveDrawPosition(params) {
|
|
|
329
330
|
const removeScore = !pairedPreviousDoubleExit;
|
|
330
331
|
result = modifyMatchUpScore({
|
|
331
332
|
...params,
|
|
332
|
-
matchUpStatusCodes:
|
|
333
|
+
matchUpStatusCodes: retainPolicyCodes(noContextTargetMatchUp),
|
|
333
334
|
removeWinningSide: unwound.winningSide === undefined,
|
|
334
335
|
matchUpId: targetMatchUp.matchUpId,
|
|
335
336
|
matchUp: noContextTargetMatchUp,
|
|
@@ -384,10 +385,10 @@ function getUnwoundState({ pairedPreviousDoubleExit, noContextTargetMatchUp, wit
|
|
|
384
385
|
if (noContextTargetMatchUp.matchUpStatus === BYE) {
|
|
385
386
|
return {
|
|
386
387
|
matchUpStatus: BYE,
|
|
387
|
-
provenance: retainForeignProvenance(
|
|
388
|
+
provenance: retainForeignProvenance(getSideExitProvenance({ matchUp: noContextTargetMatchUp }), withdrawnSourceIds),
|
|
388
389
|
};
|
|
389
390
|
}
|
|
390
|
-
const retained = retainForeignProvenance(
|
|
391
|
+
const retained = retainForeignProvenance(getSideExitProvenance({ matchUp: noContextTargetMatchUp }), withdrawnSourceIds);
|
|
391
392
|
if (pairedPreviousDoubleExit) {
|
|
392
393
|
return {
|
|
393
394
|
matchUpStatus: [DOUBLE_DEFAULT, DEFAULTED].includes(noContextTargetMatchUp?.matchUpStatus) ? DEFAULTED : WALKOVER,
|
|
@@ -397,7 +398,7 @@ function getUnwoundState({ pairedPreviousDoubleExit, noContextTargetMatchUp, wit
|
|
|
397
398
|
if (targetDrawPositionIsBye({ drawDefinition, noContextTargetMatchUp, targetMatchUp })) {
|
|
398
399
|
return {
|
|
399
400
|
matchUpStatus: BYE,
|
|
400
|
-
provenance: retainForeignProvenance(
|
|
401
|
+
provenance: retainForeignProvenance(getSideExitProvenance({ matchUp: noContextTargetMatchUp }), withdrawnSourceIds),
|
|
401
402
|
};
|
|
402
403
|
}
|
|
403
404
|
if (isDoubleExit(noContextTargetMatchUp?.matchUpStatus)) {
|
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { assignDrawPositionBye, advanceDrawPosition } from '../../matchUps/drawPositions/assignDrawPositionBye.mjs';
|
|
1
|
+
import { advanceDrawPosition, assignDrawPositionBye } from '../../matchUps/drawPositions/assignDrawPositionBye.mjs';
|
|
3
2
|
import { getPairedPreviousMatchUpIsDoubleExit } from '../../../query/matchUps/getPairedPreviousMatchUpIsDoubleExit.mjs';
|
|
4
|
-
import {
|
|
3
|
+
import { propagateUnfillableLoserBye } from '../../matchUps/drawPositions/propagateUnfillableLoserBye.mjs';
|
|
4
|
+
import { releaseAdvancedDrawPosition } from '../../matchUps/drawPositions/releaseAdvancedDrawPosition.mjs';
|
|
5
|
+
import { directWinner, assignMatchUpDrawPosition } from '../../matchUps/drawPositions/drawPositionPlacement.mjs';
|
|
6
|
+
import { propagatesByeOnDoubleExit } from '../../matchUps/drawPositions/propagatesByeOnDoubleExit.mjs';
|
|
5
7
|
import { getExitWinningSide } from '../matchUpGovernor/getExitWinningSide.mjs';
|
|
8
|
+
import { getAllStructureMatchUps } from '../../../query/matchUps/getAllStructureMatchUps.mjs';
|
|
6
9
|
import { modifyMatchUpScore } from '../../matchUps/score/modifyMatchUpScore.mjs';
|
|
7
10
|
import { getPositionAssignments } from '../../../query/drawDefinition/positionsGetter.mjs';
|
|
11
|
+
import { isFedLoserEligible } from '../../../query/matchUp/isFedLoserEligible.mjs';
|
|
12
|
+
import { isExit, isAnyExit, isDoubleExit } from '../../../validators/isExit.mjs';
|
|
8
13
|
import { getAllDrawMatchUps } from '../../../query/matchUps/drawMatchUps.mjs';
|
|
9
14
|
import { decorateResult } from '../../../functions/global/decorateResult.mjs';
|
|
10
15
|
import { positionTargets } from '../../../query/matchUp/positionTargets.mjs';
|
|
16
|
+
import { getMatchUpsMap } from '../../../query/matchUps/getMatchUpsMap.mjs';
|
|
11
17
|
import { pushGlobalLog } from '../../../functions/global/globalLog.mjs';
|
|
12
|
-
import { isExit, isDoubleExit, isAnyExit } from '../../../validators/isExit.mjs';
|
|
13
|
-
import { getAllStructureMatchUps } from '../../../query/matchUps/getAllStructureMatchUps.mjs';
|
|
14
|
-
import { isFedLoserEligible } from '../../../query/matchUp/isFedLoserEligible.mjs';
|
|
15
18
|
import { findStructure } from '../../../acquire/findStructure.mjs';
|
|
16
19
|
import { overlap } from '../../../tools/arrays.mjs';
|
|
17
|
-
import {
|
|
20
|
+
import { getExitSides, getSideExitProvenance, buildCarriedExitProvenance, retainPolicyCodes, mergeSideExitProvenance, producedExitStatus, recordByeClaim, collapseDoubleExitStatus, buildSideExitProvenance, deriveExitStateFromProvenance, deriveStatusCodes } from '../../matchUps/matchUpStatus/sideExitProvenance.mjs';
|
|
18
21
|
import { MISSING_STRUCTURE, MISSING_MATCHUP, DRAW_POSITION_ASSIGNED } from '../../../constants/errorConditionConstants.mjs';
|
|
19
22
|
import { CONTAINER, FIRST_MATCHUP } from '../../../constants/drawDefinitionConstants.mjs';
|
|
20
23
|
import { BYE } from '../../../constants/matchUpStatusValues.mjs';
|
|
@@ -51,7 +54,7 @@ function doubleExitAdvancement(params) {
|
|
|
51
54
|
winnerStatus: winnerMatchUp?.matchUpStatus,
|
|
52
55
|
winnerDP: JSON.stringify(winnerMatchUp?.drawPositions),
|
|
53
56
|
});
|
|
54
|
-
const loserTargetStillOpen = !!(appliedPolicies
|
|
57
|
+
const loserTargetStillOpen = !!(propagatesByeOnDoubleExit(appliedPolicies) &&
|
|
55
58
|
loserMatchUp?.matchUpStatus === BYE &&
|
|
56
59
|
loserTargetDrawPosition !== undefined &&
|
|
57
60
|
!getPositionAssignments({
|
|
@@ -135,19 +138,21 @@ function doubleExitAdvancement(params) {
|
|
|
135
138
|
});
|
|
136
139
|
if (result.error)
|
|
137
140
|
return decorateResult({ result, stack });
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
141
|
+
if (result.stamped) {
|
|
142
|
+
const refreshed = getAllDrawMatchUps({ inContext: true, drawDefinition, matchUpsMap })?.matchUps ?? [];
|
|
143
|
+
const carried = carryExitOnward({
|
|
144
|
+
fromMatchUp: refreshed.find((m) => m.matchUpId === loserMatchUp.matchUpId) ?? loserMatchUp,
|
|
145
|
+
EXIT: producedExitStatus(params.matchUpStatus),
|
|
146
|
+
originMatchUpId: sourceMatchUp?.matchUpId,
|
|
147
|
+
inContextDrawMatchUps: refreshed,
|
|
148
|
+
drawDefinition,
|
|
149
|
+
matchUpsMap,
|
|
150
|
+
params,
|
|
151
|
+
stack,
|
|
152
|
+
});
|
|
153
|
+
if (carried.error)
|
|
154
|
+
return decorateResult({ result: carried, stack });
|
|
155
|
+
}
|
|
151
156
|
}
|
|
152
157
|
if (winnerMatchUp) {
|
|
153
158
|
logAdvancement(stack, {
|
|
@@ -169,7 +174,7 @@ function doubleExitAdvancement(params) {
|
|
|
169
174
|
}
|
|
170
175
|
function handleLoserMatchUp({ loserMatchUpIsEmptyExit, loserMatchUpIsDoubleExit, loserTargetDrawPosition, appliedPolicies, tournamentRecord, drawDefinition, sourceMatchUp, loserMatchUp, targetLinks, matchUpsMap, params, event, stack, }) {
|
|
171
176
|
const { loserTargetLink } = targetLinks;
|
|
172
|
-
const propagateBye = appliedPolicies
|
|
177
|
+
const propagateBye = propagatesByeOnDoubleExit(appliedPolicies);
|
|
173
178
|
const targetFedIn = loserMatchUp.hasFedDrawPosition;
|
|
174
179
|
if (propagateBye || targetFedIn) {
|
|
175
180
|
logAdvancement(stack, {
|
|
@@ -230,12 +235,12 @@ function stampExitOnByeHeldLoserTarget({ loserTargetDrawPosition, drawDefinition
|
|
|
230
235
|
const { positionAssignments } = getPositionAssignments({ structureId: loserMatchUp.structureId, drawDefinition });
|
|
231
236
|
const targetAssignment = positionAssignments?.find((assignment) => assignment.drawPosition === loserTargetDrawPosition);
|
|
232
237
|
if (targetAssignment?.bye || targetAssignment?.participantId)
|
|
233
|
-
return { ...SUCCESS };
|
|
238
|
+
return { ...SUCCESS, stamped: false };
|
|
234
239
|
const drawPositions = loserMatchUp.drawPositions ?? [];
|
|
235
240
|
const positionIndex = drawPositions.indexOf(loserTargetDrawPosition);
|
|
236
241
|
const exitingSideNumber = loserMatchUp.feedRound ? 1 : positionIndex + 1;
|
|
237
242
|
if (positionIndex === -1 || (exitingSideNumber !== 1 && exitingSideNumber !== 2)) {
|
|
238
|
-
return { ...SUCCESS };
|
|
243
|
+
return { ...SUCCESS, stamped: false };
|
|
239
244
|
}
|
|
240
245
|
const noContextLoserMatchUp = matchUpsMap.drawMatchUps.find((matchUp) => matchUp.matchUpId === loserMatchUp.matchUpId);
|
|
241
246
|
if (!noContextLoserMatchUp)
|
|
@@ -258,7 +263,7 @@ function stampExitOnByeHeldLoserTarget({ loserTargetDrawPosition, drawDefinition
|
|
|
258
263
|
exitingSideNumber,
|
|
259
264
|
});
|
|
260
265
|
const result = modifyMatchUpScore({
|
|
261
|
-
matchUpStatusCodes:
|
|
266
|
+
matchUpStatusCodes: retainPolicyCodes(noContextLoserMatchUp),
|
|
262
267
|
appliedPolicies: params.appliedPolicies,
|
|
263
268
|
matchUpId: loserMatchUp.matchUpId,
|
|
264
269
|
matchUp: noContextLoserMatchUp,
|
|
@@ -269,7 +274,7 @@ function stampExitOnByeHeldLoserTarget({ loserTargetDrawPosition, drawDefinition
|
|
|
269
274
|
if (result.error)
|
|
270
275
|
return result;
|
|
271
276
|
mergeSideExitProvenance({ matchUp: noContextLoserMatchUp, provenance });
|
|
272
|
-
return { ...SUCCESS };
|
|
277
|
+
return { ...SUCCESS, stamped: true };
|
|
273
278
|
}
|
|
274
279
|
function handleEmptyExitLoser({ loserTargetDrawPosition, drawDefinition, sourceMatchUp, loserMatchUp, matchUpsMap, params, stack, }) {
|
|
275
280
|
const DOUBLE_EXIT = collapseDoubleExitStatus([params.matchUpStatus, loserMatchUp?.matchUpStatus]);
|
|
@@ -293,7 +298,7 @@ function handleEmptyExitLoser({ loserTargetDrawPosition, drawDefinition, sourceM
|
|
|
293
298
|
...getSideExitProvenance({ matchUp: noContextLoserMatchUp }),
|
|
294
299
|
...arrivingProvenance,
|
|
295
300
|
};
|
|
296
|
-
const matchUpStatusCodes =
|
|
301
|
+
const matchUpStatusCodes = retainPolicyCodes(noContextLoserMatchUp);
|
|
297
302
|
const result = modifyMatchUpScore({
|
|
298
303
|
...params,
|
|
299
304
|
matchUp: noContextLoserMatchUp,
|
|
@@ -305,37 +310,48 @@ function handleEmptyExitLoser({ loserTargetDrawPosition, drawDefinition, sourceM
|
|
|
305
310
|
if (result.error)
|
|
306
311
|
return result;
|
|
307
312
|
mergeSideExitProvenance({ matchUp: noContextLoserMatchUp, provenance });
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
matchUpId: loserMatchUp.matchUpId,
|
|
311
|
-
inContextDrawMatchUps: refreshed,
|
|
313
|
+
const onward = advanceConvergedWinner({
|
|
314
|
+
convergedMatchUp: loserMatchUp,
|
|
312
315
|
drawDefinition,
|
|
316
|
+
matchUpsMap,
|
|
317
|
+
DOUBLE_EXIT,
|
|
318
|
+
params,
|
|
319
|
+
stack,
|
|
313
320
|
});
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
logAdvancement(stack, {
|
|
317
|
-
color: 'cyan',
|
|
318
|
-
decision: 'CONVERGED_advance_its_own_winner',
|
|
319
|
-
from: loserMatchUp.matchUpId,
|
|
320
|
-
to: convergedWinnerMatchUp.matchUpId,
|
|
321
|
-
});
|
|
322
|
-
const onward = conditionallyAdvanceDrawPosition({
|
|
323
|
-
...params,
|
|
324
|
-
inContextDrawMatchUps: refreshed,
|
|
325
|
-
matchUpId: convergedWinnerMatchUp.matchUpId,
|
|
326
|
-
targetMatchUp: convergedWinnerMatchUp,
|
|
327
|
-
sourceMatchUp: inContextLoserMatchUp(refreshed, loserMatchUp.matchUpId) ?? loserMatchUp,
|
|
328
|
-
matchUpStatus: DOUBLE_EXIT,
|
|
329
|
-
drawDefinition,
|
|
330
|
-
matchUpsMap,
|
|
331
|
-
});
|
|
332
|
-
if (onward?.error)
|
|
333
|
-
return onward;
|
|
334
|
-
}
|
|
321
|
+
if (onward?.error)
|
|
322
|
+
return onward;
|
|
335
323
|
return result;
|
|
336
324
|
}
|
|
337
325
|
return { ...SUCCESS };
|
|
338
326
|
}
|
|
327
|
+
function advanceConvergedWinner({ convergedMatchUp, drawDefinition, matchUpsMap, DOUBLE_EXIT, params, stack }) {
|
|
328
|
+
const refreshed = getAllDrawMatchUps({ inContext: true, drawDefinition, matchUpsMap })?.matchUps ?? [];
|
|
329
|
+
const convergedTargets = positionTargets({
|
|
330
|
+
matchUpId: convergedMatchUp.matchUpId,
|
|
331
|
+
inContextDrawMatchUps: refreshed,
|
|
332
|
+
drawDefinition,
|
|
333
|
+
});
|
|
334
|
+
const convergedWinnerMatchUp = convergedTargets?.targetMatchUps?.winnerMatchUp;
|
|
335
|
+
if (!convergedWinnerMatchUp)
|
|
336
|
+
return { ...SUCCESS };
|
|
337
|
+
logAdvancement(stack, {
|
|
338
|
+
color: 'cyan',
|
|
339
|
+
decision: 'CONVERGED_advance_its_own_winner',
|
|
340
|
+
from: convergedMatchUp.matchUpId,
|
|
341
|
+
to: convergedWinnerMatchUp.matchUpId,
|
|
342
|
+
});
|
|
343
|
+
return conditionallyAdvanceDrawPosition({
|
|
344
|
+
...params,
|
|
345
|
+
walkoverWinningSide: undefined,
|
|
346
|
+
inContextDrawMatchUps: refreshed,
|
|
347
|
+
matchUpId: convergedWinnerMatchUp.matchUpId,
|
|
348
|
+
targetMatchUp: convergedWinnerMatchUp,
|
|
349
|
+
sourceMatchUp: inContextLoserMatchUp(refreshed, convergedMatchUp.matchUpId) ?? convergedMatchUp,
|
|
350
|
+
matchUpStatus: DOUBLE_EXIT,
|
|
351
|
+
drawDefinition,
|
|
352
|
+
matchUpsMap,
|
|
353
|
+
});
|
|
354
|
+
}
|
|
339
355
|
function inContextLoserMatchUp(inContextDrawMatchUps, matchUpId) {
|
|
340
356
|
return inContextDrawMatchUps.find((candidate) => candidate.matchUpId === matchUpId);
|
|
341
357
|
}
|
|
@@ -369,6 +385,20 @@ function conditionallyAdvanceDrawPosition(params) {
|
|
|
369
385
|
EXIT,
|
|
370
386
|
});
|
|
371
387
|
if (sameStructure && overlap(sourceDrawPositions, targetMatchUpDrawPositions)) {
|
|
388
|
+
if (isDoubleExit(params.matchUpStatus)) {
|
|
389
|
+
for (const drawPosition of targetMatchUpDrawPositions.filter((position) => sourceDrawPositions.includes(position))) {
|
|
390
|
+
releaseAdvancedDrawPosition({
|
|
391
|
+
fromRoundNumber: targetMatchUp.roundNumber,
|
|
392
|
+
structureId: targetMatchUp.structureId,
|
|
393
|
+
withdrawingExit: true,
|
|
394
|
+
event: params.event,
|
|
395
|
+
tournamentRecord,
|
|
396
|
+
drawDefinition,
|
|
397
|
+
drawPosition,
|
|
398
|
+
matchUpsMap,
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
}
|
|
372
402
|
targetMatchUpDrawPositions = targetMatchUpDrawPositions.filter((drawPosition) => !sourceDrawPositions.includes(drawPosition));
|
|
373
403
|
}
|
|
374
404
|
if (sameStructure && targetMatchUpDrawPositions.length > 1)
|
|
@@ -455,11 +485,7 @@ function conditionallyAdvanceDrawPosition(params) {
|
|
|
455
485
|
sourceMatchUpStatus,
|
|
456
486
|
sourceSideNumber,
|
|
457
487
|
});
|
|
458
|
-
const
|
|
459
|
-
...getSideExitProvenance({ matchUp: noContextTargetMatchUp }),
|
|
460
|
-
...newProvenance,
|
|
461
|
-
};
|
|
462
|
-
const matchUpStatusCodes = newProvenance ? projectExitStatusCodes(provenance) : [];
|
|
488
|
+
const matchUpStatusCodes = retainPolicyCodes(noContextTargetMatchUp);
|
|
463
489
|
logAdvancement(stack, {
|
|
464
490
|
color: 'brightgreen',
|
|
465
491
|
keyColors: { matchUpStatus: 'brightcyan', winningSide: 'brightyellow' },
|
|
@@ -482,9 +508,27 @@ function conditionallyAdvanceDrawPosition(params) {
|
|
|
482
508
|
if (result.error)
|
|
483
509
|
return decorateResult({ result, stack });
|
|
484
510
|
mergeSideExitProvenance({ matchUp: noContextTargetMatchUp, provenance: newProvenance });
|
|
511
|
+
const merged = getSideExitProvenance({ matchUp: noContextTargetMatchUp });
|
|
512
|
+
const bothDelivered = [1, 2].every((sideNumber) => isDoubleExit(merged?.[sideNumber]?.previousMatchUpStatus));
|
|
513
|
+
const convergedAfterMerge = bothDelivered && !targetHoldsBye;
|
|
514
|
+
{
|
|
515
|
+
const derived = bothDelivered ? deriveExitStateFromProvenance(merged) : undefined;
|
|
516
|
+
if (derived && !targetHoldsBye && derived.matchUpStatus !== noContextTargetMatchUp.matchUpStatus) {
|
|
517
|
+
const reconcile = modifyMatchUpScore({
|
|
518
|
+
...params,
|
|
519
|
+
removeWinningSide: derived.winningSide === undefined,
|
|
520
|
+
winningSide: derived.winningSide,
|
|
521
|
+
matchUp: noContextTargetMatchUp,
|
|
522
|
+
matchUpStatus: derived.matchUpStatus,
|
|
523
|
+
matchUpStatusCodes: deriveStatusCodes(noContextTargetMatchUp)});
|
|
524
|
+
if (reconcile.error)
|
|
525
|
+
return decorateResult({ result: reconcile, stack });
|
|
526
|
+
}
|
|
527
|
+
}
|
|
485
528
|
return advanceFromTarget({
|
|
486
529
|
pairedPreviousMatchUpIsDoubleExit,
|
|
487
530
|
targetMatchUpDrawPositions,
|
|
531
|
+
convergedAfterMerge,
|
|
488
532
|
noContextTargetMatchUp,
|
|
489
533
|
inContextDrawMatchUps,
|
|
490
534
|
walkoverWinningSide,
|
|
@@ -529,7 +573,17 @@ function inferSourceSideNumber({ inContextPairedPreviousMatchUp, pairedPreviousM
|
|
|
529
573
|
});
|
|
530
574
|
return sourceSideNumber;
|
|
531
575
|
}
|
|
532
|
-
function advanceFromTarget({ pairedPreviousMatchUpIsDoubleExit, targetMatchUpDrawPositions, noContextTargetMatchUp, inContextDrawMatchUps, walkoverWinningSide, nextWinnerMatchUp, drawDefinition, existingExit, matchUpStatus, targetMatchUp, matchUpsMap, targetData, DOUBLE_EXIT, structure, params, stack, EXIT, }) {
|
|
576
|
+
function advanceFromTarget({ pairedPreviousMatchUpIsDoubleExit, targetMatchUpDrawPositions, convergedAfterMerge, noContextTargetMatchUp, inContextDrawMatchUps, walkoverWinningSide, nextWinnerMatchUp, drawDefinition, existingExit, matchUpStatus, targetMatchUp, matchUpsMap, targetData, DOUBLE_EXIT, structure, params, stack, EXIT, }) {
|
|
577
|
+
if (convergedAfterMerge && !existingExit) {
|
|
578
|
+
return advanceConvergedWinner({
|
|
579
|
+
convergedMatchUp: targetMatchUp,
|
|
580
|
+
drawDefinition,
|
|
581
|
+
matchUpsMap,
|
|
582
|
+
DOUBLE_EXIT,
|
|
583
|
+
params,
|
|
584
|
+
stack,
|
|
585
|
+
});
|
|
586
|
+
}
|
|
533
587
|
if (existingExit) {
|
|
534
588
|
logAdvancement(stack, {
|
|
535
589
|
color: 'brightred',
|
|
@@ -656,7 +710,7 @@ function advanceByeAdvancedDrawPosition({ nextWinnerMatchUpDrawPositions, nextWi
|
|
|
656
710
|
}),
|
|
657
711
|
};
|
|
658
712
|
const result = modifyMatchUpScore({
|
|
659
|
-
matchUpStatusCodes:
|
|
713
|
+
matchUpStatusCodes: retainPolicyCodes(noContextNextWinnerMatchUp),
|
|
660
714
|
appliedPolicies: params.appliedPolicies,
|
|
661
715
|
matchUpId: noContextNextWinnerMatchUp.matchUpId,
|
|
662
716
|
matchUp: noContextNextWinnerMatchUp,
|
|
@@ -815,7 +869,7 @@ function carryExitOnward({ inContextDrawMatchUps, drawDefinition, matchUpsMap, o
|
|
|
815
869
|
matchUpStatus: holdsBye ? BYE : EXIT,
|
|
816
870
|
});
|
|
817
871
|
const result = modifyMatchUpScore({
|
|
818
|
-
matchUpStatusCodes:
|
|
872
|
+
matchUpStatusCodes: retainPolicyCodes(noContextNextWinnerMatchUp),
|
|
819
873
|
matchUpId: noContextNextWinnerMatchUp.matchUpId,
|
|
820
874
|
appliedPolicies: params.appliedPolicies,
|
|
821
875
|
matchUp: noContextNextWinnerMatchUp,
|
|
@@ -927,5 +981,149 @@ function advanceByeToLoserMatchUp(params) {
|
|
|
927
981
|
event,
|
|
928
982
|
});
|
|
929
983
|
}
|
|
984
|
+
function settleHeldExits({ tournamentRecord, appliedPolicies, drawDefinition, event }) {
|
|
985
|
+
const stack = 'settleHeldExits';
|
|
986
|
+
if (!drawDefinition || propagatesByeOnDoubleExit(appliedPolicies))
|
|
987
|
+
return { ...SUCCESS };
|
|
988
|
+
const matchUpsMap = getMatchUpsMap({ drawDefinition });
|
|
989
|
+
const carried = new Set();
|
|
990
|
+
for (let pass = 0; pass < 16; pass++) {
|
|
991
|
+
const inContextDrawMatchUps = getAllDrawMatchUps({ inContext: true, drawDefinition, matchUpsMap })?.matchUps ?? [];
|
|
992
|
+
let held;
|
|
993
|
+
for (const matchUp of inContextDrawMatchUps) {
|
|
994
|
+
if (carried.has(matchUp.matchUpId))
|
|
995
|
+
continue;
|
|
996
|
+
held = getHeldExit({ inContextDrawMatchUps, drawDefinition, matchUpsMap, matchUp });
|
|
997
|
+
if (held)
|
|
998
|
+
break;
|
|
999
|
+
}
|
|
1000
|
+
if (!held)
|
|
1001
|
+
break;
|
|
1002
|
+
carried.add(held.holder.matchUpId);
|
|
1003
|
+
const params = {
|
|
1004
|
+
matchUpStatus: held.origin.previousMatchUpStatus ?? held.origin.matchUpStatus,
|
|
1005
|
+
tournamentRecord,
|
|
1006
|
+
appliedPolicies,
|
|
1007
|
+
event,
|
|
1008
|
+
};
|
|
1009
|
+
const result = carryExitOnward({
|
|
1010
|
+
originMatchUpId: held.origin.sourceMatchUpId,
|
|
1011
|
+
EXIT: held.origin.matchUpStatus,
|
|
1012
|
+
fromMatchUp: held.holder,
|
|
1013
|
+
inContextDrawMatchUps,
|
|
1014
|
+
drawDefinition,
|
|
1015
|
+
matchUpsMap,
|
|
1016
|
+
params,
|
|
1017
|
+
stack,
|
|
1018
|
+
});
|
|
1019
|
+
if (result?.error)
|
|
1020
|
+
return decorateResult({ result, stack });
|
|
1021
|
+
}
|
|
1022
|
+
const crossed = crossLinksThroughByes({ tournamentRecord, drawDefinition, matchUpsMap, event, stack });
|
|
1023
|
+
if (crossed.error)
|
|
1024
|
+
return decorateResult({ result: crossed, stack });
|
|
1025
|
+
return { ...SUCCESS };
|
|
1026
|
+
}
|
|
1027
|
+
function crossLinksThroughByes({ tournamentRecord, drawDefinition, matchUpsMap, event, stack }) {
|
|
1028
|
+
for (let pass = 0; pass < 16; pass++) {
|
|
1029
|
+
const inContextDrawMatchUps = getAllDrawMatchUps({ inContext: true, drawDefinition, matchUpsMap })?.matchUps ?? [];
|
|
1030
|
+
const crossing = inContextDrawMatchUps
|
|
1031
|
+
.map((matchUp) => getByeCrossing({ inContextDrawMatchUps, drawDefinition, matchUp }))
|
|
1032
|
+
.find(Boolean);
|
|
1033
|
+
if (!crossing)
|
|
1034
|
+
break;
|
|
1035
|
+
logAdvancement(stack, {
|
|
1036
|
+
color: 'cyan',
|
|
1037
|
+
decision: 'BYE_advancement_crosses_winner_link',
|
|
1038
|
+
fromMatchUpId: crossing.matchUp.matchUpId,
|
|
1039
|
+
winnerMatchUpId: crossing.winnerMatchUp.matchUpId,
|
|
1040
|
+
});
|
|
1041
|
+
const result = directWinner({
|
|
1042
|
+
winnerMatchUpDrawPositionIndex: crossing.winnerMatchUpDrawPositionIndex,
|
|
1043
|
+
winningDrawPosition: crossing.drawPosition,
|
|
1044
|
+
winnerTargetLink: crossing.winnerTargetLink,
|
|
1045
|
+
sourceMatchUpId: crossing.matchUp.matchUpId,
|
|
1046
|
+
winnerMatchUp: crossing.winnerMatchUp,
|
|
1047
|
+
projectedWinningSide: undefined,
|
|
1048
|
+
sourceMatchUpStatus: undefined,
|
|
1049
|
+
dualMatchUp: undefined,
|
|
1050
|
+
inContextDrawMatchUps,
|
|
1051
|
+
tournamentRecord,
|
|
1052
|
+
drawDefinition,
|
|
1053
|
+
matchUpsMap,
|
|
1054
|
+
event,
|
|
1055
|
+
});
|
|
1056
|
+
if (result.error)
|
|
1057
|
+
return result;
|
|
1058
|
+
const after = getAllDrawMatchUps({ inContext: true, drawDefinition, matchUpsMap })?.matchUps ?? [];
|
|
1059
|
+
const target = after.find((matchUp) => matchUp.matchUpId === crossing.winnerMatchUp.matchUpId);
|
|
1060
|
+
if (!target?.sides?.some((side) => side.participantId === crossing.participantId))
|
|
1061
|
+
break;
|
|
1062
|
+
}
|
|
1063
|
+
return { ...SUCCESS };
|
|
1064
|
+
}
|
|
1065
|
+
function getByeCrossing({ inContextDrawMatchUps, drawDefinition, matchUp }) {
|
|
1066
|
+
if (matchUp.collectionId || !matchUp.winnerMatchUpId)
|
|
1067
|
+
return undefined;
|
|
1068
|
+
const occupants = (matchUp.sides ?? []).filter((side) => side.participantId && !side.bye);
|
|
1069
|
+
if (occupants.length !== 1 || !matchUpHoldsBye({ drawDefinition, matchUp }))
|
|
1070
|
+
return undefined;
|
|
1071
|
+
const { targetMatchUps, targetLinks } = positionTargets({
|
|
1072
|
+
matchUpId: matchUp.matchUpId,
|
|
1073
|
+
inContextDrawMatchUps,
|
|
1074
|
+
drawDefinition,
|
|
1075
|
+
});
|
|
1076
|
+
const winnerMatchUp = targetMatchUps?.winnerMatchUp;
|
|
1077
|
+
const winnerTargetLink = targetLinks?.winnerTargetLink;
|
|
1078
|
+
if (!winnerMatchUp || !winnerTargetLink || winnerMatchUp.structureId === matchUp.structureId)
|
|
1079
|
+
return undefined;
|
|
1080
|
+
if (winnerMatchUp.winningSide)
|
|
1081
|
+
return undefined;
|
|
1082
|
+
const [{ participantId, drawPosition }] = occupants;
|
|
1083
|
+
if (winnerMatchUp.sides?.some((side) => side.participantId === participantId))
|
|
1084
|
+
return undefined;
|
|
1085
|
+
return {
|
|
1086
|
+
winnerMatchUpDrawPositionIndex: targetMatchUps.winnerMatchUpDrawPositionIndex,
|
|
1087
|
+
winnerTargetLink,
|
|
1088
|
+
winnerMatchUp,
|
|
1089
|
+
participantId,
|
|
1090
|
+
drawPosition,
|
|
1091
|
+
matchUp,
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
function getHeldExit({ inContextDrawMatchUps, drawDefinition, matchUpsMap, matchUp }) {
|
|
1095
|
+
if (matchUp.collectionId || matchUp.winningSide || !matchUp.winnerMatchUpId)
|
|
1096
|
+
return undefined;
|
|
1097
|
+
if (matchUp.sides?.some((side) => side.participantId))
|
|
1098
|
+
return undefined;
|
|
1099
|
+
if (!matchUpHoldsBye({ drawDefinition, matchUp }))
|
|
1100
|
+
return undefined;
|
|
1101
|
+
const stored = matchUpsMap.drawMatchUps.find((candidate) => candidate.matchUpId === matchUp.matchUpId);
|
|
1102
|
+
const [exitSideNumber] = getExitSides({ matchUp: stored });
|
|
1103
|
+
const origin = exitSideNumber ? getSideExitProvenance({ matchUp: stored })?.[exitSideNumber] : undefined;
|
|
1104
|
+
if (!origin?.sourceMatchUpId || !isExit(origin.matchUpStatus))
|
|
1105
|
+
return undefined;
|
|
1106
|
+
const target = inContextDrawMatchUps.find((candidate) => candidate.matchUpId === matchUp.winnerMatchUpId);
|
|
1107
|
+
if (!target || target.winningSide)
|
|
1108
|
+
return undefined;
|
|
1109
|
+
const arrivalSideNumber = getExitArrivalSideNumber({
|
|
1110
|
+
nextWinnerMatchUp: target,
|
|
1111
|
+
sourceMatchUp: matchUp,
|
|
1112
|
+
inContextDrawMatchUps,
|
|
1113
|
+
});
|
|
1114
|
+
if (!arrivalSideNumber)
|
|
1115
|
+
return undefined;
|
|
1116
|
+
if (target.sides?.some((side) => side.sideNumber === arrivalSideNumber && side.participantId))
|
|
1117
|
+
return undefined;
|
|
1118
|
+
const storedTarget = matchUpsMap.drawMatchUps.find((candidate) => candidate.matchUpId === target.matchUpId);
|
|
1119
|
+
const targetProvenance = getSideExitProvenance({ matchUp: storedTarget });
|
|
1120
|
+
if (targetProvenance?.[arrivalSideNumber])
|
|
1121
|
+
return undefined;
|
|
1122
|
+
const opponentSide = target.sides?.find((side) => side.sideNumber === 3 - arrivalSideNumber);
|
|
1123
|
+
const settledNow = !!opponentSide?.participantId || !!opponentSide?.bye;
|
|
1124
|
+
if (!settledNow)
|
|
1125
|
+
return undefined;
|
|
1126
|
+
return { holder: matchUp, origin };
|
|
1127
|
+
}
|
|
930
1128
|
|
|
931
|
-
export { doubleExitAdvancement };
|
|
1129
|
+
export { doubleExitAdvancement, settleHeldExits };
|