tods-competition-factory 1.8.2 → 1.8.4

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.
@@ -319,7 +319,7 @@ function groupConsecutiveNumbers(arr) {
319
319
  return result;
320
320
  }, []);
321
321
  }
322
- function allNumeric(arr) {
322
+ function allNumeric$1(arr) {
323
323
  return arr.reduce((numeric, item) => !isNaN(parseInt(item)) && numeric, true);
324
324
  }
325
325
  function noNumeric(arr) {
@@ -587,6 +587,10 @@ const MISSING_VALUE = {
587
587
  message: "Missing value",
588
588
  code: "ERR_MISSING_VALUE"
589
589
  };
590
+ const INVALID_DATE = {
591
+ message: "Invalid Date",
592
+ code: "ERR_INVALID_DATE"
593
+ };
590
594
  const INVALID_PARTICIPANT_ID = {
591
595
  message: "Invalid participantId",
592
596
  code: "ERR_INVALID_PARTICIPANT_ID"
@@ -703,10 +707,18 @@ const INVALID_CONFIGURATION = {
703
707
  message: "Invalid configuration",
704
708
  code: "ERR_INVALID_CONFIG"
705
709
  };
710
+ const INVALID_COLLECTION_DEFINITION = {
711
+ message: "Invalid collectionDefinition",
712
+ code: "ERR_INVALID_COLLECTION_DEFINITION"
713
+ };
706
714
  const INVALID_OBJECT = {
707
715
  message: "Invalid object",
708
716
  code: "ERR_INVALID_OBJECT"
709
717
  };
718
+ const INVALID_CATEGORY = {
719
+ message: "Invalid category",
720
+ code: "ERR_INVALID_CATEGORY"
721
+ };
710
722
  const INVALID_VALUES = {
711
723
  message: "Invalid values",
712
724
  code: "ERR_INVALID_VALUES"
@@ -933,7 +945,11 @@ function deleteNotice({ key, topic }) {
933
945
  function getTopics() {
934
946
  return _globalStateProvider.getTopics();
935
947
  }
948
+ function getProvider() {
949
+ return _globalStateProvider;
950
+ }
936
951
 
952
+ const validDateString = /^[\d]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][\d]|3[0-1])$/;
937
953
  const validTimeString = /^((0[\d]|1[\d]|2[0-3]):[0-5][\d](:[0-5][\d])?)([.,][0-9]{3})?$/;
938
954
  const dateValidation = /^([\d]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][\d]|3[0-1]))([ T](0[\d]|1[\d]|2[0-3]):[0-5][\d](:[0-5][\d])?)?([.,][\d]{3})?Z?$/;
939
955
 
@@ -957,6 +973,9 @@ function isDateObject(value) {
957
973
  return datePrototype === "[object Date]";
958
974
  }
959
975
  }
