tods-competition-factory 1.6.19 → 1.6.20

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,29 @@ 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 hasRoundPosition = structure?.matchUps?.find(
4228
+ (matchUp) => matchUp?.roundPosition
4229
+ );
4230
+ const hasDrawPosition = structure?.matchUps?.find(
4231
+ (matchUp) => matchUp?.drawPositions?.length
4232
+ );
4233
+ return !structure?.structures && !(drawDefinition?.drawType && drawDefinition.drawType !== AD_HOC) && !hasRoundPosition && !hasDrawPosition;
4236
4234
  }
4237
4235
 
4238
4236
  const POLICY_ROUND_NAMING_DEFAULT = {
@@ -4267,14 +4265,10 @@ function getRoundContextProfile({
4267
4265
  structure,
4268
4266
  matchUps
4269
4267
  }) {
4270
- const { isNotEliminationStructure, roundProfile, roundMatchUps } = getRoundMatchUps({ matchUps });
4268
+ const { roundProfile, roundMatchUps } = getRoundMatchUps({ matchUps });
4271
4269
  const { structureAbbreviation, stage } = structure;
4272
4270
  const isAdHocStructure = isAdHoc({ structure });
4273
- const isLuckyStructure = isLucky({
4274
- isNotEliminationStructure,
4275
- roundMatchUps,
4276
- structure
4277
- });
4271
+ const isLuckyStructure = isLucky({ structure });
4278
4272
  const isRoundRobin = structure.structures;
4279
4273
  const roundNamingProfile = {};
4280
4274
  const defaultRoundNamingPolicy = POLICY_ROUND_NAMING_DEFAULT[POLICY_TYPE_ROUND_NAMING];
@@ -5296,7 +5290,7 @@ function getValidSeedBlocks({
5296
5290
  let validSeedBlocks = [];
5297
5291
  if (!structure)
5298
5292
  return { error: MISSING_STRUCTURE };
5299
- const { roundMatchUps } = getAllStructureMatchUps({
5293
+ const { matchUps, roundMatchUps } = getAllStructureMatchUps({
5300
5294
  matchUpFilters: { roundNumbers: [1] },
5301
5295
  provisionalPositioning,
5302
5296
  structure
@@ -5329,12 +5323,16 @@ function getValidSeedBlocks({
5329
5323
  const { stage, structureType, roundLimit } = structure;
5330
5324
  const isContainer = structureType === CONTAINER;
5331
5325
  const isFeedIn = !isContainer && uniqueDrawPositionsByRound?.length;
5332
- const isLucky = firstRoundDrawPositions?.length && !isPowerOf2(baseDrawSize);
5333
5326
  const qualifyingBlocks = !isContainer && stage === QUALIFYING && roundLimit;
5334
5327
  const fedSeedBlockPositions = seedRangeDrawPositionBlocks.flat(Infinity);
5335
5328
  const fedSeedNumberOffset = isFeedIn ? fedSeedBlockPositions?.length : 0;
5336
5329
  const countLimit = allPositions ? positionsCount : seedsCount;
5337
- const firstRoundSeedsCount = isLucky ? 0 : !isFeedIn && countLimit || countLimit && fedSeedBlockPositions.length < countLimit && countLimit - fedSeedBlockPositions.length || 0;
5330
+ const isLuckyStructure = isLucky({
5331
+ drawDefinition,
5332
+ structure,
5333
+ matchUps
5334
+ });
5335
+ const firstRoundSeedsCount = isLuckyStructure ? 0 : !isFeedIn && countLimit || countLimit && fedSeedBlockPositions.length < countLimit && countLimit - fedSeedBlockPositions.length || 0;
5338
5336
  if (qualifyingBlocks) {
5339
5337
  const seedingBlocksCount = structure?.matchUps ? structure.matchUps.filter(
5340
5338
  ({ roundNumber }) => roundNumber === structure.roundLimit
@@ -5370,14 +5368,14 @@ function getValidSeedBlocks({
5370
5368
  validSeedBlocks = seedRangeDrawPositionBlocks.map((block) => {
5371
5369
  return { seedNumbers: block, drawPositions: block };
5372
5370
  });
5373
- } else if (isLucky) {
5371
+ } else if (isLuckyStructure) {
5374
5372
  const blocks = chunkArray(firstRoundDrawPositions, 2).map((block, i) => ({
5375
5373
  drawPositions: [block[0]],
5376
5374
  seedNumbers: [i + 1]
5377
5375
  }));
5378
5376
  blocks.forEach((block) => validSeedBlocks.push(block));
5379
5377
  }
5380
- if (!isContainer && !isLucky && !qualifyingBlocks) {
5378
+ if (!isContainer && !isLuckyStructure && !qualifyingBlocks) {
5381
5379
  const { blocks } = constructPower2Blocks({
5382
5380
  drawPositionOffset: firstRoundDrawPositionOffset,
5383
5381
  seedNumberOffset: fedSeedNumberOffset,
@@ -5396,7 +5394,7 @@ function getValidSeedBlocks({
5396
5394
  },
5397
5395
  true
5398
5396
  );
5399
- if (!isLucky && !isFeedIn && !isContainer && !validSeedPositions) {
5397
+ if (!isLuckyStructure && !isFeedIn && !isContainer && !validSeedPositions) {
5400
5398
  return {
5401
5399
  error: INVALID_SEED_POSITION,
5402
5400
  validSeedBlocks: [],
@@ -5405,10 +5403,10 @@ function getValidSeedBlocks({
5405
5403
  };
5406
5404
  }
5407
5405
  return {
5406
+ isLuckyStructure,
5408
5407
  validSeedBlocks,
5409
5408
  isContainer,
5410
- isFeedIn,
5411
- isLucky
5409
+ isFeedIn
5412
5410
  };
5413
5411
  }
5414
5412
  function getContainerBlocks({ seedingProfile, structure }) {
@@ -11431,6 +11429,113 @@ function consolationCleanup({
11431
11429
  return { ...SUCCESS };
11432
11430
  }
11433
11431
 
11432
+ function removeLineUpSubstitutions({ lineUp }) {
11433
+ if (!Array.isArray(lineUp))
11434
+ return;
11435
+ const participantAssignments = {};
11436
+ const permutations = unique(
11437
+ lineUp.flatMap(
11438
+ ({ collectionAssignments }) => collectionAssignments.map(
11439
+ ({ collectionId, collectionPosition }) => [collectionId, collectionPosition].join("|")
11440
+ )
11441
+ )
11442
+ );
11443
+ permutations.forEach((permutation) => {
11444
+ const [collectionId, position] = permutation.split("|");
11445
+ const collectionPosition = parseInt(position);
11446
+ const { assignedParticipantIds } = getCollectionPositionAssignments({
11447
+ collectionPosition,
11448
+ collectionId,
11449
+ lineUp
11450
+ });
11451
+ assignedParticipantIds.forEach((participantId) => {
11452
+ if (!participantAssignments[participantId])
11453
+ participantAssignments[participantId] = [];
11454
+ participantAssignments[participantId].push({
11455
+ collectionId,
11456
+ collectionPosition
11457
+ });
11458
+ });
11459
+ });
11460
+ return Object.keys(participantAssignments).map((participantId) => ({
11461
+ participantId,
11462
+ collectionAssignments: participantAssignments[participantId]
11463
+ }));
11464
+ }
11465
+
11466
+ function mustBeAnArray(value) {
11467
+ return `${value} must be an array`;
11468
+ }
11469
+
11470
+ function validateLineUp({ lineUp, tieFormat }) {
11471
+ const errors = [];
11472
+ if (!Array.isArray(lineUp)) {
11473
+ errors.push(mustBeAnArray("lineUp"));
11474
+ return { valid: false, errors, error: INVALID_VALUES };
11475
+ }
11476
+ const validItems = lineUp.every((item) => {
11477
+ if (typeof item !== "object") {
11478
+ errors.push(`lineUp entries must be objects`);
11479
+ return false;
11480
+ }
11481
+ const { participantId, collectionAssignments } = item;
11482
+ if (!participantId) {
11483
+ errors.push("Missing participantId");
11484
+ return false;
11485
+ }
11486
+ if (typeof participantId !== "string") {
11487
+ errors.push("participantIds must be strings");
11488
+ return false;
11489
+ }
11490
+ if (!Array.isArray(collectionAssignments)) {
11491
+ errors.push(mustBeAnArray("collectionAssignments"));
11492
+ return false;
11493
+ }
11494
+ return collectionAssignments.every((collectionAssignment) => {
11495
+ if (typeof collectionAssignment !== "object") {
11496
+ errors.push("collectionAssignments must be objects");
11497
+ return false;
11498
+ }
11499
+ const { collectionPosition } = collectionAssignment;
11500
+ if (typeof collectionPosition !== "number") {
11501
+ errors.push("collectionPosition must be a number");
11502
+ return false;
11503
+ }
11504
+ return true;
11505
+ });
11506
+ });
11507
+ const noDuplicates = unique(lineUp.map(getParticipantId)).length === lineUp.length;
11508
+ if (!noDuplicates)
11509
+ errors.push("Duplicated participantId(s)");
11510
+ const valid = validItems && noDuplicates;
11511
+ return { valid, errors, error: errors.length ? INVALID_VALUES : void 0 };
11512
+ }
11513
+
11514
+ function updateTeamLineUp({
11515
+ drawDefinition,
11516
+ participantId,
11517
+ tieFormat,
11518
+ lineUp
11519
+ }) {
11520
+ if (typeof drawDefinition !== "object")
11521
+ return { error: MISSING_DRAW_DEFINITION };
11522
+ if (typeof participantId !== "string")
11523
+ return { error: MISSING_PARTICIPANT_ID };
11524
+ const validation = validateLineUp({ lineUp, tieFormat });
11525
+ if (!validation.valid)
11526
+ return validation;
11527
+ const { extension: existingExtension } = findExtension({
11528
+ element: drawDefinition,
11529
+ name: LINEUPS
11530
+ });
11531
+ const value = existingExtension?.value || {};
11532
+ value[participantId] = removeLineUpSubstitutions({ lineUp });
11533
+ const extension = { name: LINEUPS, value };
11534
+ addExtension({ element: drawDefinition, extension });
11535
+ addDrawNotice({ drawDefinition });
11536
+ return { ...SUCCESS };
11537
+ }
11538
+
11434
11539
  function resetLineUps({
11435
11540
  inContextDrawMatchUps,
11436
11541
  inheritance = true,
@@ -11458,10 +11563,18 @@ function resetLineUps({
11458
11563
  ({ matchUpId }) => matchUpId === inContextMatchUp.matchUpId
11459
11564
  );
11460
11565
  if (matchUp?.sides?.[sideIndex]) {
11461
- if (inheritance) {
11462
- delete matchUp.sides[sideIndex].lineUp;
11463
- } else {
11464
- matchUp.sides[sideIndex].lineUp = [];
11566
+ delete matchUp.sides[sideIndex].lineUp;
11567
+ if (inheritance === false) {
11568
+ const tieFormat = inContextMatchUp.tieFormat;
11569
+ const participantId = side.participantId;
11570
+ if (tieFormat && participantId) {
11571
+ updateTeamLineUp({
11572
+ drawDefinition,
11573
+ participantId,
11574
+ lineUp: [],
11575
+ tieFormat
11576
+ });
11577
+ }
11465
11578
  }
11466
11579
  modifyMatchUpNotice({
11467
11580
  tournamentId: tournamentRecord?.tournamentId,
@@ -12243,7 +12356,7 @@ function getSeedOrderByePositions({
12243
12356
  structure
12244
12357
  });
12245
12358
  }
12246
- const { isFeedIn, isLucky, isContainer } = seedBlockInfo;
12359
+ const { isFeedIn, isLuckyStructure, isContainer } = seedBlockInfo;
12247
12360
  let { validSeedBlocks } = seedBlockInfo;
12248
12361
  if (appliedPolicies?.seeding?.containerByesIgnoreSeeding)
12249
12362
  validSeedBlocks = [];
@@ -12287,10 +12400,10 @@ function getSeedOrderByePositions({
12287
12400
  return {
12288
12401
  strictSeedOrderByePositions,
12289
12402
  blockSeedOrderByePositions,
12403
+ isLuckyStructure,
12290
12404
  positionedSeeds,
12291
12405
  isContainer,
12292
- isFeedIn,
12293
- isLucky
12406
+ isFeedIn
12294
12407
  };
12295
12408
  }
12296
12409
  function getOrderedByePositions({
@@ -12317,12 +12430,12 @@ function getOrderedByePositions({
12317
12430
  function getUnseededByePositions({
12318
12431
  provisionalPositioning,
12319
12432
  seedOrderByePositions,
12433
+ isLuckyStructure,
12320
12434
  appliedPolicies,
12321
12435
  drawDefinition,
12322
12436
  seedLimit,
12323
12437
  structure,
12324
- isFeedIn,
12325
- isLucky
12438
+ isFeedIn
12326
12439
  }) {
12327
12440
  const seedingProfile = appliedPolicies?.seeding?.seedingProfile;
12328
12441
  const isQualifying = structure.stage === QUALIFYING;
@@ -12540,8 +12653,8 @@ function positionByes({
12540
12653
  const {
12541
12654
  strictSeedOrderByePositions,
12542
12655
  blockSeedOrderByePositions,
12543
- isFeedIn,
12544
- isLucky
12656
+ isLuckyStructure,
12657
+ isFeedIn
12545
12658
  } = getSeedOrderByePositions({
12546
12659
  provisionalPositioning,
12547
12660
  relevantMatchUps,
@@ -12556,12 +12669,12 @@ function positionByes({
12556
12669
  let { unseededByePositions } = getUnseededByePositions({
12557
12670
  provisionalPositioning,
12558
12671
  seedOrderByePositions,
12672
+ isLuckyStructure,
12559
12673
  appliedPolicies,
12560
12674
  drawDefinition,
12561
12675
  seedLimit,
12562
12676
  structure,
12563
- isFeedIn,
12564
- isLucky
12677
+ isFeedIn
12565
12678
  });
12566
12679
  const isOdd = (x) => x % 2;
12567
12680
  const isNotPaired = (arr, c) => (arr || []).every((a) => isOdd(a) ? c !== a + 1 : c !== a - 1);
@@ -16008,10 +16121,6 @@ function drawPositionsAssignedParticipantIds({ structure, matchUp }) {
16008
16121
  return assignedParticipantIds?.length === 2;
16009
16122
  }
16010
16123
 
16011
- function mustBeAnArray(value) {
16012
- return `${value} must be an array`;
16013
- }
16014
-
16015
16124
  function stringify(matchUpFormatObject, preserveRedundant) {
16016
16125
  if (typeof matchUpFormatObject !== "object")
16017
16126
  return;
@@ -16701,40 +16810,6 @@ function updateTieMatchUpScore({
16701
16810
  };
16702
16811
  }
16703
16812
 
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
16813
  function directWinner({
16739
16814
  winnerMatchUpDrawPositionIndex,
16740
16815
  inContextDrawMatchUps,