@firestone-hs/bgs-global-stats 1.0.31 → 1.0.33
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/build-battlegrounds-hero-stats-new.d.ts +6 -0
- package/dist/build-battlegrounds-hero-stats-new.js +2 -2
- package/dist/build-battlegrounds-hero-stats-new.js.map +1 -1
- package/dist/common.d.ts +4 -0
- package/dist/common.js +9 -0
- package/dist/common.js.map +1 -1
- package/dist/stats-v2/bgs-hero-stat.d.ts +24 -0
- package/dist/stats-v2/bgs-hero-stat.js.map +1 -1
- package/dist/stats-v2/stats-buikder.js +53 -9
- package/dist/stats-v2/stats-buikder.js.map +1 -1
- package/dist/stats-v2/stats-v2.js +2 -2
- package/dist/stats-v2/stats-v2.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { S3 } from '@firestone-hs/aws-lambda-utils';
|
|
2
2
|
import { Context } from 'aws-lambda';
|
|
3
|
+
import { InternalBgsRow } from './internal-model';
|
|
3
4
|
export declare const s3: S3;
|
|
4
5
|
declare const _default: (event: any, context: Context) => Promise<any>;
|
|
5
6
|
export default _default;
|
|
@@ -7,3 +8,8 @@ export declare const handleNewStats: (event: any, context: Context) => Promise<{
|
|
|
7
8
|
statusCode: number;
|
|
8
9
|
body: any;
|
|
9
10
|
}>;
|
|
11
|
+
export declare const buildCombatWinrate: (rows: readonly InternalBgsRow[]) => readonly {
|
|
12
|
+
turn: number;
|
|
13
|
+
dataPoints: number;
|
|
14
|
+
totalWinrate: number;
|
|
15
|
+
}[];
|
|
@@ -276,7 +276,7 @@ const buildHeroStats = (rows) => {
|
|
|
276
276
|
const result = Object.values(grouped).map(groupedRows => {
|
|
277
277
|
const ref = groupedRows[0];
|
|
278
278
|
const placementDistribution = common_1.buildPlacementDistribution(groupedRows);
|
|
279
|
-
const combatWinrate = buildCombatWinrate(groupedRows);
|
|
279
|
+
const combatWinrate = exports.buildCombatWinrate(groupedRows);
|
|
280
280
|
const warbandStats = buildWarbandStats(groupedRows);
|
|
281
281
|
return {
|
|
282
282
|
cardId: util_functions_1.normalizeHeroCardId(ref.heroCardId, allCards),
|
|
@@ -320,7 +320,7 @@ const buildWarbandStats = (rows) => {
|
|
|
320
320
|
}));
|
|
321
321
|
return result;
|
|
322
322
|
};
|
|
323
|
-
|
|
323
|
+
exports.buildCombatWinrate = (rows) => {
|
|
324
324
|
var _a, _b, _c;
|
|
325
325
|
const ref = rows[0];
|
|
326
326
|
const debug = ref.heroCardId === 'BG21_HERO_000';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-battlegrounds-hero-stats-new.js","sourceRoot":"/","sources":["build-battlegrounds-hero-stats-new.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-use-before-define */\r\nimport { getConnection, groupByFunction, http, logBeforeTimeout, logger, S3 } from '@firestone-hs/aws-lambda-utils';\r\nimport { AllCardsService, CardIds, Race } from '@firestone-hs/reference-data';\r\nimport { Context } from 'aws-lambda';\r\nimport AWS from 'aws-sdk';\r\nimport { ServerlessMysql } from 'serverless-mysql';\r\nimport { Readable } from 'stream';\r\nimport { gzipSync } from 'zlib';\r\nimport { BgsGlobalHeroStat2, BgsGlobalStats2, MmrPercentile } from './bgs-global-stats';\r\nimport { buildMmrPercentiles, buildPlacementDistribution, filterRowsForTimePeriod, PatchInfo } from './common';\r\nimport { InternalBgsRow } from './internal-model';\r\nimport { handleQuests } from './quests';\r\nimport { handleQuestsV2 } from './quests-v2/quests-v2';\r\nimport { handleStatsV2 } from './stats-v2/stats-v2';\r\nimport { formatDate, normalizeHeroCardId } from './utils/util-functions';\r\n\r\nexport const s3 = new S3();\r\nconst allCards = new AllCardsService();\r\nconst lambda = new AWS.Lambda();\r\n\r\nconst allTimePeriods: ('all-time' | 'past-three' | 'past-seven' | 'last-patch')[] = [\r\n\t'all-time',\r\n\t'past-three',\r\n\t'past-seven',\r\n\t'last-patch',\r\n];\r\n\r\n// This example demonstrates a NodeJS 8.10 async handler[1], however of course you could use\r\n// the more traditional callback-style handler.\r\n// [1]: https://aws.amazon.com/blogs/compute/node-js-8-10-runtime-now-available-in-aws-lambda/\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\tlogger.log('event', event);\r\n\tawait allCards.initializeCardsDb();\r\n\tconst lastPatch = await getLastBattlegroundsPatch();\r\n\r\n\tif (event.quests) {\r\n\t\tconst rows: readonly InternalBgsRow[] = await readRowsFromS3();\r\n\t\tlogger.log('read rows', rows?.length);\r\n\t\tfor (const timePeriod of allTimePeriods) {\r\n\t\t\tawait handleQuests(timePeriod, rows, lastPatch);\r\n\t\t}\r\n\t} else if (event.questsV2) {\r\n\t\tconst rows: readonly InternalBgsRow[] = await readRowsFromS3();\r\n\t\tlogger.log('read rows', rows?.length);\r\n\t\tfor (const timePeriod of allTimePeriods) {\r\n\t\t\tawait handleQuestsV2(timePeriod, rows, lastPatch);\r\n\t\t}\r\n\t} else if (event.statsV2) {\r\n\t\tconst rows: readonly InternalBgsRow[] = await readRowsFromS3();\r\n\t\tlogger.log('read rows', rows?.length);\r\n\t\tfor (const timePeriod of allTimePeriods) {\r\n\t\t\tawait handleStatsV2(timePeriod, rows, lastPatch, allCards);\r\n\t\t}\r\n\t} else if (event.permutation) {\r\n\t\tconst rows: readonly InternalBgsRow[] = await readRowsFromS3();\r\n\t\tlogger.log('read rows', rows?.length);\r\n\t\tfor (const timePeriod of allTimePeriods) {\r\n\t\t\tawait handlePermutation(event.permutation, timePeriod, event.allTribes, rows, lastPatch);\r\n\t\t}\r\n\t} else {\r\n\t\tconst mysql = await getConnection();\r\n\t\tconst rows: readonly InternalBgsRow[] = await loadRows(mysql);\r\n\t\tawait mysql.end();\r\n\t\tawait saveRowsOnS3(rows);\r\n\t\tawait dispatchNewLambdas(rows, context);\r\n\t\tawait dispatchQuestsLambda(rows, context);\r\n\t\tawait dispatchQuestsV2Lambda(rows, context);\r\n\t\tawait dispatchStatsV2Lambda(rows, context);\r\n\t}\r\n\r\n\tcleanup();\r\n\treturn { statusCode: 200, body: null };\r\n};\r\n\r\nconst dispatchQuestsLambda = async (rows: readonly InternalBgsRow[], context: Context) => {\r\n\tconst newEvent = {\r\n\t\tquests: true,\r\n\t};\r\n\tconst params = {\r\n\t\tFunctionName: context.functionName,\r\n\t\tInvocationType: 'Event',\r\n\t\tLogType: 'Tail',\r\n\t\tPayload: JSON.stringify(newEvent),\r\n\t};\r\n\tlogger.log('\\tinvoking lambda', params);\r\n\tconst result = await lambda\r\n\t\t.invoke({\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.promise();\r\n\tlogger.log('\\tinvocation result', result);\r\n};\r\n\r\nconst dispatchQuestsV2Lambda = async (rows: readonly InternalBgsRow[], context: Context) => {\r\n\tconst newEvent = {\r\n\t\tquestsV2: true,\r\n\t};\r\n\tconst params = {\r\n\t\tFunctionName: context.functionName,\r\n\t\tInvocationType: 'Event',\r\n\t\tLogType: 'Tail',\r\n\t\tPayload: JSON.stringify(newEvent),\r\n\t};\r\n\tlogger.log('\\tinvoking lambda', params);\r\n\tconst result = await lambda\r\n\t\t.invoke({\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.promise();\r\n\tlogger.log('\\tinvocation result', result);\r\n};\r\n\r\nconst dispatchStatsV2Lambda = async (rows: readonly InternalBgsRow[], context: Context) => {\r\n\tconst newEvent = {\r\n\t\tstatsV2: true,\r\n\t};\r\n\tconst params = {\r\n\t\tFunctionName: context.functionName,\r\n\t\tInvocationType: 'Event',\r\n\t\tLogType: 'Tail',\r\n\t\tPayload: JSON.stringify(newEvent),\r\n\t};\r\n\tlogger.log('\\tinvoking lambda', params);\r\n\tconst result = await lambda\r\n\t\t.invoke({\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.promise();\r\n\tlogger.log('\\tinvocation result', result);\r\n};\r\n\r\nconst dispatchNewLambdas = async (rows: readonly InternalBgsRow[], context: Context) => {\r\n\tconst allTribes = extractAllTribes(rows);\r\n\tlogger.log('all tribes', allTribes);\r\n\tconst tribePermutations: ('all' | Race[])[] = ['all', ...combine(allTribes, 5)];\r\n\tlogger.log('tribe permutations, should be 127 (126 + 1), because 9 tribes', tribePermutations.length);\r\n\tfor (const tribes of tribePermutations) {\r\n\t\tlogger.log('handling tribes', tribes, tribes !== 'all' && tribes.join('-'));\r\n\t\t// if (tribes !== 'all') {\r\n\t\t// \tcontinue;\r\n\t\t// }\r\n\t\tconst newEvent = {\r\n\t\t\tpermutation: tribes,\r\n\t\t\tallTribes: allTribes,\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\tlogger.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\tlogger.log('\\tinvocation result', result);\r\n\t}\r\n};\r\n\r\nconst handlePermutation = async (\r\n\ttribes: 'all' | readonly Race[],\r\n\ttimePeriod: 'all-time' | 'past-three' | 'past-seven' | 'last-patch',\r\n\tallTribes: readonly Race[],\r\n\trows: readonly InternalBgsRow[],\r\n\tlastPatch: PatchInfo,\r\n) => {\r\n\tconsole.log('total rows', rows.length);\r\n\tconst rowsForTimePeriod = filterRowsForTimePeriod(rows, timePeriod, lastPatch);\r\n\tconsole.log('rows for time period', rowsForTimePeriod.length);\r\n\tconst tribesStr = tribes === 'all' ? null : tribes.join(',');\r\n\tconst rowsWithTribes = !!tribesStr\r\n\t\t? rowsForTimePeriod.filter(row => !!row.tribes).filter(row => row.tribes === tribesStr)\r\n\t\t: rowsForTimePeriod;\r\n\tconsole.log('rowsWithTribes', rowsWithTribes.length);\r\n\tconst mmrPercentiles: readonly MmrPercentile[] = buildMmrPercentiles(rowsWithTribes);\r\n\tlogger.log('handling permutation', tribes, timePeriod, rows?.length, rowsWithTribes?.length);\r\n\tconst stats: readonly BgsGlobalHeroStat2[] = buildHeroes(rowsWithTribes, mmrPercentiles).map(stat => ({\r\n\t\t...stat,\r\n\t\ttribes: tribes === 'all' ? allTribes : tribes,\r\n\t\tdate: timePeriod,\r\n\t}));\r\n\tconst statsForTribes: BgsGlobalStats2 = {\r\n\t\tlastUpdateDate: formatDate(new Date()),\r\n\t\tmmrPercentiles: mmrPercentiles,\r\n\t\theroStats: stats,\r\n\t\tallTribes: allTribes,\r\n\t\ttotalMatches: stats.map(s => s.totalMatches).reduce((a, b) => a + b, 0),\r\n\t};\r\n\tlogger.log('\\tbuilt stats', statsForTribes.totalMatches, statsForTribes.heroStats?.length);\r\n\tconst tribesSuffix = tribes === 'all' ? 'all-tribes' : tribes.join('-');\r\n\tconst timeSuffix = timePeriod;\r\n\tawait s3.writeFile(\r\n\t\tgzipSync(JSON.stringify(statsForTribes)),\r\n\t\t'static.zerotoheroes.com',\r\n\t\t`api/bgs/heroes/bgs-global-stats-${tribesSuffix}-${timeSuffix}.gz.json`,\r\n\t\t'application/json',\r\n\t\t'gzip',\r\n\t);\r\n};\r\n\r\nconst saveRowsOnS3 = async (rows: readonly InternalBgsRow[]) => {\r\n\tlogger.log('saving rows on s3', rows.length);\r\n\tawait s3.writeArrayAsMultipart(rows, 'static.zerotoheroes.com', `api/bgs/working-rows.json`, 'application/json');\r\n\tlogger.log('file saved');\r\n};\r\n\r\nconst readRowsFromS3 = async (): Promise<readonly InternalBgsRow[]> => {\r\n\treturn new Promise<readonly InternalBgsRow[]>((resolve, reject) => {\r\n\t\tlet parseErrors = 0;\r\n\t\tlet totalParsed = 0;\r\n\t\tconst stream: Readable = s3.readStream('static.zerotoheroes.com', `api/bgs/working-rows.json`);\r\n\t\tconst result: InternalBgsRow[] = [];\r\n\t\tlet previousString = '';\r\n\t\tstream\r\n\t\t\t.on('data', chunk => {\r\n\t\t\t\tconst str = Buffer.from(chunk).toString('utf-8');\r\n\t\t\t\tconst newStr = previousString + str;\r\n\t\t\t\tconst split = newStr.split('\\n');\r\n\t\t\t\tconst rows: readonly InternalBgsRow[] = split.slice(0, split.length - 1).map(row => {\r\n\t\t\t\t\ttry {\r\n\t\t\t\t\t\tconst result = JSON.parse(row);\r\n\t\t\t\t\t\ttotalParsed++;\r\n\t\t\t\t\t\treturn result;\r\n\t\t\t\t\t} catch (e) {\r\n\t\t\t\t\t\t// logger.warn('could not parse row', row);\r\n\t\t\t\t\t\tparseErrors++;\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\t\t\t\tpreviousString = split[split.length - 1];\r\n\t\t\t\t// logger.log('parsing errors', parseErrors, 'and successes', totalParsed);\r\n\t\t\t\tresult.push(...rows);\r\n\t\t\t})\r\n\t\t\t.on('end', () => {\r\n\t\t\t\tconst finalResult = result.filter(row => !!row);\r\n\t\t\t\tlogger.log('stream end', result.length, finalResult.length);\r\n\t\t\t\tlogger.log('parsing errors', parseErrors, 'and successes', totalParsed);\r\n\t\t\t\tresolve(finalResult);\r\n\t\t\t});\r\n\t});\r\n};\r\n\r\n// https://stackoverflow.com/a/47204248/548701\r\nconst combine = <T>(input: readonly T[], chooseN: number): T[][] => {\r\n\tconst finalResult: T[][] = [];\r\n\r\n\tconst intermediateResult = [];\r\n\tintermediateResult.length = chooseN;\r\n\tconst combineInternal = <T>(input: readonly T[], chooseN: number, start = 0): void => {\r\n\t\tif (chooseN === 0) {\r\n\t\t\tfinalResult.push([...intermediateResult].sort());\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tfor (let i = start; i <= input.length - chooseN; i++) {\r\n\t\t\tintermediateResult[intermediateResult.length - chooseN] = input[i];\r\n\t\t\tcombineInternal(input, chooseN - 1, i + 1);\r\n\t\t}\r\n\t};\r\n\tcombineInternal(input, chooseN, 0);\r\n\r\n\treturn finalResult;\r\n};\r\n\r\nconst extractAllTribes = (rows: readonly InternalBgsRow[]): readonly Race[] => {\r\n\treturn [\r\n\t\t...new Set(\r\n\t\t\trows\r\n\t\t\t\t.map(row => row.tribes)\r\n\t\t\t\t.filter(tribes => !!tribes?.length)\r\n\t\t\t\t.map(tribes => tribes.split(',').map(strTribe => parseInt(strTribe) as Race))\r\n\t\t\t\t.reduce((a, b) => [...new Set(a.concat(b))], []),\r\n\t\t),\r\n\t];\r\n};\r\n\r\nconst buildHeroes = (\r\n\trows: readonly InternalBgsRow[],\r\n\tmmrPercentiles: readonly MmrPercentile[],\r\n): readonly BgsGlobalHeroStat2[] => {\r\n\tconst mappedByMmr = mmrPercentiles.map(\r\n\t\tmmrPercentile =>\r\n\t\t\t[\r\n\t\t\t\tmmrPercentile,\r\n\t\t\t\t// So that we also include rows where data collection failed\r\n\t\t\t\trows.filter(row => mmrPercentile.percentile === 100 || row.rating >= mmrPercentile.mmr),\r\n\t\t\t] as [MmrPercentile, readonly InternalBgsRow[]],\r\n\t);\r\n\t// logger.log('mappedByMmr');\r\n\treturn mappedByMmr\r\n\t\t.map(([mmr, rows]) => {\r\n\t\t\tlogger.log('building heroes for mmr', mmr.percentile, rows.length);\r\n\t\t\treturn buildHeroStats(rows).map(stat => ({\r\n\t\t\t\t...stat,\r\n\t\t\t\tmmrPercentile: mmr.percentile,\r\n\t\t\t}));\r\n\t\t})\r\n\t\t.reduce((a, b) => [...a, ...b], []);\r\n};\r\n\r\nconst buildHeroStats = (rows: readonly InternalBgsRow[]): readonly BgsGlobalHeroStat2[] => {\r\n\tconst grouped: { [groupingKey: string]: readonly InternalBgsRow[] } = groupByFunction(\r\n\t\t// (row: InternalBgsRow) => `${row.heroCardId}-${row.darkmoonPrizes}`,\r\n\t\t(row: InternalBgsRow) => normalizeHeroCardId(row.heroCardId, allCards),\r\n\t)(rows);\r\n\t// logger.log('grouped', Object.keys(grouped).length);\r\n\r\n\tconst result = Object.values(grouped).map(groupedRows => {\r\n\t\tconst ref = groupedRows[0];\r\n\t\tconst placementDistribution = buildPlacementDistribution(groupedRows);\r\n\t\tconst combatWinrate = buildCombatWinrate(groupedRows);\r\n\t\tconst warbandStats = buildWarbandStats(groupedRows);\r\n\t\treturn {\r\n\t\t\tcardId: normalizeHeroCardId(ref.heroCardId, allCards),\r\n\t\t\ttotalMatches: groupedRows.length,\r\n\t\t\tplacementDistribution: placementDistribution,\r\n\t\t\tcombatWinrate: combatWinrate,\r\n\t\t\twarbandStats: warbandStats,\r\n\t\t} as BgsGlobalHeroStat2;\r\n\t});\r\n\t// logger.log('built result');\r\n\treturn result;\r\n};\r\n\r\nconst buildWarbandStats = (\r\n\trows: readonly InternalBgsRow[],\r\n): readonly { turn: number; dataPoints: number; totalStats: number }[] => {\r\n\tconst data: { [turn: string]: { dataPoints: number; totalStats: number } } = {};\r\n\t// Before that, there was an issue with disconnects, where the first turn after the\r\n\t// reconnect would be turn 0, leading to an inflation of early turn stats\r\n\tconst validRows = rows.filter(row => row.id > 5348374);\r\n\tfor (const row of validRows) {\r\n\t\tif (!row.warbandStats?.length) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tconst parsed: readonly { turn: number; totalStats: number }[] = JSON.parse(row.warbandStats);\r\n\t\tif (!parsed?.length) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tfor (const turnInfo of parsed) {\r\n\t\t\tif (turnInfo.turn === 0 || turnInfo.totalStats == null || isNaN(turnInfo.totalStats)) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\t// To avoid polluting the stats with big Tarecgosa outliers\r\n\t\t\tif (turnInfo.totalStats > 20000) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tconst existingInfo = data['' + turnInfo.turn] ?? { dataPoints: 0, totalStats: 0 };\r\n\t\t\texistingInfo.dataPoints = existingInfo.dataPoints + 1;\r\n\t\t\texistingInfo.totalStats = existingInfo.totalStats + Math.round(turnInfo.totalStats);\r\n\t\t\tdata['' + turnInfo.turn] = existingInfo;\r\n\t\t}\r\n\t}\r\n\r\n\tconst result: { turn: number; dataPoints: number; totalStats: number }[] = Object.keys(data).map(turn => ({\r\n\t\tturn: +turn,\r\n\t\tdataPoints: data[turn].dataPoints,\r\n\t\ttotalStats: data[turn].totalStats,\r\n\t}));\r\n\treturn result;\r\n};\r\n\r\nconst buildCombatWinrate = (\r\n\trows: readonly InternalBgsRow[],\r\n): readonly { turn: number; dataPoints: number; totalWinrate: number }[] => {\r\n\tconst ref = rows[0];\r\n\tconst debug = ref.heroCardId === 'BG21_HERO_000';\r\n\r\n\tconst data: { [turn: string]: { dataPoints: number; totalWinrate: number } } = {};\r\n\tfor (const row of rows) {\r\n\t\t// logger.debug('building combatWinrate', row);\r\n\t\tif (!row.combatWinrate?.length) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tlet parsed: readonly { turn: number; winrate: number }[] = null;\r\n\t\ttry {\r\n\t\t\tparsed = JSON.parse(row.combatWinrate);\r\n\t\t\t// logger.debug('parsed', parsed);\r\n\t\t\tif (!parsed?.length) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t} catch (e) {\r\n\t\t\tlogger.error('Could not parse combat winrate', row.id, e);\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// if (debug) {\r\n\t\t// \tlogger.log('handling combat winrate', parsed);\r\n\t\t// }\r\n\r\n\t\tfor (const turnInfo of parsed) {\r\n\t\t\tif (turnInfo.turn === 0 || turnInfo.winrate == null) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\t// if (debug) {\r\n\t\t\t// \tlogger.log('\\t turnInfo', turnInfo);\r\n\t\t\t// }\r\n\t\t\tconst existingInfo = data['' + turnInfo.turn] ?? { dataPoints: 0, totalWinrate: 0 };\r\n\t\t\t// if (debug) {\r\n\t\t\t// \tlogger.log('\\t existingInfo', existingInfo);\r\n\t\t\t// }\r\n\t\t\texistingInfo.dataPoints = existingInfo.dataPoints + 1;\r\n\t\t\texistingInfo.totalWinrate = existingInfo.totalWinrate + Math.round(turnInfo.winrate);\r\n\t\t\t// if (debug) {\r\n\t\t\t// \tlogger.log('\\t existingInfo after', existingInfo);\r\n\t\t\t// }\r\n\t\t\tdata['' + turnInfo.turn] = existingInfo;\r\n\t\t\t// if (debug) {\r\n\t\t\t// \tlogger.log('\\t data', data);\r\n\t\t\t// }\r\n\t\t}\r\n\t}\r\n\r\n\t// if (debug) {\r\n\t// \tlogger.log('\\t data', data);\r\n\t// }\r\n\tconst result: { turn: number; dataPoints: number; totalWinrate: number }[] = Object.keys(data).map(turn => ({\r\n\t\tturn: +turn,\r\n\t\tdataPoints: data[turn].dataPoints,\r\n\t\ttotalWinrate: data[turn].totalWinrate,\r\n\t}));\r\n\t// if (debug) {\r\n\t// \tlogger.log('\\t result', result);\r\n\t// }\r\n\treturn result;\r\n};\r\n\r\nconst loadRows = async (mysql: ServerlessMysql): Promise<readonly InternalBgsRow[]> => {\r\n\t// We actually use all the fields\r\n\tconst query = `\r\n\t\tSELECT *\r\n\t\tFROM bgs_run_stats\r\n\t\tWHERE creationDate > DATE_SUB(NOW(), INTERVAL 30 DAY);\r\n\t`;\r\n\tlogger.log('running query', query);\r\n\tconst rows: readonly InternalBgsRow[] = await mysql.query(query);\r\n\tlogger.log('rows', rows?.length, rows[0]);\r\n\treturn rows\r\n\t\t.filter(row => row.heroCardId.startsWith('TB_BaconShop_') || row.heroCardId.startsWith('BG'))\r\n\t\t.filter(\r\n\t\t\trow =>\r\n\t\t\t\trow.heroCardId !== CardIds.ArannaStarseeker_ArannaUnleashedTokenBattlegrounds &&\r\n\t\t\t\trow.heroCardId !== CardIds.QueenAzshara_NagaQueenAzsharaToken,\r\n\t\t)\r\n\t\t.map(row => ({\r\n\t\t\t...row,\r\n\t\t\theroCardId: normalizeHeroCardId(row.heroCardId, allCards),\r\n\t\t}));\r\n};\r\n\r\nconst getLastBattlegroundsPatch = async (): Promise<PatchInfo> => {\r\n\tconst patchInfo = await http(`https://static.zerotoheroes.com/hearthstone/data/patches.json`);\r\n\tconst structuredPatch = JSON.parse(patchInfo);\r\n\tconst patchNumber = structuredPatch.currentBattlegroundsMetaPatch;\r\n\treturn structuredPatch.patches.find(patch => patch.number === patchNumber);\r\n};\r\n"]}
|
|
1
|
+
{"version":3,"file":"build-battlegrounds-hero-stats-new.js","sourceRoot":"/","sources":["build-battlegrounds-hero-stats-new.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-use-before-define */\r\nimport { getConnection, groupByFunction, http, logBeforeTimeout, logger, S3 } from '@firestone-hs/aws-lambda-utils';\r\nimport { AllCardsService, CardIds, Race } from '@firestone-hs/reference-data';\r\nimport { Context } from 'aws-lambda';\r\nimport AWS from 'aws-sdk';\r\nimport { ServerlessMysql } from 'serverless-mysql';\r\nimport { Readable } from 'stream';\r\nimport { gzipSync } from 'zlib';\r\nimport { BgsGlobalHeroStat2, BgsGlobalStats2, MmrPercentile } from './bgs-global-stats';\r\nimport { buildMmrPercentiles, buildPlacementDistribution, filterRowsForTimePeriod, PatchInfo } from './common';\r\nimport { InternalBgsRow } from './internal-model';\r\nimport { handleQuests } from './quests';\r\nimport { handleQuestsV2 } from './quests-v2/quests-v2';\r\nimport { handleStatsV2 } from './stats-v2/stats-v2';\r\nimport { formatDate, normalizeHeroCardId } from './utils/util-functions';\r\n\r\nexport const s3 = new S3();\r\nconst allCards = new AllCardsService();\r\nconst lambda = new AWS.Lambda();\r\n\r\nconst allTimePeriods: ('all-time' | 'past-three' | 'past-seven' | 'last-patch')[] = [\r\n\t'all-time',\r\n\t'past-three',\r\n\t'past-seven',\r\n\t'last-patch',\r\n];\r\n\r\n// This example demonstrates a NodeJS 8.10 async handler[1], however of course you could use\r\n// the more traditional callback-style handler.\r\n// [1]: https://aws.amazon.com/blogs/compute/node-js-8-10-runtime-now-available-in-aws-lambda/\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\tlogger.log('event', event);\r\n\tawait allCards.initializeCardsDb();\r\n\tconst lastPatch = await getLastBattlegroundsPatch();\r\n\r\n\tif (event.quests) {\r\n\t\tconst rows: readonly InternalBgsRow[] = await readRowsFromS3();\r\n\t\tlogger.log('read rows', rows?.length);\r\n\t\tfor (const timePeriod of allTimePeriods) {\r\n\t\t\tawait handleQuests(timePeriod, rows, lastPatch);\r\n\t\t}\r\n\t} else if (event.questsV2) {\r\n\t\tconst rows: readonly InternalBgsRow[] = await readRowsFromS3();\r\n\t\tlogger.log('read rows', rows?.length);\r\n\t\tfor (const timePeriod of allTimePeriods) {\r\n\t\t\tawait handleQuestsV2(timePeriod, rows, lastPatch);\r\n\t\t}\r\n\t} else if (event.statsV2) {\r\n\t\tconst rows: readonly InternalBgsRow[] = await readRowsFromS3();\r\n\t\tlogger.log('read rows', rows?.length);\r\n\t\tfor (const timePeriod of allTimePeriods) {\r\n\t\t\tawait handleStatsV2(timePeriod, rows, lastPatch, allCards);\r\n\t\t}\r\n\t} else if (event.permutation) {\r\n\t\tconst rows: readonly InternalBgsRow[] = await readRowsFromS3();\r\n\t\tlogger.log('read rows', rows?.length);\r\n\t\tfor (const timePeriod of allTimePeriods) {\r\n\t\t\tawait handlePermutation(event.permutation, timePeriod, event.allTribes, rows, lastPatch);\r\n\t\t}\r\n\t} else {\r\n\t\tconst mysql = await getConnection();\r\n\t\tconst rows: readonly InternalBgsRow[] = await loadRows(mysql);\r\n\t\tawait mysql.end();\r\n\t\tawait saveRowsOnS3(rows);\r\n\t\tawait dispatchNewLambdas(rows, context);\r\n\t\tawait dispatchQuestsLambda(rows, context);\r\n\t\tawait dispatchQuestsV2Lambda(rows, context);\r\n\t\tawait dispatchStatsV2Lambda(rows, context);\r\n\t}\r\n\r\n\tcleanup();\r\n\treturn { statusCode: 200, body: null };\r\n};\r\n\r\nconst dispatchQuestsLambda = async (rows: readonly InternalBgsRow[], context: Context) => {\r\n\tconst newEvent = {\r\n\t\tquests: true,\r\n\t};\r\n\tconst params = {\r\n\t\tFunctionName: context.functionName,\r\n\t\tInvocationType: 'Event',\r\n\t\tLogType: 'Tail',\r\n\t\tPayload: JSON.stringify(newEvent),\r\n\t};\r\n\tlogger.log('\\tinvoking lambda', params);\r\n\tconst result = await lambda\r\n\t\t.invoke({\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.promise();\r\n\tlogger.log('\\tinvocation result', result);\r\n};\r\n\r\nconst dispatchQuestsV2Lambda = async (rows: readonly InternalBgsRow[], context: Context) => {\r\n\tconst newEvent = {\r\n\t\tquestsV2: true,\r\n\t};\r\n\tconst params = {\r\n\t\tFunctionName: context.functionName,\r\n\t\tInvocationType: 'Event',\r\n\t\tLogType: 'Tail',\r\n\t\tPayload: JSON.stringify(newEvent),\r\n\t};\r\n\tlogger.log('\\tinvoking lambda', params);\r\n\tconst result = await lambda\r\n\t\t.invoke({\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.promise();\r\n\tlogger.log('\\tinvocation result', result);\r\n};\r\n\r\nconst dispatchStatsV2Lambda = async (rows: readonly InternalBgsRow[], context: Context) => {\r\n\tconst newEvent = {\r\n\t\tstatsV2: true,\r\n\t};\r\n\tconst params = {\r\n\t\tFunctionName: context.functionName,\r\n\t\tInvocationType: 'Event',\r\n\t\tLogType: 'Tail',\r\n\t\tPayload: JSON.stringify(newEvent),\r\n\t};\r\n\tlogger.log('\\tinvoking lambda', params);\r\n\tconst result = await lambda\r\n\t\t.invoke({\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.promise();\r\n\tlogger.log('\\tinvocation result', result);\r\n};\r\n\r\nconst dispatchNewLambdas = async (rows: readonly InternalBgsRow[], context: Context) => {\r\n\tconst allTribes = extractAllTribes(rows);\r\n\tlogger.log('all tribes', allTribes);\r\n\tconst tribePermutations: ('all' | Race[])[] = ['all', ...combine(allTribes, 5)];\r\n\tlogger.log('tribe permutations, should be 127 (126 + 1), because 9 tribes', tribePermutations.length);\r\n\tfor (const tribes of tribePermutations) {\r\n\t\tlogger.log('handling tribes', tribes, tribes !== 'all' && tribes.join('-'));\r\n\t\t// if (tribes !== 'all') {\r\n\t\t// \tcontinue;\r\n\t\t// }\r\n\t\tconst newEvent = {\r\n\t\t\tpermutation: tribes,\r\n\t\t\tallTribes: allTribes,\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\tlogger.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\tlogger.log('\\tinvocation result', result);\r\n\t}\r\n};\r\n\r\nconst handlePermutation = async (\r\n\ttribes: 'all' | readonly Race[],\r\n\ttimePeriod: 'all-time' | 'past-three' | 'past-seven' | 'last-patch',\r\n\tallTribes: readonly Race[],\r\n\trows: readonly InternalBgsRow[],\r\n\tlastPatch: PatchInfo,\r\n) => {\r\n\tconsole.log('total rows', rows.length);\r\n\tconst rowsForTimePeriod = filterRowsForTimePeriod(rows, timePeriod, lastPatch);\r\n\tconsole.log('rows for time period', rowsForTimePeriod.length);\r\n\tconst tribesStr = tribes === 'all' ? null : tribes.join(',');\r\n\tconst rowsWithTribes = !!tribesStr\r\n\t\t? rowsForTimePeriod.filter(row => !!row.tribes).filter(row => row.tribes === tribesStr)\r\n\t\t: rowsForTimePeriod;\r\n\tconsole.log('rowsWithTribes', rowsWithTribes.length);\r\n\tconst mmrPercentiles: readonly MmrPercentile[] = buildMmrPercentiles(rowsWithTribes);\r\n\tlogger.log('handling permutation', tribes, timePeriod, rows?.length, rowsWithTribes?.length);\r\n\tconst stats: readonly BgsGlobalHeroStat2[] = buildHeroes(rowsWithTribes, mmrPercentiles).map(stat => ({\r\n\t\t...stat,\r\n\t\ttribes: tribes === 'all' ? allTribes : tribes,\r\n\t\tdate: timePeriod,\r\n\t}));\r\n\tconst statsForTribes: BgsGlobalStats2 = {\r\n\t\tlastUpdateDate: formatDate(new Date()),\r\n\t\tmmrPercentiles: mmrPercentiles,\r\n\t\theroStats: stats,\r\n\t\tallTribes: allTribes,\r\n\t\ttotalMatches: stats.map(s => s.totalMatches).reduce((a, b) => a + b, 0),\r\n\t};\r\n\tlogger.log('\\tbuilt stats', statsForTribes.totalMatches, statsForTribes.heroStats?.length);\r\n\tconst tribesSuffix = tribes === 'all' ? 'all-tribes' : tribes.join('-');\r\n\tconst timeSuffix = timePeriod;\r\n\tawait s3.writeFile(\r\n\t\tgzipSync(JSON.stringify(statsForTribes)),\r\n\t\t'static.zerotoheroes.com',\r\n\t\t`api/bgs/heroes/bgs-global-stats-${tribesSuffix}-${timeSuffix}.gz.json`,\r\n\t\t'application/json',\r\n\t\t'gzip',\r\n\t);\r\n};\r\n\r\nconst saveRowsOnS3 = async (rows: readonly InternalBgsRow[]) => {\r\n\tlogger.log('saving rows on s3', rows.length);\r\n\tawait s3.writeArrayAsMultipart(rows, 'static.zerotoheroes.com', `api/bgs/working-rows.json`, 'application/json');\r\n\tlogger.log('file saved');\r\n};\r\n\r\nconst readRowsFromS3 = async (): Promise<readonly InternalBgsRow[]> => {\r\n\treturn new Promise<readonly InternalBgsRow[]>((resolve, reject) => {\r\n\t\tlet parseErrors = 0;\r\n\t\tlet totalParsed = 0;\r\n\t\tconst stream: Readable = s3.readStream('static.zerotoheroes.com', `api/bgs/working-rows.json`);\r\n\t\tconst result: InternalBgsRow[] = [];\r\n\t\tlet previousString = '';\r\n\t\tstream\r\n\t\t\t.on('data', chunk => {\r\n\t\t\t\tconst str = Buffer.from(chunk).toString('utf-8');\r\n\t\t\t\tconst newStr = previousString + str;\r\n\t\t\t\tconst split = newStr.split('\\n');\r\n\t\t\t\tconst rows: readonly InternalBgsRow[] = split.slice(0, split.length - 1).map(row => {\r\n\t\t\t\t\ttry {\r\n\t\t\t\t\t\tconst result = JSON.parse(row);\r\n\t\t\t\t\t\ttotalParsed++;\r\n\t\t\t\t\t\treturn result;\r\n\t\t\t\t\t} catch (e) {\r\n\t\t\t\t\t\t// logger.warn('could not parse row', row);\r\n\t\t\t\t\t\tparseErrors++;\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\t\t\t\tpreviousString = split[split.length - 1];\r\n\t\t\t\t// logger.log('parsing errors', parseErrors, 'and successes', totalParsed);\r\n\t\t\t\tresult.push(...rows);\r\n\t\t\t})\r\n\t\t\t.on('end', () => {\r\n\t\t\t\tconst finalResult = result.filter(row => !!row);\r\n\t\t\t\tlogger.log('stream end', result.length, finalResult.length);\r\n\t\t\t\tlogger.log('parsing errors', parseErrors, 'and successes', totalParsed);\r\n\t\t\t\tresolve(finalResult);\r\n\t\t\t});\r\n\t});\r\n};\r\n\r\n// https://stackoverflow.com/a/47204248/548701\r\nconst combine = <T>(input: readonly T[], chooseN: number): T[][] => {\r\n\tconst finalResult: T[][] = [];\r\n\r\n\tconst intermediateResult = [];\r\n\tintermediateResult.length = chooseN;\r\n\tconst combineInternal = <T>(input: readonly T[], chooseN: number, start = 0): void => {\r\n\t\tif (chooseN === 0) {\r\n\t\t\tfinalResult.push([...intermediateResult].sort());\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tfor (let i = start; i <= input.length - chooseN; i++) {\r\n\t\t\tintermediateResult[intermediateResult.length - chooseN] = input[i];\r\n\t\t\tcombineInternal(input, chooseN - 1, i + 1);\r\n\t\t}\r\n\t};\r\n\tcombineInternal(input, chooseN, 0);\r\n\r\n\treturn finalResult;\r\n};\r\n\r\nconst extractAllTribes = (rows: readonly InternalBgsRow[]): readonly Race[] => {\r\n\treturn [\r\n\t\t...new Set(\r\n\t\t\trows\r\n\t\t\t\t.map(row => row.tribes)\r\n\t\t\t\t.filter(tribes => !!tribes?.length)\r\n\t\t\t\t.map(tribes => tribes.split(',').map(strTribe => parseInt(strTribe) as Race))\r\n\t\t\t\t.reduce((a, b) => [...new Set(a.concat(b))], []),\r\n\t\t),\r\n\t];\r\n};\r\n\r\nconst buildHeroes = (\r\n\trows: readonly InternalBgsRow[],\r\n\tmmrPercentiles: readonly MmrPercentile[],\r\n): readonly BgsGlobalHeroStat2[] => {\r\n\tconst mappedByMmr = mmrPercentiles.map(\r\n\t\tmmrPercentile =>\r\n\t\t\t[\r\n\t\t\t\tmmrPercentile,\r\n\t\t\t\t// So that we also include rows where data collection failed\r\n\t\t\t\trows.filter(row => mmrPercentile.percentile === 100 || row.rating >= mmrPercentile.mmr),\r\n\t\t\t] as [MmrPercentile, readonly InternalBgsRow[]],\r\n\t);\r\n\t// logger.log('mappedByMmr');\r\n\treturn mappedByMmr\r\n\t\t.map(([mmr, rows]) => {\r\n\t\t\tlogger.log('building heroes for mmr', mmr.percentile, rows.length);\r\n\t\t\treturn buildHeroStats(rows).map(stat => ({\r\n\t\t\t\t...stat,\r\n\t\t\t\tmmrPercentile: mmr.percentile,\r\n\t\t\t}));\r\n\t\t})\r\n\t\t.reduce((a, b) => [...a, ...b], []);\r\n};\r\n\r\nconst buildHeroStats = (rows: readonly InternalBgsRow[]): readonly BgsGlobalHeroStat2[] => {\r\n\tconst grouped: { [groupingKey: string]: readonly InternalBgsRow[] } = groupByFunction(\r\n\t\t// (row: InternalBgsRow) => `${row.heroCardId}-${row.darkmoonPrizes}`,\r\n\t\t(row: InternalBgsRow) => normalizeHeroCardId(row.heroCardId, allCards),\r\n\t)(rows);\r\n\t// logger.log('grouped', Object.keys(grouped).length);\r\n\r\n\tconst result = Object.values(grouped).map(groupedRows => {\r\n\t\tconst ref = groupedRows[0];\r\n\t\tconst placementDistribution = buildPlacementDistribution(groupedRows);\r\n\t\tconst combatWinrate = buildCombatWinrate(groupedRows);\r\n\t\tconst warbandStats = buildWarbandStats(groupedRows);\r\n\t\treturn {\r\n\t\t\tcardId: normalizeHeroCardId(ref.heroCardId, allCards),\r\n\t\t\ttotalMatches: groupedRows.length,\r\n\t\t\tplacementDistribution: placementDistribution,\r\n\t\t\tcombatWinrate: combatWinrate,\r\n\t\t\twarbandStats: warbandStats,\r\n\t\t} as BgsGlobalHeroStat2;\r\n\t});\r\n\t// logger.log('built result');\r\n\treturn result;\r\n};\r\n\r\nconst buildWarbandStats = (\r\n\trows: readonly InternalBgsRow[],\r\n): readonly { turn: number; dataPoints: number; totalStats: number }[] => {\r\n\tconst data: { [turn: string]: { dataPoints: number; totalStats: number } } = {};\r\n\t// Before that, there was an issue with disconnects, where the first turn after the\r\n\t// reconnect would be turn 0, leading to an inflation of early turn stats\r\n\tconst validRows = rows.filter(row => row.id > 5348374);\r\n\tfor (const row of validRows) {\r\n\t\tif (!row.warbandStats?.length) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tconst parsed: readonly { turn: number; totalStats: number }[] = JSON.parse(row.warbandStats);\r\n\t\tif (!parsed?.length) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tfor (const turnInfo of parsed) {\r\n\t\t\tif (turnInfo.turn === 0 || turnInfo.totalStats == null || isNaN(turnInfo.totalStats)) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\t// To avoid polluting the stats with big Tarecgosa outliers\r\n\t\t\tif (turnInfo.totalStats > 20000) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tconst existingInfo = data['' + turnInfo.turn] ?? { dataPoints: 0, totalStats: 0 };\r\n\t\t\texistingInfo.dataPoints = existingInfo.dataPoints + 1;\r\n\t\t\texistingInfo.totalStats = existingInfo.totalStats + Math.round(turnInfo.totalStats);\r\n\t\t\tdata['' + turnInfo.turn] = existingInfo;\r\n\t\t}\r\n\t}\r\n\r\n\tconst result: { turn: number; dataPoints: number; totalStats: number }[] = Object.keys(data).map(turn => ({\r\n\t\tturn: +turn,\r\n\t\tdataPoints: data[turn].dataPoints,\r\n\t\ttotalStats: data[turn].totalStats,\r\n\t}));\r\n\treturn result;\r\n};\r\n\r\nexport const buildCombatWinrate = (\r\n\trows: readonly InternalBgsRow[],\r\n): readonly { turn: number; dataPoints: number; totalWinrate: number }[] => {\r\n\tconst ref = rows[0];\r\n\tconst debug = ref.heroCardId === 'BG21_HERO_000';\r\n\r\n\tconst data: { [turn: string]: { dataPoints: number; totalWinrate: number } } = {};\r\n\tfor (const row of rows) {\r\n\t\t// logger.debug('building combatWinrate', row);\r\n\t\tif (!row.combatWinrate?.length) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tlet parsed: readonly { turn: number; winrate: number }[] = null;\r\n\t\ttry {\r\n\t\t\tparsed = JSON.parse(row.combatWinrate);\r\n\t\t\t// logger.debug('parsed', parsed);\r\n\t\t\tif (!parsed?.length) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t} catch (e) {\r\n\t\t\tlogger.error('Could not parse combat winrate', row.id, e);\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\t// if (debug) {\r\n\t\t// \tlogger.log('handling combat winrate', parsed);\r\n\t\t// }\r\n\r\n\t\tfor (const turnInfo of parsed) {\r\n\t\t\tif (turnInfo.turn === 0 || turnInfo.winrate == null) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\t// if (debug) {\r\n\t\t\t// \tlogger.log('\\t turnInfo', turnInfo);\r\n\t\t\t// }\r\n\t\t\tconst existingInfo = data['' + turnInfo.turn] ?? { dataPoints: 0, totalWinrate: 0 };\r\n\t\t\t// if (debug) {\r\n\t\t\t// \tlogger.log('\\t existingInfo', existingInfo);\r\n\t\t\t// }\r\n\t\t\texistingInfo.dataPoints = existingInfo.dataPoints + 1;\r\n\t\t\texistingInfo.totalWinrate = existingInfo.totalWinrate + Math.round(turnInfo.winrate);\r\n\t\t\t// if (debug) {\r\n\t\t\t// \tlogger.log('\\t existingInfo after', existingInfo);\r\n\t\t\t// }\r\n\t\t\tdata['' + turnInfo.turn] = existingInfo;\r\n\t\t\t// if (debug) {\r\n\t\t\t// \tlogger.log('\\t data', data);\r\n\t\t\t// }\r\n\t\t}\r\n\t}\r\n\r\n\t// if (debug) {\r\n\t// \tlogger.log('\\t data', data);\r\n\t// }\r\n\tconst result: { turn: number; dataPoints: number; totalWinrate: number }[] = Object.keys(data).map(turn => ({\r\n\t\tturn: +turn,\r\n\t\tdataPoints: data[turn].dataPoints,\r\n\t\ttotalWinrate: data[turn].totalWinrate,\r\n\t}));\r\n\t// if (debug) {\r\n\t// \tlogger.log('\\t result', result);\r\n\t// }\r\n\treturn result;\r\n};\r\n\r\nconst loadRows = async (mysql: ServerlessMysql): Promise<readonly InternalBgsRow[]> => {\r\n\t// We actually use all the fields\r\n\tconst query = `\r\n\t\tSELECT *\r\n\t\tFROM bgs_run_stats\r\n\t\tWHERE creationDate > DATE_SUB(NOW(), INTERVAL 30 DAY);\r\n\t`;\r\n\tlogger.log('running query', query);\r\n\tconst rows: readonly InternalBgsRow[] = await mysql.query(query);\r\n\tlogger.log('rows', rows?.length, rows[0]);\r\n\treturn rows\r\n\t\t.filter(row => row.heroCardId.startsWith('TB_BaconShop_') || row.heroCardId.startsWith('BG'))\r\n\t\t.filter(\r\n\t\t\trow =>\r\n\t\t\t\trow.heroCardId !== CardIds.ArannaStarseeker_ArannaUnleashedTokenBattlegrounds &&\r\n\t\t\t\trow.heroCardId !== CardIds.QueenAzshara_NagaQueenAzsharaToken,\r\n\t\t)\r\n\t\t.map(row => ({\r\n\t\t\t...row,\r\n\t\t\theroCardId: normalizeHeroCardId(row.heroCardId, allCards),\r\n\t\t}));\r\n};\r\n\r\nconst getLastBattlegroundsPatch = async (): Promise<PatchInfo> => {\r\n\tconst patchInfo = await http(`https://static.zerotoheroes.com/hearthstone/data/patches.json`);\r\n\tconst structuredPatch = JSON.parse(patchInfo);\r\n\tconst patchNumber = structuredPatch.currentBattlegroundsMetaPatch;\r\n\treturn structuredPatch.patches.find(patch => patch.number === patchNumber);\r\n};\r\n"]}
|
package/dist/common.d.ts
CHANGED
|
@@ -6,6 +6,10 @@ export declare const buildPlacementDistribution: (rows: readonly InternalBgsRow[
|
|
|
6
6
|
rank: number;
|
|
7
7
|
totalMatches: number;
|
|
8
8
|
}[];
|
|
9
|
+
export declare const buildPlacementDistributionWithPercentages: (rows: readonly InternalBgsRow[]) => readonly {
|
|
10
|
+
rank: number;
|
|
11
|
+
percentage: number;
|
|
12
|
+
}[];
|
|
9
13
|
export interface PatchInfo {
|
|
10
14
|
readonly number: number;
|
|
11
15
|
readonly version: string;
|
package/dist/common.js
CHANGED
|
@@ -45,4 +45,13 @@ exports.buildPlacementDistribution = (rows) => {
|
|
|
45
45
|
Object.keys(groupedByPlacement).forEach(placement => placementDistribution.push({ rank: +placement, totalMatches: groupedByPlacement[placement].length }));
|
|
46
46
|
return placementDistribution;
|
|
47
47
|
};
|
|
48
|
+
exports.buildPlacementDistributionWithPercentages = (rows) => {
|
|
49
|
+
const placementDistribution = exports.buildPlacementDistribution(rows);
|
|
50
|
+
const totalMatches = placementDistribution.map(p => p.totalMatches).reduce((a, b) => a + b, 0);
|
|
51
|
+
const result = placementDistribution.map(p => ({
|
|
52
|
+
rank: p.rank,
|
|
53
|
+
percentage: (100 * p.totalMatches) / totalMatches,
|
|
54
|
+
}));
|
|
55
|
+
return result;
|
|
56
|
+
};
|
|
48
57
|
//# sourceMappingURL=common.js.map
|
package/dist/common.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.js","sourceRoot":"/","sources":["common.ts"],"names":[],"mappings":"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","sourcesContent":["import { groupByFunction } from '@firestone-hs/aws-lambda-utils';\r\nimport { MmrPercentile } from './bgs-global-stats';\r\nimport { InternalBgsRow } from './internal-model';\r\n\r\nexport const filterRowsForTimePeriod = (\r\n\trows: readonly InternalBgsRow[],\r\n\ttimePeriod: 'all-time' | 'past-three' | 'past-seven' | 'last-patch',\r\n\tlastPatch: PatchInfo,\r\n): readonly InternalBgsRow[] => {\r\n\tswitch (timePeriod) {\r\n\t\tcase 'last-patch':\r\n\t\t\treturn rows.filter(\r\n\t\t\t\trow =>\r\n\t\t\t\t\trow.buildNumber >= lastPatch.number ||\r\n\t\t\t\t\tnew Date(row.creationDate) > new Date(new Date(lastPatch.date).getTime() + 24 * 60 * 60 * 1000),\r\n\t\t\t);\r\n\t\tcase 'past-three':\r\n\t\t\treturn rows.filter(\r\n\t\t\t\trow => new Date(row.creationDate) > new Date(new Date().getTime() - 3 * 24 * 60 * 60 * 1000),\r\n\t\t\t);\r\n\t\tcase 'past-seven':\r\n\t\t\treturn rows.filter(\r\n\t\t\t\trow => new Date(row.creationDate) > new Date(new Date().getTime() - 7 * 24 * 60 * 60 * 1000),\r\n\t\t\t);\r\n\t\tcase 'all-time':\r\n\t\tdefault:\r\n\t\t\treturn rows;\r\n\t}\r\n};\r\n\r\nexport const buildMmrPercentiles = (rows: readonly InternalBgsRow[]): readonly MmrPercentile[] => {\r\n\tconst sortedMmrs = rows.map(row => row.rating).sort((a, b) => a - b);\r\n\tconst median = sortedMmrs[Math.floor(sortedMmrs.length / 2)];\r\n\tconst top25 = sortedMmrs[Math.floor((sortedMmrs.length / 4) * 3)];\r\n\tconst top10 = sortedMmrs[Math.floor((sortedMmrs.length / 10) * 9)];\r\n\t// const top1 = sortedMmrs[Math.floor((sortedMmrs.length / 100) * 99)];\r\n\t// logger.debug('percentiles', median, top25, top10, top1);\r\n\treturn [\r\n\t\t{\r\n\t\t\tpercentile: 100,\r\n\t\t\tmmr: 0,\r\n\t\t},\r\n\t\t{\r\n\t\t\tpercentile: 50,\r\n\t\t\tmmr: median,\r\n\t\t},\r\n\t\t{\r\n\t\t\tpercentile: 25,\r\n\t\t\tmmr: top25,\r\n\t\t},\r\n\t\t{\r\n\t\t\tpercentile: 10,\r\n\t\t\tmmr: top10,\r\n\t\t},\r\n\t\t// {\r\n\t\t// \tpercentile: 1,\r\n\t\t// \tmmr: top1,\r\n\t\t// },\r\n\t];\r\n};\r\n\r\nexport const buildPlacementDistribution = (\r\n\trows: readonly InternalBgsRow[],\r\n): readonly { rank: number; totalMatches: number }[] => {\r\n\tconst placementDistribution: { rank: number; totalMatches: number }[] = [];\r\n\tconst groupedByPlacement: { [placement: string]: readonly InternalBgsRow[] } = groupByFunction(\r\n\t\t(res: InternalBgsRow) => '' + res.rank,\r\n\t)(rows);\r\n\tObject.keys(groupedByPlacement).forEach(placement =>\r\n\t\tplacementDistribution.push({ rank: +placement, totalMatches: groupedByPlacement[placement].length }),\r\n\t);\r\n\treturn placementDistribution;\r\n};\r\n\r\nexport interface PatchInfo {\r\n\treadonly number: number;\r\n\treadonly version: string;\r\n\treadonly name: string;\r\n\treadonly date: string;\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"/","sources":["common.ts"],"names":[],"mappings":"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","sourcesContent":["import { groupByFunction } from '@firestone-hs/aws-lambda-utils';\r\nimport { MmrPercentile } from './bgs-global-stats';\r\nimport { InternalBgsRow } from './internal-model';\r\n\r\nexport const filterRowsForTimePeriod = (\r\n\trows: readonly InternalBgsRow[],\r\n\ttimePeriod: 'all-time' | 'past-three' | 'past-seven' | 'last-patch',\r\n\tlastPatch: PatchInfo,\r\n): readonly InternalBgsRow[] => {\r\n\tswitch (timePeriod) {\r\n\t\tcase 'last-patch':\r\n\t\t\treturn rows.filter(\r\n\t\t\t\trow =>\r\n\t\t\t\t\trow.buildNumber >= lastPatch.number ||\r\n\t\t\t\t\tnew Date(row.creationDate) > new Date(new Date(lastPatch.date).getTime() + 24 * 60 * 60 * 1000),\r\n\t\t\t);\r\n\t\tcase 'past-three':\r\n\t\t\treturn rows.filter(\r\n\t\t\t\trow => new Date(row.creationDate) > new Date(new Date().getTime() - 3 * 24 * 60 * 60 * 1000),\r\n\t\t\t);\r\n\t\tcase 'past-seven':\r\n\t\t\treturn rows.filter(\r\n\t\t\t\trow => new Date(row.creationDate) > new Date(new Date().getTime() - 7 * 24 * 60 * 60 * 1000),\r\n\t\t\t);\r\n\t\tcase 'all-time':\r\n\t\tdefault:\r\n\t\t\treturn rows;\r\n\t}\r\n};\r\n\r\nexport const buildMmrPercentiles = (rows: readonly InternalBgsRow[]): readonly MmrPercentile[] => {\r\n\tconst sortedMmrs = rows.map(row => row.rating).sort((a, b) => a - b);\r\n\tconst median = sortedMmrs[Math.floor(sortedMmrs.length / 2)];\r\n\tconst top25 = sortedMmrs[Math.floor((sortedMmrs.length / 4) * 3)];\r\n\tconst top10 = sortedMmrs[Math.floor((sortedMmrs.length / 10) * 9)];\r\n\t// const top1 = sortedMmrs[Math.floor((sortedMmrs.length / 100) * 99)];\r\n\t// logger.debug('percentiles', median, top25, top10, top1);\r\n\treturn [\r\n\t\t{\r\n\t\t\tpercentile: 100,\r\n\t\t\tmmr: 0,\r\n\t\t},\r\n\t\t{\r\n\t\t\tpercentile: 50,\r\n\t\t\tmmr: median,\r\n\t\t},\r\n\t\t{\r\n\t\t\tpercentile: 25,\r\n\t\t\tmmr: top25,\r\n\t\t},\r\n\t\t{\r\n\t\t\tpercentile: 10,\r\n\t\t\tmmr: top10,\r\n\t\t},\r\n\t\t// {\r\n\t\t// \tpercentile: 1,\r\n\t\t// \tmmr: top1,\r\n\t\t// },\r\n\t];\r\n};\r\n\r\nexport const buildPlacementDistribution = (\r\n\trows: readonly InternalBgsRow[],\r\n): readonly { rank: number; totalMatches: number }[] => {\r\n\tconst placementDistribution: { rank: number; totalMatches: number }[] = [];\r\n\tconst groupedByPlacement: { [placement: string]: readonly InternalBgsRow[] } = groupByFunction(\r\n\t\t(res: InternalBgsRow) => '' + res.rank,\r\n\t)(rows);\r\n\tObject.keys(groupedByPlacement).forEach(placement =>\r\n\t\tplacementDistribution.push({ rank: +placement, totalMatches: groupedByPlacement[placement].length }),\r\n\t);\r\n\treturn placementDistribution;\r\n};\r\n\r\nexport const buildPlacementDistributionWithPercentages = (\r\n\trows: readonly InternalBgsRow[],\r\n): readonly { rank: number; percentage: number }[] => {\r\n\tconst placementDistribution = buildPlacementDistribution(rows);\r\n\tconst totalMatches = placementDistribution.map(p => p.totalMatches).reduce((a, b) => a + b, 0);\r\n\tconst result: readonly { rank: number; percentage: number }[] = placementDistribution.map(p => ({\r\n\t\trank: p.rank,\r\n\t\tpercentage: (100 * p.totalMatches) / totalMatches,\r\n\t}));\r\n\treturn result;\r\n};\r\n\r\nexport interface PatchInfo {\r\n\treadonly number: number;\r\n\treadonly version: string;\r\n\treadonly name: string;\r\n\treadonly date: string;\r\n}\r\n"]}
|
|
@@ -11,6 +11,14 @@ export interface BgsGlobalHeroStat {
|
|
|
11
11
|
readonly heroCardId: string;
|
|
12
12
|
readonly dataPoints: number;
|
|
13
13
|
readonly averagePosition: number;
|
|
14
|
+
readonly placementDistribution: readonly {
|
|
15
|
+
rank: number;
|
|
16
|
+
percentage: number;
|
|
17
|
+
}[];
|
|
18
|
+
readonly combatWinrate: readonly {
|
|
19
|
+
turn: number;
|
|
20
|
+
winrate: number;
|
|
21
|
+
}[];
|
|
14
22
|
readonly tribeStats: readonly BgsHeroTribeStat[];
|
|
15
23
|
}
|
|
16
24
|
export interface BgsHeroTribeStat {
|
|
@@ -18,4 +26,20 @@ export interface BgsHeroTribeStat {
|
|
|
18
26
|
readonly dataPoints: number;
|
|
19
27
|
readonly averagePosition: number;
|
|
20
28
|
readonly impactAveragePosition: number;
|
|
29
|
+
readonly placementDistribution: readonly {
|
|
30
|
+
rank: number;
|
|
31
|
+
percentage: number;
|
|
32
|
+
}[];
|
|
33
|
+
readonly impactPlacementDistribution: readonly {
|
|
34
|
+
rank: number;
|
|
35
|
+
impact: number;
|
|
36
|
+
}[];
|
|
37
|
+
readonly combatWinrate: readonly {
|
|
38
|
+
turn: number;
|
|
39
|
+
winrate: number;
|
|
40
|
+
}[];
|
|
41
|
+
readonly impactCombatWinrate: readonly {
|
|
42
|
+
turn: number;
|
|
43
|
+
impact: number;
|
|
44
|
+
}[];
|
|
21
45
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bgs-hero-stat.js","sourceRoot":"/","sources":["stats-v2/bgs-hero-stat.ts"],"names":[],"mappings":"","sourcesContent":["import { Race } from '@firestone-hs/reference-data';\r\nimport { MmrPercentile } from '../bgs-global-stats';\r\nimport { WithMmrAndTimePeriod } from '../quests-v2/charged-stat';\r\n\r\nexport interface BgsHeroStatsV2 {\r\n\treadonly lastUpdateDate: Date;\r\n\treadonly mmrPercentiles: readonly MmrPercentile[];\r\n\treadonly dataPoints: number;\r\n\treadonly heroStats: readonly WithMmrAndTimePeriod<BgsGlobalHeroStat>[];\r\n}\r\n\r\nexport interface BgsGlobalHeroStat {\r\n\treadonly heroCardId: string;\r\n\treadonly dataPoints: number;\r\n\treadonly averagePosition: number;\r\n\
|
|
1
|
+
{"version":3,"file":"bgs-hero-stat.js","sourceRoot":"/","sources":["stats-v2/bgs-hero-stat.ts"],"names":[],"mappings":"","sourcesContent":["import { Race } from '@firestone-hs/reference-data';\r\nimport { MmrPercentile } from '../bgs-global-stats';\r\nimport { WithMmrAndTimePeriod } from '../quests-v2/charged-stat';\r\n\r\nexport interface BgsHeroStatsV2 {\r\n\treadonly lastUpdateDate: Date;\r\n\treadonly mmrPercentiles: readonly MmrPercentile[];\r\n\treadonly dataPoints: number;\r\n\treadonly heroStats: readonly WithMmrAndTimePeriod<BgsGlobalHeroStat>[];\r\n}\r\n\r\nexport interface BgsGlobalHeroStat {\r\n\treadonly heroCardId: string;\r\n\treadonly dataPoints: number;\r\n\treadonly averagePosition: number;\r\n\treadonly placementDistribution: readonly { rank: number; percentage: number }[];\r\n\treadonly combatWinrate: readonly { turn: number; winrate: number }[];\r\n\t// // Same\r\n\t// readonly warbandStats: readonly { turn: number; dataPoints: number; totalStats: number }[];\r\n\treadonly tribeStats: readonly BgsHeroTribeStat[];\r\n}\r\n\r\nexport interface BgsHeroTribeStat {\r\n\treadonly tribe: Race;\r\n\treadonly dataPoints: number;\r\n\treadonly averagePosition: number;\r\n\treadonly impactAveragePosition: number;\r\n\treadonly placementDistribution: readonly { rank: number; percentage: number }[];\r\n\treadonly impactPlacementDistribution: readonly { rank: number; impact: number }[];\r\n\treadonly combatWinrate: readonly { turn: number; winrate: number }[];\r\n\treadonly impactCombatWinrate: readonly { turn: number; impact: number }[];\r\n}\r\n"]}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const aws_lambda_utils_1 = require("@firestone-hs/aws-lambda-utils");
|
|
4
|
+
const reference_data_1 = require("@firestone-hs/reference-data");
|
|
5
|
+
const build_battlegrounds_hero_stats_new_1 = require("../build-battlegrounds-hero-stats-new");
|
|
6
|
+
const common_1 = require("../common");
|
|
4
7
|
const util_functions_1 = require("../utils/util-functions");
|
|
5
8
|
exports.buildStats = (rows, allCards) => {
|
|
6
9
|
const groupedByHero = aws_lambda_utils_1.groupByFunction((row) => util_functions_1.normalizeHeroCardId(row.heroCardId, allCards))(rows);
|
|
@@ -9,28 +12,69 @@ exports.buildStats = (rows, allCards) => {
|
|
|
9
12
|
const buildStatsForSingleHero = (rows) => {
|
|
10
13
|
const ref = rows[0];
|
|
11
14
|
const averagePosition = average(rows.map(r => r.rank));
|
|
12
|
-
|
|
15
|
+
const placementDistribution = common_1.buildPlacementDistributionWithPercentages(rows);
|
|
16
|
+
const rawCombatWinrates = build_battlegrounds_hero_stats_new_1.buildCombatWinrate(rows);
|
|
17
|
+
const combatWinrate = rawCombatWinrates.map(info => ({
|
|
18
|
+
turn: info.turn,
|
|
19
|
+
winrate: info.totalWinrate / info.dataPoints,
|
|
20
|
+
}));
|
|
21
|
+
const result = {
|
|
13
22
|
heroCardId: ref.heroCardId,
|
|
14
23
|
dataPoints: rows.length,
|
|
15
24
|
averagePosition: averagePosition,
|
|
16
|
-
|
|
25
|
+
placementDistribution: placementDistribution,
|
|
26
|
+
combatWinrate: combatWinrate,
|
|
27
|
+
tribeStats: buildTribeStats(rows, averagePosition, placementDistribution, combatWinrate),
|
|
17
28
|
};
|
|
29
|
+
if (ref.heroCardId === "TB_BaconShop_HERO_18") {
|
|
30
|
+
console.debug('Patches sanity', result);
|
|
31
|
+
console.debug('Patches sanity', result.tribeStats.map(t => t.impactAveragePosition * t.dataPoints).reduce((a, b) => a + b, 0));
|
|
32
|
+
console.debug('Patches sanity', rows.filter(r => !r.tribes.includes('' + reference_data_1.Race.PIRATE)).length, rows.filter(r => !r.tribes.includes('' + reference_data_1.Race.PIRATE)));
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
18
35
|
};
|
|
19
|
-
const buildTribeStats = (rows, refAveragePosition) => {
|
|
20
|
-
const
|
|
21
|
-
const uniqueTribes = [
|
|
22
|
-
...new Set(rowsWithTribes.flatMap(r => r.tribes.split(',')).map(r => parseInt(r))),
|
|
23
|
-
];
|
|
36
|
+
const buildTribeStats = (rows, refAveragePosition, refPlacementDistribution, refCombatWinrate) => {
|
|
37
|
+
const uniqueTribes = [...new Set(rows.flatMap(r => r.tribes.split(',')).map(r => parseInt(r)))];
|
|
24
38
|
return uniqueTribes.map(tribe => {
|
|
25
|
-
const rowsForTribe =
|
|
26
|
-
const rowsWithoutTribe =
|
|
39
|
+
const rowsForTribe = rows.filter(r => r.tribes.split(',').includes('' + tribe));
|
|
40
|
+
const rowsWithoutTribe = rows.filter(r => !r.tribes.split(',').includes('' + tribe));
|
|
27
41
|
const averagePosition = average(rowsForTribe.map(r => r.rank));
|
|
42
|
+
const placementDistribution = common_1.buildPlacementDistributionWithPercentages(rowsForTribe);
|
|
43
|
+
const rawCombatWinrates = build_battlegrounds_hero_stats_new_1.buildCombatWinrate(rowsForTribe);
|
|
44
|
+
const combatWinrate = rawCombatWinrates.map(info => ({
|
|
45
|
+
turn: info.turn,
|
|
46
|
+
winrate: info.totalWinrate / info.dataPoints,
|
|
47
|
+
}));
|
|
28
48
|
return {
|
|
29
49
|
tribe: tribe,
|
|
30
50
|
dataPoints: rowsForTribe.length,
|
|
31
51
|
dataPointsOnMissingTribe: rowsWithoutTribe.length,
|
|
32
52
|
averagePosition: averagePosition,
|
|
33
53
|
impactAveragePosition: averagePosition - refAveragePosition,
|
|
54
|
+
placementDistribution: placementDistribution,
|
|
55
|
+
impactPlacementDistribution: refPlacementDistribution.map(p => {
|
|
56
|
+
var _a, _b;
|
|
57
|
+
const newPlacementInfo = placementDistribution.find(p2 => p2.rank === p.rank);
|
|
58
|
+
if (!newPlacementInfo) {
|
|
59
|
+
console.log('missing placement info', placementDistribution, p);
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
rank: p.rank,
|
|
63
|
+
impact: (_b = (_a = newPlacementInfo) === null || _a === void 0 ? void 0 : _a.percentage, (_b !== null && _b !== void 0 ? _b : 0)) - p.percentage,
|
|
64
|
+
};
|
|
65
|
+
}),
|
|
66
|
+
combatWinrate: combatWinrate,
|
|
67
|
+
impactCombatWinrate: refCombatWinrate.map(c => {
|
|
68
|
+
var _a, _b;
|
|
69
|
+
const newCombatWinrate = combatWinrate.find(c2 => c2.turn === c.turn);
|
|
70
|
+
if (!newCombatWinrate) {
|
|
71
|
+
console.debug('missing winrate info', combatWinrate);
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
turn: c.turn,
|
|
75
|
+
impact: (_b = (_a = newCombatWinrate) === null || _a === void 0 ? void 0 : _a.winrate, (_b !== null && _b !== void 0 ? _b : 0)) - c.winrate,
|
|
76
|
+
};
|
|
77
|
+
}),
|
|
34
78
|
};
|
|
35
79
|
});
|
|
36
80
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats-buikder.js","sourceRoot":"/","sources":["stats-v2/stats-buikder.ts"],"names":[],"mappings":";;AAAA,qEAAiE;
|
|
1
|
+
{"version":3,"file":"stats-buikder.js","sourceRoot":"/","sources":["stats-v2/stats-buikder.ts"],"names":[],"mappings":"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","sourcesContent":["import { groupByFunction } from '@firestone-hs/aws-lambda-utils';\r\nimport { AllCardsService, CardIds, Race } from '@firestone-hs/reference-data';\r\nimport { buildCombatWinrate } from '../build-battlegrounds-hero-stats-new';\r\nimport { buildPlacementDistributionWithPercentages } from '../common';\r\nimport { InternalBgsRow } from '../internal-model';\r\nimport { normalizeHeroCardId } from '../utils/util-functions';\r\nimport { BgsGlobalHeroStat, BgsHeroTribeStat } from './bgs-hero-stat';\r\n\r\nexport const buildStats = (\r\n\trows: readonly InternalBgsRow[],\r\n\tallCards: AllCardsService,\r\n): readonly BgsGlobalHeroStat[] => {\r\n\tconst groupedByHero: {\r\n\t\t[questCardId: string]: readonly InternalBgsRow[];\r\n\t} = groupByFunction((row: InternalBgsRow) => normalizeHeroCardId(row.heroCardId, allCards))(rows);\r\n\treturn Object.values(groupedByHero).flatMap(data => buildStatsForSingleHero(data));\r\n};\r\n\r\n// All rows here belong to a single hero\r\nconst buildStatsForSingleHero = (rows: readonly InternalBgsRow[]): BgsGlobalHeroStat => {\r\n\tconst ref = rows[0];\r\n\tconst averagePosition = average(rows.map(r => r.rank));\r\n\tconst placementDistribution = buildPlacementDistributionWithPercentages(rows);\r\n\tconst rawCombatWinrates = buildCombatWinrate(rows);\r\n\tconst combatWinrate: readonly { turn: number; winrate: number }[] = rawCombatWinrates.map(info => ({\r\n\t\tturn: info.turn,\r\n\t\twinrate: info.totalWinrate / info.dataPoints,\r\n\t}));\r\n\tconst result: BgsGlobalHeroStat = {\r\n\t\theroCardId: ref.heroCardId,\r\n\t\tdataPoints: rows.length,\r\n\t\taveragePosition: averagePosition,\r\n\t\tplacementDistribution: placementDistribution,\r\n\t\tcombatWinrate: combatWinrate,\r\n\t\ttribeStats: buildTribeStats(rows, averagePosition, placementDistribution, combatWinrate),\r\n\t};\r\n\tif (ref.heroCardId === CardIds.PatchesThePirateBattlegrounds) {\r\n\t\tconsole.debug('Patches sanity', result);\r\n\t\tconsole.debug(\r\n\t\t\t'Patches sanity',\r\n\t\t\tresult.tribeStats.map(t => t.impactAveragePosition * t.dataPoints).reduce((a, b) => a + b, 0),\r\n\t\t);\r\n\t\tconsole.debug(\r\n\t\t\t'Patches sanity',\r\n\t\t\trows.filter(r => !r.tribes.includes('' + Race.PIRATE)).length,\r\n\t\t\trows.filter(r => !r.tribes.includes('' + Race.PIRATE)),\r\n\t\t);\r\n\t}\r\n\treturn result;\r\n};\r\n\r\nconst buildTribeStats = (\r\n\trows: readonly InternalBgsRow[],\r\n\trefAveragePosition: number,\r\n\trefPlacementDistribution: readonly { rank: number; percentage: number }[],\r\n\trefCombatWinrate: readonly { turn: number; winrate: number }[],\r\n): readonly BgsHeroTribeStat[] => {\r\n\tconst uniqueTribes: readonly Race[] = [...new Set(rows.flatMap(r => r.tribes.split(',')).map(r => parseInt(r)))];\r\n\treturn uniqueTribes.map(tribe => {\r\n\t\tconst rowsForTribe = rows.filter(r => r.tribes.split(',').includes('' + tribe));\r\n\t\tconst rowsWithoutTribe = rows.filter(r => !r.tribes.split(',').includes('' + tribe));\r\n\t\tconst averagePosition = average(rowsForTribe.map(r => r.rank));\r\n\t\tconst placementDistribution = buildPlacementDistributionWithPercentages(rowsForTribe);\r\n\t\tconst rawCombatWinrates = buildCombatWinrate(rowsForTribe);\r\n\t\tconst combatWinrate = rawCombatWinrates.map(info => ({\r\n\t\t\tturn: info.turn,\r\n\t\t\twinrate: info.totalWinrate / info.dataPoints,\r\n\t\t}));\r\n\t\treturn {\r\n\t\t\ttribe: tribe,\r\n\t\t\tdataPoints: rowsForTribe.length,\r\n\t\t\tdataPointsOnMissingTribe: rowsWithoutTribe.length,\r\n\t\t\taveragePosition: averagePosition,\r\n\t\t\timpactAveragePosition: averagePosition - refAveragePosition,\r\n\t\t\tplacementDistribution: placementDistribution,\r\n\t\t\timpactPlacementDistribution: refPlacementDistribution.map(p => {\r\n\t\t\t\tconst newPlacementInfo = placementDistribution.find(p2 => p2.rank === p.rank);\r\n\t\t\t\t// Cna happen when there isn't a lot of data points, typically for high MMR\r\n\t\t\t\tif (!newPlacementInfo) {\r\n\t\t\t\t\tconsole.log('missing placement info', placementDistribution, p);\r\n\t\t\t\t}\r\n\t\t\t\treturn {\r\n\t\t\t\t\trank: p.rank,\r\n\t\t\t\t\timpact: (newPlacementInfo?.percentage ?? 0) - p.percentage,\r\n\t\t\t\t};\r\n\t\t\t}),\r\n\t\t\tcombatWinrate: combatWinrate,\r\n\t\t\timpactCombatWinrate: refCombatWinrate.map(c => {\r\n\t\t\t\tconst newCombatWinrate = combatWinrate.find(c2 => c2.turn === c.turn);\r\n\t\t\t\tif (!newCombatWinrate) {\r\n\t\t\t\t\tconsole.debug('missing winrate info', combatWinrate);\r\n\t\t\t\t}\r\n\t\t\t\treturn {\r\n\t\t\t\t\tturn: c.turn,\r\n\t\t\t\t\timpact: (newCombatWinrate?.winrate ?? 0) - c.winrate,\r\n\t\t\t\t};\r\n\t\t\t}),\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"]}
|
|
@@ -8,7 +8,7 @@ const stats_buikder_1 = require("./stats-buikder");
|
|
|
8
8
|
exports.STATS_BUCKET = `static.zerotoheroes.com`;
|
|
9
9
|
exports.handleStatsV2 = async (timePeriod, rows, lastPatch, allCards) => {
|
|
10
10
|
var _a, _b;
|
|
11
|
-
const rowsWithStats = rows.filter(row => !!row.rank);
|
|
11
|
+
const rowsWithStats = rows.filter(row => !!row.rank).filter(r => { var _a; return !!((_a = r.tribes) === null || _a === void 0 ? void 0 : _a.length); });
|
|
12
12
|
console.log('total relevant rows', (_a = rowsWithStats) === null || _a === void 0 ? void 0 : _a.length);
|
|
13
13
|
const statResult = await data_filter_1.buildSplitStats(rowsWithStats, timePeriod, lastPatch, (data) => stats_buikder_1.buildStats(data, allCards));
|
|
14
14
|
const stats = statResult.stats;
|
|
@@ -16,7 +16,7 @@ exports.handleStatsV2 = async (timePeriod, rows, lastPatch, allCards) => {
|
|
|
16
16
|
lastUpdateDate: new Date(),
|
|
17
17
|
mmrPercentiles: statResult.mmrPercentiles,
|
|
18
18
|
heroStats: stats,
|
|
19
|
-
dataPoints:
|
|
19
|
+
dataPoints: stats.map(s => s.dataPoints).reduce((a, b) => a + b, 0),
|
|
20
20
|
};
|
|
21
21
|
aws_lambda_utils_1.logger.log('\tbuilt stats', statsV2.dataPoints, (_b = statsV2.heroStats) === null || _b === void 0 ? void 0 : _b.length);
|
|
22
22
|
const timeSuffix = timePeriod;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats-v2.js","sourceRoot":"/","sources":["stats-v2/stats-v2.ts"],"names":[],"mappings":";;AAAA,qEAAwD;AAExD,+BAAgC;AAChC,8FAA2D;AAG3D,0DAA2D;AAE3D,mDAA6C;AAEhC,QAAA,YAAY,GAAG,yBAAyB,CAAC;AAEzC,QAAA,aAAa,GAAG,KAAK,EACjC,UAAmE,EACnE,IAA+B,EAC/B,SAAoB,EACpB,QAAyB,EACxB,EAAE;;IACH,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"stats-v2.js","sourceRoot":"/","sources":["stats-v2/stats-v2.ts"],"names":[],"mappings":";;AAAA,qEAAwD;AAExD,+BAAgC;AAChC,8FAA2D;AAG3D,0DAA2D;AAE3D,mDAA6C;AAEhC,QAAA,YAAY,GAAG,yBAAyB,CAAC;AAEzC,QAAA,aAAa,GAAG,KAAK,EACjC,UAAmE,EACnE,IAA+B,EAC/B,SAAoB,EACpB,QAAyB,EACxB,EAAE;;IACH,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAC,OAAA,CAAC,QAAC,CAAC,CAAC,MAAM,0CAAE,MAAM,CAAA,CAAA,EAAA,CAAC,CAAC;IACrF,OAAO,CAAC,GAAG,CAAC,qBAAqB,QAAE,aAAa,0CAAE,MAAM,CAAC,CAAC;IAE1D,MAAM,UAAU,GAAG,MAAM,6BAAe,CAAC,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,IAAsB,EAAE,EAAE,CACzG,0BAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,CAC1B,CAAC;IACF,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC;IAC/B,MAAM,OAAO,GAAmB;QAC/B,cAAc,EAAE,IAAI,IAAI,EAAE;QAC1B,cAAc,EAAE,UAAU,CAAC,cAAc;QACzC,SAAS,EAAE,KAAK;QAChB,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;KACnE,CAAC;IACF,yBAAM,CAAC,GAAG,CAAC,eAAe,EAAE,OAAO,CAAC,UAAU,QAAE,OAAO,CAAC,SAAS,0CAAE,MAAM,CAAC,CAAC;IAC3E,MAAM,UAAU,GAAG,UAAU,CAAC;IAC9B,MAAM,uCAAE,CAAC,SAAS,CACjB,eAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,EACjC,oBAAY,EACZ,wBAAwB,UAAU,UAAU,EAC5C,kBAAkB,EAClB,MAAM,CACN,CAAC;AACH,CAAC,CAAC","sourcesContent":["import { logger } from '@firestone-hs/aws-lambda-utils';\r\nimport { AllCardsService } from '@firestone-hs/reference-data';\r\nimport { gzipSync } from 'zlib';\r\nimport { s3 } from '../build-battlegrounds-hero-stats-new';\r\nimport { PatchInfo } from '../common';\r\nimport { InternalBgsRow } from '../internal-model';\r\nimport { buildSplitStats } from '../quests-v2/data-filter';\r\nimport { BgsHeroStatsV2 } from './bgs-hero-stat';\r\nimport { buildStats } from './stats-buikder';\r\n\r\nexport const STATS_BUCKET = `static.zerotoheroes.com`;\r\n\r\nexport const handleStatsV2 = async (\r\n\ttimePeriod: 'all-time' | 'past-three' | 'past-seven' | 'last-patch',\r\n\trows: readonly InternalBgsRow[],\r\n\tlastPatch: PatchInfo,\r\n\tallCards: AllCardsService,\r\n) => {\r\n\tconst rowsWithStats = rows.filter(row => !!row.rank).filter(r => !!r.tribes?.length);\r\n\tconsole.log('total relevant rows', rowsWithStats?.length);\r\n\r\n\tconst statResult = await buildSplitStats(rowsWithStats, timePeriod, lastPatch, (data: InternalBgsRow[]) =>\r\n\t\tbuildStats(data, allCards),\r\n\t);\r\n\tconst stats = statResult.stats;\r\n\tconst statsV2: BgsHeroStatsV2 = {\r\n\t\tlastUpdateDate: new Date(),\r\n\t\tmmrPercentiles: statResult.mmrPercentiles,\r\n\t\theroStats: stats,\r\n\t\tdataPoints: stats.map(s => s.dataPoints).reduce((a, b) => a + b, 0),\r\n\t};\r\n\tlogger.log('\\tbuilt stats', statsV2.dataPoints, statsV2.heroStats?.length);\r\n\tconst timeSuffix = timePeriod;\r\n\tawait s3.writeFile(\r\n\t\tgzipSync(JSON.stringify(statsV2)),\r\n\t\tSTATS_BUCKET,\r\n\t\t`api/bgs/stats-v2/bgs-${timeSuffix}.gz.json`,\r\n\t\t'application/json',\r\n\t\t'gzip',\r\n\t);\r\n};\r\n"]}
|