tods-competition-factory 7.2.0 → 7.4.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.
Files changed (47) hide show
  1. package/README.md +1 -1
  2. package/dist/esm/assemblies/generators/mocks/processLeagueProfiles.mjs +2 -1
  3. package/dist/esm/assemblies/governors/scoreGovernor/index.mjs +2 -1
  4. package/dist/esm/assemblies/governors/scoreGovernor/query.mjs +2 -1
  5. package/dist/esm/constants/matchUpStatusConstants.mjs +1 -1
  6. package/dist/esm/fixtures/policies/POLICY_PROGRESSION_DEFAULT.mjs +1 -1
  7. package/dist/esm/mutate/drawDefinitions/matchUpGovernor/noDownstreamDependencies.mjs +4 -0
  8. package/dist/esm/mutate/drawDefinitions/matchUpGovernor/{matchUpStatusCodes.mjs → recordSourceSideProvenance.mjs} +3 -14
  9. package/dist/esm/mutate/drawDefinitions/matchUpGovernor/removeDoubleExit.mjs +12 -25
  10. package/dist/esm/mutate/drawDefinitions/matchUpGovernor/unwindDualDoubleExit.mjs +13 -0
  11. package/dist/esm/mutate/drawDefinitions/positionGovernor/doubleExitAdvancement.mjs +266 -61
  12. package/dist/esm/mutate/matchUps/drawPositions/assignDrawPositionBye.mjs +69 -45
  13. package/dist/esm/mutate/matchUps/drawPositions/directParticipants.mjs +1 -0
  14. package/dist/esm/mutate/matchUps/drawPositions/drawPositionPlacement.mjs +26 -25
  15. package/dist/esm/mutate/matchUps/drawPositions/positionClear.mjs +60 -3
  16. package/dist/esm/mutate/matchUps/drawPositions/progressExitStatus.mjs +20 -13
  17. package/dist/esm/mutate/matchUps/drawPositions/propagateUnfillableLoserBye.mjs +22 -8
  18. package/dist/esm/mutate/matchUps/drawPositions/propagatesByeOnDoubleExit.mjs +5 -0
  19. package/dist/esm/mutate/matchUps/drawPositions/releaseAdvancedDrawPosition.mjs +22 -1
  20. package/dist/esm/mutate/matchUps/drawPositions/removeDirectedParticipants.mjs +5 -4
  21. package/dist/esm/mutate/matchUps/drawPositions/removeSubsequentRoundsParticipant.mjs +4 -3
  22. package/dist/esm/mutate/matchUps/matchUpStatus/applyWithdrawnExits.mjs +1 -0
  23. package/dist/esm/mutate/matchUps/matchUpStatus/reconcileDecider.mjs +104 -0
  24. package/dist/esm/mutate/matchUps/matchUpStatus/reconcileStaleExitOrigins.mjs +65 -0
  25. package/dist/esm/mutate/matchUps/matchUpStatus/setMatchUpState.mjs +11 -3
  26. package/dist/esm/mutate/matchUps/matchUpStatus/setMatchUpStatus.mjs +50 -16
  27. package/dist/esm/mutate/matchUps/matchUpStatus/sideExitProvenance.mjs +94 -45
  28. package/dist/esm/mutate/matchUps/matchUpStatus/sideStatusCodes.mjs +36 -0
  29. package/dist/esm/mutate/matchUps/score/modifyMatchUpScore.mjs +16 -0
  30. package/dist/esm/mutate/venues/modifyCourt.mjs +1 -1
  31. package/dist/esm/package.json.mjs +1 -1
  32. package/dist/esm/query/drawDefinition/getStructureInconsistencies.mjs +67 -6
  33. package/dist/esm/query/matchUp/analyzeMatchUp.mjs +29 -2
  34. package/dist/esm/query/matchUp/checkSetIsComplete.mjs +15 -5
  35. package/dist/esm/query/matchUp/getComplement.mjs +19 -1
  36. package/dist/esm/query/matchUp/retainScoreForFormat.mjs +57 -0
  37. package/dist/esm/query/matchUps/getDrawPositionSides.mjs +11 -1
  38. package/dist/esm/validators/validateMatchUpScore.mjs +23 -4
  39. package/dist/schema/tournament.schema.json +4421 -0
  40. package/dist/tods-competition-factory.d.cts +60 -22
  41. package/dist/tods-competition-factory.d.mts +60 -22
  42. package/dist/tods-competition-factory.d.ts +60 -22
  43. package/dist/tods-competition-factory.development.cjs.js +1618 -823
  44. package/dist/tods-competition-factory.development.cjs.js.map +1 -1
  45. package/dist/tods-competition-factory.production.cjs.min.js +1 -1
  46. package/dist/tods-competition-factory.production.cjs.min.js.map +1 -1
  47. package/package.json +31 -27
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,000+ tests** covering draw generation and exit propagation, scheduling, scoring, participants and entries, team competition, publishing and embargo, ranking points and ratings, officiating and sanctioning.
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 { CANCELLED, ABANDONED, COMPLETED, DEAD_RUBBER, DEFAULTED, DOUBLE_WALKOVER, DOUBLE_DEFAULT, RETIRED, WALKOVER, TO_BE_PLAYED, SUSPENDED, NOT_PLAYED, INCOMPLETE, IN_PROGRESS, CHALLENGED, BYE, AWAITING_RESULT } from './matchUpStatusValues.mjs';
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: false,
5
+ doubleExitPropagateBye: true,
6
6
  autoPlaceQualifiers: false,
