tods-competition-factory 7.4.0 → 7.6.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/findDrawMatchUp.mjs +10 -1
- package/dist/esm/assemblies/engines/async/asyncEngineInvoke.mjs +4 -2
- package/dist/esm/assemblies/engines/async/asyncExecutionQueue.mjs +4 -2
- package/dist/esm/assemblies/engines/parts/checkMutationLock.mjs +2 -1
- package/dist/esm/assemblies/engines/parts/engineStart.mjs +16 -1
- package/dist/esm/assemblies/engines/parts/executeMethod.mjs +9 -11
- package/dist/esm/assemblies/engines/scoring/ScoringEngine.mjs +29 -24
- package/dist/esm/assemblies/engines/sync/engineInvoke.mjs +4 -2
- package/dist/esm/assemblies/engines/sync/executionQueue.mjs +4 -2
- package/dist/esm/assemblies/generators/drawDefinitions/drawTypes/adHoc/drawMatic/generateCandidate.mjs +3 -2
- package/dist/esm/assemblies/generators/drawDefinitions/drawTypes/adHoc/drawMatic/getPairings.mjs +2 -1
- package/dist/esm/assemblies/generators/drawDefinitions/generateSeedingScaleItems.mjs +2 -1
- package/dist/esm/assemblies/generators/drawDefinitions/getDrawFormat.mjs +1 -0
- package/dist/esm/assemblies/generators/drawDefinitions/validateAndDeriveDrawValues.mjs +3 -0
- package/dist/esm/assemblies/generators/matchUps/generateScoreString.mjs +2 -1
- package/dist/esm/assemblies/generators/matchUps/matchUpScore.mjs +4 -1
- package/dist/esm/assemblies/generators/mocks/applyScenarioProfile.mjs +2 -1
- package/dist/esm/assemblies/generators/mocks/generateOutcome.mjs +27 -1
- package/dist/esm/assemblies/generators/mocks/generateOutcomeFromScoreString.mjs +10 -5
- package/dist/esm/assemblies/generators/mocks/generateParticipants.mjs +1 -1
- package/dist/esm/assemblies/generators/mocks/generatePersons.mjs +1 -1
- package/dist/esm/assemblies/generators/mocks/generateTournamentRecord.mjs +2 -1
- package/dist/esm/assemblies/generators/mocks/processLeagueProfiles.mjs +2 -0
- package/dist/esm/assemblies/generators/scheduling/utils/generateVirtualCourts.mjs +1 -1
- package/dist/esm/assemblies/generators/tournamentRecords/anonymizeTournamentRecord.mjs +4 -3
- package/dist/esm/assemblies/generators/tournamentRecords/copyTournamentRecord.mjs +1 -1
- package/dist/esm/assemblies/generators/tournamentRecords/createTournamentRecord.mjs +1 -1
- package/dist/esm/assemblies/generators/tournamentRecords/generateStatCrew.mjs +1 -1
- package/dist/esm/assemblies/generators/venues/generateCourts.mjs +2 -2
- package/dist/esm/assemblies/governors/matchUpFormatGovernor/index.mjs +1 -0
- package/dist/esm/assemblies/governors/scoreGovernor/help.mjs +1 -0
- package/dist/esm/assemblies/governors/scoreGovernor/index.mjs +1 -0
- package/dist/esm/assemblies/tools/index.mjs +3 -0
- package/dist/esm/constants/errorConditionConstants.mjs +37 -1
- package/dist/esm/constants/index.mjs +1 -0
- package/dist/esm/constants/matchUpActionConstants.mjs +3 -1
- package/dist/esm/constants/matchUpStatusConstants.mjs +0 -1
- package/dist/esm/constants/outcomePipelineConstants.mjs +10 -0
- package/dist/esm/constants/penaltyConstants.mjs +17 -5
- package/dist/esm/constants/scheduleConstants.mjs +5 -1
- package/dist/esm/constants/scoreWarningConstants.mjs +8 -0
- package/dist/esm/errors/subclasses.mjs +16 -13
- package/dist/esm/fixtures/policies/POLICY_POSITION_ACTIONS_DEFAULT.mjs +1 -1
- package/dist/esm/fixtures/policies/POLICY_SCORING_DEFAULT.mjs +3 -3
- package/dist/esm/forge/unwrap.mjs +2 -1
- package/dist/esm/functions/declaration/transitionRecordStatus.mjs +2 -1
- package/dist/esm/global/state/globalState.mjs +26 -1
- package/dist/esm/helpers/keyValueScore/keyValueSetScore.mjs +10 -9
- package/dist/esm/helpers/keyValueScore/processIncompleteSetScore.mjs +14 -37
- package/dist/esm/helpers/keyValueScore/scoreAnalysis.mjs +2 -1
- package/dist/esm/helpers/matchUpFormatCode/aggregateDecider.mjs +17 -0
- package/dist/esm/helpers/matchUpFormatCode/parse.mjs +41 -1
- package/dist/esm/helpers/matchUpFormatCode/stringify.mjs +16 -2
- package/dist/esm/helpers/scoreRepair/repairScore.mjs +38 -0
- package/dist/esm/index.mjs +1 -0
- package/dist/esm/mutate/base/unifiedIds.mjs +3 -2
- package/dist/esm/mutate/drawDefinitions/addDrawDefinitionTimeItem.mjs +2 -1
- package/dist/esm/mutate/drawDefinitions/draft/resolveDraftPositions.mjs +4 -2
- package/dist/esm/mutate/drawDefinitions/luckyDrawAdvancement.mjs +5 -3
- package/dist/esm/mutate/drawDefinitions/matchUpGovernor/attemptToModifyScore.mjs +2 -2
- package/dist/esm/mutate/drawDefinitions/matchUpGovernor/noDownstreamDependencies.mjs +7 -4
- package/dist/esm/mutate/drawDefinitions/matchUpGovernor/removeDoubleExit.mjs +3 -1
- package/dist/esm/mutate/drawDefinitions/positionGovernor/byePositioning/getBlockSortedRandomDrawPositions.mjs +2 -1
- package/dist/esm/mutate/drawDefinitions/positionGovernor/doubleExitAdvancement.mjs +97 -13
- package/dist/esm/mutate/drawDefinitions/removeDrawPositionAssignment.mjs +4 -0
- package/dist/esm/mutate/entries/destroyPairEntry.mjs +6 -2
- package/dist/esm/mutate/events/setEventDates.mjs +2 -2
- package/dist/esm/mutate/extensions/addExtension.mjs +2 -1
- package/dist/esm/mutate/matchUps/drawPositions/assignDrawPositionBye.mjs +16 -9
- package/dist/esm/mutate/matchUps/drawPositions/carryEmptiedSeatsPastByes.mjs +64 -0
- package/dist/esm/mutate/matchUps/drawPositions/directLoser.mjs +31 -9
- package/dist/esm/mutate/matchUps/drawPositions/directParticipants.mjs +9 -4
- package/dist/esm/mutate/matchUps/drawPositions/drawPositionPlacement.mjs +33 -19
- package/dist/esm/mutate/matchUps/drawPositions/normalizeDrawPositions.mjs +6 -1
- package/dist/esm/mutate/matchUps/drawPositions/positionParticipantAction.mjs +12 -9
- package/dist/esm/mutate/matchUps/drawPositions/positionSeeds.mjs +2 -2
- package/dist/esm/mutate/matchUps/drawPositions/reconcileFedLoserEligibility.mjs +1 -0
- package/dist/esm/mutate/matchUps/drawPositions/relabelLoserExit.mjs +185 -0
- package/dist/esm/mutate/matchUps/drawPositions/releaseAdvancedDrawPosition.mjs +20 -11
- package/dist/esm/mutate/matchUps/drawPositions/removeDirectedParticipants.mjs +9 -4
- package/dist/esm/mutate/matchUps/drawPositions/removeOnwardLoserPlacements.mjs +19 -5
- package/dist/esm/mutate/matchUps/lineUps/ensureSideLineUps.mjs +8 -3
- package/dist/esm/mutate/matchUps/matchUpStatus/applyWithdrawnExits.mjs +23 -0
- package/dist/esm/mutate/matchUps/matchUpStatus/reconcileScoredTimes.mjs +26 -0
- package/dist/esm/mutate/matchUps/matchUpStatus/reconcileStaleExitOrigins.mjs +3 -4
- package/dist/esm/mutate/matchUps/matchUpStatus/setMatchUpState.mjs +71 -35
- package/dist/esm/mutate/matchUps/matchUpStatus/setMatchUpStatus.mjs +85 -8
- package/dist/esm/mutate/matchUps/matchUpStatus/settleRederivedDoubleExits.mjs +133 -0
- package/dist/esm/mutate/matchUps/matchUpStatus/sideExitProvenance.mjs +31 -8
- package/dist/esm/mutate/matchUps/matchUpStatus/sideStatusCodes.mjs +1 -1
- package/dist/esm/mutate/matchUps/outcome/decide.mjs +287 -0
- package/dist/esm/mutate/matchUps/outcome/differential.mjs +58 -0
- package/dist/esm/mutate/matchUps/outcome/direction.mjs +120 -0
- package/dist/esm/mutate/matchUps/outcome/refusals.mjs +192 -0
- package/dist/esm/mutate/matchUps/outcome/route.mjs +82 -0
- package/dist/esm/mutate/matchUps/outcome/view.mjs +343 -0
- package/dist/esm/mutate/matchUps/outcome/write.mjs +127 -0
- package/dist/esm/mutate/matchUps/schedule/addSchedulingProfileRound.mjs +2 -2
- package/dist/esm/mutate/matchUps/schedule/byeScheduling.mjs +11 -1
- package/dist/esm/mutate/matchUps/schedule/scheduleItems/addMatchUpScheduledDate.mjs +1 -1
- package/dist/esm/mutate/matchUps/schedule/scheduleItems/scheduleItems.mjs +2 -1
- package/dist/esm/mutate/matchUps/schedule/scheduleMatchUps/scheduleMatchUps.mjs +2 -2
- package/dist/esm/mutate/matchUps/schedule/scheduleProfileGrid.mjs +2 -2
- package/dist/esm/mutate/matchUps/schedule/scheduleProfileRounds.mjs +2 -2
- package/dist/esm/mutate/matchUps/schedule/scheduledTime.mjs +2 -2
- package/dist/esm/mutate/matchUps/schedule/schedulers/jinnScheduler/jinnScheduler.mjs +2 -1
- package/dist/esm/mutate/matchUps/schedule/schedulers/proScheduler/proConflicts.mjs +6 -1
- package/dist/esm/mutate/matchUps/schedule/schedulers/v2Scheduler/v2Scheduler.mjs +2 -1
- package/dist/esm/mutate/matchUps/schedule/setMatchUpCalledAt.mjs +2 -2
- package/dist/esm/mutate/matchUps/score/modifyMatchUpScore.mjs +3 -0
- package/dist/esm/mutate/matchUps/score/updateTieMatchUpScore.mjs +7 -2
- package/dist/esm/mutate/notifications/drawNotifications.mjs +3 -2
- package/dist/esm/mutate/officiating/addCertification.mjs +2 -1
- package/dist/esm/mutate/officiating/addCertificationRequirement.mjs +2 -1
- package/dist/esm/mutate/officiating/addConflictDeclaration.mjs +2 -1
- package/dist/esm/mutate/officiating/addEvaluation.mjs +2 -1
- package/dist/esm/mutate/officiating/addEvaluationPolicy.mjs +2 -1
- package/dist/esm/mutate/officiating/addSuspension.mjs +2 -1
- package/dist/esm/mutate/officiating/assignOfficial.mjs +2 -1
- package/dist/esm/mutate/officiating/createOfficialRecord.mjs +2 -1
- package/dist/esm/mutate/officiating/modifyCertification.mjs +2 -1
- package/dist/esm/mutate/officiating/modifyEvaluation.mjs +2 -1
- package/dist/esm/mutate/officiating/removeCertification.mjs +2 -1
- package/dist/esm/mutate/officiating/removeConflictDeclaration.mjs +2 -1
- package/dist/esm/mutate/officiating/removeEvaluation.mjs +2 -1
- package/dist/esm/mutate/officiating/removeOfficialAssignment.mjs +2 -1
- package/dist/esm/mutate/officiating/removeSuspension.mjs +2 -1
- package/dist/esm/mutate/participants/addParticipantOtherId.mjs +3 -2
- package/dist/esm/mutate/participants/addPersonOtherId.mjs +3 -2
- package/dist/esm/mutate/participants/modifyParticipant.mjs +2 -1
- package/dist/esm/mutate/participants/modifyParticipantsPaymentStatus.mjs +2 -1
- package/dist/esm/mutate/participants/modifyParticipantsSignInStatus.mjs +2 -1
- package/dist/esm/mutate/participants/penalties/addPenalty.mjs +4 -2
- package/dist/esm/mutate/participants/penalties/modifyPenalty.mjs +4 -1
- package/dist/esm/mutate/participants/penalties/normalizePenaltyType.mjs +11 -0
- package/dist/esm/mutate/participants/scaleItems/addScaleItems.mjs +2 -1
- package/dist/esm/mutate/practice/addPracticeRegistration.mjs +2 -1
- package/dist/esm/mutate/practice/removePracticeRegistration.mjs +2 -1
- package/dist/esm/mutate/practice/updatePracticeRegistration.mjs +2 -1
- package/dist/esm/mutate/presence/buildAttestation.mjs +2 -1
- package/dist/esm/mutate/sanctioning/addEventProposal.mjs +2 -1
- package/dist/esm/mutate/sanctioning/addReviewNote.mjs +3 -2
- package/dist/esm/mutate/sanctioning/amendments.mjs +5 -4
- package/dist/esm/mutate/sanctioning/compliance.mjs +9 -8
- package/dist/esm/mutate/sanctioning/conditionallyApprove.mjs +2 -1
- package/dist/esm/mutate/sanctioning/createSanctioningRecord.mjs +2 -1
- package/dist/esm/mutate/sanctioning/endorsement.mjs +6 -5
- package/dist/esm/mutate/sanctioning/meetCondition.mjs +3 -2
- package/dist/esm/mutate/sanctioning/openProposalRegistration.mjs +2 -1
- package/dist/esm/mutate/sanctioning/removeEventProposal.mjs +2 -1
- package/dist/esm/mutate/sanctioning/transitionStatus.mjs +2 -1
- package/dist/esm/mutate/sanctioning/updateEventProposal.mjs +2 -1
- package/dist/esm/mutate/sanctioning/updateProposal.mjs +2 -1
- package/dist/esm/mutate/scoring/addPoint.mjs +29 -18
- package/dist/esm/mutate/scoring/createMatchUp.mjs +4 -2
- package/dist/esm/mutate/timeItems/addTimeItem.mjs +2 -1
- package/dist/esm/mutate/timeItems/publishTournamentInfo.mjs +2 -2
- package/dist/esm/mutate/tournaments/mutationLocks/addMutationLock.mjs +2 -1
- package/dist/esm/mutate/tournaments/setTournamentDates.mjs +2 -2
- package/dist/esm/mutate/venues/addCourt.mjs +2 -2
- package/dist/esm/mutate/venues/addCourtGridBooking.mjs +2 -1
- package/dist/esm/mutate/venues/addVenueOtherId.mjs +3 -2
- package/dist/esm/mutate/venues/updateCourtAvailability.mjs +2 -2
- package/dist/esm/package.json.mjs +1 -1
- package/dist/esm/query/drawDefinition/getRandomQualifierList.mjs +2 -1
- package/dist/esm/query/drawDefinition/hasPropagatedExitDownstream.mjs +2 -2
- package/dist/esm/query/drawDefinition/isActiveDownstream.mjs +31 -12
- package/dist/esm/query/drawDefinition/matchUpActions/matchUpActions.mjs +47 -5
- package/dist/esm/query/entries/categoryValidation.mjs +1 -1
- package/dist/esm/query/event/getCategoryAgeDetails.mjs +2 -1
- package/dist/esm/query/hierarchical/resolveScoringFormat.mjs +10 -0
- package/dist/esm/query/matchUp/activeMatchUp.mjs +1 -1
- package/dist/esm/query/matchUp/analyzeMatchUp.mjs +2 -1
- package/dist/esm/query/matchUp/analyzeScore.mjs +26 -11
- package/dist/esm/query/matchUp/analyzeSet.mjs +38 -26
- package/dist/esm/query/matchUp/checkSetIsComplete.mjs +11 -8
- package/dist/esm/query/matchUp/getComplement.mjs +14 -20
- package/dist/esm/query/matchUp/getDrawPositionWinCount.mjs +1 -1
- package/dist/esm/query/matchUp/getProjectedDualWinningSide.mjs +5 -1
- package/dist/esm/query/matchUp/matchUpDuration.mjs +2 -1
- package/dist/esm/query/matchUp/retainScoreForFormat.mjs +2 -1
- package/dist/esm/query/matchUp/tiebreakAtRules.mjs +44 -0
- package/dist/esm/query/matchUp/tiebreakSetShape.mjs +51 -0
- package/dist/esm/query/matchUps/addGoesTo.mjs +19 -1
- package/dist/esm/query/matchUps/addMatchUpContext.mjs +4 -1
- package/dist/esm/query/matchUps/competitionScheduleMatchUps.mjs +7 -3
- package/dist/esm/query/matchUps/getAllStructureMatchUps.mjs +5 -0
- package/dist/esm/query/matchUps/getDrawPositionSides.mjs +28 -1
- package/dist/esm/query/matchUps/participantScheduledMatchUps.mjs +2 -2
- package/dist/esm/query/matchUps/scheduling/getRounds.mjs +2 -2
- package/dist/esm/query/matchUps/scheduling/getSchedulingProfileIssues.mjs +1 -1
- package/dist/esm/query/officiating/getOfficialEligibility.mjs +2 -1
- package/dist/esm/query/publishing/isEmbargoed.mjs +2 -1
- package/dist/esm/query/publishing/tournamentVisibility.mjs +2 -1
- 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/wrapEntryStatusReport.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/wrapParticipantExperienceReport.mjs +2 -1
- package/dist/esm/query/reports/wrappers/wrapParticipantResultsReport.mjs +2 -1
- package/dist/esm/query/reports/wrappers/wrapParticipantStats.mjs +2 -1
- package/dist/esm/query/reports/wrappers/wrapRecoveryTimeReport.mjs +2 -1
- package/dist/esm/query/reports/wrappers/wrapSeedingPerformanceReport.mjs +2 -1
- package/dist/esm/query/reports/wrappers/wrapStructureReport.mjs +2 -1
- package/dist/esm/query/reports/wrappers/wrapVenuesReport.mjs +2 -1
- package/dist/esm/query/scoring/getEpisodes.mjs +3 -1
- package/dist/esm/query/scoring/getScore.mjs +10 -11
- package/dist/esm/query/scoring/getScoreboard.mjs +2 -1
- package/dist/esm/query/scoring/getWinner.mjs +3 -1
- package/dist/esm/query/scoring/isComplete.mjs +3 -1
- package/dist/esm/query/tournaments/cleanExpiredMutationLocks.mjs +2 -1
- package/dist/esm/query/tournaments/getCompetitionDateRange.mjs +1 -1
- package/dist/esm/query/tournaments/getMutationLocks.mjs +2 -1
- package/dist/esm/tools/UUID.mjs +2 -1
- package/dist/esm/tools/arrays.mjs +4 -3
- package/dist/esm/tools/canonicalJson.mjs +63 -0
- package/dist/esm/tools/clock.mjs +39 -0
- package/dist/esm/tools/dateTime.mjs +4 -3
- package/dist/esm/tools/math.mjs +4 -3
- package/dist/esm/tools/parseScoreString.mjs +5 -11
- package/dist/esm/tools/plainDate.mjs +3 -2
- package/dist/esm/tools/prng.mjs +28 -2
- package/dist/esm/tools/scoring/scoringUtilities.mjs +10 -5
- package/dist/esm/tools/timeCode.mjs +3 -1
- package/dist/esm/tools/timeZone.mjs +2 -1
- package/dist/esm/types/tournamentTypes.mjs +6 -0
- package/dist/esm/validators/isMatchUpStatus.mjs +8 -0
- package/dist/esm/validators/isValidMatchUpFormat.mjs +1 -17
- package/dist/esm/validators/officiating/validateCertification.mjs +2 -1
- package/dist/esm/validators/sanctioning/validateProposal.mjs +3 -2
- package/dist/esm/validators/scoreCompleteness.mjs +31 -0
- package/dist/esm/validators/scoring/mcpValidator.mjs +2 -1
- package/dist/esm/validators/scoring/pbpValidator.mjs +2 -1
- package/dist/esm/validators/scoring/validateMatchUp.mjs +2 -1
- package/dist/esm/validators/setCount.mjs +43 -0
- package/dist/esm/validators/timedSetWinner.mjs +10 -0
- package/dist/esm/validators/validateMatchUpScore.mjs +70 -34
- package/dist/esm/validators/validateScheduleScenario.mjs +1 -1
- package/dist/esm/validators/validateSchedulingProfile.mjs +1 -1
- package/dist/esm/validators/validateScore.mjs +75 -25
- package/dist/schema/tournament.schema.json +6 -0
- package/dist/tods-competition-factory.d.cts +4394 -850
- package/dist/tods-competition-factory.d.mts +4394 -850
- package/dist/tods-competition-factory.d.ts +4394 -850
- package/dist/tods-competition-factory.development.cjs.js +32221 -29635
- 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 +17 -3
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
|
-
**
|
|
145
|
+
**15,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.
|
|
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,3 +1,4 @@
|
|
|
1
|
+
import { getMatchUpsMap, getMappedStructureMatchUps } from '../query/matchUps/getMatchUpsMap.mjs';
|
|
1
2
|
import { checkRequiredParameters } from '../helpers/parameters/checkRequiredParameters.mjs';
|
|
2
3
|
import { getAllStructureMatchUps } from '../query/matchUps/getAllStructureMatchUps.mjs';
|
|
3
4
|
import { getContextContent } from '../query/hierarchical/getContextContent.mjs';
|
|
@@ -10,11 +11,15 @@ function findDrawMatchUp(params) {
|
|
|
10
11
|
const paramsCheck = checkRequiredParameters(params, [{ [DRAW_DEFINITION]: true, [MATCHUP_ID]: true }]);
|
|
11
12
|
if (paramsCheck.error)
|
|
12
13
|
return paramsCheck;
|
|
13
|
-
const { tournamentParticipants, participantsProfile, afterRecoveryTimes, contextProfile, drawDefinition,
|
|
14
|
+
const { tournamentParticipants, participantsProfile, afterRecoveryTimes, contextProfile, drawDefinition, matchUpId, inContext, context, event, } = params;
|
|
14
15
|
const { structures = [] } = getDrawStructures({ drawDefinition });
|
|
15
16
|
const contextContent = params.contextContent ?? (contextProfile && getContextContent({ contextProfile, drawDefinition }));
|
|
17
|
+
const matchUpsMap = params.matchUpsMap ?? getMatchUpsMap({ drawDefinition });
|
|
16
18
|
for (const structure of structures) {
|
|
19
|
+
if (!structureHoldsMatchUp({ structureId: structure.structureId, matchUpsMap, matchUpId }))
|
|
20
|
+
continue;
|
|
17
21
|
const { matchUps } = getAllStructureMatchUps({
|
|
22
|
+
hydrateMatchUpId: inContext ? matchUpId : undefined,
|
|
18
23
|
tournamentParticipants,
|
|
19
24
|
participantsProfile,
|
|
20
25
|
afterRecoveryTimes,
|
|
@@ -33,5 +38,9 @@ function findDrawMatchUp(params) {
|
|
|
33
38
|
}
|
|
34
39
|
return { error: MATCHUP_NOT_FOUND };
|
|
35
40
|
}
|
|
41
|
+
function structureHoldsMatchUp({ matchUpsMap, structureId, matchUpId, }) {
|
|
42
|
+
return getMappedStructureMatchUps({ matchUpsMap, structureId }).some((matchUp) => matchUp.matchUpId === matchUpId ||
|
|
43
|
+
matchUp.tieMatchUps?.some((tieMatchUp) => tieMatchUp.matchUpId === matchUpId));
|
|
44
|
+
}
|
|
36
45
|
|
|
37
46
|
export { findDrawMatchUp };
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { getMutationStatus } from '../parts/getMutationStatus.mjs';
|
|
2
2
|
import { logMethodNotFound } from '../parts/logMethodNotFound.mjs';
|
|
3
|
-
import { getTournamentRecords, deleteNotices } from '../../../global/state/globalState.mjs';
|
|
3
|
+
import { getTournamentRecords, deleteNotices, getInvokeObserver } from '../../../global/state/globalState.mjs';
|
|
4
4
|
import { executeFunction } from '../parts/executeMethod.mjs';
|
|
5
5
|
import { notifySubscribersAsync } from '../../../global/state/notifySubscribers.mjs';
|
|
6
6
|
import { setState } from '../parts/stateMethods.mjs';
|
|
7
7
|
import { isObject, isFunction, isString } from '../../../tools/objects.mjs';
|
|
8
8
|
import { getMethods } from '../../../global/state/syncGlobalState.mjs';
|
|
9
9
|
import { makeDeepCopy } from '../../../tools/makeDeepCopy.mjs';
|
|
10
|
+
import { nowMs } from '../../../tools/clock.mjs';
|
|
10
11
|
import { INVALID_VALUES, METHOD_NOT_FOUND } from '../../../constants/errorConditionConstants.mjs';
|
|
11
12
|
|
|
12
13
|
async function asyncEngineInvoke(engine, args) {
|
|
@@ -32,7 +33,7 @@ async function asyncEngineInvoke(engine, args) {
|
|
|
32
33
|
const result = (await executeFunction(engine, method, params, methodName, 'async')) ?? {};
|
|
33
34
|
if (result?.error && snapshot)
|
|
34
35
|
setState(snapshot);
|
|
35
|
-
const timeStamp =
|
|
36
|
+
const timeStamp = nowMs();
|
|
36
37
|
const mutationStatus = getMutationStatus({ timeStamp });
|
|
37
38
|
const notify = result?.success && params?.delayNotify !== true && params?.doNotNotify !== true;
|
|
38
39
|
if (notify)
|
|
@@ -43,6 +44,7 @@ async function asyncEngineInvoke(engine, args) {
|
|
|
43
44
|
});
|
|
44
45
|
if (notify || !result?.success || params?.doNotNotify)
|
|
45
46
|
deleteNotices();
|
|
47
|
+
getInvokeObserver()?.({ phase: 'after', methodName, engineType: 'async', params, result });
|
|
46
48
|
return result;
|
|
47
49
|
}
|
|
48
50
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { getMethods, getTournamentRecords, deleteNotices } from '../../../global/state/globalState.mjs';
|
|
1
|
+
import { getMethods, getTournamentRecords, deleteNotices, getInvokeObserver } from '../../../global/state/globalState.mjs';
|
|
2
2
|
import { getMutationStatus } from '../parts/getMutationStatus.mjs';
|
|
3
3
|
import { logMethodNotFound } from '../parts/logMethodNotFound.mjs';
|
|
4
4
|
import { executeFunction } from '../parts/executeMethod.mjs';
|
|
5
5
|
import { notifySubscribersAsync } from '../../../global/state/notifySubscribers.mjs';
|
|
6
6
|
import { setState } from '../parts/stateMethods.mjs';
|
|
7
7
|
import { makeDeepCopy } from '../../../tools/makeDeepCopy.mjs';
|
|
8
|
+
import { nowMs } from '../../../tools/clock.mjs';
|
|
8
9
|
import { INVALID_VALUES } from '../../../constants/errorConditionConstants.mjs';
|
|
9
10
|
|
|
10
11
|
async function asyncExecutionQueue(engine, directives, rollbackOnError) {
|
|
@@ -30,6 +31,7 @@ async function asyncExecutionQueue(engine, directives, rollbackOnError) {
|
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
33
|
const result = executeFunction(engine, methods[methodName], params, methodName, 'async');
|
|
34
|
+
getInvokeObserver()?.({ phase: 'after', methodName, engineType: 'async', params, result });
|
|
33
35
|
if (result?.error) {
|
|
34
36
|
if (snapshot)
|
|
35
37
|
setState(snapshot);
|
|
@@ -37,7 +39,7 @@ async function asyncExecutionQueue(engine, directives, rollbackOnError) {
|
|
|
37
39
|
}
|
|
38
40
|
results.push({ ...result, methodName });
|
|
39
41
|
}
|
|
40
|
-
const timeStamp =
|
|
42
|
+
const timeStamp = nowMs();
|
|
41
43
|
const mutationStatus = getMutationStatus({ timeStamp });
|
|
42
44
|
await notifySubscribersAsync({ directives, mutationStatus, timeStamp });
|
|
43
45
|
deleteNotices();
|
|
@@ -2,6 +2,7 @@ import { methodScopeMap } from '../../../constants/mutationLockScopeMap.mjs';
|
|
|
2
2
|
import { addExtension } from '../../../mutate/extensions/addExtension.mjs';
|
|
3
3
|
import { findExtension } from '../../../acquire/findExtension.mjs';
|
|
4
4
|
import { findVenue } from '../../../query/venues/findVenue.mjs';
|
|
5
|
+
import { nowIso } from '../../../tools/clock.mjs';
|
|
5
6
|
import { MUTATION_LOCKED } from '../../../constants/errorConditionConstants.mjs';
|
|
6
7
|
import { MUTATION_LOCKS } from '../../../constants/extensionConstants.mjs';
|
|
7
8
|
|
|
@@ -15,7 +16,7 @@ function checkMutationLock(methodName, params, tournamentRecord) {
|
|
|
15
16
|
if (!scope)
|
|
16
17
|
return undefined;
|
|
17
18
|
const lockToken = params.lockToken;
|
|
18
|
-
const now =
|
|
19
|
+
const now = nowIso();
|
|
19
20
|
const elements = [];
|
|
20
21
|
if (params.drawDefinition) {
|
|
21
22
|
elements.push({ element: params.drawDefinition, label: `draw:${params.drawDefinition.drawId}` });
|
|
@@ -8,9 +8,11 @@ import { createTournamentRecord } from '../../generators/tournamentRecords/creat
|
|
|
8
8
|
import { methodImporter } from './methodImporter.mjs';
|
|
9
9
|
import { processResult } from './processResult.mjs';
|
|
10
10
|
import { factoryVersion } from '../../../functions/global/factoryVersion.mjs';
|
|
11
|
+
import { setRandomSource } from '../../../tools/prng.mjs';
|
|
11
12
|
import { getTournament, getState, setTournamentRecord, setState, removeUnlinkedTournamentRecords } from './stateMethods.mjs';
|
|
12
|
-
import { setTournamentRecords, getDevContext, getSchemaWriteMode, getSaveDrawDeletions, getAuditAuthorityServer, setTournamentId, setDeepCopy, getTournamentId, removeTournamentRecord, setDevContext, setSchemaWriteMode, setSaveDrawDeletions, setAuditAuthorityServer } from '../../../global/state/globalState.mjs';
|
|
13
|
+
import { setTournamentRecords, getDevContext, getSchemaWriteMode, getOutcomePipeline, getSaveDrawDeletions, getAuditAuthorityServer, setTournamentId, setDeepCopy, getTournamentId, removeTournamentRecord, setDevContext, setSchemaWriteMode, setOutcomePipeline, setSaveDrawDeletions, setAuditAuthorityServer } from '../../../global/state/globalState.mjs';
|
|
13
14
|
import { SUCCESS } from '../../../constants/resultConstants.mjs';
|
|
15
|
+
import { setClock } from '../../../tools/clock.mjs';
|
|
14
16
|
|
|
15
17
|
function engineStart(engine, engineInvoke) {
|
|
16
18
|
engine.importMethods = (methods, collections, depth, global) => methodImporter(engine, engineInvoke, methods, collections, depth, global);
|
|
@@ -34,6 +36,11 @@ function engineStart(engine, engineInvoke) {
|
|
|
34
36
|
return processResult(engine, result);
|
|
35
37
|
};
|
|
36
38
|
engine.getSchemaWriteMode = () => getSchemaWriteMode();
|
|
39
|
+
engine.outcomePipeline = (mode) => {
|
|
40
|
+
const result = setOutcomePipeline(mode);
|
|
41
|
+
return processResult(engine, result);
|
|
42
|
+
};
|
|
43
|
+
engine.getOutcomePipeline = () => getOutcomePipeline();
|
|
37
44
|
engine.saveDrawDeletions = (flag) => {
|
|
38
45
|
const result = setSaveDrawDeletions(flag);
|
|
39
46
|
return processResult(engine, result);
|
|
@@ -44,6 +51,14 @@ function engineStart(engine, engineInvoke) {
|
|
|
44
51
|
return processResult(engine, result);
|
|
45
52
|
};
|
|
46
53
|
engine.getAuditAuthorityServer = () => getAuditAuthorityServer();
|
|
54
|
+
engine.setRandomSource = (source) => {
|
|
55
|
+
const result = setRandomSource(source);
|
|
56
|
+
return processResult(engine, result);
|
|
57
|
+
};
|
|
58
|
+
engine.setClock = (clock) => {
|
|
59
|
+
const result = setClock(clock);
|
|
60
|
+
return processResult(engine, result);
|
|
61
|
+
};
|
|
47
62
|
engine.newTournamentRecord = (params = {}) => {
|
|
48
63
|
const result = createTournamentRecord(params);
|
|
49
64
|
const tournamentId = result.tournamentId;
|
|
@@ -2,7 +2,7 @@ import { engineLogging } from '../../../global/state/engineLogging.mjs';
|
|
|
2
2
|
import { checkMutationLock } from './checkMutationLock.mjs';
|
|
3
3
|
import { paramsMiddleware } from './paramsMiddleware.mjs';
|
|
4
4
|
import { makeDeepCopy } from '../../../tools/makeDeepCopy.mjs';
|
|
5
|
-
import { getTournamentId, getTournamentRecord, getTournamentRecords, getDevContext, handleCaughtError } from '../../../global/state/globalState.mjs';
|
|
5
|
+
import { getTournamentId, getTournamentRecord, getTournamentRecords, getDevContext, handleCaughtError, getInvokeObserver } from '../../../global/state/globalState.mjs';
|
|
6
6
|
|
|
7
7
|
function executeFunction(engine, method, params, methodName, engineType, options) {
|
|
8
8
|
delete engine.success;
|
|
@@ -17,22 +17,20 @@ function executeFunction(engine, method, params, methodName, engineType, options
|
|
|
17
17
|
}) ||
|
|
18
18
|
getTournamentRecords();
|
|
19
19
|
const paramsToLog = params ? makeDeepCopy(params, undefined, true) : undefined;
|
|
20
|
+
getInvokeObserver()?.({ phase: 'before', methodName, engineType, params: paramsToLog });
|
|
21
|
+
const result = resolve({ method, params, methodName, tournamentRecords, tournamentRecord });
|
|
22
|
+
const elapsed = Date.now() - start;
|
|
23
|
+
engineLogging({ result, methodName, elapsed, params: paramsToLog, engineType, dryRun: options?.dryRun });
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
function resolve({ method, params, methodName, tournamentRecords, tournamentRecord }) {
|
|
20
27
|
const augmentedParams = params ? paramsMiddleware(tournamentRecords, params) : undefined;
|
|
21
28
|
if (augmentedParams?.error)
|
|
22
29
|
return augmentedParams;
|
|
23
30
|
const lockError = checkMutationLock(methodName, augmentedParams, tournamentRecord);
|
|
24
31
|
if (lockError)
|
|
25
32
|
return lockError;
|
|
26
|
-
|
|
27
|
-
params: augmentedParams,
|
|
28
|
-
tournamentRecords,
|
|
29
|
-
tournamentRecord,
|
|
30
|
-
methodName,
|
|
31
|
-
method,
|
|
32
|
-
});
|
|
33
|
-
const elapsed = Date.now() - start;
|
|
34
|
-
engineLogging({ result, methodName, elapsed, params: paramsToLog, engineType, dryRun: options?.dryRun });
|
|
35
|
-
return result;
|
|
33
|
+
return invoke({ params: augmentedParams, tournamentRecords, tournamentRecord, methodName, method });
|
|
36
34
|
}
|
|
37
35
|
function invoke({ tournamentRecords, tournamentRecord, params, methodName, method }) {
|
|
38
36
|
if (getDevContext()) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { openSetNumber, finalSetGoverns } from '../../../helpers/matchUpFormatCode/aggregateDecider.mjs';
|
|
1
2
|
import { calculateMatchStatistics } from '../../../query/scoring/statistics/standalone.mjs';
|
|
2
3
|
import { toStatObjects } from '../../../query/scoring/statistics/toStatObjects.mjs';
|
|
3
4
|
import { resolveSetType } from '../../../tools/scoring/scoringUtilities.mjs';
|
|
@@ -8,7 +9,9 @@ import { getEpisodes } from '../../../query/scoring/getEpisodes.mjs';
|
|
|
8
9
|
import { isComplete } from '../../../query/scoring/isComplete.mjs';
|
|
9
10
|
import { getWinner } from '../../../query/scoring/getWinner.mjs';
|
|
10
11
|
import { getScore } from '../../../query/scoring/getScore.mjs';
|
|
12
|
+
import { nowIso } from '../../../tools/clock.mjs';
|
|
11
13
|
import { addPoint, deriveServer, deriveServerBase, checkStandardSetWon, checkAndFinalizeMatch } from '../../../mutate/scoring/addPoint.mjs';
|
|
14
|
+
import { COMPLETED, TO_BE_PLAYED, IN_PROGRESS } from '../../../constants/matchUpStatusValues.mjs';
|
|
12
15
|
|
|
13
16
|
class ScoringEngine {
|
|
14
17
|
constructor(options = {}) {
|
|
@@ -49,7 +52,7 @@ class ScoringEngine {
|
|
|
49
52
|
const pointIndex = this.state.history?.points.length || 0;
|
|
50
53
|
const prevTotalGames = this.state.score.sets.reduce((sum, s) => sum + (s.side1Score || 0) + (s.side2Score || 0), 0);
|
|
51
54
|
const prevCompletedSets = this.state.score.sets.filter((s) => s.winningSide !== undefined).length;
|
|
52
|
-
const prevComplete = this.state.matchUpStatus ===
|
|
55
|
+
const prevComplete = this.state.matchUpStatus === COMPLETED;
|
|
53
56
|
const activePlayersSnapshot = this.hasLineUp() ? this.getActivePlayers() : undefined;
|
|
54
57
|
this.state = addPoint(this.state, options, {
|
|
55
58
|
pointMultipliers: this.pointMultipliers,
|
|
@@ -81,7 +84,7 @@ class ScoringEngine {
|
|
|
81
84
|
result: options.result,
|
|
82
85
|
penaltyType: options.penaltyType,
|
|
83
86
|
},
|
|
84
|
-
timestamp: options.timestamp ||
|
|
87
|
+
timestamp: options.timestamp || nowIso(),
|
|
85
88
|
pointIndex,
|
|
86
89
|
});
|
|
87
90
|
this.redoStack = [];
|
|
@@ -98,7 +101,7 @@ class ScoringEngine {
|
|
|
98
101
|
const setWinner = completedSet?.winningSide === 1 ? 0 : 1;
|
|
99
102
|
this.eventHandlers.onSetComplete?.({ ...ctx, setWinner });
|
|
100
103
|
}
|
|
101
|
-
if (!prevComplete && this.state.matchUpStatus ===
|
|
104
|
+
if (!prevComplete && this.state.matchUpStatus === COMPLETED) {
|
|
102
105
|
const matchWinner = this.state.winningSide === 1 ? 0 : 1;
|
|
103
106
|
this.eventHandlers.onMatchComplete?.({ ...ctx, matchWinner });
|
|
104
107
|
}
|
|
@@ -111,7 +114,7 @@ class ScoringEngine {
|
|
|
111
114
|
this.state.history.entries.push({
|
|
112
115
|
type: 'set',
|
|
113
116
|
data: { ...options, winningSide },
|
|
114
|
-
timestamp: options.timestamp ||
|
|
117
|
+
timestamp: options.timestamp || nowIso(),
|
|
115
118
|
});
|
|
116
119
|
this.redoStack = [];
|
|
117
120
|
}
|
|
@@ -121,7 +124,7 @@ class ScoringEngine {
|
|
|
121
124
|
this.state.history.entries.push({
|
|
122
125
|
type: 'game',
|
|
123
126
|
data: options,
|
|
124
|
-
timestamp: options.timestamp ||
|
|
127
|
+
timestamp: options.timestamp || nowIso(),
|
|
125
128
|
});
|
|
126
129
|
this.redoStack = [];
|
|
127
130
|
}
|
|
@@ -132,7 +135,7 @@ class ScoringEngine {
|
|
|
132
135
|
this.state.history.entries.push({
|
|
133
136
|
type: 'endSegment',
|
|
134
137
|
data: { setNumber: currentSetIndex + 1, ...options },
|
|
135
|
-
timestamp: options?.timestamp ||
|
|
138
|
+
timestamp: options?.timestamp || nowIso(),
|
|
136
139
|
});
|
|
137
140
|
}
|
|
138
141
|
setInitialScore(options) {
|
|
@@ -143,10 +146,10 @@ class ScoringEngine {
|
|
|
143
146
|
this.state.history.entries.push({
|
|
144
147
|
type: 'setInitialScore',
|
|
145
148
|
data: options,
|
|
146
|
-
timestamp:
|
|
149
|
+
timestamp: nowIso(),
|
|
147
150
|
});
|
|
148
|
-
if (this.state.matchUpStatus ===
|
|
149
|
-
this.state.matchUpStatus =
|
|
151
|
+
if (this.state.matchUpStatus === TO_BE_PLAYED) {
|
|
152
|
+
this.state.matchUpStatus = IN_PROGRESS;
|
|
150
153
|
}
|
|
151
154
|
}
|
|
152
155
|
undo(count = 1) {
|
|
@@ -257,7 +260,7 @@ class ScoringEngine {
|
|
|
257
260
|
if (set.winningSide === 2)
|
|
258
261
|
setsWon[1]++;
|
|
259
262
|
});
|
|
260
|
-
const setType = resolveSetType(this.cachedFormatStructure, setsWon);
|
|
263
|
+
const setType = resolveSetType(this.cachedFormatStructure, setsWon, openSetNumber(this.state.score.sets));
|
|
261
264
|
return deriveServer(this.state, this.cachedFormatStructure, setType);
|
|
262
265
|
}
|
|
263
266
|
setServer(side, options) {
|
|
@@ -270,7 +273,7 @@ class ScoringEngine {
|
|
|
270
273
|
if (set.winningSide === 2)
|
|
271
274
|
setsWon[1]++;
|
|
272
275
|
});
|
|
273
|
-
const setType = resolveSetType(this.cachedFormatStructure, setsWon);
|
|
276
|
+
const setType = resolveSetType(this.cachedFormatStructure, setsWon, openSetNumber(this.state.score.sets));
|
|
274
277
|
const baseServer = deriveServerBase(this.state, this.cachedFormatStructure, setType);
|
|
275
278
|
this.state.serverFlip = side !== baseServer;
|
|
276
279
|
if (options?.recordEntry === false)
|
|
@@ -279,7 +282,7 @@ class ScoringEngine {
|
|
|
279
282
|
this.state.history.entries.push({
|
|
280
283
|
type: 'setServer',
|
|
281
284
|
data: { side },
|
|
282
|
-
timestamp:
|
|
285
|
+
timestamp: nowIso(),
|
|
283
286
|
});
|
|
284
287
|
this.redoStack = [];
|
|
285
288
|
}
|
|
@@ -375,7 +378,7 @@ class ScoringEngine {
|
|
|
375
378
|
this.state.history.entries.push({
|
|
376
379
|
type: 'substitution',
|
|
377
380
|
data: subEvent,
|
|
378
|
-
timestamp: options.timestamp ||
|
|
381
|
+
timestamp: options.timestamp || nowIso(),
|
|
379
382
|
});
|
|
380
383
|
this.redoStack = [];
|
|
381
384
|
}
|
|
@@ -568,8 +571,8 @@ class ScoringEngine {
|
|
|
568
571
|
if (side2TiebreakScore !== undefined)
|
|
569
572
|
newSet.side2TiebreakScore = side2TiebreakScore;
|
|
570
573
|
this.state.score.sets.push(newSet);
|
|
571
|
-
if (this.state.matchUpStatus ===
|
|
572
|
-
this.state.matchUpStatus =
|
|
574
|
+
if (this.state.matchUpStatus === TO_BE_PLAYED) {
|
|
575
|
+
this.state.matchUpStatus = IN_PROGRESS;
|
|
573
576
|
}
|
|
574
577
|
if (winningSide !== undefined) {
|
|
575
578
|
this.checkMatchCompletion();
|
|
@@ -602,8 +605,8 @@ class ScoringEngine {
|
|
|
602
605
|
currentSet.side1TiebreakScore = tiebreakScore[0];
|
|
603
606
|
currentSet.side2TiebreakScore = tiebreakScore[1];
|
|
604
607
|
}
|
|
605
|
-
if (this.state.matchUpStatus ===
|
|
606
|
-
this.state.matchUpStatus =
|
|
608
|
+
if (this.state.matchUpStatus === TO_BE_PLAYED) {
|
|
609
|
+
this.state.matchUpStatus = IN_PROGRESS;
|
|
607
610
|
}
|
|
608
611
|
this.checkSetCompletion(currentSet);
|
|
609
612
|
if (currentSet.winningSide !== undefined) {
|
|
@@ -652,7 +655,8 @@ class ScoringEngine {
|
|
|
652
655
|
if (set.winningSide === 2)
|
|
653
656
|
setsWon[1]++;
|
|
654
657
|
});
|
|
655
|
-
const
|
|
658
|
+
const setNumber = currentSet.setNumber ?? this.state.score.sets.indexOf(currentSet) + 1;
|
|
659
|
+
const isDecidingSet = finalSetGoverns(formatStructure, setNumber, setsWon[0] === setsToWin - 1 && setsWon[1] === setsToWin - 1);
|
|
656
660
|
const activeSetFormat = isDecidingSet && formatStructure.finalSetFormat ? formatStructure.finalSetFormat : formatStructure.setFormat;
|
|
657
661
|
if (!activeSetFormat)
|
|
658
662
|
return;
|
|
@@ -729,8 +733,8 @@ class ScoringEngine {
|
|
|
729
733
|
}
|
|
730
734
|
if (this.initialScore) {
|
|
731
735
|
this.applyInitialScore(newState, this.initialScore);
|
|
732
|
-
if (newState.matchUpStatus ===
|
|
733
|
-
newState.matchUpStatus =
|
|
736
|
+
if (newState.matchUpStatus === TO_BE_PLAYED) {
|
|
737
|
+
newState.matchUpStatus = IN_PROGRESS;
|
|
734
738
|
}
|
|
735
739
|
}
|
|
736
740
|
newState.history = { points: [], entries: [...entries] };
|
|
@@ -744,7 +748,7 @@ class ScoringEngine {
|
|
|
744
748
|
if (set.winningSide === 2)
|
|
745
749
|
setsWon[1]++;
|
|
746
750
|
});
|
|
747
|
-
const setType = resolveSetType(this.cachedFormatStructure, setsWon);
|
|
751
|
+
const setType = resolveSetType(this.cachedFormatStructure, setsWon, openSetNumber(this.state.score.sets));
|
|
748
752
|
const baseServer = deriveServerBase(this.state, this.cachedFormatStructure, setType);
|
|
749
753
|
this.state.serverFlip = data.side !== baseServer;
|
|
750
754
|
}
|
|
@@ -757,8 +761,8 @@ class ScoringEngine {
|
|
|
757
761
|
});
|
|
758
762
|
if (this.initialScore) {
|
|
759
763
|
this.applyInitialScore(newState, this.initialScore);
|
|
760
|
-
if (newState.matchUpStatus ===
|
|
761
|
-
newState.matchUpStatus =
|
|
764
|
+
if (newState.matchUpStatus === TO_BE_PLAYED) {
|
|
765
|
+
newState.matchUpStatus = IN_PROGRESS;
|
|
762
766
|
}
|
|
763
767
|
}
|
|
764
768
|
for (const point of currentPoints) {
|
|
@@ -791,7 +795,8 @@ class ScoringEngine {
|
|
|
791
795
|
}
|
|
792
796
|
if (setData.winningSide === undefined) {
|
|
793
797
|
const fs = this.cachedFormatStructure;
|
|
794
|
-
const
|
|
798
|
+
const isFinalSet = finalSetGoverns(fs, i + 1, i === (fs?.bestOf ?? fs?.exactly ?? 3) - 1);
|
|
799
|
+
const setFormat = fs?.finalSetFormat && isFinalSet ? fs.finalSetFormat : fs?.setFormat;
|
|
795
800
|
const setTo = setFormat?.setTo;
|
|
796
801
|
if (setTo && (setData.side1Score >= setTo || setData.side2Score >= setTo)) {
|
|
797
802
|
if (setData.side1Score > setData.side2Score)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getMutationStatus } from '../parts/getMutationStatus.mjs';
|
|
2
2
|
import { logMethodNotFound } from '../parts/logMethodNotFound.mjs';
|
|
3
|
-
import { getTournamentRecords, deleteNotices } from '../../../global/state/globalState.mjs';
|
|
3
|
+
import { getTournamentRecords, deleteNotices, getInvokeObserver } from '../../../global/state/globalState.mjs';
|
|
4
4
|
import { executeFunction } from '../parts/executeMethod.mjs';
|
|
5
5
|
import { notifySubscribers } from '../../../global/state/notifySubscribers.mjs';
|
|
6
6
|
import { setState } from '../parts/stateMethods.mjs';
|
|
@@ -9,6 +9,7 @@ import { getMethods } from '../../../global/state/syncGlobalState.mjs';
|
|
|
9
9
|
import { makeDeepCopy } from '../../../tools/makeDeepCopy.mjs';
|
|
10
10
|
import { createSeededRandom } from '../../../tools/prng.mjs';
|
|
11
11
|
import { INVALID_VALUES, METHOD_NOT_FOUND } from '../../../constants/errorConditionConstants.mjs';
|
|
12
|
+
import { nowMs } from '../../../tools/clock.mjs';
|
|
12
13
|
|
|
13
14
|
function engineInvoke(engine, args) {
|
|
14
15
|
if (!isObject(args))
|
|
@@ -37,7 +38,7 @@ function engineInvoke(engine, args) {
|
|
|
37
38
|
const result = executeFunction(engine, method, params, methodName, 'sync') ?? {};
|
|
38
39
|
if (result?.error && snapshot)
|
|
39
40
|
setState(snapshot);
|
|
40
|
-
const timeStamp =
|
|
41
|
+
const timeStamp = nowMs();
|
|
41
42
|
const mutationStatus = getMutationStatus({ timeStamp });
|
|
42
43
|
const notify = result?.success && params?.delayNotify !== true && params?.doNotNotify !== true;
|
|
43
44
|
if (notify)
|
|
@@ -48,6 +49,7 @@ function engineInvoke(engine, args) {
|
|
|
48
49
|
});
|
|
49
50
|
if (notify || !result?.success || params?.doNotNotify)
|
|
50
51
|
deleteNotices();
|
|
52
|
+
getInvokeObserver()?.({ phase: 'after', methodName, engineType: 'sync', params, result });
|
|
51
53
|
return result;
|
|
52
54
|
}
|
|
53
55
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getMethods, getTournamentRecords, deleteNotices } from '../../../global/state/globalState.mjs';
|
|
1
|
+
import { getMethods, getTournamentRecords, deleteNotices, getInvokeObserver } from '../../../global/state/globalState.mjs';
|
|
2
2
|
import { getMutationStatus } from '../parts/getMutationStatus.mjs';
|
|
3
3
|
import { logMethodNotFound } from '../parts/logMethodNotFound.mjs';
|
|
4
4
|
import { executeFunction } from '../parts/executeMethod.mjs';
|
|
@@ -7,6 +7,7 @@ import { setState } from '../parts/stateMethods.mjs';
|
|
|
7
7
|
import { makeDeepCopy } from '../../../tools/makeDeepCopy.mjs';
|
|
8
8
|
import { createSeededRandom } from '../../../tools/prng.mjs';
|
|
9
9
|
import { INVALID_VALUES } from '../../../constants/errorConditionConstants.mjs';
|
|
10
|
+
import { nowMs } from '../../../tools/clock.mjs';
|
|
10
11
|
|
|
11
12
|
function executionQueue(engine, directives, rollbackOnError) {
|
|
12
13
|
if (!Array.isArray(directives))
|
|
@@ -37,6 +38,7 @@ function executionQueue(engine, directives, rollbackOnError) {
|
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
const result = executeFunction(engine, methods[methodName], params, methodName, 'sync');
|
|
41
|
+
getInvokeObserver()?.({ phase: 'after', methodName, engineType: 'sync', params, result });
|
|
40
42
|
if (result?.error) {
|
|
41
43
|
if (snapshot)
|
|
42
44
|
setState(snapshot);
|
|
@@ -44,7 +46,7 @@ function executionQueue(engine, directives, rollbackOnError) {
|
|
|
44
46
|
}
|
|
45
47
|
results.push({ ...result, methodName });
|
|
46
48
|
}
|
|
47
|
-
const timeStamp =
|
|
49
|
+
const timeStamp = nowMs();
|
|
48
50
|
const mutationStatus = getMutationStatus({ timeStamp });
|
|
49
51
|
notifySubscribers({ directives, mutationStatus, timeStamp });
|
|
50
52
|
deleteNotices();
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { randomPop, chunkArray, shuffleArray } from '../../../../../../tools/arrays.mjs';
|
|
2
2
|
import { stringSort } from '../../../../../../functions/sorters/stringSort.mjs';
|
|
3
|
+
import { randomSource } from '../../../../../../tools/prng.mjs';
|
|
3
4
|
|
|
4
5
|
function generateCandidate({ maxIterations = 4000, valueSortedPairings, individualIdsMap, pairingValues, valueObjects, deltaObjects, random, }) {
|
|
5
|
-
const rng = random ??
|
|
6
|
+
const rng = random ?? randomSource();
|
|
6
7
|
const pairingValueMap = Object.assign({}, ...valueSortedPairings.map((rm) => ({ [rm.pairing]: rm.value })));
|
|
7
8
|
const actors = Object.keys(pairingValues);
|
|
8
9
|
let proposedCandidates = [];
|
|
@@ -89,7 +90,7 @@ function candidateHash(candidate) {
|
|
|
89
90
|
.join('/');
|
|
90
91
|
}
|
|
91
92
|
function roundCandidate({ valueSortedPairings, stipulated = [], individualIdsMap, pairingValueMap, deltaObjects, valueObjects, actorsCount, random, }) {
|
|
92
|
-
const rng = random ??
|
|
93
|
+
const rng = random ?? randomSource();
|
|
93
94
|
const occupants = (participantId) => {
|
|
94
95
|
const individualIds = individualIdsMap?.[participantId];
|
|
95
96
|
return individualIds?.length ? individualIds : [participantId];
|
package/dist/esm/assemblies/generators/drawDefinitions/drawTypes/adHoc/drawMatic/getPairings.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getParticipantPairingValues } from './getParticipantPairingValues.mjs';
|
|
2
2
|
import { generateCandidate } from './generateCandidate.mjs';
|
|
3
3
|
import { getSideRatings } from './getSideRatings.mjs';
|
|
4
|
+
import { randomSource } from '../../../../../../tools/prng.mjs';
|
|
4
5
|
|
|
5
6
|
function getPairings(params) {
|
|
6
7
|
const { tournamentParticipants, adHocRatings = {}, possiblePairings, individualIdsMap, uniquePairings, maxIterations, minimizeDelta, deltaObjects, valueObjects, eventType, scaleName, salted, } = params;
|
|
@@ -13,7 +14,7 @@ function getPairings(params) {
|
|
|
13
14
|
pairing,
|
|
14
15
|
});
|
|
15
16
|
const salting = (typeof salted === 'number' && salted) || 0.5;
|
|
16
|
-
const rng = params.random ??
|
|
17
|
+
const rng = params.random ?? randomSource();
|
|
17
18
|
const salt = (salted && (Math.round(rng()) ? salting : salting * -1)) || 0;
|
|
18
19
|
const ratingsDifference = Math.abs(ratings[0] - ratings[1]) + salt;
|
|
19
20
|
const pairingDelta = Math.abs(ratings[0] - ratings[1]);
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { MISSING_VALUE } from '../../../constants/errorConditionConstants.mjs';
|
|
2
2
|
import { SEEDING } from '../../../constants/scaleConstants.mjs';
|
|
3
|
+
import { nowIso } from '../../../tools/clock.mjs';
|
|
3
4
|
|
|
4
5
|
function generateSeedingScaleItems({ scaleAttributes, scaledEntries, stageEntries, seedsCount, scaleName, }) {
|
|
5
6
|
if (!scaleAttributes)
|
|
6
7
|
return { error: MISSING_VALUE, info: 'missing scaleAttributes' };
|
|
7
8
|
const seededEntries = Object.assign({}, ...(scaledEntries ?? []).slice(0, seedsCount).map(({ participantId }, index) => ({ [participantId]: index + 1 })));
|
|
8
9
|
scaleName = scaleName || scaleAttributes.scaleName;
|
|
9
|
-
const scaleDate =
|
|
10
|
+
const scaleDate = nowIso();
|
|
10
11
|
const scaleItemsWithParticipantIds = stageEntries.map(({ participantId }) => {
|
|
11
12
|
const scaleItem = {
|
|
12
13
|
scaleValue: seededEntries[participantId],
|
|
@@ -5,6 +5,7 @@ import { TEAM } from '../../../constants/eventConstants.mjs';
|
|
|
5
5
|
import { MAIN } from '../../../constants/drawDefinitionConstants.mjs';
|
|
6
6
|
import { FORMAT_STANDARD } from '../../../fixtures/scoring/matchUpFormats/index.mjs';
|
|
7
7
|
import '../../../helpers/keyValueScore/constants.mjs';
|
|
8
|
+
import '../../../validators/isMatchUpStatus.mjs';
|
|
8
9
|
|
|
9
10
|
function getDrawFormat(params) {
|
|
10
11
|
const { existingDrawDefinition, hydrateCollections, enforceGender, tieFormatName, tieFormatId, matchUpType, eventType, isMock, event, } = params;
|
|
@@ -15,7 +15,10 @@ import '../../../query/formatWizard/suggestFormatPlans.mjs';
|
|
|
15
15
|
import '../../../types/tournamentTypes.mjs';
|
|
16
16
|
import { isAdHocType } from '../../../query/drawDefinition/isAdHocType.mjs';
|
|
17
17
|
import '../../../query/matchUp/isScheduleLocked.mjs';
|
|
18
|
+
import '../../../mutate/matchUps/schedule/byeScheduling.mjs';
|
|
18
19
|
import '../../../query/matchUp/predictMatchUpCompetitiveBands.mjs';
|
|
20
|
+
import '../../../mutate/matchUps/matchUpStatus/sideStatusCodes.mjs';
|
|
21
|
+
import '../../../validators/isMatchUpStatus.mjs';
|
|
19
22
|
import '../../../functions/sorters/roundSort.mjs';
|
|
20
23
|
import '../../../query/drawDefinition/predictDrawCompetitiveBands.mjs';
|
|
21
24
|
import { getDrawTypeCoercion } from './getDrawTypeCoercion.mjs';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { finalSetGoverns } from '../../../helpers/matchUpFormatCode/aggregateDecider.mjs';
|
|
1
2
|
import { parse } from '../../../helpers/matchUpFormatCode/parse.mjs';
|
|
2
3
|
import { isNumeric } from '../../../tools/math.mjs';
|
|
3
4
|
import { MISSING_VALUE } from '../../../constants/errorConditionConstants.mjs';
|
|
@@ -23,7 +24,7 @@ function generateScoreString(params) {
|
|
|
23
24
|
return `${outcomeString} ${setScores}`;
|
|
24
25
|
return `${setScores} ${outcomeString}`;
|
|
25
26
|
function setString(currentSet) {
|
|
26
|
-
const isFinalSet = bestOf && currentSet.setNumber === bestOf;
|
|
27
|
+
const isFinalSet = finalSetGoverns(parsedFormat, currentSet.setNumber, !!bestOf && currentSet.setNumber === bestOf);
|
|
27
28
|
const format = isFinalSet && finalSetFormat ? finalSetFormat : setFormat;
|
|
28
29
|
const hasGameScores = (set) => isNumeric(set?.side1Score) || isNumeric(set?.side2Score);
|
|
29
30
|
const hasTiebreakScores = (set) => isNumeric(set?.side1TiebreakScore) || isNumeric(set?.side2TiebreakScore);
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import { withPointsInTiebreakFields, formatForSet } from '../../../query/matchUp/tiebreakSetShape.mjs';
|
|
1
2
|
import { generateScoreString } from './generateScoreString.mjs';
|
|
3
|
+
import { parse } from '../../../helpers/matchUpFormatCode/parse.mjs';
|
|
2
4
|
|
|
3
5
|
function matchUpScore(params) {
|
|
4
6
|
const { matchUpFormat, matchUpStatus, winningSide, score, setTBlast } = params;
|
|
5
7
|
if (!score)
|
|
6
8
|
return { sets: [] };
|
|
7
|
-
const
|
|
9
|
+
const parsedFormat = score.sets?.length && matchUpFormat ? parse(matchUpFormat) : undefined;
|
|
10
|
+
const sets = (score.sets ?? []).map((set) => withPointsInTiebreakFields(set, formatForSet(parsedFormat, set?.setNumber)));
|
|
8
11
|
let scoreStringSide1 = generateScoreString({
|
|
9
12
|
winnerFirst: false,
|
|
10
13
|
matchUpFormat,
|
|
@@ -2,6 +2,7 @@ import { addMatchUpScheduledDate } from '../../../mutate/matchUps/schedule/sched
|
|
|
2
2
|
import { addMatchUpScheduledTime } from '../../../mutate/matchUps/schedule/scheduledTime.mjs';
|
|
3
3
|
import { scheduleProfileGrid } from '../../../mutate/matchUps/schedule/scheduleProfileGrid.mjs';
|
|
4
4
|
import { decorateResult } from '../../../functions/global/decorateResult.mjs';
|
|
5
|
+
import { now } from '../../../tools/clock.mjs';
|
|
5
6
|
import { extractDate } from '../../../tools/plainDate.mjs';
|
|
6
7
|
import { allTournamentMatchUps } from '../../../query/matchUps/getAllTournamentMatchUps.mjs';
|
|
7
8
|
import { INVALID_VALUES, INVALID_DATE } from '../../../constants/errorConditionConstants.mjs';
|
|
@@ -32,7 +33,7 @@ function applyScenarioProfile({ tournamentRecord, scenarioProfile }) {
|
|
|
32
33
|
const { anchor = 'NOW', minutesBeforeAnchor = 0, assignCourts } = scenarioProfile;
|
|
33
34
|
if (typeof minutesBeforeAnchor !== 'number' || !isFinite(minutesBeforeAnchor))
|
|
34
35
|
return { error: INVALID_VALUES };
|
|
35
|
-
const anchorDate = anchor === 'NOW' ?
|
|
36
|
+
const anchorDate = anchor === 'NOW' ? now() : new Date(anchor);
|
|
36
37
|
if (isNaN(anchorDate.getTime()))
|
|
37
38
|
return { error: INVALID_VALUES };
|
|
38
39
|
const matchUps = allTournamentMatchUps({ tournamentRecord }).matchUps ?? [];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { finalSetGoverns, aggregateDeciderSetNumber } from '../../../helpers/matchUpFormatCode/aggregateDecider.mjs';
|
|
1
2
|
import { getSetComplement, getTiebreakComplement } from '../../../query/matchUp/getComplement.mjs';
|
|
2
3
|
import { matchUpScore } from '../matchUps/matchUpScore.mjs';
|
|
3
4
|
import { isValidMatchUpFormat } from '../../../validators/isValidMatchUpFormat.mjs';
|
|
@@ -157,7 +158,7 @@ function generateScoredOutcome({ pointsPerMinute, matchUpFormat, matchUpStatus,
|
|
|
157
158
|
let weightedWinningSide;
|
|
158
159
|
const setsToGenerate = generateRange(1, (exactly ?? bestOf) + 1);
|
|
159
160
|
for (const setNumber of setsToGenerate) {
|
|
160
|
-
const isFinalSet = setNumber === (exactly ?? bestOf);
|
|
161
|
+
const isFinalSet = finalSetGoverns(parsedFormat, setNumber, setNumber === (exactly ?? bestOf));
|
|
161
162
|
const { set, incomplete, winningSideNumber } = generateSet({
|
|
162
163
|
setFormat: (isFinalSet && finalSetFormat) || setFormat,
|
|
163
164
|
incomplete: incompleteAt === setNumber,
|
|
@@ -176,6 +177,22 @@ function generateScoredOutcome({ pointsPerMinute, matchUpFormat, matchUpStatus,
|
|
|
176
177
|
if (analysis.calculatedWinningSide && !parsedFormat?.aggregate)
|
|
177
178
|
break;
|
|
178
179
|
}
|
|
180
|
+
const deciderSetNumber = aggregateDeciderSetNumber(parsedFormat);
|
|
181
|
+
if (deciderSetNumber && finalSetFormat && !weightedWinningSide && aggregateIsLevel(sets)) {
|
|
182
|
+
const { set } = generateSet({
|
|
183
|
+
weightedRange: winningSide ? [winningSide - 1] : weightedRange,
|
|
184
|
+
setFormat: finalSetFormat,
|
|
185
|
+
setNumber: deciderSetNumber,
|
|
186
|
+
incomplete: false,
|
|
187
|
+
pointsPerMinute,
|
|
188
|
+
matchUpStatus,
|
|
189
|
+
random,
|
|
190
|
+
});
|
|
191
|
+
if (winningSide && set.winningSide !== winningSide)
|
|
192
|
+
swapSides(set);
|
|
193
|
+
sets.push(set);
|
|
194
|
+
weightedWinningSide = set.winningSide;
|
|
195
|
+
}
|
|
179
196
|
const matchUpWinningSide = determineMatchUpWinningSide({
|
|
180
197
|
weightedWinningSide,
|
|
181
198
|
matchUpFormat,
|
|
@@ -196,6 +213,15 @@ function generateScoredOutcome({ pointsPerMinute, matchUpFormat, matchUpStatus,
|
|
|
196
213
|
};
|
|
197
214
|
return { outcome };
|
|
198
215
|
}
|
|
216
|
+
function swapSides(set) {
|
|
217
|
+
[set.side1Score, set.side2Score] = [set.side2Score, set.side1Score];
|
|
218
|
+
[set.side1TiebreakScore, set.side2TiebreakScore] = [set.side2TiebreakScore, set.side1TiebreakScore];
|
|
219
|
+
set.winningSide = set.winningSide === 1 ? 2 : 1;
|
|
220
|
+
}
|
|
221
|
+
function aggregateIsLevel(sets) {
|
|
222
|
+
const total = (side) => sets.reduce((sum, set) => sum + (set[`side${side}Score`] ?? 0), 0);
|
|
223
|
+
return sets.length > 0 && total(1) === total(2);
|
|
224
|
+
}
|
|
199
225
|
function determineMatchUpWinningSide({ weightedWinningSide, matchUpFormat, parsedFormat, winningSide, random, sets }) {
|
|
200
226
|
if (weightedWinningSide) {
|
|
201
227
|
return winningSide || weightedWinningSide;
|