@firestone-hs/bgs-global-stats 1.0.53 → 1.0.55
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.
- package/dist/common/anomalies.js +4 -3
- package/dist/common/anomalies.js.map +1 -1
- package/dist/common/performance-analyzer.d.ts +12 -0
- package/dist/common/performance-analyzer.js +52 -0
- package/dist/common/performance-analyzer.js.map +1 -0
- package/dist/duos/final-stats/config.js.map +1 -0
- package/dist/duos/{aggregate-hourly → final-stats}/heroes/_build-aggregated-stats.js +35 -31
- package/dist/duos/final-stats/heroes/_build-aggregated-stats.js.map +1 -0
- package/dist/duos/final-stats/heroes/s3-saver.js.map +1 -0
- package/dist/duos/{aggregate-hourly → final-stats}/heroes/stats-merger.js +3 -24
- package/dist/duos/final-stats/heroes/stats-merger.js.map +1 -0
- package/dist/duos/final-stats/hourly-utils.js.map +1 -0
- package/dist/duos/final-stats/percentiles.js.map +1 -0
- package/dist/duos/final-stats/s3-loader.js.map +1 -0
- package/dist/duos/hourly/_build-battlegrounds-hero-stats.js +19 -29
- package/dist/duos/hourly/_build-battlegrounds-hero-stats.js.map +1 -1
- package/dist/duos/hourly/hero-stats-buikder.js +2 -2
- package/dist/duos/hourly/hero-stats-buikder.js.map +1 -1
- package/dist/duos/hourly/rows.js +4 -4
- package/dist/duos/hourly/rows.js.map +1 -1
- package/dist/duos/hourly/utils.js +1 -1
- package/dist/duos/hourly/utils.js.map +1 -1
- package/dist/internal-model.d.ts +12 -0
- package/dist/internal-model.js.map +1 -1
- package/dist/model-comps.d.ts +20 -0
- package/dist/model-comps.js.map +1 -1
- package/dist/models.d.ts +1 -4
- package/dist/models.js.map +1 -1
- package/dist/solo/aggregate-daily/cards/_build-aggregated-stats.js +9 -13
- package/dist/solo/aggregate-daily/cards/_build-aggregated-stats.js.map +1 -1
- package/dist/solo/aggregate-daily/cards/s3-saver.js +1 -1
- package/dist/solo/aggregate-daily/cards/s3-saver.js.map +1 -1
- package/dist/solo/aggregate-daily/cards/stats-builder.js +2 -2
- package/dist/solo/aggregate-daily/cards/stats-builder.js.map +1 -1
- package/dist/solo/aggregate-daily/heroes/_build-aggregated-stats.js +115 -0
- package/dist/solo/aggregate-daily/heroes/_build-aggregated-stats.js.map +1 -0
- package/dist/solo/aggregate-daily/heroes/s3-saver.d.ts +2 -0
- package/dist/solo/aggregate-daily/heroes/s3-saver.js +24 -0
- package/dist/solo/aggregate-daily/heroes/s3-saver.js.map +1 -0
- package/dist/solo/final-stats/cards/_build-aggregated-stats.js +11 -29
- package/dist/solo/final-stats/cards/_build-aggregated-stats.js.map +1 -1
- package/dist/solo/final-stats/cards/s3-saver.js +1 -5
- package/dist/solo/final-stats/cards/s3-saver.js.map +1 -1
- package/dist/solo/final-stats/cards/stats-builder.js +5 -3
- package/dist/solo/final-stats/cards/stats-builder.js.map +1 -1
- package/dist/solo/{aggregate-hourly → final-stats}/comps/_build-aggregated-stats.js +19 -23
- package/dist/solo/final-stats/comps/_build-aggregated-stats.js.map +1 -0
- package/dist/solo/final-stats/comps/s3-saver.js.map +1 -0
- package/dist/solo/final-stats/comps/stats-builder.js +88 -0
- package/dist/solo/final-stats/comps/stats-builder.js.map +1 -0
- package/dist/solo/{aggregate-hourly → final-stats}/config.js +1 -1
- package/dist/solo/final-stats/config.js.map +1 -0
- package/dist/solo/{aggregate-hourly → final-stats}/heroes/_build-aggregated-stats.js +30 -34
- package/dist/solo/final-stats/heroes/_build-aggregated-stats.js.map +1 -0
- package/dist/solo/final-stats/heroes/s3-saver.js.map +1 -0
- package/dist/solo/{aggregate-hourly → final-stats}/heroes/stats-merger.d.ts +5 -0
- package/dist/solo/{aggregate-hourly → final-stats}/heroes/stats-merger.js +6 -5
- package/dist/solo/final-stats/heroes/stats-merger.js.map +1 -0
- package/dist/solo/final-stats/hourly-utils.js.map +1 -0
- package/dist/solo/final-stats/percentiles.js.map +1 -0
- package/dist/solo/final-stats/quests/_build-aggregated-stats.d.ts +5 -0
- package/dist/solo/{aggregate-hourly → final-stats}/quests/_build-aggregated-stats.js +13 -24
- package/dist/solo/final-stats/quests/_build-aggregated-stats.js.map +1 -0
- package/dist/solo/{aggregate-hourly → final-stats}/quests/quest-stats-merger.js +4 -4
- package/dist/solo/final-stats/quests/quest-stats-merger.js.map +1 -0
- package/dist/solo/{aggregate-hourly → final-stats}/quests/reward-stats-merger.js +3 -3
- package/dist/solo/final-stats/quests/reward-stats-merger.js.map +1 -0
- package/dist/solo/final-stats/quests/s3-saver.js.map +1 -0
- package/dist/solo/{aggregate-hourly → final-stats}/s3-loader.d.ts +1 -1
- package/dist/solo/{aggregate-hourly → final-stats}/s3-loader.js +22 -17
- package/dist/solo/final-stats/s3-loader.js.map +1 -0
- package/dist/solo/{aggregate-hourly → final-stats}/trinkets/_build-aggregated-stats.js +8 -18
- package/dist/solo/final-stats/trinkets/_build-aggregated-stats.js.map +1 -0
- package/dist/solo/final-stats/trinkets/s3-saver.js.map +1 -0
- package/dist/solo/{aggregate-hourly → final-stats}/trinkets/stats-builder.js +1 -1
- package/dist/solo/final-stats/trinkets/stats-builder.js.map +1 -0
- package/dist/solo/hourly/_build-battlegrounds-hero-stats.js +39 -56
- package/dist/solo/hourly/_build-battlegrounds-hero-stats.js.map +1 -1
- package/dist/solo/hourly/cards/card-stats-builder.js +8 -11
- package/dist/solo/hourly/cards/card-stats-builder.js.map +1 -1
- package/dist/solo/hourly/cards/card-stats.js +0 -5
- package/dist/solo/hourly/cards/card-stats.js.map +1 -1
- package/dist/solo/hourly/comps/comp-stats-builder.d.ts +2 -1
- package/dist/solo/hourly/comps/comp-stats-builder.js +58 -11
- package/dist/solo/hourly/comps/comp-stats-builder.js.map +1 -1
- package/dist/solo/hourly/comps/comp-stats.d.ts +2 -1
- package/dist/solo/hourly/comps/comp-stats.js +4 -2
- package/dist/solo/hourly/comps/comp-stats.js.map +1 -1
- package/dist/solo/hourly/hero-stats-buikder.js +2 -2
- package/dist/solo/hourly/hero-stats-buikder.js.map +1 -1
- package/dist/solo/hourly/quests/quest-stats-buikder.js +3 -3
- package/dist/solo/hourly/quests/quest-stats-buikder.js.map +1 -1
- package/dist/solo/hourly/quests/reward-stats-builder.js +2 -2
- package/dist/solo/hourly/quests/reward-stats-builder.js.map +1 -1
- package/dist/solo/hourly/rows.js +17 -16
- package/dist/solo/hourly/rows.js.map +1 -1
- package/dist/solo/hourly/trinkets/trinket-stats-builder.js +2 -4
- package/dist/solo/hourly/trinkets/trinket-stats-builder.js.map +1 -1
- package/dist/solo/hourly/utils.js +1 -1
- package/dist/solo/hourly/utils.js.map +1 -1
- package/package.json +7 -3
- package/dist/duos/aggregate-hourly/config.js.map +0 -1
- package/dist/duos/aggregate-hourly/heroes/_build-aggregated-stats.js.map +0 -1
- package/dist/duos/aggregate-hourly/heroes/s3-saver.js.map +0 -1
- package/dist/duos/aggregate-hourly/heroes/stats-merger.js.map +0 -1
- package/dist/duos/aggregate-hourly/hourly-utils.js.map +0 -1
- package/dist/duos/aggregate-hourly/percentiles.js.map +0 -1
- package/dist/duos/aggregate-hourly/s3-loader.js.map +0 -1
- package/dist/solo/aggregate-hourly/comps/_build-aggregated-stats.js.map +0 -1
- package/dist/solo/aggregate-hourly/comps/s3-saver.js.map +0 -1
- package/dist/solo/aggregate-hourly/comps/stats-builder.js +0 -32
- package/dist/solo/aggregate-hourly/comps/stats-builder.js.map +0 -1
- package/dist/solo/aggregate-hourly/config.js.map +0 -1
- package/dist/solo/aggregate-hourly/heroes/_build-aggregated-stats.js.map +0 -1
- package/dist/solo/aggregate-hourly/heroes/s3-saver.js.map +0 -1
- package/dist/solo/aggregate-hourly/heroes/stats-merger.js.map +0 -1
- package/dist/solo/aggregate-hourly/hourly-utils.js.map +0 -1
- package/dist/solo/aggregate-hourly/percentiles.js.map +0 -1
- package/dist/solo/aggregate-hourly/quests/_build-aggregated-stats.js.map +0 -1
- package/dist/solo/aggregate-hourly/quests/quest-stats-merger.js.map +0 -1
- package/dist/solo/aggregate-hourly/quests/reward-stats-merger.js.map +0 -1
- package/dist/solo/aggregate-hourly/quests/s3-saver.js.map +0 -1
- package/dist/solo/aggregate-hourly/s3-loader.js.map +0 -1
- package/dist/solo/aggregate-hourly/trinkets/_build-aggregated-stats.js.map +0 -1
- package/dist/solo/aggregate-hourly/trinkets/s3-saver.js.map +0 -1
- package/dist/solo/aggregate-hourly/trinkets/stats-builder.js.map +0 -1
- /package/dist/duos/{aggregate-hourly → final-stats}/config.d.ts +0 -0
- /package/dist/duos/{aggregate-hourly → final-stats}/config.js +0 -0
- /package/dist/duos/{aggregate-hourly → final-stats}/heroes/_build-aggregated-stats.d.ts +0 -0
- /package/dist/duos/{aggregate-hourly → final-stats}/heroes/s3-saver.d.ts +0 -0
- /package/dist/duos/{aggregate-hourly → final-stats}/heroes/s3-saver.js +0 -0
- /package/dist/duos/{aggregate-hourly → final-stats}/heroes/stats-merger.d.ts +0 -0
- /package/dist/duos/{aggregate-hourly → final-stats}/hourly-utils.d.ts +0 -0
- /package/dist/duos/{aggregate-hourly → final-stats}/hourly-utils.js +0 -0
- /package/dist/duos/{aggregate-hourly → final-stats}/percentiles.d.ts +0 -0
- /package/dist/duos/{aggregate-hourly → final-stats}/percentiles.js +0 -0
- /package/dist/duos/{aggregate-hourly → final-stats}/s3-loader.d.ts +0 -0
- /package/dist/duos/{aggregate-hourly → final-stats}/s3-loader.js +0 -0
- /package/dist/solo/{aggregate-hourly → aggregate-daily}/heroes/_build-aggregated-stats.d.ts +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/comps/_build-aggregated-stats.d.ts +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/comps/s3-saver.d.ts +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/comps/s3-saver.js +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/comps/stats-builder.d.ts +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/config.d.ts +0 -0
- /package/dist/solo/{aggregate-hourly/quests → final-stats/heroes}/_build-aggregated-stats.d.ts +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/heroes/s3-saver.d.ts +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/heroes/s3-saver.js +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/hourly-utils.d.ts +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/hourly-utils.js +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/percentiles.d.ts +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/percentiles.js +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/quests/quest-stats-merger.d.ts +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/quests/reward-stats-merger.d.ts +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/quests/s3-saver.d.ts +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/quests/s3-saver.js +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/trinkets/_build-aggregated-stats.d.ts +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/trinkets/s3-saver.d.ts +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/trinkets/s3-saver.js +0 -0
- /package/dist/solo/{aggregate-hourly → final-stats}/trinkets/stats-builder.d.ts +0 -0
package/dist/common/anomalies.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.readAllAnomalies = void 0;
|
|
4
|
-
const
|
|
5
|
-
const s3 = new
|
|
4
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
5
|
+
const s3 = new client_s3_1.S3();
|
|
6
6
|
const readAllAnomalies = async (bucket, folder) => {
|
|
7
7
|
var _a, _b;
|
|
8
8
|
const params = {
|
|
@@ -16,7 +16,8 @@ const readAllAnomalies = async (bucket, folder) => {
|
|
|
16
16
|
params.ContinuationToken = continuationToken;
|
|
17
17
|
}
|
|
18
18
|
try {
|
|
19
|
-
const
|
|
19
|
+
const command = new client_s3_1.ListObjectsV2Command(params);
|
|
20
|
+
const data = await s3.send(command);
|
|
20
21
|
const allKeysForToken = (_b = (_a = data.Contents) === null || _a === void 0 ? void 0 : _a.map((item) => item.Key)) !== null && _b !== void 0 ? _b : [];
|
|
21
22
|
const suffixes = allKeysForToken.map((key) => key.replace(`${folder}/`, ''));
|
|
22
23
|
const anomalies = suffixes.map((suffix) => suffix.split('/')[0]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anomalies.js","sourceRoot":"","sources":["../../src/common/anomalies.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"anomalies.js","sourceRoot":"","sources":["../../src/common/anomalies.ts"],"names":[],"mappings":";;;AAAA,kDAAqH;AAErH,MAAM,EAAE,GAAG,IAAI,cAAE,EAAE,CAAC;AAEb,MAAM,gBAAgB,GAAG,KAAK,EAAE,MAAc,EAAE,MAAc,EAAuC,EAAE;;IAC7G,MAAM,MAAM,GAA8B;QACzC,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,MAAM;KACd,CAAC;IACF,IAAI,OAAO,GAAa,EAAE,CAAC;IAC3B,IAAI,iBAAqC,CAAC;IAE1C,GAAG;QACF,IAAI,iBAAiB,EAAE;YACtB,MAAM,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;SAC7C;QAED,IAAI;YACH,MAAM,OAAO,GAAG,IAAI,gCAAoB,CAAC,MAAM,CAAC,CAAC;YACjD,MAAM,IAAI,GAA+B,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAEhE,MAAM,eAAe,GAAG,MAAA,MAAA,IAAI,CAAC,QAAQ,0CAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,mCAAI,EAAE,CAAC;YACrE,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,MAAM,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;YAC7E,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACjE,MAAM,eAAe,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;YAEhD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YAC1C,iBAAiB,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC,SAAS,CAAC;SAC9E;QAAC,OAAO,KAAK,EAAE;YACf,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;YAC7C,OAAO,CAAC,IAAI,CAAC,CAAC;SACd;KACD,QAAQ,iBAAiB,EAAE;IAE5B,MAAM,UAAU,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IAEzC,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,GAAG,UAAU,CAAC,CAAC;IAErC,OAAO,MAAM,CAAC;AACf,CAAC,CAAC;AAnCW,QAAA,gBAAgB,oBAmC3B","sourcesContent":["import { ListObjectsV2Command, ListObjectsV2CommandInput, ListObjectsV2CommandOutput, S3 } from '@aws-sdk/client-s3';\r\n\r\nconst s3 = new S3();\r\n\r\nexport const readAllAnomalies = async (bucket: string, folder: string): Promise<readonly (string | null)[]> => {\r\n\tconst params: ListObjectsV2CommandInput = {\r\n\t\tBucket: bucket,\r\n\t\tPrefix: folder,\r\n\t};\r\n\tlet allKeys: string[] = [];\r\n\tlet continuationToken: string | undefined;\r\n\r\n\tdo {\r\n\t\tif (continuationToken) {\r\n\t\t\tparams.ContinuationToken = continuationToken;\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\tconst command = new ListObjectsV2Command(params);\r\n\t\t\tconst data: ListObjectsV2CommandOutput = await s3.send(command);\r\n\t\t\t// console.debug('listing result', params.ContinuationToken, data.Contents);\r\n\t\t\tconst allKeysForToken = data.Contents?.map((item) => item.Key) ?? [];\r\n\t\t\tconst suffixes = allKeysForToken.map((key) => key.replace(`${folder}/`, ''));\r\n\t\t\tconst anomalies = suffixes.map((suffix) => suffix.split('/')[0]);\r\n\t\t\tconst uniqueAnomalies = [...new Set(anomalies)];\r\n\t\t\t// console.debug('uniqueAnomalies', uniqueAnomalies);\r\n\t\t\tallKeys = allKeys.concat(uniqueAnomalies);\r\n\t\t\tcontinuationToken = data.IsTruncated ? data.NextContinuationToken : undefined;\r\n\t\t} catch (error) {\r\n\t\t\tconsole.error('Error listing files:', error);\r\n\t\t\treturn [null];\r\n\t\t}\r\n\t} while (continuationToken);\r\n\r\n\tconst uniqueKeys = [...new Set(allKeys)];\r\n\t// console.debug('uniqueKeys', uniqueKeys);\r\n\tconst result = [null, ...uniqueKeys];\r\n\t// console.debug('listing anomalies', bucket, folder, result);\r\n\treturn result;\r\n};\r\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare class PerformanceAnalyzer {
|
|
2
|
+
private timers;
|
|
3
|
+
private results;
|
|
4
|
+
startTimer(name: string): void;
|
|
5
|
+
endTimer(name: string): number;
|
|
6
|
+
getResults(): {
|
|
7
|
+
[key: string]: number;
|
|
8
|
+
};
|
|
9
|
+
logSummary(): void;
|
|
10
|
+
private getTotalTime;
|
|
11
|
+
}
|
|
12
|
+
export declare const perf: PerformanceAnalyzer;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.perf = exports.PerformanceAnalyzer = void 0;
|
|
4
|
+
const perf_hooks_1 = require("perf_hooks");
|
|
5
|
+
class PerformanceAnalyzer {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.timers = new Map();
|
|
8
|
+
this.results = new Map();
|
|
9
|
+
}
|
|
10
|
+
startTimer(name) {
|
|
11
|
+
this.timers.set(name, perf_hooks_1.performance.now());
|
|
12
|
+
}
|
|
13
|
+
endTimer(name) {
|
|
14
|
+
return 0;
|
|
15
|
+
const startTime = this.timers.get(name);
|
|
16
|
+
if (!startTime) {
|
|
17
|
+
console.warn(`Timer ${name} was not started`);
|
|
18
|
+
return 0;
|
|
19
|
+
}
|
|
20
|
+
const duration = perf_hooks_1.performance.now() - startTime;
|
|
21
|
+
this.results.set(name, duration);
|
|
22
|
+
this.timers.delete(name);
|
|
23
|
+
console.log(`⏱️ ${name}: ${duration.toFixed(2)}ms`);
|
|
24
|
+
return duration;
|
|
25
|
+
}
|
|
26
|
+
getResults() {
|
|
27
|
+
return Object.fromEntries(this.results);
|
|
28
|
+
}
|
|
29
|
+
logSummary() {
|
|
30
|
+
return;
|
|
31
|
+
console.log('\n📊 Performance Summary:');
|
|
32
|
+
console.log('========================');
|
|
33
|
+
const sorted = Array.from(this.results.entries())
|
|
34
|
+
.sort((a, b) => b[1] - a[1])
|
|
35
|
+
.map(([name, duration]) => ({
|
|
36
|
+
name,
|
|
37
|
+
duration: duration.toFixed(2),
|
|
38
|
+
percentage: ((duration / this.getTotalTime()) * 100).toFixed(1),
|
|
39
|
+
}));
|
|
40
|
+
sorted.forEach(({ name, duration, percentage }) => {
|
|
41
|
+
console.log(`${name.padEnd(30)} ${duration}ms (${percentage}%)`);
|
|
42
|
+
});
|
|
43
|
+
console.log(`${'TOTAL'.padEnd(30)} ${this.getTotalTime().toFixed(2)}ms`);
|
|
44
|
+
console.log('========================\n');
|
|
45
|
+
}
|
|
46
|
+
getTotalTime() {
|
|
47
|
+
return Array.from(this.results.values()).reduce((sum, duration) => sum + duration, 0);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.PerformanceAnalyzer = PerformanceAnalyzer;
|
|
51
|
+
exports.perf = new PerformanceAnalyzer();
|
|
52
|
+
//# sourceMappingURL=performance-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance-analyzer.js","sourceRoot":"","sources":["../../src/common/performance-analyzer.ts"],"names":[],"mappings":";;;AAAA,2CAAyC;AAEzC,MAAa,mBAAmB;IAAhC;QACS,WAAM,GAAwB,IAAI,GAAG,EAAE,CAAC;QACxC,YAAO,GAAwB,IAAI,GAAG,EAAE,CAAC;IAkDlD,CAAC;IAhDA,UAAU,CAAC,IAAY;QACtB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,wBAAW,CAAC,GAAG,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,QAAQ,CAAC,IAAY;QACpB,OAAO,CAAC,CAAC;QACT,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,SAAS,EAAE;YACf,OAAO,CAAC,IAAI,CAAC,SAAS,IAAI,kBAAkB,CAAC,CAAC;YAC9C,OAAO,CAAC,CAAC;SACT;QAED,MAAM,QAAQ,GAAG,wBAAW,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QAC/C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAEzB,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACrD,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED,UAAU;QACT,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,UAAU;QACT,OAAO;QACP,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;QAExC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;aAC/C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;aAC3B,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3B,IAAI;YACJ,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;YAC7B,UAAU,EAAE,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;SAC/D,CAAC,CAAC,CAAC;QAEL,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE;YACjD,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,QAAQ,OAAO,UAAU,IAAI,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACzE,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC3C,CAAC;IAEO,YAAY;QACnB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,CAAC,GAAG,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC;IACvF,CAAC;CACD;AApDD,kDAoDC;AAGY,QAAA,IAAI,GAAG,IAAI,mBAAmB,EAAE,CAAC","sourcesContent":["import { performance } from 'perf_hooks';\r\n\r\nexport class PerformanceAnalyzer {\r\n\tprivate timers: Map<string, number> = new Map();\r\n\tprivate results: Map<string, number> = new Map();\r\n\r\n\tstartTimer(name: string): void {\r\n\t\tthis.timers.set(name, performance.now());\r\n\t}\r\n\r\n\tendTimer(name: string): number {\r\n\t\treturn 0;\r\n\t\tconst startTime = this.timers.get(name);\r\n\t\tif (!startTime) {\r\n\t\t\tconsole.warn(`Timer ${name} was not started`);\r\n\t\t\treturn 0;\r\n\t\t}\r\n\r\n\t\tconst duration = performance.now() - startTime;\r\n\t\tthis.results.set(name, duration);\r\n\t\tthis.timers.delete(name);\r\n\r\n\t\tconsole.log(`⏱️ ${name}: ${duration.toFixed(2)}ms`);\r\n\t\treturn duration;\r\n\t}\r\n\r\n\tgetResults(): { [key: string]: number } {\r\n\t\treturn Object.fromEntries(this.results);\r\n\t}\r\n\r\n\tlogSummary(): void {\r\n\t\treturn;\r\n\t\tconsole.log('\\n📊 Performance Summary:');\r\n\t\tconsole.log('========================');\r\n\r\n\t\tconst sorted = Array.from(this.results.entries())\r\n\t\t\t.sort((a, b) => b[1] - a[1])\r\n\t\t\t.map(([name, duration]) => ({\r\n\t\t\t\tname,\r\n\t\t\t\tduration: duration.toFixed(2),\r\n\t\t\t\tpercentage: ((duration / this.getTotalTime()) * 100).toFixed(1),\r\n\t\t\t}));\r\n\r\n\t\tsorted.forEach(({ name, duration, percentage }) => {\r\n\t\t\tconsole.log(`${name.padEnd(30)} ${duration}ms (${percentage}%)`);\r\n\t\t});\r\n\r\n\t\tconsole.log(`${'TOTAL'.padEnd(30)} ${this.getTotalTime().toFixed(2)}ms`);\r\n\t\tconsole.log('========================\\n');\r\n\t}\r\n\r\n\tprivate getTotalTime(): number {\r\n\t\treturn Array.from(this.results.values()).reduce((sum, duration) => sum + duration, 0);\r\n\t}\r\n}\r\n\r\n// Singleton instance\r\nexport const perf = new PerformanceAnalyzer();\r\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/duos/final-stats/config.ts"],"names":[],"mappings":";;;AAAA,+FAA6E;AAEhE,QAAA,aAAa,GAAG,GAAG,kDAAgB,oFAAoF,CAAC;AACxH,QAAA,mBAAmB,GAAG,GAAG,kDAAgB,2DAA2D,CAAC;AACrG,QAAA,cAAc,GAAG,GAAG,kDAAgB,4EAA4E,CAAC","sourcesContent":["import { STATS_KEY_PREFIX } from '../hourly/_build-battlegrounds-hero-stats';\r\n\r\nexport const STAT_KEY_HERO = `${STATS_KEY_PREFIX}/hero-stats/mmr-%mmrPercentile%/%timePeriod%/%anomaly%overview-from-hourly.gz.json`;\r\nexport const STAT_KEY_PERCENTILE = `${STATS_KEY_PREFIX}/hero-stats/%timePeriod%/%anomaly%mmr-percentiles.gz.json`;\r\nexport const STAT_KEY_QUEST = `${STATS_KEY_PREFIX}/quest-stats/mmr-%mmrPercentile%/%timePeriod%/overview-from-hourly.gz.json`;\r\n"]}
|
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.s3 = void 0;
|
|
4
|
+
const client_lambda_1 = require("@aws-sdk/client-lambda");
|
|
7
5
|
const aws_lambda_utils_1 = require("@firestone-hs/aws-lambda-utils");
|
|
8
6
|
const reference_data_1 = require("@firestone-hs/reference-data");
|
|
9
|
-
const
|
|
10
|
-
const anomalies_1 = require("../../../common/anomalies");
|
|
11
|
-
const _build_battlegrounds_hero_stats_1 = require("../../hourly/_build-battlegrounds-hero-stats");
|
|
7
|
+
const performance_analyzer_1 = require("../../../common/performance-analyzer");
|
|
12
8
|
const percentiles_1 = require("../percentiles");
|
|
13
9
|
const s3_loader_1 = require("../s3-loader");
|
|
14
10
|
const s3_saver_1 = require("./s3-saver");
|
|
15
11
|
const stats_merger_1 = require("./stats-merger");
|
|
16
12
|
const allCards = new reference_data_1.AllCardsService();
|
|
17
13
|
exports.s3 = new aws_lambda_utils_1.S3();
|
|
18
|
-
const lambda = new
|
|
14
|
+
const lambda = new client_lambda_1.LambdaClient({
|
|
15
|
+
region: process.env.AWS_REGION || 'us-west-2',
|
|
16
|
+
});
|
|
19
17
|
exports.default = async (event, context) => {
|
|
18
|
+
performance_analyzer_1.perf.startTimer('total-execution');
|
|
20
19
|
await allCards.initializeCardsDb();
|
|
21
20
|
if (!event.timePeriod) {
|
|
22
21
|
await dispatchEvents(context);
|
|
@@ -26,13 +25,17 @@ exports.default = async (event, context) => {
|
|
|
26
25
|
const timePeriod = event.timePeriod;
|
|
27
26
|
const mmrPercentile = event.mmrPercentile;
|
|
28
27
|
const anomaly = event.anomaly;
|
|
28
|
+
console.log('aggregating data', timePeriod, mmrPercentile);
|
|
29
29
|
const patchInfo = await (0, aws_lambda_utils_1.getLastBattlegroundsPatch)();
|
|
30
|
+
performance_analyzer_1.perf.startTimer('load-hourly-data');
|
|
30
31
|
const hourlyData = await (0, s3_loader_1.loadHourlyDataFromS3)('hero', timePeriod, mmrPercentile, anomaly, patchInfo);
|
|
32
|
+
performance_analyzer_1.perf.endTimer('load-hourly-data');
|
|
31
33
|
if (!(hourlyData === null || hourlyData === void 0 ? void 0 : hourlyData.length)) {
|
|
32
34
|
console.log('no data found', timePeriod, mmrPercentile, anomaly);
|
|
33
35
|
cleanup();
|
|
34
36
|
return;
|
|
35
37
|
}
|
|
38
|
+
console.log('hourlyData', hourlyData.length);
|
|
36
39
|
const lastUpdate = hourlyData
|
|
37
40
|
.map((d) => ({
|
|
38
41
|
date: new Date(d.lastUpdateDate),
|
|
@@ -40,41 +43,42 @@ exports.default = async (event, context) => {
|
|
|
40
43
|
time: new Date(d.lastUpdateDate).getTime(),
|
|
41
44
|
}))
|
|
42
45
|
.sort((a, b) => b.time - a.time)[0].date;
|
|
46
|
+
performance_analyzer_1.perf.startTimer('merge-stats');
|
|
43
47
|
const mergedStats = (0, stats_merger_1.mergeStats)(hourlyData, mmrPercentile, allCards);
|
|
48
|
+
performance_analyzer_1.perf.endTimer('merge-stats');
|
|
49
|
+
performance_analyzer_1.perf.startTimer('build-mmr-percentiles');
|
|
44
50
|
const mmrPercentiles = (0, percentiles_1.buildMmrPercentiles)(hourlyData);
|
|
51
|
+
performance_analyzer_1.perf.endTimer('build-mmr-percentiles');
|
|
52
|
+
performance_analyzer_1.perf.startTimer('persist-data');
|
|
45
53
|
await (0, s3_saver_1.persistData)(mergedStats, mmrPercentiles, anomaly, lastUpdate, timePeriod, mmrPercentile);
|
|
54
|
+
performance_analyzer_1.perf.endTimer('persist-data');
|
|
55
|
+
performance_analyzer_1.perf.endTimer('total-execution');
|
|
56
|
+
performance_analyzer_1.perf.logSummary();
|
|
46
57
|
cleanup();
|
|
47
58
|
};
|
|
48
59
|
const dispatchEvents = async (context) => {
|
|
49
60
|
console.log('dispatching events');
|
|
50
61
|
const allTimePeriod = ['all-time', 'past-three', 'past-seven', 'last-patch'];
|
|
51
62
|
const mmrPercentiles = [100, 50, 25, 10, 1];
|
|
52
|
-
const allAnomalies =
|
|
53
|
-
await (0, s3_saver_1.persistAnomaliesList)(allAnomalies);
|
|
63
|
+
const allAnomalies = [null];
|
|
54
64
|
for (const timePeriod of allTimePeriod) {
|
|
55
65
|
for (const percentile of mmrPercentiles) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
LogType: 'Tail',
|
|
73
|
-
Payload: JSON.stringify(newEvent),
|
|
74
|
-
})
|
|
75
|
-
.promise();
|
|
76
|
-
await (0, aws_lambda_utils_1.sleep)(50);
|
|
77
|
-
}
|
|
66
|
+
const newEvent = {
|
|
67
|
+
timePeriod: timePeriod,
|
|
68
|
+
mmrPercentile: percentile,
|
|
69
|
+
};
|
|
70
|
+
const params = {
|
|
71
|
+
FunctionName: context.functionName,
|
|
72
|
+
InvocationType: 'Event',
|
|
73
|
+
LogType: 'Tail',
|
|
74
|
+
Payload: JSON.stringify(newEvent),
|
|
75
|
+
};
|
|
76
|
+
const result = await lambda.send(new client_lambda_1.InvokeCommand({
|
|
77
|
+
FunctionName: context.functionName,
|
|
78
|
+
InvocationType: 'Event',
|
|
79
|
+
LogType: 'Tail',
|
|
80
|
+
Payload: JSON.stringify(newEvent),
|
|
81
|
+
}));
|
|
78
82
|
}
|
|
79
83
|
}
|
|
80
84
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_build-aggregated-stats.js","sourceRoot":"","sources":["../../../../src/duos/final-stats/heroes/_build-aggregated-stats.ts"],"names":[],"mappings":"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","sourcesContent":["import { InvokeCommand, LambdaClient } from '@aws-sdk/client-lambda';\r\nimport { S3, getLastBattlegroundsPatch, logBeforeTimeout } from '@firestone-hs/aws-lambda-utils';\r\nimport { AllCardsService } from '@firestone-hs/reference-data';\r\nimport { Context } from 'aws-lambda';\r\nimport { perf } from '../../../common/performance-analyzer';\r\nimport { BgsGlobalHeroStat, BgsHeroStatsV2, MmrPercentile, MmrPercentileFilter, TimePeriod } from '../../../models';\r\nimport { buildMmrPercentiles } from '../percentiles';\r\nimport { loadHourlyDataFromS3 } from '../s3-loader';\r\nimport { persistData } from './s3-saver';\r\nimport { mergeStats } from './stats-merger';\r\n\r\nconst allCards = new AllCardsService();\r\nexport const s3 = new S3();\r\nconst lambda = new LambdaClient({\r\n\tregion: process.env.AWS_REGION || 'us-west-2',\r\n});\r\n\r\nexport default async (event, context: Context): Promise<any> => {\r\n\tperf.startTimer('total-execution');\r\n\tawait allCards.initializeCardsDb();\r\n\r\n\tif (!event.timePeriod) {\r\n\t\tawait dispatchEvents(context);\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst cleanup = logBeforeTimeout(context);\r\n\tconst timePeriod: TimePeriod = event.timePeriod;\r\n\tconst mmrPercentile: MmrPercentileFilter = event.mmrPercentile;\r\n\tconst anomaly: string | null = event.anomaly;\r\n\r\n\tconsole.log('aggregating data', timePeriod, mmrPercentile);\r\n\r\n\t// Build the list of files based on the timeframe, and load all of these\r\n\tconst patchInfo = await getLastBattlegroundsPatch();\r\n\r\n\tperf.startTimer('load-hourly-data');\r\n\tconst hourlyData: readonly BgsHeroStatsV2[] = await loadHourlyDataFromS3(\r\n\t\t'hero',\r\n\t\ttimePeriod,\r\n\t\tmmrPercentile,\r\n\t\tanomaly,\r\n\t\tpatchInfo,\r\n\t);\r\n\tperf.endTimer('load-hourly-data');\r\n\r\n\tif (!hourlyData?.length) {\r\n\t\tconsole.log('no data found', timePeriod, mmrPercentile, anomaly);\r\n\t\tcleanup();\r\n\t\treturn;\r\n\t}\r\n\r\n\tconsole.log('hourlyData', hourlyData.length);\r\n\r\n\tconst lastUpdate = hourlyData\r\n\t\t.map((d) => ({\r\n\t\t\tdate: new Date(d.lastUpdateDate),\r\n\t\t\tdateStr: d.lastUpdateDate,\r\n\t\t\ttime: new Date(d.lastUpdateDate).getTime(),\r\n\t\t}))\r\n\t\t.sort((a, b) => b.time - a.time)[0].date;\r\n\r\n\t// Here it's ok that the MMR corresponding to each MMR percentile is not the same across all the hourly data chunks\r\n\t// as the actual MMR evolves over time\r\n\t// The only issue is that the samples might be too small for the MMR percentiles to be really representative in\r\n\t// each group\r\n\t// Empirically, it looks like there isn't much variation on a hour-by-hour basis, so it should be ok\r\n\t// A possible solution, if this becomes an issue, is to compute the MMR percentiles on the full last day of data\r\n\t// when building the hourly data\r\n\tperf.startTimer('merge-stats');\r\n\tconst mergedStats: readonly BgsGlobalHeroStat[] = mergeStats(hourlyData, mmrPercentile, allCards);\r\n\tperf.endTimer('merge-stats');\r\n\r\n\tperf.startTimer('build-mmr-percentiles');\r\n\tconst mmrPercentiles: readonly MmrPercentile[] = buildMmrPercentiles(hourlyData);\r\n\tperf.endTimer('build-mmr-percentiles');\r\n\r\n\tperf.startTimer('persist-data');\r\n\tawait persistData(mergedStats, mmrPercentiles, anomaly, lastUpdate, timePeriod, mmrPercentile);\r\n\tperf.endTimer('persist-data');\r\n\r\n\tperf.endTimer('total-execution');\r\n\tperf.logSummary();\r\n\r\n\tcleanup();\r\n};\r\n\r\nconst dispatchEvents = async (context: Context) => {\r\n\tconsole.log('dispatching events');\r\n\tconst allTimePeriod: readonly TimePeriod[] = ['all-time', 'past-three', 'past-seven', 'last-patch'];\r\n\tconst mmrPercentiles: readonly MmrPercentileFilter[] = [100, 50, 25, 10, 1];\r\n\tconst allAnomalies: readonly (string | null)[] = [null];\r\n\t// await readAllAnomalies(\r\n\t// \tSTATS_BUCKET,\r\n\t// \t`${STATS_KEY_PREFIX}/hero-stats/anomalies`,\r\n\t// );\r\n\t// await persistAnomaliesList(allAnomalies);\r\n\tfor (const timePeriod of allTimePeriod) {\r\n\t\tfor (const percentile of mmrPercentiles) {\r\n\t\t\t// for (const anomaly of allAnomalies) {\r\n\t\t\tconst newEvent = {\r\n\t\t\t\ttimePeriod: timePeriod,\r\n\t\t\t\tmmrPercentile: percentile,\r\n\t\t\t\t// anomaly: anomaly,\r\n\t\t\t};\r\n\t\t\tconst params = {\r\n\t\t\t\tFunctionName: context.functionName,\r\n\t\t\t\tInvocationType: 'Event',\r\n\t\t\t\tLogType: 'Tail',\r\n\t\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t\t};\r\n\t\t\t// console.log('\\tinvoking lambda', params);\r\n\t\t\tconst result = await lambda.send(\r\n\t\t\t\tnew InvokeCommand({\r\n\t\t\t\t\tFunctionName: context.functionName,\r\n\t\t\t\t\tInvocationType: 'Event',\r\n\t\t\t\t\tLogType: 'Tail',\r\n\t\t\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t\t\t}),\r\n\t\t\t);\r\n\t\t}\r\n\t\t// }\r\n\t}\r\n};\r\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3-saver.js","sourceRoot":"","sources":["../../../../src/duos/final-stats/heroes/s3-saver.ts"],"names":[],"mappings":";;;AAAA,+BAAgC;AAEhC,kGAA8F;AAC9F,sCAA+D;AAC/D,uEAA+C;AAExC,MAAM,oBAAoB,GAAG,KAAK,EAAE,SAA4B,EAAE,EAAE;IAC1E,MAAM,4BAAE,CAAC,SAAS,CACjB,IAAA,eAAQ,EAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,EACnC,8CAAY,EACZ,GAAG,kDAAgB,yBAAyB,EAC5C,kBAAkB,EAClB,MAAM,CACN,CAAC;AACH,CAAC,CAAC;AARW,QAAA,oBAAoB,wBAQ/B;AAEK,MAAM,WAAW,GAAG,KAAK,EAC/B,WAAyC,EACzC,cAAwC,EACxC,OAAsB,EACtB,UAAgB,EAChB,UAAsB,EACtB,aAAkC,EACjC,EAAE;IACH,MAAM,IAAI,GAAmB;QAC5B,SAAS,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACrC,GAAG,IAAI;YACP,aAAa,EAAE,aAAa;YAC5B,UAAU,EAAE,UAAU;SACtB,CAAC,CAAC;QACH,cAAc,EAAE,UAAU;QAC1B,UAAU,EAAE,WAAW,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;QAC3E,cAAc,EAAE,cAAc;KAC9B,CAAC;IAEF,MAAM,4BAAE,CAAC,SAAS,CACjB,IAAA,eAAQ,EAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,EAC9B,8CAAY,EACZ,sBAAa,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;SACxE,OAAO,CAAC,iBAAiB,EAAE,GAAG,aAAa,EAAE,CAAC;SAC9C,OAAO,CAAC,cAAc,EAAE,UAAU,CAAC,EACrC,kBAAkB,EAClB,MAAM,CACN,CAAC;IACF,MAAM,4BAAE,CAAC,SAAS,CACjB,IAAA,eAAQ,EAAC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,EACxC,8CAAY,EACZ,4BAAmB,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CACvF,cAAc,EACd,UAAU,CACV,EACD,kBAAkB,EAClB,MAAM,CACN,CAAC;AACH,CAAC,CAAC;AAtCW,QAAA,WAAW,eAsCtB","sourcesContent":["import { gzipSync } from 'zlib';\r\nimport { BgsGlobalHeroStat, BgsHeroStatsV2, MmrPercentile, MmrPercentileFilter, TimePeriod } from '../../../models';\r\nimport { STATS_BUCKET, STATS_KEY_PREFIX } from '../../hourly/_build-battlegrounds-hero-stats';\r\nimport { STAT_KEY_HERO, STAT_KEY_PERCENTILE } from '../config';\r\nimport { s3 } from './_build-aggregated-stats';\r\n\r\nexport const persistAnomaliesList = async (anomalies: readonly string[]) => {\r\n\tawait s3.writeFile(\r\n\t\tgzipSync(JSON.stringify(anomalies)),\r\n\t\tSTATS_BUCKET,\r\n\t\t`${STATS_KEY_PREFIX}/anomalies-list.gz.json`,\r\n\t\t'application/json',\r\n\t\t'gzip',\r\n\t);\r\n};\r\n\r\nexport const persistData = async (\r\n\tmergedStats: readonly BgsGlobalHeroStat[],\r\n\tmmrPercentiles: readonly MmrPercentile[],\r\n\tanomaly: string | null,\r\n\tlastUpdate: Date,\r\n\ttimePeriod: TimePeriod,\r\n\tmmrPercentile: MmrPercentileFilter,\r\n) => {\r\n\tconst stat: BgsHeroStatsV2 = {\r\n\t\theroStats: mergedStats.map((stat) => ({\r\n\t\t\t...stat,\r\n\t\t\tmmrPercentile: mmrPercentile,\r\n\t\t\ttimePeriod: timePeriod,\r\n\t\t})),\r\n\t\tlastUpdateDate: lastUpdate,\r\n\t\tdataPoints: mergedStats.map((s) => s.dataPoints).reduce((a, b) => a + b, 0),\r\n\t\tmmrPercentiles: mmrPercentiles,\r\n\t};\r\n\t// console.log('persisting data', stat.dataPoints, stat.heroStats?.length);\r\n\tawait s3.writeFile(\r\n\t\tgzipSync(JSON.stringify(stat)),\r\n\t\tSTATS_BUCKET,\r\n\t\tSTAT_KEY_HERO.replace('%anomaly%', anomaly ? `anomalies/${anomaly}/` : '')\r\n\t\t\t.replace('%mmrPercentile%', `${mmrPercentile}`)\r\n\t\t\t.replace('%timePeriod%', timePeriod),\r\n\t\t'application/json',\r\n\t\t'gzip',\r\n\t);\r\n\tawait s3.writeFile(\r\n\t\tgzipSync(JSON.stringify(mmrPercentiles)),\r\n\t\tSTATS_BUCKET,\r\n\t\tSTAT_KEY_PERCENTILE.replace('%anomaly%', anomaly ? `anomalies/${anomaly}/` : '').replace(\r\n\t\t\t'%timePeriod%',\r\n\t\t\ttimePeriod,\r\n\t\t),\r\n\t\t'application/json',\r\n\t\t'gzip',\r\n\t);\r\n};\r\n"]}
|
|
@@ -3,12 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.mergeStats = void 0;
|
|
4
4
|
const aws_lambda_utils_1 = require("@firestone-hs/aws-lambda-utils");
|
|
5
5
|
const util_functions_1 = require("../../../common/util-functions");
|
|
6
|
+
const stats_merger_1 = require("../../../solo/final-stats/heroes/stats-merger");
|
|
6
7
|
const mergeStats = (hourlyData, mmrPercentile, allCards) => {
|
|
7
8
|
const allStats = hourlyData
|
|
8
9
|
.flatMap((data) => data.heroStats)
|
|
9
10
|
.filter((stat) => stat.mmrPercentile === mmrPercentile)
|
|
10
11
|
.filter((stat) => stat.heroCardId !== "TB_BaconShop_HERO_PH");
|
|
11
|
-
const groupedByHero = (0, aws_lambda_utils_1.groupByFunction)((stat) => stat.heroCardId)
|
|
12
|
+
const groupedByHero = (0, aws_lambda_utils_1.groupByFunction)(allStats, (stat) => stat.heroCardId);
|
|
12
13
|
const result = Object.values(groupedByHero).map((stats) => mergeStatsForSingleHero(stats, allCards));
|
|
13
14
|
const maxDataPoints = Math.max(...result.map((r) => r.dataPoints));
|
|
14
15
|
const filtered = result.filter((r) => r.dataPoints > maxDataPoints / 50);
|
|
@@ -36,7 +37,7 @@ const mergeStatsForSingleHero = (stats, allCards) => {
|
|
|
36
37
|
standardDeviation: (0, util_functions_1.round)(standardDeviation),
|
|
37
38
|
standardDeviationOfTheMean: (0, util_functions_1.round)(standardDeviationOfTheMean),
|
|
38
39
|
conservativePositionEstimate: (0, util_functions_1.round)(averagePosition + 3 * standardDeviationOfTheMean),
|
|
39
|
-
placementDistribution: mergePlacementDistributions(stats),
|
|
40
|
+
placementDistribution: (0, stats_merger_1.mergePlacementDistributions)(stats),
|
|
40
41
|
warbandStats: mergeWarbandStats(stats),
|
|
41
42
|
combatWinrate: mergeCombatWinrate(stats, debug),
|
|
42
43
|
tribeStats: mergeTribeStats(stats, averagePosition).filter((s) => s.dataPointsOnMissingTribe > s.dataPoints / 20),
|
|
@@ -72,28 +73,6 @@ const mergeTribeStats = (stats, refAveragePosition) => {
|
|
|
72
73
|
});
|
|
73
74
|
return result;
|
|
74
75
|
};
|
|
75
|
-
const mergePlacementDistributions = (stats) => {
|
|
76
|
-
var _a, _b;
|
|
77
|
-
const rawMerge = mergePlacementDistributionsRaw(stats);
|
|
78
|
-
const result = [];
|
|
79
|
-
const totalDataPoints = rawMerge.map((s) => s.totalMatches).reduce((a, b) => a + b, 0);
|
|
80
|
-
for (let i = 1; i <= 8; i++) {
|
|
81
|
-
const total = (_b = (_a = rawMerge.find((d) => d.rank === i)) === null || _a === void 0 ? void 0 : _a.totalMatches) !== null && _b !== void 0 ? _b : 0;
|
|
82
|
-
result.push({ rank: i, percentage: (0, util_functions_1.round)((100 * total) / totalDataPoints) });
|
|
83
|
-
}
|
|
84
|
-
return result;
|
|
85
|
-
};
|
|
86
|
-
const mergePlacementDistributionsRaw = (stats) => {
|
|
87
|
-
const rawStats = stats.map((stat) => stat.placementDistributionRaw);
|
|
88
|
-
const result = [];
|
|
89
|
-
for (let i = 1; i <= 8; i++) {
|
|
90
|
-
const total = rawStats
|
|
91
|
-
.map((d) => { var _a, _b; return (_b = (_a = d === null || d === void 0 ? void 0 : d.find((info) => info.rank === i)) === null || _a === void 0 ? void 0 : _a.totalMatches) !== null && _b !== void 0 ? _b : 0; })
|
|
92
|
-
.reduce((a, b) => a + b, 0);
|
|
93
|
-
result.push({ rank: i, totalMatches: total });
|
|
94
|
-
}
|
|
95
|
-
return result;
|
|
96
|
-
};
|
|
97
76
|
const mergeWarbandStats = (stats) => {
|
|
98
77
|
const { rawMerge, maxTurn } = mergeWarbandStatsRaw(stats);
|
|
99
78
|
const result = [];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats-merger.js","sourceRoot":"","sources":["../../../../src/duos/final-stats/heroes/stats-merger.ts"],"names":[],"mappings":"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","sourcesContent":["import { groupByFunction } from '@firestone-hs/aws-lambda-utils';\r\nimport { AllCardsService, CardIds } from '@firestone-hs/reference-data';\r\nimport { round } from '../../../common/util-functions';\r\nimport { BgsGlobalHeroStat, BgsHeroStatsV2, BgsHeroTribeStat, MmrPercentileFilter } from '../../../models';\r\nimport { mergePlacementDistributions } from '../../../solo/final-stats/heroes/stats-merger';\r\n\r\nexport const mergeStats = (\r\n\thourlyData: readonly BgsHeroStatsV2[],\r\n\tmmrPercentile: MmrPercentileFilter,\r\n\tallCards: AllCardsService,\r\n): readonly BgsGlobalHeroStat[] => {\r\n\tconst allStats: readonly BgsGlobalHeroStat[] = hourlyData\r\n\t\t.flatMap((data) => data.heroStats)\r\n\t\t.filter((stat) => stat.mmrPercentile === mmrPercentile)\r\n\t\t.filter((stat) => stat.heroCardId !== CardIds.BaconphheroHeroic);\r\n\t// console.debug('allStats', mmrPercentile, allStats.length, '/', hourlyData.length);\r\n\tconst groupedByHero: {\r\n\t\t[heroCardId: string]: readonly BgsGlobalHeroStat[];\r\n\t} = groupByFunction(allStats, (stat) => stat.heroCardId);\r\n\tconst result: readonly BgsGlobalHeroStat[] = Object.values(groupedByHero).map((stats) =>\r\n\t\tmergeStatsForSingleHero(stats, allCards),\r\n\t);\r\n\tconst maxDataPoints = Math.max(...result.map((r) => r.dataPoints));\r\n\tconst filtered = result.filter((r) => r.dataPoints > maxDataPoints / 50);\r\n\treturn filtered;\r\n};\r\n\r\nconst mergeStatsForSingleHero = (stats: readonly BgsGlobalHeroStat[], allCards: AllCardsService): BgsGlobalHeroStat => {\r\n\tconst ref = stats[0];\r\n\tconst debug = ref.heroCardId === 'BG21_HERO_010';\r\n\r\n\tconst totalWeightedAverage = stats.map((s) => s.averagePosition * s.dataPoints).reduce((a, b) => a + b, 0);\r\n\tconst totalDataPoints = stats.map((s) => s.dataPoints).reduce((a, b) => a + b, 0);\r\n\tconst averagePosition = totalWeightedAverage / totalDataPoints;\r\n\r\n\tconst totalWeightedVariance = stats\r\n\t\t.map((s) => s.standardDeviation * s.standardDeviation * s.dataPoints)\r\n\t\t.reduce((a, b) => a + b, 0);\r\n\tconst overallVariance = totalWeightedVariance / totalDataPoints;\r\n\tconst standardDeviation = Math.sqrt(overallVariance);\r\n\tconst standardDeviationOfTheMean = standardDeviation / Math.sqrt(totalDataPoints);\r\n\r\n\tconst result: BgsGlobalHeroStat = {\r\n\t\theroCardId: ref.heroCardId,\r\n\t\tdataPoints: stats.map((stat) => stat.dataPoints).reduce((a, b) => a + b, 0),\r\n\t\ttotalOffered: stats.map((stat) => stat.totalOffered ?? 0).reduce((a, b) => a + b, 0),\r\n\t\ttotalPicked: stats.map((stat) => stat.totalPicked ?? 0).reduce((a, b) => a + b, 0),\r\n\t\taveragePosition: round(averagePosition),\r\n\t\tstandardDeviation: round(standardDeviation),\r\n\t\tstandardDeviationOfTheMean: round(standardDeviationOfTheMean),\r\n\t\tconservativePositionEstimate: round(averagePosition + 3 * standardDeviationOfTheMean),\r\n\t\tplacementDistribution: mergePlacementDistributions(stats),\r\n\t\twarbandStats: mergeWarbandStats(stats),\r\n\t\tcombatWinrate: mergeCombatWinrate(stats, debug),\r\n\t\ttribeStats: mergeTribeStats(stats, averagePosition).filter(\r\n\t\t\t(s) => s.dataPointsOnMissingTribe > s.dataPoints / 20,\r\n\t\t),\r\n\t};\r\n\treturn result;\r\n};\r\n\r\nconst mergeTribeStats = (\r\n\tstats: readonly BgsGlobalHeroStat[],\r\n\trefAveragePosition: number,\r\n): readonly BgsHeroTribeStat[] => {\r\n\tconst allTribeStats = stats.flatMap((stat) => stat.tribeStats);\r\n\tconst uniqueTribes = new Set(allTribeStats.map((tribe) => tribe.tribe));\r\n\tconst result: BgsHeroTribeStat[] = [...uniqueTribes].map((tribe) => {\r\n\t\tconst tribeStats = allTribeStats.filter((stat) => stat.tribe === tribe);\r\n\t\tconst totalStatDataPoints = tribeStats.map((stat) => stat.dataPoints).reduce((a, b) => a + b, 0);\r\n\t\tconst averagePosition =\r\n\t\t\ttribeStats.map((stat) => stat.averagePosition * stat.dataPoints).reduce((a, b) => a + b, 0) /\r\n\t\t\ttotalStatDataPoints;\r\n\t\tconst averagePositionWithoutTribe =\r\n\t\t\ttribeStats\r\n\t\t\t\t.map((stat) => stat.averagePositionWithoutTribe * stat.dataPointsOnMissingTribe)\r\n\t\t\t\t.reduce((a, b) => a + b, 0) /\r\n\t\t\ttribeStats.map((stat) => stat.dataPointsOnMissingTribe).reduce((a, b) => a + b, 0);\r\n\t\t// const impactAveragePosition =\r\n\t\t// \ttribeStats.map((stat) => stat.impactAveragePosition * stat.dataPoints).reduce((a, b) => a + b, 0) /\r\n\t\t// \ttotalStatDataPoints;\r\n\t\t// const impactAveragePositionVsMissingTribe =\r\n\t\t// \ttribeStats\r\n\t\t// \t\t.map((stat) => stat.impactAveragePositionVsMissingTribe * stat.dataPoints)\r\n\t\t// \t\t.reduce((a, b) => a + b, 0) / totalStatDataPoints;\r\n\t\treturn {\r\n\t\t\ttribe: tribe,\r\n\t\t\tdataPoints: totalStatDataPoints,\r\n\t\t\tdataPointsOnMissingTribe: tribeStats\r\n\t\t\t\t.map((stat) => stat.dataPointsOnMissingTribe)\r\n\t\t\t\t.reduce((a, b) => a + b, 0),\r\n\t\t\ttotalOffered: tribeStats.map((stat) => stat.totalOffered ?? 0).reduce((a, b) => a + b, 0),\r\n\t\t\ttotalPicked: tribeStats.map((stat) => stat.totalPicked ?? 0).reduce((a, b) => a + b, 0),\r\n\t\t\taveragePosition: round(averagePosition),\r\n\t\t\taveragePositionWithoutTribe: round(averagePositionWithoutTribe),\r\n\t\t\trefAveragePosition: refAveragePosition,\r\n\t\t\timpactAveragePosition: round(averagePosition - refAveragePosition),\r\n\t\t\t// impactAveragePositionDebug: round(impactAveragePosition),\r\n\t\t\timpactAveragePositionVsMissingTribe: round(averagePosition - averagePositionWithoutTribe),\r\n\t\t};\r\n\t});\r\n\treturn result;\r\n};\r\n\r\nconst mergeWarbandStats = (stats: readonly BgsGlobalHeroStat[]): readonly { turn: number; averageStats: number }[] => {\r\n\tconst { rawMerge, maxTurn } = mergeWarbandStatsRaw(stats);\r\n\tconst result: { turn: number; averageStats: number }[] = [];\r\n\tfor (let i = 1; i <= maxTurn; i++) {\r\n\t\tconst statsForTurn = rawMerge.find((d) => d.turn === i);\r\n\t\tresult.push({ turn: i, averageStats: round(statsForTurn.totalStats / statsForTurn.dataPoints) });\r\n\t}\r\n\treturn result;\r\n};\r\n\r\nconst mergeWarbandStatsRaw = (\r\n\tstats: readonly BgsGlobalHeroStat[],\r\n): { rawMerge: readonly { turn: number; dataPoints: number; totalStats: number }[]; maxTurn: number } => {\r\n\tconst rawStats = stats.map((stat) => stat.warbandStatsRaw).filter((s) => !!s?.length);\r\n\tconst result: { turn: number; dataPoints: number; totalStats: number }[] = [];\r\n\tconst maxTurn = Math.min(20, Math.max(...rawStats.map((stat) => getMaxTurn(stat))));\r\n\tfor (let i = 1; i <= maxTurn; i++) {\r\n\t\tconst rawStatsForTurn = rawStats.map((stat) => stat.find((info) => info.turn === i));\r\n\t\tconst totalStats: number = rawStatsForTurn.map((d) => d?.totalStats ?? 0).reduce((a, b) => a + b, 0);\r\n\t\tconst totalDataPoints = rawStatsForTurn.map((d) => d?.dataPoints ?? 0).reduce((a, b) => a + b, 0);\r\n\t\tresult.push({ turn: i, totalStats: totalStats, dataPoints: totalDataPoints });\r\n\t}\r\n\treturn { rawMerge: result, maxTurn: maxTurn };\r\n};\r\n\r\nconst mergeCombatWinrate = (\r\n\tstats: readonly BgsGlobalHeroStat[],\r\n\tdebug = false,\r\n): readonly { turn: number; winrate: number }[] => {\r\n\tconst { rawMerge, maxTurn } = mergeCombatWinrateRaw(stats, debug);\r\n\tconst result: { turn: number; winrate: number }[] = [];\r\n\tfor (let i = 1; i <= maxTurn; i++) {\r\n\t\tconst statForTurn = rawMerge.find((d) => d.turn === i);\r\n\t\tresult.push({ turn: i, winrate: round(statForTurn.totalWinrate / statForTurn.dataPoints) });\r\n\t}\r\n\treturn result;\r\n};\r\n\r\nconst mergeCombatWinrateRaw = (\r\n\tstats: readonly BgsGlobalHeroStat[],\r\n\tdebug = false,\r\n): { rawMerge: readonly { turn: number; dataPoints: number; totalWinrate: number }[]; maxTurn: number } => {\r\n\tconst rawStats = stats.map((stat) => stat.combatWinrateRaw).filter((stat) => !!stat?.length);\r\n\t// debug && console.log('rawStats', rawStats?.length, rawStats);\r\n\tconst result: { turn: number; dataPoints: number; totalWinrate: number }[] = [];\r\n\tconst maxTurn = Math.min(20, Math.max(...rawStats.map((stat) => getMaxTurn(stat))));\r\n\t// debug && console.log('maxTurn', maxTurn);\r\n\tfor (let i = 0; i <= maxTurn; i++) {\r\n\t\tconst rawStatsForTurn = rawStats.map((stat) => stat.find((info) => info.turn === i));\r\n\t\tconst totalWinrate: number = rawStatsForTurn.map((d) => d?.totalWinrate ?? 0).reduce((a, b) => a + b, 0);\r\n\t\tconst totalDataPoints = rawStatsForTurn.map((d) => d?.dataPoints ?? 0).reduce((a, b) => a + b, 0);\r\n\t\tresult.push({ turn: i, totalWinrate: totalWinrate, dataPoints: totalDataPoints });\r\n\t}\r\n\t// debug && console.log('result', result);\r\n\treturn { rawMerge: result, maxTurn: maxTurn };\r\n};\r\n\r\nconst getMaxTurn = (rawStats: readonly { turn: number }[]): number => {\r\n\tif (!rawStats?.length) {\r\n\t\treturn 0;\r\n\t}\r\n\treturn Math.max(...rawStats.map((stat) => stat.turn));\r\n};\r\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hourly-utils.js","sourceRoot":"","sources":["../../../src/duos/final-stats/hourly-utils.ts"],"names":[],"mappings":";;;AAIO,MAAM,uBAAuB,GAAG,CAAC,UAAsB,EAAE,SAAoB,EAAU,EAAE;IAC/F,QAAQ,UAAU,EAAE;QACnB,KAAK,YAAY;YAChB,OAAO,CAAC,GAAG,EAAE,CAAC;QACf,KAAK,YAAY;YAChB,OAAO,CAAC,GAAG,EAAE,CAAC;QACf,KAAK,UAAU;YACd,OAAO,EAAE,GAAG,EAAE,CAAC;QAChB,KAAK,YAAY;YAChB,MAAM,gBAAgB,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,gBAAgB,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;YAEvF,OAAO,KAAK,CAAC;KACd;AACF,CAAC,CAAC;AAdW,QAAA,uBAAuB,2BAclC;AAEK,MAAM,cAAc,GAAG,CAAC,SAAiB,EAAqB,EAAE;IAGtE,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE;QACnC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC1D,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAExB,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACnC,SAAS,CAAC,IAAI,CAAC,GAAG,OAAO,EAAE,CAAC,CAAC;KAC7B;IACD,OAAO,SAAS,CAAC;AAClB,CAAC,CAAC;AAfW,QAAA,cAAc,kBAezB","sourcesContent":["/* eslint-disable no-case-declarations */\r\nimport { PatchInfo } from '@firestone-hs/aws-lambda-utils';\r\nimport { TimePeriod } from '../../models';\r\n\r\nexport const computeHoursBackFromNow = (timePeriod: TimePeriod, patchInfo: PatchInfo): number => {\r\n\tswitch (timePeriod) {\r\n\t\tcase 'past-three':\r\n\t\t\treturn 3 * 24;\r\n\t\tcase 'past-seven':\r\n\t\t\treturn 7 * 24;\r\n\t\tcase 'all-time':\r\n\t\t\treturn 20 * 24;\r\n\t\tcase 'last-patch':\r\n\t\t\tconst patchReleaseDate = new Date(patchInfo.date);\r\n\t\t\tconst hours = Math.floor((Date.now() - patchReleaseDate.getTime()) / (1000 * 60 * 60));\r\n\t\t\t// console.debug('hours since last patch', hours, patchReleaseDate, patchInfo);\r\n\t\t\treturn hours;\r\n\t}\r\n};\r\n\r\nexport const buildFileNames = (hoursBack: number): readonly string[] => {\r\n\t// Build a list of file names, in the form YYYY-MM-dd (e.g. 2020-05-01)\r\n\t// that start from the day before the current date and go back in time\r\n\tconst fileNames: string[] = [];\r\n\tconst now = new Date();\r\n\tfor (let i = 0; i < hoursBack; i++) {\r\n\t\tconst date = new Date(now.getTime() - i * 60 * 60 * 1000);\r\n\t\tdate.setMinutes(0);\r\n\t\tdate.setSeconds(0);\r\n\t\tdate.setMilliseconds(0);\r\n\t\t// The date in the format YYYY-MM-ddTHH:mm:ss.sssZ\r\n\t\tconst dateStr = date.toISOString();\r\n\t\tfileNames.push(`${dateStr}`);\r\n\t}\r\n\treturn fileNames;\r\n};\r\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"percentiles.js","sourceRoot":"","sources":["../../../src/duos/final-stats/percentiles.ts"],"names":[],"mappings":";;;AAGO,MAAM,mBAAmB,GAAG,CAClC,UAAuD,EAC5B,EAAE;IAG7B,OAAO,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,CAC1B,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CACrF,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC;AACrB,CAAC,CAAC;AARW,QAAA,mBAAmB,uBAQ9B","sourcesContent":["import { BgsQuestStats } from '../../model-quests';\r\nimport { BgsHeroStatsV2, MmrPercentile } from '../../models';\r\n\r\nexport const buildMmrPercentiles = (\r\n\thourlyData: readonly (BgsHeroStatsV2 | BgsQuestStats)[],\r\n): readonly MmrPercentile[] => {\r\n\t// For now we simply pick the latest MMR percentiles, as it reflects the most accurately the current\r\n\t// state of the game\r\n\treturn [...hourlyData].sort(\r\n\t\t(a, b) => new Date(b.lastUpdateDate).getTime() - new Date(a.lastUpdateDate).getTime(),\r\n\t)[0].mmrPercentiles;\r\n};\r\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3-loader.js","sourceRoot":"","sources":["../../../src/duos/final-stats/s3-loader.ts"],"names":[],"mappings":";;;AAGA,+FAA4G;AAC5G,8EAAsD;AACtD,iDAAyE;AAKlE,MAAM,oBAAoB,GAAG,KAAK,EACxC,IAAO,EACP,UAAsB,EACtB,aAAkC,EAClC,OAAsB,EACtB,SAAoB,EACgB,EAAE;IACtC,MAAM,SAAS,GAAW,IAAA,sCAAuB,EAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IACzE,MAAM,SAAS,GAAsB,IAAA,6BAAc,EAAC,SAAS,CAAC,CAAC;IAE/D,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CACpC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,wBAAwB,CAAC,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC,CAC7F,CAAC;IACF,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AACjD,CAAC,CAAC;AAdW,QAAA,oBAAoB,wBAc/B;AAEF,MAAM,wBAAwB,GAAG,KAAK,EACrC,IAAO,EACP,OAAsB,EACtB,aAAkC,EAClC,QAAgB,EACS,EAAE;IAC3B,MAAM,OAAO,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,iDAAe,CAAC,CAAC,CAAC,kDAAgB,CAAC;IACrE,MAAM,OAAO,GAAG,OAAO;SACrB,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5D,OAAO,CAAC,iBAAiB,EAAE,GAAG,aAAa,EAAE,CAAC;SAC9C,OAAO,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,MAAM,4BAAE,CAAC,eAAe,CAAC,8CAAY,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;IACvE,MAAM,MAAM,GAAkB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC;AACf,CAAC,CAAC","sourcesContent":["import { PatchInfo } from '@firestone-hs/aws-lambda-utils';\r\nimport { BgsQuestStats } from '../../model-quests';\r\nimport { BgsHeroStatsV2, MmrPercentileFilter, TimePeriod } from '../../models';\r\nimport { HOURLY_KEY_HERO, HOURLY_KEY_QUEST, STATS_BUCKET } from '../hourly/_build-battlegrounds-hero-stats';\r\nimport { s3 } from './heroes/_build-aggregated-stats';\r\nimport { buildFileNames, computeHoursBackFromNow } from './hourly-utils';\r\n\r\nexport type DataType = 'hero' | 'quest';\r\nexport type DataResult<T extends DataType> = T extends 'hero' ? BgsHeroStatsV2 : BgsQuestStats;\r\n\r\nexport const loadHourlyDataFromS3 = async <T extends DataType>(\r\n\ttype: T,\r\n\ttimePeriod: TimePeriod,\r\n\tmmrPercentile: MmrPercentileFilter,\r\n\tanomaly: string | null,\r\n\tpatchInfo: PatchInfo,\r\n): Promise<readonly DataResult<T>[]> => {\r\n\tconst hoursBack: number = computeHoursBackFromNow(timePeriod, patchInfo);\r\n\tconst fileNames: readonly string[] = buildFileNames(hoursBack);\r\n\t// console.debug('fileNames', timePeriod, mmrPercentile, fileNames);\r\n\tconst fileResults = await Promise.all(\r\n\t\tfileNames.map((fileName) => loadHourlyDeckStatFromS3(type, anomaly, mmrPercentile, fileName)),\r\n\t);\r\n\treturn fileResults.filter((result) => !!result);\r\n};\r\n\r\nconst loadHourlyDeckStatFromS3 = async <T extends DataType>(\r\n\ttype: T,\r\n\tanomaly: string | null,\r\n\tmmrPercentile: MmrPercentileFilter,\r\n\tfileName: string,\r\n): Promise<DataResult<T>> => {\r\n\tconst mainKey = type === 'hero' ? HOURLY_KEY_HERO : HOURLY_KEY_QUEST;\r\n\tconst fileKey = mainKey\r\n\t\t.replace('%anomaly%', anomaly ? `anomalies/${anomaly}/` : '')\r\n\t\t.replace('%mmrPercentile%', `${mmrPercentile}`)\r\n\t\t.replace('%startDate%', fileName);\r\n\tconst data = await s3.readGzipContent(STATS_BUCKET, fileKey, 1, false);\r\n\tconst result: DataResult<T> = JSON.parse(data);\r\n\treturn result;\r\n};\r\n"]}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.handleNewStats = exports.HOURLY_KEY_TRINKET = exports.HOURLY_KEY_QUEST = exports.HOURLY_KEY_HERO = exports.WORKING_ROWS_FILE = exports.STATS_KEY_PREFIX = exports.STATS_BUCKET = exports.s3 = void 0;
|
|
4
|
+
const client_lambda_1 = require("@aws-sdk/client-lambda");
|
|
7
5
|
const aws_lambda_utils_1 = require("@firestone-hs/aws-lambda-utils");
|
|
8
6
|
const reference_data_1 = require("@firestone-hs/reference-data");
|
|
9
|
-
const aws_sdk_1 = __importDefault(require("aws-sdk"));
|
|
10
7
|
const trinket_stats_1 = require("../../solo/hourly/trinkets/trinket-stats");
|
|
11
8
|
const hero_stats_1 = require("./hero-stats");
|
|
12
9
|
const rows_1 = require("./rows");
|
|
10
|
+
const quest_stats_1 = require("../../solo/hourly/quest-stats");
|
|
13
11
|
exports.s3 = new aws_lambda_utils_1.S3();
|
|
14
12
|
const allCards = new reference_data_1.AllCardsService();
|
|
15
|
-
const lambda = new
|
|
13
|
+
const lambda = new client_lambda_1.LambdaClient({
|
|
14
|
+
region: process.env.AWS_REGION || 'us-west-2',
|
|
15
|
+
});
|
|
16
16
|
const allMmrPercentiles = [100, 50, 25, 10, 1];
|
|
17
17
|
exports.STATS_BUCKET = 'static.zerotoheroes.com';
|
|
18
18
|
exports.STATS_KEY_PREFIX = `api/bgs/duo`;
|
|
@@ -36,15 +36,13 @@ const handleNewStats = async (event, context) => {
|
|
|
36
36
|
cleanup();
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
|
-
if (event.
|
|
39
|
+
if (event.questsV2) {
|
|
40
|
+
const lastHourRows = await (0, rows_1.readRowsFromS3)(event.startDate);
|
|
41
|
+
await (0, quest_stats_1.buildQuestStats)(event.startDate, event.mmr, lastHourRows, allCards, exports.s3);
|
|
42
|
+
}
|
|
43
|
+
else if (event.statsV2) {
|
|
40
44
|
const lastHourRows = await (0, rows_1.readRowsFromS3)(event.startDate);
|
|
41
|
-
const uniqueAnomalies = [
|
|
42
|
-
null,
|
|
43
|
-
...lastHourRows
|
|
44
|
-
.flatMap((r) => { var _a; return (_a = r.bgsAnomalies) === null || _a === void 0 ? void 0 : _a.split(','); })
|
|
45
|
-
.filter((a) => a)
|
|
46
|
-
.filter((value, index, self) => self.indexOf(value) === index),
|
|
47
|
-
];
|
|
45
|
+
const uniqueAnomalies = [null];
|
|
48
46
|
for (const anomaly of uniqueAnomalies) {
|
|
49
47
|
console.log('building hero stats', event.startDate, event.mmr, lastHourRows === null || lastHourRows === void 0 ? void 0 : lastHourRows.length, anomaly);
|
|
50
48
|
await (0, hero_stats_1.buildHeroStats)(event.startDate, event.mmr, anomaly, lastHourRows, allCards);
|
|
@@ -91,14 +89,12 @@ const dispatchTrinketsLambda = async (context, startDate) => {
|
|
|
91
89
|
Payload: JSON.stringify(newEvent),
|
|
92
90
|
};
|
|
93
91
|
console.log('\tinvoking lambda', params);
|
|
94
|
-
const result = await lambda
|
|
95
|
-
.invoke({
|
|
92
|
+
const result = await lambda.send(new client_lambda_1.InvokeCommand({
|
|
96
93
|
FunctionName: context.functionName,
|
|
97
94
|
InvocationType: 'Event',
|
|
98
95
|
LogType: 'Tail',
|
|
99
96
|
Payload: JSON.stringify(newEvent),
|
|
100
|
-
})
|
|
101
|
-
.promise();
|
|
97
|
+
}));
|
|
102
98
|
}
|
|
103
99
|
};
|
|
104
100
|
const dispatchQuestsV2Lambda = async (context, startDate) => {
|
|
@@ -115,14 +111,12 @@ const dispatchQuestsV2Lambda = async (context, startDate) => {
|
|
|
115
111
|
Payload: JSON.stringify(newEvent),
|
|
116
112
|
};
|
|
117
113
|
console.log('\tinvoking lambda', params);
|
|
118
|
-
const result = await lambda
|
|
119
|
-
.invoke({
|
|
114
|
+
const result = await lambda.send(new client_lambda_1.InvokeCommand({
|
|
120
115
|
FunctionName: context.functionName,
|
|
121
116
|
InvocationType: 'Event',
|
|
122
117
|
LogType: 'Tail',
|
|
123
118
|
Payload: JSON.stringify(newEvent),
|
|
124
|
-
})
|
|
125
|
-
.promise();
|
|
119
|
+
}));
|
|
126
120
|
}
|
|
127
121
|
};
|
|
128
122
|
const dispatchStatsV2Lambda = async (context, startDate) => {
|
|
@@ -139,14 +133,12 @@ const dispatchStatsV2Lambda = async (context, startDate) => {
|
|
|
139
133
|
Payload: JSON.stringify(newEvent),
|
|
140
134
|
};
|
|
141
135
|
console.log('\tinvoking lambda', params);
|
|
142
|
-
const result = await lambda
|
|
143
|
-
.invoke({
|
|
136
|
+
const result = await lambda.send(new client_lambda_1.InvokeCommand({
|
|
144
137
|
FunctionName: context.functionName,
|
|
145
138
|
InvocationType: 'Event',
|
|
146
139
|
LogType: 'Tail',
|
|
147
140
|
Payload: JSON.stringify(newEvent),
|
|
148
|
-
})
|
|
149
|
-
.promise();
|
|
141
|
+
}));
|
|
150
142
|
}
|
|
151
143
|
};
|
|
152
144
|
const dispatchCatchUpEvents = async (context, daysInThePast) => {
|
|
@@ -171,14 +163,12 @@ const dispatchCatchUpEvents = async (context, daysInThePast) => {
|
|
|
171
163
|
LogType: 'Tail',
|
|
172
164
|
Payload: JSON.stringify(newEvent),
|
|
173
165
|
};
|
|
174
|
-
const result = await lambda
|
|
175
|
-
.invoke({
|
|
166
|
+
const result = await lambda.send(new client_lambda_1.InvokeCommand({
|
|
176
167
|
FunctionName: context.functionName,
|
|
177
168
|
InvocationType: 'Event',
|
|
178
169
|
LogType: 'Tail',
|
|
179
170
|
Payload: JSON.stringify(newEvent),
|
|
180
|
-
})
|
|
181
|
-
.promise();
|
|
171
|
+
}));
|
|
182
172
|
await (0, aws_lambda_utils_1.sleep)(50);
|
|
183
173
|
}
|
|
184
174
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_build-battlegrounds-hero-stats.js","sourceRoot":"","sources":["../../../src/duos/hourly/_build-battlegrounds-hero-stats.ts"],"names":[],"mappings":";;;;;;AACA,qEAA6E;AAC7E,iEAA+D;AAE/D,sDAA0B;AAE1B,4EAA6E;AAC7E,6CAA8C;AAC9C,iCAAsD;AAEzC,QAAA,EAAE,GAAG,IAAI,qBAAE,EAAE,CAAC;AAC3B,MAAM,QAAQ,GAAG,IAAI,gCAAe,EAAE,CAAC;AACvC,MAAM,MAAM,GAAG,IAAI,iBAAG,CAAC,MAAM,EAAE,CAAC;AAEhC,MAAM,iBAAiB,GAA+B,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAE9D,QAAA,YAAY,GAAG,yBAAyB,CAAC;AACzC,QAAA,gBAAgB,GAAG,aAAa,CAAC;AACjC,QAAA,iBAAiB,GAAG,GAAG,wBAAgB,mCAAmC,CAAC;AAC3E,QAAA,eAAe,GAAG,GAAG,wBAAgB,qEAAqE,CAAC;AAC3G,QAAA,gBAAgB,GAAG,GAAG,wBAAgB,6DAA6D,CAAC;AACpG,QAAA,kBAAkB,GAAG,GAAG,wBAAgB,+DAA+D,CAAC;AAErH,kBAAe,KAAK,EAAE,KAAK,EAAE,OAAgB,EAAgB,EAAE;IAC9D,MAAM,IAAA,sBAAc,EAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AACtC,CAAC,CAAC;AAEK,MAAM,cAAc,GAAG,KAAK,EAAE,KAAK,EAAE,OAAgB,EAAE,EAAE;IAC/D,MAAM,OAAO,GAAG,IAAA,mCAAgB,EAAC,OAAO,CAAC,CAAC;IAE1C,MAAM,QAAQ,CAAC,iBAAiB,EAAE,CAAC;IAEnC,IAAI,KAAK,CAAC,OAAO,EAAE;QAClB,MAAM,qBAAqB,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrD,OAAO,EAAE,CAAC;QACV,OAAO;KACP;IAED,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE;QACzD,MAAM,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACzC,OAAO,EAAE,CAAC;QACV,OAAO;KACP;IAOD,IAAI,KAAK,CAAC,OAAO,EAAE;QAClB,MAAM,YAAY,GAA8B,MAAM,IAAA,qBAAc,EAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACtF,MAAM,eAAe,GAAG;YACvB,IAAI;YACJ,GAAG,YAAY;iBACb,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,WAAC,OAAA,MAAA,CAAC,CAAC,YAAY,0CAAE,KAAK,CAAC,GAAG,CAAC,CAAA,EAAA,CAAC;iBAC1C,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;iBAChB,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC;SAC/D,CAAC;QACF,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE;YACtC,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,EAAE,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,MAAM,EAAE,OAAO,CAAC,CAAC;YAC9F,MAAM,IAAA,2BAAc,EAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;SAClF;KACD;SAAM,IAAI,KAAK,CAAC,QAAQ,EAAE;QAC1B,MAAM,YAAY,GAA8B,MAAM,IAAA,qBAAc,EAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAEtF,MAAM,IAAA,iCAAiB,EACtB,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,GAAG,EACT,YAAY,EACZ,QAAQ,EACR,oBAAY,EACZ,0BAAkB,EAClB,UAAE,CACF,CAAC;KACF;IAED,OAAO,EAAE,CAAC;AACX,CAAC,CAAC;AAlDW,QAAA,cAAc,kBAkDzB;AAEF,MAAM,kBAAkB,GAAG,KAAK,EAAE,OAAgB,EAAE,KAAK,EAAE,EAAE;IAC5D,MAAM,SAAS,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAE/C,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC;IAEzC,MAAM,IAAA,mBAAY,EAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAEjD,MAAM,qBAAqB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAEhD,MAAM,sBAAsB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AAClD,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAQ,EAAE;IAC7C,IAAI,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,UAAU,EAAE;QACtB,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC9C,OAAO,UAAU,CAAC;KAClB;IAGD,MAAM,gBAAgB,GAAG,IAAI,IAAI,EAAE,CAAC;IACpC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC/B,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC/B,gBAAgB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IACpC,gBAAgB,CAAC,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC;IAC3D,OAAO,gBAAgB,CAAC;AACzB,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,KAAK,EAAE,OAAgB,EAAE,SAAe,EAAE,EAAE;IAC1E,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE;QACpC,MAAM,QAAQ,GAAG;YAChB,QAAQ,EAAE,IAAI;YACd,GAAG,EAAE,GAAG;YACR,SAAS,EAAE,SAAS;SACpB,CAAC;QACF,MAAM,MAAM,GAAG;YACd,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,cAAc,EAAE,OAAO;YACvB,OAAO,EAAE,MAAM;YACf,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;SACjC,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,MAAM,MAAM;aACzB,MAAM,CAAC;YACP,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,cAAc,EAAE,OAAO;YACvB,OAAO,EAAE,MAAM;YACf,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;SACjC,CAAC;aACD,OAAO,EAAE,CAAC;KAEZ;AACF,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,KAAK,EAAE,OAAgB,EAAE,SAAe,EAAE,EAAE;IAC1E,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE;QACpC,MAAM,QAAQ,GAAG;YAChB,QAAQ,EAAE,IAAI;YACd,GAAG,EAAE,GAAG;YACR,SAAS,EAAE,SAAS;SACpB,CAAC;QACF,MAAM,MAAM,GAAG;YACd,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,cAAc,EAAE,OAAO;YACvB,OAAO,EAAE,MAAM;YACf,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;SACjC,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,MAAM,MAAM;aACzB,MAAM,CAAC;YACP,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,cAAc,EAAE,OAAO;YACvB,OAAO,EAAE,MAAM;YACf,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;SACjC,CAAC;aACD,OAAO,EAAE,CAAC;KAEZ;AACF,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,KAAK,EAAE,OAAgB,EAAE,SAAe,EAAE,EAAE;IACzE,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE;QACpC,MAAM,QAAQ,GAAG;YAChB,OAAO,EAAE,IAAI;YACb,GAAG,EAAE,GAAG;YACR,SAAS,EAAE,SAAS;SACpB,CAAC;QACF,MAAM,MAAM,GAAG;YACd,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,cAAc,EAAE,OAAO;YACvB,OAAO,EAAE,MAAM;YACf,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;SACjC,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,MAAM,MAAM;aACzB,MAAM,CAAC;YACP,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,cAAc,EAAE,OAAO;YACvB,OAAO,EAAE,MAAM;YACf,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;SACjC,CAAC;aACD,OAAO,EAAE,CAAC;KAEZ;AACF,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,KAAK,EAAE,OAAgB,EAAE,aAAqB,EAAE,EAAE;IAE/E,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,KAAK,GAAG,EAAE,CAAC;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,aAAa,EAAE,CAAC,EAAE,EAAE;QAC5C,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/B,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACvB,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACvB,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC/D,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;KAC/B;IAED,KAAK,MAAM,UAAU,IAAI,KAAK,EAAE;QAC/B,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE,UAAU,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAG;YAChB,UAAU,EAAE,UAAU;SACtB,CAAC;QACF,MAAM,MAAM,GAAG;YACd,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,cAAc,EAAE,OAAO;YACvB,OAAO,EAAE,MAAM;YACf,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;SACjC,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,MAAM;aACzB,MAAM,CAAC;YACP,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,cAAc,EAAE,OAAO;YACvB,OAAO,EAAE,MAAM;YACf,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;SACjC,CAAC;aACD,OAAO,EAAE,CAAC;QAEZ,MAAM,IAAA,wBAAK,EAAC,EAAE,CAAC,CAAC;KAChB;AACF,CAAC,CAAC","sourcesContent":["/* eslint-disable @typescript-eslint/no-use-before-define */\r\nimport { S3, logBeforeTimeout, sleep } from '@firestone-hs/aws-lambda-utils';\r\nimport { AllCardsService } from '@firestone-hs/reference-data';\r\nimport { Context } from 'aws-lambda';\r\nimport AWS from 'aws-sdk';\r\nimport { InternalBgsRow } from '../../internal-model';\r\nimport { buildTrinketStats } from '../../solo/hourly/trinkets/trinket-stats';\r\nimport { buildHeroStats } from './hero-stats';\r\nimport { readRowsFromS3, saveRowsOnS3 } from './rows';\r\n\r\nexport const s3 = new S3();\r\nconst allCards = new AllCardsService();\r\nconst lambda = new AWS.Lambda();\r\n\r\nconst allMmrPercentiles: (100 | 50 | 25 | 10 | 1)[] = [100, 50, 25, 10, 1];\r\n\r\nexport const STATS_BUCKET = 'static.zerotoheroes.com';\r\nexport const STATS_KEY_PREFIX = `api/bgs/duo`;\r\nexport const WORKING_ROWS_FILE = `${STATS_KEY_PREFIX}/working/working-rows-%time%.json`;\r\nexport const HOURLY_KEY_HERO = `${STATS_KEY_PREFIX}/hero-stats/%anomaly%mmr-%mmrPercentile%/hourly/%startDate%.gz.json`;\r\nexport const HOURLY_KEY_QUEST = `${STATS_KEY_PREFIX}/quest-stats/mmr-%mmrPercentile%/hourly/%startDate%.gz.json`;\r\nexport const HOURLY_KEY_TRINKET = `${STATS_KEY_PREFIX}/trinket-stats/mmr-%mmrPercentile%/hourly/%startDate%.gz.json`;\r\n\r\nexport default async (event, context: Context): Promise<any> => {\r\n\tawait handleNewStats(event, context);\r\n};\r\n\r\nexport const handleNewStats = async (event, context: Context) => {\r\n\tconst cleanup = logBeforeTimeout(context);\r\n\t// logger.log('event', event);\r\n\tawait allCards.initializeCardsDb();\r\n\r\n\tif (event.catchUp) {\r\n\t\tawait dispatchCatchUpEvents(context, +event.catchUp);\r\n\t\tcleanup();\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!event.statsV2 && !event.questsV2 && !event.trinkets) {\r\n\t\tawait dispatchMainEvents(context, event);\r\n\t\tcleanup();\r\n\t\treturn;\r\n\t}\r\n\r\n\t// if (event.questsV2) {\r\n\t// \tconst lastHourRows: readonly InternalBgsRow[] = await readRowsFromS3(event.startDate);\r\n\t// \t// logger.log('building quest stats', event.timePeriod, event.startDate, lastHourRows?.length);\r\n\t// \tawait buildQuestStats(event.startDate, event.mmr, lastHourRows, allCards, s3);\r\n\t// } else\r\n\tif (event.statsV2) {\r\n\t\tconst lastHourRows: readonly InternalBgsRow[] = await readRowsFromS3(event.startDate);\r\n\t\tconst uniqueAnomalies = [\r\n\t\t\tnull,\r\n\t\t\t...lastHourRows\r\n\t\t\t\t.flatMap((r) => r.bgsAnomalies?.split(','))\r\n\t\t\t\t.filter((a) => a)\r\n\t\t\t\t.filter((value, index, self) => self.indexOf(value) === index),\r\n\t\t];\r\n\t\tfor (const anomaly of uniqueAnomalies) {\r\n\t\t\tconsole.log('building hero stats', event.startDate, event.mmr, lastHourRows?.length, anomaly);\r\n\t\t\tawait buildHeroStats(event.startDate, event.mmr, anomaly, lastHourRows, allCards);\r\n\t\t}\r\n\t} else if (event.trinkets) {\r\n\t\tconst lastHourRows: readonly InternalBgsRow[] = await readRowsFromS3(event.startDate);\r\n\t\t// logger.log('building hero stats', event.startDate, lastHourRows?.length);\r\n\t\tawait buildTrinketStats(\r\n\t\t\tevent.startDate,\r\n\t\t\tevent.mmr,\r\n\t\t\tlastHourRows,\r\n\t\t\tallCards,\r\n\t\t\tSTATS_BUCKET,\r\n\t\t\tHOURLY_KEY_TRINKET,\r\n\t\t\ts3,\r\n\t\t);\r\n\t}\r\n\r\n\tcleanup();\r\n};\r\n\r\nconst dispatchMainEvents = async (context: Context, event) => {\r\n\tconst startDate = buildProcessStartDate(event);\r\n\t// End one hour later\r\n\tconst endDate = new Date(startDate);\r\n\tendDate.setHours(endDate.getHours() + 1);\r\n\r\n\tawait saveRowsOnS3(startDate, endDate, allCards);\r\n\r\n\tawait dispatchStatsV2Lambda(context, startDate);\r\n\t// await dispatchQuestsV2Lambda(context, startDate);\r\n\tawait dispatchTrinketsLambda(context, startDate);\r\n};\r\n\r\nconst buildProcessStartDate = (event): Date => {\r\n\tif (event?.targetDate) {\r\n\t\tconst targetDate = new Date(event.targetDate);\r\n\t\treturn targetDate;\r\n\t}\r\n\r\n\t// Start from the start of the current hour\r\n\tconst processStartDate = new Date();\r\n\tprocessStartDate.setMinutes(0);\r\n\tprocessStartDate.setSeconds(0);\r\n\tprocessStartDate.setMilliseconds(0);\r\n\tprocessStartDate.setHours(processStartDate.getHours() - 1);\r\n\treturn processStartDate;\r\n};\r\n\r\nconst dispatchTrinketsLambda = async (context: Context, startDate: Date) => {\r\n\tfor (const mmr of allMmrPercentiles) {\r\n\t\tconst newEvent = {\r\n\t\t\ttrinkets: true,\r\n\t\t\tmmr: mmr,\r\n\t\t\tstartDate: startDate,\r\n\t\t};\r\n\t\tconst params = {\r\n\t\t\tFunctionName: context.functionName,\r\n\t\t\tInvocationType: 'Event',\r\n\t\t\tLogType: 'Tail',\r\n\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t};\r\n\t\tconsole.log('\\tinvoking lambda', params);\r\n\t\tconst result = await lambda\r\n\t\t\t.invoke({\r\n\t\t\t\tFunctionName: context.functionName,\r\n\t\t\t\tInvocationType: 'Event',\r\n\t\t\t\tLogType: 'Tail',\r\n\t\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t\t})\r\n\t\t\t.promise();\r\n\t\t// logger.log('\\tinvocation result', result);\r\n\t}\r\n};\r\n\r\nconst dispatchQuestsV2Lambda = async (context: Context, startDate: Date) => {\r\n\tfor (const mmr of allMmrPercentiles) {\r\n\t\tconst newEvent = {\r\n\t\t\tquestsV2: true,\r\n\t\t\tmmr: mmr,\r\n\t\t\tstartDate: startDate,\r\n\t\t};\r\n\t\tconst params = {\r\n\t\t\tFunctionName: context.functionName,\r\n\t\t\tInvocationType: 'Event',\r\n\t\t\tLogType: 'Tail',\r\n\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t};\r\n\t\tconsole.log('\\tinvoking lambda', params);\r\n\t\tconst result = await lambda\r\n\t\t\t.invoke({\r\n\t\t\t\tFunctionName: context.functionName,\r\n\t\t\t\tInvocationType: 'Event',\r\n\t\t\t\tLogType: 'Tail',\r\n\t\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t\t})\r\n\t\t\t.promise();\r\n\t\t// logger.log('\\tinvocation result', result);\r\n\t}\r\n};\r\n\r\nconst dispatchStatsV2Lambda = async (context: Context, startDate: Date) => {\r\n\tfor (const mmr of allMmrPercentiles) {\r\n\t\tconst newEvent = {\r\n\t\t\tstatsV2: true,\r\n\t\t\tmmr: mmr,\r\n\t\t\tstartDate: startDate,\r\n\t\t};\r\n\t\tconst params = {\r\n\t\t\tFunctionName: context.functionName,\r\n\t\t\tInvocationType: 'Event',\r\n\t\t\tLogType: 'Tail',\r\n\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t};\r\n\t\tconsole.log('\\tinvoking lambda', params);\r\n\t\tconst result = await lambda\r\n\t\t\t.invoke({\r\n\t\t\t\tFunctionName: context.functionName,\r\n\t\t\t\tInvocationType: 'Event',\r\n\t\t\t\tLogType: 'Tail',\r\n\t\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t\t})\r\n\t\t\t.promise();\r\n\t\t// logger.log('\\tinvocation result', result);\r\n\t}\r\n};\r\n\r\nconst dispatchCatchUpEvents = async (context: Context, daysInThePast: number) => {\r\n\t// Build a list of hours for the last `daysInThePast` days, in the format YYYY-MM-ddTHH:mm:ss.sssZ\r\n\tconst now = new Date();\r\n\tconst hours = [];\r\n\tfor (let i = 0; i < 24 * daysInThePast; i++) {\r\n\t\tconst baseDate = new Date(now);\r\n\t\tbaseDate.setMinutes(0);\r\n\t\tbaseDate.setSeconds(0);\r\n\t\tbaseDate.setMilliseconds(0);\r\n\t\tconst hour = new Date(baseDate.getTime() - i * 60 * 60 * 1000);\r\n\t\thours.push(hour.toISOString());\r\n\t}\r\n\r\n\tfor (const targetDate of hours) {\r\n\t\tconsole.log('dispatching catch-up for date', targetDate);\r\n\t\tconst newEvent = {\r\n\t\t\ttargetDate: targetDate,\r\n\t\t};\r\n\t\tconst params = {\r\n\t\t\tFunctionName: context.functionName,\r\n\t\t\tInvocationType: 'Event',\r\n\t\t\tLogType: 'Tail',\r\n\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t};\r\n\t\t// console.log('\\tinvoking lambda', params);\r\n\t\tconst result = await lambda\r\n\t\t\t.invoke({\r\n\t\t\t\tFunctionName: context.functionName,\r\n\t\t\t\tInvocationType: 'Event',\r\n\t\t\t\tLogType: 'Tail',\r\n\t\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t\t})\r\n\t\t\t.promise();\r\n\t\t// console.log('\\tinvocation result', result);\r\n\t\tawait sleep(50);\r\n\t}\r\n};\r\n"]}
|
|
1
|
+
{"version":3,"file":"_build-battlegrounds-hero-stats.js","sourceRoot":"","sources":["../../../src/duos/hourly/_build-battlegrounds-hero-stats.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-use-before-define */\r\nimport { InvokeCommand, LambdaClient } from '@aws-sdk/client-lambda';\r\nimport { S3, logBeforeTimeout, sleep } from '@firestone-hs/aws-lambda-utils';\r\nimport { AllCardsService } from '@firestone-hs/reference-data';\r\nimport { Context } from 'aws-lambda';\r\nimport { InternalBgsRow } from '../../internal-model';\r\nimport { buildTrinketStats } from '../../solo/hourly/trinkets/trinket-stats';\r\nimport { buildHeroStats } from './hero-stats';\r\nimport { readRowsFromS3, saveRowsOnS3 } from './rows';\r\nimport { buildQuestStats } from '../../solo/hourly/quest-stats';\r\n\r\nexport const s3 = new S3();\r\nconst allCards = new AllCardsService();\r\nconst lambda = new LambdaClient({\r\n\tregion: process.env.AWS_REGION || 'us-west-2',\r\n});\r\n\r\nconst allMmrPercentiles: (100 | 50 | 25 | 10 | 1)[] = [100, 50, 25, 10, 1];\r\n\r\nexport const STATS_BUCKET = 'static.zerotoheroes.com';\r\nexport const STATS_KEY_PREFIX = `api/bgs/duo`;\r\nexport const WORKING_ROWS_FILE = `${STATS_KEY_PREFIX}/working/working-rows-%time%.json`;\r\nexport const HOURLY_KEY_HERO = `${STATS_KEY_PREFIX}/hero-stats/%anomaly%mmr-%mmrPercentile%/hourly/%startDate%.gz.json`;\r\nexport const HOURLY_KEY_QUEST = `${STATS_KEY_PREFIX}/quest-stats/mmr-%mmrPercentile%/hourly/%startDate%.gz.json`;\r\nexport const HOURLY_KEY_TRINKET = `${STATS_KEY_PREFIX}/trinket-stats/mmr-%mmrPercentile%/hourly/%startDate%.gz.json`;\r\n\r\nexport default async (event, context: Context): Promise<any> => {\r\n\tawait handleNewStats(event, context);\r\n};\r\n\r\nexport const handleNewStats = async (event, context: Context) => {\r\n\tconst cleanup = logBeforeTimeout(context);\r\n\t// logger.log('event', event);\r\n\tawait allCards.initializeCardsDb();\r\n\r\n\tif (event.catchUp) {\r\n\t\tawait dispatchCatchUpEvents(context, +event.catchUp);\r\n\t\tcleanup();\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (!event.statsV2 && !event.questsV2 && !event.trinkets) {\r\n\t\tawait dispatchMainEvents(context, event);\r\n\t\tcleanup();\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (event.questsV2) {\r\n\t\tconst lastHourRows: readonly InternalBgsRow[] = await readRowsFromS3(event.startDate);\r\n\t\t// logger.log('building quest stats', event.timePeriod, event.startDate, lastHourRows?.length);\r\n\t\tawait buildQuestStats(event.startDate, event.mmr, lastHourRows, allCards, s3);\r\n\t} else if (event.statsV2) {\r\n\t\tconst lastHourRows: readonly InternalBgsRow[] = await readRowsFromS3(event.startDate);\r\n\t\tconst uniqueAnomalies = [null];\r\n\t\t// [\r\n\t\t// \tnull,\r\n\t\t// \t...lastHourRows\r\n\t\t// \t\t.flatMap((r) => r.bgsAnomalies?.split(','))\r\n\t\t// \t\t.filter((a) => a)\r\n\t\t// \t\t.filter((value, index, self) => self.indexOf(value) === index),\r\n\t\t// ];\r\n\t\tfor (const anomaly of uniqueAnomalies) {\r\n\t\t\tconsole.log('building hero stats', event.startDate, event.mmr, lastHourRows?.length, anomaly);\r\n\t\t\tawait buildHeroStats(event.startDate, event.mmr, anomaly, lastHourRows, allCards);\r\n\t\t}\r\n\t} else if (event.trinkets) {\r\n\t\tconst lastHourRows: readonly InternalBgsRow[] = await readRowsFromS3(event.startDate);\r\n\t\t// logger.log('building hero stats', event.startDate, lastHourRows?.length);\r\n\t\tawait buildTrinketStats(\r\n\t\t\tevent.startDate,\r\n\t\t\tevent.mmr,\r\n\t\t\tlastHourRows,\r\n\t\t\tallCards,\r\n\t\t\tSTATS_BUCKET,\r\n\t\t\tHOURLY_KEY_TRINKET,\r\n\t\t\ts3,\r\n\t\t);\r\n\t}\r\n\r\n\tcleanup();\r\n};\r\n\r\nconst dispatchMainEvents = async (context: Context, event) => {\r\n\tconst startDate = buildProcessStartDate(event);\r\n\t// End one hour later\r\n\tconst endDate = new Date(startDate);\r\n\tendDate.setHours(endDate.getHours() + 1);\r\n\r\n\tawait saveRowsOnS3(startDate, endDate, allCards);\r\n\r\n\tawait dispatchStatsV2Lambda(context, startDate);\r\n\t// await dispatchQuestsV2Lambda(context, startDate);\r\n\tawait dispatchTrinketsLambda(context, startDate);\r\n};\r\n\r\nconst buildProcessStartDate = (event): Date => {\r\n\tif (event?.targetDate) {\r\n\t\tconst targetDate = new Date(event.targetDate);\r\n\t\treturn targetDate;\r\n\t}\r\n\r\n\t// Start from the start of the current hour\r\n\tconst processStartDate = new Date();\r\n\tprocessStartDate.setMinutes(0);\r\n\tprocessStartDate.setSeconds(0);\r\n\tprocessStartDate.setMilliseconds(0);\r\n\tprocessStartDate.setHours(processStartDate.getHours() - 1);\r\n\treturn processStartDate;\r\n};\r\n\r\nconst dispatchTrinketsLambda = async (context: Context, startDate: Date) => {\r\n\tfor (const mmr of allMmrPercentiles) {\r\n\t\tconst newEvent = {\r\n\t\t\ttrinkets: true,\r\n\t\t\tmmr: mmr,\r\n\t\t\tstartDate: startDate,\r\n\t\t};\r\n\t\tconst params = {\r\n\t\t\tFunctionName: context.functionName,\r\n\t\t\tInvocationType: 'Event',\r\n\t\t\tLogType: 'Tail',\r\n\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t};\r\n\t\tconsole.log('\\tinvoking lambda', params);\r\n\t\tconst result = await lambda.send(\r\n\t\t\tnew InvokeCommand({\r\n\t\t\t\tFunctionName: context.functionName,\r\n\t\t\t\tInvocationType: 'Event',\r\n\t\t\t\tLogType: 'Tail',\r\n\t\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t\t}),\r\n\t\t);\r\n\t\t// logger.log('\\tinvocation result', result);\r\n\t}\r\n};\r\n\r\nconst dispatchQuestsV2Lambda = async (context: Context, startDate: Date) => {\r\n\tfor (const mmr of allMmrPercentiles) {\r\n\t\tconst newEvent = {\r\n\t\t\tquestsV2: true,\r\n\t\t\tmmr: mmr,\r\n\t\t\tstartDate: startDate,\r\n\t\t};\r\n\t\tconst params = {\r\n\t\t\tFunctionName: context.functionName,\r\n\t\t\tInvocationType: 'Event',\r\n\t\t\tLogType: 'Tail',\r\n\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t};\r\n\t\tconsole.log('\\tinvoking lambda', params);\r\n\t\tconst result = await lambda.send(\r\n\t\t\tnew InvokeCommand({\r\n\t\t\t\tFunctionName: context.functionName,\r\n\t\t\t\tInvocationType: 'Event',\r\n\t\t\t\tLogType: 'Tail',\r\n\t\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t\t}),\r\n\t\t);\r\n\t\t// logger.log('\\tinvocation result', result);\r\n\t}\r\n};\r\n\r\nconst dispatchStatsV2Lambda = async (context: Context, startDate: Date) => {\r\n\tfor (const mmr of allMmrPercentiles) {\r\n\t\tconst newEvent = {\r\n\t\t\tstatsV2: true,\r\n\t\t\tmmr: mmr,\r\n\t\t\tstartDate: startDate,\r\n\t\t};\r\n\t\tconst params = {\r\n\t\t\tFunctionName: context.functionName,\r\n\t\t\tInvocationType: 'Event',\r\n\t\t\tLogType: 'Tail',\r\n\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t};\r\n\t\tconsole.log('\\tinvoking lambda', params);\r\n\t\tconst result = await lambda.send(\r\n\t\t\tnew InvokeCommand({\r\n\t\t\t\tFunctionName: context.functionName,\r\n\t\t\t\tInvocationType: 'Event',\r\n\t\t\t\tLogType: 'Tail',\r\n\t\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t\t}),\r\n\t\t);\r\n\t\t// logger.log('\\tinvocation result', result);\r\n\t}\r\n};\r\n\r\nconst dispatchCatchUpEvents = async (context: Context, daysInThePast: number) => {\r\n\t// Build a list of hours for the last `daysInThePast` days, in the format YYYY-MM-ddTHH:mm:ss.sssZ\r\n\tconst now = new Date();\r\n\tconst hours = [];\r\n\tfor (let i = 0; i < 24 * daysInThePast; i++) {\r\n\t\tconst baseDate = new Date(now);\r\n\t\tbaseDate.setMinutes(0);\r\n\t\tbaseDate.setSeconds(0);\r\n\t\tbaseDate.setMilliseconds(0);\r\n\t\tconst hour = new Date(baseDate.getTime() - i * 60 * 60 * 1000);\r\n\t\thours.push(hour.toISOString());\r\n\t}\r\n\r\n\tfor (const targetDate of hours) {\r\n\t\tconsole.log('dispatching catch-up for date', targetDate);\r\n\t\tconst newEvent = {\r\n\t\t\ttargetDate: targetDate,\r\n\t\t};\r\n\t\tconst params = {\r\n\t\t\tFunctionName: context.functionName,\r\n\t\t\tInvocationType: 'Event',\r\n\t\t\tLogType: 'Tail',\r\n\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t};\r\n\t\t// console.log('\\tinvoking lambda', params);\r\n\t\tconst result = await lambda.send(\r\n\t\t\tnew InvokeCommand({\r\n\t\t\t\tFunctionName: context.functionName,\r\n\t\t\t\tInvocationType: 'Event',\r\n\t\t\t\tLogType: 'Tail',\r\n\t\t\t\tPayload: JSON.stringify(newEvent),\r\n\t\t\t}),\r\n\t\t);\r\n\t\t// console.log('\\tinvocation result', result);\r\n\t\tawait sleep(50);\r\n\t}\r\n};\r\n"]}
|
|
@@ -6,7 +6,7 @@ const util_functions_1 = require("../../common/util-functions");
|
|
|
6
6
|
const builders_1 = require("./builders");
|
|
7
7
|
const utils_1 = require("./utils");
|
|
8
8
|
const buildHeroStatsForMmr = (rows, allCards) => {
|
|
9
|
-
const groupedByHero = (0, aws_lambda_utils_1.groupByFunction)((row) => row.heroCardId)
|
|
9
|
+
const groupedByHero = (0, aws_lambda_utils_1.groupByFunction)(rows, (row) => row.heroCardId);
|
|
10
10
|
return Object.values(groupedByHero).flatMap((data) => buildStatsForSingleHero(data, rows));
|
|
11
11
|
};
|
|
12
12
|
exports.buildHeroStatsForMmr = buildHeroStatsForMmr;
|
|
@@ -36,7 +36,7 @@ const buildStatsForSingleHero = (rowsForHero, allRows) => {
|
|
|
36
36
|
standardDeviation: (0, util_functions_1.round)(standardDeviation),
|
|
37
37
|
standardDeviationOfTheMean: (0, util_functions_1.round)(standardDeviationOfTheMean),
|
|
38
38
|
conservativePositionEstimate: (0, util_functions_1.round)(averagePosition + 3 * standardDeviationOfTheMean),
|
|
39
|
-
|
|
39
|
+
placementDistribution: placementDistribution,
|
|
40
40
|
combatWinrateRaw: rawCombatWinrates,
|
|
41
41
|
warbandStatsRaw: rawWarbandStats,
|
|
42
42
|
tribeStats: tribeStats,
|