tods-competition-factory 1.7.3 → 1.7.5

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.
@@ -1557,6 +1557,7 @@ function getMatchUpFormatAverageTimes({
1557
1557
  });
1558
1558
  }
1559
1559
 
1560
+ const DYNAMIC = "DYNAMIC";
1560
1561
  const RANKING = "RANKING";
1561
1562
  const RATING = "RATING";
1562
1563
  const SCALE = "SCALE";
@@ -1575,14 +1576,15 @@ function getScaleValues({ participant }) {
1575
1576
  for (const itemType of itemTypes) {
1576
1577
  const scaleItem = latestScaleItem(itemType);
1577
1578
  if (scaleItem) {
1578
- const [, type, format, scaleName] = scaleItem.itemType.split(".");
1579
+ const [, type, format, scaleName, modifier] = scaleItem.itemType.split(".");
1580
+ const namedScale = modifier ? `${scaleName}.${modifier}` : scaleName;
1579
1581
  const scaleType = type === SEEDING && "seedings" || type === RANKING && "rankings" || "ratings";
1580
1582
  if (!scales[scaleType][format])
1581
1583
  scales[scaleType][format] = [];
1582
1584
  scales[scaleType][format].push({
1583
1585
  scaleValue: scaleItem.itemValue,
1584
1586
  scaleDate: scaleItem.itemDate,
1585
- scaleName
1587
+ scaleName: namedScale
1586
1588
  });
1587
1589
  }
1588
1590
  }
@@ -13935,7 +13937,7 @@ function treeMatchUps({
13935
13937
  uuids
13936
13938
  }));
13937
13939
  roundNumber++;
