tods-competition-factory 1.8.6 → 1.8.7

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.
@@ -9867,26 +9867,161 @@ function getCompetitionVenues({
9867
9867
  );
9868
9868
  }
9869
9869
 
9870
- function getParticipantEventDetails({
9871
- tournamentRecord,
9872
- participantId
9870
+ function validateSchedulingProfile({
9871
+ tournamentRecords,
9872
+ schedulingProfile
9873
9873
  }) {
9874
- if (!tournamentRecord)
9875
- return { error: MISSING_TOURNAMENT_RECORD };
9876
- if (!participantId)
9877
- return { error: MISSING_PARTICIPANT_ID };
9878
- const relevantParticipantIds = [participantId].concat(
9879
- (tournamentRecord.participants || []).filter(
9880
- (participant) => participant?.participantType && [TEAM$2, PAIR].includes(participant.participantType) && participant.individualParticipantIds?.includes(participantId)
9881
- ).map((participant) => participant.participantId)
9874
+ if (!schedulingProfile)
9875
+ return { valid: true };
9876
+ if (!Array.isArray(schedulingProfile))
9877
+ return { valid: false, error: INVALID_VALUES };
9878
+ const { venueIds, tournamentsMap } = getAllRelevantSchedulingIds({
9879
+ tournamentRecords
9880
+ });
9881
+ let error, info;
9882
+ const isValid = schedulingProfile.every((dateSchedule) => {
9883
+ const { scheduleDate, venues } = dateSchedule;
9884
+ if (!isValidDateString(scheduleDate)) {
9885
+ return false;
9886
+ }
9887
+ return venues.every((venueProfile) => {
9888
+ const { venueId, rounds } = venueProfile;
9889
+ if (typeof venueId !== "string") {
9890
+ info = "venueId should be a string";
9891
+ return false;
9892
+ }
9893
+ if (!Array.isArray(rounds)) {
9894
+ info = "rounds should be an array";
9895
+ return false;
9896
+ }
9897
+ if (!venueIds.includes(venueId)) {
9898
+ error = VENUE_NOT_FOUND;
9899
+ return false;
9900
+ }
9901
+ const validRounds = rounds.every((round) => {
9902
+ if (!round) {
9903
+ info = "empty round";
9904
+ return false;
9905
+ }
9906
+ const {
9907
+ roundSegment,
9908
+ tournamentId,
9909
+ structureId,
9910
+ roundNumber,
9911
+ eventId,
9912
+ drawId
9913
+ } = round;
9914
+ const rounds2 = tournamentsMap?.[tournamentId]?.[eventId]?.[drawId]?.[structureId];
9915
+ const validRound = rounds2?.includes(roundNumber);
9916
+ if (!validRound)
9917
+ info = "Invalid rounds";
9918
+ const { segmentNumber, segmentsCount } = roundSegment || {};
9919
+ const validSegment = !roundSegment || isConvertableInteger(segmentNumber) && isPowerOf2(segmentsCount) && segmentNumber <= segmentsCount;
9920
+ if (!validSegment)
9921
+ info = "Invalid segment";
9922
+ return validRound && validSegment;
9923
+ });
9924
+ return !validRounds ? false : true;
9925
+ });
9926
+ });
9927
+ if (!isValid && !error) {
9928
+ error = INVALID_VALUES;
9929
+ }
9930
+ return { valid: !!isValid, error, info };
9931
+ }
9932
+ function tournamentRelevantSchedulingIds(params) {
9933
+ const { tournamentRecord = {}, tournamentMap = {}, requireCourts } = params;
9934
+ const tournamentIds = [];
9935
+ const structureIds = [];
9936
+ const eventIds = [];
9937
+ const drawIds = [];
9938
+ const venueIds = (tournamentRecord?.venues || []).map(
9939
+ ({ venueId, courts }) => (!requireCourts || courts?.length) && venueId
9882
9940
  );
9883
- const relevantEvents = (tournamentRecord.events || []).filter((event) => {
9884
- const enteredParticipantIds = (event?.entries || []).map(
9885
- (entry) => entry.participantId
9886
- );
9887
- return overlap(enteredParticipantIds, relevantParticipantIds);
9888
- }).map((event) => ({ eventName: event.eventName, eventId: event.eventId }));
9889
- return { eventDetails: relevantEvents };
9941
+ const tournamentId = tournamentRecord?.tournamentId;
9942
+ if (tournamentId) {
9943
+ tournamentIds.push(tournamentId);
9944
+ tournamentMap[tournamentId] = {};
9945
+ const events = tournamentRecord?.events || [];
9946
+ events.forEach((event) => {
9947
+ const eventId = event.eventId;
9948
+ eventIds.push(eventId);
9949
+ tournamentMap[tournamentId][eventId] = {};
9950
+ (event.drawDefinitions || []).forEach((drawDefinition) => {
9951
+ const drawId = drawDefinition.drawId;
9952
+ drawIds.push(drawId);
9953
+ tournamentMap[tournamentId][eventId][drawId] = {};
9954
+ const { structures } = getDrawStructures({ drawDefinition });
9955
+ (structures || []).forEach((structure) => {
9956
+ const structureId = structure.structureId;
9957
+ const { matchUps } = getAllStructureMatchUps({ structure });
9958
+ const { roundMatchUps } = getRoundMatchUps({ matchUps });
9959
+ const rounds = roundMatchUps && Object.keys(roundMatchUps).map(
9960
+ (roundNumber) => parseInt(roundNumber)
9961
+ );
9962
+ tournamentMap[tournamentId][eventId][drawId][structureId] = rounds;
9963
+ structureIds.push(structureId);
9964
+ if (structure.structures?.length) {
9965
+ structure.structures.forEach((itemStructure) => {
9966
+ structureIds.push(itemStructure.structureId);
9967
+ tournamentMap[tournamentId][eventId][drawId][itemStructure.structureId] = rounds;
9968
+ });
9969
+ }
9970
+ });
9971
+ });
9972
+ });
9973
+ }
9974
+ return {
9975
+ tournamentMap,
9976
+ tournamentIds,
9977
+ structureIds,
9978
+ venueIds,
9979
+ eventIds,
9980
+ drawIds
9981
+ };
9982
+ }
9983
+ function getAllRelevantSchedulingIds(params) {
9984
+ const records = params?.tournamentRecords && Object.values(params?.tournamentRecords) || [];
9985
+ const tournamentsMap = {};
9986
+ const { venueIds, eventIds, drawIds, structureIds, tournamentIds } = records.reduce(
9987
+ (aggregator, tournamentRecord) => {
9988
+ const {
9989
+ tournamentIds: tournamentIds2,
9990
+ tournamentMap,
9991
+ structureIds: structureIds2,
9992
+ venueIds: venueIds2,
9993
+ eventIds: eventIds2,
9994
+ drawIds: drawIds2
9995
+ } = tournamentRelevantSchedulingIds({
9996
+ tournamentRecord
9997
+ });
9998
+ venueIds2.forEach((venueId) => {
9999
+ if (!aggregator.venueIds.includes(venueId))
10000
+ aggregator.venueIds.push(venueId);
10001
+ });
10002
+ aggregator.tournamentIds.push(...tournamentIds2);
10003
+ aggregator.structureIds.push(...structureIds2);
10004
+ aggregator.eventIds.push(...eventIds2);
10005
+ aggregator.drawIds.push(...drawIds2);
10006
+ Object.assign(tournamentsMap, tournamentMap);
10007
+ return aggregator;
10008
+ },
10009
+ {
10010
+ tournamentIds: [],
10011
+ structureIds: [],
10012
+ venueIds: [],
10013
+ eventIds: [],
10014
+ drawIds: []
10015
+ }
10016
+ );
10017
+ return {
10018
+ tournamentsMap,
10019
+ tournamentIds,
10020
+ structureIds,
10021
+ venueIds,
10022
+ eventIds,
10023
+ drawIds
10024
+ };
9890
10025
  }
9891
10026
 
9892
10027
  function getTournamentInfo({ tournamentRecord }) {
@@ -9956,449 +10091,502 @@ function getCompetitionDateRange({
9956
10091
  return { startDate, endDate };
9957
10092
  }
9958
10093
 
9959
- function getEliminationDrawSize({
9960
- participantsCount,
9961
- participantCount
9962
- // TODO: to be deprecated
10094
+ function getEventIdsAndDrawIds({
10095
+ tournamentRecords
9963
10096
  }) {
9964
- participantsCount = participantsCount || participantCount;
9965
- if (!participantsCount)
9966
- return { error: INVALID_VALUES };
9967
- const drawSize = nextPowerOf2(participantsCount);
9968
- if (!drawSize)
9969
- return decorateResult({
9970
- result: { error: INVALID_VALUES },
9971
- stack: "getEliminationDrawSize",
9972
- context: { participantsCount }
9973
- });
9974
- return { drawSize };
10097
+ if (!tournamentRecords)
10098
+ return { error: MISSING_TOURNAMENT_RECORDS };
10099
+ const tournamentIds = Object.keys(tournamentRecords);
10100
+ return tournamentIds.reduce(
10101
+ (aggregator, tournamentId) => {
10102
+ aggregator.tournamentIdMap[tournamentId] = [];
10103
+ const tournamentRecord = tournamentRecords[tournamentId];
10104
+ const events = tournamentRecord.events || [];
10105
+ const eventIds = events.map(({ eventId }) => eventId);
10106
+ const drawIds = events.map(
10107
+ (event) => (event.drawDefinitions || []).map(({ drawId }) => drawId)
10108
+ ).flat();
10109
+ aggregator.tournamentIdMap[tournamentId].push(...eventIds, ...drawIds);
10110
+ aggregator.eventIds.push(...eventIds);
10111
+ aggregator.drawIds.push(...drawIds);
10112
+ return aggregator;
10113
+ },
10114
+ { eventIds: [], drawIds: [], tournamentIdMap: {} }
10115
+ );
9975
10116
  }
9976
10117
 
9977
- function getStageEntries({
9978
- selected = true,
9979
- drawDefinition,
9980
- entryStatuses,
9981
- drawId,
9982
- event,
9983
- stage
10118
+ function getSchedulingProfile({
10119
+ tournamentRecords
9984
10120
  }) {
9985
- let entries = event.entries ?? [];
9986
- if (drawId) {
9987
- const { flightProfile } = getFlightProfile({ event });
9988
- const flight = flightProfile?.flights?.find(
9989
- (flight2) => flight2.drawId === drawId
9990
- );
9991
- if (flight) {
9992
- entries = flight.drawEntries;
9993
- } else if (drawDefinition.entries) {
9994
- entries = drawDefinition?.entries;
10121
+ if (typeof tournamentRecords !== "object" || !Object.keys(tournamentRecords).length)
10122
+ return { error: MISSING_TOURNAMENT_RECORDS };
10123
+ const { extension } = findExtension$1({
10124
+ name: SCHEDULING_PROFILE,
10125
+ tournamentRecords
10126
+ });
10127
+ let schedulingProfile = extension?.value || [];
10128
+ if (schedulingProfile.length) {
10129
+ const { venueIds } = getCompetitionVenues({
10130
+ requireCourts: true,
10131
+ tournamentRecords
10132
+ });
10133
+ const { eventIds, drawIds } = getEventIdsAndDrawIds({ tournamentRecords });
10134
+ const { updatedSchedulingProfile, modifications, issues } = getUpdatedSchedulingProfile({
10135
+ schedulingProfile,
10136
+ venueIds,
10137
+ eventIds,
10138
+ drawIds
10139
+ });
10140
+ if (modifications) {
10141
+ schedulingProfile = updatedSchedulingProfile;
10142
+ const result = setSchedulingProfile({
10143
+ tournamentRecords,
10144
+ schedulingProfile
10145
+ });
10146
+ if (result.error)
10147
+ return result;
10148
+ return { schedulingProfile, modifications, issues };
9995
10149
  }
9996
10150
  }
9997
- const stageEntries = entries.filter(
9998
- (entry) => (!entryStatuses?.length || !entry.entryStatus || entryStatuses.includes(entry.entryStatus)) && (!stage || !entry.entryStage || entry.entryStage === stage) && (!selected || entry.entryStatus && STRUCTURE_SELECTED_STATUSES.includes(entry.entryStatus))
9999
- );
10000
- return { entries, stageEntries };
10151
+ return { schedulingProfile, modifications: 0 };
10001
10152
  }
10002
-
10003
- function getSeedsCount(params) {
10004
- let {
10005
- drawSizeProgression = false,
10006
- policyDefinitions,
10007
- drawSize
10008
- } = params || {};
10009
- const {
10010
- requireParticipantCount = true,
10011
- tournamentRecord,
10012
- drawDefinition,
10013
- event
10014
- } = params || {};
10015
- const stack = "getSeedsCount";
10016
- const participantsCount = params?.participantsCount || params?.participantCount;
10017
- if (!policyDefinitions) {
10018
- const result = getPolicyDefinitions({
10019
- tournamentRecord,
10020
- drawDefinition,
10021
- event
10022
- });
10023
- if (result.error)
10024
- return decorateResult({ result, stack });
10025
- policyDefinitions = result.policyDefinitions;
10026
- }
10027
- const validParticpantCount = isConvertableInteger(participantsCount);
10028
- if (participantsCount && !validParticpantCount)
10029
- return decorateResult({
10030
- result: { error: INVALID_VALUES },
10031
- context: { participantsCount },
10032
- stack
10033
- });
10034
- if (requireParticipantCount && !validParticpantCount)
10035
- return decorateResult({
10036
- result: { error: MISSING_PARTICIPANT_COUNT },
10037
- stack
10038
- });
10039
- if (isNaN(drawSize)) {
10040
- if (participantsCount) {
10041
- ({ drawSize } = getEliminationDrawSize({
10042
- participantsCount
10043
- }));
10044
- } else {
10045
- return decorateResult({ result: { error: MISSING_DRAW_SIZE }, stack });
10046
- }
10047
- }
10048
- const consideredParticipantCount = requireParticipantCount && participantsCount || drawSize;
10049
- if (consideredParticipantCount > drawSize)
10050
- return { error: PARTICIPANT_COUNT_EXCEEDS_DRAW_SIZE };
10051
- const policy = policyDefinitions[POLICY_TYPE_SEEDING];
10052
- if (!policy)
10053
- return { error: INVALID_POLICY_DEFINITION };
10054
- const seedsCountThresholds = policy.seedsCountThresholds;
10055
- if (!seedsCountThresholds)
10056
- return { error: MISSING_SEEDCOUNT_THRESHOLDS };
10057
- if (policy.drawSizeProgression !== void 0)
10058
- drawSizeProgression = policy.drawSizeProgression;
10059
- const relevantThresholds = seedsCountThresholds.filter((threshold) => {
10060
- return drawSizeProgression ? threshold.drawSize <= drawSize : drawSize === threshold.drawSize;
10153
+ function setSchedulingProfile({ tournamentRecords, schedulingProfile }) {
10154
+ const profileValidity = validateSchedulingProfile({
10155
+ tournamentRecords,
10156
+ schedulingProfile
10061
10157
  });
10062
- const seedsCount = relevantThresholds.reduce((seedsCount2, threshold) => {
10063
- return participantsCount >= threshold.minimumParticipantCount ? threshold.seedsCount : seedsCount2;
10064
- }, 0);
10065
- return { seedsCount };
10158
+ if (profileValidity.error)
10159
+ return profileValidity;
10160
+ if (!schedulingProfile)
10161
+ return removeExtension({ tournamentRecords, name: SCHEDULING_PROFILE });
10162
+ const extension = {
10163
+ name: SCHEDULING_PROFILE,
10164
+ value: schedulingProfile
10165
+ };
10166
+ return addExtension({ tournamentRecords, extension });
10066
10167
  }
10067
-
10068
- function getEntriesAndSeedsCount({
10069
- policyDefinitions,
10070
- drawDefinition,
10071
- drawSize,
10072
- drawId,
10073
- event,
10074
- stage
10168
+ function getUpdatedSchedulingProfile({
10169
+ schedulingProfile,
10170
+ venueIds,
10171
+ eventIds,
10172
+ drawIds
10075
10173
  }) {
10076
- if (!event)
10077
- return { error: MISSING_EVENT };
10078
- const { entries, stageEntries } = getStageEntries({
10079
- drawDefinition,
10080
- drawId,
10081
- stage,
10082
- event
10083
- });
10084
- const participantsCount = stageEntries.length;
10085
- const { drawSize: eliminationDrawSize } = getEliminationDrawSize({
10086
- participantsCount
10087
- });
10088
- const result = getSeedsCount({
10089
- drawSize: drawSize ?? eliminationDrawSize,
10090
- participantsCount,
10091
- policyDefinitions
10092
- });
10093
- if (result.error)
10094
- return decorateResult({ result, stack: "getEntriesAndSeedsCount" });
10095
- const { seedsCount } = result;
10096
- return { entries, seedsCount, stageEntries };
10097
- }
10098
-
10099
- function getMatchUpDailyLimits$1({ tournamentRecord }) {
10100
- if (!tournamentRecord)
10101
- return { error: MISSING_TOURNAMENT_RECORD };
10102
- const { policy } = findPolicy({
10103
- policyType: POLICY_TYPE_SCHEDULING,
10104
- tournamentRecord
10105
- });
10106
- const { extension } = findTournamentExtension({
10107
- name: SCHEDULE_LIMITS,
10108
- tournamentRecord
10109
- });
10110
- const tournamentDailyLimits = extension?.value?.dailyLimits;
10111
- const policyDailyLimits = policy?.defaultDailyLimits;
10112
- return { matchUpDailyLimits: tournamentDailyLimits || policyDailyLimits };
10174
+ const issues = [];
10175
+ const updatedSchedulingProfile = schedulingProfile?.map((dateSchedulingProfile) => {
10176
+ const date = extractDate(dateSchedulingProfile?.scheduleDate);
10177
+ if (!date) {
10178
+ issues.push(`Invalid date: ${dateSchedulingProfile?.scheduledDate}`);
10179
+ return;
10180
+ }
10181
+ const venues = (dateSchedulingProfile?.venues || []).map((venue) => {
10182
+ const { rounds, venueId } = venue;
10183
+ const venueExists = venueIds.includes(venueId);
10184
+ if (!venueExists) {
10185
+ issues.push(`Missing venueId: ${venueId}`);
10186
+ return;
10187
+ }
10188
+ const filteredRounds = rounds.filter((round) => {
10189
+ const validEventIdAndDrawId = eventIds.includes(round.eventId) && drawIds.includes(round.drawId);
10190
+ if (!validEventIdAndDrawId)
10191
+ issues.push(
10192
+ `Invalid eventId: ${round.eventId} or drawId: ${round.drawId}`
10193
+ );
10194
+ return validEventIdAndDrawId;
10195
+ });
10196
+ if (!filteredRounds.length)
10197
+ return;
10198
+ return { venueId, rounds: filteredRounds };
10199
+ }).filter(Boolean);
10200
+ return venues.length && date && { ...dateSchedulingProfile, venues };
10201
+ }).filter(Boolean);
10202
+ const modifications = issues.length;
10203
+ return { updatedSchedulingProfile, modifications, issues };
10113
10204
  }
10114
10205
 
10115
- function getMatchUpDailyLimits({
10206
+ function findMatchUpFormatTiming({
10207
+ defaultRecoveryMinutes = 0,
10208
+ defaultAverageMinutes,
10116
10209
  tournamentRecords,
10117
- tournamentId
10210
+ matchUpFormat,
10211
+ categoryName,
10212
+ categoryType,
10213
+ tournamentId,
10214
+ eventType,
10215
+ eventId
10118
10216
  }) {
10119
- if (typeof tournamentRecords !== "object" || !Object.keys(tournamentRecords).length)
10120
- return { error: MISSING_TOURNAMENT_RECORDS };
10217
+ if (!isValid(matchUpFormat))
10218
+ return { error: UNRECOGNIZED_MATCHUP_FORMAT };
10121
10219
  const tournamentIds = Object.keys(tournamentRecords).filter(
10122
10220
  (currentTournamentId) => !tournamentId || currentTournamentId === tournamentId
10123
10221
  );
10124
- let dailyLimits;
10125
- tournamentIds.forEach((tournamentId2) => {
10126
- const tournamentRecord = tournamentRecords[tournamentId2];
10127
- const { matchUpDailyLimits } = getMatchUpDailyLimits$1({
10128
- tournamentRecord
10222
+ let timing;
10223
+ tournamentIds.forEach((currentTournamentId) => {
10224
+ if (timing)
10225
+ return;
10226
+ const tournamentRecord = tournamentRecords[currentTournamentId];
10227
+ const event = eventId ? findEvent({ tournamentRecord, eventId })?.event : void 0;
10228
+ timing = getMatchUpFormatTiming({
10229
+ tournamentRecord,
10230
+ matchUpFormat,
10231
+ categoryName,
10232
+ categoryType,
10233
+ eventType,
10234
+ event
10129
10235
  });
10130
- dailyLimits = matchUpDailyLimits;
10236
+ return timing?.averageMinutes || timing?.recoveryMinutes;
10131
10237
  });
10132
- return { matchUpDailyLimits: dailyLimits };
10238
+ return {
10239
+ recoveryMinutes: timing?.recoveryMinutes || defaultRecoveryMinutes,
10240
+ averageMinutes: timing?.averageMinutes || defaultAverageMinutes,
10241
+ typeChangeRecoveryMinutes: timing?.typeChangeRecoveryMinutes || timing?.recoveryMinutes || defaultRecoveryMinutes
10242
+ };
10133
10243
  }
10134
10244
 
10135
- function validateSchedulingProfile({
10136
- tournamentRecords,
10137
- schedulingProfile
10138
- }) {
10139
- if (!schedulingProfile)
10140
- return { valid: true };
10141
- if (!Array.isArray(schedulingProfile))
10142
- return { valid: false, error: INVALID_VALUES };
10143
- const { venueIds, tournamentsMap } = getAllRelevantSchedulingIds({
10144
- tournamentRecords
10245
+ function getRoundId(obj) {
10246
+ const {
10247
+ containerStructureId,
10248
+ roundSegment,
10249
+ isRoundRobin,
10250
+ tournamentId,
10251
+ roundNumber,
10252
+ structureId,
10253
+ eventId,
10254
+ drawId
10255
+ } = obj;
10256
+ const relevantStructureId = isRoundRobin ? containerStructureId : structureId;
10257
+ const id = [
10258
+ tournamentId,
10259
+ // 1
10260
+ eventId,
10261
+ // 2
10262
+ drawId,
10263
+ // 3
10264
+ relevantStructureId,
10265
+ // 4
10266
+ roundNumber
10267
+ // 5
10268
+ ].join("|");
10269
+ return definedAttributes({
10270
+ structureId: relevantStructureId,
10271
+ roundSegment,
10272
+ tournamentId,
10273
+ roundNumber,
10274
+ eventId,
10275
+ drawId,
10276
+ id
10145
10277
  });
10146
- let error, info;
10147
- const isValid = schedulingProfile.every((dateSchedule) => {
10148
- const { scheduleDate, venues } = dateSchedule;
10149
- if (!isValidDateString(scheduleDate)) {
10150
- return false;
10151
- }
10152
- return venues.every((venueProfile) => {
10153
- const { venueId, rounds } = venueProfile;
10154
- if (typeof venueId !== "string") {
10155
- info = "venueId should be a string";
10156
- return false;
10157
- }
10158
- if (!Array.isArray(rounds)) {
10159
- info = "rounds should be an array";
10160
- return false;
10161
- }
10162
- if (!venueIds.includes(venueId)) {
10163
- error = VENUE_NOT_FOUND;
10164
- return false;
10165
- }
10166
- const validRounds = rounds.every((round) => {
10167
- if (!round) {
10168
- info = "empty round";
10169
- return false;
10170
- }
10171
- const {
10172
- roundSegment,
10173
- tournamentId,
10174
- structureId,
10175
- roundNumber,
10176
- eventId,
10177
- drawId
10178
- } = round;
10179
- const rounds2 = tournamentsMap?.[tournamentId]?.[eventId]?.[drawId]?.[structureId];
10180
- const validRound = rounds2?.includes(roundNumber);
10181
- if (!validRound)
10182
- info = "Invalid rounds";
10183
- const { segmentNumber, segmentsCount } = roundSegment || {};
10184
- const validSegment = !roundSegment || isConvertableInteger(segmentNumber) && isPowerOf2(segmentsCount) && segmentNumber <= segmentsCount;
10185
- if (!validSegment)
10186
- info = "Invalid segment";
10187
- return validRound && validSegment;
10188
- });
10189
- return !validRounds ? false : true;
10190
- });
10191
- });
10192
- if (!isValid && !error) {
10193
- error = INVALID_VALUES;
10194
- }
10195
- return { valid: !!isValid, error, info };
10196
10278
  }
10197
- function tournamentRelevantSchedulingIds(params) {
10198
- const { tournamentRecord = {}, tournamentMap = {}, requireCourts } = params;
10199
- const tournamentIds = [];
10200
- const structureIds = [];
10201
- const eventIds = [];
10202
- const drawIds = [];
10203
- const venueIds = (tournamentRecord?.venues || []).map(
10204
- ({ venueId, courts }) => (!requireCourts || courts?.length) && venueId
10279
+ function getRoundTiming({ round, matchUps, events, tournamentRecords }) {
10280
+ const event = events.find((event2) => event2.eventId === round.eventId);
10281
+ const { eventType, category, categoryType } = event || {};
10282
+ const { categoryName, ageCategoryCode } = category || {};
10283
+ const formatCounts = instanceCount(
10284
+ matchUps.map(({ matchUpFormat }) => matchUpFormat)
10205
10285
  );
10206
- const tournamentId = tournamentRecord?.tournamentId;
10207
- if (tournamentId) {
10208
- tournamentIds.push(tournamentId);
10209
- tournamentMap[tournamentId] = {};
10210
- const events = tournamentRecord?.events || [];
10211
- events.forEach((event) => {
10212
- const eventId = event.eventId;
10213
- eventIds.push(eventId);
10214
- tournamentMap[tournamentId][eventId] = {};
10215
- (event.drawDefinitions || []).forEach((drawDefinition) => {
10216
- const drawId = drawDefinition.drawId;
10217
- drawIds.push(drawId);
10218
- tournamentMap[tournamentId][eventId][drawId] = {};
10219
- const { structures } = getDrawStructures({ drawDefinition });
10220
- (structures || []).forEach((structure) => {
10221
- const structureId = structure.structureId;
10222
- const { matchUps } = getAllStructureMatchUps({ structure });
10223
- const { roundMatchUps } = getRoundMatchUps({ matchUps });
10224
- const rounds = roundMatchUps && Object.keys(roundMatchUps).map(
10225
- (roundNumber) => parseInt(roundNumber)
10226
- );
10227
- tournamentMap[tournamentId][eventId][drawId][structureId] = rounds;
10228
- structureIds.push(structureId);
10229
- if (structure.structures?.length) {
10230
- structure.structures.forEach((itemStructure) => {
10231
- structureIds.push(itemStructure.structureId);
10232
- tournamentMap[tournamentId][eventId][drawId][itemStructure.structureId] = rounds;
10233
- });
10234
- }
10235
- });
10236
- });
10286
+ let roundMinutes = 0;
10287
+ Object.keys(formatCounts).forEach((matchUpFormat) => {
10288
+ const formatCount = formatCounts[matchUpFormat];
10289
+ const result = findMatchUpFormatTiming({
10290
+ categoryName: categoryName || ageCategoryCode,
10291
+ tournamentId: round.tournamentId,
10292
+ eventId: round.eventId,
10293
+ tournamentRecords,
10294
+ matchUpFormat,
10295
+ categoryType,
10296
+ eventType
10237
10297
  });
10238
- }
10239
- return {
10240
- tournamentMap,
10241
- tournamentIds,
10242
- structureIds,
10243
- venueIds,
10244
- eventIds,
10245
- drawIds
10246
- };
10298
+ if (result.error)
10299
+ return result;
10300
+ const formatMinutes = result.averageMinutes * formatCount;
10301
+ if (!isNaN(roundMinutes))
10302
+ roundMinutes += formatMinutes;
10303
+ return void 0;
10304
+ });
10305
+ return { roundMinutes };
10247
10306
  }
10248
- function getAllRelevantSchedulingIds(params) {
10249
- const records = params?.tournamentRecords && Object.values(params?.tournamentRecords) || [];
10250
- const tournamentsMap = {};
10251
- const { venueIds, eventIds, drawIds, structureIds, tournamentIds } = records.reduce(
10252
- (aggregator, tournamentRecord) => {
10253
- const {
10254
- tournamentIds: tournamentIds2,
10255
- tournamentMap,
10256
- structureIds: structureIds2,
10257
- venueIds: venueIds2,
10258
- eventIds: eventIds2,
10259
- drawIds: drawIds2
10260
- } = tournamentRelevantSchedulingIds({
10261
- tournamentRecord
10262
- });
10263
- venueIds2.forEach((venueId) => {
10264
- if (!aggregator.venueIds.includes(venueId))
10265
- aggregator.venueIds.push(venueId);
10266
- });
10267
- aggregator.tournamentIds.push(...tournamentIds2);
10268
- aggregator.structureIds.push(...structureIds2);
10269
- aggregator.eventIds.push(...eventIds2);
10270
- aggregator.drawIds.push(...drawIds2);
10271
- Object.assign(tournamentsMap, tournamentMap);
10272
- return aggregator;
10307
+ function getFinishingPositionDetails(matchUps) {
10308
+ return (matchUps || []).reduce(
10309
+ (foo, matchUp) => {
10310
+ const sum = (matchUp.finishingPositionRange?.winner || []).reduce(
10311
+ (a, b) => a + b,
10312
+ 0
10313
+ );
10314
+ const winnerFinishingPositionRange = (matchUp.finishingPositionRange?.winner || []).join("-") || "";
10315
+ return !foo.minFinishingSum || sum < foo.minFinishingSum ? { minFinishingSum: sum, winnerFinishingPositionRange } : foo;
10273
10316
  },
10274
- {
10275
- tournamentIds: [],
10276
- structureIds: [],
10277
- venueIds: [],
10278
- eventIds: [],
10279
- drawIds: []
10280
- }
10317
+ { minFinishingSum: 0, winnerFinishingPositionRange: "" }
10281
10318
  );
10319
+ }
10320
+ function getRoundProfile(matchUps) {
10321
+ const matchUpsCount = matchUps.length;
10322
+ const byeCount = matchUps.filter(({ sides }) => sides?.some(({ bye }) => bye)).length || 0;
10323
+ const completedCount = matchUps.filter(
10324
+ ({ winningSide, matchUpStatus }) => winningSide || completedMatchUpStatuses.includes(matchUpStatus)
10325
+ ).length || 0;
10326
+ const scheduledCount = matchUps.filter(
10327
+ ({ schedule }) => schedule?.scheduledDate && schedule?.scheduledTime
10328
+ ).length || 0;
10329
+ const consideredCount = matchUpsCount - byeCount;
10330
+ const isComplete = consideredCount === completedCount;
10331
+ const unscheduledCount = consideredCount - scheduledCount;
10332
+ const incompleteCount = consideredCount - scheduledCount;
10333
+ const isScheduled = consideredCount === scheduledCount;
10282
10334
  return {
10283
- tournamentsMap,
10284
- tournamentIds,
10285
- structureIds,
10286
- venueIds,
10287
- eventIds,
10288
- drawIds
10335
+ unscheduledCount,
10336
+ incompleteCount,
10337
+ scheduledCount,
10338
+ completedCount,
10339
+ matchUpsCount,
10340
+ isScheduled,
10341
+ isComplete,
10342
+ byeCount
10289
10343
  };
10290
10344
  }
10291
10345
 
10292
- function getEventIdsAndDrawIds({
10293
- tournamentRecords
10346
+ function getProfileRounds({
10347
+ tournamentRecords,
10348
+ schedulingProfile,
10349
+ tournamentRecord,
10350
+ withRoundId
10294
10351
  }) {
10295
- if (!tournamentRecords)
10296
- return { error: MISSING_TOURNAMENT_RECORDS };
10297
- const tournamentIds = Object.keys(tournamentRecords);
10298
- return tournamentIds.reduce(
10299
- (aggregator, tournamentId) => {
10300
- aggregator.tournamentIdMap[tournamentId] = [];
10301
- const tournamentRecord = tournamentRecords[tournamentId];
10302
- const events = tournamentRecord.events || [];
10303
- const eventIds = events.map(({ eventId }) => eventId);
10304
- const drawIds = events.map(
10305
- (event) => (event.drawDefinitions || []).map(({ drawId }) => drawId)
10306
- ).flat();
10307
- aggregator.tournamentIdMap[tournamentId].push(...eventIds, ...drawIds);
10308
- aggregator.eventIds.push(...eventIds);
10309
- aggregator.drawIds.push(...drawIds);
10310
- return aggregator;
10311
- },
10312
- { eventIds: [], drawIds: [], tournamentIdMap: {} }
10313
- );
10352
+ if (tournamentRecord && !tournamentRecords) {
10353
+ if (typeof tournamentRecord !== "object") {
10354
+ return { error: INVALID_TOURNAMENT_RECORD };
10355
+ } else {
10356
+ tournamentRecords = { [tournamentRecord.tournamentId]: tournamentRecord };
10357
+ }
10358
+ }
10359
+ if (schedulingProfile) {
10360
+ const profileValidity = validateSchedulingProfile({
10361
+ tournamentRecords,
10362
+ schedulingProfile
10363
+ });
10364
+ if (profileValidity.error)
10365
+ return profileValidity;
10366
+ }
10367
+ if (!schedulingProfile && tournamentRecords) {
10368
+ const result = getSchedulingProfile({ tournamentRecords });
10369
+ if (result.error)
10370
+ return result;
10371
+ schedulingProfile = result.schedulingProfile;
10372
+ }
10373
+ if (!schedulingProfile)
10374
+ return { error: NOT_FOUND };
10375
+ const segmentedRounds = {};
10376
+ const profileRounds = schedulingProfile.map(
10377
+ ({ venues, scheduleDate }) => venues.map(
10378
+ ({ rounds }) => rounds.map((round) => {
10379
+ const roundRef = getRoundId(round);
10380
+ if (roundRef.roundSegment?.segmentsCount) {
10381
+ segmentedRounds[roundRef.id] = roundRef.roundSegment.segmentsCount;
10382
+ }
10383
+ return definedAttributes({
10384
+ id: withRoundId ? roundRef.id : void 0,
10385
+ scheduleDate,
10386
+ ...roundRef
10387
+ });
10388
+ })
10389
+ )
10390
+ ).flat(Infinity);
10391
+ return { profileRounds, segmentedRounds };
10314
10392
  }
10315
10393
 
10316
- function getSchedulingProfile({
10317
- tournamentRecords
10394
+ function getParticipantEventDetails({
10395
+ tournamentRecord,
10396
+ participantId
10318
10397
  }) {
10319
- if (typeof tournamentRecords !== "object" || !Object.keys(tournamentRecords).length)
10320
- return { error: MISSING_TOURNAMENT_RECORDS };
10321
- const { extension } = findExtension$1({
10322
- name: SCHEDULING_PROFILE,
10323
- tournamentRecords
10324
- });
10325
- let schedulingProfile = extension?.value || [];
10326
- if (schedulingProfile.length) {
10327
- const { venueIds } = getCompetitionVenues({
10328
- requireCourts: true,
10329
- tournamentRecords
10398
+ if (!tournamentRecord)
10399
+ return { error: MISSING_TOURNAMENT_RECORD };
10400
+ if (!participantId)
10401
+ return { error: MISSING_PARTICIPANT_ID };
10402
+ const relevantParticipantIds = [participantId].concat(
10403
+ (tournamentRecord.participants || []).filter(
10404
+ (participant) => participant?.participantType && [TEAM$2, PAIR].includes(participant.participantType) && participant.individualParticipantIds?.includes(participantId)
10405
+ ).map((participant) => participant.participantId)
10406
+ );
10407
+ const relevantEvents = (tournamentRecord.events || []).filter((event) => {
10408
+ const enteredParticipantIds = (event?.entries || []).map(
10409
+ (entry) => entry.participantId
10410
+ );
10411
+ return overlap(enteredParticipantIds, relevantParticipantIds);
10412
+ }).map((event) => ({ eventName: event.eventName, eventId: event.eventId }));
10413
+ return { eventDetails: relevantEvents };
10414
+ }
10415
+
10416
+ function getEliminationDrawSize({
10417
+ participantsCount,
10418
+ participantCount
10419
+ // TODO: to be deprecated
10420
+ }) {
10421
+ participantsCount = participantsCount || participantCount;
10422
+ if (!participantsCount)
10423
+ return { error: INVALID_VALUES };
10424
+ const drawSize = nextPowerOf2(participantsCount);
10425
+ if (!drawSize)
10426
+ return decorateResult({
10427
+ result: { error: INVALID_VALUES },
10428
+ stack: "getEliminationDrawSize",
10429
+ context: { participantsCount }
10330
10430
  });
10331
- const { eventIds, drawIds } = getEventIdsAndDrawIds({ tournamentRecords });
10332
- const { updatedSchedulingProfile, modifications, issues } = getUpdatedSchedulingProfile({
10333
- schedulingProfile,
10334
- venueIds,
10335
- eventIds,
10336
- drawIds
10431
+ return { drawSize };
10432
+ }
10433
+
10434
+ function getStageEntries({
10435
+ selected = true,
10436
+ drawDefinition,
10437
+ entryStatuses,
10438
+ drawId,
10439
+ event,
10440
+ stage
10441
+ }) {
10442
+ let entries = event.entries ?? [];
10443
+ if (drawId) {
10444
+ const { flightProfile } = getFlightProfile({ event });
10445
+ const flight = flightProfile?.flights?.find(
10446
+ (flight2) => flight2.drawId === drawId
10447
+ );
10448
+ if (flight) {
10449
+ entries = flight.drawEntries;
10450
+ } else if (drawDefinition.entries) {
10451
+ entries = drawDefinition?.entries;
10452
+ }
10453
+ }
10454
+ const stageEntries = entries.filter(
10455
+ (entry) => (!entryStatuses?.length || !entry.entryStatus || entryStatuses.includes(entry.entryStatus)) && (!stage || !entry.entryStage || entry.entryStage === stage) && (!selected || entry.entryStatus && STRUCTURE_SELECTED_STATUSES.includes(entry.entryStatus))
10456
+ );
10457
+ return { entries, stageEntries };
10458
+ }
10459
+
10460
+ function getSeedsCount(params) {
10461
+ let {
10462
+ drawSizeProgression = false,
10463
+ policyDefinitions,
10464
+ drawSize
10465
+ } = params || {};
10466
+ const {
10467
+ requireParticipantCount = true,
10468
+ tournamentRecord,
10469
+ drawDefinition,
10470
+ event
10471
+ } = params || {};
10472
+ const stack = "getSeedsCount";
10473
+ const participantsCount = params?.participantsCount || params?.participantCount;
10474
+ if (!policyDefinitions) {
10475
+ const result = getPolicyDefinitions({
10476
+ tournamentRecord,
10477
+ drawDefinition,
10478
+ event
10337
10479
  });
10338
- if (modifications) {
10339
- schedulingProfile = updatedSchedulingProfile;
10340
- const result = setSchedulingProfile({
10341
- tournamentRecords,
10342
- schedulingProfile
10343
- });
10344
- if (result.error)
10345
- return result;
10346
- return { schedulingProfile, modifications, issues };
10480
+ if (result.error)
10481
+ return decorateResult({ result, stack });
10482
+ policyDefinitions = result.policyDefinitions;
10483
+ }
10484
+ const validParticpantCount = isConvertableInteger(participantsCount);
10485
+ if (participantsCount && !validParticpantCount)
10486
+ return decorateResult({
10487
+ result: { error: INVALID_VALUES },
10488
+ context: { participantsCount },
10489
+ stack
10490
+ });
10491
+ if (requireParticipantCount && !validParticpantCount)
10492
+ return decorateResult({
10493
+ result: { error: MISSING_PARTICIPANT_COUNT },
10494
+ stack
10495
+ });
10496
+ if (isNaN(drawSize)) {
10497
+ if (participantsCount) {
10498
+ ({ drawSize } = getEliminationDrawSize({
10499
+ participantsCount
10500
+ }));
10501
+ } else {
10502
+ return decorateResult({ result: { error: MISSING_DRAW_SIZE }, stack });
10347
10503
  }
10348
10504
  }
10349
- return { schedulingProfile, modifications: 0 };
10505
+ const consideredParticipantCount = requireParticipantCount && participantsCount || drawSize;
10506
+ if (consideredParticipantCount > drawSize)
10507
+ return { error: PARTICIPANT_COUNT_EXCEEDS_DRAW_SIZE };
10508
+ const policy = policyDefinitions[POLICY_TYPE_SEEDING];
10509
+ if (!policy)
10510
+ return { error: INVALID_POLICY_DEFINITION };
10511
+ const seedsCountThresholds = policy.seedsCountThresholds;
10512
+ if (!seedsCountThresholds)
10513
+ return { error: MISSING_SEEDCOUNT_THRESHOLDS };
10514
+ if (policy.drawSizeProgression !== void 0)
10515
+ drawSizeProgression = policy.drawSizeProgression;
10516
+ const relevantThresholds = seedsCountThresholds.filter((threshold) => {
10517
+ return drawSizeProgression ? threshold.drawSize <= drawSize : drawSize === threshold.drawSize;
10518
+ });
10519
+ const seedsCount = relevantThresholds.reduce((seedsCount2, threshold) => {
10520
+ return participantsCount >= threshold.minimumParticipantCount ? threshold.seedsCount : seedsCount2;
10521
+ }, 0);
10522
+ return { seedsCount };
10350
10523
  }
10351
- function setSchedulingProfile({ tournamentRecords, schedulingProfile }) {
10352
- const profileValidity = validateSchedulingProfile({
10353
- tournamentRecords,
10354
- schedulingProfile
10524
+
10525
+ function getEntriesAndSeedsCount({
10526
+ policyDefinitions,
10527
+ drawDefinition,
10528
+ drawSize,
10529
+ drawId,
10530
+ event,
10531
+ stage
10532
+ }) {
10533
+ if (!event)
10534
+ return { error: MISSING_EVENT };
10535
+ const { entries, stageEntries } = getStageEntries({
10536
+ drawDefinition,
10537
+ drawId,
10538
+ stage,
10539
+ event
10355
10540
  });
10356
- if (profileValidity.error)
10357
- return profileValidity;
10358
- if (!schedulingProfile)
10359
- return removeExtension({ tournamentRecords, name: SCHEDULING_PROFILE });
10360
- const extension = {
10361
- name: SCHEDULING_PROFILE,
10362
- value: schedulingProfile
10363
- };
10364
- return addExtension({ tournamentRecords, extension });
10541
+ const participantsCount = stageEntries.length;
10542
+ const { drawSize: eliminationDrawSize } = getEliminationDrawSize({
10543
+ participantsCount
10544
+ });
10545
+ const result = getSeedsCount({
10546
+ drawSize: drawSize ?? eliminationDrawSize,
10547
+ participantsCount,
10548
+ policyDefinitions
10549
+ });
10550
+ if (result.error)
10551
+ return decorateResult({ result, stack: "getEntriesAndSeedsCount" });
10552
+ const { seedsCount } = result;
10553
+ return { entries, seedsCount, stageEntries };
10365
10554
  }
10366
- function getUpdatedSchedulingProfile({
10367
- schedulingProfile,
10368
- venueIds,
10369
- eventIds,
10370
- drawIds
10555
+
10556
+ function getMatchUpDailyLimits$1({ tournamentRecord }) {
10557
+ if (!tournamentRecord)
10558
+ return { error: MISSING_TOURNAMENT_RECORD };
10559
+ const { policy } = findPolicy({
10560
+ policyType: POLICY_TYPE_SCHEDULING,
10561
+ tournamentRecord
10562
+ });
10563
+ const { extension } = findTournamentExtension({
10564
+ name: SCHEDULE_LIMITS,
10565
+ tournamentRecord
10566
+ });
10567
+ const tournamentDailyLimits = extension?.value?.dailyLimits;
10568
+ const policyDailyLimits = policy?.defaultDailyLimits;
10569
+ return { matchUpDailyLimits: tournamentDailyLimits || policyDailyLimits };
10570
+ }
10571
+
10572
+ function getMatchUpDailyLimits({
10573
+ tournamentRecords,
10574
+ tournamentId
10371
10575
  }) {
10372
- const issues = [];
10373
- const updatedSchedulingProfile = schedulingProfile?.map((dateSchedulingProfile) => {
10374
- const date = extractDate(dateSchedulingProfile?.scheduleDate);
10375
- if (!date) {
10376
- issues.push(`Invalid date: ${dateSchedulingProfile?.scheduledDate}`);
10377
- return;
10378
- }
10379
- const venues = (dateSchedulingProfile?.venues || []).map((venue) => {
10380
- const { rounds, venueId } = venue;
10381
- const venueExists = venueIds.includes(venueId);
10382
- if (!venueExists) {
10383
- issues.push(`Missing venueId: ${venueId}`);
10384
- return;
10385
- }
10386
- const filteredRounds = rounds.filter((round) => {
10387
- const validEventIdAndDrawId = eventIds.includes(round.eventId) && drawIds.includes(round.drawId);
10388
- if (!validEventIdAndDrawId)
10389
- issues.push(
10390
- `Invalid eventId: ${round.eventId} or drawId: ${round.drawId}`
10391
- );
10392
- return validEventIdAndDrawId;
10393
- });
10394
- if (!filteredRounds.length)
10395
- return;
10396
- return { venueId, rounds: filteredRounds };
10397
- }).filter(Boolean);
10398
- return venues.length && date && { ...dateSchedulingProfile, venues };
10399
- }).filter(Boolean);
10400
- const modifications = issues.length;
10401
- return { updatedSchedulingProfile, modifications, issues };
10576
+ if (typeof tournamentRecords !== "object" || !Object.keys(tournamentRecords).length)
10577
+ return { error: MISSING_TOURNAMENT_RECORDS };
10578
+ const tournamentIds = Object.keys(tournamentRecords).filter(
10579
+ (currentTournamentId) => !tournamentId || currentTournamentId === tournamentId
10580
+ );
10581
+ let dailyLimits;
10582
+ tournamentIds.forEach((tournamentId2) => {
10583
+ const tournamentRecord = tournamentRecords[tournamentId2];
10584
+ const { matchUpDailyLimits } = getMatchUpDailyLimits$1({
10585
+ tournamentRecord
10586
+ });
10587
+ dailyLimits = matchUpDailyLimits;
10588
+ });
10589
+ return { matchUpDailyLimits: dailyLimits };
10402
10590
  }
10403
10591
 
10404
10592
  function scheduledSortedMatchUps({
@@ -10734,9 +10922,203 @@ function getCompetitionPublishedDrawIds({
10734
10922
  return { drawIds };
10735
10923
  }
10736
10924
 
10737
- function filterParticipants({
10738
- participantFilters = {},
10739
- tournamentRecord,
10925
+ const { stageOrder } = drawDefinitionConstants;
10926
+ function roundSort(a, b) {
10927
+ return a.eventName.localeCompare(b.eventName) || a.eventId.localeCompare(b.eventId) || (stageOrder[a?.stage] || 0) - (stageOrder[b?.stage] || 0) || b.matchUpsCount - a.matchUpsCount || `${a.stageSequence}-${a.roundNumber}-${a.minFinishingSum}`.localeCompare(
10928
+ `${b.stageSequence}-${b.roundNumber}-${b.minFinishingSum}`
10929
+ );
10930
+ }
10931
+
10932
+ function getRounds({
10933
+ excludeScheduleDateProfileRounds,
10934
+ excludeScheduledRounds,
10935
+ excludeCompletedRounds,
10936
+ inContextMatchUps,
10937
+ tournamentRecords,
10938
+ schedulingProfile,
10939
+ tournamentRecord,
10940
+ withSplitRounds,
10941
+ matchUpFilters,
10942
+ scheduleDate,
10943
+ withRoundId,
10944
+ venueId,
10945
+ context
10946
+ }) {
10947
+ if (inContextMatchUps && !Array.isArray(
10948
+ inContextMatchUps || typeof inContextMatchUps[0] !== "object"
10949
+ )) {
10950
+ return { error: INVALID_VALUES, inContextMatchUps };
10951
+ }
10952
+ if (tournamentRecord && !tournamentRecords) {
10953
+ if (typeof tournamentRecord !== "object") {
10954
+ return { error: INVALID_TOURNAMENT_RECORD };
10955
+ } else {
10956
+ tournamentRecords = { [tournamentRecord.tournamentId]: tournamentRecord };
10957
+ }
10958
+ }
10959
+ const noTournamentRecords = typeof tournamentRecords !== "object" || !Object.keys(tournamentRecords).length;
10960
+ const needsTournamentRecords = venueId || scheduleDate || !inContextMatchUps || !schedulingProfile && (excludeScheduleDateProfileRounds || excludeCompletedRounds || schedulingProfile || withSplitRounds);
10961
+ if (needsTournamentRecords && noTournamentRecords)
10962
+ return { error: MISSING_TOURNAMENT_RECORDS };
10963
+ const tournamentVenueIds = Object.assign(
10964
+ {},
10965
+ ...Object.values(tournamentRecords ?? {}).map(
10966
+ ({ venues = [], tournamentId }) => ({
10967
+ [tournamentId]: venues?.map(({ venueId: venueId2 }) => venueId2)
10968
+ })
10969
+ )
10970
+ );
10971
+ const events = Object.values(tournamentRecords ?? {}).map(
10972
+ ({ events: events2 = [], tournamentId, startDate, endDate }) => events2.map((event) => ({
10973
+ ...event,
10974
+ validVenueIds: tournamentVenueIds[tournamentId],
10975
+ startDate: event.startDate ?? startDate,
10976
+ endDate: event.endDate ?? endDate
10977
+ }))
10978
+ ).flat();
10979
+ const { segmentedRounds, profileRounds } = tournamentRecords && (excludeScheduleDateProfileRounds || excludeCompletedRounds || schedulingProfile || withSplitRounds) && getProfileRounds({ tournamentRecords, schedulingProfile }) || {};
10980
+ const profileRoundsMap = excludeScheduleDateProfileRounds && Object.assign(
10981
+ {},
10982
+ ...profileRounds.map((profile) => ({ [profile.id]: profile }))
10983
+ );
10984
+ const consideredMatchUps = inContextMatchUps || tournamentRecords && allCompetitionMatchUps({ tournamentRecords, matchUpFilters })?.matchUps || [];
10985
+ const excludedRounds = [];
10986
+ const rounds = consideredMatchUps && Object.values(
10987
+ consideredMatchUps.reduce((rounds2, matchUp) => {
10988
+ const id = getRoundId(matchUp).id;
10989
+ const segmentsCount = segmentedRounds?.[id];
10990
+ const matchUps = [...rounds2[id]?.matchUps ?? [], matchUp];
10991
+ const {
10992
+ containerStructureId,
10993
+ stageSequence,
10994
+ structureName,
10995
+ tournamentId,
10996
+ isRoundRobin,
10997
+ matchUpType,
10998
+ roundNumber,
10999
+ roundOffset,
11000
+ structureId,
11001
+ eventName,
11002
+ roundName,
11003
+ drawName,
11004
+ eventId,
11005
+ drawId
11006
+ } = matchUp;
11007
+ const relevantStructureId = isRoundRobin ? containerStructureId : structureId;
11008
+ return {
11009
+ ...rounds2,
11010
+ [id]: {
11011
+ id: withRoundId ? id : void 0,
11012
+ structureId: relevantStructureId,
11013
+ stageSequence,
11014
+ segmentsCount,
11015
+ structureName,
11016
+ tournamentId,
11017
+ matchUpType,
11018
+ roundNumber,
11019
+ roundOffset,
11020
+ eventName,
11021
+ roundName,
11022
+ drawName,
11023
+ matchUps,
11024
+ eventId,
11025
+ drawId
11026
+ }
11027
+ };
11028
+ }, {})
11029
+ ).map((round) => {
11030
+ const { minFinishingSum, winnerFinishingPositionRange } = getFinishingPositionDetails(round.matchUps);
11031
+ const segmentsCount = round.segmentsCount;
11032
+ if (segmentsCount) {
11033
+ const chunkSize = round.matchUps.length / segmentsCount;
11034
+ const sortedMatchUps = chunkArray(
11035
+ round.matchUps.sort((a, b) => a.roundPosition - b.roundPosition),
11036
+ chunkSize
11037
+ );
11038
+ return sortedMatchUps.map((matchUps, i) => {
11039
+ const {
11040
+ unscheduledCount: unscheduledCount2,
11041
+ incompleteCount: incompleteCount2,
11042
+ matchUpsCount: matchUpsCount2,
11043
+ isScheduled: isScheduled2,
11044
+ isComplete: isComplete2,
11045
+ byeCount: byeCount2
11046
+ } = getRoundProfile(matchUps);
11047
+ const roundTiming2 = getRoundTiming({
11048
+ matchUps: round.matchUps,
11049
+ tournamentRecords,
11050
+ events,
11051
+ round
11052
+ });
11053
+ return definedAttributes({
11054
+ ...round,
11055
+ ...context,
11056
+ roundSegment: { segmentsCount, segmentNumber: i + 1 },
11057
+ winnerFinishingPositionRange,
11058
+ unscheduledCount: unscheduledCount2,
11059
+ incompleteCount: incompleteCount2,
11060
+ minFinishingSum,
11061
+ matchUpsCount: matchUpsCount2,
11062
+ isScheduled: isScheduled2,
11063
+ roundTiming: roundTiming2,
11064
+ isComplete: isComplete2,
11065
+ byeCount: byeCount2,
11066
+ matchUps
11067
+ });
11068
+ });
11069
+ }
11070
+ const {
11071
+ unscheduledCount,
11072
+ incompleteCount,
11073
+ matchUpsCount,
11074
+ isScheduled,
11075
+ isComplete,
11076
+ byeCount
11077
+ } = getRoundProfile(round.matchUps);
11078
+ const roundTiming = getRoundTiming({
11079
+ matchUps: round.matchUps,
11080
+ tournamentRecords,
11081
+ events,
11082
+ round
11083
+ });
11084
+ return definedAttributes({
11085
+ ...round,
11086
+ ...context,
11087
+ winnerFinishingPositionRange,
11088
+ unscheduledCount,
11089
+ incompleteCount,
11090
+ minFinishingSum,
11091
+ matchUpsCount,
11092
+ isScheduled,
11093
+ roundTiming,
11094
+ isComplete,
11095
+ byeCount
11096
+ });
11097
+ }).flat().filter((round) => {
11098
+ if (excludeScheduleDateProfileRounds) {
11099
+ const scheduleDate2 = extractDate(excludeScheduleDateProfileRounds);
11100
+ const roundId = withRoundId ? round.id : getRoundId(round).id;
11101
+ if (scheduleDate2 && profileRoundsMap[roundId] && extractDate(profileRoundsMap[roundId].scheduleDate) === scheduleDate2) {
11102
+ return false;
11103
+ }
11104
+ }
11105
+ const { isComplete, isScheduled } = round;
11106
+ const keepComplete = !excludeCompletedRounds || !isComplete;
11107
+ const keepScheduled = !excludeScheduledRounds || !isScheduled;
11108
+ const event = venueId || scheduleDate ? events?.find(({ eventId }) => eventId === round.eventId) : void 0;
11109
+ const validDate = !scheduleDate || event?.startDate && event?.endDate && new Date(scheduleDate) >= new Date(event?.startDate) && new Date(scheduleDate) <= new Date(event?.endDate);
11110
+ const validVenue = !venueId || event?.validVenueIds.includes(venueId);
11111
+ const keepRound = keepComplete && keepScheduled && validVenue && validDate;
11112
+ if (!keepRound)
11113
+ excludedRounds.push(round);
11114
+ return keepRound;
11115
+ }).sort(roundSort) || [];
11116
+ return { ...SUCCESS, rounds, excludedRounds };
11117
+ }
11118
+
11119
+ function filterParticipants({
11120
+ participantFilters = {},
11121
+ tournamentRecord,
10740
11122
  participants = []
10741
11123
  }) {
10742
11124
  if (!Object.keys(participantFilters).length) {
@@ -15432,364 +15814,5 @@ function getEventData(params) {
15432
15814
  return { ...SUCCESS, eventData };
15433
15815
  }
15434
15816
 
15435
- function findMatchUpFormatTiming({
15436
- defaultRecoveryMinutes = 0,
15437
- defaultAverageMinutes,
15438
- tournamentRecords,
15439
- matchUpFormat,
15440
- categoryName,
15441
- categoryType,
15442
- tournamentId,
15443
- eventType,
15444
- eventId
15445
- }) {
15446
- if (!isValid(matchUpFormat))
15447
- return { error: UNRECOGNIZED_MATCHUP_FORMAT };
15448
- const tournamentIds = Object.keys(tournamentRecords).filter(
15449
- (currentTournamentId) => !tournamentId || currentTournamentId === tournamentId
15450
- );
15451
- let timing;
15452
- tournamentIds.forEach((currentTournamentId) => {
15453
- if (timing)
15454
- return;
15455
- const tournamentRecord = tournamentRecords[currentTournamentId];
15456
- const event = eventId ? findEvent({ tournamentRecord, eventId })?.event : void 0;
15457
- timing = getMatchUpFormatTiming({
15458
- tournamentRecord,
15459
- matchUpFormat,
15460
- categoryName,
15461
- categoryType,
15462
- eventType,
15463
- event
15464
- });
15465
- return timing?.averageMinutes || timing?.recoveryMinutes;
15466
- });
15467
- return {
15468
- recoveryMinutes: timing?.recoveryMinutes || defaultRecoveryMinutes,
15469
- averageMinutes: timing?.averageMinutes || defaultAverageMinutes,
15470
- typeChangeRecoveryMinutes: timing?.typeChangeRecoveryMinutes || timing?.recoveryMinutes || defaultRecoveryMinutes
15471
- };
15472
- }
15473
-
15474
- const { stageOrder } = drawDefinitionConstants;
15475
- function getProfileRounds({
15476
- tournamentRecords,
15477
- schedulingProfile,
15478
- tournamentRecord,
15479
- withRoundId
15480
- }) {
15481
- if (tournamentRecord && !tournamentRecords) {
15482
- if (typeof tournamentRecord !== "object") {
15483
- return { error: INVALID_TOURNAMENT_RECORD };
15484
- } else {
15485
- tournamentRecords = { [tournamentRecord.tournamentId]: tournamentRecord };
15486
- }
15487
- }
15488
- if (schedulingProfile) {
15489
- const profileValidity = validateSchedulingProfile({
15490
- tournamentRecords,
15491
- schedulingProfile
15492
- });
15493
- if (profileValidity.error)
15494
- return profileValidity;
15495
- }
15496
- if (!schedulingProfile && tournamentRecords) {
15497
- const result = getSchedulingProfile({ tournamentRecords });
15498
- if (result.error)
15499
- return result;
15500
- schedulingProfile = result.schedulingProfile;
15501
- }
15502
- if (!schedulingProfile)
15503
- return { error: NOT_FOUND };
15504
- const segmentedRounds = {};
15505
- const profileRounds = schedulingProfile.map(
15506
- ({ venues, scheduleDate }) => venues.map(
15507
- ({ rounds }) => rounds.map((round) => {
15508
- const roundRef = getRoundId(round);
15509
- if (roundRef.roundSegment?.segmentsCount) {
15510
- segmentedRounds[roundRef.id] = roundRef.roundSegment.segmentsCount;
15511
- }
15512
- return definedAttributes({
15513
- id: withRoundId ? roundRef.id : void 0,
15514
- scheduleDate,
15515
- ...roundRef
15516
- });
15517
- })
15518
- )
15519
- ).flat(Infinity);
15520
- return { profileRounds, segmentedRounds };
15521
- }
15522
- function getRoundId(obj) {
15523
- const {
15524
- containerStructureId,
15525
- roundSegment,
15526
- isRoundRobin,
15527
- tournamentId,
15528
- roundNumber,
15529
- structureId,
15530
- eventId,
15531
- drawId
15532
- } = obj;
15533
- const relevantStructureId = isRoundRobin ? containerStructureId : structureId;
15534
- const id = [
15535
- tournamentId,
15536
- // 1
15537
- eventId,
15538
- // 2
15539
- drawId,
15540
- // 3
15541
- relevantStructureId,
15542
- // 4
15543
- roundNumber
15544
- // 5
15545
- ].join("|");
15546
- return definedAttributes({
15547
- id,
15548
- roundSegment,
15549
- tournamentId,
15550
- eventId,
15551
- drawId,
15552
- structureId: relevantStructureId,
15553
- roundNumber
15554
- });
15555
- }
15556
- function getRoundProfile(matchUps) {
15557
- const matchUpsCount = matchUps.length;
15558
- const byeCount = matchUps.filter(({ sides }) => sides?.some(({ bye }) => bye)).length || 0;
15559
- const completedCount = matchUps.filter(
15560
- ({ winningSide, matchUpStatus }) => winningSide || completedMatchUpStatuses.includes(matchUpStatus)
15561
- ).length || 0;
15562
- const scheduledCount = matchUps.filter(
15563
- ({ schedule }) => schedule?.scheduledDate && schedule?.scheduledTime
15564
- ).length || 0;
15565
- const consideredCount = matchUpsCount - byeCount;
15566
- const isComplete = consideredCount === completedCount;
15567
- const unscheduledCount = consideredCount - scheduledCount;
15568
- const incompleteCount = consideredCount - scheduledCount;
15569
- const isScheduled = consideredCount === scheduledCount;
15570
- return {
15571
- unscheduledCount,
15572
- incompleteCount,
15573
- scheduledCount,
15574
- completedCount,
15575
- matchUpsCount,
15576
- isScheduled,
15577
- isComplete,
15578
- byeCount
15579
- };
15580
- }
15581
- function getRounds({
15582
- excludeScheduleDateProfileRounds,
15583
- excludeScheduledRounds,
15584
- excludeCompletedRounds,
15585
- inContextMatchUps,
15586
- tournamentRecords,
15587
- schedulingProfile,
15588
- tournamentRecord,
15589
- withSplitRounds,
15590
- matchUpFilters,
15591
- withRoundId,
15592
- context
15593
- }) {
15594
- if (inContextMatchUps && !Array.isArray(
15595
- inContextMatchUps || typeof inContextMatchUps[0] !== "object"
15596
- )) {
15597
- return { error: INVALID_VALUES, inContextMatchUps };
15598
- }
15599
- if (tournamentRecord && !tournamentRecords) {
15600
- if (typeof tournamentRecord !== "object") {
15601
- return { error: INVALID_TOURNAMENT_RECORD };
15602
- } else {
15603
- tournamentRecords = { [tournamentRecord.tournamentId]: tournamentRecord };
15604
- }
15605
- }
15606
- const noTournamentRecords = typeof tournamentRecords !== "object" || !Object.keys(tournamentRecords).length;
15607
- const needsTournamentRecords = !inContextMatchUps || !schedulingProfile && (excludeScheduleDateProfileRounds || excludeCompletedRounds || schedulingProfile || withSplitRounds);
15608
- if (needsTournamentRecords && noTournamentRecords)
15609
- return { error: MISSING_TOURNAMENT_RECORDS };
15610
- const events = Object.values(tournamentRecords ?? {}).map(({ events: events2 }) => events2).flat();
15611
- const { segmentedRounds, profileRounds } = tournamentRecords && (excludeScheduleDateProfileRounds || excludeCompletedRounds || schedulingProfile || withSplitRounds) && getProfileRounds({ tournamentRecords, schedulingProfile }) || {};
15612
- const profileRoundsMap = excludeScheduleDateProfileRounds && Object.assign(
15613
- {},
15614
- ...profileRounds.map((profile) => ({ [profile.id]: profile }))
15615
- );
15616
- const consideredMatchUps = inContextMatchUps || tournamentRecords && allCompetitionMatchUps({ tournamentRecords, matchUpFilters })?.matchUps || [];
15617
- const excludedRounds = [];
15618
- const rounds = consideredMatchUps && Object.values(
15619
- consideredMatchUps.reduce((rounds2, matchUp) => {
15620
- const id = getRoundId(matchUp).id;
15621
- const segmentsCount = segmentedRounds?.[id];
15622
- const matchUps = [...rounds2[id]?.matchUps ?? [], matchUp];
15623
- const {
15624
- containerStructureId,
15625
- stageSequence,
15626
- structureName,
15627
- tournamentId,
15628
- isRoundRobin,
15629
- matchUpType,
15630
- roundNumber,
15631
- roundOffset,
15632
- structureId,
15633
- eventName,
15634
- roundName,
15635
- drawName,
15636
- eventId,
15637
- drawId
15638
- } = matchUp;
15639
- const relevantStructureId = isRoundRobin ? containerStructureId : structureId;
15640
- return {
15641
- ...rounds2,
15642
- [id]: {
15643
- id: withRoundId ? id : void 0,
15644
- structureId: relevantStructureId,
15645
- stageSequence,
15646
- segmentsCount,
15647
- structureName,
15648
- tournamentId,
15649
- matchUpType,
15650
- roundNumber,
15651
- roundOffset,
15652
- eventName,
15653
- roundName,
15654
- drawName,
15655
- matchUps,
15656
- eventId,
15657
- drawId
15658
- }
15659
- };
15660
- }, {})
15661
- ).map((round) => {
15662
- const { minFinishingSum, winnerFinishingPositionRange } = getFinishingPositionDetails(round.matchUps);
15663
- const segmentsCount = round.segmentsCount;
15664
- if (segmentsCount) {
15665
- const chunkSize = round.matchUps.length / segmentsCount;
15666
- const sortedMatchUps = chunkArray(
15667
- round.matchUps.sort((a, b) => a.roundPosition - b.roundPosition),
15668
- chunkSize
15669
- );
15670
- return sortedMatchUps.map((matchUps, i) => {
15671
- const {
15672
- unscheduledCount: unscheduledCount2,
15673
- incompleteCount: incompleteCount2,
15674
- matchUpsCount: matchUpsCount2,
15675
- isScheduled: isScheduled2,
15676
- isComplete: isComplete2,
15677
- byeCount: byeCount2
15678
- } = getRoundProfile(matchUps);
15679
- const roundTiming2 = getRoundTiming({
15680
- matchUps: round.matchUps,
15681
- tournamentRecords,
15682
- events,
15683
- round
15684
- });
15685
- return definedAttributes({
15686
- ...round,
15687
- ...context,
15688
- roundSegment: { segmentsCount, segmentNumber: i + 1 },
15689
- winnerFinishingPositionRange,
15690
- unscheduledCount: unscheduledCount2,
15691
- incompleteCount: incompleteCount2,
15692
- minFinishingSum,
15693
- matchUpsCount: matchUpsCount2,
15694
- isScheduled: isScheduled2,
15695
- roundTiming: roundTiming2,
15696
- isComplete: isComplete2,
15697
- byeCount: byeCount2,
15698
- matchUps
15699
- });
15700
- });
15701
- }
15702
- const {
15703
- unscheduledCount,
15704
- incompleteCount,
15705
- matchUpsCount,
15706
- isScheduled,
15707
- isComplete,
15708
- byeCount
15709
- } = getRoundProfile(round.matchUps);
15710
- const roundTiming = getRoundTiming({
15711
- matchUps: round.matchUps,
15712
- tournamentRecords,
15713
- events,
15714
- round
15715
- });
15716
- return definedAttributes({
15717
- ...round,
15718
- ...context,
15719
- winnerFinishingPositionRange,
15720
- unscheduledCount,
15721
- incompleteCount,
15722
- minFinishingSum,
15723
- matchUpsCount,
15724
- isScheduled,
15725
- roundTiming,
15726
- isComplete,
15727
- byeCount
15728
- });
15729
- }).flat().filter((round) => {
15730
- if (excludeScheduleDateProfileRounds) {
15731
- const scheduleDate = extractDate(excludeScheduleDateProfileRounds);
15732
- const roundId = withRoundId ? round.id : getRoundId(round).id;
15733
- if (scheduleDate && profileRoundsMap[roundId] && extractDate(profileRoundsMap[roundId].scheduleDate) === scheduleDate) {
15734
- return false;
15735
- }
15736
- }
15737
- const { isComplete, isScheduled } = round;
15738
- const keepComplete = !excludeCompletedRounds || !isComplete;
15739
- const keepScheduled = !excludeScheduledRounds || !isScheduled;
15740
- const keepRound = keepComplete && keepScheduled;
15741
- if (!keepRound)
15742
- excludedRounds.push(round);
15743
- return keepRound;
15744
- }).sort(roundSort) || [];
15745
- return { ...SUCCESS, rounds, excludedRounds };
15746
- }
15747
- function getRoundTiming({ round, matchUps, events, tournamentRecords }) {
15748
- const event = events.find((event2) => event2.eventId === round.eventId);
15749
- const { eventType, category, categoryType } = event || {};
15750
- const { categoryName, ageCategoryCode } = category || {};
15751
- const formatCounts = instanceCount(
15752
- matchUps.map(({ matchUpFormat }) => matchUpFormat)
15753
- );
15754
- let roundMinutes = 0;
15755
- Object.keys(formatCounts).forEach((matchUpFormat) => {
15756
- const formatCount = formatCounts[matchUpFormat];
15757
- const result = findMatchUpFormatTiming({
15758
- categoryName: categoryName || ageCategoryCode,
15759
- tournamentId: round.tournamentId,
15760
- eventId: round.eventId,
15761
- tournamentRecords,
15762
- matchUpFormat,
15763
- categoryType,
15764
- eventType
15765
- });
15766
- if (result.error)
15767
- return result;
15768
- const formatMinutes = result.averageMinutes * formatCount;
15769
- if (!isNaN(roundMinutes))
15770
- roundMinutes += formatMinutes;
15771
- return void 0;
15772
- });
15773
- return { roundMinutes };
15774
- }
15775
- function roundSort(a, b) {
15776
- return a.eventName.localeCompare(b.eventName) || a.eventId.localeCompare(b.eventId) || (stageOrder[a?.stage] || 0) - (stageOrder[b?.stage] || 0) || b.matchUpsCount - a.matchUpsCount || `${a.stageSequence}-${a.roundNumber}-${a.minFinishingSum}`.localeCompare(
15777
- `${b.stageSequence}-${b.roundNumber}-${b.minFinishingSum}`
15778
- );
15779
- }
15780
- function getFinishingPositionDetails(matchUps) {
15781
- return (matchUps || []).reduce(
15782
- (foo, matchUp) => {
15783
- const sum = (matchUp.finishingPositionRange?.winner || []).reduce(
15784
- (a, b) => a + b,
15785
- 0
15786
- );
15787
- const winnerFinishingPositionRange = (matchUp.finishingPositionRange?.winner || []).join("-") || "";
15788
- return !foo.minFinishingSum || sum < foo.minFinishingSum ? { minFinishingSum: sum, winnerFinishingPositionRange } : foo;
15789
- },
15790
- { minFinishingSum: 0, winnerFinishingPositionRange: "" }
15791
- );
15792
- }
15793
-
15794
15817
  export { allCompetitionMatchUps, allDrawMatchUps, allEventMatchUps, allTournamentMatchUps, matchUpActions as competitionMatchUpActions, competitionMatchUps, competitionScheduleMatchUps, drawMatchUps, eventMatchUps, filterParticipants, findExtension, findMatchUp, publicFindParticipant as findParticipant, generateSeedingScaleItems, getCompetitionDateRange, getCompetitionParticipants, getCompetitionVenues, getVenuesAndCourts as getCompetitionVenuesAndCourts, getEligibleVoluntaryConsolationParticipants, getEntriesAndSeedsCount, getEventData, getEventMatchUpFormatTiming, getFlightProfile, getMatchUpDailyLimits, getMatchUpDailyLimitsUpdate, getMatchUpFormatTimingUpdate, getOrderedDrawPositions, getParticipantEventDetails, getParticipantScaleItem, getPolicyDefinitions, getPositionAssignments, getProfileRounds, getRoundContextProfile, getRoundMatchUps, getRounds, getSeedsCount, getTimeItem, getVenuesAndCourts$1 as getTournamentVenuesAndCourts, getValidGroupSizes, isValid as isValidMatchUpFormat, parse as parseMatchUpFormat, parseScoreString, participantScaleItem, positionActions, matchUpActions$1 as tournamentMatchUpActions, tournamentMatchUps, validateScore };
15795
15818
  //# sourceMappingURL=query.mjs.map