@firestone-hs/bgs-global-stats 1.0.53 → 1.0.54

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.
@@ -85,10 +85,18 @@ export interface InternalBgsGlobalCompStat {
85
85
  readonly archetype: string;
86
86
  readonly dataPoints: number;
87
87
  readonly averagePlacement: number;
88
+ readonly placementDistribution: readonly {
89
+ rank: number;
90
+ totalMatches: number;
91
+ }[];
88
92
  readonly heroStats: readonly InternalBgsCompHeroStat[];
89
93
  }
90
94
  export interface InternalBgsCompHeroStat {
91
95
  readonly heroCardId: string;
92
96
  readonly dataPoints: number;
93
97
  readonly averagePlacement: number;
98
+ readonly placementDistribution: readonly {
99
+ rank: number;
100
+ totalMatches: number;
101
+ }[];
94
102
  }
@@ -1 +1 @@
1
- {"version":3,"file":"internal-model.js","sourceRoot":"","sources":["../src/internal-model.ts"],"names":[],"mappings":"","sourcesContent":["import { Race } from '@firestone-hs/reference-data';\r\n\r\n// bgs_run_stats and bgs_run_stats_duo\r\nexport interface InternalBgsRow {\r\n\treadonly id: number;\r\n\treadonly reviewId: string;\r\n\treadonly creationDate: Date;\r\n\treadonly buildNumber: number;\r\n\treadonly rating: number;\r\n\t// Normalized once it goes out of the \"rows.ts\" process\r\n\treadonly heroCardId: string;\r\n\treadonly playerRank: number;\r\n\t/** @deprecated */\r\n\treadonly tribes: string;\r\n\treadonly tribesExpanded: readonly Race[];\r\n\t/** @deprecated */\r\n\treadonly combatWinrate: string;\r\n\t// readonly combatWinrateExpanded: readonly { turn: number; winrate: number }[];\r\n\t/** @deprecated */\r\n\treadonly warbandStats: string;\r\n\t// readonly warbandStatsExpanded: readonly { turn: number; totalStats: number }[];\r\n\treadonly darkmoonPrizes: boolean;\r\n\treadonly quests: boolean;\r\n\treadonly bgsHeroQuests: string;\r\n\treadonly bgsQuestsCompletedTimings: string;\r\n\treadonly bgsQuestsDifficulties: string;\r\n\treadonly bgsHeroQuestRewards: string;\r\n\treadonly bgsAnomalies: string;\r\n\treadonly bgsTrinkets: string;\r\n\treadonly bgsTrinketsOptions: string;\r\n\t/** @deprecated */\r\n\treadonly heroesOptions: string;\r\n\treadonly heroesOptionsExpanded: readonly string[];\r\n\treadonly playedCards: string;\r\n\treadonly playedCardsExpanded: readonly { cardId: string; turn: number }[];\r\n\treadonly archetype: string;\r\n}\r\n\r\nimport { MmrPercentile, WithMmrAndTimePeriod } from './models';\r\n\r\nexport interface InternalBgsTrinketStats {\r\n\treadonly lastUpdateDate: Date;\r\n\treadonly mmrPercentiles: readonly MmrPercentile[];\r\n\treadonly dataPoints: number;\r\n\treadonly trinketStats: readonly WithMmrAndTimePeriod<InternalBgsGlobalTrinketStat>[];\r\n}\r\n\r\nexport interface InternalBgsCompStats {\r\n\treadonly lastUpdateDate: Date;\r\n\treadonly mmrPercentiles: readonly MmrPercentile[];\r\n\treadonly dataPoints: number;\r\n\treadonly compStats: readonly WithMmrAndTimePeriod<InternalBgsGlobalCompStat>[];\r\n}\r\nexport interface InternalBgsCardStats {\r\n\treadonly lastUpdateDate: Date;\r\n\treadonly mmrPercentiles: readonly MmrPercentile[];\r\n\treadonly dataPoints: number;\r\n\treadonly cardStats: readonly WithMmrAndTimePeriod<InternalBgsCardStat>[];\r\n}\r\n\r\nexport interface InternalBgsCardStat {\r\n\treadonly cardId: string;\r\n\treadonly totalPlayed: number;\r\n\treadonly averagePlacement: number;\r\n\treadonly totalOther: number;\r\n\treadonly averagePlacementOther: number;\r\n\treadonly turnStats: readonly InternalBgsCardTurnStat[];\r\n\t// Not tested yet, there are some error in heroStats.turnStats.totalOther, which is always 0\r\n\t// readonly heroStats: readonly InternalBgsCardHeroStat[];\r\n}\r\n\r\nexport interface InternalBgsCardHeroStat {\r\n\treadonly heroCardId: string;\r\n\treadonly totalPlayedWithHero: number;\r\n\treadonly averagePlacement: number;\r\n\treadonly turnStats: readonly InternalBgsCardTurnStat[];\r\n}\r\n\r\nexport interface InternalBgsCardTurnStat {\r\n\treadonly turn: number;\r\n\treadonly totalPlayed: number;\r\n\treadonly averagePlacement: number;\r\n\treadonly totalOther: number;\r\n\treadonly averagePlacementOther: number;\r\n}\r\n\r\nexport interface InternalBgsGlobalTrinketStat {\r\n\treadonly trinketCardId: string;\r\n\treadonly dataPoints: number;\r\n\treadonly totalOffered: number;\r\n\treadonly averagePlacement: number;\r\n\treadonly heroStats: readonly InternalBgsTrinketHeroStat[];\r\n}\r\nexport interface InternalBgsTrinketHeroStat {\r\n\treadonly heroCardId: string;\r\n\treadonly dataPoints: number;\r\n\treadonly averagePlacement: number;\r\n}\r\n\r\nexport interface InternalBgsGlobalCompStat {\r\n\treadonly archetype: string;\r\n\treadonly dataPoints: number;\r\n\treadonly averagePlacement: number;\r\n\treadonly heroStats: readonly InternalBgsCompHeroStat[];\r\n}\r\nexport interface InternalBgsCompHeroStat {\r\n\treadonly heroCardId: string;\r\n\treadonly dataPoints: number;\r\n\treadonly averagePlacement: number;\r\n}\r\n"]}
1
+ {"version":3,"file":"internal-model.js","sourceRoot":"","sources":["../src/internal-model.ts"],"names":[],"mappings":"","sourcesContent":["import { Race } from '@firestone-hs/reference-data';\r\n\r\n// bgs_run_stats and bgs_run_stats_duo\r\nexport interface InternalBgsRow {\r\n\treadonly id: number;\r\n\treadonly reviewId: string;\r\n\treadonly creationDate: Date;\r\n\treadonly buildNumber: number;\r\n\treadonly rating: number;\r\n\t// Normalized once it goes out of the \"rows.ts\" process\r\n\treadonly heroCardId: string;\r\n\treadonly playerRank: number;\r\n\t/** @deprecated */\r\n\treadonly tribes: string;\r\n\treadonly tribesExpanded: readonly Race[];\r\n\t/** @deprecated */\r\n\treadonly combatWinrate: string;\r\n\t// readonly combatWinrateExpanded: readonly { turn: number; winrate: number }[];\r\n\t/** @deprecated */\r\n\treadonly warbandStats: string;\r\n\t// readonly warbandStatsExpanded: readonly { turn: number; totalStats: number }[];\r\n\treadonly darkmoonPrizes: boolean;\r\n\treadonly quests: boolean;\r\n\treadonly bgsHeroQuests: string;\r\n\treadonly bgsQuestsCompletedTimings: string;\r\n\treadonly bgsQuestsDifficulties: string;\r\n\treadonly bgsHeroQuestRewards: string;\r\n\treadonly bgsAnomalies: string;\r\n\treadonly bgsTrinkets: string;\r\n\treadonly bgsTrinketsOptions: string;\r\n\t/** @deprecated */\r\n\treadonly heroesOptions: string;\r\n\treadonly heroesOptionsExpanded: readonly string[];\r\n\treadonly playedCards: string;\r\n\treadonly playedCardsExpanded: readonly { cardId: string; turn: number }[];\r\n\treadonly archetype: string;\r\n}\r\n\r\nimport { MmrPercentile, WithMmrAndTimePeriod } from './models';\r\n\r\nexport interface InternalBgsTrinketStats {\r\n\treadonly lastUpdateDate: Date;\r\n\treadonly mmrPercentiles: readonly MmrPercentile[];\r\n\treadonly dataPoints: number;\r\n\treadonly trinketStats: readonly WithMmrAndTimePeriod<InternalBgsGlobalTrinketStat>[];\r\n}\r\n\r\nexport interface InternalBgsCompStats {\r\n\treadonly lastUpdateDate: Date;\r\n\treadonly mmrPercentiles: readonly MmrPercentile[];\r\n\treadonly dataPoints: number;\r\n\treadonly compStats: readonly WithMmrAndTimePeriod<InternalBgsGlobalCompStat>[];\r\n}\r\nexport interface InternalBgsCardStats {\r\n\treadonly lastUpdateDate: Date;\r\n\treadonly mmrPercentiles: readonly MmrPercentile[];\r\n\treadonly dataPoints: number;\r\n\treadonly cardStats: readonly WithMmrAndTimePeriod<InternalBgsCardStat>[];\r\n}\r\n\r\nexport interface InternalBgsCardStat {\r\n\treadonly cardId: string;\r\n\treadonly totalPlayed: number;\r\n\treadonly averagePlacement: number;\r\n\treadonly totalOther: number;\r\n\treadonly averagePlacementOther: number;\r\n\treadonly turnStats: readonly InternalBgsCardTurnStat[];\r\n\t// Not tested yet, there are some error in heroStats.turnStats.totalOther, which is always 0\r\n\t// readonly heroStats: readonly InternalBgsCardHeroStat[];\r\n}\r\n\r\nexport interface InternalBgsCardHeroStat {\r\n\treadonly heroCardId: string;\r\n\treadonly totalPlayedWithHero: number;\r\n\treadonly averagePlacement: number;\r\n\treadonly turnStats: readonly InternalBgsCardTurnStat[];\r\n}\r\n\r\nexport interface InternalBgsCardTurnStat {\r\n\treadonly turn: number;\r\n\treadonly totalPlayed: number;\r\n\treadonly averagePlacement: number;\r\n\treadonly totalOther: number;\r\n\treadonly averagePlacementOther: number;\r\n}\r\n\r\nexport interface InternalBgsGlobalTrinketStat {\r\n\treadonly trinketCardId: string;\r\n\treadonly dataPoints: number;\r\n\treadonly totalOffered: number;\r\n\treadonly averagePlacement: number;\r\n\treadonly heroStats: readonly InternalBgsTrinketHeroStat[];\r\n}\r\nexport interface InternalBgsTrinketHeroStat {\r\n\treadonly heroCardId: string;\r\n\treadonly dataPoints: number;\r\n\treadonly averagePlacement: number;\r\n}\r\n\r\nexport interface InternalBgsGlobalCompStat {\r\n\treadonly archetype: string;\r\n\treadonly dataPoints: number;\r\n\treadonly averagePlacement: number;\r\n\treadonly placementDistribution: readonly { rank: number; totalMatches: number }[];\r\n\treadonly heroStats: readonly InternalBgsCompHeroStat[];\r\n}\r\nexport interface InternalBgsCompHeroStat {\r\n\treadonly heroCardId: string;\r\n\treadonly dataPoints: number;\r\n\treadonly averagePlacement: number;\r\n\treadonly placementDistribution: readonly { rank: number; totalMatches: number }[];\r\n}\r\n"]}
@@ -11,6 +11,19 @@ export interface BgsCompStat {
11
11
  readonly averagePlacement: number;
12
12
  readonly averagePlacementAtMmr: readonly {
13
13
  mmr: number;
14
+ dataPoints: number;
14
15
  placement: number;
15
16
  }[];
17
+ readonly placementDistribution: readonly {
18
+ rank: number;
19
+ totalMatches: number;
20
+ }[];
21
+ readonly placementDistributionAtMmr: readonly {
22
+ mmr: number;
23
+ dataPoints: number;
24
+ placementDistribution: readonly {
25
+ rank: number;
26
+ totalMatches: number;
27
+ }[];
28
+ }[];
16
29
  }