13938
- roundLimit = roundLimit || qualifyingRoundNumber || (qualifyingPositions ? drawSize / 2 / qualifyingPositions : void 0);
13940
+ roundLimit = roundLimit || qualifyingRoundNumber;
13939
13941
  while (roundNodes.length > 1) {
13940
13942
  if (qualifyingPositions && roundNodes.length === qualifyingPositions) {
13941
13943
  roundLimit = roundNumber - 1;
@@ -14092,6 +14094,7 @@ function generateCurtisConsolation(params) {
14092
14094
  finishingPositionOffset,
14093
14095
  structureName = MAIN,
14094
14096
  stageSequence = 1,
14097
+ structureNameMap,
14095
14098
  staggeredEntry,
14096
14099
  stage = MAIN,
14097
14100
  matchUpType,
@@ -14125,8 +14128,9 @@ function generateCurtisConsolation(params) {
14125
14128
  const consolationItems = feedRoundOffsets.map((roundOffset, index) => {
14126
14129
  const stageSequence2 = index + 1;
14127
14130
  const { consolationStructure } = consolationFeedStructure({
14128
- structureId: uuids?.pop(),
14129
14131
  idPrefix: idPrefix && `${idPrefix}-c${index}`,
14132
+ structureId: uuids?.pop(),
14133
+ structureNameMap,
14130
14134
  stageSequence: stageSequence2,
14131
14135
  roundOffset,
14132
14136
  matchUpType,
@@ -14155,9 +14159,9 @@ function generateCurtisConsolation(params) {
14155
14159
  isMock
14156
14160
  });
14157
14161
  const playoffStructure = structureTemplate({
14162
+ structureName: structureNameMap?.[PLAY_OFF] || PLAY_OFF,
14158
14163
  structureId: uuids?.pop(),
14159
14164
  matchUps: playoffMatchUps,
14160
- structureName: PLAY_OFF,
14161
14165
  stageSequence: 2,
14162
14166
  stage: PLAY_OFF,
14163
14167
  matchUpType
@@ -14182,6 +14186,7 @@ function generateCurtisConsolation(params) {
14182
14186
  }
14183
14187
  function consolationFeedStructure({
14184
14188
  stageSequence = 1,
14189
+ structureNameMap,
14185
14190
  roundOffset = 0,
14186
14191
  matchUpType,
14187
14192
  structureId,
@@ -14202,7 +14207,8 @@ function consolationFeedStructure({
14202
14207
  isMock,
14203
14208
  uuids
14204
14209
  });
14205
- const structureName = `${CONSOLATION} ${index + 1}`;
14210
+ const defaultName = `${CONSOLATION} ${index + 1}`;
14211
+ const structureName = structureNameMap?.[defaultName] || defaultName;
14206
14212
  const consolationStructure = structureTemplate({
14207
14213
  matchUps: consolationMatchUps,
14208
14214
  stage: CONSOLATION,
@@ -14487,6 +14493,7 @@ function processPlayoffGroups({
14487
14493
  }
14488
14494
  const params = {
14489
14495
  structureId: playoffGroup.structureId ?? uuids?.pop(),
14496
+ structureNameMap: playoffGroup.structureNameMap,
14490
14497
  structureName: playoffGroup.structureName,
14491
14498
  idPrefix: idPrefix && `${idPrefix}-po`,
14492
14499
  appliedPolicies: policyDefinitions,
@@ -19605,98 +19612,6 @@ function generateVoluntaryConsolation(params) {
19605
19612
  return generateVoluntaryConsolation$1({ participants: tournamentParticipants, ...params });
19606
19613
  }
19607
19614
 
19608
- function generateCandidate({
19609
- maxIterations = 5e3,
19610
- // cap the processing intensity of the candidate generator
19611
- valueSortedPairings,
19612
- // pairings sorted by value from low to high
19613
- pairingValues,
19614
- deltaObjects
19615
- }) {
19616
- const rankedMatchUpValues = Object.assign(
19617
- {},
19618
- ...valueSortedPairings.map((rm) => ({ [rm.pairing]: rm.value }))
19619
- );
19620
- let candidate = roundCandidate({
19621
- rankedMatchUpValues,
19622
- valueSortedPairings,
19623
- deltaObjects
19624
- });
19625
- let deltaCandidate = candidate;
19626
- const actors = Object.keys(pairingValues);
19627
- let candidatesCount = 0;
19628
- let iterations;
19629
- let opponentCount = actors.length;
19630
- do {
19631
- opponentCount -= 1;
19632
- iterations = actors.length * opponentCount * valueSortedPairings.length / 2;
19633
- } while (iterations > maxIterations && opponentCount > 2);
19634
- const stipulatedPairs = [];
19635
- actors.forEach((actor) => {
19636
- const participantIdPairings = pairingValues[actor];
19637
- participantIdPairings.slice(0, opponentCount).forEach((pairing) => {
19638
- const stipulatedPair = pairingHash(actor, pairing.opponent);
19639
- if (!stipulatedPairs.includes(stipulatedPair)) {
19640
- const proposed = roundCandidate({
19641
- // each roundCandidate starts with stipulated pairings
19642
- stipulated: [[actor, pairing.opponent]],
19643
- rankedMatchUpValues,
19644
- valueSortedPairings,
19645
- deltaObjects
19646
- });
19647
- if (proposed.maxDelta < deltaCandidate.maxDelta)
19648
- deltaCandidate = proposed;
19649
- if (proposed.value < candidate.value)
19650
- candidate = proposed;
19651
- stipulatedPairs.push(stipulatedPair);
19652
- candidatesCount += 1;
19653
- }
19654
- });
19655
- });
19656
- return { candidate, deltaCandidate, candidatesCount, iterations };
19657
- }
19658
- function roundCandidate({
19659
- rankedMatchUpValues,
19660
- valueSortedPairings,
19661
- stipulated = [],
19662
- deltaObjects
19663
- }) {
19664
- const roundPlayers = [].concat(...stipulated);
19665
- const participantIdPairings = [];
19666
- let candidateValue = 0;
19667
- stipulated.filter(Boolean).forEach((participantIds) => {
19668
- const [p1, p2] = participantIds;
19669
- const pairing = pairingHash(p1, p2);
19670
- const value = rankedMatchUpValues[pairing];
19671
- participantIdPairings.push({ participantIds, value });
19672
- candidateValue += rankedMatchUpValues[pairing];
19673
- });
19674
- valueSortedPairings.forEach((rankedPairing) => {
19675
- const participantIds = rankedPairing.pairing.split("|");
19676
- const opponentExists = participantIds.reduce(
19677
- (p, c) => roundPlayers.includes(c) || p,
19678
- false
19679
- );
19680
- if (!opponentExists) {
19681
- roundPlayers.push(...participantIds);
19682
- const value = rankedPairing.value;
19683
- candidateValue += value;
19684
- participantIdPairings.push({ participantIds, value });
19685
- }
19686
- });
19687
- participantIdPairings.sort((a, b) => a.value - b.value);
19688
- const maxDelta = participantIdPairings.reduce((p, c) => {
19689
- const [p1, p2] = c.participantIds;
19690
- const hash = pairingHash(p1, p2);
19691
- const delta = deltaObjects[hash];
19692
- return delta > p ? delta : p;
19693
- }, 0);
19694
- return { value: candidateValue, participantIdPairings, maxDelta };
19695
- }
19696
- function pairingHash(id1, id2) {
19697
- return [id1, id2].sort().join("|");
19698
- }
19699
-
19700
19615
  function generateAdHocMatchUps({
19701
19616
  participantIdPairings,
19702
19617
  addToStructure = true,
@@ -19831,11 +19746,315 @@ function addAdHocMatchUps({
19831
19746
  return { ...SUCCESS };
19832
19747
  }
19833
19748
 
19834
- const ENCOUNTER_VALUE = 50;
19835
- const SAME_TEAM_VALUE = 60;
19749
+ function generateCandidate({
19750
+ maxIterations = 4e3,
19751
+ // cap the processing intensity of the candidate generator
19752
+ valueSortedPairings,
19753
+ // pairings sorted by value from low to high
19754
+ pairingValues,
19755
+ valueObjects,
19756
+ deltaObjects
19757
+ }) {
19758
+ const pairingValueMap = Object.assign(
19759
+ {},
19760
+ ...valueSortedPairings.map((rm) => ({ [rm.pairing]: rm.value }))
19761
+ );
19762
+ const actors = Object.keys(pairingValues);
19763
+ let proposedCandidates = [];
19764
+ const initialProposal = roundCandidate({
19765
+ actorsCount: actors.length,
19766
+ valueSortedPairings,
19767
+ pairingValueMap,
19768
+ deltaObjects,
19769
+ valueObjects
19770
+ });
19771
+ const candidateHashes = [candidateHash(initialProposal)];
19772
+ proposedCandidates.push(initialProposal);
19773
+ let lowCandidateValue = initialProposal.value;
19774
+ let deltaCandidate = initialProposal;
19775
+ let candidatesCount = 0;
19776
+ let iterations = 0;
19777
+ let opponentCount = actors.length;
19778
+ let calculatedIterations;
19779
+ do {
19780
+ opponentCount -= 1;
19781
+ calculatedIterations = actors.length * pairingValues[actors[0]].length;
19782
+ } while (calculatedIterations > maxIterations && opponentCount > 5);
19783
+ const stipulatedPairs = [];
19784
+ actors.forEach((actor) => {
19785
+ const participantIdPairings = pairingValues[actor];
19786
+ participantIdPairings.slice(0, opponentCount).forEach((pairing) => {
19787
+ iterations += 1;
19788
+ const stipulatedPair = pairingHash(actor, pairing.opponent);
19789
+ if (!stipulatedPairs.includes(stipulatedPair)) {
19790
+ const proposed = roundCandidate({
19791
+ // each roundCandidate starts with stipulated pairings
19792
+ stipulated: [[actor, pairing.opponent]],
19793
+ actorsCount: actors.length,
19794
+ valueSortedPairings,
19795
+ pairingValueMap,
19796
+ deltaObjects,
19797
+ valueObjects
19798
+ });
19799
+ if (!candidateHashes.includes(candidateHash(proposed))) {
19800
+ candidateHashes.push(candidateHash(proposed));
19801
+ proposedCandidates.push(proposed);
19802
+ const { maxDelta, value } = proposed;
19803
+ if (maxDelta < deltaCandidate.maxDelta)
19804
+ deltaCandidate = proposed;
19805
+ if (value < lowCandidateValue || value === lowCandidateValue && Math.round(Math.random())) {
19806
+ lowCandidateValue = value;
19807
+ }
19808
+ stipulatedPairs.push(stipulatedPair);
19809
+ candidatesCount += 1;
19810
+ }
19811
+ }
19812
+ });
19813
+ proposedCandidates = proposedCandidates.filter(
19814
+ (proposed) => Math.abs(proposed.value - lowCandidateValue) < 5
19815
+ );
19816
+ });
19817
+ proposedCandidates.sort((a, b) => a.maxDiff - b.maxDiff);
19818
+ const candidate = randomPop(proposedCandidates);
19819
+ return {
19820
+ candidatesCount,
19821
+ deltaCandidate,
19822
+ maxIterations,
19823
+ iterations,
19824
+ candidate
19825
+ };
19826
+ }
19827
+ function candidateHash(candidate) {
19828
+ return candidate.participantIdPairings.map(({ participantIds }) => participantIds.sort().join("|")).sort().join("/");
19829
+ }
19830
+ function roundCandidate({
19831
+ valueSortedPairings,
19832
+ stipulated = [],
19833
+ pairingValueMap,
19834
+ deltaObjects,
19835
+ valueObjects,
19836
+ actorsCount
19837
+ }) {
19838
+ const roundPlayers = [].concat(...stipulated);
19839
+ const participantIdPairings = [];
19840
+ let candidateValue = 0;
19841
+ stipulated.filter(Boolean).forEach((participantIds) => {
19842
+ const [p1, p2] = participantIds;
19843
+ const pairing = pairingHash(p1, p2);
19844
+ const value = pairingValueMap[pairing];
19845
+ participantIdPairings.push({ participantIds, value });
19846
+ candidateValue += pairingValueMap[pairing];
19847
+ });
19848
+ const consideredPairings = chunkArray(valueSortedPairings, actorsCount).map(
19849
+ (pairings) => shuffleArray(pairings).map((pairing) => ({
19850
+ ...pairing,
19851
+ value: pairing.value + Math.random() * Math.round(Math.random())
19852
+ }))
19853
+ ).flat();
19854
+ consideredPairings.forEach((rankedPairing) => {
19855
+ const participantIds = rankedPairing.pairing.split("|");
19856
+ const opponentExists = participantIds.reduce(
19857
+ (p, c) => roundPlayers.includes(c) || p,
19858
+ false
19859
+ );
19860
+ if (!opponentExists) {
19861
+ roundPlayers.push(...participantIds);
19862
+ const value = rankedPairing.value;
19863
+ candidateValue += value;
19864
+ participantIdPairings.push({ participantIds, value });
19865
+ }
19866
+ });
19867
+ participantIdPairings.sort((a, b) => a.value - b.value);
19868
+ const maxDelta = participantIdPairings.reduce((p, c) => {
19869
+ const [p1, p2] = c.participantIds;
19870
+ const hash = pairingHash(p1, p2);
19871
+ const delta = deltaObjects[hash];
19872
+ return delta > p ? delta : p;
19873
+ }, 0);
19874
+ const maxDiff = participantIdPairings.reduce((p, c) => {
19875
+ const [p1, p2] = c.participantIds;
19876
+ const hash = pairingHash(p1, p2);
19877
+ const diff = valueObjects[hash];
19878
+ return diff > p ? diff : p;
19879
+ }, 0);
19880
+ return { value: candidateValue, participantIdPairings, maxDelta, maxDiff };
19881
+ }
19882
+ function pairingHash(id1, id2) {
19883
+ return [id1, id2].sort().join("|");
19884
+ }
19885
+
19886
+ function getPairingsData({ participantIds }) {
19887
+ const possiblePairings = {};
19888
+ const uniquePairings = [];
19889
+ participantIds.forEach((participantId) => {
19890
+ possiblePairings[participantId] = participantIds.filter(
19891
+ (id) => id !== participantId
19892
+ );
19893
+ possiblePairings[participantId].forEach((id) => {
19894
+ const pairing = pairingHash(id, participantId);
19895
+ if (!uniquePairings.includes(pairing))
19896
+ uniquePairings.push(pairing);
19897
+ });
19898
+ });
19899
+ const deltaObjects = Object.assign(
19900
+ {},
19901
+ ...uniquePairings.map((pairing) => ({ [pairing]: 0 }))
19902
+ );
19903
+ return { uniquePairings, possiblePairings, deltaObjects };
19904
+ }
19905
+
19906
+ function getEncounters({ matchUps }) {
19907
+ const encounters = [];
19908
+ for (const matchUp of matchUps) {
19909
+ const participantIds = matchUp.sides.map(
19910
+ extractAttributes("participantId")
19911
+ );
19912
+ if (participantIds.length === 2) {
19913
+ const [p1, p2] = participantIds;
19914
+ const pairing = pairingHash(p1, p2);
19915
+ if (!encounters.includes(pairing))
19916
+ encounters.push(pairing);
19917
+ }
19918
+ }
19919
+ return { encounters };
19920
+ }
19921
+
19922
+ function getParticipantPairingValues({
19923
+ possiblePairings,
19924
+ valueObjects
19925
+ }) {
19926
+ const pairingValues = {};
19927
+ for (const participantId of Object.keys(possiblePairings)) {
19928
+ const participantValues = possiblePairings[participantId].map(
19929
+ (opponent) => pairingValue(participantId, opponent)
19930
+ );
19931
+ pairingValues[participantId] = participantValues.sort(
19932
+ (a, b) => a.value - b.value
19933
+ );
19934
+ }
19935
+ function pairingValue(participantId, opponent) {
19936
+ const key = pairingHash(participantId, opponent);
19937
+ return { opponent, value: valueObjects[key] };
19938
+ }
19939
+ return { pairingValues };
19940
+ }
19941
+
19942
+ const ELO = "ELO";
19943
+ const NTRP = "NTRP";
19944
+ const UTR = "UTR";
19945
+ const WTN = "WTN";
19946
+
19947
+ const ratingsParameters = {
19948
+ [ELO]: { range: [0, 3e3], decimalsCount: 0, defaultInitialization: 1500 },
19949
+ [NTRP]: {
19950
+ accessors: ["ntrpRating", "dntrpRatingHundredths"],
19951
+ attributes: { ustaRatingType: "" },
19952
+ accessor: "dntrpRatingHundredths",
19953
+ defaultInitialization: 3,
19954
+ decimalsCount: 1,
19955
+ range: [1, 7]
19956
+ },
19957
+ [UTR]: {
19958
+ defaultInitialization: 6,
19959
+ accessors: ["utrRating"],
19960
+ accessor: "utrRating",
19961
+ decimalsCount: 2,
19962
+ range: [1, 16]
19963
+ },
19964
+ [WTN]: {
19965
+ attributes: { confidence: { generator: true, range: [60, 100] } },
19966
+ accessors: ["wtnRating", "confidence"],
19967
+ defaultInitialization: 23,
19968
+ accessor: "wtnRating",
19969
+ decimalsCount: 2,
19970
+ range: [40, 1]
19971
+ }
19972
+ };
19973
+
19836
19974
  const DEFAULT_RATING = 0;
19837
- const MAX_ITERATIONS = 5e3;
19975
+ function getSideRatings({
19976
+ tournamentParticipants,
19977
+ adHocRatings,
19978
+ eventType,
19979
+ scaleName,
19980
+ pairing
19981
+ }) {
19982
+ const defaultRating = ratingsParameters[scaleName]?.defaultInitialization ?? DEFAULT_RATING;
19983
+ return pairing.split("|").map((participantId) => {
19984
+ if (eventType === DOUBLES) {
19985
+ const individualParticipantIds = tournamentParticipants?.find(
19986
+ (participant) => participant.participantId === participantId
19987
+ )?.individualParticipantIds;
19988
+ return !individualParticipantIds ? defaultRating * 2 : individualParticipantIds?.map(
19989
+ (participantId2) => adHocRatings[participantId2] || defaultRating
19990
+ );
19991
+ } else {
19992
+ return adHocRatings[participantId] || defaultRating;
19993
+ }
19994
+ });
19995
+ }
19996
+
19997
+ function getPairings({
19998
+ tournamentParticipants,
19999
+ adHocRatings = {},
20000
+ possiblePairings,
20001
+ // participant keyed; provides array of possible opponents
20002
+ uniquePairings,
20003
+ // hashes of all possible participantId pairings
20004
+ maxIterations,
20005
+ deltaObjects,
20006
+ // difference in rating between paired participants
20007
+ valueObjects,
20008
+ // calculated value of a pairing of participants, used for sorting pairings
20009
+ eventType,
20010
+ scaleName,
20011
+ salted
20012
+ }) {
20013
+ uniquePairings.forEach((pairing) => {
20014
+ const ratings = getSideRatings({
20015
+ tournamentParticipants,
20016
+ adHocRatings,
20017
+ scaleName,
20018
+ eventType,
20019
+ pairing
20020
+ });
20021
+ const salting = typeof salted === "number" && salted || 0.5;
20022
+ const salt = salted && (Math.round(Math.random()) ? salting : salting * -1) || 0;
20023
+ const ratingsDifference = Math.abs(ratings[0] - ratings[1]) + salt;
20024
+ const pairingDelta = Math.abs(ratings[0] - ratings[1]);
20025
+ deltaObjects[pairing] = pairingDelta;
20026
+ if (!valueObjects[pairing])
20027
+ valueObjects[pairing] = 0;
20028
+ valueObjects[pairing] += ratingsDifference ? Math.pow(ratingsDifference, 2) : 0;
20029
+ });
20030
+ const valueSortedPairings = uniquePairings.map((pairing) => ({ pairing, value: valueObjects[pairing] })).sort((a, b) => a.value - b.value);
20031
+ const { pairingValues } = getParticipantPairingValues({
20032
+ possiblePairings,
20033
+ valueObjects
20034
+ });
20035
+ const { candidate, candidatesCount, deltaCandidate, iterations } = generateCandidate({
20036
+ valueSortedPairings,
20037
+ maxIterations,
20038
+ pairingValues,
20039
+ deltaObjects,
20040
+ valueObjects
20041
+ });
20042
+ const { participantIdPairings } = candidate;
20043
+ return {
20044
+ participantIdPairings,
20045
+ candidatesCount,
20046
+ deltaCandidate,
20047
+ iterations,
20048
+ candidate
20049
+ };
20050
+ }
20051
+
20052
+ const ENCOUNTER_VALUE = 100;
20053
+ const SAME_TEAM_VALUE = 100;
20054
+ const MAX_ITERATIONS = 4e3;
19838
20055
  function generateDrawMaticRound({
20056
+ encounterValue = ENCOUNTER_VALUE,
20057
+ sameTeamValue = SAME_TEAM_VALUE,
19839
20058
  maxIterations = MAX_ITERATIONS,
19840
20059
  generateMatchUps = true,
19841
20060
  tournamentParticipants,
@@ -19845,9 +20064,11 @@ function generateDrawMaticRound({
19845
20064
  drawDefinition,
19846
20065
  adHocRatings,
19847
20066
  structureId,
20067
+ salted = 0.5,
19848
20068
  matchUpIds,
19849
20069
  eventType,
19850
- structure
20070
+ structure,
20071
+ scaleName
19851
20072
  }) {
19852
20073
  if (!drawDefinition)
19853
20074
  return { error: MISSING_DRAW_DEFINITION };
@@ -19866,7 +20087,7 @@ function generateDrawMaticRound({
19866
20087
  for (const pairing of encounters) {
19867
20088
  if (!valueObjects[pairing])
19868
20089
  valueObjects[pairing] = 0;
19869
- valueObjects[pairing] += ENCOUNTER_VALUE;
20090
+ valueObjects[pairing] += encounterValue;
19870
20091
  }
19871
20092
  const teamParticipants = tournamentParticipants?.filter(
19872
20093
  ({ participantType }) => participantType === TEAM
@@ -19878,7 +20099,7 @@ function generateDrawMaticRound({
19878
20099
  for (const pairing of uniquePairings2) {
19879
20100
  if (!valueObjects[pairing])
19880
20101
  valueObjects[pairing] = 0;
19881
- valueObjects[pairing] += SAME_TEAM_VALUE;
20102
+ valueObjects[pairing] += sameTeamValue;
19882
20103
  }
19883
20104
  }
19884
20105
  }
@@ -19896,9 +20117,11 @@ function generateDrawMaticRound({
19896
20117
  deltaObjects,
19897
20118
  valueObjects,
19898
20119
  eventType,
19899
- structure
20120
+ scaleName,
20121
+ structure,
20122
+ salted
19900
20123
  };
19901
- const { candidatesCount, participantIdPairings, iterations } = getPairings(params);
20124
+ const { candidatesCount, participantIdPairings, iterations, candidate } = getPairings(params);
19902
20125
  if (!candidatesCount)
19903
20126
  return { error: NO_CANDIDATES };
19904
20127
  let matchUps;
@@ -19916,122 +20139,17 @@ function generateDrawMaticRound({
19916
20139
  return result;
19917
20140
  matchUps = result.matchUps;
19918
20141
  }
20142
+ const { maxDelta, maxDiff } = candidate;
19919
20143
  return {
19920
20144
  ...SUCCESS,
19921
20145
  participantIdPairings,
19922
20146
  candidatesCount,
19923
20147
  iterations,
19924
- matchUps
20148
+ matchUps,
20149
+ maxDelta,
20150
+ maxDiff
19925
20151
  };
19926
20152
  }
19927
- function getSideRatings({
19928
- tournamentParticipants,
19929
- adHocRatings,
19930
- eventType,
19931
- pairing
19932
- }) {
19933
- return pairing.split("|").map((participantId) => {
19934
- if (eventType === DOUBLES) {
19935
- const individualParticipantIds = tournamentParticipants?.find(
19936
- (participant) => participant.participantId === participantId
19937
- )?.individualParticipantIds;
19938
- return !individualParticipantIds ? DEFAULT_RATING * 2 : individualParticipantIds?.map(
19939
- (participantId2) => adHocRatings[participantId2 || DEFAULT_RATING]
19940
- );
19941
- } else {
19942
- return adHocRatings[participantId] || DEFAULT_RATING;
19943
- }
19944
- });
19945
- }
19946
- function getPairings({
19947
- tournamentParticipants,
19948
- adHocRatings = {},
19949
- possiblePairings,
19950
- // participant keyed; provides array of possible opponents
19951
- uniquePairings,
19952
- // hashes of all possible participantId pairings
19953
- maxIterations,
19954
- deltaObjects,
19955
- // difference in rating between paired participants
19956
- valueObjects,
19957
- // calculated value of a pairing of participants, used for sorting pairings
19958
- eventType
19959
- }) {
19960
- uniquePairings.forEach((pairing) => {
19961
- const ratings = getSideRatings({
19962
- tournamentParticipants,
19963
- adHocRatings,
19964
- eventType,
19965
- pairing
19966
- });
19967
- const ratingsDifference = Math.abs(ratings[0] - ratings[1]) + 1;
19968
- deltaObjects[pairing] = Math.abs(ratings[0] - ratings[1]);
19969
- if (!valueObjects[pairing])
19970
- valueObjects[pairing] = 0;
19971
- valueObjects[pairing] += Math.pow(ratingsDifference, 2);
19972
- });
19973
- const valueSortedPairings = uniquePairings.map((pairing) => ({ pairing, value: valueObjects[pairing] })).sort((a, b) => a.value - b.value);
19974
- const { pairingValues } = getParticipantPairingValues({
19975
- possiblePairings,
19976
- valueObjects
19977
- });
19978
- const { candidate, candidatesCount, iterations } = generateCandidate({
19979
- valueSortedPairings,
19980
- maxIterations,
19981
- pairingValues,
19982
- deltaObjects
19983
- });
19984
- const { participantIdPairings } = candidate;
19985
- return { candidatesCount, participantIdPairings, iterations };
19986
- }
19987
- function getPairingsData({ participantIds }) {
19988
- const possiblePairings = {};
19989
- const uniquePairings = [];
19990
- participantIds.forEach((participantId) => {
19991
- possiblePairings[participantId] = participantIds.filter(
19992
- (id) => id !== participantId
19993
- );
19994
- possiblePairings[participantId].forEach((id) => {
19995
- const pairing = pairingHash(id, participantId);
19996
- if (!uniquePairings.includes(pairing))
19997
- uniquePairings.push(pairing);
19998
- });
19999
- });
20000
- const deltaObjects = Object.assign(
20001
- {},
20002
- ...uniquePairings.map((pairing) => ({ [pairing]: 0 }))
20003
- );
20004
- return { uniquePairings, possiblePairings, deltaObjects };
20005
- }
20006
- function getEncounters({ matchUps }) {
20007
- const encounters = [];
20008
- for (const matchUp of matchUps) {
20009
- const participantIds = matchUp.sides.map(getParticipantId);
20010
- if (participantIds.length === 2) {
20011
- const [p1, p2] = participantIds;
20012
- const pairing = pairingHash(p1, p2);
20013
- if (!encounters.includes(pairing))
20014
- encounters.push(pairing);
20015
- }
20016
- }
20017
- return { encounters };
20018
- }
20019
- function getParticipantPairingValues({ possiblePairings, valueObjects }) {
20020
- const pairingValues = {};
20021
- for (const participantId of Object.keys(possiblePairings)) {
20022
- const participantValues = possiblePairings[participantId].map(
20023
- (opponent) => pairingValue(participantId, opponent)
20024
- );
20025
- pairingValues[participantId] = participantValues.sort(
20026
- (a, b) => a.value - b.value
20027
- );
20028
- }
20029
- function pairingValue(participantId, opponent) {
20030
- const key = pairingHash(participantId, opponent);
20031
- return { opponent, value: valueObjects[key] };
20032
- }
20033
- return { pairingValues };
20034
- }
20035
20153
 
20036
20154
  function generateQualifyingLink({
20037
20155
  targetEntryRound = 1,
@@ -22567,10 +22685,13 @@ function prepareStage(params) {
22567
22685
  function drawMatic({
22568
22686
  tournamentParticipants,
22569
22687
  restrictEntryStatus,
22570
- tournamentRecord,
22688
+ adHocRatings = {},
22571
22689
  generateMatchUps,
22690
+ tournamentRecord,
22572
22691
  addToStructure,
22573
22692
  participantIds,
22693
+ encounterValue,
22694
+ sameTeamValue,
22574
22695
  drawDefinition,
22575
22696
  scaleAccessor,
22576
22697
  maxIterations,
@@ -22579,6 +22700,7 @@ function drawMatic({
22579
22700
  scaleName,
22580
22701
  // custom rating name to seed dynamic ratings
22581
22702
  eventType,
22703
+ salted,
22582
22704
  event
22583
22705
  }) {
22584
22706
  if (typeof drawDefinition !== "object" || drawDefinition.drawType && drawDefinition.drawType !== AD_HOC) {
@@ -22621,12 +22743,16 @@ function drawMatic({
22621
22743
  if (!structureIsAdHoc)
22622
22744
  return { error: INVALID_DRAW_DEFINITION };
22623
22745
  tournamentParticipants = tournamentParticipants ?? tournamentRecord.participants ?? [];
22624
- const adHocRatings = {};
22625
22746
  for (const participantId of participantIds ?? []) {
22626
22747
  const participant = tournamentParticipants?.find(
22627
22748
  (participant2) => participant2.participantId === participantId
22628
22749
  );
22629
- let scaleValue = getScaleValue({ eventType, participant });
22750
+ let scaleValue = getScaleValue({
22751
+ scaleName: `${scaleName}.${DYNAMIC}`,
22752
+ scaleAccessor,
22753
+ participant,
22754
+ eventType
22755
+ });
22630
22756
  if (!scaleValue && scaleName) {
22631
22757
  scaleValue = getScaleValue({
22632
22758
  scaleAccessor,
@@ -22635,32 +22761,36 @@ function drawMatic({
22635
22761
  eventType
22636
22762
  });
22637
22763
  }
22638
- if (scaleValue)
22764
+ if (scaleValue && !adHocRatings[participantId])
22639
22765
  adHocRatings[participantId] = scaleValue;
22640
22766
  }
22641
22767
  return generateDrawMaticRound({
22642
22768
  tournamentParticipants,
22643
- tournamentRecord,
22644
22769
  generateMatchUps,
22645
- participantIds,
22770
+ tournamentRecord,
22646
22771
  addToStructure,
22772
+ participantIds,
22773
+ encounterValue,
22774
+ sameTeamValue,
22647
22775
  drawDefinition,
22648
22776
  maxIterations,
22649
22777
  adHocRatings,
22650
22778
  matchUpIds,
22651
22779
  structure,
22652
- eventType
22780
+ eventType,
22781
+ salted
22653
22782
  });
22654
22783
  }
22655
22784
  function getScaleValue({
22656
- eventType = TypeEnum.Singles,
22657
- scaleName = "dynamic",
22785
+ scaleType = RATING,
22658
22786
  scaleAccessor,
22659
- participant
22787
+ participant,
22788
+ scaleName,
22789
+ eventType
22660
22790
  }) {
22661
22791
  const scaleAttributes = {
22662
22792
  eventType: eventType || TypeEnum.Singles,
22663
- scaleType: RATING,
22793
+ scaleType,
22664
22794
  scaleName
22665
22795
  };
22666
22796
  const result = participant && participantScaleItem({