tods-competition-factory 1.7.3 → 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.
@@ -1406,8 +1406,9 @@ type GenerateDrawMaticRoundArgs = {
1406
1406
  };
1407
1407
  restrictEntryStatus?: boolean;
1408
1408
  drawDefinition: DrawDefinition;
1409
- generateMatchUps?: boolean;
1410
1409
  tournamentRecord: Tournament;
1410
+ generateMatchUps?: boolean;
1411
+ salted?: number | boolean;
1411
1412
  participantIds?: string[];
1412
1413
  addToStructure?: boolean;
1413
1414
  maxIterations?: number;
@@ -1415,9 +1416,10 @@ type GenerateDrawMaticRoundArgs = {
1415
1416
  structure?: Structure;
1416
1417
  structureId?: string;
1417
1418
  eventType?: TypeEnum;
1419
+ scaleName?: string;
1418
1420
  drawId?: string;
1419
1421
  };
1420
- declare function generateDrawMaticRound({ maxIterations, generateMatchUps, tournamentParticipants, tournamentRecord, participantIds, addToStructure, drawDefinition, adHocRatings, structureId, matchUpIds, eventType, structure, }: GenerateDrawMaticRoundArgs): ResultType | {
1422
+ declare function generateDrawMaticRound({ maxIterations, generateMatchUps, tournamentParticipants, tournamentRecord, participantIds, addToStructure, drawDefinition, adHocRatings, structureId, salted, matchUpIds, eventType, structure, scaleName, }: GenerateDrawMaticRoundArgs): ResultType | {
1421
1423
  participantIdPairings: string[][];
1422
1424
  candidatesCount: number;
1423
1425
  matchUps: MatchUp[];
@@ -1427,6 +1429,9 @@ declare function generateDrawMaticRound({ maxIterations, generateMatchUps, tourn
1427
1429
 
1428
1430
  type DrawMaticArgs = {
1429
1431
  tournamentParticipants?: HydratedParticipant[];
1432
+ adHocRatings?: {
1433
+ [key: string]: number;
1434
+ };
1430
1435
  restrictEntryStatus?: boolean;
1431
1436
  drawDefinition?: DrawDefinition;
1432
1437
  tournamentRecord: Tournament;
@@ -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";
@@ -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,
@@ -19831,9 +19745,311 @@ function addAdHocMatchUps({
19831
19745
  return { ...SUCCESS };
19832
19746
  }
19833
19747
 
19834
- const ENCOUNTER_VALUE = 50;
19835
- 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
+
19836
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;
19837
20053
  const MAX_ITERATIONS = 5e3;
19838
20054
  function generateDrawMaticRound({
19839
20055
  maxIterations = MAX_ITERATIONS,
@@ -19845,9 +20061,11 @@ function generateDrawMaticRound({
19845
20061
  drawDefinition,
19846
20062
  adHocRatings,
19847
20063
  structureId,
20064
+ salted = 0.5,
19848
20065
  matchUpIds,
19849
20066
  eventType,
19850
- structure
20067
+ structure,
20068
+ scaleName
19851
20069
  }) {
19852
20070
  if (!drawDefinition)
19853
20071
  return { error: MISSING_DRAW_DEFINITION };
@@ -19896,7 +20114,9 @@ function generateDrawMaticRound({
19896
20114
  deltaObjects,
19897
20115
  valueObjects,
19898
20116
  eventType,
19899
- structure
20117
+ scaleName,
20118
+ structure,
20119
+ salted
19900
20120
  };
19901
20121
  const { candidatesCount, participantIdPairings, iterations } = getPairings(params);
19902
20122
  if (!candidatesCount)
@@ -19924,114 +20144,6 @@ function generateDrawMaticRound({
19924
20144
  matchUps
19925
20145
  };
19926
20146
  }
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
20147
 
20036
20148
  function generateQualifyingLink({
20037
20149
  targetEntryRound = 1,
@@ -22567,6 +22679,7 @@ function prepareStage(params) {
22567
22679
  function drawMatic({
22568
22680
  tournamentParticipants,
22569
22681
  restrictEntryStatus,
22682
+ adHocRatings = {},
22570
22683
  tournamentRecord,
22571
22684
  generateMatchUps,
22572
22685
  addToStructure,
@@ -22621,12 +22734,16 @@ function drawMatic({
22621
22734
  if (!structureIsAdHoc)
22622
22735
  return { error: INVALID_DRAW_DEFINITION };
22623
22736
  tournamentParticipants = tournamentParticipants ?? tournamentRecord.participants ?? [];
22624
- const adHocRatings = {};
22625
22737
  for (const participantId of participantIds ?? []) {
22626
22738
  const participant = tournamentParticipants?.find(
22627
22739
  (participant2) => participant2.participantId === participantId
22628
22740
  );
22629
- let scaleValue = getScaleValue({ eventType, participant });
22741
+ let scaleValue = getScaleValue({
22742
+ scaleName: `${scaleName}.${DYNAMIC}`,
22743
+ scaleAccessor,
22744
+ participant,
22745
+ eventType
22746
+ });
22630
22747
  if (!scaleValue && scaleName) {
22631
22748
  scaleValue = getScaleValue({
22632
22749
  scaleAccessor,
@@ -22635,7 +22752,7 @@ function drawMatic({
22635
22752
  eventType
22636
22753
  });
22637
22754
  }
22638
- if (scaleValue)
22755
+ if (scaleValue && !adHocRatings[participantId])
22639
22756
  adHocRatings[participantId] = scaleValue;
22640
22757
  }
22641
22758
  return generateDrawMaticRound({
@@ -22653,14 +22770,15 @@ function drawMatic({
22653
22770
  });
22654
22771
  }
22655
22772
  function getScaleValue({
22656
- eventType = TypeEnum.Singles,
22657
- scaleName = "dynamic",
22773
+ scaleType = RATING,
22658
22774
  scaleAccessor,
22659
- participant
22775
+ participant,
22776
+ scaleName,
22777
+ eventType
22660
22778
  }) {
22661
22779
  const scaleAttributes = {
22662
22780
  eventType: eventType || TypeEnum.Singles,
22663
- scaleType: RATING,
22781
+ scaleType,
22664
22782
  scaleName
22665
22783
  };
22666
22784
  const result = participant && participantScaleItem({