@@ -1 +1 @@
1
- {"version":3,"file":"model-comps.js","sourceRoot":"","sources":["../src/model-comps.ts"],"names":[],"mappings":"","sourcesContent":["import { TimePeriod } from './models';\r\n\r\nexport interface BgsCompStats {\r\n\treadonly lastUpdateDate: Date;\r\n\treadonly dataPoints: number;\r\n\treadonly timePeriod: TimePeriod;\r\n\treadonly compStats: readonly BgsCompStat[];\r\n}\r\nexport interface BgsCompStat {\r\n\treadonly archetype: string;\r\n\treadonly dataPoints: number;\r\n\treadonly averagePlacement: number;\r\n\treadonly averagePlacementAtMmr: readonly {\r\n\t\tmmr: number;\r\n\t\tplacement: number;\r\n\t}[];\r\n}\r\n"]}
1
+ {"version":3,"file":"model-comps.js","sourceRoot":"","sources":["../src/model-comps.ts"],"names":[],"mappings":"","sourcesContent":["import { TimePeriod } from './models';\r\n\r\nexport interface BgsCompStats {\r\n\treadonly lastUpdateDate: Date;\r\n\treadonly dataPoints: number;\r\n\treadonly timePeriod: TimePeriod;\r\n\treadonly compStats: readonly BgsCompStat[];\r\n}\r\nexport interface BgsCompStat {\r\n\treadonly archetype: string;\r\n\treadonly dataPoints: number;\r\n\treadonly averagePlacement: number;\r\n\treadonly averagePlacementAtMmr: readonly {\r\n\t\tmmr: number;\r\n\t\tdataPoints: number;\r\n\t\tplacement: number;\r\n\t}[];\r\n\treadonly placementDistribution: readonly { rank: number; totalMatches: number }[];\r\n\treadonly placementDistributionAtMmr: readonly {\r\n\t\tmmr: number;\r\n\t\tdataPoints: number;\r\n\t\tplacementDistribution: readonly { rank: number; totalMatches: number }[];\r\n\t}[];\r\n}\r\n"]}
@@ -21,12 +21,40 @@ const buildSingleCompStat = (data, allCards) => {
21
21
  placement: averagePlacement,
22
22
  };
