From 21bafa1b7b6f3ecadde3e3c9f8e6d76dec5e450b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Wed, 20 Mar 2024 16:58:43 -0500 Subject: [PATCH] feat: added more stats --- scripts/buildRatingsLeaderboard.ts | 2 +- src/core/blitz/getAccountInfo.ts | 2 +- src/core/blitzkrieg/getArchivedRatingsInfo.ts | 28 +++---- .../getArchivedRatingsLeaderboard.ts | 25 +++---- .../getArchivedRatingsMidnightLeaderboard.ts | 35 ++++----- src/core/statistics/deltaBkrlBlitzStats.ts | 18 +++++ src/core/statistics/deltaTankStats.ts | 75 +++++++++---------- src/core/streams/bkrl.ts | 10 +-- src/events/interactionCreate/index.ts | 2 + 9 files changed, 103 insertions(+), 94 deletions(-) create mode 100644 src/core/statistics/deltaBkrlBlitzStats.ts diff --git a/scripts/buildRatingsLeaderboard.ts b/scripts/buildRatingsLeaderboard.ts index 0c2d25c16..010a3c87e 100644 --- a/scripts/buildRatingsLeaderboard.ts +++ b/scripts/buildRatingsLeaderboard.ts @@ -156,7 +156,7 @@ for (const leaderboardChunk of chunk(leaderboard, 100)) { hits: stat.statistics.rating!.hits, kills: stat.statistics.rating!.frags, shots: stat.statistics.rating!.shots, - survived: stat.statistics.rating!.win_and_survived, + survived: stat.statistics.rating!.survived_battles, wins: stat.statistics.rating!.wins, }; }); diff --git a/src/core/blitz/getAccountInfo.ts b/src/core/blitz/getAccountInfo.ts index 8d63a8693..3f15faaa0 100644 --- a/src/core/blitz/getAccountInfo.ts +++ b/src/core/blitz/getAccountInfo.ts @@ -51,7 +51,7 @@ export interface ClanStats { dropped_capture_points: number; } -interface RatingStats { +export interface RatingStats { spotted: number; calibration_battles_left: number; hits: number; diff --git a/src/core/blitzkrieg/getArchivedRatingsInfo.ts b/src/core/blitzkrieg/getArchivedRatingsInfo.ts index b6970e8c2..ab25d4308 100644 --- a/src/core/blitzkrieg/getArchivedRatingsInfo.ts +++ b/src/core/blitzkrieg/getArchivedRatingsInfo.ts @@ -1,7 +1,9 @@ import { RatingsInfo } from '../../commands/ratings'; import { Region } from '../../constants/regions'; +import { asset } from './asset'; +import { superDecompress } from './superDecompress'; -const INFO_CACHE: Record< +const cache: Record< Region, Record< number, @@ -19,18 +21,18 @@ export default async function getArchivedRatingsInfo( region: Region, season: number, ) { - if (INFO_CACHE[region][season]) { - return INFO_CACHE[region][season]; + if (!cache[region][season]) { + const info = await fetch( + asset(`regions/${region}/ratings/${season}/info.cdon.lz4`), + ) + .then((response) => response.arrayBuffer()) + .then((buffer) => + superDecompress( + new Uint8Array(buffer), + ), + ); + cache[region][season] = info; } - const response = await fetch( - `https://raw.githubusercontent.com/tresabhi/blitzkrieg-assets/main/regions/${region}/ratings/${season}/info.json`, - ); - const jsonContent = (await response.json()) as RatingsInfo & { - detail: undefined; - }; - - INFO_CACHE[region][season] = jsonContent; - - return jsonContent; + return cache[region][season]; } diff --git a/src/core/blitzkrieg/getArchivedRatingsLeaderboard.ts b/src/core/blitzkrieg/getArchivedRatingsLeaderboard.ts index f87507e90..58e096afa 100644 --- a/src/core/blitzkrieg/getArchivedRatingsLeaderboard.ts +++ b/src/core/blitzkrieg/getArchivedRatingsLeaderboard.ts @@ -1,10 +1,8 @@ -import { BlitzkriegRatingsLeaderboard } from '../../../scripts/buildRatingsLeaderboard'; import { Region } from '../../constants/regions'; +import { BkrlDiscriminatedEntries, BkrlReadStream } from '../streams/bkrl'; +import { asset } from './asset'; -const LEADERBOARD_CACHE: Record< - Region, - Record -> = { +const cache: Record> = { asia: {}, eu: {}, com: {}, @@ -14,15 +12,14 @@ export async function getArchivedRatingsLeaderboard( region: Region, season: number, ) { - if (LEADERBOARD_CACHE[region][season]) { - return LEADERBOARD_CACHE[region][season]; + if (!cache[region][season]) { + const info = await fetch( + asset(`regions/${region}/ratings/${season}/latest.bkrl`), + ) + .then((response) => response.arrayBuffer()) + .then((buffer) => new BkrlReadStream(buffer).bkrl()); + cache[region][season] = info; } - const response = await fetch( - `https://raw.githubusercontent.com/tresabhi/blitzkrieg-assets/main/regions/${region}/ratings/${season}/latest.json`, - ); - const json = (await response.json()) as BlitzkriegRatingsLeaderboard; - LEADERBOARD_CACHE[region][season] = json; - - return json; + return cache[region][season]; } diff --git a/src/core/blitzkrieg/getArchivedRatingsMidnightLeaderboard.ts b/src/core/blitzkrieg/getArchivedRatingsMidnightLeaderboard.ts index 72d39cd29..0a611eb65 100644 --- a/src/core/blitzkrieg/getArchivedRatingsMidnightLeaderboard.ts +++ b/src/core/blitzkrieg/getArchivedRatingsMidnightLeaderboard.ts @@ -1,10 +1,8 @@ -import { BlitzkriegRatingsLeaderboard } from '../../../scripts/buildRatingsLeaderboard'; import { Region } from '../../constants/regions'; +import { BkrlDiscriminatedEntries, BkrlReadStream } from '../streams/bkrl'; +import { asset } from './asset'; -const MIDNIGHT_LEADERBOARD_CACHE: Record< - Region, - Record -> = { +const cache: Record> = { com: {}, eu: {}, asia: {}, @@ -14,21 +12,18 @@ export default async function getArchivedRatingsMidnightLeaderboard( region: Region, season: number, ) { - if (MIDNIGHT_LEADERBOARD_CACHE[region][season]) { - return MIDNIGHT_LEADERBOARD_CACHE[region][season]; + if (!cache[region][season]) { + const info = await fetch( + asset(`regions/${region}/ratings/${season}/midnight.bkrl`), + ) + .then((response) => + response.status === 404 ? null : response.arrayBuffer(), + ) + .then((buffer) => + buffer === null ? null : new BkrlReadStream(buffer).bkrl(), + ); + cache[region][season] = info; } - try { - const response = await fetch( - `https://raw.githubusercontent.com/tresabhi/blitzkrieg-assets/main/regions/${region}/ratings/${season}/midnight.json`, - ); - const json = (await response.json()) as BlitzkriegRatingsLeaderboard; - MIDNIGHT_LEADERBOARD_CACHE[region][season] = json; - - return json; - } catch (error) { - console.warn( - `No midnight leaderboard found for season ${season}, region ${region}`, - ); - } + return cache[region][season]; } diff --git a/src/core/statistics/deltaBkrlBlitzStats.ts b/src/core/statistics/deltaBkrlBlitzStats.ts new file mode 100644 index 000000000..7d14828f9 --- /dev/null +++ b/src/core/statistics/deltaBkrlBlitzStats.ts @@ -0,0 +1,18 @@ +import { RatingStats } from '../blitz/getAccountInfo'; +import { BkrlComprehensive1Entry, BkrlMinimalEntry } from '../streams/bkrl'; + +export function deltaBkrlBlitzStats( + a: BkrlComprehensive1Entry, + b: RatingStats, +) { + return { + battles: b.battles - a.battles, + damageDealt: b.damage_dealt - a.damageDealt, + damageReceived: b.damage_received - a.damageReceived, + hits: b.hits - a.hits, + kills: b.frags - a.kills, + shots: b.shots - a.shots, + survived: b.survived_battles - a.survived, + wins: b.wins - a.wins, + } satisfies Omit; +} diff --git a/src/core/statistics/deltaTankStats.ts b/src/core/statistics/deltaTankStats.ts index a1996edbe..aacb2c7bd 100644 --- a/src/core/statistics/deltaTankStats.ts +++ b/src/core/statistics/deltaTankStats.ts @@ -5,60 +5,55 @@ import { } from '../../types/tanksStats'; export function deltaTankStats( - a: NormalizedTankStats, - b: NormalizedTankStats, + aRaw: NormalizedTankStats, + bRaw: NormalizedTankStats, time?: number, ) { - const bTanks = Object.keys(b); + const bTanks = Object.keys(bRaw); const changedTanks = bTanks.filter((id) => { return ( - a[id as unknown as number]?.all.battles !== - b[id as unknown as number].all.battles && + aRaw[id as unknown as number]?.all.battles !== + bRaw[id as unknown as number].all.battles && (time === undefined ? true - : b[id as unknown as number].last_battle_time > time) + : bRaw[id as unknown as number].last_battle_time > time) ); }); const diff = changedTanks.map((id) => { - const aTank = a[id as unknown as number] ?? emptyIndividualTankStats; - const bTank = b[id as unknown as number]; + const a = aRaw[id as unknown as number] ?? emptyIndividualTankStats; + const b = bRaw[id as unknown as number]; const tankDiff = { - account_id: bTank.account_id, - battle_life_time: bTank.battle_life_time, - frags: (bTank.frags ?? aTank.frags ?? 0) - (aTank.frags ?? 0), - max_frags: Math.max(aTank.max_frags, bTank.max_frags), - in_garage: bTank.in_garage, - max_xp: Math.max(aTank.max_xp, bTank.max_xp), - in_garage_updated: bTank.in_garage_updated, - last_battle_time: Math.max( - bTank.last_battle_time, - aTank.last_battle_time, - ), - mark_of_mastery: bTank.mark_of_mastery, - tank_id: bTank.tank_id, + account_id: b.account_id, + battle_life_time: b.battle_life_time, + frags: (b.frags ?? a.frags ?? 0) - (a.frags ?? 0), + max_frags: Math.max(a.max_frags, b.max_frags), + in_garage: b.in_garage, + max_xp: Math.max(a.max_xp, b.max_xp), + in_garage_updated: b.in_garage_updated, + last_battle_time: Math.max(b.last_battle_time, a.last_battle_time), + mark_of_mastery: b.mark_of_mastery, + tank_id: b.tank_id, all: { - battles: bTank.all.battles - aTank.all.battles, - wins: bTank.all.wins - aTank.all.wins, - capture_points: bTank.all.capture_points - aTank.all.capture_points, - damage_dealt: bTank.all.damage_dealt - aTank.all.damage_dealt, - damage_received: bTank.all.damage_received - aTank.all.damage_received, + battles: b.all.battles - a.all.battles, + wins: b.all.wins - a.all.wins, + capture_points: b.all.capture_points - a.all.capture_points, + damage_dealt: b.all.damage_dealt - a.all.damage_dealt, + damage_received: b.all.damage_received - a.all.damage_received, dropped_capture_points: - bTank.all.dropped_capture_points - aTank.all.dropped_capture_points, - frags: bTank.all.frags - aTank.all.frags, - frags8p: bTank.all.frags8p - aTank.all.frags8p, - hits: bTank.all.hits - aTank.all.hits, - losses: bTank.all.losses - aTank.all.losses, - max_frags: Math.max(aTank.max_frags, bTank.max_frags), - max_xp: Math.max(aTank.max_xp, bTank.max_xp), - shots: bTank.all.shots - aTank.all.shots, - spotted: bTank.all.spotted - aTank.all.spotted, - survived_battles: - bTank.all.survived_battles - aTank.all.survived_battles, - win_and_survived: - bTank.all.win_and_survived - aTank.all.win_and_survived, - xp: bTank.all.xp - aTank.all.xp, + b.all.dropped_capture_points - a.all.dropped_capture_points, + frags: b.all.frags - a.all.frags, + frags8p: b.all.frags8p - a.all.frags8p, + hits: b.all.hits - a.all.hits, + losses: b.all.losses - a.all.losses, + max_frags: Math.max(a.max_frags, b.max_frags), + max_xp: Math.max(a.max_xp, b.max_xp), + shots: b.all.shots - a.all.shots, + spotted: b.all.spotted - a.all.spotted, + survived_battles: b.all.survived_battles - a.all.survived_battles, + win_and_survived: b.all.win_and_survived - a.all.win_and_survived, + xp: b.all.xp - a.all.xp, }, } satisfies IndividualTankStats; diff --git a/src/core/streams/bkrl.ts b/src/core/streams/bkrl.ts index 120f30cf1..79b9e2706 100644 --- a/src/core/streams/bkrl.ts +++ b/src/core/streams/bkrl.ts @@ -28,7 +28,7 @@ export interface BkrlComprehensive1Entry { kills: number; } -type DiscriminatedEntries = +export type BkrlDiscriminatedEntries = | { format: BkrlFormat.Minimal; entries: BkrlMinimalEntry[]; @@ -45,7 +45,7 @@ export class BkrlReadStream extends ReadStream { return this.body(header); } - body(header: ReturnType): DiscriminatedEntries { + body(header: ReturnType): BkrlDiscriminatedEntries { switch (header.format) { case BkrlFormat.Minimal: { return { @@ -107,13 +107,13 @@ export class BkrlReadStream extends ReadStream { } export class BkrlWriteStream extends WriteStream { - bkrl(discriminatedEntries: DiscriminatedEntries) { + bkrl(discriminatedEntries: BkrlDiscriminatedEntries) { this.magic(); this.header(discriminatedEntries); this.body(discriminatedEntries); } - body(discriminatedEntries: DiscriminatedEntries) { + body(discriminatedEntries: BkrlDiscriminatedEntries) { switch (discriminatedEntries.format) { case BkrlFormat.Minimal: { discriminatedEntries.entries.forEach((entry) => { @@ -145,7 +145,7 @@ export class BkrlWriteStream extends WriteStream { } } - header(discriminatedEntries: DiscriminatedEntries) { + header(discriminatedEntries: BkrlDiscriminatedEntries) { this.uint16(1); this.uint8(discriminatedEntries.format); this.uint32(discriminatedEntries.entries.length); diff --git a/src/events/interactionCreate/index.ts b/src/events/interactionCreate/index.ts index bcbdcfe95..4b22d1fb4 100644 --- a/src/events/interactionCreate/index.ts +++ b/src/events/interactionCreate/index.ts @@ -30,6 +30,7 @@ import { researchCommand } from '../../commands/research'; import { searchClansCommand } from '../../commands/searchClans'; import { searchPlayersCommand } from '../../commands/searchPlayers'; import { statsCommand } from '../../commands/stats'; +import { testCommand } from '../../commands/test'; import { todayCommand } from '../../commands/today'; import getClientId from '../../core/blitzkrieg/getClientId'; import isDev from '../../core/blitzkrieg/isDev'; @@ -95,6 +96,7 @@ export const COMMANDS_RAW: Promise[] = [ ratingsCommand, todayCommand, researchCommand, + testCommand, ]; export const commands = Promise.allSettled(COMMANDS_RAW).then((rawCommands) => {