tods-competition-factory 1.7.2 → 1.7.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.
@@ -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";
@@ -2962,7 +2963,7 @@ function getRoundMatchUps({
2962
2963
  roundProfile[roundNumber].finishingRound = finishingRoundMap[roundNumber]?.finishingRound;
2963
2964
  roundProfile[roundNumber].roundName = finishingRoundMap[roundNumber]?.roundName;
2964
2965
  roundProfile[roundNumber].abbreviatedRoundName = finishingRoundMap[roundNumber]?.abbreviatedRoundName;
2965
- roundProfile[roundNumber].finishingPositionRange = roundMatchUps[roundNumber][0].finishingPositionRange;
2966
+ roundProfile[roundNumber].finishingPositionRange = roundMatchUps[roundNumber]?.[0]?.finishingPositionRange;
2966
2967
  if (roundNumber === 1 || !roundProfile[roundNumber - 1]) {
2967
2968
  const orderedDrawPositions = currentRoundDrawPositions.sort(numericSort);
2968
2969
  const pairedDrawPositions = chunkArray(orderedDrawPositions, 2);
@@ -14092,6 +14093,7 @@ function generateCurtisConsolation(params) {
14092
14093
  finishingPositionOffset,
14093
14094
  structureName = MAIN,
14094
14095
  stageSequence = 1,
14096
+ structureNameMap,
14095
14097
  staggeredEntry,
14096
14098
  stage = MAIN,
14097
14099
  matchUpType,
@@ -14125,8 +14127,9 @@ function generateCurtisConsolation(params) {
14125
14127
  const consolationItems = feedRoundOffsets.map((roundOffset, index) => {
14126
14128
  const stageSequence2 = index + 1;
14127
14129
  const { consolationStructure } = consolationFeedStructure({
14128
- structureId: uuids?.pop(),
14129
14130
  idPrefix: idPrefix && `${idPrefix}-c${index}`,
14131
+ structureId: uuids?.pop(),
14132
+ structureNameMap,
14130
14133
  stageSequence: stageSequence2,
14131
14134
  roundOffset,
14132
14135
  matchUpType,
@@ -14155,9 +14158,9 @@ function generateCurtisConsolation(params) {
14155
14158
  isMock
14156
14159
  });
14157
14160
  const playoffStructure = structureTemplate({
14161
+ structureName: structureNameMap?.[PLAY_OFF] || PLAY_OFF,
14158
14162
  structureId: uuids?.pop(),
14159
14163
  matchUps: playoffMatchUps,
14160
- structureName: PLAY_OFF,
14161
14164
  stageSequence: 2,
14162
14165
  stage: PLAY_OFF,
14163
14166
  matchUpType
@@ -14182,6 +14185,7 @@ function generateCurtisConsolation(params) {
14182
14185
  }
14183
14186
  function consolationFeedStructure({
14184
14187
  stageSequence = 1,
14188
+ structureNameMap,
14185
14189
  roundOffset = 0,
14186
14190
  matchUpType,
14187
14191
  structureId,
@@ -14202,7 +14206,8 @@ function consolationFeedStructure({
14202
14206
  isMock,
14203
14207
  uuids
14204
14208
  });
14205
- const structureName = `${CONSOLATION} ${index + 1}`;
14209
+ const defaultName = `${CONSOLATION} ${index + 1}`;
14210
+ const structureName = structureNameMap?.[defaultName] || defaultName;
14206
14211
  const consolationStructure = structureTemplate({
14207
14212
  matchUps: consolationMatchUps,
14208
14213
  stage: CONSOLATION,
@@ -14487,6 +14492,7 @@ function processPlayoffGroups({
14487
14492
  }
14488
14493
  const params = {
14489
14494
  structureId: playoffGroup.structureId ?? uuids?.pop(),
14495
+ structureNameMap: playoffGroup.structureNameMap,
14490
14496
  structureName: playoffGroup.structureName,
14491
14497
  idPrefix: idPrefix && `${idPrefix}-po`,
14492
14498
  appliedPolicies: policyDefinitions,
@@ -19605,98 +19611,6 @@ function generateVoluntaryConsolation(params) {
19605
19611
  return generateVoluntaryConsolation$1({ participants: tournamentParticipants, ...params });
19606
19612
  }
19607
19613
 
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
19614
  function generateAdHocMatchUps({
19701
19615
  participantIdPairings,
19702
19616
  addToStructure = true,
@@ -19714,21 +19628,30 @@ function generateAdHocMatchUps({
19714
19628
  structureId = drawDefinition.structures?.[0]?.structureId;
19715
19629
  if (typeof structureId !== "string")
19716
19630
  return { error: MISSING_STRUCTURE_ID };
19717
- if (newRound && !matchUpsCount) {
19631
+ const structure = drawDefinition.structures?.find(
19632
+ (structure2) => structure2.structureId === structureId
19633
+ );
19634
+ if (!structure)
19635
+ return { error: STRUCTURE_NOT_FOUND };
19636
+ if (!matchUpsCount) {
19718
19637
  const selectedEntries = drawDefinition?.entries?.filter((entry) => {
19719
19638
  const entryStatus = entry.entryStatus;
19720
19639
  return STRUCTURE_SELECTED_STATUSES.includes(entryStatus);
19721
19640
  }) ?? [];
19722
- matchUpsCount = Math.floor(selectedEntries?.length / 2) || 1;
19641
+ const roundMatchUpsCount = Math.floor(selectedEntries?.length / 2) || 1;
19642
+ if (newRound) {
19643
+ matchUpsCount = roundMatchUpsCount;
19644
+ } else {
19645
+ const maxRemaining = roundMatchUpsCount - (structure.matchUps?.length || 0);
19646
+ if (maxRemaining > 0)
19647
+ matchUpsCount = maxRemaining;
19648
+ }
19723
19649
  }
19724
19650
  if (participantIdPairings && !Array.isArray(participantIdPairings) || matchUpsCount && !isConvertableInteger(matchUpsCount) || matchUpIds && !Array.isArray(matchUpIds) || !participantIdPairings && !matchUpsCount) {
19725
19651
  return { error: INVALID_VALUES, info: "matchUpsCount or pairings error" };
19726
19652
  }
19727
- const structure = drawDefinition?.structures?.find(
19728
- (structure2) => structure2.structureId === structureId
19729
- );
19730
19653
  let structureHasRoundPositions;
19731
- const existingMatchUps = structure?.matchUps;
19654
+ const existingMatchUps = structure.matchUps ?? [];
19732
19655
  const lastRoundNumber = existingMatchUps?.reduce(
19733
19656
  (roundNumber2, matchUp) => {
19734
19657
  if (matchUp.roundPosition)
@@ -19737,12 +19660,12 @@ function generateAdHocMatchUps({
19737
19660
  },
19738
19661
  0
19739
19662
  );
19740
- if (structure?.structures || structureHasRoundPositions || structure?.finishingPosition === ROUND_OUTCOME) {
19663
+ if (structure.structures || structureHasRoundPositions || structure.finishingPosition === ROUND_OUTCOME) {
19741
19664
  return { error: INVALID_STRUCTURE };
19742
19665
  }
19743
19666
  if (roundNumber && roundNumber - 1 > (lastRoundNumber || 0))
19744
19667
  return { error: INVALID_VALUES, info: "roundNumber error" };
19745
- const nextRoundNumber = roundNumber ?? (newRound ? (lastRoundNumber ?? 0) + 1 : lastRoundNumber ?? 1);
19668
+ const nextRoundNumber = roundNumber ?? (newRound && (lastRoundNumber ?? 0) + 1 || lastRoundNumber || 1);
19746
19669
  participantIdPairings = participantIdPairings ?? generateRange(0, matchUpsCount).map(() => ({
19747
19670
  participantIds: [void 0, void 0]
19748
19671
  }));
@@ -19822,9 +19745,311 @@ function addAdHocMatchUps({
19822
19745
  return { ...SUCCESS };
19823
19746
  }
19824
19747
 
19825
- const ENCOUNTER_VALUE = 50;
19826
- const SAME_TEAM_VALUE = 60;
19748
+ function generateCandidate({
19749
+ maxIterations = 4e3,
19750
+ // cap the processing intensity of the candidate generator
19751
+ valueSortedPairings,
19752
+ // pairings sorted by value from low to high
19753
+ pairingValues,
19754
+ valueObjects,
19755
+ deltaObjects
19756
+ }) {
19757
+ const pairingValueMap = Object.assign(
19758
+ {},
19759
+ ...valueSortedPairings.map((rm) => ({ [rm.pairing]: rm.value }))
19760
+ );
19761
+ const actors = Object.keys(pairingValues);
19762
+ let proposedCandidates = [];
19763
+ const initialProposal = roundCandidate({
19764
+ actorsCount: actors.length,
19765
+ valueSortedPairings,
19766
+ pairingValueMap,
19767
+ deltaObjects,
19768
+ valueObjects
19769
+ });
19770
+ const candidateHashes = [candidateHash(initialProposal)];
19771
+ proposedCandidates.push(initialProposal);
19772
+ let lowCandidateValue = initialProposal.value;
19773
+ let deltaCandidate = initialProposal;
19774
+ let candidatesCount = 0;
19775
+ let iterations = 0;
19776
+ let opponentCount = actors.length;
19777
+ let calculatedIterations;
19778
+ do {
19779
+ opponentCount -= 1;
19780
+ calculatedIterations = actors.length * pairingValues[actors[0]].length;
19781
+ } while (calculatedIterations > maxIterations && opponentCount > 5);
19782
+ const stipulatedPairs = [];
19783
+ actors.forEach((actor) => {
19784
+ const participantIdPairings = pairingValues[actor];
19785
+ participantIdPairings.slice(0, opponentCount).forEach((pairing) => {
19786
+ iterations += 1;
19787
+ const stipulatedPair = pairingHash(actor, pairing.opponent);
19788
+ if (!stipulatedPairs.includes(stipulatedPair)) {
19789
+ const proposed = roundCandidate({
19790
+ // each roundCandidate starts with stipulated pairings
19791
+ stipulated: [[actor, pairing.opponent]],
19792
+ actorsCount: actors.length,
19793
+ valueSortedPairings,
19794
+ pairingValueMap,
19795
+ deltaObjects,
19796
+ valueObjects
19797
+ });
19798
+ if (!candidateHashes.includes(candidateHash(proposed))) {
19799
+ candidateHashes.push(candidateHash(proposed));
19800
+ proposedCandidates.push(proposed);
19801
+ const { maxDelta, value } = proposed;
19802
+ if (maxDelta < deltaCandidate.maxDelta)
19803
+ deltaCandidate = proposed;
19804
+ if (value < lowCandidateValue || value === lowCandidateValue && Math.round(Math.random())) {
19805
+ lowCandidateValue = value;
19806
+ }
19807
+ stipulatedPairs.push(stipulatedPair);
19808
+ candidatesCount += 1;
19809
+ }
19810
+ }
19811
+ });
19812
+ proposedCandidates = proposedCandidates.filter(
19813
+ (proposed) => Math.abs(proposed.value - lowCandidateValue) < 5
19814
+ );
19815
+ });
19816
+ proposedCandidates.sort((a, b) => a.maxDiff - b.maxDiff);
19817
+ const candidate = randomPop(proposedCandidates);
19818
+ return {
19819
+ candidatesCount,
19820
+ deltaCandidate,
19821
+ maxIterations,
19822
+ iterations,
19823
+ candidate
19824
+ };
19825
+ }
19826
+ function candidateHash(candidate) {
19827
+ return candidate.participantIdPairings.map(({ participantIds }) => participantIds.sort().join("|")).sort().join("/");
19828
+ }
19829
+ function roundCandidate({
19830
+ valueSortedPairings,
19831
+ stipulated = [],
19832
+ pairingValueMap,
19833
+ deltaObjects,
19834
+ valueObjects,
19835
+ actorsCount
19836
+ }) {
19837
+ const roundPlayers = [].concat(...stipulated);
19838
+ const participantIdPairings = [];
19839
+ let candidateValue = 0;
19840
+ stipulated.filter(Boolean).forEach((participantIds) => {
19841
+ const [p1, p2] = participantIds;
19842
+ const pairing = pairingHash(p1, p2);
19843
+ const value = pairingValueMap[pairing];
19844
+ participantIdPairings.push({ participantIds, value });
19845
+ candidateValue += pairingValueMap[pairing];
19846
+ });
19847
+ const consideredPairings = chunkArray(valueSortedPairings, actorsCount).map(
19848
+ (pairings) => shuffleArray(pairings).map((pairing) => ({
19849
+ ...pairing,
19850
+ value: pairing.value + Math.random() * Math.round(Math.random())
19851
+ }))
19852
+ ).flat();
19853
+ consideredPairings.forEach((rankedPairing) => {
19854
+ const participantIds = rankedPairing.pairing.split("|");
19855
+ const opponentExists = participantIds.reduce(
19856
+ (p, c) => roundPlayers.includes(c) || p,
19857
+ false
19858
+ );
19859
+ if (!opponentExists) {
19860
+ roundPlayers.push(...participantIds);
19861
+ const value = rankedPairing.value;
19862
+ candidateValue += value;
19863
+ participantIdPairings.push({ participantIds, value });
19864
+ }
19865
+ });
19866
+ participantIdPairings.sort((a, b) => a.value - b.value);
19867
+ const maxDelta = participantIdPairings.reduce((p, c) => {
19868
+ const [p1, p2] = c.participantIds;
19869
+ const hash = pairingHash(p1, p2);
19870
+ const delta = deltaObjects[hash];
19871
+ return delta > p ? delta : p;
19872
+ }, 0);
19873
+ const maxDiff = participantIdPairings.reduce((p, c) => {
19874
+ const [p1, p2] = c.participantIds;
19875
+ const hash = pairingHash(p1, p2);
19876
+ const diff = valueObjects[hash];
19877
+ return diff > p ? diff : p;
19878
+ }, 0);
19879
+ return { value: candidateValue, participantIdPairings, maxDelta, maxDiff };
19880
+ }
19881
+ function pairingHash(id1, id2) {
19882
+ return [id1, id2].sort().join("|");
19883
+ }
19884
+
19885
+ function getPairingsData({ participantIds }) {
19886
+ const possiblePairings = {};
19887
+ const uniquePairings = [];
19888
+ participantIds.forEach((participantId) => {
19889
+ possiblePairings[participantId] = participantIds.filter(
19890
+ (id) => id !== participantId
19891
+ );
19892
+ possiblePairings[participantId].forEach((id) => {
19893
+ const pairing = pairingHash(id, participantId);
19894
+ if (!uniquePairings.includes(pairing))
19895
+ uniquePairings.push(pairing);
19896
+ });
19897
+ });
19898
+ const deltaObjects = Object.assign(
19899
+ {},
19900
+ ...uniquePairings.map((pairing) => ({ [pairing]: 0 }))
19901
+ );
19902
+ return { uniquePairings, possiblePairings, deltaObjects };
19903
+ }
19904
+
19905
+ function getEncounters({ matchUps }) {
19906
+ const encounters = [];
19907
+ for (const matchUp of matchUps) {
19908
+ const participantIds = matchUp.sides.map(
19909
+ extractAttributes("participantId")
19910
+ );
19911
+ if (participantIds.length === 2) {
19912
+ const [p1, p2] = participantIds;
19913
+ const pairing = pairingHash(p1, p2);
19914
+ if (!encounters.includes(pairing))
19915
+ encounters.push(pairing);
19916
+ }
19917
+ }
19918
+ return { encounters };
19919
+ }
19920
+
19921
+ function getParticipantPairingValues({
19922
+ possiblePairings,
19923
+ valueObjects
19924
+ }) {
19925
+ const pairingValues = {};
19926
+ for (const participantId of Object.keys(possiblePairings)) {
19927
+ const participantValues = possiblePairings[participantId].map(
19928
+ (opponent) => pairingValue(participantId, opponent)
19929
+ );
19930
+ pairingValues[participantId] = participantValues.sort(
19931
+ (a, b) => a.value - b.value
19932
+ );
19933
+ }
19934
+ function pairingValue(participantId, opponent) {
19935
+ const key = pairingHash(participantId, opponent);
19936
+ return { opponent, value: valueObjects[key] };
19937
+ }
19938
+ return { pairingValues };
19939
+ }
19940
+
19941
+ const ELO = "ELO";
19942
+ const NTRP = "NTRP";
19943
+ const UTR = "UTR";
19944
+ const WTN = "WTN";
19945
+
19946
+ const ratingsParameters = {
19947
+ [ELO]: { range: [0, 3e3], decimalsCount: 0, defaultInitialization: 1500 },
19948
+ [NTRP]: {
19949
+ accessors: ["ntrpRating", "dntrpRatingHundredths"],
19950
+ attributes: { ustaRatingType: "" },
19951
+ accessor: "dntrpRatingHundredths",
19952
+ defaultInitialization: 3,
19953
+ decimalsCount: 1,
19954
+ range: [1, 7]
19955
+ },
19956
+ [UTR]: {
19957
+ defaultInitialization: 6,
19958
+ accessors: ["utrRating"],
19959
+ accessor: "utrRating",
19960
+ decimalsCount: 2,
19961
+ range: [1, 16]
19962
+ },
19963
+ [WTN]: {
19964
+ attributes: { confidence: { generator: true, range: [60, 100] } },
19965
+ accessors: ["wtnRating", "confidence"],
19966
+ defaultInitialization: 23,
19967
+ accessor: "wtnRating",
19968
+ decimalsCount: 2,
19969
+ range: [40, 1]
19970
+ }
19971
+ };
19972
+
19827
19973
  const DEFAULT_RATING = 0;
19974
+ function getSideRatings({
19975
+ tournamentParticipants,
19976
+ adHocRatings,
19977
+ eventType,
19978
+ scaleName,
19979
+ pairing
19980
+ }) {
19981
+ const defaultRating = ratingsParameters[scaleName]?.defaultInitialization ?? DEFAULT_RATING;
19982
+ return pairing.split("|").map((participantId) => {
19983
+ if (eventType === DOUBLES) {
19984
+ const individualParticipantIds = tournamentParticipants?.find(
19985
+ (participant) => participant.participantId === participantId
19986
+ )?.individualParticipantIds;
19987
+ return !individualParticipantIds ? defaultRating * 2 : individualParticipantIds?.map(
19988
+ (participantId2) => adHocRatings[participantId2] || defaultRating
19989
+ );
19990
+ } else {
19991
+ return adHocRatings[participantId] || defaultRating;
19992
+ }
19993
+ });
19994
+ }
19995
+
19996
+ function getPairings({
19997
+ tournamentParticipants,
19998
+ adHocRatings = {},
19999
+ possiblePairings,
20000
+ // participant keyed; provides array of possible opponents
20001
+ uniquePairings,
20002
+ // hashes of all possible participantId pairings
20003
+ maxIterations,
20004
+ deltaObjects,
20005
+ // difference in rating between paired participants
20006
+ valueObjects,
20007
+ // calculated value of a pairing of participants, used for sorting pairings
20008
+ eventType,
20009
+ scaleName,
20010
+ salted
20011
+ }) {
20012
+ uniquePairings.forEach((pairing) => {
20013
+ const ratings = getSideRatings({
20014
+ tournamentParticipants,
20015
+ adHocRatings,
20016
+ scaleName,
20017
+ eventType,
20018
+ pairing
20019
+ });
20020
+ const salting = typeof salted === "number" && salted || 0.5;
20021
+ const salt = salted && (Math.round(Math.random()) ? salting : salting * -1) || 0;
20022
+ const ratingsDifference = Math.abs(ratings[0] - ratings[1]) + salt;
20023
+ const pairingDelta = Math.abs(ratings[0] - ratings[1]);
20024
+ deltaObjects[pairing] = pairingDelta;
20025
+ if (!valueObjects[pairing])
20026
+ valueObjects[pairing] = 0;
20027
+ valueObjects[pairing] += ratingsDifference ? Math.pow(ratingsDifference, 2) : 0;
20028
+ });
20029
+ const valueSortedPairings = uniquePairings.map((pairing) => ({ pairing, value: valueObjects[pairing] })).sort((a, b) => a.value - b.value);
20030
+ const { pairingValues } = getParticipantPairingValues({
20031
+ possiblePairings,
20032
+ valueObjects
20033
+ });
20034
+ const { candidate, candidatesCount, deltaCandidate, iterations } = generateCandidate({
20035
+ valueSortedPairings,
20036
+ maxIterations,
20037
+ pairingValues,
20038
+ deltaObjects,
20039
+ valueObjects
20040
+ });
20041
+ const { participantIdPairings } = candidate;
20042
+ return {
20043
+ participantIdPairings,
20044
+ candidatesCount,
20045
+ deltaCandidate,
20046
+ iterations,
20047
+ candidate
20048
+ };
20049
+ }
20050
+
20051
+ const ENCOUNTER_VALUE = 100;
20052
+ const SAME_TEAM_VALUE = 100;
19828
20053
  const MAX_ITERATIONS = 5e3;
19829
20054
  function generateDrawMaticRound({
19830
20055
  maxIterations = MAX_ITERATIONS,
@@ -19836,9 +20061,11 @@ function generateDrawMaticRound({
19836
20061
  drawDefinition,
19837
20062
  adHocRatings,
19838
20063
  structureId,
20064
+ salted = 0.5,
19839
20065
  matchUpIds,
19840
20066
  eventType,
19841
- structure
20067
+ structure,
20068
+ scaleName
19842
20069
  }) {
19843
20070
  if (!drawDefinition)
19844
20071
  return { error: MISSING_DRAW_DEFINITION };
@@ -19887,7 +20114,9 @@ function generateDrawMaticRound({
19887
20114
  deltaObjects,
19888
20115
  valueObjects,
19889
20116
  eventType,
19890
- structure
20117
+ scaleName,
20118
+ structure,
20119
+ salted
19891
20120
  };
19892
20121
  const { candidatesCount, participantIdPairings, iterations } = getPairings(params);
19893
20122
  if (!candidatesCount)
@@ -19915,114 +20144,6 @@ function generateDrawMaticRound({
19915
20144
  matchUps
19916
20145
  };
19917
20146
  }
19918
- function getSideRatings({
19919
- tournamentParticipants,
19920
- adHocRatings,
19921
- eventType,
19922
- pairing
19923
- }) {
19924
- return pairing.split("|").map((participantId) => {
19925
- if (eventType === DOUBLES) {
19926
- const individualParticipantIds = tournamentParticipants?.find(
19927
- (participant) => participant.participantId === participantId
19928
- )?.individualParticipantIds;
19929
- return !individualParticipantIds ? DEFAULT_RATING * 2 : individualParticipantIds?.map(
19930
- (participantId2) => adHocRatings[participantId2 || DEFAULT_RATING]
19931
- );
19932
- } else {
19933
- return adHocRatings[participantId] || DEFAULT_RATING;
19934
- }
19935
- });
19936
- }
19937
- function getPairings({
19938
- tournamentParticipants,
19939
- adHocRatings = {},
19940
- possiblePairings,
19941
- // participant keyed; provides array of possible opponents
19942
- uniquePairings,
19943
- // hashes of all possible participantId pairings
19944
- maxIterations,
19945
- deltaObjects,
19946
- // difference in rating between paired participants
19947
- valueObjects,
19948
- // calculated value of a pairing of participants, used for sorting pairings
19949
- eventType
19950
- }) {
19951
- uniquePairings.forEach((pairing) => {
19952
- const ratings = getSideRatings({
19953
- tournamentParticipants,
19954
- adHocRatings,
19955
- eventType,
19956
- pairing
19957
- });
19958
- const ratingsDifference = Math.abs(ratings[0] - ratings[1]) + 1;
19959
- deltaObjects[pairing] = Math.abs(ratings[0] - ratings[1]);
19960
- if (!valueObjects[pairing])
19961
- valueObjects[pairing] = 0;
19962
- valueObjects[pairing] += Math.pow(ratingsDifference, 2);
19963
- });
19964
- const valueSortedPairings = uniquePairings.map((pairing) => ({ pairing, value: valueObjects[pairing] })).sort((a, b) => a.value - b.value);
19965
- const { pairingValues } = getParticipantPairingValues({
19966
- possiblePairings,
19967
- valueObjects
19968
- });
19969
- const { candidate, candidatesCount, iterations } = generateCandidate({
19970
- valueSortedPairings,
19971
- maxIterations,
19972
- pairingValues,
19973
- deltaObjects
19974
- });
19975
- const { participantIdPairings } = candidate;
19976
- return { candidatesCount, participantIdPairings, iterations };
19977
- }
19978
- function getPairingsData({ participantIds }) {
19979
- const possiblePairings = {};
19980
- const uniquePairings = [];
19981
- participantIds.forEach((participantId) => {
19982
- possiblePairings[participantId] = participantIds.filter(
19983
- (id) => id !== participantId
19984
- );
19985
- possiblePairings[participantId].forEach((id) => {
19986
- const pairing = pairingHash(id, participantId);
19987
- if (!uniquePairings.includes(pairing))
19988
- uniquePairings.push(pairing);
19989
- });
19990
- });
19991
- const deltaObjects = Object.assign(
19992
- {},
19993
- ...uniquePairings.map((pairing) => ({ [pairing]: 0 }))
19994
- );
19995
- return { uniquePairings, possiblePairings, deltaObjects };
19996
- }
19997
- function getEncounters({ matchUps }) {
19998
- const encounters = [];
19999
- for (const matchUp of matchUps) {
20000
- const participantIds = matchUp.sides.map(getParticipantId);
20001
- if (participantIds.length === 2) {
20002
- const [p1, p2] = participantIds;
20003
- const pairing = pairingHash(p1, p2);
20004
- if (!encounters.includes(pairing))
20005
- encounters.push(pairing);
20006
- }
20007
- }
20008
- return { encounters };
20009
- }
20010
- function getParticipantPairingValues({ possiblePairings, valueObjects }) {
20011
- const pairingValues = {};
20012
- for (const participantId of Object.keys(possiblePairings)) {
20013
- const participantValues = possiblePairings[participantId].map(
20014
- (opponent) => pairingValue(participantId, opponent)
20015
- );
20016
- pairingValues[participantId] = participantValues.sort(
20017
- (a, b) => a.value - b.value
20018
- );
20019
- }
20020
- function pairingValue(participantId, opponent) {
20021
- const key = pairingHash(participantId, opponent);
20022
- return { opponent, value: valueObjects[key] };
20023
- }
20024
- return { pairingValues };
20025
- }
20026
20147
 
20027
20148
  function generateQualifyingLink({
20028
20149
  targetEntryRound = 1,
@@ -22558,6 +22679,7 @@ function prepareStage(params) {
22558
22679
  function drawMatic({
22559
22680
  tournamentParticipants,
22560
22681
  restrictEntryStatus,
22682
+ adHocRatings = {},
22561
22683
  tournamentRecord,
22562
22684
  generateMatchUps,
22563
22685
  addToStructure,
@@ -22612,12 +22734,16 @@ function drawMatic({
22612
22734
  if (!structureIsAdHoc)
22613
22735
  return { error: INVALID_DRAW_DEFINITION };
22614
22736
  tournamentParticipants = tournamentParticipants ?? tournamentRecord.participants ?? [];
22615
- const adHocRatings = {};
22616
22737
  for (const participantId of participantIds ?? []) {
22617
22738
  const participant = tournamentParticipants?.find(
22618
22739
  (participant2) => participant2.participantId === participantId
22619
22740
  );
22620
- let scaleValue = getScaleValue({ eventType, participant });
22741
+ let scaleValue = getScaleValue({
22742
+ scaleName: `${scaleName}.${DYNAMIC}`,
22743
+ scaleAccessor,
22744
+ participant,
22745
+ eventType
22746
+ });
22621
22747
  if (!scaleValue && scaleName) {
22622
22748
  scaleValue = getScaleValue({
22623
22749
  scaleAccessor,
@@ -22626,7 +22752,7 @@ function drawMatic({
22626
22752
  eventType
22627
22753
  });
22628
22754
  }
22629
- if (scaleValue)
22755
+ if (scaleValue && !adHocRatings[participantId])
22630
22756
  adHocRatings[participantId] = scaleValue;
22631
22757
  }
22632
22758
  return generateDrawMaticRound({
@@ -22644,14 +22770,15 @@ function drawMatic({
22644
22770
  });
22645
22771
  }
22646
22772
  function getScaleValue({
22647
- eventType = TypeEnum.Singles,
22648
- scaleName = "dynamic",
22773
+ scaleType = RATING,
22649
22774
  scaleAccessor,
22650
- participant
22775
+ participant,
22776
+ scaleName,
22777
+ eventType
22651
22778
  }) {
22652
22779
  const scaleAttributes = {
22653
22780
  eventType: eventType || TypeEnum.Singles,
22654
- scaleType: RATING,
22781
+ scaleType,
22655
22782
  scaleName
22656
22783
  };
22657
22784
  const result = participant && participantScaleItem({