23
23
  });
24
+ const placementDistributionByMmr = _build_aggregated_stats_1.mmrPercentiles.map((percentile) => {
25
+ const allData = data.filter((d) => d.mmrPercentile === percentile);
26
+ const placementDistribution = buildPlacementDistribution(allData);
27
+ return {
28
+ mmr: percentile,
29
+ dataPoints: allData.map((d) => d.dataPoints).reduce((a, b) => a + b, 0),
30
+ placementDistribution: placementDistribution,
31
+ };
32
+ });
33
+ const placementDistribution = buildPlacementDistribution(data);
24
34
  const result = {
25
35
  archetype: ref.archetype,
26
36
  dataPoints: placementByMmr.find((d) => d.mmr === 100).dataPoints,
27
37
  averagePlacement: placementByMmr.find((d) => d.mmr === 100).placement,
28
38
  averagePlacementAtMmr: placementByMmr,
39
+ placementDistribution: placementDistribution,
40
+ placementDistributionAtMmr: placementDistributionByMmr,
29
41
  };
30
42
  return result;
31
43
  };
44
+ const buildPlacementDistribution = (data) => {
45
+ var _a;
46
+ const placementDistribution = [];
47
+ for (const d of data) {
48
+ for (const placement of (_a = d.placementDistribution) !== null && _a !== void 0 ? _a : []) {
49
+ const existing = placementDistribution.find((p) => p.rank === placement.rank);
50
+ if (existing) {
51
+ existing.totalMatches += placement.totalMatches;
52
+ }
53
+ else {
54
+ placementDistribution.push(placement);
55
+ }
56
+ }
57
+ }
58
+ return placementDistribution;
59
+ };
32
60
  //# sourceMappingURL=stats-builder.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stats-builder.js","sourceRoot":"","sources":["../../../../src/solo/aggregate-hourly/comps/stats-builder.ts"],"names":[],"mappings":";;;AAAA,qEAAiE;AAEjE,mEAAyD;AAIzD,uEAA2D;AAEpD,MAAM,cAAc,GAAG,CAC7B,UAA2C,EAC3C,QAAyB,EACA,EAAE;IAC3B,MAAM,YAAY,GAA+D,UAAU,CAAC,OAAO,CAClG,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CACxB,CAAC;IACF,MAAM,aAAa,GAAG,IAAA,kCAAe,EAAC,CAAC,IAAqD,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAC/G,YAAY,CACZ,CAAC;IACF,OAAO,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,mBAAmB,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC/G,CAAC,CAAC;AAXW,QAAA,cAAc,kBAWzB;AAEF,MAAM,mBAAmB,GAAG,CAC3B,IAAgE,EAChE,QAAyB,EACX,EAAE;IAChB,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,cAAc,GAId,wCAAc,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,UAAU,CAAC,CAAC;QACnE,MAAM,gBAAgB,GAAG,IAAA,wBAAO,EAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC;QACzE,OAAO;YACN,GAAG,EAAE,UAAU;YACf,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACvE,SAAS,EAAE,gBAAgB;SAC3B,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAgB;QAC3B,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,UAAU,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,UAAU;QAChE,gBAAgB,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,SAAS;QACrE,qBAAqB,EAAE,cAAc;KACrC,CAAC;IACF,OAAO,MAAM,CAAC;AACf,CAAC,CAAC","sourcesContent":["import { groupByFunction } from '@firestone-hs/aws-lambda-utils';\r\nimport { AllCardsService } from '@firestone-hs/reference-data';\r\nimport { average } from '../../../common/util-functions';\r\nimport { InternalBgsCompStats, InternalBgsGlobalCompStat } from '../../../internal-model';\r\nimport { BgsCompStat } from '../../../model-comps';\r\nimport { WithMmrAndTimePeriod } from '../../../models';\r\nimport { mmrPercentiles } from './_build-aggregated-stats';\r\n\r\nexport const buildCompStats = (\r\n\thourlyData: readonly InternalBgsCompStats[],\r\n\tallCards: AllCardsService,\r\n): readonly BgsCompStat[] => {\r\n\tconst allCompStats: readonly WithMmrAndTimePeriod<InternalBgsGlobalCompStat>[] = hourlyData.flatMap(\r\n\t\t(data) => data.compStats,\r\n\t);\r\n\tconst groupedByComp = groupByFunction((data: WithMmrAndTimePeriod<InternalBgsGlobalCompStat>) => data.archetype)(\r\n\t\tallCompStats,\r\n\t);\r\n\treturn Object.keys(groupedByComp).map((archetype) => buildSingleCompStat(groupedByComp[archetype], allCards));\r\n};\r\n\r\nconst buildSingleCompStat = (\r\n\tdata: readonly WithMmrAndTimePeriod<InternalBgsGlobalCompStat>[],\r\n\tallCards: AllCardsService,\r\n): BgsCompStat => {\r\n\tconst ref = data[0];\r\n\tconst placementByMmr: readonly {\r\n\t\tmmr: number;\r\n\t\tdataPoints: number;\r\n\t\tplacement: number;\r\n\t}[] = mmrPercentiles.map((percentile) => {\r\n\t\tconst allData = data.filter((d) => d.mmrPercentile === percentile);\r\n\t\tconst averagePlacement = average(allData.map((d) => d.averagePlacement));\r\n\t\treturn {\r\n\t\t\tmmr: percentile,\r\n\t\t\tdataPoints: allData.map((d) => d.dataPoints).reduce((a, b) => a + b, 0),\r\n\t\t\tplacement: averagePlacement,\r\n\t\t};\r\n\t});\r\n\r\n\tconst result: BgsCompStat = {\r\n\t\tarchetype: ref.archetype,\r\n\t\tdataPoints: placementByMmr.find((d) => d.mmr === 100).dataPoints,\r\n\t\taveragePlacement: placementByMmr.find((d) => d.mmr === 100).placement,\r\n\t\taveragePlacementAtMmr: placementByMmr,\r\n\t};\r\n\treturn result;\r\n};\r\n"]}