7
7
  autoReplaceQualifiers: false,
8
8
  autoRemoveQualifiers: false,
@@ -8,6 +8,7 @@ import { checkConnectedStructures } from './checkConnectedStructures.mjs';
8
8
  import { attemptToSetWinningSide } from './attemptToSetWinningSide.mjs';
9
9
  import { decorateResult } from '../../../functions/global/decorateResult.mjs';
10
10
  import { attemptToModifyScore } from './attemptToModifyScore.mjs';
11
+ import { unwindDualDoubleExit } from './unwindDualDoubleExit.mjs';
11
12
  import { pushGlobalLog } from '../../../functions/global/globalLog.mjs';
12
13
  import { isExit, isDoubleExit } from '../../../validators/isExit.mjs';
13
14
  import { removeDoubleExit } from './removeDoubleExit.mjs';
@@ -25,6 +26,9 @@ function noDownstreamDependencies(params) {
25
26
  if (result.error)
26
27
  return decorateResult({ result, stack });
27
28
  }
29
+ const dualUnwound = unwindDualDoubleExit(params);
30
+ if (dualUnwound.error)
31
+ return decorateResult({ result: dualUnwound, stack });
28
32
  const doubleExit = isDoubleExit(matchUpStatus);
29
33
  const preserveScoreStatuses = [IN_PROGRESS, SUSPENDED, CANCELLED, ABANDONED, INCOMPLETE];
30
34
  const scoreWithNoWinningSide = checkScoreHasValue({ score }) &&
