tods-competition-factory 1.6.19 → 1.6.21

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.
@@ -3002,15 +3002,15 @@ function getRoundMatchUps({
3002
3002
  roundIndex += 1;
3003
3003
  }
3004
3004
  });
3005
- const isNotEliminationStructure = !!Object.values(roundProfile).find(
3005
+ const roundsNotPowerOf2 = !!Object.values(roundProfile).find(
3006
3006
  ({ matchUpsCount }) => !isPowerOf2(matchUpsCount)
3007
3007
  );
3008
3008
  const hasNoRoundPositions = matchUps.some(
3009
3009
  (matchUp) => !matchUp.roundPosition
3010
3010
  );
3011
3011
  return {
3012
- isNotEliminationStructure,
3013
3012
  hasNoRoundPositions,
3013
+ roundsNotPowerOf2,
3014
3014
  maxMatchUpsCount,
3015
3015
  roundMatchUps,
3016
3016
  roundNumbers,
@@ -4208,31 +4208,28 @@ function filterMatchUps(params) {
4208
4208
  }
4209
4209
 
4210
4210
  function isLucky({
4211
- isNotEliminationStructure,
4211
+ roundsNotPowerOf2,
4212
4212
  drawDefinition,
4213
- roundMatchUps,
4214
- structure
4213
+ structure,
4214
+ matchUps
4215
4215
  }) {
4216
4216
  if (!structure)
4217
4217
  return false;
4218
- if (!roundMatchUps) {
4219
- ({ isNotEliminationStructure, roundMatchUps } = getRoundMatchUps({
4220
- matchUps: structure.matchUps ?? []
4221
- }));
4222
- }
4223
- const hasFirstRoundDrawPositions = !!roundMatchUps?.[1]?.find(
4224
- ({ drawPositions }) => drawPositions
4225
- );
4226
- const noSecondRoundDrawPositions = !roundMatchUps?.[2]?.find(
4227
- ({ drawPositions }) => drawPositions
4228
- );
4229
- return isNotEliminationStructure && !structure?.structures && hasFirstRoundDrawPositions && noSecondRoundDrawPositions && !(drawDefinition?.drawType && drawDefinition.drawType !== LUCKY_DRAW);
4218
+ matchUps = matchUps ?? structure.matchUps ?? [];
4219
+ roundsNotPowerOf2 = roundsNotPowerOf2 ?? getRoundMatchUps({ matchUps }).roundsNotPowerOf2;
4220
+ const hasDrawPositions = !!structure.positionAssignments?.find(({ drawPosition }) => drawPosition) || !!matchUps?.find(({ drawPositions }) => drawPositions?.length);
4221
+ return (!drawDefinition?.drawType || drawDefinition.drawType !== LUCKY_DRAW) && !structure?.structures && roundsNotPowerOf2 && hasDrawPositions;
4230
4222
  }
4231
4223
 
4232
4224
  function isAdHoc({ drawDefinition, structure }) {
4233
4225
  if (!structure)
4234
4226
  return false;
4235
- return !structure?.structures && !(drawDefinition?.drawType && drawDefinition.drawType !== AD_HOC) && !structure?.matchUps?.find(({ roundPosition }) => !!roundPosition);
4227
+ const matchUps = structure.matchUps || structure.roundMatchUps && Object.values(structure.roundMatchUps).flat();
4228
+ const hasRoundPosition = matchUps?.find((matchUp) => matchUp?.roundPosition);
4229
+ const hasDrawPosition = matchUps?.find(
4230
+ (matchUp) => matchUp?.drawPositions?.length
4231
+ );
4232
+ return !structure?.structures && !(drawDefinition?.drawType && drawDefinition.drawType !== AD_HOC) && !hasRoundPosition && !hasDrawPosition;
4236
4233
  }
4237
4234
 
4238
4235
  const POLICY_ROUND_NAMING_DEFAULT = {
@@ -4267,14 +4264,10 @@ function getRoundContextProfile({
4267
4264
  structure,
4268
4265
  matchUps
4269
4266
  }) {
4270
- const { isNotEliminationStructure, roundProfile, roundMatchUps } = getRoundMatchUps({ matchUps });
4267
+ const { roundProfile, roundMatchUps } = getRoundMatchUps({ matchUps });
4271
4268
  const { structureAbbreviation, stage } = structure;
4272
4269
  const isAdHocStructure = isAdHoc({ structure });
4273
- const isLuckyStructure = isLucky({
4274
- isNotEliminationStructure,
4275
- roundMatchUps,
4276
- structure
4277
- });
4270
+ const isLuckyStructure = isLucky({ structure });
4278
4271
  const isRoundRobin = structure.structures;
4279
4272
  const roundNamingProfile = {};
4280
4273
  const defaultRoundNamingPolicy = POLICY_ROUND_NAMING_DEFAULT[POLICY_TYPE_ROUND_NAMING];
@@ -4508,8 +4501,8 @@ function getAllStructureMatchUps({
4508
4501
  matchUpsMap,
4509
4502
  structureId
4510
4503
  }).drawPositionsRanges : void 0;
4511
- matchUps = matchUps.map(
4512
- (matchUp) => addMatchUpContext({
4504
+ matchUps = matchUps.map((matchUp) => {
4505
+ return addMatchUpContext({
4513
4506
  scheduleVisibilityFilters,
4514
4507
  sourceDrawPositionRanges,
4515
4508
  drawPositionsRanges,
@@ -4520,8 +4513,8 @@ function getAllStructureMatchUps({
4520
4513
  roundProfile,
4521
4514
  matchUp,
4522
4515
  event
4523
- })
4524
- );
4516
+ });
4517
+ });
4525
4518
  const matchUpTies = matchUps?.filter(
4526
4519
  (matchUp) => Array.isArray(matchUp.tieMatchUps)
4527
4520
  );
@@ -5296,7 +5289,7 @@ function getValidSeedBlocks({
5296
5289
  let validSeedBlocks = [];
5297
5290
  if (!structure)
5298
5291
  return { error: MISSING_STRUCTURE };
5299
- const { roundMatchUps } = getAllStructureMatchUps({
5292
+ const { matchUps, roundMatchUps } = getAllStructureMatchUps({
5300
5293
  matchUpFilters: { roundNumbers: [1] },
5301
5294
  provisionalPositioning,
5302
5295
  structure
@@ -5329,12 +5322,16 @@ function getValidSeedBlocks({
5329
5322
  const { stage, structureType, roundLimit } = structure;
5330
5323
  const isContainer = structureType === CONTAINER;
5331
5324
  const isFeedIn = !isContainer && uniqueDrawPositionsByRound?.length;
5332
- const isLucky = firstRoundDrawPositions?.length && !isPowerOf2(baseDrawSize);
5333
5325
  const qualifyingBlocks = !isContainer && stage === QUALIFYING && roundLimit;
5334
5326
  const fedSeedBlockPositions = seedRangeDrawPositionBlocks.flat(Infinity);
5335
5327
  const fedSeedNumberOffset = isFeedIn ? fedSeedBlockPositions?.length : 0;
5336
5328
  const countLimit = allPositions ? positionsCount : seedsCount;
5337
- const firstRoundSeedsCount = isLucky ? 0 : !isFeedIn && countLimit || countLimit && fedSeedBlockPositions.length < countLimit && countLimit - fedSeedBlockPositions.length || 0;
5329
+ const isLuckyStructure = isLucky({
5330
+ drawDefinition,
5331
+ structure,
5332
+ matchUps
5333
+ });
5334
+ const firstRoundSeedsCount = isLuckyStructure ? 0 : !isFeedIn && countLimit || countLimit && fedSeedBlockPositions.length < countLimit && countLimit - fedSeedBlockPositions.length || 0;
5338
5335
  if (qualifyingBlocks) {
5339
5336
  const seedingBlocksCount = structure?.matchUps ? structure.matchUps.filter(
5340
5337
  ({ roundNumber }) => roundNumber === structure.roundLimit
@@ -5370,14 +5367,14 @@ function getValidSeedBlocks({
5370
5367
  validSeedBlocks = seedRangeDrawPositionBlocks.map((block) => {
5371
5368
  return { seedNumbers: block, drawPositions: block };
5372
5369
  });
5373
- } else if (isLucky) {
5370
+ } else if (isLuckyStructure) {
5374
5371
  const blocks = chunkArray(firstRoundDrawPositions, 2).map((block, i) => ({
5375
5372
  drawPositions: [block[0]],
5376
5373
  seedNumbers: [i + 1]
5377
5374
  }));
5378
5375
  blocks.forEach((block) => validSeedBlocks.push(block));
5379
5376
  }
5380
- if (!isContainer && !isLucky && !qualifyingBlocks) {
5377
+ if (!isContainer && !isLuckyStructure && !qualifyingBlocks) {
5381
5378
  const { blocks } = constructPower2Blocks({
5382
5379
  drawPositionOffset: firstRoundDrawPositionOffset,
5383
5380
  seedNumberOffset: fedSeedNumberOffset,
@@ -5396,7 +5393,7 @@ function getValidSeedBlocks({
5396
5393
  },
5397
5394
  true
5398
5395
  );
5399
- if (!isLucky && !isFeedIn && !isContainer && !validSeedPositions) {
5396
+ if (!isLuckyStructure && !isFeedIn && !isContainer && !validSeedPositions) {
5400
5397
  return {
5401
5398
  error: INVALID_SEED_POSITION,
5402
5399
  validSeedBlocks: [],
@@ -5405,10 +5402,10 @@ function getValidSeedBlocks({
5405
5402
  };
5406
5403
  }
5407
5404
  return {
5405
+ isLuckyStructure,
5408
5406
  validSeedBlocks,
5409
5407
  isContainer,
5410
- isFeedIn,
5411
- isLucky
5408
+ isFeedIn
5412
5409
  };
5413
5410
  }
5414
5411
  function getContainerBlocks({ seedingProfile, structure }) {
@@ -11431,6 +11428,113 @@ function consolationCleanup({
11431
11428
  return { ...SUCCESS };
11432
11429
  }
11433
11430
 
11431
+ function removeLineUpSubstitutions({ lineUp }) {
11432
+ if (!Array.isArray(lineUp))
11433
+ return;
11434
+ const participantAssignments = {};
11435
+ const permutations = unique(
11436
+ lineUp.flatMap(
11437
+ ({ collectionAssignments }) => collectionAssignments.map(
11438
+ ({ collectionId, collectionPosition }) => [collectionId, collectionPosition].join("|")
11439
+ )
11440
+ )
11441
+ );
11442
+ permutations.forEach((permutation) => {
11443
+ const [collectionId, position] = permutation.split("|");
11444
+ const collectionPosition = parseInt(position);
11445
+ const { assignedParticipantIds } = getCollectionPositionAssignments({
11446
+ collectionPosition,
11447
+ collectionId,
11448
+ lineUp
11449
+ });
11450
+ assignedParticipantIds.forEach((participantId) => {
11451
+ if (!participantAssignments[participantId])
11452
+ participantAssignments[participantId] = [];
11453
+ participantAssignments[participantId].push({
11454
+ collectionId,
11455
+ collectionPosition
11456
+ });
11457
+ });
11458
+ });
11459
+ return Object.keys(participantAssignments).map((participantId) => ({
11460
+ participantId,
11461
+ collectionAssignments: participantAssignments[participantId]
11462
+ }));
11463
+ }
11464
+
11465
+ function mustBeAnArray(value) {
11466
+ return `${value} must be an array`;
11467
+ }
11468
+
11469
+ function validateLineUp({ lineUp, tieFormat }) {
11470
+ const errors = [];
11471
+ if (!Array.isArray(lineUp)) {
11472
+ errors.push(mustBeAnArray("lineUp"));
11473
+ return { valid: false, errors, error: INVALID_VALUES };
11474
+ }
11475
+ const validItems = lineUp.every((item) => {
11476
+ if (typeof item !== "object") {
11477
+ errors.push(`lineUp entries must be objects`);
11478
+ return false;
11479
+ }
11480
+ const { participantId, collectionAssignments } = item;
11481
+ if (!participantId) {
11482
+ errors.push("Missing participantId");
11483
+ return false;
11484
+ }
11485
+ if (typeof participantId !== "string") {
11486
+ errors.push("participantIds must be strings");
11487
+ return false;
11488
+ }
11489
+ if (!Array.isArray(collectionAssignments)) {
11490
+ errors.push(mustBeAnArray("collectionAssignments"));
11491
+ return false;
11492
+ }
11493
+ return collectionAssignments.every((collectionAssignment) => {
11494
+ if (typeof collectionAssignment !== "object") {
11495
+ errors.push("collectionAssignments must be objects");
11496
+ return false;
11497
+ }
11498
+ const { collectionPosition } = collectionAssignment;
11499
+ if (typeof collectionPosition !== "number") {
11500
+ errors.push("collectionPosition must be a number");
11501
+ return false;
11502
+ }
11503
+ return true;
11504
+ });
11505
+ });
11506
+ const noDuplicates = unique(lineUp.map(getParticipantId)).length === lineUp.length;
11507
+ if (!noDuplicates)
11508
+ errors.push("Duplicated participantId(s)");
11509
+ const valid = validItems && noDuplicates;
11510
+ return { valid, errors, error: errors.length ? INVALID_VALUES : void 0 };
11511
+ }
11512
+
11513
+ function updateTeamLineUp({
11514
+ drawDefinition,
11515
+ participantId,
11516
+ tieFormat,
11517
+ lineUp
11518
+ }) {
11519
+ if (typeof drawDefinition !== "object")
11520
+ return { error: MISSING_DRAW_DEFINITION };
11521
+ if (typeof participantId !== "string")
11522
+ return { error: MISSING_PARTICIPANT_ID };
11523
+ const validation = validateLineUp({ lineUp, tieFormat });
11524
+ if (!validation.valid)
11525
+ return validation;
11526
+ const { extension: existingExtension } = findExtension({
11527
+ element: drawDefinition,
11528
+ name: LINEUPS
11529
+ });
11530
+ const value = existingExtension?.value || {};
11531
+ value[participantId] = removeLineUpSubstitutions({ lineUp });
11532
+ const extension = { name: LINEUPS, value };
11533
+ addExtension({ element: drawDefinition, extension });
11534
+ addDrawNotice({ drawDefinition });
11535
+ return { ...SUCCESS };
11536
+ }
11537
+
11434
11538
  function resetLineUps({
11435
11539
  inContextDrawMatchUps,
11436
11540
  inheritance = true,
@@ -11458,10 +11562,18 @@ function resetLineUps({
11458
11562
  ({ matchUpId }) => matchUpId === inContextMatchUp.matchUpId
11459
11563
  );
11460
11564
  if (matchUp?.sides?.[sideIndex]) {
11461
- if (inheritance) {
11462
- delete matchUp.sides[sideIndex].lineUp;
11463
- } else {
11464
- matchUp.sides[sideIndex].lineUp = [];
11565
+ delete matchUp.sides[sideIndex].lineUp;
11566
+ if (inheritance === false) {
11567
+ const tieFormat = inContextMatchUp.tieFormat;
11568
+ const participantId = side.participantId;
11569
+ if (tieFormat && participantId) {
11570
+ updateTeamLineUp({
11571
+ drawDefinition,
11572
+ participantId,
11573
+ lineUp: [],
11574
+ tieFormat
11575
+ });
11576
+ }
11465
11577
  }
11466
11578
  modifyMatchUpNotice({
11467
11579
  tournamentId: tournamentRecord?.tournamentId,
@@ -12243,7 +12355,7 @@ function getSeedOrderByePositions({
12243
12355
  structure
12244
12356
  });
12245
12357
  }
12246
- const { isFeedIn, isLucky, isContainer } = seedBlockInfo;
12358
+ const { isFeedIn, isLuckyStructure, isContainer } = seedBlockInfo;
12247
12359
  let { validSeedBlocks } = seedBlockInfo;
12248
12360
  if (appliedPolicies?.seeding?.containerByesIgnoreSeeding)
12249
12361
  validSeedBlocks = [];
@@ -12287,10 +12399,10 @@ function getSeedOrderByePositions({
12287
12399
  return {
12288
12400
  strictSeedOrderByePositions,
12289
12401
  blockSeedOrderByePositions,
12402
+ isLuckyStructure,
12290
12403
  positionedSeeds,
12291
12404
  isContainer,
12292
- isFeedIn,
12293
- isLucky
12405
+ isFeedIn
12294
12406
  };
12295
12407
  }
12296
12408
  function getOrderedByePositions({
@@ -12317,12 +12429,12 @@ function getOrderedByePositions({
12317
12429
  function getUnseededByePositions({
12318
12430
  provisionalPositioning,
12319
12431
  seedOrderByePositions,
12432
+ isLuckyStructure,
12320
12433
  appliedPolicies,
12321
12434
  drawDefinition,
12322
12435
  seedLimit,
12323
12436
  structure,
12324
- isFeedIn,
12325
- isLucky
12437
+ isFeedIn
12326
12438
  }) {
12327
12439
  const seedingProfile = appliedPolicies?.seeding?.seedingProfile;
12328
12440
  const isQualifying = structure.stage === QUALIFYING;
@@ -12540,8 +12652,8 @@ function positionByes({
12540
12652
  const {
12541
12653
  strictSeedOrderByePositions,
12542
12654
  blockSeedOrderByePositions,
12543
- isFeedIn,
12544
- isLucky
12655
+ isLuckyStructure,
12656
+ isFeedIn
12545
12657
  } = getSeedOrderByePositions({
12546
12658
  provisionalPositioning,
12547
12659
  relevantMatchUps,
@@ -12556,12 +12668,12 @@ function positionByes({
12556
12668
  let { unseededByePositions } = getUnseededByePositions({
12557
12669
  provisionalPositioning,
12558
12670
  seedOrderByePositions,
12671
+ isLuckyStructure,
12559
12672
  appliedPolicies,
12560
12673
  drawDefinition,
12561
12674
  seedLimit,
12562
12675
  structure,
12563
- isFeedIn,
12564
- isLucky
12676
+ isFeedIn
12565
12677
  });
12566
12678
  const isOdd = (x) => x % 2;
12567
12679
  const isNotPaired = (arr, c) => (arr || []).every((a) => isOdd(a) ? c !== a + 1 : c !== a - 1);
@@ -16008,10 +16120,6 @@ function drawPositionsAssignedParticipantIds({ structure, matchUp }) {
16008
16120
  return assignedParticipantIds?.length === 2;
16009
16121
  }
16010
16122
 
16011
- function mustBeAnArray(value) {
16012
- return `${value} must be an array`;
16013
- }
16014
-
16015
16123
  function stringify(matchUpFormatObject, preserveRedundant) {
16016
16124
  if (typeof matchUpFormatObject !== "object")
16017
16125
  return;
@@ -16701,40 +16809,6 @@ function updateTieMatchUpScore({
16701
16809
  };
16702
16810
  }
16703
16811
 
16704
- function removeLineUpSubstitutions({ lineUp }) {
16705
- if (!Array.isArray(lineUp))
16706
- return;
16707
- const participantAssignments = {};
16708
- const permutations = unique(
16709
- lineUp.flatMap(
16710
- ({ collectionAssignments }) => collectionAssignments.map(
16711
- ({ collectionId, collectionPosition }) => [collectionId, collectionPosition].join("|")
16712
- )
16713
- )
16714
- );
16715
- permutations.forEach((permutation) => {
16716
- const [collectionId, position] = permutation.split("|");
16717
- const collectionPosition = parseInt(position);
16718
- const { assignedParticipantIds } = getCollectionPositionAssignments({
16719
- collectionPosition,
16720
- collectionId,
16721
- lineUp
16722
- });
16723
- assignedParticipantIds.forEach((participantId) => {
16724
- if (!participantAssignments[participantId])
16725
- participantAssignments[participantId] = [];
16726
- participantAssignments[participantId].push({
16727
- collectionId,
16728
- collectionPosition
16729
- });
16730
- });
16731
- });
16732
- return Object.keys(participantAssignments).map((participantId) => ({
16733
- participantId,
16734
- collectionAssignments: participantAssignments[participantId]
16735
- }));
16736
- }
16737
-
16738
16812
  function directWinner({
16739
16813
  winnerMatchUpDrawPositionIndex,
16740
16814
  inContextDrawMatchUps,