1
+ {"version":3,"file":"stats-builder.js","sourceRoot":"","sources":["../../../../src/solo/aggregate-hourly/comps/stats-builder.ts"],"names":[],"mappings":"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","sourcesContent":["import { groupByFunction } from '@firestone-hs/aws-lambda-utils';\r\nimport { AllCardsService } from '@firestone-hs/reference-data';\r\nimport { average } from '../../../common/util-functions';\r\nimport { InternalBgsCompStats, InternalBgsGlobalCompStat } from '../../../internal-model';\r\nimport { BgsCompStat } from '../../../model-comps';\r\nimport { WithMmrAndTimePeriod } from '../../../models';\r\nimport { mmrPercentiles } from './_build-aggregated-stats';\r\n\r\nexport const buildCompStats = (\r\n\thourlyData: readonly InternalBgsCompStats[],\r\n\tallCards: AllCardsService,\r\n): readonly BgsCompStat[] => {\r\n\tconst allCompStats: readonly WithMmrAndTimePeriod<InternalBgsGlobalCompStat>[] = hourlyData.flatMap(\r\n\t\t(data) => data.compStats,\r\n\t);\r\n\tconst groupedByComp = groupByFunction((data: WithMmrAndTimePeriod<InternalBgsGlobalCompStat>) => data.archetype)(\r\n\t\tallCompStats,\r\n\t);\r\n\treturn Object.keys(groupedByComp).map((archetype) => buildSingleCompStat(groupedByComp[archetype], allCards));\r\n};\r\n\r\nconst buildSingleCompStat = (\r\n\tdata: readonly WithMmrAndTimePeriod<InternalBgsGlobalCompStat>[],\r\n\tallCards: AllCardsService,\r\n): BgsCompStat => {\r\n\tconst ref = data[0];\r\n\tconst placementByMmr: readonly {\r\n\t\tmmr: number;\r\n\t\tdataPoints: number;\r\n\t\tplacement: number;\r\n\t}[] = mmrPercentiles.map((percentile) => {\r\n\t\tconst allData = data.filter((d) => d.mmrPercentile === percentile);\r\n\t\tconst averagePlacement = average(allData.map((d) => d.averagePlacement));\r\n\t\treturn {\r\n\t\t\tmmr: percentile,\r\n\t\t\tdataPoints: allData.map((d) => d.dataPoints).reduce((a, b) => a + b, 0),\r\n\t\t\tplacement: averagePlacement,\r\n\t\t};\r\n\t});\r\n\tconst placementDistributionByMmr: readonly {\r\n\t\tmmr: number;\r\n\t\tdataPoints: number;\r\n\t\tplacementDistribution: readonly { rank: number; totalMatches: number }[];\r\n\t}[] = mmrPercentiles.map((percentile) => {\r\n\t\tconst allData = data.filter((d) => d.mmrPercentile === percentile);\r\n\t\tconst placementDistribution = buildPlacementDistribution(allData);\r\n\t\treturn {\r\n\t\t\tmmr: percentile,\r\n\t\t\tdataPoints: allData.map((d) => d.dataPoints).reduce((a, b) => a + b, 0),\r\n\t\t\tplacementDistribution: placementDistribution,\r\n\t\t};\r\n\t});\r\n\tconst placementDistribution = buildPlacementDistribution(data);\r\n\r\n\tconst result: BgsCompStat = {\r\n\t\tarchetype: ref.archetype,\r\n\t\tdataPoints: placementByMmr.find((d) => d.mmr === 100).dataPoints,\r\n\t\taveragePlacement: placementByMmr.find((d) => d.mmr === 100).placement,\r\n\t\taveragePlacementAtMmr: placementByMmr,\r\n\t\tplacementDistribution: placementDistribution,\r\n\t\tplacementDistributionAtMmr: placementDistributionByMmr,\r\n\t};\r\n\treturn result;\r\n};\r\n\r\nconst buildPlacementDistribution = (\r\n\tdata: readonly WithMmrAndTimePeriod<InternalBgsGlobalCompStat>[],\r\n): readonly { rank: number; totalMatches: number }[] => {\r\n\tconst placementDistribution: { rank: number; totalMatches: number }[] = [];\r\n\tfor (const d of data) {\r\n\t\tfor (const placement of d.placementDistribution ?? []) {\r\n\t\t\tconst existing = placementDistribution.find((p) => p.rank === placement.rank);\r\n\t\t\tif (existing) {\r\n\t\t\t\texisting.totalMatches += placement.totalMatches;\r\n\t\t\t} else {\r\n\t\t\t\tplacementDistribution.push(placement);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn placementDistribution;\r\n};\r\n"]}
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildCompStatsForMmr = void 0;
4
4
  const aws_lambda_utils_1 = require("@firestone-hs/aws-lambda-utils");