@@ -1,9 +1,9 @@
1
- import { producedExitStatus, mergeSideExitProvenance } from '../../matchUps/matchUpStatus/sideExitProvenance.mjs';
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 updateMatchUpStatusCodes({ inContextDrawMatchUps, sourceMatchUpStatus, sourceMatchUpId, matchUpsMap, matchUp, }) {
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 { updateMatchUpStatusCodes };
36
+ export { recordSourceSideProvenance };
@@ -1,17 +1,17 @@
1
- import { withdrawByeClaim, withdrawByeClaimsFrom, byeClaimSurvives, getNativeSideExitProvenance, projectExitStatusCodes, setSideExitProvenance, retainForeignProvenance, deriveExitStateFromProvenance } from '../../matchUps/matchUpStatus/sideExitProvenance.mjs';
2
1
  import { removeDirectedBye, removeDirectedWinner } from '../../matchUps/drawPositions/removeDirectedParticipants.mjs';
2
+ import { propagatesByeOnDoubleExit } from '../../matchUps/drawPositions/propagatesByeOnDoubleExit.mjs';
3
3
  import { getPairedPreviousMatchUp } from '../../../query/matchUps/getPairedPreviousMatchup.mjs';
4
4
  import { modifyMatchUpScore } from '../../matchUps/score/modifyMatchUpScore.mjs';
5
5
  import { decorateResult } from '../../../functions/global/decorateResult.mjs';
6
- import { chunkArray, intersection, overlap } from '../../../tools/arrays.mjs';
7
6
  import { positionTargets } from '../../../query/matchUp/positionTargets.mjs';
8
7
  import { pushGlobalLog } from '../../../functions/global/globalLog.mjs';
9
8
  import { findStructure } from '../../../acquire/findStructure.mjs';
9
+ import { intersection, overlap } from '../../../tools/arrays.mjs';
10
10
  import { isDoubleExit } from '../../../validators/isExit.mjs';
11
- import { FIRST_MATCHUP } from '../../../constants/drawDefinitionConstants.mjs';
11
+ import { withdrawByeClaim, withdrawByeClaimsFrom, byeClaimSurvives, getSideExitProvenance, retainPolicyCodes, setSideExitProvenance, retainForeignProvenance, deriveExitStateFromProvenance } from '../../matchUps/matchUpStatus/sideExitProvenance.mjs';
12
12
  import { SUCCESS } from '../../../constants/resultConstants.mjs';
13
13
  import { completedMatchUpStatuses } from '../../../constants/matchUpStatusConstants.mjs';
14
- import { BYE, DOUBLE_DEFAULT, DOUBLE_WALKOVER, DEFAULTED, WALKOVER, TO_BE_PLAYED } from '../../../constants/matchUpStatusValues.mjs';
14
+ import { BYE, DOUBLE_WALKOVER, DOUBLE_DEFAULT, DEFAULTED, WALKOVER, TO_BE_PLAYED } from '../../../constants/matchUpStatusValues.mjs';
15
15
 
16
16
  const keyColors = {
17
17
  drawPositionToRemove: 'green',
@@ -60,19 +60,6 @@ function removeDoubleExit(params) {
60
60
  const claimSideNumber = (rawLoserMatchUp?.drawPositions ?? []).indexOf(loserTargetDrawPosition) + 1 || 1;
61
61
  withdrawByeClaim({ matchUp: rawLoserMatchUp, sideNumber: claimSideNumber, claimantMatchUpId: matchUpId });
62
62
  withdrawByeClaimsFrom({ matchUps: matchUpsMap?.drawMatchUps, claimantMatchUpId: matchUpId });
63
- const isFMLC = targetData?.targetLinks?.loserTargetLink?.linkCondition === FIRST_MATCHUP;
64
- if (byePropagatedToLoserMatchUp && isFMLC) {
65
- const roundMatchUps = inContextDrawMatchUps.filter(({ roundNumber, structureId }) => structureId === matchUp.structureId && roundNumber === 1);
66
- const roundPositions = roundMatchUps.map(({ roundPosition }) => roundPosition);
67
- const pairedPositions = chunkArray(roundPositions.toSorted((a, b) => a - b), 2).find((chunk) => chunk.includes(matchUp.roundPosition));
68
- const pairedMatchUpStatuses = roundMatchUps
69
- .filter(({ roundPosition }) => pairedPositions.includes(roundPosition))
70
- ?.map(({ matchUpStatus }) => matchUpStatus);
71
- const pairedMatchUpIsDoubleExit = pairedMatchUpStatuses.every((matchUpStatus) => [DOUBLE_DEFAULT, DOUBLE_WALKOVER].includes(matchUpStatus));
72
- if (pairedMatchUpIsDoubleExit) {
73
- return decorateResult({ result: { ...SUCCESS }, stack });
74
- }
75
- }
76
63
  if (loserMatchUp && (loserMatchUp.matchUpStatus !== BYE || byePropagatedToLoserMatchUp)) {
77
64
  const inContextLoserMatchUp = inContextDrawMatchUps.find(({ matchUpId }) => matchUpId === loserMatchUp.matchUpId);
78
65
  const { structure: loserStructure } = findStructure({
@@ -98,7 +85,7 @@ function removeDoubleExit(params) {
98
85
  if (anotherClaimSurvives) {
99
86
  return decorateResult({ result: { ...SUCCESS }, stack });
100
87
  }
101
- if (appliedPolicies?.progression?.doubleExitPropagateBye || byePropagatedToLoserMatchUp) {
88
+ if (propagatesByeOnDoubleExit(appliedPolicies) || byePropagatedToLoserMatchUp) {
102
89
  removeDirectedBye({
103
90
  drawPosition: loserTargetDrawPosition,
104
91
  targetLink: loserTargetLink,
@@ -133,7 +120,7 @@ function removeDoubleExit(params) {
133
120
  return decorateResult({ result: { ...SUCCESS }, stack });
134
121
  }
135
122
  function carriesWithdrawnOrigin(matchUp, withdrawnSourceIds) {
136
- const provenance = getNativeSideExitProvenance({ matchUp });
123
+ const provenance = getSideExitProvenance({ matchUp });
137
124
  if (!provenance)
138
125
  return false;
139
126
  return [1, 2].some((sideNumber) => {
@@ -170,7 +157,7 @@ function withdrawExitFromByeChain({ inContextDrawMatchUps, withdrawnSourceIds, d
170
157
  keyColors,
171
158
  });
172
159
  const result = modifyMatchUpScore({
173
- matchUpStatusCodes: unwound.provenance ? projectExitStatusCodes(unwound.provenance) : [],
160
+ matchUpStatusCodes: retainPolicyCodes(noContextTargetMatchUp),
174
161
  removeWinningSide: unwound.winningSide === undefined,
175
162
  matchUpStatus: unwound.matchUpStatus,
176
163
  matchUpId: fromMatchUp.matchUpId,
@@ -308,7 +295,7 @@ function conditionallyRemoveDrawPosition(params) {
308
295
  if (result.error)
309
296
  return decorateResult({ result, stack });
310
297
  const carriesSomethingOfThisCascade = carriesWithdrawnOrigin(noContextTargetMatchUp, withdrawnSourceIds);
311
- const holdsProvenance = !!getNativeSideExitProvenance({ matchUp: noContextTargetMatchUp });
298
+ const holdsProvenance = !!getSideExitProvenance({ matchUp: noContextTargetMatchUp });
312
299
  if (holdsProvenance && !carriesSomethingOfThisCascade) {
313
300
  pushGlobalLog({
314
301
  method: stack,
@@ -329,7 +316,7 @@ function conditionallyRemoveDrawPosition(params) {
329
316
  const removeScore = !pairedPreviousDoubleExit;
330
317
  result = modifyMatchUpScore({
331
318
  ...params,
332
- matchUpStatusCodes: unwound.provenance ? projectExitStatusCodes(unwound.provenance) : [],
319
+ matchUpStatusCodes: retainPolicyCodes(noContextTargetMatchUp),
333
320
  removeWinningSide: unwound.winningSide === undefined,
334
321
  matchUpId: targetMatchUp.matchUpId,
335
322
  matchUp: noContextTargetMatchUp,
@@ -384,10 +371,10 @@ function getUnwoundState({ pairedPreviousDoubleExit, noContextTargetMatchUp, wit
384
371
  if (noContextTargetMatchUp.matchUpStatus === BYE) {
385
372
  return {
386
373
  matchUpStatus: BYE,
387
- provenance: retainForeignProvenance(getNativeSideExitProvenance({ matchUp: noContextTargetMatchUp }), withdrawnSourceIds),
374
+ provenance: retainForeignProvenance(getSideExitProvenance({ matchUp: noContextTargetMatchUp }), withdrawnSourceIds),
388
375
  };
389
376
  }
390
- const retained = retainForeignProvenance(getNativeSideExitProvenance({ matchUp: noContextTargetMatchUp }), withdrawnSourceIds);
377
+ const retained = retainForeignProvenance(getSideExitProvenance({ matchUp: noContextTargetMatchUp }), withdrawnSourceIds);
391
378
  if (pairedPreviousDoubleExit) {
392
379
  return {
393
380
  matchUpStatus: [DOUBLE_DEFAULT, DEFAULTED].includes(noContextTargetMatchUp?.matchUpStatus) ? DEFAULTED : WALKOVER,
@@ -397,7 +384,7 @@ function getUnwoundState({ pairedPreviousDoubleExit, noContextTargetMatchUp, wit
397
384
  if (targetDrawPositionIsBye({ drawDefinition, noContextTargetMatchUp, targetMatchUp })) {
398
385
  return {
399
386
  matchUpStatus: BYE,
400
- provenance: retainForeignProvenance(getNativeSideExitProvenance({ matchUp: noContextTargetMatchUp }), withdrawnSourceIds),
387
+ provenance: retainForeignProvenance(getSideExitProvenance({ matchUp: noContextTargetMatchUp }), withdrawnSourceIds),
401
388
  };
402
389
  }
403
390
  if (isDoubleExit(noContextTargetMatchUp?.matchUpStatus)) {
@@ -0,0 +1,13 @@
1
+ import { removeDoubleExit } from './removeDoubleExit.mjs';
2
+ import { isDoubleExit } from '../../../validators/isExit.mjs';
3
+ import { SUCCESS } from '../../../constants/resultConstants.mjs';
4
+
5
+ function unwindDualDoubleExit(params) {
6
+ const { isCollectionMatchUp, dualMatchUp, matchUpsMap } = params;
7
+ if (!isCollectionMatchUp || !isDoubleExit(dualMatchUp?.matchUpStatus))
8
+ return { ...SUCCESS };
9
+ const rawDual = matchUpsMap?.drawMatchUps?.find((candidate) => candidate.matchUpId === dualMatchUp.matchUpId) ?? dualMatchUp;
10
+ return removeDoubleExit({ ...params, matchUp: rawDual });
11
+ }
12
+
13
+ export { unwindDualDoubleExit };