tods-competition-factory 7.26.0 → 7.28.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 (296) hide show
  1. package/dist/esm/acquire/findStructure.mjs +2 -2
  2. package/dist/esm/assemblies/engines/async/public.mjs +8 -0
  3. package/dist/esm/assemblies/engines/parts/engineStart.mjs +1 -1
  4. package/dist/esm/assemblies/engines/parts/stateMethods.mjs +1 -1
  5. package/dist/esm/assemblies/engines/scoring/v2/actions.mjs +2 -0
  6. package/dist/esm/assemblies/engines/scoring/v2/decide.mjs +34 -0
  7. package/dist/esm/assemblies/engines/scoring/v2/engine.mjs +72 -9
  8. package/dist/esm/assemblies/engines/scoring/v2/format.mjs +30 -2
  9. package/dist/esm/assemblies/engines/scoring/v2/overtime.mjs +30 -0
  10. package/dist/esm/assemblies/engines/scoring/v2/record.mjs +6 -0
  11. package/dist/esm/assemblies/engines/scoring/v2/reduce.mjs +73 -12
  12. package/dist/esm/assemblies/engines/scoring/v2/score.mjs +7 -2
  13. package/dist/esm/assemblies/engines/scoring/v2/view.mjs +3 -0
  14. package/dist/esm/assemblies/generators/drawDefinitions/drawTypes/adHoc/drawMatic/generateDrawMaticRound.mjs +1 -1
  15. package/dist/esm/assemblies/generators/drawDefinitions/drawTypes/adHoc/swiss/generateSwissRound.mjs +1 -1
  16. package/dist/esm/assemblies/generators/drawDefinitions/drawTypes/generateVoluntaryConsolation.mjs +1 -1
  17. package/dist/esm/assemblies/generators/drawDefinitions/generateAndPopulatePlayoffStructures.mjs +1 -1
  18. package/dist/esm/assemblies/generators/drawDefinitions/generateDrawDefinition/checkQualifyingEntriesFit.mjs +40 -0
  19. package/dist/esm/assemblies/generators/drawDefinitions/generateDrawDefinition/entriesNotPlaced.mjs +35 -0
  20. package/dist/esm/assemblies/generators/drawDefinitions/generateDrawDefinition/generateDrawDefinition.mjs +5 -2
  21. package/dist/esm/assemblies/generators/drawDefinitions/generateDrawDefinition/generateNewDrawDefinition.mjs +29 -7
  22. package/dist/esm/assemblies/generators/drawDefinitions/generateDrawDefinition/generateOrGetExisting.mjs +24 -2
  23. package/dist/esm/assemblies/generators/drawDefinitions/generateDrawDefinition/processExistingDrawDefinition.mjs +33 -5
  24. package/dist/esm/assemblies/generators/drawDefinitions/generateDrawStructuresAndLinks.mjs +1 -1
  25. package/dist/esm/assemblies/generators/drawDefinitions/generateDrawTypeAndModifyDrawDefinition.mjs +1 -1
  26. package/dist/esm/assemblies/generators/drawDefinitions/generateFlightProfile.mjs +59 -8
  27. package/dist/esm/assemblies/generators/drawDefinitions/getDrawFormat.mjs +2 -0
  28. package/dist/esm/assemblies/generators/drawDefinitions/validateAndDeriveDrawValues.mjs +4 -2
  29. package/dist/esm/assemblies/generators/mocks/generateSeason.mjs +97 -0
  30. package/dist/esm/assemblies/generators/mocks/modifyTournamentRecord.mjs +1 -1
  31. package/dist/esm/assemblies/generators/mocks/processLeagueProfiles.mjs +2 -1
  32. package/dist/esm/assemblies/generators/scheduling/utils/defaultPeriodLength.mjs +33 -0
  33. package/dist/esm/assemblies/generators/scheduling/utils/generateBookings.mjs +2 -0
  34. package/dist/esm/assemblies/generators/scheduling/utils/generateScheduleTimes.mjs +2 -0
  35. package/dist/esm/assemblies/generators/tournamentRecords/anonymizeTournamentRecord.mjs +259 -242
  36. package/dist/esm/assemblies/generators/tournamentRecords/generateStatCrew.mjs +51 -19
  37. package/dist/esm/assemblies/generators/venues/generateCourts.mjs +1 -1
  38. package/dist/esm/assemblies/governors/drawsGovernor/index.mjs +1 -0
  39. package/dist/esm/assemblies/governors/drawsGovernor/mutate.mjs +1 -0
  40. package/dist/esm/assemblies/governors/entriesGovernor/index.mjs +2 -0
  41. package/dist/esm/assemblies/governors/entriesGovernor/query.mjs +2 -0
  42. package/dist/esm/assemblies/governors/index.mjs +10 -8
  43. package/dist/esm/assemblies/governors/matchUpFormatGovernor/index.mjs +1 -1
  44. package/dist/esm/assemblies/governors/matchUpGovernor/index.mjs +2 -0
  45. package/dist/esm/assemblies/governors/matchUpGovernor/query.mjs +2 -0
  46. package/dist/esm/assemblies/governors/mocksGovernor/generate.mjs +1 -0
  47. package/dist/esm/assemblies/governors/mocksGovernor/index.mjs +1 -0
  48. package/dist/esm/assemblies/governors/queryGovernor/index.mjs +6 -0
  49. package/dist/esm/assemblies/governors/scheduleGovernor/index.mjs +2 -0
  50. package/dist/esm/assemblies/governors/scheduleGovernor/query.mjs +2 -0
  51. package/dist/esm/assemblies/governors/seasonGovernor/index.mjs +7 -0
  52. package/dist/esm/assemblies/governors/seasonGovernor/query.mjs +5 -0
  53. package/dist/esm/assemblies/governors/tournamentGovernor/index.mjs +1 -0
  54. package/dist/esm/assemblies/governors/tournamentGovernor/mutate.mjs +1 -0
  55. package/dist/esm/constants/dualIssueConstants.mjs +22 -0
  56. package/dist/esm/constants/entryStatusConstants.mjs +1 -1
  57. package/dist/esm/constants/errorConditionConstants.mjs +26 -1
  58. package/dist/esm/constants/flightConstants.mjs +7 -1
  59. package/dist/esm/constants/homeParticipantConstants.mjs +12 -0
  60. package/dist/esm/constants/index.mjs +3 -0
  61. package/dist/esm/constants/matchUpFormatConstants.mjs +1 -0
  62. package/dist/esm/constants/mutationLockScopeMap.mjs +1 -0
  63. package/dist/esm/constants/policyConstants.mjs +1 -0
  64. package/dist/esm/constants/seasonConstants.mjs +27 -0
  65. package/dist/esm/fixtures/policies/POLICY_ROUND_ROBIN_TALLY_FIBA.mjs +28 -0
  66. package/dist/esm/fixtures/policies/POLICY_ROUND_ROBIN_TALLY_USTA_LEAGUE.mjs +21 -0
  67. package/dist/esm/fixtures/policies/index.mjs +4 -0
  68. package/dist/esm/functions/sorters/structureSort.mjs +1 -1
  69. package/dist/esm/global/state/globalState.mjs +3 -3
  70. package/dist/esm/helpers/matchUpFormatCode/aggregateDecider.mjs +8 -0
  71. package/dist/esm/helpers/matchUpFormatCode/overtimeContext.mjs +67 -0
  72. package/dist/esm/helpers/matchUpFormatCode/overtimeFormat.mjs +40 -0
  73. package/dist/esm/helpers/matchUpFormatCode/parse.mjs +36 -8
  74. package/dist/esm/helpers/matchUpFormatCode/stringify.mjs +15 -3
  75. package/dist/esm/helpers/matchUpTypeOptions.mjs +30 -0
  76. package/dist/esm/helpers/parameters/checkRequiredParameters.mjs +3 -1
  77. package/dist/esm/index.mjs +17 -13
  78. package/dist/esm/mutate/drawDefinitions/addDrawDefinition.mjs +22 -7
  79. package/dist/esm/mutate/drawDefinitions/addDrawEntries.mjs +2 -0
  80. package/dist/esm/mutate/drawDefinitions/addLinkedConsolationStructure.mjs +1 -1
  81. package/dist/esm/mutate/drawDefinitions/competition/processCompetitionMatchUp.mjs +5 -79
  82. package/dist/esm/mutate/drawDefinitions/competition/processCompetitionRound.mjs +13 -24
  83. package/dist/esm/mutate/drawDefinitions/entryGovernor/addDrawEntries.mjs +6 -2
  84. package/dist/esm/mutate/drawDefinitions/entryGovernor/modifySeedAssignment.mjs +8 -1
  85. package/dist/esm/mutate/drawDefinitions/links/repairMalformedLinks.mjs +1 -1
  86. package/dist/esm/mutate/drawDefinitions/matchUpGovernor/attemptToSetWinningSide.mjs +1 -1
  87. package/dist/esm/mutate/drawDefinitions/matchUpGovernor/noDownstreamDependencies.mjs +19 -9
  88. package/dist/esm/mutate/drawDefinitions/matchUpGovernor/setDelegatedOutcome.mjs +4 -0
  89. package/dist/esm/mutate/drawDefinitions/matchUpGovernor/setOrderOfFinish.mjs +23 -4
  90. package/dist/esm/mutate/drawDefinitions/modifyDrawName.mjs +1 -1
  91. package/dist/esm/mutate/drawDefinitions/modifyPairAssignment.mjs +1 -1
  92. package/dist/esm/mutate/drawDefinitions/positionGovernor/qualifierProgression.mjs +18 -3
  93. package/dist/esm/mutate/drawDefinitions/removeSeededParticipant.mjs +9 -1
  94. package/dist/esm/mutate/drawDefinitions/resetDrawDefinition.mjs +10 -8
  95. package/dist/esm/mutate/drawDefinitions/resetQualifyingStructure.mjs +1 -1
  96. package/dist/esm/mutate/drawDefinitions/resetStructure.mjs +66 -0
  97. package/dist/esm/mutate/entries/addEventEntries.mjs +2 -2
  98. package/dist/esm/mutate/entries/modifyEntriesStatus.mjs +22 -10
  99. package/dist/esm/mutate/entries/moveEntryToGroup.mjs +38 -0
  100. package/dist/esm/mutate/entries/promoteAlternate.mjs +88 -63
  101. package/dist/esm/mutate/entries/refreshEntryPositions.mjs +2 -1
  102. package/dist/esm/mutate/events/addFlight.mjs +10 -1
  103. package/dist/esm/mutate/events/deleteDrawDefinitions.mjs +1 -1
  104. package/dist/esm/mutate/events/deleteEvent.mjs +1 -1
  105. package/dist/esm/mutate/events/deleteFlightAndFlightDraw.mjs +14 -14
  106. package/dist/esm/mutate/events/modifyEvent.mjs +30 -1
  107. package/dist/esm/mutate/events/refreshEventDrawOrder.mjs +6 -4
  108. package/dist/esm/mutate/events/setEventDates.mjs +37 -2
  109. package/dist/esm/mutate/events/updateDrawIdsOrder.mjs +2 -1
  110. package/dist/esm/mutate/extensions/events/modifyEventMatchUpFormatTiming.mjs +2 -2
  111. package/dist/esm/mutate/extensions/policies/attachPolicies.mjs +49 -25
  112. package/dist/esm/mutate/extensions/policies/removePolicy.mjs +11 -12
  113. package/dist/esm/mutate/matchUps/drawPositions/adHocPositionSwap.mjs +1 -1
  114. package/dist/esm/mutate/matchUps/drawPositions/assignDrawPositionBye.mjs +1 -1
  115. package/dist/esm/mutate/matchUps/drawPositions/assignMatchUpSideParticipant.mjs +5 -1
  116. package/dist/esm/mutate/matchUps/drawPositions/removeDirectedParticipants.mjs +6 -3
  117. package/dist/esm/mutate/matchUps/lineUps/applyLineUps.mjs +15 -0
  118. package/dist/esm/mutate/matchUps/lineUps/assignTieMatchUpParticipant.mjs +3 -3
  119. package/dist/esm/mutate/matchUps/lineUps/removeTieMatchUpParticipant.mjs +1 -1
  120. package/dist/esm/mutate/matchUps/lineUps/replaceTieMatchUpParticipant.mjs +2 -2
  121. package/dist/esm/mutate/matchUps/matchUpFormat/applyMatchUpFormat.mjs +8 -6
  122. package/dist/esm/mutate/matchUps/matchUpFormat/setMatchUpFormat.mjs +30 -18
  123. package/dist/esm/mutate/matchUps/matchUpStatus/setMatchUpState.mjs +29 -11
  124. package/dist/esm/mutate/matchUps/matchUpStatus/setMatchUpStatus.mjs +9 -5
  125. package/dist/esm/mutate/matchUps/outcome/apply.mjs +39 -6
  126. package/dist/esm/mutate/matchUps/outcome/decide.mjs +42 -7
  127. package/dist/esm/mutate/matchUps/outcome/differential.mjs +1 -11
  128. package/dist/esm/mutate/matchUps/outcome/finishingOrderOps.mjs +57 -0
  129. package/dist/esm/mutate/matchUps/outcome/ops.mjs +32 -1
  130. package/dist/esm/mutate/matchUps/outcome/plan.mjs +718 -185
  131. package/dist/esm/mutate/matchUps/outcome/refusals.mjs +34 -6
  132. package/dist/esm/mutate/matchUps/outcome/shadow.mjs +2 -2
  133. package/dist/esm/mutate/matchUps/outcome/unwindWalk.mjs +378 -0
  134. package/dist/esm/mutate/matchUps/outcome/view.mjs +281 -19
  135. package/dist/esm/mutate/matchUps/resetScorecard.mjs +19 -1
  136. package/dist/esm/mutate/matchUps/schedule/addSchedulingProfileRound.mjs +19 -2
  137. package/dist/esm/mutate/matchUps/schedule/bulkRescheduleMatchUps.mjs +15 -5
  138. package/dist/esm/mutate/matchUps/schedule/bulkScheduleMatchUps.mjs +1 -1
  139. package/dist/esm/mutate/matchUps/schedule/bulkUpdateCourtAssignments.mjs +1 -1
  140. package/dist/esm/mutate/matchUps/schedule/pipeline/periodStages.mjs +49 -0
  141. package/dist/esm/mutate/matchUps/schedule/pipeline/plan.mjs +13 -2
  142. package/dist/esm/mutate/matchUps/schedule/pipeline/scheduleProfile.mjs +30 -1
  143. package/dist/esm/mutate/matchUps/schedule/pipeline/view.mjs +43 -5
  144. package/dist/esm/mutate/matchUps/schedule/pipeline/write.mjs +14 -6
  145. package/dist/esm/mutate/matchUps/schedule/reorderUpcomingMatchUps.mjs +1 -1
  146. package/dist/esm/mutate/matchUps/schedule/scheduleItems/addMatchUpScheduledDate.mjs +7 -2
  147. package/dist/esm/mutate/matchUps/schedule/scheduleItems/scheduleItems.mjs +45 -7
  148. package/dist/esm/mutate/matchUps/schedule/scheduleItems/setMatchUpHomeParticipantId.mjs +1 -1
  149. package/dist/esm/mutate/matchUps/schedule/scheduleMatchUps/calculateScheduleTimes.mjs +2 -0
  150. package/dist/esm/mutate/matchUps/schedule/scheduleMatchUps/resolveScheduleMatchUpsTiming.mjs +2 -1
  151. package/dist/esm/mutate/matchUps/schedule/scheduleMatchUps/scheduleMatchUps.mjs +42 -4
  152. package/dist/esm/mutate/matchUps/schedule/scheduleProfileGrid.mjs +44 -3
  153. package/dist/esm/mutate/matchUps/schedule/scheduledTime.mjs +5 -2
  154. package/dist/esm/mutate/matchUps/schedule/schedulers/auditAutoScheduling.mjs +3 -0
  155. package/dist/esm/mutate/matchUps/schedule/schedulers/proScheduler/proAutoSchedule.mjs +31 -3
  156. package/dist/esm/mutate/matchUps/schedule/schedulers/processAlreadyScheduledMatchUps.mjs +2 -1
  157. package/dist/esm/mutate/matchUps/score/modifyMatchUpScore.mjs +42 -3
  158. package/dist/esm/mutate/notifications/drawNotifications.mjs +1 -1
  159. package/dist/esm/mutate/participants/addParticipant.mjs +2 -2
  160. package/dist/esm/mutate/participants/createTeamsFromAttributes.mjs +3 -2
  161. package/dist/esm/mutate/participants/deleteParticipants.mjs +1 -1
  162. package/dist/esm/mutate/participants/modifyParticipant.mjs +235 -150
  163. package/dist/esm/mutate/participants/modifyPersonFields.mjs +159 -0
  164. package/dist/esm/mutate/participants/participantSetterFields.mjs +148 -0
  165. package/dist/esm/mutate/participants/personAttributeShapes.mjs +139 -0
  166. package/dist/esm/mutate/participants/removeIndividualParticipantIds.mjs +1 -1
  167. package/dist/esm/mutate/participants/scaleItems/addScaleItems.mjs +1 -1
  168. package/dist/esm/mutate/sanctioning/activateFromSanctioning.mjs +10 -0
  169. package/dist/esm/mutate/scoring/addPoint.mjs +4 -3
  170. package/dist/esm/mutate/simulation/completeDrawMatchUps.mjs +2 -2
  171. package/dist/esm/mutate/structures/deleteAdHocMatchUps.mjs +1 -1
  172. package/dist/esm/mutate/structures/removeRoundMatchUps.mjs +1 -1
  173. package/dist/esm/mutate/tieFormat/addCollectionDefinition.mjs +6 -1
  174. package/dist/esm/mutate/tieFormat/checkTieFormat.mjs +1 -0
  175. package/dist/esm/mutate/tieFormat/collectionGroupUpdate.mjs +1 -1
  176. package/dist/esm/mutate/tieFormat/collectionTypeChange.mjs +147 -0
  177. package/dist/esm/mutate/tieFormat/modifyCollectionDefinition.mjs +95 -27
  178. package/dist/esm/mutate/tieFormat/modifyTieFormat.mjs +26 -2
  179. package/dist/esm/mutate/tieFormat/orderCollectionDefinitions.mjs +1 -1
  180. package/dist/esm/mutate/tieFormat/removeCollectionDefinition.mjs +1 -1
  181. package/dist/esm/mutate/tieFormat/resetTieFormat.mjs +5 -2
  182. package/dist/esm/mutate/timeItems/matchUps/checkInParticipant.mjs +1 -1
  183. package/dist/esm/mutate/timeItems/matchUps/checkOutParticipant.mjs +1 -1
  184. package/dist/esm/mutate/timeItems/matchUps/matchUpTimeItems.mjs +6 -0
  185. package/dist/esm/mutate/tournaments/migrateTournamentRecord.mjs +44 -7
  186. package/dist/esm/mutate/tournaments/schedulingProfile.mjs +20 -3
  187. package/dist/esm/mutate/tournaments/setSanctionConstraints.mjs +118 -0
  188. package/dist/esm/mutate/tournaments/setTournamentDates.mjs +76 -32
  189. package/dist/esm/mutate/tournaments/tournamentDateTrims.mjs +117 -0
  190. package/dist/esm/mutate/venues/addCourtGridBooking.mjs +1 -1
  191. package/dist/esm/mutate/venues/removeCourtGridBooking.mjs +1 -1
  192. package/dist/esm/package.json.mjs +1 -1
  193. package/dist/esm/query/base/timeItems.mjs +1 -1
  194. package/dist/esm/query/drawDefinition/checkSanctionedEntryLimits.mjs +57 -0
  195. package/dist/esm/query/drawDefinition/competition/deriveCompetitionState.mjs +124 -0
  196. package/dist/esm/query/drawDefinition/competition/getCompetitionLeaderboard.mjs +84 -71
  197. package/dist/esm/query/drawDefinition/competition/getCompetitionParticipantState.mjs +2 -2
  198. package/dist/esm/query/drawDefinition/competition/getCompetitionState.mjs +15 -8
  199. package/dist/esm/query/drawDefinition/getBestFinishers.mjs +11 -0
  200. package/dist/esm/query/drawDefinition/getDrawCompositionConstraints.mjs +28 -10
  201. package/dist/esm/query/drawDefinition/getEntryProfileQualifiers.mjs +17 -0
  202. package/dist/esm/query/drawDefinition/getSeedsCount.mjs +1 -1
  203. package/dist/esm/query/drawDefinition/getStageDrawPositions.mjs +53 -16
  204. package/dist/esm/query/drawDefinition/getStageSpace.mjs +36 -17
  205. package/dist/esm/query/drawDefinition/linkGetter.mjs +1 -1
  206. package/dist/esm/query/drawDefinition/linkTraversal.mjs +1 -1
  207. package/dist/esm/query/drawDefinition/stageGetter.mjs +18 -5
  208. package/dist/esm/query/entries/entryPositionGroup.mjs +17 -0
  209. package/dist/esm/query/entries/entryStatusReport.mjs +3 -3
  210. package/dist/esm/query/entries/getEntryStatusOrdinals.mjs +28 -0
  211. package/dist/esm/query/entries/getEventEntrySpace.mjs +44 -0
  212. package/dist/esm/query/event/extractEventInfo.mjs +10 -2
  213. package/dist/esm/query/event/getAllEventData.mjs +1 -1
  214. package/dist/esm/query/event/getEventData.mjs +19 -1
  215. package/dist/esm/query/event/getEventInconsistencies.mjs +30 -3
  216. package/dist/esm/query/event/getEveryDrawFlight.mjs +20 -0
  217. package/dist/esm/query/event/timingCategoryName.mjs +6 -0
  218. package/dist/esm/query/events/eventDateWarning.mjs +28 -0
  219. package/dist/esm/query/events/eventPlaysOnDate.mjs +126 -0
  220. package/dist/esm/query/extensions/getAppliedPolicies.mjs +1 -1
  221. package/dist/esm/query/extensions/matchUpFormatTiming/getEventMatchUpFormatTiming.mjs +3 -2
  222. package/dist/esm/query/extensions/matchUpFormatTiming/getMatchUpFormatTiming.mjs +12 -11
  223. package/dist/esm/query/extensions/matchUpFormatTiming/getScheduleTiming.mjs +2 -1
  224. package/dist/esm/query/hierarchical/getCompetitionFormat.mjs +1 -1
  225. package/dist/esm/query/hierarchical/getMatchUpFormat.mjs +1 -1
  226. package/dist/esm/query/hierarchical/getTieFormat.mjs +1 -1
  227. package/dist/esm/query/hierarchical/tieFormats/getTieFormatDescription.mjs +9 -3
  228. package/dist/esm/query/hierarchical/tieFormats/getTieMatchUpContext.mjs +7 -1
  229. package/dist/esm/query/matchUp/calculateWinCriteria.mjs +9 -5
  230. package/dist/esm/query/matchUp/collectionChoice.mjs +51 -0
  231. package/dist/esm/query/matchUp/finishingOrder.mjs +63 -0
  232. package/dist/esm/query/matchUp/getDualIssues.mjs +171 -0
  233. package/dist/esm/query/matchUp/getMatchUpCheckInHistory.mjs +1 -1
  234. package/dist/esm/query/matchUp/getMatchUpScheduleDetails.mjs +1 -0
  235. package/dist/esm/query/matchUp/resolveDeltaBand.mjs +1 -1
  236. package/dist/esm/query/matchUp/resolveHomeParticipantId.mjs +60 -0
  237. package/dist/esm/query/matchUps/addGoesTo.mjs +1 -1
  238. package/dist/esm/query/matchUps/addMatchUpContext.mjs +23 -13
  239. package/dist/esm/query/matchUps/getCollectionAssignment.mjs +2 -2
  240. package/dist/esm/query/matchUps/roundRobinTally/calculatePercentages.mjs +13 -17
  241. package/dist/esm/query/matchUps/roundRobinTally/getGroupOrder.mjs +25 -211
  242. package/dist/esm/query/matchUps/roundRobinTally/getParticipantResults.mjs +64 -44
  243. package/dist/esm/query/matchUps/roundRobinTally/tallyParticipantResults.mjs +25 -4
  244. package/dist/esm/query/matchUps/scheduling/getEventDateIssues.mjs +38 -0
  245. package/dist/esm/query/matchUps/scheduling/getOvernightRestWarnings.mjs +2 -1
  246. package/dist/esm/query/matchUps/scheduling/getRounds.mjs +22 -6
  247. package/dist/esm/query/matchUps/scheduling/getScheduledRoundsDetails.mjs +2 -2
  248. package/dist/esm/query/matchUps/scheduling/getSchedulingProfileIssues.mjs +30 -3
  249. package/dist/esm/query/matchUps/scheduling/schedulingTiming.mjs +2 -1
  250. package/dist/esm/query/matchUps/scheduling/schedulingUtils.mjs +3 -3
  251. package/dist/esm/query/matchUps/structuralIndex.mjs +28 -7
  252. package/dist/esm/query/participant/participantRoleOf.mjs +10 -0
  253. package/dist/esm/query/participant/paymentStatus.mjs +1 -1
  254. package/dist/esm/query/participant/presencePolicy.mjs +2 -2
  255. package/dist/esm/query/participants/filterParticipants.mjs +5 -7
  256. package/dist/esm/query/readModel/publicParticipant.mjs +2 -2
  257. package/dist/esm/query/reports/recoveryTimeline.mjs +2 -1
  258. package/dist/esm/query/reports/wrappers/wrapParticipantResultsReport.mjs +1 -1
  259. package/dist/esm/query/scoring/getScore.mjs +5 -1
  260. package/dist/esm/query/scoring/getScoreboard.mjs +5 -0
  261. package/dist/esm/query/scoring/overtimeScore.mjs +35 -0
  262. package/dist/esm/query/season/getSeasonAdvancement.mjs +40 -0
  263. package/dist/esm/query/season/getSeasonMovement.mjs +110 -0
  264. package/dist/esm/query/season/getSeasonStandings.mjs +264 -0
  265. package/dist/esm/query/season/planNextPeriod.mjs +84 -0
  266. package/dist/esm/query/standings/fromV1.mjs +98 -0
  267. package/dist/esm/query/standings/orderParticipants.mjs +310 -0
  268. package/dist/esm/query/standings/resultPoints.mjs +40 -0
  269. package/dist/esm/query/tournaments/getTournamentInconsistencies.mjs +75 -2
  270. package/dist/esm/query/tournaments/getTournamentInfo.mjs +4 -3
  271. package/dist/esm/query/venues/getInContextCourt.mjs +12 -2
  272. package/dist/esm/query/venues/venuesAndCourtsGetter.mjs +1 -0
  273. package/dist/esm/tests/engines/asyncEngine/index.mjs +1 -2
  274. package/dist/esm/tools/civilDateTime.mjs +1 -1
  275. package/dist/esm/tools/clock.mjs +1 -1
  276. package/dist/esm/validators/isValidMatchUpFormat.mjs +30 -3
  277. package/dist/esm/validators/rotatingPartnerDraw.mjs +2 -3
  278. package/dist/esm/validators/validateCollectionDefinition.mjs +63 -25
  279. package/dist/esm/validators/validateEntryProfile.mjs +86 -0
  280. package/dist/esm/validators/validateSeason.mjs +249 -0
  281. package/dist/esm/validators/validateTallyPolicy.mjs +171 -0
  282. package/dist/esm/validators/validateTeamLineUp.mjs +6 -0
  283. package/dist/esm/validators/validateTieFormat.mjs +14 -1
  284. package/dist/governors.d.cts +2 -0
  285. package/dist/governors.d.mts +2 -0
  286. package/dist/governors.d.ts +2 -0
  287. package/dist/governors.js +3 -0
  288. package/dist/schema/tournament.schema.json +1700 -355
  289. package/dist/tods-competition-factory.d.cts +3984 -2821
  290. package/dist/tods-competition-factory.d.mts +3984 -2821
  291. package/dist/tods-competition-factory.d.ts +3984 -2821
  292. package/dist/tods-competition-factory.development.cjs.js +17166 -10793
  293. package/dist/tods-competition-factory.development.cjs.js.map +1 -1
  294. package/dist/tods-competition-factory.production.cjs.min.js +1 -1
  295. package/dist/tods-competition-factory.production.cjs.min.js.map +1 -1
  296. package/package.json +29 -16
