tods-competition-factory 2.3.0 → 2.3.2

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.
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  function factoryVersion() {
6
- return '2.3.0';
6
+ return '2.3.2';
7
7
  }
8
8
 
9
9
  const SINGLES_MATCHUP = 'SINGLES';
@@ -989,6 +989,14 @@ const COURT_EXISTS = {
989
989
  message: 'Court exists',
990
990
  code: 'ERR_EXISTING_COURT',
991
991
  };
992
+ const BOOKING_NOT_FOUND = {
993
+ message: 'Booking not found',
994
+ code: 'ERR_NOT_FOUND_BOOKING',
995
+ };
996
+ const EXISTING_MATCHUPS = {
997
+ message: 'Existing matchUps conflict with booking',
998
+ code: 'ERR_EXISTING_MATCHUPS',
999
+ };
992
1000
  const VENUE_EXISTS = {
993
1001
  message: 'Venue exists',
994
1002
  code: 'ERR_EXISTING_VENUE',
@@ -1152,6 +1160,7 @@ const SCORES_PRESENT = {
1152
1160
  };
1153
1161
  const errorConditionConstants = {
1154
1162
  ANACHRONISM,
1163
+ BOOKING_NOT_FOUND,
1155
1164
  CANNOT_CHANGE_WINNING_SIDE,
1156
1165
  CANNOT_MODIFY_TIEFORMAT,
1157
1166
  CANNOT_MODIFY_PARTICIPANT_TYPE,
@@ -1160,6 +1169,7 @@ const errorConditionConstants = {
1160
1169
  CATEGORY_MISMATCH,
1161
1170
  COURT_EXISTS,
1162
1171
  COURT_NOT_FOUND,
1172
+ EXISTING_MATCHUPS,
1163
1173
  DRAW_DEFINITION_NOT_FOUND,
1164
1174
  DRAW_ID_EXISTS,
1165
1175
  DRAW_POSITION_ACTIVE,
@@ -2289,7 +2299,8 @@ function validTimeValue(value) {
2289
2299
  const spaceSplit = typeof value === 'string' ? value?.split(' ') : [];
2290
2300
  if (value && spaceSplit?.length > 1 && !['AM', 'PM'].includes(spaceSplit[1].toUpperCase()))
2291
2301
  return false;
2292
- return !!(!value || timeValidation.test(convertTime(value, true, true)));
2302
+ const converted = convertTime(value, true, true);
2303
+ return !!(!value || (converted && timeValidation.test(converted)));
2293
2304
  }
2294
2305
  function isValidDateString(scheduleDate) {
2295
2306
  return isISODateString(scheduleDate) || validDateString.test(scheduleDate);
@@ -2300,7 +2311,7 @@ function DateHHMM(date) {
2300
2311
  return HHMMSS(secs, { displaySeconds: false });
2301
2312
  }
2302
2313
  function HHMMSS(s, format) {
2303
- const secondNumber = parseInt(s, 10);
2314
+ const secondNumber = Number.parseInt(s, 10);
2304
2315
  const hours = Math.floor(secondNumber / 3600);
2305
2316
  const minutes = Math.floor((secondNumber - hours * 3600) / 60);
2306
2317
  const seconds = secondNumber - hours * 3600 - minutes * 60;
@@ -2321,7 +2332,7 @@ function timeUTC(date) {
2321
2332
  function formatDate(date, separator = '-', format = 'YMD') {
2322
2333
  if (!date)
2323
2334
  return '';
2324
- if (typeof date === 'string' && date.indexOf('T') < 0)
2335
+ if (typeof date === 'string' && !date.includes('T'))
2325
2336
  date = date + 'T00:00';
2326
2337
  const d = new Date(date);
2327
2338
  let month = '' + (d.getMonth() + 1);
@@ -2354,8 +2365,11 @@ function offsetTime(date) {
2354
2365
  function isDate(dateArg) {
2355
2366
  if (typeof dateArg == 'boolean')
2356
2367
  return false;
2357
- const t = (dateArg instanceof Date && dateArg) || (!isNaN(dateArg) && new Date(dateArg)) || false;
2358
- return t && !isNaN(t.valueOf());
2368
+ const t = (dateArg instanceof Date && dateArg) || (!Number.isNaN(Number(dateArg)) && new Date(dateArg)) || false;
2369
+ return t && !Number.isNaN(Number(t.valueOf()));
2370
+ }
2371
+ function isValidDateRange(minDate, maxDate) {
2372
+ return minDate <= maxDate;
2359
2373
  }
2360
2374
  function generateDateRange(startDt, endDt) {
2361
2375
  if (!isValidDateString(startDt) || !isValidDateString(endDt))
@@ -2377,9 +2391,6 @@ function generateDateRange(startDt, endDt) {
2377
2391
  }
2378
2392
  }
2379
2393
  return between.map((date) => formatDate(date));
2380
- function isValidDateRange(minDate, maxDate) {
2381
- return minDate <= maxDate;
2382
- }
2383
2394
  }
2384
2395
  const re = /^([+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24:?00)([.,]\d+(?!:))?)?(\17[0-5]\d([.,]\d+)?)?([zZ]|([+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/;
2385
2396
  function isISODateString(dateString) {
@@ -2392,15 +2403,15 @@ function isTimeString(timeString) {
2392
2403
  return false;
2393
2404
  const noZ = timeString.split('Z')[0];
2394
2405
  const parts = noZ.split(':');
2395
- const isNumeric = parts.every((part) => !isNaN(parseInt(part)));
2396
- const invalid = parts.length < 2 || !isNumeric || parseInt(parts[0]) > 23 || parseInt(parts[1]) > 60;
2406
+ const isNumeric = parts.every((part) => !Number.isNaN(Number.parseInt(part)));
2407
+ const invalid = parts.length < 2 || !isNumeric || Number.parseInt(parts[0]) > 23 || Number.parseInt(parts[1]) > 60;
2397
2408
  return !invalid;
2398
2409
  }
2399
2410
  function timeStringMinutes$1(timeString) {
2400
2411
  const validTimeString = extractTime$1(timeString);
2401
2412
  if (!validTimeString)
2402
2413
  return 0;
2403
- const [hours, minutes] = validTimeString.split(':').map((value) => parseInt(value));
2414
+ const [hours, minutes] = validTimeString.split(':').map((value) => Number.parseInt(value));
2404
2415
  return hours * 60 + minutes;
2405
2416
  }
2406
2417
  function dayMinutesToTimeString(totalMinutes) {
@@ -2419,7 +2430,7 @@ function extractTime$1(dateString) {
2419
2430
  : tidyTime(dateString);
2420
2431
  }
2421
2432
  function extractDate(dateString) {
2422
- return isISODateString(dateString) || dateValidation.test(dateString) ? dateString.split('T')[0] : undefined;
2433
+ return isISODateString(dateString) || dateValidation.test(dateString) ? dateString.split('T')[0] : '';
2423
2434
  }
2424
2435
  function dateStringDaysChange(dateString, daysChange) {
2425
2436
  const date = new Date(dateString);
@@ -2427,20 +2438,22 @@ function dateStringDaysChange(dateString, daysChange) {
2427
2438
  return extractDate(date.toISOString());
2428
2439
  }
2429
2440
  function splitTime(value) {
2430
- value = typeof value !== 'string' ? '00:00' : value;
2441
+ value = typeof value === 'string' ? value : '00:00';
2431
2442
  const o = {}, time = {};
2432
2443
  ({ 0: o.time, 1: o.ampm } = value.split(' ') || []);
2433
2444
  ({ 0: time.hours, 1: time.minutes } = o.time.split(':') || []);
2434
2445
  time.ampm = o.ampm;
2435
- if (isNaN(time.hours) || isNaN(time.minutes) || (time.ampm && !['AM', 'PM'].includes(time.ampm.toUpperCase())))
2446
+ if (Number.isNaN(Number.parseInt(time.hours)) ||
2447
+ Number.isNaN(Number.parseInt(time.minutes)) ||
2448
+ (time.ampm && !['AM', 'PM'].includes(time.ampm.toUpperCase())))
2436
2449
  return {};
2437
2450
  return time;
2438
2451
  }
2439
2452
  function militaryTime(value) {
2440
2453
  const time = splitTime(value);
2441
2454
  if (time.ampm && time.hours) {
2442
- if (time.ampm.toLowerCase() === 'pm' && parseInt(time.hours) < 12)
2443
- time.hours = ((time.hours && parseInt(time.hours)) || 0) + 12;
2455
+ if (time.ampm.toLowerCase() === 'pm' && Number.parseInt(time.hours) < 12)
2456
+ time.hours = ((time.hours && Number.parseInt(time.hours)) || 0) + 12;
2444
2457
  if (time.ampm.toLowerCase() === 'am' && time.hours === '12')
2445
2458
  time.hours = '00';
2446
2459
  }
@@ -2476,21 +2489,21 @@ function convertTime(value, time24, keepDate) {
2476
2489
  const hasDate = extractDate(value);
2477
2490
  const timeString = extractTime$1(value);
2478
2491
  const timeValue = hasDate ? timeString : value;
2479
- return !value
2480
- ? undefined
2481
- : (time24 && ((hasDate && keepDate && value) || militaryTime(timeValue))) || regularTime(timeValue);
2492
+ return value
2493
+ ? (time24 && ((hasDate && keepDate && value) || militaryTime(timeValue))) || regularTime(timeValue)
2494
+ : undefined;
2482
2495
  }
2483
2496
  function timeSort(a, b) {
2484
2497
  const as = splitTime(a);
2485
2498
  const bs = splitTime(b);
2486
- if (parseInt(as.hours) < parseInt(bs.hours))
2499
+ if (Number.parseInt(as.hours) < Number.parseInt(bs.hours))
2487
2500
  return -1;
2488
- if (parseInt(as.hours) > parseInt(bs.hours))
2501
+ if (Number.parseInt(as.hours) > Number.parseInt(bs.hours))
2489
2502
  return 1;
2490
2503
  if (as.hours === bs.hours) {
2491
- if (parseInt(as.minutes) < parseInt(bs.minutes))
2504
+ if (Number.parseInt(as.minutes) < Number.parseInt(bs.minutes))
2492
2505
  return -1;
2493
- if (parseInt(as.minutes) > parseInt(bs.minutes))
2506
+ if (Number.parseInt(as.minutes) > Number.parseInt(bs.minutes))
2494
2507
  return 1;
2495
2508
  }
2496
2509
  return 0;
@@ -2529,8 +2542,8 @@ function addMinutesToTimeString(timeString, minutes) {
2529
2542
  const validTimeString = extractTime$1(timeString);
2530
2543
  if (!validTimeString)
2531
2544
  return '00:00';
2532
- const minutesToAdd = isNaN(minutes) ? 0 : minutes;
2533
- return extractTime$1(addMinutes(timeToDate(validTimeString), minutesToAdd).toISOString());
2545
+ const minutesToAdd = Number.isNaN(minutes) ? 0 : minutes;
2546
+ return extractTime$1(addMinutes(timeToDate(validTimeString), minutesToAdd).toISOString()) || '00:00';
2534
2547
  }
2535
2548
  function addMinutes(startDate, minutes) {
2536
2549
  const date = new Date(startDate);
@@ -2586,23 +2599,27 @@ function getCategoryAgeDetails(params) {
2586
2599
  if (!isValidCategory)
2587
2600
  return { error: INVALID_CATEGORY };
2588
2601
  const consideredDate = params.consideredDate ?? extractDate(new Date().toLocaleDateString('sv'));
2589
- if (!isValidDateString(consideredDate))
2602
+ if (!consideredDate || !isValidDateString(consideredDate))
2590
2603
  return { error: INVALID_DATE };
2591
2604
  const [consideredYear] = consideredDate
2592
2605
  .split('-')
2593
2606
  .slice(0, 3)
2594
- .map((n) => parseInt(n));
2607
+ .map((n) => Number.parseInt(n));
2595
2608
  const previousDayDate = dateStringDaysChange(consideredDate, -1);
2609
+ if (!previousDayDate)
2610
+ return { error: INVALID_DATE };
2596
2611
  const [previousDayMonth, previousDay] = previousDayDate
2597
2612
  .split('-')
2598
2613
  .slice(1, 3)
2599
- .map((n) => parseInt(n));
2614
+ .map((n) => Number.parseInt(n));
2600
2615
  const previousMonthDay = `${zeroPad(previousDayMonth)}-${zeroPad(previousDay)}`;
2601
2616
  const nextDayDate = dateStringDaysChange(consideredDate, 1);
2617
+ if (!nextDayDate)
2618
+ return { error: INVALID_DATE };
2602
2619
  const [nextDayMonth, nextDay] = nextDayDate
2603
2620
  .split('-')
2604
2621
  .slice(1, 3)
2605
- .map((n) => parseInt(n));
2622
+ .map((n) => Number.parseInt(n));
2606
2623
  const nextMonthDay = `${zeroPad(nextDayMonth)}-${zeroPad(nextDay)}`;
2607
2624
  let calculatedAgeMaxDate = ageMin && dateStringDaysChange(consideredDate, -1 * 365 * ageMin);
2608
2625
  let calculatedAgeMinDate = ageMax && dateStringDaysChange(consideredDate, -1 * 365 * ageMax);
@@ -2679,7 +2696,7 @@ function getCategoryAgeDetails(params) {
2679
2696
  };
2680
2697
  const processCode = (code) => {
2681
2698
  const [pre, age, post] = (code.match(prePost) || []).slice(1);
2682
- const ageInt = parseInt(age);
2699
+ const ageInt = Number.parseInt(age);
2683
2700
  if (pre === 'U') {
2684
2701
  if (category.ageMaxDate && category.ageMaxDate !== ageMaxDate) {
2685
2702
  addError(`Invalid submitted ageMaxDate: ${category.ageMaxDate}`);
@@ -2698,8 +2715,8 @@ function getCategoryAgeDetails(params) {
2698
2715
  else if (post === 'O') {
2699
2716
  oPost(ageInt);
2700
2717
  }
2701
- ageMaxDate = ageMaxDate ?? calculatedAgeMaxDate;
2702
- ageMinDate = ageMinDate ?? calculatedAgeMinDate;
2718
+ ageMaxDate = (ageMaxDate ?? calculatedAgeMaxDate) || undefined;
2719
+ ageMinDate = (ageMinDate ?? calculatedAgeMinDate) || undefined;
2703
2720
  };
2704
2721
  if (isCombined) {
2705
2722
  ageMaxDate = undefined;
@@ -2714,7 +2731,7 @@ function getCategoryAgeDetails(params) {
2714
2731
  const ageMinYear = consideredYear - category.ageMax - 1;
2715
2732
  ageMinDate = constructedDate(ageMinYear, nextMonthDay);
2716
2733
  }
2717
- const [lowAge, highAge] = (ageCategoryCode?.match(extractCombined) ?? []).slice(1).map((n) => parseInt(n));
2734
+ const [lowAge, highAge] = (ageCategoryCode?.match(extractCombined) ?? []).slice(1).map((n) => Number.parseInt(n));
2718
2735
  if (lowAge <= highAge) {
2719
2736
  ageMin = lowAge;
2720
2737
  ageMax = highAge;
@@ -8675,7 +8692,7 @@ function getRoundMatchUps({ matchUps = [], interpolate }) {
8675
8692
  if (interpolate) {
8676
8693
  const maxRoundNumber = Math.max(...Object.keys(roundMatchUps)
8677
8694
  .map((key) => ensureInt(key))
8678
- .filter((f) => !isNaN(f)));
8695
+ .filter((f) => !Number.isNaN(f)));
8679
8696
  const maxRoundMatchUpsCount = roundMatchUps[maxRoundNumber]?.length;
8680
8697
  if (maxRoundMatchUpsCount > 1 && isPowerOf2(maxRoundMatchUpsCount)) {
8681
8698
  const nextRound = maxRoundNumber + 1;
@@ -8698,10 +8715,10 @@ function getRoundMatchUps({ matchUps = [], interpolate }) {
8698
8715
  let feedRoundIndex = 0;
8699
8716
  const roundNumbers = Object.keys(roundMatchUps)
8700
8717
  .map((key) => ensureInt(key))
8701
- .filter((f) => !isNaN(f));
8718
+ .filter((f) => !Number.isNaN(f));
8702
8719
  roundNumbers.forEach((roundNumber) => {
8703
8720
  const currentRoundMatchUps = roundMatchUps[roundNumber].sort((a, b) => a.roundPosition - b.roundPosition);
8704
- const currentRoundDrawPositions = currentRoundMatchUps.map((matchUp) => matchUp?.drawPositions || []).flat();
8721
+ const currentRoundDrawPositions = currentRoundMatchUps.flatMap((matchUp) => matchUp?.drawPositions || []);
8705
8722
  roundProfile[roundNumber].roundNumber = roundNumber;
8706
8723
  roundProfile[roundNumber].roundFactor = roundProfile[roundNumber].matchUpsCount
8707
8724
  ? maxMatchUpsCount / roundProfile[roundNumber].matchUpsCount
@@ -8762,7 +8779,7 @@ function getRoundMatchUps({ matchUps = [], interpolate }) {
8762
8779
  roundIndex += 1;
8763
8780
  }
8764
8781
  });
8765
- const roundsNotPowerOf2 = !!Object.values(roundProfile).find(({ matchUpsCount }) => !isPowerOf2(matchUpsCount));
8782
+ const roundsNotPowerOf2 = !!Object.values(roundProfile).some(({ matchUpsCount }) => !isPowerOf2(matchUpsCount));
8766
8783
  const hasNoRoundPositions = matchUps.some((matchUp) => !matchUp.roundPosition);
8767
8784
  return {
8768
8785
  hasNoRoundPositions,
@@ -9115,7 +9132,7 @@ function getRoundContextProfile({ roundNamingPolicy, drawDefinition, structure,
9115
9132
  const add = (a, b) => (a || 0) + (b || 0);
9116
9133
  function getBand(spread, bandProfiles) {
9117
9134
  const spreadValue = Array.isArray(spread) ? spread[0] : spread;
9118
- return ((isNaN(spreadValue) && WALKOVER$1) ||
9135
+ return ((Number.isNaN(spreadValue) && WALKOVER$1) ||
9119
9136
  (spreadValue <= bandProfiles[DECISIVE] && DECISIVE) ||
9120
9137
  (spreadValue <= bandProfiles[ROUTINE] && ROUTINE) ||
9121
9138
  COMPETITIVE);
@@ -9285,7 +9302,7 @@ function getCheckedInParticipantIds({ matchUp }) {
9285
9302
  return { error: MISSING_MATCHUP };
9286
9303
  if (!matchUp.hasContext)
9287
9304
  return { error: MISSING_CONTEXT };
9288
- if (!matchUp.sides || matchUp.sides.filter(Boolean).length !== 2) {
9305
+ if (!matchUp.sides || matchUp?.sides.filter(Boolean).length !== 2) {
9289
9306
  return { error: INVALID_MATCHUP };
9290
9307
  }
9291
9308
  const { nestedIndividualParticipantIds, allRelevantParticipantIds, sideParticipantIds } = getMatchUpParticipantIds({
@@ -15782,6 +15799,84 @@ function addVoluntaryConsolationStructure({ structureName = constantToString(VOL
15782
15799
  return { ...SUCCESS };
15783
15800
  }
15784
15801
 
15802
+ function getDivisions({ size }) {
15803
+ const divisions = [size];
15804
+ let division = size;
15805
+ while (division / 2 === Math.floor(division / 2)) {
15806
+ division = division / 2;
15807
+ divisions.push(division);
15808
+ }
15809
+ if (!divisions.includes(1))
15810
+ divisions.push(1);
15811
+ divisions.sort(numericSort);
15812
+ divisions.reverse();
15813
+ return divisions;
15814
+ }
15815
+ function getSubBlock({ blockPattern, index }) {
15816
+ let i = 0;
15817
+ for (const subBlock of blockPattern) {
15818
+ if (i === index)
15819
+ return subBlock;
15820
+ let j = 0;
15821
+ while (j < subBlock.length) {
15822
+ if (i === index)
15823
+ return subBlock;
15824
+ i += 1;
15825
+ j++;
15826
+ }
15827
+ }
15828
+ }
15829
+ function generateBlockPattern({ positioning, size }) {
15830
+ const divisions = getDivisions({ size });
15831
+ const divisionGroupings = [];
15832
+ const selected = [];
15833
+ const firstMember = (arr) => arr[0];
15834
+ const lastMember = (arr) => arr[arr.length - 1];
15835
+ const getMember = (arr, i) => (positioning && [CLUSTER, ADJACENT, WATERFALL].includes(positioning) && i % 2
15836
+ ? lastMember(arr)
15837
+ : firstMember(arr)) || firstMember(arr);
15838
+ const noneSelected = (chunk, i) => {
15839
+ if (chunk.every((member) => !selected.includes(member))) {
15840
+ const member = getMember(chunk, i);
15841
+ selected.push(member);
15842
+ return member;
15843
+ }
15844
+ };
15845
+ const notSelected = (chunk) => {
15846
+ const notSelected = chunk.filter((member) => !selected.includes(member));
15847
+ if (notSelected.length) {
15848
+ selected.push(...notSelected);
15849
+ return notSelected;
15850
+ }
15851
+ };
15852
+ const select = (chunk, i) => {
15853
+ const member = getMember(chunk, i);
15854
+ if (!selected.includes(member)) {
15855
+ selected.push(member);
15856
+ return member;
15857
+ }
15858
+ };
15859
+ const range = generateRange(1, size + 1);
15860
+ for (const division of divisions) {
15861
+ if (division === 1) {
15862
+ const chunks = chunkArray(range, 2);
15863
+ const positions = chunks.map(noneSelected).filter(Boolean);
15864
+ if (positions.length)
15865
+ divisionGroupings.push(positions);
15866
+ const lastPositions = chunks.flatMap(notSelected).filter(Boolean);
15867
+ if (lastPositions.length)
15868
+ divisionGroupings.push(lastPositions);
15869
+ }
15870
+ else {
15871
+ const chunks = chunkArray(range, division);
15872
+ const positions = chunks.map(select).filter(Boolean);
15873
+ if (positions.length)
15874
+ divisionGroupings.push(positions);
15875
+ }
15876
+ }
15877
+ return { divisions, divisionGroupings };
15878
+ }
15879
+
15785
15880
  function getRoundRobinGroupMatchUps({ drawPositions }) {
15786
15881
  if (!drawPositions?.length)
15787
15882
  return { error: MISSING_DRAW_POSITIONS };
@@ -16132,84 +16227,6 @@ function getNumericSeedValue(seedValue) {
16132
16227
  return Infinity;
16133
16228
  }
16134
16229
 
16135
- function getDivisions({ size }) {
16136
- const divisions = [size];
16137
- let division = size;
16138
- while (division / 2 === Math.floor(division / 2)) {
16139
- division = division / 2;
16140
- divisions.push(division);
16141
- }
16142
- if (!divisions.includes(1))
16143
- divisions.push(1);
16144
- divisions.sort(numericSort);
16145
- divisions.reverse();
16146
- return divisions;
16147
- }
16148
- function getSubBlock({ blockPattern, index }) {
16149
- let i = 0;
16150
- for (const subBlock of blockPattern) {
16151
- if (i === index)
16152
- return subBlock;
16153
- let j = 0;
16154
- while (j < subBlock.length) {
16155
- if (i === index)
16156
- return subBlock;
16157
- i += 1;
16158
- j++;
16159
- }
16160
- }
16161
- }
16162
- function generateBlockPattern({ positioning, size }) {
16163
- const divisions = getDivisions({ size });
16164
- const divisionGroupings = [];
16165
- const selected = [];
16166
- const firstMember = (arr) => arr[0];
16167
- const lastMember = (arr) => arr[arr.length - 1];
16168
- const getMember = (arr, i) => (positioning && [CLUSTER, ADJACENT, WATERFALL].includes(positioning) && i % 2
16169
- ? lastMember(arr)
16170
- : firstMember(arr)) || firstMember(arr);
16171
- const noneSelected = (chunk, i) => {
16172
- if (chunk.every((member) => !selected.includes(member))) {
16173
- const member = getMember(chunk, i);
16174
- selected.push(member);
16175
- return member;
16176
- }
16177
- };
16178
- const notSelected = (chunk) => {
16179
- const notSelected = chunk.filter((member) => !selected.includes(member));
16180
- if (notSelected.length) {
16181
- selected.push(...notSelected);
16182
- return notSelected;
16183
- }
16184
- };
16185
- const select = (chunk, i) => {
16186
- const member = getMember(chunk, i);
16187
- if (!selected.includes(member)) {
16188
- selected.push(member);
16189
- return member;
16190
- }
16191
- };
16192
- const range = generateRange(1, size + 1);
16193
- for (const division of divisions) {
16194
- if (division === 1) {
16195
- const chunks = chunkArray(range, 2);
16196
- const positions = chunks.map(noneSelected).filter(Boolean);
16197
- if (positions.length)
16198
- divisionGroupings.push(positions);
16199
- const lastPositions = chunks.flatMap(notSelected).filter(Boolean);
16200
- if (lastPositions.length)
16201
- divisionGroupings.push(lastPositions);
16202
- }
16203
- else {
16204
- const chunks = chunkArray(range, division);
16205
- const positions = chunks.map(select).filter(Boolean);
16206
- if (positions.length)
16207
- divisionGroupings.push(positions);
16208
- }
16209
- }
16210
- return { divisions, divisionGroupings };
16211
- }
16212
-
16213
16230
  function getValidSeedBlocks({ provisionalPositioning, returnAllProxies, appliedPolicies, seedingProfile, drawDefinition, allPositions, structure, }) {
16214
16231
  let validSeedBlocks = [];
16215
16232
  if (!structure)
@@ -16399,7 +16416,7 @@ function constructPower2Blocks(params) {
16399
16416
  let count = 1;
16400
16417
  const blocks = [];
16401
16418
  const { seedBlocks } = getSeedBlocks({
16402
- cluster: getSeedPattern(seedingProfile) === CLUSTER,
16419
+ cluster: [CLUSTER, ADJACENT].includes(getSeedPattern(seedingProfile)),
16403
16420
  participantsCount: baseDrawSize,
16404
16421
  roundRobinGroupsCount,
16405
16422
  });
@@ -18855,7 +18872,7 @@ function getUnseededByePositions({ provisionalPositioning, seedOrderByePositions
18855
18872
  if (isFeedIn) {
18856
18873
  const baseDrawSize = relevantDrawPositions.length;
18857
18874
  const { seedBlocks } = getSeedBlocks({
18858
- cluster: getSeedPattern(seedingProfile) === CLUSTER,
18875
+ cluster: [CLUSTER, ADJACENT].includes(getSeedPattern(seedingProfile)),
18859
18876
  participantsCount: baseDrawSize,
18860
18877
  });
18861
18878
  const blockDrawPositions = seedBlocks.map((seedBlock) => seedBlock.map((drawPosition) => drawPosition + drawPositionOffset));
@@ -21671,8 +21688,7 @@ function processPlayoffGroups({ requireSequential = true, playoffMatchUpFormat,
21671
21688
  finishingPositions,
21672
21689
  sourceStructureId,
21673
21690
  });
21674
- links.push(playoffLink);
21675
- links.push(...playoffLinks);
21691
+ links.push(playoffLink, ...playoffLinks);
21676
21692
  structures.push(...playoffStructures);
21677
21693
  finishingPositionTargets.push({
21678
21694
  structureId: playoffStructure.structureId,
@@ -21799,8 +21815,7 @@ function processPlayoffGroups({ requireSequential = true, playoffMatchUpFormat,
21799
21815
  finishingPositions,
21800
21816
  sourceStructureId,
21801
21817
  });
21802
- links.push(playoffLink);
21803
- links.push(...feedInLinks);
21818
+ links.push(playoffLink, ...feedInLinks);
21804
21819
  structures.push(...champitionShipStructures);
21805
21820
  finishingPositionTargets.push({
21806
21821
  structureId: playoffStructure.structureId,
@@ -22015,7 +22030,7 @@ function getRatingConvertedFromELO({ targetRatingType, sourceRating }) {
22015
22030
  sourceRange: eloRatingRange,
22016
22031
  value: sourceRating,
22017
22032
  });
22018
- const convertedRating = parseFloat(result.toFixed(decimalPlaces));
22033
+ const convertedRating = Number.parseFloat(result.toFixed(decimalPlaces));
22019
22034
  return invertedScale ? maxTargetRatingRange - convertedRating : convertedRating;
22020
22035
  }
22021
22036
 
@@ -22066,8 +22081,8 @@ function calculatePressureRatings({ participantResults, sides, score }) {
22066
22081
  }
22067
22082
  }
22068
22083
  function getSideValues$1({ side1ConvertedRating, side2ConvertedRating, score }) {
22069
- const highRating = side1ConvertedRating > side2ConvertedRating ? side1ConvertedRating : side2ConvertedRating;
22070
- const lowRating = side1ConvertedRating > side2ConvertedRating ? side2ConvertedRating : side1ConvertedRating;
22084
+ const highRating = Math.max(side1ConvertedRating, side2ConvertedRating);
22085
+ const lowRating = Math.min(side1ConvertedRating, side2ConvertedRating);
22071
22086
  const ratingsDifference = Math.abs(side1ConvertedRating - side2ConvertedRating);
22072
22087
  const eloRatingRange = ratingsParameters[ELO].range;
22073
22088
  const rangeMax = Math.max(...eloRatingRange);
@@ -22232,19 +22247,19 @@ function calculatePercentages({ participantResults, groupingTotal, matchUpFormat
22232
22247
  ? totalSets
22233
22248
  : perPlayer * (bracketSetsToWin) || setsWon + setsLost;
22234
22249
  let setsPct = Math.round((setsWon / setsTotal) * precision) / precision;
22235
- if (setsPct === Infinity || isNaN(setsPct))
22250
+ if (setsPct === Infinity || Number.isNaN(setsPct))
22236
22251
  setsPct = setsTotal;
22237
22252
  const tieMatchUpsWon = participantResults[participantId].tieMatchUpsWon;
22238
22253
  const tieMatchUpsLost = participantResults[participantId].tieMatchUpsLost;
22239
22254
  const tieMatchUpsTotal = tieMatchUpsWon + tieMatchUpsLost;
22240
22255
  let tieMatchUpsPct = Math.round((tieMatchUpsWon / tieMatchUpsTotal) * precision) / precision;
22241
- if (tieMatchUpsPct === Infinity || isNaN(tieMatchUpsPct))
22256
+ if (tieMatchUpsPct === Infinity || Number.isNaN(tieMatchUpsPct))
22242
22257
  tieMatchUpsPct = tieMatchUpsWon;
22243
22258
  const matchUpsWon = participantResults[participantId].matchUpsWon;
22244
22259
  const matchUpsLost = participantResults[participantId].matchUpsLost;
22245
22260
  const matchUpsTotal = matchUpsWon + matchUpsLost;
22246
22261
  let matchUpsPct = Math.round((matchUpsWon / matchUpsTotal) * precision) / precision;
22247
- if (matchUpsPct === Infinity || isNaN(matchUpsPct))
22262
+ if (matchUpsPct === Infinity || Number.isNaN(matchUpsPct))
22248
22263
  matchUpsPct = matchUpsWon;
22249
22264
  const gamesWon = participantResults[participantId].gamesWon || 0;
22250
22265
  const gamesLost = participantResults[participantId].gamesLost || 0;
@@ -22253,11 +22268,11 @@ function calculatePercentages({ participantResults, groupingTotal, matchUpFormat
22253
22268
  ? totalGames
22254
22269
  : Math.max(minimumExpectedGames, gamesWon + gamesLost);
22255
22270
  let gamesPct = Math.round((gamesWon / gamesTotal) * precision) / precision;
22256
- if (gamesPct === Infinity || isNaN(gamesPct))
22271
+ if (gamesPct === Infinity || Number.isNaN(gamesPct))
22257
22272
  gamesPct = 0;
22258
22273
  const pointsTotal = participantResults[participantId].pointsWon + participantResults[participantId].pointsLost;
22259
22274
  let pointsPct = Math.round((participantResults[participantId].pointsWon / pointsTotal) * precision) / precision;
22260
- if (pointsPct === Infinity || isNaN(pointsPct))
22275
+ if (pointsPct === Infinity || Number.isNaN(pointsPct))
22261
22276
  pointsPct = 0;
22262
22277
  participantResults[participantId].setsWon = setsWon;
22263
22278
  participantResults[participantId].setsLost = setsLost;
@@ -23476,16 +23491,16 @@ function evaluateCollectionResult({ collectionDefinition, groupValueNumbers, gro
23476
23491
  else {
23477
23492
  sideCollectionValues = sideMatchUpValues;
23478
23493
  }
23479
- if (!belongsToValueGroup) {
23480
- sideCollectionValues.forEach((sideCollectionValue, i) => (sideTieValues[i] += sideCollectionValue || 0));
23481
- }
23482
- else {
23494
+ if (belongsToValueGroup) {
23483
23495
  groupValueGroups[collectionGroupNumber].sideWins[0] += sideWins[0] || 0;
23484
23496
  groupValueGroups[collectionGroupNumber].sideWins[1] += sideWins[1] || 0;
23485
23497
  groupValueGroups[collectionGroupNumber].allGroupMatchUpsCompleted =
23486
23498
  groupValueGroups[collectionGroupNumber].allGroupMatchUpsCompleted && allCollectionMatchUpsCompleted;
23487
23499
  groupValueGroups[collectionGroupNumber].matchUpsCount += collectionMatchUps.length;
23488
23500
  }
23501
+ else {
23502
+ sideCollectionValues.forEach((sideCollectionValue, i) => (sideTieValues[i] += sideCollectionValue || 0));
23503
+ }
23489
23504
  }
23490
23505
  function getCollectionPositionValue({ collectionDefinition, collectionPosition }) {
23491
23506
  const collectionValueProfiles = collectionDefinition.collectionValueProfiles || [];
@@ -23497,7 +23512,7 @@ function generateTieMatchUpScore(params) {
23497
23512
  const { sideAdjustments = [0, 0], separator = '-', drawDefinition, matchUpsMap, structure, matchUp, event, } = params;
23498
23513
  if (!Array.isArray(sideAdjustments) ||
23499
23514
  sideAdjustments.length !== 2 ||
23500
- isNaN(sideAdjustments.reduce((a, b) => a + b))) {
23515
+ Number.isNaN(sideAdjustments.reduce((a, b) => a + b))) {
23501
23516
  return { error: INVALID_VALUES };
23502
23517
  }
23503
23518
  if (!matchUp)
@@ -24902,7 +24917,7 @@ function analyzeDraws({ tournamentRecord }) {
24902
24917
  };
24903
24918
  const eventsMap = {};
24904
24919
  const eventDraws = tournamentRecord.events
24905
- ?.map((event) => {
24920
+ ?.flatMap((event) => {
24906
24921
  const eventId = event.eventId;
24907
24922
  eventsMap[eventId] = event;
24908
24923
  return (event?.drawDefinitions || []).map((drawDefinition) => ({
@@ -24910,7 +24925,6 @@ function analyzeDraws({ tournamentRecord }) {
24910
24925
  eventId,
24911
24926
  }));
24912
24927
  })
24913
- .flat()
24914
24928
  .filter(Boolean);
24915
24929
  eventDraws.forEach(({ drawDefinition, eventId }) => {
24916
24930
  let positionsAssignedCount = 0;
@@ -24944,11 +24958,11 @@ function analyzeDraws({ tournamentRecord }) {
24944
24958
  const activeRounds = roundProfile &&
24945
24959
  Object.keys(roundProfile)
24946
24960
  .filter((roundNumber) => !roundProfile[roundNumber].inactiveRound)
24947
- .map((roundNumber) => parseInt(roundNumber));
24961
+ .map((roundNumber) => Number.parseInt(roundNumber));
24948
24962
  const inactiveRounds = roundProfile &&
24949
24963
  Object.keys(roundProfile)
24950
24964
  .filter((roundNumber) => roundProfile[roundNumber].inactiveRound)
24951
- .map((roundNumber) => parseInt(roundNumber));
24965
+ .map((roundNumber) => Number.parseInt(roundNumber));
24952
24966
  const inactiveStructure = roundProfile && Object.values(roundProfile).every((profile) => profile.inactiveRound);
24953
24967
  return {
24954
24968
  positionsAssignedCount: positionsAssigned?.length ?? 0,
@@ -28379,7 +28393,7 @@ const k538 = (countables = 0) => 250 / Math.pow(countables + 5, 0.4);
28379
28393
  const kDefault = () => 1;
28380
28394
  function kSet(maxCountables = 3, counted = 2) {
28381
28395
  const kset = maxCountables / counted;
28382
- return isNaN(kset) ? eloConfig.kDefault() : kset;
28396
+ return Number.isNaN(kset) ? eloConfig.kDefault() : kset;
28383
28397
  }
28384
28398
  const eloConfig = {
28385
28399
  nSpread: 400,
@@ -28400,7 +28414,7 @@ function calculateNewRatings(params) {
28400
28414
  const invertedScale = ratingRange[0] > ratingRange[1];
28401
28415
  const decimalPlaces = ratingParameters.decimalsCount || 0;
28402
28416
  const consideredRange = invertedScale ? ratingRange.slice().reverse() : ratingRange;
28403
- const inRange = (range, value) => parseFloat(value) >= Math.min(...range) && parseFloat(value) <= Math.max(...range);
28417
+ const inRange = (range, value) => Number.parseFloat(value) >= Math.min(...range) && Number.parseFloat(value) <= Math.max(...range);
28404
28418
  if (!inRange(ratingRange, winnerRating) || !inRange(ratingRange, loserRating)) {
28405
28419
  if (!inRange(ratingRange, winnerRating))
28406
28420
  winnerRating = ratingParameters.defaultInitialization;
@@ -28438,9 +28452,9 @@ function calculateNewRatings(params) {
28438
28452
  const updatedWinnerRating = invertedScale
28439
28453
  ? ratingRange[0] - convertedUpdatedWinnerRating
28440
28454
  : convertedUpdatedWinnerRating;
28441
- let newWinnerRating = parseFloat(updatedWinnerRating.toFixed(decimalPlaces));
28455
+ let newWinnerRating = Number.parseFloat(updatedWinnerRating.toFixed(decimalPlaces));
28442
28456
  const updatedLoserRating = invertedScale ? ratingRange[0] - convertedUpdatedLoserRating : convertedUpdatedLoserRating;
28443
- let newLoserRating = parseFloat(updatedLoserRating.toFixed(decimalPlaces));
28457
+ let newLoserRating = Number.parseFloat(updatedLoserRating.toFixed(decimalPlaces));
28444
28458
  const percentageDifference = Math.max(...ratingRange)
28445
28459
  ? Math.abs(winnerRating - loserRating) / Math.max(...ratingRange)
28446
28460
  : 0;
@@ -30447,7 +30461,7 @@ function keyValueScore(params) {
30447
30461
  const { tiebreakTo, NoAD } = tiebreakFormat || {};
30448
30462
  const leadingSide = getLeadingSide({ set });
30449
30463
  if (!analysis.isTiebreakSet) {
30450
- const lowTiebreakScore = parseInt(scoreString.split(open).reverse()[0]);
30464
+ const lowTiebreakScore = Number.parseInt(scoreString.split(open).reverse()[0]);
30451
30465
  const highTiebreakScore = getHighTiebreakValue$1({
30452
30466
  lowValue: lowTiebreakScore,
30453
30467
  tiebreakTo,
@@ -34591,11 +34605,13 @@ function getCompetitionDateRange({ tournamentRecords }) {
34591
34605
  const dateRange = tournamentIds.reduce((dateRange, tournamentId) => {
34592
34606
  const tournamentRecord = tournamentRecords[tournamentId];
34593
34607
  const { tournamentInfo: { startDate, endDate }, } = getTournamentInfo({ tournamentRecord });
34594
- const dateOfStart = startDate && new Date(extractDate(startDate));
34608
+ const extractedStart = startDate && extractDate(startDate);
34609
+ const dateOfStart = extractedStart && new Date(extractedStart);
34595
34610
  if (!dateRange.startDate || (dateOfStart && dateOfStart < dateRange.startDate)) {
34596
34611
  dateRange.startDate = dateOfStart;
34597
34612
  }
34598
- const dateOfEnd = endDate && new Date(extractDate(endDate));
34613
+ const extractedEnd = endDate && extractDate(endDate);
34614
+ const dateOfEnd = extractedEnd && new Date(extractedEnd);
34599
34615
  if (!dateRange.endDate || (dateOfEnd && dateOfEnd > dateRange.endDate)) {
34600
34616
  dateRange.endDate = dateOfEnd;
34601
34617
  }
@@ -36675,7 +36691,31 @@ function getProfileRounds({ tournamentRecords, schedulingProfile, tournamentReco
36675
36691
  return { profileRounds, segmentedRounds };
36676
36692
  }
36677
36693
 
36678
- function courtGridRows({ courtPrefix = 'C|', minRowsCount, courtsData }) {
36694
+ function getCourtDateAvailability({ court, date }) {
36695
+ const targetDateAvailability = date && court.dateAvailability.find((availability) => sameDay(availability.date, date));
36696
+ const defaultAvailability = court.dateAvailability.find((availability) => !availability.date);
36697
+ return targetDateAvailability || defaultAvailability;
36698
+ }
36699
+
36700
+ function getGridBookings({ court, date }) {
36701
+ const courtDate = getCourtDateAvailability({ court, date });
36702
+ const gridBookings = new Map();
36703
+ const timeBookings = [];
36704
+ (courtDate?.bookings || []).forEach((booking) => {
36705
+ if (typeof booking.courtOrder === 'number') {
36706
+ const rowCount = booking.rowCount || 1;
36707
+ for (let i = 0; i < rowCount; i++) {
36708
+ gridBookings.set(booking.courtOrder + i, booking);
36709
+ }
36710
+ }
36711
+ else {
36712
+ timeBookings.push(booking);
36713
+ }
36714
+ });
36715
+ return { gridBookings, timeBookings };
36716
+ }
36717
+
36718
+ function courtGridRows({ courtPrefix = 'C|', minRowsCount, courtsData, scheduledDate }) {
36679
36719
  if (!Array.isArray(courtsData))
36680
36720
  return { error: INVALID_VALUES };
36681
36721
  const maxCourtOrder = courtsData?.reduce((order, court) => {
@@ -36687,7 +36727,21 @@ function courtGridRows({ courtPrefix = 'C|', minRowsCount, courtsData }) {
36687
36727
  const rowBuilder = generateRange(0, rowsCount).map((rowIndex) => ({
36688
36728
  matchUps: generateRange(0, courtsData.length).map((courtIndex) => {
36689
36729
  const courtInfo = courtsData[courtIndex];
36690
- const { courtId, venueId } = courtInfo;
36730
+ const { courtId, venueId, court } = courtInfo;
36731
+ if (scheduledDate && court) {
36732
+ const { gridBookings } = getGridBookings({
36733
+ court,
36734
+ date: scheduledDate,
36735
+ });
36736
+ if (gridBookings.has(rowIndex + 1)) {
36737
+ const booking = gridBookings.get(rowIndex + 1);
36738
+ return {
36739
+ schedule: { courtOrder: rowIndex + 1, venueId, courtId },
36740
+ isBlocked: true,
36741
+ booking,
36742
+ };
36743
+ }
36744
+ }
36691
36745
  return {
36692
36746
  schedule: {
36693
36747
  courtOrder: rowIndex + 1,
@@ -37557,8 +37611,10 @@ function competitionScheduleMatchUps(params) {
37557
37611
  venues,
37558
37612
  };
37559
37613
  if (withCourtGridRows) {
37614
+ const scheduledDate = params.matchUpFilters?.scheduledDate;
37560
37615
  const { rows, courtPrefix } = courtGridRows({
37561
37616
  minRowsCount: Math.max(minCourtGridRows || 0, dateMatchUps.length || 0),
37617
+ scheduledDate,
37562
37618
  courtsData,
37563
37619
  });
37564
37620
  result.courtPrefix = courtPrefix;
@@ -38497,7 +38553,7 @@ function getEvents({ tournamentRecord, withScaleValues, scaleEventType, inContex
38497
38553
  withScaleValues: true,
38498
38554
  tournamentRecord,
38499
38555
  }).participantMap;
38500
- const sum = (values) => values.reduce((total, value) => total + parseFloat(value), 0);
38556
+ const sum = (values) => values.reduce((total, value) => total + Number.parseFloat(value), 0);
38501
38557
  for (const event of eventCopies) {
38502
38558
  const eventType = scaleEventType ?? event.eventType;
38503
38559
  const eventId = event.eventId;
@@ -38518,7 +38574,7 @@ function getEvents({ tournamentRecord, withScaleValues, scaleEventType, inContex
38518
38574
  eventsMap[eventId].ratings[scaleName] = [];
38519
38575
  const accessor = ratingsParameters[scaleName]?.accessor;
38520
38576
  if (accessor) {
38521
- const value = parseFloat(rating.scaleValue?.[accessor]);
38577
+ const value = Number.parseFloat(rating.scaleValue?.[accessor]);
38522
38578
  if (value)
38523
38579
  eventsMap[eventId].ratings[scaleName].push(value);
38524
38580
  }
@@ -38536,15 +38592,15 @@ function getEvents({ tournamentRecord, withScaleValues, scaleEventType, inContex
38536
38592
  };
38537
38593
  for (const participantId of participantIds) {
38538
38594
  const participant = participantMap?.[participantId]?.participant;
38539
- if (participant?.participantType !== INDIVIDUAL) {
38595
+ if (participant?.participantType === INDIVIDUAL) {
38596
+ processParticipant(participant);
38597
+ }
38598
+ else {
38540
38599
  for (const individualParticipantId of participant?.individualParticipantIds ?? []) {
38541
38600
  const individualParticipant = participantMap?.[individualParticipantId]?.participant;
38542
38601
  processParticipant(individualParticipant);
38543
38602
  }
38544
38603
  }
38545
- else {
38546
- processParticipant(participant);
38547
- }
38548
38604
  }
38549
38605
  const ratings = eventsMap[eventId].ratings;
38550
38606
  for (const scaleName of Object.keys(ratings)) {
@@ -38553,8 +38609,8 @@ function getEvents({ tournamentRecord, withScaleValues, scaleEventType, inContex
38553
38609
  continue;
38554
38610
  const med = median(scaleRating)?.toFixed(2);
38555
38611
  eventsMap[eventId].ratingsStats[scaleName] = {
38556
- avg: parseFloat((sum(scaleRating) / scaleRating.length).toFixed(2)),
38557
- median: med ? parseFloat(med) : undefined,
38612
+ avg: Number.parseFloat((sum(scaleRating) / scaleRating.length).toFixed(2)),
38613
+ median: med ? Number.parseFloat(med) : undefined,
38558
38614
  max: Math.max(...scaleRating),
38559
38615
  min: Math.min(...scaleRating),
38560
38616
  };
@@ -38568,7 +38624,7 @@ function getEvents({ tournamentRecord, withScaleValues, scaleEventType, inContex
38568
38624
  eventsMap[eventId].draws[drawId].ratings[scaleName] = [];
38569
38625
  const accessor = ratingsParameters[scaleName]?.accessor;
38570
38626
  if (accessor) {
38571
- const value = parseFloat(rating.scaleValue?.[accessor]);
38627
+ const value = Number.parseFloat(rating.scaleValue?.[accessor]);
38572
38628
  if (value) {
38573
38629
  eventsMap[eventId].draws[drawId].ratings[scaleName].push(value);
38574
38630
  }
@@ -38589,15 +38645,15 @@ function getEvents({ tournamentRecord, withScaleValues, scaleEventType, inContex
38589
38645
  };
38590
38646
  for (const participantId of participantIds.filter(Boolean)) {
38591
38647
  const participant = participantMap?.[participantId]?.participant;
38592
- if (participant?.participantType !== INDIVIDUAL) {
38648
+ if (participant?.participantType === INDIVIDUAL) {
38649
+ processParticipant(participant);
38650
+ }
38651
+ else {
38593
38652
  for (const individualParticipantId of participant?.individualParticipantIds ?? []) {
38594
38653
  const individualParticipant = participantMap?.[individualParticipantId]?.participant;
38595
38654
  processParticipant(individualParticipant);
38596
38655
  }
38597
38656
  }
38598
- else {
38599
- processParticipant(participant);
38600
- }
38601
38657
  }
38602
38658
  };
38603
38659
  const processedDrawIds = [];
@@ -38634,8 +38690,8 @@ function getEvents({ tournamentRecord, withScaleValues, scaleEventType, inContex
38634
38690
  continue;
38635
38691
  const med = median(scaleRating)?.toFixed(2);
38636
38692
  eventsMap[eventId].draws[drawId].ratingsStats[scaleName] = {
38637
- avg: parseFloat((sum(scaleRating) / scaleRating.length).toFixed(2)),
38638
- median: med ? parseFloat(med) : undefined,
38693
+ avg: Number.parseFloat((sum(scaleRating) / scaleRating.length).toFixed(2)),
38694
+ median: med ? Number.parseFloat(med) : undefined,
38639
38695
  max: Math.max(...scaleRating),
38640
38696
  min: Math.min(...scaleRating),
38641
38697
  };
@@ -42085,12 +42141,6 @@ function generateCourts(params) {
42085
42141
  return { ...SUCCESS, courts };
42086
42142
  }
42087
42143
 
42088
- function getCourtDateAvailability({ court, date }) {
42089
- const targetDateAvailability = date && court.dateAvailability.find((availability) => sameDay(availability.date, date));
42090
- const defaultAvailability = court.dateAvailability.find((availability) => !availability.date);
42091
- return targetDateAvailability || defaultAvailability;
42092
- }
42093
-
42094
42144
  function generateTimeSlots(params) {
42095
42145
  const paramsCheck = checkRequiredParameters(params, [{ courtDate: true, _ofType: OBJECT }]);
42096
42146
  if (paramsCheck.error)
@@ -42100,7 +42150,7 @@ function generateTimeSlots(params) {
42100
42150
  let startTime = timeToDate(courtDate.startTime);
42101
42151
  (courtDate.bookings || [])
42102
42152
  .filter((booking) => !booking.bookingType || !includeBookingTypes.includes(booking.bookingType))
42103
- .sort((a, b) => tidyTime(a.startTime).localeCompare(tidyTime(b.startTime)))
42153
+ .sort((a, b) => (tidyTime(a.startTime) || '').localeCompare(tidyTime(b.startTime) || ''))
42104
42154
  .forEach((booking) => {
42105
42155
  const timeSlot = {
42106
42156
  startTime: extractTime$1(startTime.toISOString()),
@@ -42195,11 +42245,11 @@ function generateVirtualCourts(params) {
42195
42245
  const { courtBookings, unassignedBookings } = bookings.reduce((accumulator, booking) => {
42196
42246
  const { courtId } = booking;
42197
42247
  if (courtId) {
42198
- if (!accumulator.courtBookings[courtId]) {
42199
- accumulator.courtBookings[courtId] = [booking];
42248
+ if (accumulator.courtBookings[courtId]) {
42249
+ accumulator.courtBookings[courtId].push(booking);
42200
42250
  }
42201
42251
  else {
42202
- accumulator.courtBookings[courtId].push(booking);
42252
+ accumulator.courtBookings[courtId] = [booking];
42203
42253
  }
42204
42254
  }
42205
42255
  else {
@@ -42233,8 +42283,7 @@ function generateVirtualCourts(params) {
42233
42283
  };
42234
42284
  });
42235
42285
  unassignedBookings.sort((a, b) => timeStringMinutes$1(a.startTime) - timeStringMinutes$1(b.startTime));
42236
- const getCourtTimeSlots = () => inProcessCourts
42237
- .map((court) => {
42286
+ const getCourtTimeSlots = () => inProcessCourts.flatMap((court) => {
42238
42287
  const courtDate = court.dateAvailability;
42239
42288
  const { timeSlots = [] } = generateTimeSlots({ courtDate });
42240
42289
  return {
@@ -42242,8 +42291,7 @@ function generateVirtualCourts(params) {
42242
42291
  courtId: court.courtId,
42243
42292
  timeSlots,
42244
42293
  };
42245
- })
42246
- .flat();
42294
+ });
42247
42295
  const assignedBookings = [];
42248
42296
  for (const unassignedBooking of unassignedBookings) {
42249
42297
  const { startTime, endTime, averageMinutes, recoveryMinutes, matchUpId } = unassignedBooking;
@@ -42340,7 +42388,7 @@ function getFirstTimeSlotStartTime({ averageMinutes, startTime, endTime, courts,
42340
42388
  const available = timeSlotMinutes >= averageMinutes;
42341
42389
  if (available) {
42342
42390
  const timeString = extractTime$1(timeSlotStartTime.toISOString());
42343
- if (!firstTimeSlotStartTime || timeString < firstTimeSlotStartTime) {
42391
+ if (timeString && (!firstTimeSlotStartTime || timeString < firstTimeSlotStartTime)) {
42344
42392
  firstTimeSlotStartTime = timeString;
42345
42393
  }
42346
42394
  }
@@ -45282,15 +45330,15 @@ function addMatchUpScheduleItems(params) {
45282
45330
  let { matchUpDependencies, inContextMatchUps } = params;
45283
45331
  const { errorOnAnachronism = false, checkChronology = true, removePriorValues, tournamentRecords, tournamentRecord, drawDefinition, disableNotice, drawMatchUps, matchUpId, schedule, event, } = params;
45284
45332
  let matchUp, warning;
45285
- if (!drawMatchUps) {
45333
+ if (drawMatchUps) {
45334
+ matchUp = drawMatchUps.find((drawMatchUp) => drawMatchUp.matchUpId === matchUpId);
45335
+ }
45336
+ else {
45286
45337
  const result = findDrawMatchUp({ drawDefinition, event, matchUpId });
45287
45338
  if (result.error)
45288
45339
  return result;
45289
45340
  matchUp = result.matchUp;
45290
45341
  }
45291
- else {
45292
- matchUp = drawMatchUps.find((drawMatchUp) => drawMatchUp.matchUpId === matchUpId);
45293
- }
45294
45342
  const { endTime, courtId, courtIds, courtOrder, resumeTime, homeParticipantId, scheduledDate, scheduledTime, startTime, stopTime, timeModifiers, venueId, } = schedule;
45295
45343
  if (checkChronology && (!matchUpDependencies || !inContextMatchUps)) {
45296
45344
  ({ matchUpDependencies, matchUps: inContextMatchUps } = getMatchUpDependencies({
@@ -45304,11 +45352,11 @@ function addMatchUpScheduleItems(params) {
45304
45352
  priorMatchUpIds.includes(matchUp.matchUpId))
45305
45353
  .map(({ schedule }) => {
45306
45354
  const isoDateString = getIsoDateString(schedule);
45307
- return new Date(isoDateString).getTime();
45355
+ return new Date(isoDateString ?? '').getTime();
45308
45356
  });
45309
45357
  if (priorMatchUpTimes?.length) {
45310
45358
  const isoDateString = getIsoDateString(schedule);
45311
- const matchUpTime = new Date(isoDateString).getTime();
45359
+ const matchUpTime = new Date(isoDateString ?? '').getTime();
45312
45360
  const maxPriorMatchUpTime = Math.max(...priorMatchUpTimes);
45313
45361
  if (maxPriorMatchUpTime >= matchUpTime) {
45314
45362
  if (errorOnAnachronism) {
@@ -45618,8 +45666,8 @@ function addMatchUpStopTime({ removePriorValues, tournamentRecord, drawDefinitio
45618
45666
  const relevantTimeItems = timeItems
45619
45667
  .filter((timeItem) => [START_TIME, RESUME_TIME, STOP_TIME].includes(timeItem?.itemType))
45620
45668
  .sort((a, b) => timeDate(a.itemValue, scheduledDate) - timeDate(b.itemValue, scheduledDate));
45621
- const lastRelevantTimeItem = relevantTimeItems[relevantTimeItems.length - 1];
45622
- const lastRelevantTimeItemIsStop = lastRelevantTimeItem && lastRelevantTimeItem.itemType === STOP_TIME;
45669
+ const lastRelevantTimeItem = relevantTimeItems.at(-1);
45670
+ const lastRelevantTimeItemIsStop = lastRelevantTimeItem?.itemType === STOP_TIME;
45623
45671
  const latestRelevantTimeValue = relevantTimeItems
45624
45672
  .filter((timeItem) => !lastRelevantTimeItemIsStop || timeItem.createdAt !== lastRelevantTimeItem.createdAt)
45625
45673
  .map((timeItem) => timeDate(timeItem.itemValue, scheduledDate))
@@ -45664,8 +45712,8 @@ function addMatchUpResumeTime({ removePriorValues, tournamentRecord, drawDefinit
45664
45712
  const relevantTimeItems = timeItems
45665
45713
  .filter((timeItem) => [START_TIME, RESUME_TIME, STOP_TIME].includes(timeItem?.itemType))
45666
45714
  .sort((a, b) => timeDate(a.itemValue, scheduledDate) - timeDate(b.itemValue, scheduledDate));
45667
- const lastRelevantTimeItem = relevantTimeItems[relevantTimeItems.length - 1];
45668
- const lastRelevantTimeItemIsResume = lastRelevantTimeItem && lastRelevantTimeItem.itemType === RESUME_TIME;
45715
+ const lastRelevantTimeItem = relevantTimeItems.at(-1);
45716
+ const lastRelevantTimeItemIsResume = lastRelevantTimeItem?.itemType === RESUME_TIME;
45669
45717
  const latestRelevantTimeValue = relevantTimeItems
45670
45718
  .filter((timeItem) => !lastRelevantTimeItemIsResume || timeItem.createdAt !== lastRelevantTimeItem.createdAt)
45671
45719
  .map((timeItem) => timeDate(timeItem.itemValue, scheduledDate))
@@ -47432,7 +47480,9 @@ function updateTimeAfterRecovery({ matchUpPotentialParticipantIds, individualPar
47432
47480
  participantId,
47433
47481
  });
47434
47482
  const matchUpTypeChange = individualParticipantProfiles[participantId].priorMatchUpType !== matchUp.matchUpType;
47435
- const recoveryValue = matchUpTypeChange ? typeChangeTimeAfterRecovery || timeAfterRecovery : timeAfterRecovery;
47483
+ const recoveryValue = matchUpTypeChange
47484
+ ? typeChangeTimeAfterRecovery || timeAfterRecovery
47485
+ : timeAfterRecovery;
47436
47486
  if (potentialIndividualParticipantIds.includes(participantId)) {
47437
47487
  addParticipantPotentialRecovery({
47438
47488
  individualParticipantProfiles,
@@ -47521,22 +47571,23 @@ function checkRequestConflicts({ averageMatchUpMinutes = 90, requestConflicts =
47521
47571
  const averageEnd = extractTime$1(addMinutes(scheduleStart, averageMatchUpMinutes).toISOString());
47522
47572
  for (const request of relevantPersonRequests) {
47523
47573
  const { requestId, startTime, endTime } = request;
47524
- const conflict = (scheduleTime > startTime && scheduleTime < endTime) || (averageEnd > startTime && averageEnd < endTime);
47574
+ const conflict = (scheduleTime > startTime && scheduleTime < endTime) ||
47575
+ (averageEnd && averageEnd > startTime && averageEnd < endTime);
47525
47576
  if (conflict) {
47526
47577
  conflicts.push({ matchUpId, request, scheduleTime });
47527
- if (!requestConflicts[requestId]) {
47578
+ if (requestConflicts[requestId]) {
47579
+ if (!requestConflicts[requestId].scheduleTimes.includes(scheduleTime))
47580
+ requestConflicts[requestId].scheduleTimes.push(scheduleTime);
47581
+ if (!requestConflicts[requestId].matchUpIds.includes(matchUpId))
47582
+ requestConflicts[requestId].matchUpIds.push(matchUpId);
47583
+ }
47584
+ else {
47528
47585
  requestConflicts[requestId] = {
47529
47586
  request,
47530
47587
  scheduleTimes: [scheduleTime],
47531
47588
  matchUpIds: [matchUpId],
47532
47589
  };
47533
47590
  }
47534
- else {
47535
- if (!requestConflicts[requestId].scheduleTimes.includes(scheduleTime))
47536
- requestConflicts[requestId].scheduleTimes.push(scheduleTime);
47537
- if (!requestConflicts[requestId].matchUpIds.includes(matchUpId))
47538
- requestConflicts[requestId].matchUpIds.push(matchUpId);
47539
- }
47540
47591
  }
47541
47592
  }
47542
47593
  return { conflicts };
@@ -48421,7 +48472,7 @@ function getEarliestCourtTime({ averageMinutes, startTime, endTime, court, date
48421
48472
  const available = timeSlotMinutes >= averageMinutes;
48422
48473
  if (available) {
48423
48474
  const timeString = extractTime$1(consideredStartTime.toISOString());
48424
- if (!first || timeString < first)
48475
+ if (timeString && (!first || timeString < first))
48425
48476
  first = timeString;
48426
48477
  }
48427
48478
  return first;
@@ -49662,7 +49713,7 @@ function generatePersonData(params) {
49662
49713
  function generatePersons(params) {
49663
49714
  let count = params?.count || 1;
49664
49715
  const { personExtensions, consideredDate, isMock = true, gendersCount, personData, category, sex } = params || {};
49665
- if (isNaN(count))
49716
+ if (Number.isNaN(Number(count)))
49666
49717
  return { error: INVALID_VALUES };
49667
49718
  const maleCount = gendersCount?.[MALE] || (isMale(sex) && count) || 0;
49668
49719
  const femaleCount = gendersCount?.[FEMALE] || (isFemale(sex) && count) || 0;
@@ -49702,7 +49753,7 @@ function generatePersons(params) {
49702
49753
  if (person.nationalityCode &&
49703
49754
  (typeof person.nationalityCode !== 'string' ||
49704
49755
  person.nationalityCode.length > 3 ||
49705
- !countries.find(({ iso, ioc }) => [iso, ioc].includes(person.nationalityCode))))
49756
+ !countries.some(({ iso, ioc }) => [iso, ioc].includes(person.nationalityCode))))
49706
49757
  return false;
49707
49758
  if (person.nationalityCode)
49708
49759
  nationalityCodes.push(person.nationalityCode);
@@ -50410,7 +50461,9 @@ function generateOutcome(params) {
50410
50461
  return { error: INVALID_VALUES };
50411
50462
  if (defaultWithScorePercent > 100)
50412
50463
  defaultWithScorePercent = 100;
50413
- if (isNaN(defaultWithScorePercent) || isNaN(pointsPerMinute) || isNaN(sideWeight))
50464
+ if (Number.isNaN(Number(defaultWithScorePercent)) ||
50465
+ Number.isNaN(Number(pointsPerMinute)) ||
50466
+ Number.isNaN(Number(sideWeight)))
50414
50467
  return { error: INVALID_VALUES };
50415
50468
  const matchUpStatuses = Object.keys(matchUpStatusProfile).filter((matchUpStatus) => Object.keys(matchUpStatusConstants).includes(matchUpStatus) && matchUpStatus !== COMPLETED$1);
50416
50469
  const matchUpStatusTotals = Object.keys(matchUpStatuses).reduce((total, key) => total + matchUpStatusProfile[key], 0);
@@ -50531,9 +50584,7 @@ function generateSet({ weightedRange = [0, 1], pointsPerMinute, matchUpStatus, i
50531
50584
  return { set, incomplete, winningSideNumber };
50532
50585
  }
50533
50586
  else {
50534
- const range = generateRange(1, setTo + 1)
50535
- .map((value) => generateRange(0, setTo + 2 - value).map(() => value))
50536
- .flat();
50587
+ const range = generateRange(1, setTo + 1).flatMap((value) => generateRange(0, setTo + 2 - value).map(() => value));
50537
50588
  const lowValue = range[randomInt(0, range.length - 1)];
50538
50589
  const scores = setTo &&
50539
50590
  getSetComplement({
@@ -50563,9 +50614,7 @@ function generateSet({ weightedRange = [0, 1], pointsPerMinute, matchUpStatus, i
50563
50614
  let tiebreakWinningSide;
50564
50615
  if (setAnalysis.hasTiebreakCondition || isTiebreakSet) {
50565
50616
  const { NoAD: tiebreakNoAd, tiebreakTo } = tiebreakFormat || tiebreakSet || {};
50566
- const range = generateRange(1, tiebreakTo + 1)
50567
- .map((value) => generateRange(0, tiebreakTo + 2 - value).map(() => value))
50568
- .flat();
50617
+ const range = generateRange(1, tiebreakTo + 1).flatMap((value) => generateRange(0, tiebreakTo + 2 - value).map(() => value));
50569
50618
  const lowValue = range[randomInt(0, range.length - 1)];
50570
50619
  const scores = getTiebreakComplement({
50571
50620
  isSide1: true,
@@ -55105,7 +55154,7 @@ function proAutoSchedule({ scheduleCompletedMatchUps, tournamentRecords, schedul
55105
55154
  }
55106
55155
  }
55107
55156
  });
55108
- const availableCourts = Object.values(row).filter((c) => isObject(c) && !c.matchUpId);
55157
+ const availableCourts = Object.values(row).filter((c) => isObject(c) && !c.matchUpId && !c.isBlocked);
55109
55158
  return gridRows.concat({
55110
55159
  matchUpIds,
55111
55160
  availableCourts,
@@ -56024,8 +56073,151 @@ function setMatchUpDailyLimits(params) {
56024
56073
  return { ...SUCCESS };
56025
56074
  }
56026
56075
 
56076
+ function addCourtGridBooking(params) {
56077
+ const { tournamentRecord, disableNotice, scheduledDate, bookingType, courtOrder, rowCount = 1, courtId, notes, } = params;
56078
+ if (!tournamentRecord) {
56079
+ return decorateResult({
56080
+ result: { error: INVALID_VALUES },
56081
+ info: 'tournamentRecord is required',
56082
+ });
56083
+ }
56084
+ if (!courtId) {
56085
+ return { error: COURT_NOT_FOUND };
56086
+ }
56087
+ if (!scheduledDate) {
56088
+ return decorateResult({
56089
+ result: { error: INVALID_VALUES },
56090
+ info: 'scheduledDate is required',
56091
+ });
56092
+ }
56093
+ if (!bookingType) {
56094
+ return decorateResult({
56095
+ result: { error: INVALID_VALUES },
56096
+ info: 'bookingType is required',
56097
+ });
56098
+ }
56099
+ if (courtOrder === undefined || courtOrder === null) {
56100
+ return decorateResult({
56101
+ result: { error: INVALID_VALUES },
56102
+ info: 'courtOrder is required',
56103
+ });
56104
+ }
56105
+ if (!Number.isInteger(courtOrder) || courtOrder < 1) {
56106
+ return decorateResult({
56107
+ result: { error: INVALID_VALUES },
56108
+ info: 'courtOrder must be a positive integer',
56109
+ });
56110
+ }
56111
+ if (!Number.isInteger(rowCount) || rowCount < 1) {
56112
+ return decorateResult({
56113
+ result: { error: INVALID_VALUES },
56114
+ info: 'rowCount must be a positive integer',
56115
+ });
56116
+ }
56117
+ const { court, venue } = findCourt({ tournamentRecord, courtId });
56118
+ if (!court)
56119
+ return { error: COURT_NOT_FOUND };
56120
+ const courtDate = getCourtDateAvailability({ court, date: scheduledDate });
56121
+ if (!courtDate) {
56122
+ if (!court.dateAvailability)
56123
+ court.dateAvailability = [];
56124
+ const newAvailability = {
56125
+ date: scheduledDate,
56126
+ bookings: [],
56127
+ };
56128
+ court.dateAvailability.push(newAvailability);
56129
+ }
56130
+ const targetCourtDate = getCourtDateAvailability({ court, date: scheduledDate });
56131
+ if (targetCourtDate.bookings) {
56132
+ for (const existingBooking of targetCourtDate.bookings) {
56133
+ if (typeof existingBooking.courtOrder === 'number') {
56134
+ const existingStart = existingBooking.courtOrder;
56135
+ const existingEnd = existingStart + (existingBooking.rowCount || 1) - 1;
56136
+ const newStart = courtOrder;
56137
+ const newEnd = courtOrder + rowCount - 1;
56138
+ if (newStart <= existingEnd && newEnd >= existingStart) {
56139
+ return decorateResult({
56140
+ result: { error: EXISTING_MATCHUPS },
56141
+ info: `Booking conflicts with existing booking at rows ${existingStart}-${existingEnd}`,
56142
+ });
56143
+ }
56144
+ }
56145
+ }
56146
+ }
56147
+ const booking = {
56148
+ courtOrder,
56149
+ rowCount,
56150
+ bookingType,
56151
+ notes,
56152
+ createdAt: new Date().toISOString(),
56153
+ };
56154
+ if (!targetCourtDate.bookings)
56155
+ targetCourtDate.bookings = [];
56156
+ targetCourtDate.bookings.push(booking);
56157
+ if (!disableNotice && venue) {
56158
+ addNotice({
56159
+ payload: { venue, tournamentId: tournamentRecord.tournamentId },
56160
+ topic: MODIFY_VENUE,
56161
+ key: venue.venueId,
56162
+ });
56163
+ }
56164
+ return { ...SUCCESS, booking };
56165
+ }
56166
+
56167
+ function removeCourtGridBooking(params) {
56168
+ const { tournamentRecord, disableNotice, scheduledDate, courtOrder, courtId, } = params;
56169
+ if (!tournamentRecord) {
56170
+ return decorateResult({
56171
+ result: { error: INVALID_VALUES },
56172
+ info: 'tournamentRecord is required',
56173
+ });
56174
+ }
56175
+ if (!courtId) {
56176
+ return { error: COURT_NOT_FOUND };
56177
+ }
56178
+ if (!scheduledDate) {
56179
+ return decorateResult({
56180
+ result: { error: INVALID_VALUES },
56181
+ info: 'scheduledDate is required',
56182
+ });
56183
+ }
56184
+ if (courtOrder === undefined || courtOrder === null) {
56185
+ return decorateResult({
56186
+ result: { error: INVALID_VALUES },
56187
+ info: 'courtOrder is required',
56188
+ });
56189
+ }
56190
+ const { court, venue } = findCourt({ tournamentRecord, courtId });
56191
+ if (!court)
56192
+ return { error: COURT_NOT_FOUND };
56193
+ const courtDate = getCourtDateAvailability({ court, date: scheduledDate });
56194
+ if (!courtDate?.bookings) {
56195
+ return decorateResult({
56196
+ result: { error: BOOKING_NOT_FOUND },
56197
+ info: 'No bookings found for this date',
56198
+ });
56199
+ }
56200
+ const bookingIndex = courtDate.bookings.findIndex((b) => b.courtOrder === courtOrder);
56201
+ if (bookingIndex === -1) {
56202
+ return decorateResult({
56203
+ result: { error: BOOKING_NOT_FOUND },
56204
+ info: `No booking found at row ${courtOrder}`,
56205
+ });
56206
+ }
56207
+ const removed = courtDate.bookings.splice(bookingIndex, 1)[0];
56208
+ if (!disableNotice && venue) {
56209
+ addNotice({
56210
+ payload: { venue, tournamentId: tournamentRecord.tournamentId },
56211
+ topic: MODIFY_VENUE,
56212
+ key: venue.venueId,
56213
+ });
56214
+ }
56215
+ return { ...SUCCESS, booking: removed };
56216
+ }
56217
+
56027
56218
  var mutate$3 = {
56028
56219
  __proto__: null,
56220
+ addCourtGridBooking: addCourtGridBooking,
56029
56221
  addMatchUpCourtOrder: addMatchUpCourtOrder,
56030
56222
  addMatchUpEndTime: addMatchUpEndTime,
56031
56223
  addMatchUpOfficial: addMatchUpOfficial,
@@ -56053,6 +56245,7 @@ var mutate$3 = {
56053
56245
  modifyMatchUpFormatTiming: modifyMatchUpFormatTiming,
56054
56246
  proAutoSchedule: proAutoSchedule,
56055
56247
  proConflicts: proConflicts,
56248
+ removeCourtGridBooking: removeCourtGridBooking,
56056
56249
  removeEventMatchUpFormatTiming: removeEventMatchUpFormatTiming,
56057
56250
  removeMatchUpCourtAssignment: removeMatchUpCourtAssignment,
56058
56251
  reorderUpcomingMatchUps: reorderUpcomingMatchUps,
@@ -56067,6 +56260,7 @@ var mutate$3 = {
56067
56260
 
56068
56261
  var index$5 = {
56069
56262
  __proto__: null,
56263
+ addCourtGridBooking: addCourtGridBooking,
56070
56264
  addMatchUpCourtOrder: addMatchUpCourtOrder,
56071
56265
  addMatchUpEndTime: addMatchUpEndTime,
56072
56266
  addMatchUpOfficial: addMatchUpOfficial,
@@ -56105,6 +56299,7 @@ var index$5 = {
56105
56299
  proConflicts: proConflicts,
56106
56300
  publicFindCourt: publicFindCourt,
56107
56301
  query: query$4,
56302
+ removeCourtGridBooking: removeCourtGridBooking,
56108
56303
  removeEventMatchUpFormatTiming: removeEventMatchUpFormatTiming,
56109
56304
  removeMatchUpCourtAssignment: removeMatchUpCourtAssignment,
56110
56305
  reorderUpcomingMatchUps: reorderUpcomingMatchUps,