976
+ function isValidDateString(scheduleDate) {
977
+ return isISODateString(scheduleDate) || validDateString.test(scheduleDate);
978
+ }
960
979
  const getUTCdateString = (date) => {
961
980
  const dateDate = isDate(date) || isISODateString(date) ? new Date(date) : /* @__PURE__ */ new Date();
962
981
  const monthNumber = dateDate.getUTCMonth() + 1;
@@ -1007,6 +1026,11 @@ function extractTime(dateString) {
1007
1026
  function extractDate(dateString) {
1008
1027
  return isISODateString(dateString) || dateValidation.test(dateString) ? dateString.split("T")[0] : void 0;
1009
1028
  }
1029
+ function dateStringDaysChange(dateString, daysChange) {
1030
+ const date = new Date(dateString);
1031
+ date.setDate(date.getDate() + daysChange);
1032
+ return extractDate(date.toISOString());
1033
+ }
1010
1034
  function splitTime(value) {
1011
1035
  value = typeof value !== "string" ? "00:00" : value;
1012
1036
  const o = {}, time = {};
@@ -1060,6 +1084,13 @@ function sameDay(date1, date2) {
1060
1084
  }
1061
1085
 
1062
1086
  function makeDeepCopy(sourceObject, convertExtensions, internalUse, removeExtensions, iteration = 0) {
1087
+ if (getProvider().makeDeepCopy)
1088
+ return getProvider().makeDeepCopy(
1089
+ sourceObject,
1090
+ convertExtensions,
1091
+ internalUse,
1092
+ removeExtensions
1093
+ );
1063
1094
  const deepCopy = deepCopyEnabled();
1064
1095
  const { stringify, toJSON, ignore, modulate } = deepCopy || {};
1065
1096
  if (!deepCopy?.enabled && !internalUse || typeof sourceObject !== "object" || typeof sourceObject === "function" || sourceObject === null || typeof deepCopy?.threshold === "number" && iteration >= deepCopy.threshold) {
@@ -3170,20 +3201,20 @@ const ROUND_ROBIN_WITH_PLAYOFF = "ROUND_ROBIN_WITH_PLAYOFF";
3170
3201
  const DECIDER = "DECIDER";
3171
3202
  const BACKDRAW = "BACKDRAW";
3172
3203
  const COMPASS_ATTRIBUTES = {
3173
- 0: { name: "EAST", abbreviation: "E" },
3174
- "0-1": { name: "WEST", abbreviation: "W" },
3175
- "0-2": { name: "NORTH", abbreviation: "N" },
3176
- "0-3": { name: "NORTHEAST", abbreviation: "NE" },
3177
- "0-1-1": { name: "SOUTH", abbreviation: "S" },
3178
- "0-1-2": { name: "SOUTHWEST", abbreviation: "SW" },
3179
- "0-2-1": { name: "NORTHWEST", abbreviation: "NW" },
3180
- "0-1-1-1": { name: "SOUTHEAST", abbreviation: "SE" }
3204
+ 0: { name: "East", abbreviation: "E" },
3205
+ "0-1": { name: "West", abbreviation: "W" },
3206
+ "0-2": { name: "North", abbreviation: "N" },
3207
+ "0-3": { name: "Northeast", abbreviation: "NE" },
3208
+ "0-1-1": { name: "South", abbreviation: "S" },
3209
+ "0-1-2": { name: "Southwest", abbreviation: "SW" },
3210
+ "0-2-1": { name: "Northwest", abbreviation: "NW" },
3211
+ "0-1-1-1": { name: "Southeast", abbreviation: "SE" }
3181
3212
  };
3182
3213
  const OLYMPIC_ATTRIBUTES = {
3183
- 0: { name: "EAST", abbreviation: "E" },
3184
- "0-1": { name: "WEST", abbreviation: "W" },
3185
- "0-2": { name: "NORTH", abbreviation: "N" },
3186
- "0-1-1": { name: "SOUTH", abbreviation: "S" }
3214
+ 0: { name: "East", abbreviation: "E" },
3215
+ "0-1": { name: "West", abbreviation: "W" },
3216
+ "0-2": { name: "North", abbreviation: "N" },
3217
+ "0-1-1": { name: "South", abbreviation: "S" }
3187
3218
  };
3188
3219
  const WIN_RATIO = "WIN_RATIO";
3189
3220
  const ROUND_OUTCOME = "ROUND_OUTCOME";
@@ -3893,7 +3924,7 @@ function getOrderedDrawPositions({
3893
3924
  (pair) => overlap(pair || [], drawPositions.filter(Boolean))
3894
3925
  ) || unassignedDrawPositions;
3895
3926
  const isFeedRound = targetRoundProfile?.feedRound;
3896
- if (allNumeric(drawPositions)) {
3927
+ if (allNumeric$1(drawPositions)) {
3897
3928
  const orderedDrawPositions = drawPositions.sort(numericSort);
3898
3929
  return {
3899
3930
  orderedDrawPositions: orderedDrawPositions.length === 2 ? orderedDrawPositions : displayOrder,
@@ -5035,21 +5066,25 @@ function groupRounds({ groupSize, drawPositionOffset }) {
5035
5066
  );
5036
5067
  }
5037
5068
 
5038
- function generateRoundRobin({
5039
- structureName = constantToString(MAIN),
5040
- stageSequence = 1,
5041
- structureOptions,
5042
- appliedPolicies,
5043
- seedingProfile,
5044
- stage = MAIN,
5045
- matchUpType,
5046
- roundTarget,
5047
- structureId,
5048
- drawSize,
5049
- idPrefix,
5050
- isMock,
5051
- uuids
5052
- }) {
5069
+ function generateRoundRobin(params) {
5070
+ const {
5071
+ groupNameBase = "Group",
5072
+ playoffAttributes,
5073
+ stageSequence = 1,
5074
+ structureOptions,
5075
+ appliedPolicies,
5076
+ seedingProfile,
5077
+ stage = MAIN,
5078
+ matchUpType,
5079
+ roundTarget,
5080
+ structureId,
5081
+ groupNames,
5082
+ drawSize,
5083
+ idPrefix,
5084
+ isMock,
5085
+ uuids
5086
+ } = params;
5087
+ const structureName = params.structureName ?? playoffAttributes?.["0"]?.name ?? constantToString(MAIN);
5053
5088
  const { groupCount, groupSize } = deriveGroups({
5054
5089
  structureOptions,
5055
5090
  appliedPolicies,
@@ -5069,12 +5104,13 @@ function generateRoundRobin({
5069
5104
  maxRoundNumber = Math.max(
5070
5105
  ...matchUps.map(({ roundNumber }) => roundNumber)
5071
5106
  );
5107
+ const structureName2 = groupNames?.[structureOrder - 1] ?? `${groupNameBase} ${structureOrder}`;
5072
5108
  return structureTemplate({
5073
- structureName: `Group ${structureOrder}`,
5074
5109
  structureId: uuids?.pop(),
5075
5110
  structureType: ITEM,
5076
5111
  finishingPosition,
5077
5112
  structureOrder,
5113
+ structureName: structureName2,
5078
5114
  matchUps
5079
5115
  });
5080
5116
  });
@@ -13964,6 +14000,7 @@ function treeMatchUps({
13964
14000
  function firstRoundLoserConsolation(params) {
13965
14001
  const {
13966
14002
  finishingPositionOffset = 0,
14003
+ playoffAttributes,
13967
14004
  stageSequence = 1,
13968
14005
  staggeredEntry,
13969
14006
  structureName,
@@ -13985,7 +14022,7 @@ function firstRoundLoserConsolation(params) {
13985
14022
  };
13986
14023
  const { matchUps } = staggeredEntry ? feedInMatchUps(mainParams) : treeMatchUps(mainParams);
13987
14024
  const mainStructure = structureTemplate({
13988
- structureName: structureName || constantToString(MAIN),
14025
+ structureName: structureName || playoffAttributes?.["0"]?.name || constantToString(MAIN),
13989
14026
  structureId: structureId || uuids?.pop(),
13990
14027
  stageSequence,
13991
14028
  matchUpType,
@@ -14004,7 +14041,7 @@ function firstRoundLoserConsolation(params) {
14004
14041
  isMock
14005
14042
  });
14006
14043
  const consolation = constantToString(CONSOLATION);
14007
- const consolationStructureName = params.consolationStructureName || (structureName ? `${structureName} ${consolation}` : consolation);
14044
+ const consolationStructureName = playoffAttributes?.["0-1"]?.name ?? params.consolationStructureName ?? (structureName ? `${structureName} ${consolation}` : consolation);
14008
14045
  const consolationStructure = structureTemplate({
14009
14046
  structureName: consolationStructureName,
14010
14047
  matchUps: consolationMatchUps,
@@ -14082,10 +14119,10 @@ function feedInLinks({
14082
14119
 
14083
14120
  function generateCurtisConsolation(params) {
14084
14121
  const {
14085
- structureName = constantToString(MAIN),
14086
14122
  playoffStructureNameBase,
14087
14123
  finishingPositionOffset,
14088
14124
  stageSequence = 1,
14125
+ playoffAttributes,
14089
14126
  structureNameMap,
14090
14127
  staggeredEntry,
14091
14128
  stage = MAIN,
@@ -14105,6 +14142,7 @@ function generateCurtisConsolation(params) {
14105
14142
  uuids
14106
14143
  };
14107
14144
  const { matchUps, roundsCount: mainDrawRoundsCount } = staggeredEntry ? feedInMatchUps(mainParams) : treeMatchUps(mainParams);
14145
+ const structureName = params.structureName ?? playoffAttributes?.["0"]?.name ?? constantToString(MAIN);
14108
14146
  const mainStructure = structureTemplate({
14109
14147
  structureId: structureId || uuids?.pop(),
14110
14148
  structureName,
@@ -14123,6 +14161,7 @@ function generateCurtisConsolation(params) {
14123
14161
  idPrefix: idPrefix && `${idPrefix}-c${index}`,
14124
14162
  structureId: uuids?.pop(),
14125
14163
  playoffStructureNameBase,
14164
+ playoffAttributes,
14126
14165
  structureNameMap,
14127
14166
  stageSequence: stageSequence2,
14128
14167
  roundOffset,
@@ -14151,7 +14190,7 @@ function generateCurtisConsolation(params) {
14151
14190
  matchUpType,
14152
14191
  isMock
14153
14192
  });
14154
- const defaultName = constantToString(PLAY_OFF);
14193
+ const defaultName = playoffAttributes?.["3-4"]?.name ?? constantToString(PLAY_OFF);
14155
14194
  const mappedStructureName = structureNameMap?.[defaultName] || defaultName;
14156
14195
  const structureName2 = playoffStructureNameBase ? `${playoffStructureNameBase} ${mappedStructureName}` : mappedStructureName;
14157
14196
  const playoffStructure = structureTemplate({
@@ -14183,6 +14222,7 @@ function generateCurtisConsolation(params) {
14183
14222
  function consolationFeedStructure({
14184
14223
  playoffStructureNameBase,
14185
14224
  stageSequence = 1,
14225
+ playoffAttributes,
14186
14226
  structureNameMap,
14187
14227
  roundOffset = 0,
14188
14228
  matchUpType,
@@ -14204,7 +14244,8 @@ function consolationFeedStructure({
14204
14244
  isMock,
14205
14245
  uuids
14206
14246
  });
14207
- const defaultName = `${constantToString(CONSOLATION)} ${index + 1}`;
14247
+ const indexedStructureName = index === 0 && playoffAttributes?.["0-1"]?.name || index === 1 && playoffAttributes?.["0-3"]?.name;
14248
+ const defaultName = indexedStructureName || `${constantToString(CONSOLATION)} ${index + 1}`;
14208
14249
  const mappedStructureName = structureNameMap?.[defaultName] || defaultName;
14209
14250
  const structureName = playoffStructureNameBase ? `${playoffStructureNameBase} ${mappedStructureName}` : mappedStructureName;
14210
14251
  const consolationStructure = structureTemplate({
@@ -14254,8 +14295,8 @@ function generatePlayoffStructures(params) {
14254
14295
  const finishingPositionRange = `${finishingPositionsFrom}-${finishingPositionsTo}`;
14255
14296
  const attributeProfile = playoffAttributes?.[exitProfile];
14256
14297
  const base = playoffStructureNameBase && `${playoffStructureNameBase} ` || "";
14257
- const customNaming = finishingPositionNaming?.[finishingPositionRange];
14258
- const structureName = customNaming?.name || attributeProfile?.name && (addNameBaseToAttributeName ? `${base}${attributeProfile?.name}` : attributeProfile.name) || `${base}${finishingPositionRange}`;
14298
+ const customNaming = playoffAttributes?.[finishingPositionRange] ?? finishingPositionNaming?.[finishingPositionRange];
14299
+ const structureName = params.structureName || customNaming?.name || attributeProfile?.name && (addNameBaseToAttributeName ? `${base}${attributeProfile?.name}` : attributeProfile.name) || `${base}${finishingPositionRange}`;
14259
14300
  const structureAbbreviation = customNaming?.abbreviation || attributeProfile?.abbreviation;
14260
14301
  const mainParams = {
14261
14302
  idPrefix: idPrefix && `${idPrefix}-${structureName}-RP`,
@@ -14359,6 +14400,7 @@ function feedInChampionship(params) {
14359
14400
  const {
14360
14401
  finishingPositionOffset,
14361
14402
  stageSequence = 1,
14403
+ playoffAttributes,
14362
14404
  policyDefinitions,
14363
14405
  feedsFromFinal,
14364
14406
  staggeredEntry,
@@ -14386,7 +14428,7 @@ function feedInChampionship(params) {
14386
14428
  };
14387
14429
  const { matchUps } = staggeredEntry ? feedInMatchUps(mainParams) : treeMatchUps(mainParams);
14388
14430
  const mainStructure = structureTemplate({
14389
- structureName: structureName || constantToString(MAIN),
14431
+ structureName: structureName || playoffAttributes?.["0"]?.name || constantToString(MAIN),
14390
14432
  structureId: structureId || uuids?.pop(),
14391
14433
  stageSequence,
14392
14434
  matchUpType,
@@ -14410,12 +14452,14 @@ function feedInChampionship(params) {
14410
14452
  fmlc
14411
14453
  });
14412
14454
  if (drawSize > 2) {
14455
+ const name = playoffAttributes?.["0-1"]?.name ?? constantToString(CONSOLATION);
14456
+ const structureName2 = params.playoffStructureNameBase ? `${params.playoffStructureNameBase} ${name}` : name;
14413
14457
  const consolationStructure = structureTemplate({
14414
- structureName: constantToString(CONSOLATION),
14415
14458
  matchUps: consolationMatchUps,
14416
14459
  structureId: uuids?.pop(),
14417
14460
  stage: CONSOLATION,
14418
14461
  stageSequence: 1,
14462
+ structureName: structureName2,
14419
14463
  matchUpType
14420
14464
  });
14421
14465
  structures.push(consolationStructure);
@@ -14436,10 +14480,9 @@ function feedInChampionship(params) {
14436
14480
  }
14437
14481
 
14438
14482
  function processPlayoffGroups({
14439
- compassAttributes = COMPASS_ATTRIBUTES,
14440
- olympicAttributes = OLYMPIC_ATTRIBUTES,
14441
14483
  requireSequential = true,
14442
14484
  playoffMatchUpFormat,
14485
+ playoffAttributes,
14443
14486
  sourceStructureId,
14444
14487
  policyDefinitions,
14445
14488
  stageSequence,
@@ -14488,6 +14531,8 @@ function processPlayoffGroups({
14488
14531
  if (positionsPlayedOff) {
14489
14532
  finishingPositionOffset = Math.min(...positionsPlayedOff) - 1;
14490
14533
  }
14534
+ const finishingPositionRange = positionsPlayedOff && `${Math.min(...positionsPlayedOff)}-${Math.max(...positionsPlayedOff)}`;
14535
+ const structureName = playoffGroup.structureName || finishingPositionRange && playoffGroup.playoffAttributes?.[finishingPositionRange]?.name || playoffGroup.playoffAttributes?.["0"]?.name;
14491
14536
  const playoffGroupParams = {
14492
14537
  addNameBaseToAttributeName: playoffGroup.addNameBaseToAttributeName,
14493
14538
  playoffStructureNameBase: playoffGroup.playoffStructureNameBase,
@@ -14496,8 +14541,8 @@ function processPlayoffGroups({
14496
14541
  structureId: playoffGroup.structureId ?? uuids?.pop(),
14497
14542
  playoffAttributes: playoffGroup.playoffAttributes,
14498
14543
  structureNameMap: playoffGroup.structureNameMap,
14499
- structureName: playoffGroup.structureName,
14500
- sequenceLimit: playoffGroup.sequenceLimit
14544
+ sequenceLimit: playoffGroup.sequenceLimit,
14545
+ structureName
14501
14546
  };
14502
14547
  const params = {
14503
14548
  ...playoffGroupParams,
@@ -14539,9 +14584,9 @@ function processPlayoffGroups({
14539
14584
  });
14540
14585
  const playoffStructure = structureTemplate({
14541
14586
  structureId: playoffGroup.structureId ?? uuids?.pop(),
14542
- structureName: playoffGroup.structureName,
14543
14587
  matchUpFormat: playoffMatchUpFormat,
14544
14588
  stage: PLAY_OFF,
14589
+ structureName,
14545
14590
  stageSequence,
14546
14591
  matchUps
14547
14592
  });
@@ -14558,10 +14603,11 @@ function processPlayoffGroups({
14558
14603
  finishingPositions
14559
14604
  });
14560
14605
  } else if ([COMPASS, OLYMPIC, PLAY_OFF].includes(playoffDrawType)) {
14561
- const { structureName } = playoffGroup;
14562
14606
  const params2 = {
14607
+ playoffAttributes: playoffGroup.playoffAttributes ?? playoffAttributes,
14608
+ playoffStructureNameBase: playoffGroup.playoffStructureNameBase,
14563
14609
  structureId: playoffGroup.structureId ?? uuids?.pop(),
14564
- playoffStructureNameBase: structureName,
14610
+ structureName: playoffGroup.structureName,
14565
14611
  idPrefix: idPrefix && `${idPrefix}-po`,
14566
14612
  addNameBaseToAttributeName: true,
14567
14613
  finishingPositionOffset,
@@ -14574,12 +14620,12 @@ function processPlayoffGroups({
14574
14620
  };
14575
14621
  if (playoffDrawType === COMPASS) {
14576
14622
  Object.assign(params2, {
14577
- playoffAttributes: compassAttributes,
14623
+ playoffAttributes: playoffGroup?.playoffAttributes ?? playoffAttributes ?? COMPASS_ATTRIBUTES,
14578
14624
  roundOffsetLimit: 3
14579
14625
  });
14580
14626
  } else if (playoffDrawType === OLYMPIC) {
14581
14627
  Object.assign(params2, {
14582
- playoffAttributes: olympicAttributes,
14628
+ playoffAttributes: playoffGroup?.playoffAttributes ?? playoffAttributes ?? OLYMPIC_ATTRIBUTES,
14583
14629
  roundOffsetLimit: 2
14584
14630
  });
14585
14631
  }
@@ -14614,12 +14660,14 @@ function processPlayoffGroups({
14614
14660
  ].includes(playoffDrawType)) {
14615
14661
  const uuidsFMLC = [uuids?.pop(), uuids?.pop()];
14616
14662
  const params2 = {
14663
+ playoffStructureNameBase: playoffGroup.playoffStructureNameBase,
14617
14664
  structureId: playoffGroup.structureId ?? uuids?.pop(),
14618
- structureName: playoffGroup.structureName,
14665
+ playoffAttributes: playoffGroup.playoffAttributes,
14619
14666
  idPrefix: idPrefix && `${idPrefix}-po`,
14620
14667
  finishingPositionOffset,
14621
14668
  uuids: uuidsFMLC,
14622
14669
  stage: PLAY_OFF,
14670
+ structureName,
14623
14671
  matchUpType,
14624
14672
  feedPolicy,
14625
14673
  drawSize,
@@ -16156,6 +16204,208 @@ function drawPositionsAssignedParticipantIds({ structure, matchUp }) {
16156
16204
  return assignedParticipantIds?.length === 2;
16157
16205
  }
16158
16206
 
16207
+ const typeMatch = (arr, type) => arr.filter(Boolean).every((i) => typeof i === type);
16208
+ const allNumeric = (arr) => arr.filter(Boolean).every(isNumeric);
16209
+ function getCategoryAgeDetails(params) {
16210
+ const category = params.category;
16211
+ if (typeof category !== "object")
16212
+ return { error: INVALID_CATEGORY };
16213
+ let { ageCategoryCode, ageMaxDate, ageMinDate, ageMax, ageMin } = category;
16214
+ const categoryName = category.categoryName;
16215
+ let combinedAge;
16216
+ if (!typeMatch(
16217
+ [ageCategoryCode, ageMaxDate, ageMinDate, categoryName],
16218
+ "string"
16219
+ ) || !allNumeric(
16220
+ [ageMax, ageMin]
16221
+ ))
16222
+ return { error: INVALID_CATEGORY };
16223
+ const consideredDate = params.consideredDate ?? extractDate((/* @__PURE__ */ new Date()).toLocaleDateString("sv"));
16224
+ if (!isValidDateString(consideredDate))
16225
+ return { error: INVALID_DATE };
16226
+ const [consideredYear] = consideredDate.split("-").slice(0, 3).map((n) => parseInt(n));
16227
+ const previousDayDate = dateStringDaysChange(consideredDate, -1);
16228
+ const [previousDayMonth, previousDay] = previousDayDate.split("-").slice(1, 3).map((n) => parseInt(n));
16229
+ const previousMonthDay = `${zeroPad(previousDayMonth)}-${zeroPad(
16230
+ previousDay
16231
+ )}`;
16232
+ const nextDayDate = dateStringDaysChange(consideredDate, 1);
16233
+ const [nextDayMonth, nextDay] = nextDayDate.split("-").slice(1, 3).map((n) => parseInt(n));
16234
+ const nextMonthDay = `${zeroPad(nextDayMonth)}-${zeroPad(nextDay)}`;
16235
+ let calculatedAgeMaxDate = ageMin && dateStringDaysChange(consideredDate, -1 * 365 * ageMin);
16236
+ let calculatedAgeMinDate = ageMax && dateStringDaysChange(consideredDate, -1 * 365 * ageMax);
16237
+ const errors = [];
16238
+ const addError = (errorString) => !errors.includes(errorString) && errors.push(errorString);
16239
+ ageCategoryCode = ageCategoryCode ?? categoryName;
16240
+ const prePost = /^([UO]?)(\d{1,2})([UO]?)$/;
16241
+ const extractCombined = /^C(\d{1,2})-(\d{1,2})$/;
16242
+ const isBetween = ageCategoryCode?.includes("-");
16243
+ const isCombined = isBetween && ageCategoryCode?.match(extractCombined);
16244
+ const isCoded = ageCategoryCode?.match(prePost);
16245
+ const constructedDate = (y, df) => `${y}-${df}`;
16246
+ const uPre = (ageInt) => {
16247
+ const ageMinYear = consideredYear - ageInt;
16248
+ const newMinDate = constructedDate(ageMinYear, nextMonthDay);
16249
+ if (category.ageMinDate && category.ageMinDate !== newMinDate)
16250
+ addError(`Invalid submitted ageMinDate: ${ageMinDate}`);
16251
+ ageMinDate = newMinDate;
16252
+ if (ageCategoryCode) {
16253
+ if (category.ageMax && category.ageMax !== ageInt - 1) {
16254
+ addError(`Invalid submitted ageMax: ${ageMax}`);
16255
+ calculatedAgeMinDate = void 0;
16256
+ }
16257
+ ageMax = ageInt - 1;
16258
+ }
16259
+ };
16260
+ const uPost = (ageInt) => {
16261
+ const ageMinYear = consideredYear - ageInt - 1;
16262
+ const newMinDate = constructedDate(ageMinYear, nextMonthDay);
16263
+ if (category.ageMin && category.ageMin > ageInt) {
16264
+ addError(`Invalid submitted ageMin: ${ageMin}`);
16265
+ }
16266
+ if (category.ageMax && category.ageMax > ageInt) {
16267
+ addError(`Invalid submitted ageMax: ${ageMax}`);
16268
+ }
16269
+ if (category.ageMinDate && category.ageMinDate !== newMinDate)
16270
+ addError(`Invalid submitted ageMinDate: ${ageMinDate}`);
16271
+ ageMinDate = newMinDate;
16272
+ if (ageCategoryCode) {
16273
+ if (category.ageMax && category.ageMax !== ageInt) {
16274
+ addError(`Invalid submitted ageMax: ${ageMax}`);
16275
+ calculatedAgeMaxDate = void 0;
16276
+ }
16277
+ ageMax = ageInt;
16278
+ }
16279
+ };
16280
+ const oPre = (ageInt) => {
16281
+ const ageMaxYear = consideredYear - ageInt;
16282
+ const newMaxDate = constructedDate(ageMaxYear, previousMonthDay);
16283
+ if (category.ageMaxDate && category.ageMaxDate !== newMaxDate)
16284
+ addError(`Invalid submitted ageMaxDate: ${ageMaxDate}`);
16285
+ ageMaxDate = newMaxDate;
16286
+ if (ageCategoryCode) {
16287
+ if (category.ageMin && category.ageMin !== ageInt + 1) {
16288
+ addError(`Invalid submitted ageMin: ${ageMin}`);
16289
+ calculatedAgeMaxDate = void 0;
16290
+ }
16291
+ ageMin = ageInt + 1;
16292
+ }
16293
+ };
16294
+ const oPost = (ageInt) => {
16295
+ const ageMaxYear = consideredYear - ageInt - 1;
16296
+ const newMaxDate = constructedDate(ageMaxYear, previousMonthDay);
16297
+ if (category.ageMaxDate && category.ageMaxDate !== newMaxDate)
16298
+ addError(`Invalid submitted ageMaxDate: ${ageMaxDate}`);
16299
+ ageMaxDate = newMaxDate;
16300
+ if (ageCategoryCode) {
16301
+ if (category.ageMin && category.ageMin !== ageInt) {
16302
+ addError(`Invalid submitted ageMin: ${ageMin}`);
16303
+ calculatedAgeMaxDate = void 0;
16304
+ }
16305
+ ageMin = ageInt;
16306
+ }
16307
+ };
16308
+ const processCode = (code) => {
16309
+ const [pre, age, post] = (code.match(prePost) || []).slice(1);
16310
+ const ageInt = parseInt(age);
16311
+ if (pre === "U") {
16312
+ if (category.ageMaxDate && category.ageMaxDate !== ageMaxDate) {
16313
+ addError(`Invalid submitted ageMaxDate: ${category.ageMaxDate}`);
16314
+ }
16315
+ uPre(ageInt);
16316
+ } else if (pre === "O") {
16317
+ oPre(ageInt);
16318
+ }
16319
+ if (post === "U") {
16320
+ if (category.ageMaxDate && category.ageMaxDate !== ageMaxDate) {
16321
+ addError(`Invalid submitted ageMaxDate: ${category.ageMaxDate}`);
16322
+ }
16323
+ uPost(ageInt);
16324
+ } else if (post === "O") {
16325
+ oPost(ageInt);
16326
+ }
16327
+ ageMaxDate = ageMaxDate ?? calculatedAgeMaxDate;
16328
+ ageMinDate = ageMinDate ?? calculatedAgeMinDate;
16329
+ };
16330
+ if (isCombined) {
16331
+ ageMaxDate = void 0;
16332
+ ageMinDate = void 0;
16333
+ ageMax = void 0;
16334
+ ageMin = void 0;
16335
+ if (category.ageMin) {
16336
+ const ageMaxYear = consideredYear - category.ageMin;
16337
+ ageMaxDate = constructedDate(ageMaxYear, previousMonthDay);
16338
+ }
16339
+ if (category.ageMax) {
16340
+ const ageMinYear = consideredYear - category.ageMax - 1;
16341
+ ageMinDate = constructedDate(ageMinYear, nextMonthDay);
16342
+ }
16343
+ const [lowAge, highAge] = (ageCategoryCode?.match(extractCombined) ?? []).slice(1).map((n) => parseInt(n));
16344
+ if (lowAge <= highAge) {
16345
+ ageMin = lowAge;
16346
+ ageMax = highAge;
16347
+ combinedAge = true;
16348
+ } else {
16349
+ addError(`Invalid combined age range ${ageCategoryCode}`);
16350
+ }
16351
+ } else if (isBetween) {
16352
+ ageCategoryCode?.split("-").forEach(processCode);
16353
+ } else if (isCoded) {
16354
+ processCode(ageCategoryCode);
16355
+ } else {
16356
+ if (ageMin)
16357
+ oPre(ageMin);
16358
+ if (ageMax)
16359
+ uPost(ageMax);
16360
+ }
16361
+ if (ageMax && category.ageMin && category.ageMin > ageMax) {
16362
+ addError(`Invalid submitted ageMin: ${category.ageMin}`);
16363
+ ageMin = void 0;
16364
+ }
16365
+ const result = definedAttributes({
16366
+ consideredDate,
16367
+ combinedAge,
16368
+ ageMaxDate,
16369
+ ageMinDate,
16370
+ ageMax,
16371
+ ageMin
16372
+ });
16373
+ if (errors.length)
16374
+ result.errors = errors;
16375
+ return result;
16376
+ }
16377
+
16378
+ function categoryCanContain({
16379
+ childCategory,
16380
+ withDetails,
16381
+ category
16382
+ }) {
16383
+ const categoryDetails = getCategoryAgeDetails({ category });
16384
+ const childCategoryDetails = getCategoryAgeDetails({
16385
+ category: childCategory
16386
+ });
16387
+ const invalidAgeMin = childCategoryDetails.ageMin && (categoryDetails.ageMin && childCategoryDetails.ageMin < categoryDetails.ageMin || categoryDetails.ageMax && childCategoryDetails.ageMin > categoryDetails.ageMax);
16388
+ const invalidAgeMax = childCategoryDetails.ageMax && (categoryDetails.ageMax && childCategoryDetails.ageMax > categoryDetails.ageMax || categoryDetails.ageMin && childCategoryDetails.ageMax < categoryDetails.ageMin);
16389
+ const invalidAgeMinDate = childCategoryDetails.ageMinDate && categoryDetails.ageMaxDate && new Date(childCategoryDetails.ageMinDate) > new Date(categoryDetails.ageMaxDate);
16390
+ const invalidAgeMaxDate = childCategoryDetails.ageMaxDate && categoryDetails.ageMinDate && new Date(childCategoryDetails.ageMaxDate) < new Date(categoryDetails.ageMinDate);
16391
+ const valid = !invalidAgeMax && !invalidAgeMin && !invalidAgeMinDate && !invalidAgeMaxDate;
16392
+ const ignoreFalse = true;
16393
+ const result = definedAttributes(
16394
+ {
16395
+ valid,
16396
+ invalidAgeMax,
16397
+ invalidAgeMin,
16398
+ invalidAgeMinDate,
16399
+ invalidAgeMaxDate
16400
+ },
16401
+ ignoreFalse
16402
+ );
16403
+ if (withDetails) {
16404
+ Object.assign(result, { categoryDetails, childCategoryDetails });
16405
+ }
16406
+ return result;
16407
+ }
16408
+
16159
16409
  function stringify(matchUpFormatObject, preserveRedundant) {
16160
16410
  if (typeof matchUpFormatObject !== "object")
16161
16411
  return;
@@ -16264,6 +16514,7 @@ const matchUpFormatCode = {
16264
16514
  };
16265
16515
 
16266
16516
  function validateTieFormat(params) {
16517
+ const checkCategory = !!(params?.enforceCategory !== false && params?.category);
16267
16518
  const checkGender = !!(params?.enforceGender !== false && params?.gender);
16268
16519
  const checkCollectionIds = params?.checkCollectionIds;
16269
16520
  const tieFormat = params?.tieFormat;
@@ -16300,9 +16551,11 @@ function validateTieFormat(params) {
16300
16551
  if ((setValue || scoreValue) && !collectionValue)
16301
16552
  aggregateValueImperative = true;
16302
16553
  const { valid: valid2, errors: collectionDefinitionErrors } = validateCollectionDefinition({
16554
+ referenceCategory: params.category,
16303
16555
  referenceGender: params.gender,
16304
16556
  collectionDefinition,
16305
16557
  checkCollectionIds,
16558
+ checkCategory,
16306
16559
  checkGender
16307
16560
  });
16308
16561
  if (valid2) {
@@ -16344,19 +16597,22 @@ function validateTieFormat(params) {
16344
16597
  return result;
16345
16598
  }
16346
16599
  function validateCollectionDefinition({
16600
+ checkCategory = true,
16347
16601
  collectionDefinition,
16348
16602
  checkCollectionIds,
16349
16603
  checkGender = true,
16604
+ referenceCategory,
16350
16605
  referenceGender,
16351
16606
  event
16352
16607
  }) {
16353
16608
  referenceGender = referenceGender ?? event?.gender;
16609
+ const stack = "validateCollectionDefinition";
16354
16610
  const errors = [];
16355
16611
  if (typeof collectionDefinition !== "object") {
16356
16612
  errors.push(
16357
16613
  `collectionDefinition must be an object: ${collectionDefinition}`
16358
16614
  );
16359
- return { errors, error: INVALID_OBJECT };
16615
+ return decorateResult({ result: { errors, error: INVALID_OBJECT }, stack });
16360
16616
  }
16361
16617
  const {
16362
16618
  collectionValueProfiles,
@@ -16369,6 +16625,7 @@ function validateCollectionDefinition({
16369
16625
  matchUpType,
16370
16626
  scoreValue,
16371
16627
  setValue,
16628
+ category,
16372
16629
  gender
16373
16630
  } = collectionDefinition;
16374
16631
  if (checkCollectionIds && typeof collectionId !== "string") {
@@ -16414,8 +16671,23 @@ function validateCollectionDefinition({
16414
16671
  if (checkGender && referenceGender && gender && [GenderEnum.Male, GenderEnum.Female].includes(referenceGender) && referenceGender !== gender) {
16415
16672
  errors.push(`Invalid gender: ${gender}`);
16416
16673
  }
16674
+ if (checkCategory && referenceCategory && category) {
16675
+ const result = categoryCanContain({
16676
+ category: referenceCategory,
16677
+ childCategory: category
16678
+ });
16679
+ if (!result.valid)
16680
+ return decorateResult({
16681
+ result: { error: INVALID_CATEGORY },
16682
+ context: result,
16683
+ stack
16684
+ });
16685
+ }
16417
16686
  if (errors.length)
16418
- return { errors, error: INVALID_OBJECT };
16687
+ return decorateResult({
16688
+ result: { errors, error: INVALID_COLLECTION_DEFINITION },
16689
+ stack
16690
+ });
16419
16691
  return { valid: true };
16420
16692
  }
16421
16693
  function checkTieFormat(tieFormat) {
@@ -19103,7 +19375,7 @@ function generateRoundRobinWithPlayOff(params) {
19103
19375
  };
19104
19376
  const { structures, groupCount, groupSize } = generateRoundRobin(mainDrawProperties);
19105
19377
  if (groupCount < 1) {
19106
- console.log(INVALID_CONFIGURATION);
19378
+ return { error: INVALID_CONFIGURATION };
19107
19379
  }
19108
19380
  const playoffGroups = structureOptions?.playoffGroups || [
19109
19381
  { finishingPositions: [1], structureName: constantToString(PLAY_OFF) }
@@ -19369,10 +19641,8 @@ function luckyRoundProfiles(drawSize) {
19369
19641
 
19370
19642
  function getGenerators(params) {
19371
19643
  const {
19372
- compassAttributes = COMPASS_ATTRIBUTES,
19373
- olympicAttributes = OLYMPIC_ATTRIBUTES,
19644
+ playoffAttributes,
19374
19645
  stageSequence = 1,
19375
- structureName,
19376
19646
  structureId,
19377
19647
  stage = MAIN,
19378
19648
  matchUpType,
@@ -19382,13 +19652,13 @@ function getGenerators(params) {
19382
19652
  const { appliedPolicies } = getAppliedPolicies(params);
19383
19653
  const feedPolicy = params.policyDefinitions?.[POLICY_TYPE_FEED_IN] || appliedPolicies?.[POLICY_TYPE_FEED_IN];
19384
19654
  params.skipRounds = params.skipRounds || drawSize <= 4 && (feedPolicy?.feedMainFinal ? 0 : 1) || 0;
19385
- const main = constantToString(MAIN);
19655
+ const structureName = params.structureName ?? playoffAttributes?.["0"]?.name ?? constantToString(MAIN);
19386
19656
  const singleElimination = () => {
19387
19657
  const { matchUps } = treeMatchUps(params);
19388
19658
  const structure = structureTemplate({
19389
19659
  structureId: structureId || uuids?.pop(),
19390
- structureName: structureName || main,
19391
19660
  stageSequence,
19661
+ structureName,
19392
19662
  matchUpType,
19393
19663
  matchUps,
19394
19664
  stage
@@ -19399,9 +19669,9 @@ function getGenerators(params) {
19399
19669
  [AD_HOC]: () => {
19400
19670
  const structure = structureTemplate({
19401
19671
  structureId: structureId || uuids?.pop(),
19402
- structureName: structureName || main,
19403
19672
  finishingPosition: WIN_RATIO,
19404
19673
  stageSequence,
19674
+ structureName,
19405
19675
  matchUps: [],
19406
19676
  matchUpType,
19407
19677
  stage
@@ -19412,8 +19682,8 @@ function getGenerators(params) {
19412
19682
  const { matchUps } = luckyDraw(params);
19413
19683
  const structure = structureTemplate({
19414
19684
  structureId: structureId || uuids?.pop(),
19415
- structureName: structureName || main,
19416
19685
  stageSequence,
19686
+ structureName,
19417
19687
  matchUpType,
19418
19688
  matchUps,
19419
19689
  stage
@@ -19425,12 +19695,12 @@ function getGenerators(params) {
19425
19695
  [COMPASS]: () => generatePlayoffStructures({
19426
19696
  ...params,
19427
19697
  roundOffsetLimit: 3,
19428
- playoffAttributes: compassAttributes
19698
+ playoffAttributes: playoffAttributes ?? COMPASS_ATTRIBUTES
19429
19699
  }),
19430
19700
  [OLYMPIC]: () => generatePlayoffStructures({
19431
19701
  ...params,
19432
19702
  roundOffsetLimit: 2,
19433
- playoffAttributes: olympicAttributes
19703
+ playoffAttributes: playoffAttributes ?? OLYMPIC_ATTRIBUTES
19434
19704
  }),
19435
19705
  [PLAY_OFF]: () => {
19436
19706
  return generatePlayoffStructures(params);
@@ -19439,8 +19709,8 @@ function getGenerators(params) {
19439
19709
  const { matchUps } = feedInMatchUps({ drawSize, uuids, matchUpType });
19440
19710
  const structure = structureTemplate({
19441
19711
  structureId: structureId || uuids?.pop(),
19442
- structureName: structureName || main,
19443
19712
  stageSequence,
19713
+ structureName,
19444
19714
  matchUpType,
19445
19715
  stage: MAIN,
19446
19716
  matchUps
@@ -20217,7 +20487,9 @@ function generateQualifyingStructures({
20217
20487
  }
20218
20488
  const roundTargetName = qualifyingProfiles.length > 1 ? `${roundTarget}-` : "";
20219
20489
  const stageSequenceName = structureProfiles.length > 1 || roundTargetName ? stageSequence : "";
20220
- const qualifyingStructureName = structureName || (roundTargetName || stageSequenceName ? `${QUALIFYING} ${roundTargetName}${stageSequenceName}` : QUALIFYING);
20490
+ const qualifyingStructureName = structureName || (roundTargetName || stageSequenceName ? `${constantToString(
20491
+ QUALIFYING
20492
+ )} ${roundTargetName}${stageSequenceName}` : constantToString(QUALIFYING));
20221
20493
  if (drawType === ROUND_ROBIN) {
20222
20494
  const {
20223
20495
  structures: structures2,
@@ -20686,7 +20958,7 @@ function generateDrawTypeAndModifyDrawDefinition(params) {
20686
20958
  }
20687
20959
 
20688
20960
  function addVoluntaryConsolationStructure$1({
20689
- structureName = VOLUNTARY_CONSOLATION,
20961
+ structureName = constantToString(VOLUNTARY_CONSOLATION),
20690
20962
  structureAbbreviation,
20691
20963
  drawDefinition,
20692
20964
  matchUpType,
@@ -22707,8 +22979,8 @@ function prepareStage(params) {
22707
22979
  });
22708
22980
  if (!scaledEntries?.length && seedByRanking) {
22709
22981
  const rankingScaleAttributes = {
22710
- scaleType: RANKING,
22711
22982
  scaleName: categoryName || ageCategoryCode,
22983
+ scaleType: RANKING,
22712
22984
  eventType
22713
22985
  };
22714
22986
  ({ scaledEntries } = getScaledEntries({