@@ -2,9 +2,9 @@ import { checkRequiredParameters } from '../helpers/parameters/checkRequiredPara
2
2
  import { firstClassOrExtension } from './firstClassOrExtension.mjs';
3
3
  import { structureSort } from '../functions/sorters/structureSort.mjs';
4
4
  import { structuresOf } from './structureMembers.mjs';
5
- import { STRUCTURE_NOT_FOUND, MISSING_DRAW_DEFINITION, MISSING_STRUCTURES } from '../constants/errorConditionConstants.mjs';
5
+ import { MISSING_DRAW_DEFINITION, MISSING_STRUCTURES, STRUCTURE_NOT_FOUND } from '../constants/errorConditionConstants.mjs';
6
6
  import { STRUCTURE_ID, DRAW_DEFINITION } from '../constants/attributeConstants.mjs';
7
- import { ITEM, validStages } from '../constants/drawDefinitionConstants.mjs';
7
+ import { validStages, ITEM } from '../constants/drawDefinitionConstants.mjs';
8
8
  import { ROUND_TARGET } from '../constants/extensionConstants.mjs';
9
9
 
10
10
  function findStructure(params) {
@@ -0,0 +1,8 @@
1
+ import { competitionEngineAsync as competitionEngineAsync$1 } from '../../../tests/engines/asyncEngine/index.mjs';
2
+ import { asyncEngine as asyncEngine$1 } from './index.mjs';
3
+
4
+ const asyncEngine = asyncEngine$1;
5
+ const competitionEngineAsync = competitionEngineAsync$1;
6
+ const tournamentEngineAsync = competitionEngineAsync;
7
+
8
+ export { asyncEngine, competitionEngineAsync, tournamentEngineAsync };
@@ -11,7 +11,7 @@ import { processResult } from './processResult.mjs';
11
11
  import { factoryVersion } from '../../../functions/global/factoryVersion.mjs';
12
12
  import { setRandomSource } from '../../../tools/prng.mjs';
13
13
  import { getTournament, getState, setTournamentRecord, setState, removeUnlinkedTournamentRecords } from './stateMethods.mjs';
14
- import { setTournamentRecords, getDevContext, getSchemaWriteMode, getOutcomePipeline, getSaveDrawDeletions, getAuditAuthorityServer, setTournamentId, setDeepCopy, getTournamentId, removeTournamentRecord, setDevContext, setSchemaWriteMode, setOutcomePipeline, setSaveDrawDeletions, setAuditAuthorityServer } from '../../../global/state/globalState.mjs';
14
+ import { setTournamentRecords, getDevContext, setSchemaWriteMode, getSchemaWriteMode, setOutcomePipeline, getOutcomePipeline, setSaveDrawDeletions, getSaveDrawDeletions, setAuditAuthorityServer, getAuditAuthorityServer, setTournamentId, setDeepCopy, getTournamentId, removeTournamentRecord, setDevContext } from '../../../global/state/globalState.mjs';
15
15
  import { SUCCESS } from '../../../constants/resultConstants.mjs';
16
16
 
17
17
  function engineStart(engine, engineInvoke) {
@@ -1,6 +1,6 @@
1
1
  import { getRecordLinkedTournamentIds } from '../../../acquire/getRecordLinkedTournamentIds.mjs';
2
2
  import { makeDeepCopy } from '../../../tools/makeDeepCopy.mjs';
3
- import { getTournamentId, getTournamentRecord, setTournamentRecord as setTournamentRecord$1, setTournamentId, setTournamentRecords, getTournamentRecords } from '../../../global/state/globalState.mjs';
3
+ import { getTournamentId, getTournamentRecord, getTournamentRecords, setTournamentRecord as setTournamentRecord$1, setTournamentId, setTournamentRecords } from '../../../global/state/globalState.mjs';
4
4
  import { INVALID_OBJECT, INVALID_VALUES, INVALID_RECORDS } from '../../../constants/errorConditionConstants.mjs';
5
5
 
6
6
  function getState({ convertExtensions, removeExtensions }) {
@@ -30,6 +30,8 @@ const CALCULATED_POINT_FIELDS = new Set([
30
30
  'gamesToSet',
31
31
  'isBreakpoint',
32
32
  'serveSide',
33
+ 'phase',
34
+ 'periodNumber',
33
35
  ]);
34
36
  function refusal(message) {
35
37
  return { code: INVALID_VALUES.code, message };
@@ -22,6 +22,8 @@ function units(set) {
22
22
  return [set.side1TiebreakScore ?? set.side1Score, set.side2TiebreakScore ?? set.side2Score];
23
23
  }
24
24
  function decideAggregate(match, sets) {
25
+ if (match.overtime)
26
+ return decideOvertime(match, sets);
25
27
  const counted = sets.slice(0, match.n);
26
28
  if (counted.length < match.n || !counted.every(isClosed))
27
29
  return IN_PLAY;
@@ -39,6 +41,38 @@ function decideAggregate(match, sets) {
39
41
  return IN_PLAY;
40
42
  return { complete: true, winningSide: decider.winningSide };
41
43
  }
44
+ function decideOvertime(match, sets) {
45
+ const regulation = sets.slice(0, match.n);
46
+ if (regulation.length < match.n || !regulation.every(isClosed))
47
+ return IN_PLAY;
48
+ let total = sumUnits(regulation);
49
+ if (total[0] !== total[1])
50
+ return moreOf(total);
51
+ const overtime = match.overtime;
52
+ const periods = sets.slice(match.n, overtime.count === 'unlimited' ? undefined : match.n + overtime.count);
53
+ for (const period of periods) {
54
+ const [a, b] = units(period);
55
+ total = [total[0] + a, total[1] + b];
56
+ if (!isClosed(period))
57
+ return overtime.suddenDeath && total[0] !== total[1] ? moreOf(total) : IN_PLAY;
58
+ if (!overtime.exactly && total[0] !== total[1])
59
+ return moreOf(total);
60
+ }
61
+ if (overtime.count === 'unlimited' || periods.length < overtime.count)
62
+ return IN_PLAY;
63
+ if (total[0] !== total[1])
64
+ return moreOf(total);
65
+ if (!match.final)
66
+ return { complete: true };
67
+ const decider = sets[match.n + overtime.count];
68
+ return decider && isClosed(decider) ? { complete: true, winningSide: decider.winningSide } : IN_PLAY;
69
+ }
70
+ function sumUnits(sets) {
71
+ return sets.reduce((sum, set) => {
72
+ const [a, b] = units(set);
73
+ return [sum[0] + a, sum[1] + b];
74
+ }, [0, 0]);
75
+ }
42
76
  function decidePastClose(match, sets) {
43
77
  if (sets.length < match.n || !sets.every(isClosed))
44
78
  return IN_PLAY;
@@ -1,17 +1,18 @@
1
- import { calculateMatchStatistics } from '../../../../query/scoring/statistics/standalone.mjs';
1
+ import { overtimeLayout, scoringPeriod, segmentClosed } from '../../../../helpers/matchUpFormatCode/overtimeContext.mjs';
2
+ import { initialState, createContext, step, positionOf, INVALID_FORMAT, serverOf } from './reduce.mjs';
2
3
  import { DEFAULT_MATCHUP_FORMAT, takesInput, finalGoverns } from './format.mjs';
4
+ import { readChallenge, readServer, readPoint, CALCULATED_POINT_FIELDS } from './actions.mjs';
5
+ import { replayLegacy, LEGACY_REFUSED_INPUT, LEGACY_IGNORED_INPUT } from './legacy.mjs';
6
+ import { calculateMatchStatistics } from '../../../../query/scoring/statistics/standalone.mjs';
3
7
  import { toStatObjects } from '../../../../query/scoring/statistics/toStatObjects.mjs';
4
- import { initialState, createContext, step, positionOf, INVALID_FORMAT, serverOf } from './reduce.mjs';
5
8
  import { createMatchUp } from '../../../../mutate/scoring/createMatchUp.mjs';
6
9
  import { getScoreboard } from '../../../../query/scoring/getScoreboard.mjs';
7
10
  import { parse } from '../../../../helpers/matchUpFormatCode/parse.mjs';
8
11
  import { getEpisodes } from '../../../../query/scoring/getEpisodes.mjs';
9
- import { readChallenge, readServer, readPoint, CALCULATED_POINT_FIELDS } from './actions.mjs';
10
- import { replayLegacy, LEGACY_REFUSED_INPUT, LEGACY_IGNORED_INPUT } from './legacy.mjs';
11
12
  import { scoreOf, ruleInPlay } from './score.mjs';
12
13
  import { materialize } from './record.mjs';
13
- import { setsWon } from './decide.mjs';
14
14
  import { nowIso } from '../../../../tools/clock.mjs';
15
+ import { setsWon } from './decide.mjs';
15
16
  import { initialLineUpsOf, substitutionError, substituted, substitutionViolations, copyLineUps, hasLineUps } from './lineUps.mjs';
16
17
  import { COMPLETED } from '../../../../constants/matchUpStatusValues.mjs';
17
18
 
@@ -63,14 +64,16 @@ class ScoringEngine {
63
64
  isDoubles: options.isDoubles || false,
64
65
  });
65
66
  this.entries = [];
67
+ if (this.context().match?.overtime)
68
+ this.write([]);
66
69
  }
67
70
  context() {
68
71
  const context = createContext({
69
72
  matchUpFormat: this.matchUpFormat,
70
73
  competitionFormat: this.competitionFormat,
71
74
  pointMultipliers: this.pointMultipliers,
72
- });
73
- if (!this.pastClose || !context.match)
75
+ }, { allowOvertime: true });
76
+ if (!this.pastClose || !context.match || context.match.overtime)
74
77
  return context;
75
78
  return { ...context, match: { ...context.match, pastClose: true } };
76
79
  }
@@ -104,7 +107,7 @@ class ScoringEngine {
104
107
  const before = state;
105
108
  const result = step(context, state, unindexed);
106
109
  let next = result.state;
107
- if (!result.outcome.recorded) {
110
+ if (!result.outcome.recorded && !context.match?.overtime) {
108
111
  const v1 = replayLegacy(context, state, unindexed, result.outcome);
109
112
  legacy.add(v1?.shape ?? ('refused' in result.outcome ? LEGACY_REFUSED_INPUT : LEGACY_IGNORED_INPUT));
110
113
  if (v1)
@@ -379,6 +382,10 @@ class ScoringEngine {
379
382
  }
380
383
  patchPoint(pointIndex, fields) {
381
384
  const points = [...(this.record.history?.points ?? [])];
385
+ if (this.context().match?.overtime) {
386
+ const { phase: _phase, periodNumber: _period, ...metadata } = fields;
387
+ fields = metadata;
388
+ }
382
389
  points[pointIndex] = { ...points[pointIndex], ...fields };
383
390
  this.record = { ...this.record, history: { ...this.record.history, points } };
384
391
  }
@@ -434,17 +441,25 @@ class ScoringEngine {
434
441
  this.legacyShapes = new Set();
435
442
  this.stale = false;
436
443
  this.initialServer = undefined;
444
+ if (this.context().match?.overtime)
445
+ this.write([]);
437
446
  this.eventHandlers?.onReset?.(this.eventContext());
438
447
  }
439
448
  setState(matchUp) {
440
449
  const loaded = copy(matchUp);
450
+ const overtime = !!parse(loaded.matchUpFormat)?.overtimeFormat;
451
+ const overtimeTimeline = overtime ? readOvertimeTimeline(loaded) : undefined;
441
452
  this.record = loaded;
442
453
  this.matchUpFormat = loaded.matchUpFormat;
443
454
  this.redoStack = [];
444
- this.entries = loaded.history?.entries ? [...loaded.history.entries] : undefined;
455
+ this.entries = overtimeTimeline ?? (loaded.history?.entries ? [...loaded.history.entries] : undefined);
445
456
  this.lineUps = lineUpsOf(loaded);
446
457
  this.initialLineUps = initialLineUpsOf(this.lineUps, this.entries, loaded.history?.substitutions);
447
458
  this.initialServer = loaded.history?.initialServer;
459
+ if (overtime) {
460
+ this.rebuild();
461
+ return;
462
+ }
448
463
  this.prepare();
449
464
  this.legacyShapes = new Set();
450
465
  this.stale = true;
@@ -571,6 +586,14 @@ class ScoringEngine {
571
586
  return undefined;
572
587
  const closed = this.state.sets.filter((set) => set.winningSide || set.segmentComplete);
573
588
  const setNumber = Math.min(positionOf(match, this.state).set.setNumber, Math.max(closed.length + 1, 1));
589
+ const layout = overtimeLayout(structure);
590
+ if (layout) {
591
+ const current = this.state.matchUpStatus === COMPLETED ? (this.state.sets.at(-1)?.setNumber ?? 1) : setNumber;
592
+ const period = scoringPeriod(layout, current);
593
+ if (period?.phase === 'OVERTIME')
594
+ return structure.overtimeFormat?.setFormat;
595
+ return period?.phase === 'DECIDER' ? structure.finalSetFormat : structure.setFormat;
596
+ }
574
597
  const final = finalGoverns(match, setNumber, setsWon(this.state.sets.slice(0, setNumber - 1)));
575
598
  return final && structure.finalSetFormat ? structure.finalSetFormat : structure.setFormat;
576
599
  }
@@ -653,6 +676,46 @@ class ScoringEngine {
653
676
  return this.competitionFormat?.playerRules;
654
677
  }
655
678
  }
679
+ function readOvertimeTimeline(record) {
680
+ const context = createContext({ matchUpFormat: record.matchUpFormat }, { allowOvertime: true });
681
+ if (!context.match?.overtime)
682
+ throw new Error('Unsupported overtime format');
683
+ if (record.history?.entries?.length)
684
+ return [...record.history.entries];
685
+ if (record.history?.points?.length)
686
+ throw new Error('Overtime point records require a scoring timeline');
687
+ const sets = record.score.sets;
688
+ const last = sets.at(-1);
689
+ if (!last)
690
+ return [];
691
+ const open = record.matchUpStatus !== COMPLETED && !segmentClosed(last);
692
+ const entry = {
693
+ type: 'setInitialScore',
694
+ timestamp: record.endTime ?? record.createdAt ?? nowIso(),
695
+ data: {
696
+ sets: open ? sets.slice(0, -1) : sets,
697
+ ...(open ? openOvertimeBaseline(last) : {}),
698
+ matchUpStatus: record.matchUpStatus,
699
+ ...(record.winningSide === undefined ? {} : { winningSide: record.winningSide }),
700
+ },
701
+ };
702
+ const result = step(context, initialState(), { ...entry });
703
+ if (!result.outcome.recorded)
704
+ refusedWith(result.outcome);
705
+ return [entry];
706
+ }
707
+ function openOvertimeBaseline(set) {
708
+ if (set.isTiebreakOnly) {
709
+ return {
710
+ currentSetScore: { side1Score: 0, side2Score: 0 },
711
+ currentGameScore: {
712
+ side1Points: set.side1GameScores?.at(-1) ?? set.side1TiebreakScore ?? set.side1Score ?? 0,
713
+ side2Points: set.side2GameScores?.at(-1) ?? set.side2TiebreakScore ?? set.side2Score ?? 0,
714
+ },
715
+ };
716
+ }
717
+ return { currentSetScore: { side1Score: set.side1Score ?? 0, side2Score: set.side2Score ?? 0 } };
718
+ }
656
719
  function lineUpsAfter(initial, entries) {
657
720
  if (!initial)
658
721
  return undefined;
@@ -1,3 +1,4 @@
1
+ import { overtimeFinalNumber, overtimeGoverns } from './overtime.mjs';
1
2
  import { parse } from '../../../../helpers/matchUpFormatCode/parse.mjs';
2
3
 
3
4
  const DEFAULT_MATCHUP_FORMAT = 'SET3-S:6/TB7';
@@ -47,17 +48,20 @@ function segmentRule(setFormat, gameFormat, context) {
47
48
  const at = Number(setFormat.tiebreakAt ?? setTo);
48
49
  return { kind: 'standard', setTo, winBy: 2, tiebreak: { at, race: raceRule(setFormat.tiebreakFormat) }, game };
49
50
  }
50
- function resolveFormat(code) {
51
+ function resolveFormat(code, options = {}) {
51
52
  if (!code)
52
53
  return undefined;
53
54
  const parsed = parse(code);
54
- if (!parsed?.setFormat)
55
+ if (!parsed?.setFormat || (parsed.overtimeFormat && !options.allowOvertime))
55
56
  return undefined;
56
57
  const exactly = parsed.exactly;
57
58
  const n = exactly ?? parsed.bestOf ?? 1;
58
59
  const context = { tennisFamily: !parsed.matchRoot && !parsed.aggregate && !parsed.simplified };
59
60
  const ordinary = segmentRule(parsed.setFormat, parsed.gameFormat, context);
60
61
  const final = parsed.finalSetFormat ? segmentRule(parsed.finalSetFormat, parsed.gameFormat, context) : undefined;
62
+ const overtime = parsed.overtimeFormat;
63
+ if (overtime && !supportsOvertime(parsed, n, ordinary, final))
64
+ return undefined;
61
65
  return {
62
66
  code,
63
67
  mode: exactly ? 'exactly' : 'bestOf',
@@ -66,12 +70,34 @@ function resolveFormat(code) {
66
70
  setsToWin: Math.floor(n / 2) + 1,
67
71
  ordinary,
68
72
  ...(final ? { final } : {}),
73
+ ...(overtime
74
+ ? {
75
+ overtime: {
76
+ count: overtime.count,
77
+ exactly: !!overtime.exactly,
78
+ suddenDeath: !!overtime.suddenDeath,
79
+ rule: segmentRule(overtime.setFormat, parsed.gameFormat, context),
80
+ },
81
+ }
82
+ : {}),
69
83
  };
70
84
  }
85
+ function supportsOvertime(parsed, n, ordinary, final) {
86
+ const overtime = parsed.overtimeFormat;
87
+ if (parsed.matchUpConstraint || ordinary.kind !== 'timed' || ordinary.tiebreak)
88
+ return false;
89
+ if (!overtime.setFormat.timed || overtime.setFormat.tiebreakFormat)
90
+ return false;
91
+ if (final && final.kind !== 'tiebreakOnly' && (final.kind !== 'timed' || final.tiebreak))
92
+ return false;
93
+ return overtime.count === 'unlimited' || Number.isSafeInteger(n + overtime.count + (final ? 1 : 0));
94
+ }
71
95
  function configuredFormat(config) {
72
96
  return config.matchUpFormat ?? config.competitionFormat?.matchUpFormat ?? DEFAULT_MATCHUP_FORMAT;
73
97
  }
74
98
  function finalGoverns(match, setNumber, setsWon) {
99
+ if (match.overtime)
100
+ return setNumber === overtimeFinalNumber(match);
75
101
  if (match.mode === 'exactly')
76
102
  return setNumber === (match.aggregate ? match.n + 1 : match.n);
77
103
  if (setNumber === match.n)
@@ -82,6 +108,8 @@ function finalGoverns(match, setNumber, setsWon) {
82
108
  return setsWon[0] === oneFromWinning && setsWon[1] === oneFromWinning;
83
109
  }
84
110
  function ruleForSet(match, setNumber, setsWon) {
111
+ if (match.overtime && overtimeGoverns(match, setNumber))
112
+ return match.overtime.rule;
85
113
  return match.final && finalGoverns(match, setNumber, setsWon) ? match.final : match.ordinary;
86
114
  }
87
115
  function takesInput(rule, input) {
@@ -0,0 +1,30 @@
1
+ import { scoringPeriod } from '../../../../helpers/matchUpFormatCode/overtimeContext.mjs';
2
+
3
+ function overtimeGoverns(match, setNumber) {
4
+ const overtime = match.overtime;
5
+ return !!overtime && setNumber > match.n && (overtime.count === 'unlimited' || setNumber <= match.n + overtime.count);
6
+ }
7
+ function overtimeFinalNumber(match) {
8
+ const overtime = match.overtime;
9
+ return overtime && overtime.count !== 'unlimited' && match.final ? match.n + overtime.count + 1 : undefined;
10
+ }
11
+ function lastPlayableSet(match) {
12
+ if (match.overtime) {
13
+ if (match.overtime.count === 'unlimited')
14
+ return undefined;
15
+ return match.n + match.overtime.count + (match.final ? 1 : 0);
16
+ }
17
+ return match.n + (match.mode === 'exactly' && match.aggregate && match.final ? 1 : 0);
18
+ }
19
+ function overtimeTotalError(match, setNumber, totals) {
20
+ return match.overtime?.suddenDeath && overtimeGoverns(match, setNumber) && totals[0] > 0 && totals[1] > 0
21
+ ? 'a sudden-death overtime total cannot have scoring by both sides'
22
+ : undefined;
23
+ }
24
+ function periodForSet(match, setNumber) {
25
+ return match.overtime
26
+ ? scoringPeriod({ regulationCount: match.n, overtimeCount: match.overtime.count, finalDecider: !!match.final }, setNumber)
27
+ : undefined;
28
+ }
29
+
30
+ export { lastPlayableSet, overtimeFinalNumber, overtimeGoverns, overtimeTotalError, periodForSet };
@@ -1,4 +1,6 @@
1
1
  import { hasLineUps, substituted, activePlayersOf } from './lineUps.mjs';
2
+ import { overtimeScoreContext } from '../../../../helpers/matchUpFormatCode/overtimeContext.mjs';
3
+ import { parse } from '../../../../helpers/matchUpFormatCode/parse.mjs';
2
4
  import { isClosed } from './decide.mjs';
3
5
  import { COMPLETED } from '../../../../constants/matchUpStatusValues.mjs';
4
6
  import { POINT, SUBSTITUTION } from './actions.mjs';
@@ -59,6 +61,10 @@ function materialize({ base, state, entries, completedBy, lineUps, timeline, ini
59
61
  score: { sets: recordedSets(state) },
60
62
  sides: (identity.sides ?? []).map((side) => lineUps.current?.[side.sideNumber] ? { ...side, lineUp: lineUps.current[side.sideNumber] } : side),
61
63
  };
64
+ const format = parse(base.matchUpFormat);
65
+ const overtime = format && overtimeScoreContext(format, recorded.score.sets, state.matchUpStatus);
66
+ if (overtime)
67
+ recorded.score.overtime = overtime;
62
68
  if (previous || entries.length || points.length || initialServer !== undefined)
63
69
  recorded.history = history;
64
70
  return recorded;
@@ -1,14 +1,15 @@
1
1
  import { INITIAL_SERVICE, nextServer, corrected, serveSide, afterPoint, serviceCode } from './service.mjs';
2
+ import { lastPlayableSet, overtimeTotalError, periodForSet, overtimeGoverns } from './overtime.mjs';
2
3
  import { resolveFormat, configuredFormat, ruleForSet, takesInput } from './format.mjs';
3
- import { pointsTo, isBreakpoint } from './view.mjs';
4
4
  import { setsWon, isClosed, decideMatch } from './decide.mjs';
5
- import { openSet, atTimeIn, segmentEnd, segmentTotal, segmentGame, pointsAreUnits, segmentPoint, decidedInPlay } from './segments/segment.mjs';
5
+ import { pointsTo, isBreakpoint } from './view.mjs';
6
6
  import { NEEDS_A_FORMAT, refusal, ANNOTATION, SUBSTITUTION, CHALLENGE, readChallenge, SET_SERVER, readServer, END_SEGMENT, SET_INITIAL_SCORE, SET, GAME, POINT, readEndSegment, readSetTotal, readGame, readPoint, pointFacts } from './actions.mjs';
7
+ import { openSet, atTimeIn, segmentEnd, segmentTotal, segmentGame, pointsAreUnits, segmentPoint, decidedInPlay } from './segments/segment.mjs';
7
8
  import { TO_BE_PLAYED, COMPLETED, IN_PROGRESS } from '../../../../constants/matchUpStatusValues.mjs';
8
9
 
9
- function createContext(config) {
10
+ function createContext(config, options = {}) {
10
11
  return {
11
- match: resolveFormat(configuredFormat(config)),
12
+ match: resolveFormat(configuredFormat(config), options),
12
13
  multipliers: config.pointMultipliers ?? config.competitionFormat?.pointMultipliers ?? [],
13
14
  rules: { winnerServes: config.competitionFormat?.serverRule === 'WINNER_SERVES' },
14
15
  };
@@ -48,20 +49,27 @@ function target(match, state) {
48
49
  return { set: last, rule, game: state.game, index: state.sets.length - 1, atTime: atTimeIn(rule, last) };
49
50
  }
50
51
  const setNumber = state.sets.length + 1;
51
- const decider = match.mode === 'exactly' && match.aggregate && match.final ? 1 : 0;
52
- if (setNumber > match.n + decider && !match.pastClose)
52
+ const limit = lastPlayableSet(match);
53
+ if (limit !== undefined && setNumber > limit && !match.pastClose)
53
54
  return undefined;
54
55
  const rule = ruleForSet(match, setNumber, setsWon(state.sets));
55
56
  return { set: openSet(rule, setNumber), rule, index: state.sets.length, atTime: false };
56
57
  }
57
58
  function scored(match, state, at, result, scoring = true) {
58
- const sets = [...state.sets.slice(0, at.index), result.set];
59
+ const labeled = { ...result.set, ...periodForSet(match, at.set.setNumber) };
60
+ const sets = [...state.sets.slice(0, at.index), labeled];
59
61
  const decision = decideMatch(match, sets);
62
+ const suddenDeathWin = match.overtime?.suddenDeath &&
63
+ overtimeGoverns(match, at.set.setNumber) &&
64
+ decision.complete &&
65
+ decision.winningSide;
66
+ if (suddenDeathWin)
67
+ sets[at.index] = { ...labeled, segmentComplete: true, winningSide: decision.winningSide };
60
68
  const { winningSide: _previous, game: _game, ...rest } = state;
61
69
  return {
62
70
  ...rest,
63
71
  sets,
64
- ...(result.game ? { game: result.game } : {}),
72
+ ...(result.game && !suddenDeathWin ? { game: result.game } : {}),
65
73
  matchUpStatus: decision.complete ? COMPLETED : IN_PROGRESS,
66
74
  ...(decision.winningSide ? { winningSide: decision.winningSide } : {}),
67
75
  scoringEntries: state.scoringEntries + (scoring ? 1 : 0),
@@ -115,6 +123,7 @@ function point(context, match, state, entry) {
115
123
  const index = state.points.length;
116
124
  const materialized = {
117
125
  ...pointFacts(entry.data),
126
+ ...periodForSet(match, at.set.setNumber),
118
127
  winner,
119
128
  winningSide: (winner + 1),
120
129
  ...(server === undefined ? {} : { server, serverSideNumber: (server + 1) }),
@@ -156,6 +165,9 @@ function set(match, state, entry) {
156
165
  const at = aimed(match, state);
157
166
  if (typeof at === 'string')
158
167
  return ignored(state, at);
168
+ const overtimeError = overtimeTotalError(match, at.set.setNumber, facts.total.totals);
169
+ if (overtimeError)
170
+ return refused(state, refusal(overtimeError));
159
171
  const result = segmentTotal(at.rule, at.set.setNumber, facts.total);
160
172
  if ('refused' in result)
161
173
  return refused(state, refusal(result.refused));
@@ -202,9 +214,14 @@ function baselineSets(match, given) {
202
214
  const sets = [];
203
215
  let atTime = false;
204
216
  for (const [i, data] of given.entries()) {
217
+ if (match.overtime && decideMatch(match, sets).complete)
218
+ return { refused: 'an overtime baseline includes a segment after the match was decided' };
205
219
  const facts = readSetTotal(data);
206
220
  if (facts.refused)
207
221
  return { refused: facts.refused.message };
222
+ const overtimeError = overtimeTotalError(match, i + 1, facts.total.totals);
223
+ if (overtimeError)
224
+ return { refused: overtimeError };
208
225
  const rule = ruleForSet(match, i + 1, setsWon(sets));
209
226
  const judged = segmentTotal(rule, i + 1, facts.total);
210
227
  if ('refused' in judged)
@@ -214,7 +231,7 @@ function baselineSets(match, given) {
214
231
  return { refused: `Set ${i + 1} is not finished and is not the last set` };
215
232
  if (atTimeSet)
216
233
  atTime = true;
217
- sets.push(judged.set);
234
+ sets.push({ ...judged.set, ...periodForSet(match, i + 1) });
218
235
  }
219
236
  return { sets, atTime };
220
237
  }
@@ -245,15 +262,45 @@ function baselineInPlay(match, sets, data) {
245
262
  if (given && raceInPlay)
246
263
  return { refused: raceNamedTwice(setNumber) };
247
264
  const base = open && !raceInPlay ? last : openSet(rule, setNumber);
248
- const inPlay = { ...base, side1Score: base.side1Score + games[0], side2Score: base.side2Score + games[1] };
265
+ const checked = overtimeBaselineSet(match, rule, {
266
+ ...base,
267
+ side1Score: base.side1Score + games[0],
268
+ side2Score: base.side2Score + games[1],
269
+ ...periodForSet(match, setNumber),
270
+ }, given, !!currentSetScore);
271
+ if ('refused' in checked)
272
+ return checked;
273
+ const inPlay = checked;
249
274
  if (decidedInPlay(rule, [inPlay.side1Score, inPlay.side2Score]))
250
275
  return { refused: 'the set in play is already won' };
251
276
  if (rule.kind === 'combined')
252
277
  return { sets: [...closed, inPlay] };
253
- const points = given ?? (raceInPlay ? [last.side1Score, last.side2Score] : [0, 0]);
278
+ const points = baselinePoints(match, rule, inPlay, raceInPlay ? last : undefined, given);
254
279
  const withGame = { ...inPlay, side1GameScores: [points[0]], side2GameScores: [points[1]] };
255
280
  return { sets: [...closed, withGame], game: { score: points, pointsPlayed: points[0] + points[1] } };
256
281
  }
282
+ function baselinePoints(match, rule, inPlay, race, given) {
283
+ if (given)
284
+ return given;
285
+ if (match.overtime && rule.kind === 'timed')
286
+ return [inPlay.side1Score, inPlay.side2Score];
287
+ return race ? [race.side1Score, race.side2Score] : [0, 0];
288
+ }
289
+ function overtimeBaselineSet(match, rule, set, given, setGiven) {
290
+ if (!match.overtime)
291
+ return set;
292
+ let inPlay = set;
293
+ if (rule.kind === 'timed' && given) {
294
+ if (setGiven && (given[0] !== set.side1Score || given[1] !== set.side2Score))
295
+ return { refused: 'timed overtime baseline games and points name the same totals and must agree' };
296
+ inPlay = { ...set, side1Score: given[0], side2Score: given[1] };
297
+ }
298
+ if (match.overtime.suddenDeath &&
299
+ overtimeGoverns(match, set.setNumber) &&
300
+ [inPlay.side1Score, inPlay.side2Score, ...(given ?? [])].some((score) => score > 0))
301
+ return { refused: 'a sudden-death overtime with a nonzero score is already decided, not in play' };
302
+ return inPlay;
303
+ }
257
304
  const raceNamedTwice = (setNumber) => `Set ${setNumber} is a tiebreak-only set in play, and a currentGameScore names its points again`;
258
305
  function combinedInPlay(match, sets, open) {
259
306
  const closed = open ? sets.slice(0, -1) : sets;
@@ -341,5 +388,19 @@ function apply(context, state, entry, live) {
341
388
  return scoreless(state);
342
389
  }
343
390
  }
391
+ function reduce(config, timeline, options = {}) {
392
+ const context = createContext(config, options);
393
+ const outcomes = [];
394
+ const legacy = [];
395
+ let state = initialState();
396
+ for (const [index, entry] of timeline.entries()) {
397
+ const result = step(context, state, entry);
398
+ outcomes.push(result.outcome);
399
+ if (!result.outcome.recorded)
400
+ legacy.push(index);
401
+ state = result.state;
402
+ }
403
+ return { state, outcomes, legacy };
404
+ }
344
405
 
345
- export { INVALID_FORMAT, createContext, initialState, positionOf, raceNamedTwice, serverOf, step };
406
+ export { INVALID_FORMAT, createContext, initialState, positionOf, raceNamedTwice, reduce, serverOf, step };
@@ -1,6 +1,8 @@
1
- import { positionOf, serverOf } from './reduce.mjs';
1
+ import { overtimeScoreContext, overtimeScoreString } from '../../../../helpers/matchUpFormatCode/overtimeContext.mjs';
2
+ import { parse } from '../../../../helpers/matchUpFormatCode/parse.mjs';
2
3
  import { combinedClosed } from './segments/combined.mjs';
3
4
  import { inTiebreak } from './segments/standard.mjs';
5
+ import { positionOf, serverOf } from './reduce.mjs';
4
6
  import { atTimeIn } from './segments/segment.mjs';
5
7
  import { isClosed } from './decide.mjs';
6
8
  import { pointsTo } from './view.mjs';
@@ -110,9 +112,12 @@ function inPlay(context, state) {
110
112
  }
111
113
  function scoreOf(context, state, sets) {
112
114
  const { games, points, pointDisplay } = inPlay(context, state);
115
+ const format = context.match?.overtime && parse(context.match.code);
116
+ const overtime = format && overtimeScoreContext(format, sets, state.matchUpStatus);
113
117
  return {
114
118
  sets,
115
- scoreString: scoreString(sets),
119
+ scoreString: overtime ? overtimeScoreString(overtime) : scoreString(sets),
120
+ ...(overtime ? { overtime } : {}),
116
121
  games,
117
122
  points,
118
123
  pointDisplay,
@@ -1,5 +1,6 @@
1
1
  import { playRacePoint, playGamePoint, NEW_GAME } from './segments/game.mjs';
2
2
  import { inTiebreak, standardSetWinner } from './segments/standard.mjs';
3
+ import { overtimeGoverns } from './overtime.mjs';
3
4
  import { ruleForSet } from './format.mjs';
4
5
  import { setsWon } from './decide.mjs';
5
6
 
@@ -108,6 +109,8 @@ function counted(rule) {
108
109
  return rule.kind === 'standard' || rule.kind === 'tiebreakOnly';
109
110
  }
110
111
  function pointsTo(state, position) {
112
+ if (position.match.overtime?.suddenDeath && overtimeGoverns(position.match, position.set.setNumber))
113
+ return { pointsToGame: [1, 1], pointsToSet: [1, 1], pointsToMatch: [1, 1], gamesToSet: [1, 1] };
111
114
  const { rule, set, game } = position;
112
115
  if (!counted(rule))
113
116
  return undefined;
@@ -35,7 +35,7 @@ function generateDrawMaticRound(params) {
35
35
  let sourceRatingType;
36
36
  const { competitionPolicy } = getCompetitionPolicy({ tournamentRecord, drawDefinition, event });
37
37
  const { competitionState } = competitionPolicy
38
- ? getCompetitionState({ drawDefinition })
38
+ ? getCompetitionState({ drawDefinition, competitionPolicy })
39
39
  : { competitionState: undefined };
40
40
  const useCompetitionRatings = competitionPolicy && competitionState && competitionPolicy.pairingPolicy.ratingSource === 'DYNAMIC_FORM';
41
41
  if (useCompetitionRatings) {
@@ -47,7 +47,7 @@ function generateSwissRound(params) {
47
47
  }
48
48
  const { competitionPolicy } = getCompetitionPolicy({ tournamentRecord, drawDefinition, event });
49
49
  const { competitionState } = competitionPolicy
50
- ? getCompetitionState({ drawDefinition })
50
+ ? getCompetitionState({ drawDefinition, competitionPolicy })
51
51
  : { competitionState: undefined };
52
52
  let adHocRatings;
53
53
  if (competitionPolicy && competitionState && competitionPolicy.pairingPolicy.ratingSource === 'DYNAMIC_FORM') {
@@ -35,7 +35,7 @@ function generateVoluntaryConsolation(params) {
35
35
  return { error: INVALID_DRAW_SIZE };
36
36
  let { tieFormat, matchUpType } = params;
37
37
  if (tieFormat) {
38
- const result = validateTieFormat({ tieFormat });
38
+ const result = validateTieFormat({ tieFormat, enforceValues: true });
39
39
  if (result.error)
40
40
  return result;
41
41
  }
@@ -22,7 +22,7 @@ import { addGoesTo } from '../../../query/matchUps/addGoesTo.mjs';
22
22
  import { generateTieMatchUps } from './tieMatchUps.mjs';
23
23
  import { makeDeepCopy } from '../../../tools/makeDeepCopy.mjs';
24
24
  import { ensureInt } from '../../../tools/ensureInt.mjs';
25
- import { INVALID_VALUES, MISSING_DRAW_DEFINITION, STRUCTURE_NOT_FOUND } from '../../../constants/errorConditionConstants.mjs';
25
+ import { MISSING_DRAW_DEFINITION, INVALID_VALUES, STRUCTURE_NOT_FOUND } from '../../../constants/errorConditionConstants.mjs';
26
26
  import { TOP_DOWN, LOSER, CONTAINER, PLAY_OFF } from '../../../constants/drawDefinitionConstants.mjs';
27
27
  import { BYE } from '../../../constants/matchUpStatusValues.mjs';
28
28
  import { SUCCESS } from '../../../constants/resultConstants.mjs';