5
+ const utils_1 = require("../utils");
5
6
  const buildCompStatsForMmr = (rows, allCards) => {
6
7
  console.debug('building comp stats for', rows.length, 'rows');
7
8
  const groupedByComp = (0, aws_lambda_utils_1.groupByFunction)((row) => row.archetype)(rows);
@@ -11,10 +12,12 @@ exports.buildCompStatsForMmr = buildCompStatsForMmr;
11
12
  const buildStatsForSingleComp = (rows) => {
12
13
  const ref = rows[0];
13
14
  const averagePlacement = average(rows.map((r) => r.playerRank));
15
+ const placementDistribution = (0, utils_1.buildPlacementDistribution)(rows);
14
16
  return {
15
17
  archetype: ref.archetype,
16
18
  dataPoints: rows.length,
17
19
  averagePlacement: averagePlacement,
20
+ placementDistribution: placementDistribution,
18
21
  heroStats: buildHeroStats(rows, averagePlacement),
19
22
  };
20
23
  };
@@ -22,10 +25,12 @@ const buildHeroStats = (rows, refAveragePlacement) => {
22
25
  const groupedByHero = (0, aws_lambda_utils_1.groupByFunction)((r) => r.heroCardId)(rows);
23
26
  return Object.keys(groupedByHero).map((heroCardId) => {
24
27
  const rowsForHero = groupedByHero[heroCardId];
28
+ const placementDistribution = (0, utils_1.buildPlacementDistribution)(rowsForHero);
25
29
  return {
26
30
  heroCardId: heroCardId,
27
31
  dataPoints: rowsForHero.length,
28
32
  averagePlacement: average(rowsForHero.map((r) => r.playerRank)),
33
+ placementDistribution: placementDistribution,
29
34
  };
30
35
  });
31
36
  };
@@ -1 +1 @@
1
- {"version":3,"file":"comp-stats-builder.js","sourceRoot":"","sources":["../../../../src/solo/hourly/comps/comp-stats-builder.ts"],"names":[],"mappings":";;;AAAA,qEAAiE;AAI1D,MAAM,oBAAoB,GAAG,CACnC,IAA+B,EAC/B,QAAyB,EACc,EAAE;IACzC,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9D,MAAM,aAAa,GAEf,IAAA,kCAAe,EAAC,CAAC,GAAmB,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC;IAClE,OAAO,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC;AACtF,CAAC,CAAC;AATW,QAAA,oBAAoB,wBAS/B;AAGF,MAAM,uBAAuB,GAAG,CAAC,IAA+B,EAA6B,EAAE;IAC9F,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;IAEhE,OAAO;QACN,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,UAAU,EAAE,IAAI,CAAC,MAAM;QACvB,gBAAgB,EAAE,gBAAgB;QAClC,SAAS,EAAE,cAAc,CAAC,IAAI,EAAE,gBAAgB,CAAC;KACjD,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CACtB,IAA+B,EAC/B,mBAA2B,EACU,EAAE;IACvC,MAAM,aAAa,GAAG,IAAA,kCAAe,EAAC,CAAC,CAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC;IACjF,OAAO,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;QACpD,MAAM,WAAW,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;QAC9C,OAAO;YACN,UAAU,EAAE,UAAU;YACtB,UAAU,EAAE,WAAW,CAAC,MAAM;YAC9B,gBAAgB,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;SAC/D,CAAC;IACH,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,OAAO,GAAG,CAAC,IAAuB,EAAU,EAAE;IACnD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;AACtD,CAAC,CAAC","sourcesContent":["import { groupByFunction } from '@firestone-hs/aws-lambda-utils';\r\nimport { AllCardsService } from '@firestone-hs/reference-data';\r\nimport { InternalBgsCompHeroStat, InternalBgsGlobalCompStat, InternalBgsRow } from '../../../internal-model';\r\n\r\nexport const buildCompStatsForMmr = (\r\n\trows: readonly InternalBgsRow[],\r\n\tallCards: AllCardsService,\r\n): readonly InternalBgsGlobalCompStat[] => {\r\n\tconsole.debug('building comp stats for', rows.length, 'rows');\r\n\tconst groupedByComp: {\r\n\t\t[comp: string]: readonly InternalBgsRow[];\r\n\t} = groupByFunction((row: InternalBgsRow) => row.archetype)(rows);\r\n\treturn Object.values(groupedByComp).flatMap((data) => buildStatsForSingleComp(data));\r\n};\r\n\r\n// All rows here belong to a single comp\r\nconst buildStatsForSingleComp = (rows: readonly InternalBgsRow[]): InternalBgsGlobalCompStat => {\r\n\tconst ref = rows[0];\r\n\tconst averagePlacement = average(rows.map((r) => r.playerRank));\r\n\r\n\treturn {\r\n\t\tarchetype: ref.archetype,\r\n\t\tdataPoints: rows.length,\r\n\t\taveragePlacement: averagePlacement,\r\n\t\theroStats: buildHeroStats(rows, averagePlacement),\r\n\t};\r\n};\r\n\r\nconst buildHeroStats = (\r\n\trows: readonly InternalBgsRow[],\r\n\trefAveragePlacement: number,\r\n): readonly InternalBgsCompHeroStat[] => {\r\n\tconst groupedByHero = groupByFunction((r: InternalBgsRow) => r.heroCardId)(rows);\r\n\treturn Object.keys(groupedByHero).map((heroCardId) => {\r\n\t\tconst rowsForHero = groupedByHero[heroCardId];\r\n\t\treturn {\r\n\t\t\theroCardId: heroCardId,\r\n\t\t\tdataPoints: rowsForHero.length,\r\n\t\t\taveragePlacement: average(rowsForHero.map((r) => r.playerRank)),\r\n\t\t};\r\n\t});\r\n};\r\n\r\nconst average = (data: readonly number[]): number => {\r\n\treturn data.reduce((a, b) => a + b, 0) / data.length;\r\n};\r\n"]}
1
+ {"version":3,"file":"comp-stats-builder.js","sourceRoot":"","sources":["../../../../src/solo/hourly/comps/comp-stats-builder.ts"],"names":[],"mappings":";;;AAAA,qEAAiE;AAGjE,oCAAsD;AAE/C,MAAM,oBAAoB,GAAG,CACnC,IAA+B,EAC/B,QAAyB,EACc,EAAE;IACzC,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9D,MAAM,aAAa,GAEf,IAAA,kCAAe,EAAC,CAAC,GAAmB,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC;IAClE,OAAO,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC;AACtF,CAAC,CAAC;AATW,QAAA,oBAAoB,wBAS/B;AAGF,MAAM,uBAAuB,GAAG,CAAC,IAA+B,EAA6B,EAAE;IAC9F,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;IAChE,MAAM,qBAAqB,GAAG,IAAA,kCAA0B,EAAC,IAAI,CAAC,CAAC;IAE/D,OAAO;QACN,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,UAAU,EAAE,IAAI,CAAC,MAAM;QACvB,gBAAgB,EAAE,gBAAgB;QAClC,qBAAqB,EAAE,qBAAqB;QAC5C,SAAS,EAAE,cAAc,CAAC,IAAI,EAAE,gBAAgB,CAAC;KACjD,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CACtB,IAA+B,EAC/B,mBAA2B,EACU,EAAE;IACvC,MAAM,aAAa,GAAG,IAAA,kCAAe,EAAC,CAAC,CAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC;IACjF,OAAO,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;QACpD,MAAM,WAAW,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;QAC9C,MAAM,qBAAqB,GAAG,IAAA,kCAA0B,EAAC,WAAW,CAAC,CAAC;QACtE,OAAO;YACN,UAAU,EAAE,UAAU;YACtB,UAAU,EAAE,WAAW,CAAC,MAAM;YAC9B,gBAAgB,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YAC/D,qBAAqB,EAAE,qBAAqB;SAC5C,CAAC;IACH,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,OAAO,GAAG,CAAC,IAAuB,EAAU,EAAE;IACnD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;AACtD,CAAC,CAAC","sourcesContent":["import { groupByFunction } from '@firestone-hs/aws-lambda-utils';\r\nimport { AllCardsService } from '@firestone-hs/reference-data';\r\nimport { InternalBgsCompHeroStat, InternalBgsGlobalCompStat, InternalBgsRow } from '../../../internal-model';\r\nimport { buildPlacementDistribution } from '../utils';\r\n\r\nexport const buildCompStatsForMmr = (\r\n\trows: readonly InternalBgsRow[],\r\n\tallCards: AllCardsService,\r\n): readonly InternalBgsGlobalCompStat[] => {\r\n\tconsole.debug('building comp stats for', rows.length, 'rows');\r\n\tconst groupedByComp: {\r\n\t\t[comp: string]: readonly InternalBgsRow[];\r\n\t} = groupByFunction((row: InternalBgsRow) => row.archetype)(rows);\r\n\treturn Object.values(groupedByComp).flatMap((data) => buildStatsForSingleComp(data));\r\n};\r\n\r\n// All rows here belong to a single comp\r\nconst buildStatsForSingleComp = (rows: readonly InternalBgsRow[]): InternalBgsGlobalCompStat => {\r\n\tconst ref = rows[0];\r\n\tconst averagePlacement = average(rows.map((r) => r.playerRank));\r\n\tconst placementDistribution = buildPlacementDistribution(rows);\r\n\r\n\treturn {\r\n\t\tarchetype: ref.archetype,\r\n\t\tdataPoints: rows.length,\r\n\t\taveragePlacement: averagePlacement,\r\n\t\tplacementDistribution: placementDistribution,\r\n\t\theroStats: buildHeroStats(rows, averagePlacement),\r\n\t};\r\n};\r\n\r\nconst buildHeroStats = (\r\n\trows: readonly InternalBgsRow[],\r\n\trefAveragePlacement: number,\r\n): readonly InternalBgsCompHeroStat[] => {\r\n\tconst groupedByHero = groupByFunction((r: InternalBgsRow) => r.heroCardId)(rows);\r\n\treturn Object.keys(groupedByHero).map((heroCardId) => {\r\n\t\tconst rowsForHero = groupedByHero[heroCardId];\r\n\t\tconst placementDistribution = buildPlacementDistribution(rowsForHero);\r\n\t\treturn {\r\n\t\t\theroCardId: heroCardId,\r\n\t\t\tdataPoints: rowsForHero.length,\r\n\t\t\taveragePlacement: average(rowsForHero.map((r) => r.playerRank)),\r\n\t\t\tplacementDistribution: placementDistribution,\r\n\t\t};\r\n\t});\r\n};\r\n\r\nconst average = (data: readonly number[]): number => {\r\n\treturn data.reduce((a, b) => a + b, 0) / data.length;\r\n};\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@firestone-hs/bgs-global-stats",
3
- "version": "1.0.53",
3
+ "version": "1.0.54",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "lint": "eslint --color --fix --ext .ts .",