diff --git a/scripts/build.js b/scripts/build.js index 49774e78b..a49c88c09 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -1,5 +1,5 @@ import { build } from 'esbuild'; -import { copyFile, mkdir, rm, writeFile } from 'fs/promises'; +import { copyFile, mkdir, rm } from 'fs/promises'; import { argv } from 'process'; const isProd = !argv.includes('--dev'); @@ -17,29 +17,6 @@ if (isProd) { await mkdir('dist'); console.log('✅ Dist created'); - console.log('🟡 Caching tankopedia...'); - fetch('https://www.blitzstars.com/bs-tankopedia.json') - .then((response) => response.text()) - .then((tankopedia) => writeFile('./dist/tankopedia.json', tankopedia)) - .then(() => console.log('✅ Tankopedia cached')); - - console.log('🟡 Caching tank averages...'); - fetch('https://www.blitzstars.com/api/tankaverages.json') - .then((response) => response.json()) - .then((individualTankAverages) => { - const tankAverages = {}; - - individualTankAverages.forEach((individualTankAverage) => { - tankAverages[individualTankAverage.tank_id] = individualTankAverage; - }); - - return writeFile( - './dist/tankaverages.json', - JSON.stringify(tankAverages), - ); - }) - .then(() => console.log('✅ Tank averages cached')); - console.log('🟡 Copying package.json...'); copyFile('package.dist.json', 'dist/package.json').then(() => console.log('✅ package.json copied'), diff --git a/src/commands/debug.ts b/src/commands/debug.ts index d3cb7805a..77af7954d 100644 --- a/src/commands/debug.ts +++ b/src/commands/debug.ts @@ -12,14 +12,14 @@ const executionStart = new Date().getTime(); export const debugCommand: CommandRegistry = { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() .setName('debug') .setDescription('Debug information about the bot'), - handler(interaction) { + async handler(interaction) { const currentTime = new Date().getTime(); const uptime = currentTime - executionStart; @@ -37,8 +37,8 @@ export const debugCommand: CommandRegistry = { (uptime / 1000) % 60, )}s ${Math.floor(uptime % 1000)}ms`, ], - ['Tankopedia cached', `${tankopedia !== undefined}`], - ['Tank averages cached', `${tankAverages !== undefined}`], + ['Tankopedia cached', `${(await tankopedia) !== undefined}`], + ['Tank averages cached', `${(await tankAverages) !== undefined}`], ]), ); }, diff --git a/src/commands/eligible.ts b/src/commands/eligible.ts index 48312b13f..52e0a4177 100644 --- a/src/commands/eligible.ts +++ b/src/commands/eligible.ts @@ -15,6 +15,7 @@ import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand.j import { WARGAMING_APPLICATION_ID } from '../core/node/arguments.js'; import { CommandRegistry } from '../events/interactionCreate/index.js'; import { AccountInfo } from '../types/accountInfo.js'; +import { PossiblyPromise } from '../types/possiblyPromise.js'; export type SkilledClan = 'SKLLD' | 'SMRI'; @@ -25,7 +26,7 @@ export const SKILLED_CLANS: Record = { export const eligibleCommand: CommandRegistry = { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: false, command: new SlashCommandBuilder() @@ -67,41 +68,56 @@ export const eligibleCommand: CommandRegistry = { const entries = Object.entries(tankStatsOverTime); const stats = sumStats(entries.map(([, stats]) => stats)); const averageTier = - entries.reduce((accumulator, [tankIdString, stats]) => { - const tankId = parseInt(tankIdString); - const tankTier = tankopedia[tankId].tier; + (await entries.reduce>( + async (accumulator, [tankIdString, stats]) => { + const tankId = parseInt(tankIdString); + const tankTier = (await tankopedia)[tankId].tier; - return accumulator + tankTier * stats.battles; - }, 0) / stats.battles; + return (await accumulator) + tankTier * stats.battles; + }, + 0, + )) / stats.battles; const WN8 = - entries.reduce((accumulator, [tankIdString, stats]) => { - const tankId = parseInt(tankIdString); + (await entries.reduce>( + async (accumulator, [tankIdString, stats]) => { + const tankId = parseInt(tankIdString); - // edge case where new tanks don't have averages - if (tankAverages[tankId]) { - const tankWN8 = calculateWN8(tankAverages[tankId].all, stats); + // edge case where new tanks don't have averages + if ((await tankAverages)[tankId]) { + const tankWN8 = calculateWN8( + (await tankAverages)[tankId].all, + stats, + ); - if (isNaN(tankWN8)) return accumulator; - return accumulator + tankWN8 * stats.battles; - } else return accumulator; - }, 0) / stats.battles; + if (isNaN(tankWN8)) return accumulator; + return (await accumulator) + tankWN8 * stats.battles; + } else return accumulator; + }, + 0, + )) / stats.battles; const tier10Damage = - entries.reduce((accumulator, [tankIdString, stats]) => { - const tankId = parseInt(tankIdString); + (await entries.reduce>( + async (accumulator, [tankIdString, stats]) => { + const tankId = parseInt(tankIdString); - if (tankopedia[tankId]?.tier === 10) { - const tankStats = tankStatsOverTime[tankId]; - return accumulator + tankStats.damage_dealt; - } else return accumulator; - }, 0) / - entries.reduce((accumulator, [tankIdString, stats]) => { - const tankId = parseInt(tankIdString); + if ((await tankopedia)[tankId]?.tier === 10) { + const tankStats = tankStatsOverTime[tankId]; + return (await accumulator) + tankStats.damage_dealt; + } else return accumulator; + }, + 0, + )) / + (await entries.reduce>( + async (accumulator, [tankIdString, stats]) => { + const tankId = parseInt(tankIdString); - if (tankopedia[tankId]?.tier === 10) { - const tankStats = tankStatsOverTime[tankId]; - return accumulator + tankStats.battles; - } else return accumulator; - }, 0); + if ((await tankopedia)[tankId]?.tier === 10) { + const tankStats = tankStatsOverTime[tankId]; + return (await accumulator) + tankStats.battles; + } else return accumulator; + }, + 0, + )); if (stats.battles < 126) { problems.push(['Battles', `${stats.battles} (${stats.battles - 126})`]); diff --git a/src/commands/evolution.tsx b/src/commands/evolution.tsx index 2e467e769..3187aab66 100644 --- a/src/commands/evolution.tsx +++ b/src/commands/evolution.tsx @@ -36,7 +36,7 @@ export const evolutionCommand: CommandRegistry = { const player = await resolvePlayerFromCommand(interaction); const period = resolvePeriodFromCommand(interaction); const tankIdRaw = interaction.options.getString('tank')!; - const tankId = commandGroup === 'tank' ? resolveTankId(tankIdRaw) : null; + const tankId = commandGroup === 'tank' ? await resolveTankId(tankIdRaw) : null; const start = interaction.options.getInteger('start'); const end = interaction.options.getInteger('end'); const { nickname } = ( diff --git a/src/commands/help.ts b/src/commands/help.ts index 408fe78b7..164acd3df 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -10,7 +10,7 @@ import { export const helpCommand: CommandRegistry = { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() diff --git a/src/commands/inactive.tsx b/src/commands/inactive.tsx index 987f6568d..0dc891f13 100644 --- a/src/commands/inactive.tsx +++ b/src/commands/inactive.tsx @@ -18,7 +18,7 @@ const DEFAULT_THRESHOLD = 7; export const inactiveCommand: CommandRegistry = { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() diff --git a/src/commands/ownedTanks.tsx b/src/commands/ownedTanks.tsx index 66dd7e816..2d63ca6bd 100644 --- a/src/commands/ownedTanks.tsx +++ b/src/commands/ownedTanks.tsx @@ -43,7 +43,7 @@ const COMP_TANKS = [ export const ownedTanksCommand: CommandRegistry = { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() @@ -77,9 +77,11 @@ export const ownedTanksCommand: CommandRegistry = { `https://api.wotblitz.${server}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`, ); const tankStats = await getTankStats(server, id); - const tanks = tankStats - .map((tankData) => tankopedia[tankData.tank_id]) - .filter((tank) => tank?.tier === tier); + const tanks = ( + await Promise.all( + tankStats.map(async (tankData) => (await tankopedia)[tankData.tank_id]), + ) + ).filter((tank) => tank?.tier === tier); const clanData = await getWargamingResponse( `https://api.wotblitz.${server}/wotb/clans/accountinfo/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}&extra=clan`, ); diff --git a/src/commands/ping.ts b/src/commands/ping.ts index 71e2bde94..bcaa52371 100644 --- a/src/commands/ping.ts +++ b/src/commands/ping.ts @@ -3,7 +3,7 @@ import { CommandRegistry } from '../events/interactionCreate/index.js'; export const pingCommand: CommandRegistry = { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, handlesInteraction: true, diff --git a/src/commands/playerAchievements.ts b/src/commands/playerAchievements.ts index a0a6d41d9..fcd9c9a75 100644 --- a/src/commands/playerAchievements.ts +++ b/src/commands/playerAchievements.ts @@ -18,7 +18,7 @@ type SortBy = 'name' | 'count'; export const playerAchievementsCommand: CommandRegistry = { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() diff --git a/src/commands/playerInfo.ts b/src/commands/playerInfo.ts index d33e2f06a..67ddcf1fa 100644 --- a/src/commands/playerInfo.ts +++ b/src/commands/playerInfo.ts @@ -12,7 +12,7 @@ import { AccountInfo } from '../types/accountInfo.js'; export const playerInfoCommand: CommandRegistry = { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() diff --git a/src/commands/searchClans.ts b/src/commands/searchClans.ts index 64980acde..18bdc8f00 100644 --- a/src/commands/searchClans.ts +++ b/src/commands/searchClans.ts @@ -11,7 +11,7 @@ import { ClanList } from '../types/clanList.js'; export const searchClansCommand: CommandRegistry = { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() diff --git a/src/commands/searchPlayers.ts b/src/commands/searchPlayers.ts index 4db2f37e4..870342c7a 100644 --- a/src/commands/searchPlayers.ts +++ b/src/commands/searchPlayers.ts @@ -12,7 +12,7 @@ import { AccountList } from '../types/accountList.js'; export const searchPlayersCommand: CommandRegistry = { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() diff --git a/src/commands/searchTanks.ts b/src/commands/searchTanks.ts index 1bb160254..144d2f54a 100644 --- a/src/commands/searchTanks.ts +++ b/src/commands/searchTanks.ts @@ -8,7 +8,7 @@ import { CommandRegistry } from '../events/interactionCreate/index.js'; export const searchTanksCommand: CommandRegistry = { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() diff --git a/src/commands/stats.tsx b/src/commands/stats.tsx index 45702853b..9a8e4e59f 100644 --- a/src/commands/stats.tsx +++ b/src/commands/stats.tsx @@ -36,7 +36,8 @@ export const statsCommand: CommandRegistry = { const player = await resolvePlayerFromCommand(interaction); const period = resolvePeriodFromCommand(interaction); const tankIdRaw = interaction.options.getString('tank')!; - const tankId = commandGroup === 'tank' ? resolveTankId(tankIdRaw) : null; + const tankId = + commandGroup === 'tank' ? await resolveTankId(tankIdRaw) : null; const start = interaction.options.getInteger('start'); const end = interaction.options.getInteger('end'); const path = interactionToURL(interaction, { diff --git a/src/commands/statsFull.tsx b/src/commands/statsFull.tsx index 501e6e511..180cc59f6 100644 --- a/src/commands/statsFull.tsx +++ b/src/commands/statsFull.tsx @@ -19,7 +19,7 @@ import { AccountInfo } from '../types/accountInfo.js'; export const statsFullCommand: CommandRegistry = { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: addStatTypeSubCommandGroups( @@ -35,7 +35,8 @@ export const statsFullCommand: CommandRegistry = { const player = await resolvePlayerFromCommand(interaction); const period = resolvePeriodFromCommand(interaction); const tankIdRaw = interaction.options.getString('tank')!; - const tankId = commandGroup === 'tank' ? resolveTankId(tankIdRaw) : null; + const tankId = + commandGroup === 'tank' ? await resolveTankId(tankIdRaw) : null; const start = interaction.options.getInteger('start'); const end = interaction.options.getInteger('end'); const path = interactionToURL(interaction, { diff --git a/src/commands/today.tsx b/src/commands/today.tsx index d2a166afd..613014928 100644 --- a/src/commands/today.tsx +++ b/src/commands/today.tsx @@ -14,7 +14,7 @@ import { AccountInfo } from '../types/accountInfo.js'; export const todayCommand: CommandRegistry = { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() diff --git a/src/commands/verify.ts b/src/commands/verify.ts index c3cfb4b59..0dc4aa4a5 100644 --- a/src/commands/verify.ts +++ b/src/commands/verify.ts @@ -14,7 +14,7 @@ import { PlayerClanData } from '../types/playerClanData.js'; export const verifyCommand: CommandRegistry = { inProduction: true, - inDevelopment: false, + inDevelopment: true, inPublic: true, command: new SlashCommandBuilder() diff --git a/src/core/blitz/resolveTankId.ts b/src/core/blitz/resolveTankId.ts index 89da65c1d..ddbe33b66 100644 --- a/src/core/blitz/resolveTankId.ts +++ b/src/core/blitz/resolveTankId.ts @@ -2,7 +2,7 @@ import { go } from 'fuzzysort'; import throwError from '../node/throwError.js'; import { TANKS, tankopedia } from './tankopedia.js'; -export default function resolveTankId(tank: string) { +export default async function resolveTankId(tank: string) { const number = parseInt(tank); if (Number.isNaN(number)) { @@ -17,7 +17,7 @@ export default function resolveTankId(tank: string) { return searchResult[0].obj.tank_id; } } else { - if (tankopedia[number]) { + if ((await tankopedia)[number]) { return number; } else { throw throwError( diff --git a/src/core/blitz/resolveTankName.ts b/src/core/blitz/resolveTankName.ts index 2f97fdb7f..51ca38cea 100644 --- a/src/core/blitz/resolveTankName.ts +++ b/src/core/blitz/resolveTankName.ts @@ -1,6 +1,6 @@ import { tankopedia } from './tankopedia.js'; -export default function resolveTankName(tankId: number) { - const tankopediaName = tankopedia[tankId].name; +export default async function resolveTankName(tankId: number) { + const tankopediaName = (await tankopedia)[tankId].name; return tankopediaName ? tankopediaName : `Unknown Tank ${tankId}`; } diff --git a/src/core/blitz/tankopedia.ts b/src/core/blitz/tankopedia.ts index 6e0b2678e..981a59002 100644 --- a/src/core/blitz/tankopedia.ts +++ b/src/core/blitz/tankopedia.ts @@ -1,6 +1,3 @@ -import { readFileSync } from 'fs'; -import { join } from 'path'; - export type TankType = 'AT-SPG' | 'lightTank' | 'mediumTank' | 'heavyTank'; export interface TankopediaEntry { @@ -19,11 +16,13 @@ export interface Tankopedia { [id: number]: TankopediaEntry; } -export const tankopedia = ( - JSON.parse( - readFileSync(join(__dirname, 'tankopedia.json')) as unknown as string, - ) as { data: Tankopedia } -).data; +console.log('Caching tankopedia...'); +export const tankopedia = fetch('https://www.blitzstars.com/bs-tankopedia.json') + .then((response) => response.json()) + .then((wrapperTankopedia) => { + console.log('Tankopedia cached'); + return (wrapperTankopedia as { data: Tankopedia }).data; + }); const entries = Object.entries(tankopedia); export const TANK_IDS = entries.map(([, { tank_id }]) => tank_id as number); export const TANKS = entries.map(([, entry]) => entry as TankopediaEntry); diff --git a/src/core/blitzstars/playerAverage.ts b/src/core/blitzstars/playerAverage.ts index a2315adb1..f2206d83c 100644 --- a/src/core/blitzstars/playerAverage.ts +++ b/src/core/blitzstars/playerAverage.ts @@ -3,7 +3,7 @@ import { emptyAllStats } from './getTankStatsDiffed.js'; import { tankAverages } from './tankAverages.js'; console.log('Calculating player average...'); -export const playerAverage = Object.entries(tankAverages).reduce( +export const playerAverage = Object.entries(await tankAverages).reduce( (accumulator, [, tankAverage]) => { return sumStats([accumulator, tankAverage.all]); }, diff --git a/src/core/blitzstars/tankAverages.ts b/src/core/blitzstars/tankAverages.ts index b5858a13b..84733e336 100644 --- a/src/core/blitzstars/tankAverages.ts +++ b/src/core/blitzstars/tankAverages.ts @@ -1,5 +1,3 @@ -import { readFileSync } from 'fs'; -import { join } from 'path'; import { AllStats } from '../../types/accountInfo.js'; export interface SpecialStats { @@ -82,6 +80,22 @@ export interface IndividualTankAverage { export type TankAverages = Record; -export const tankAverages = JSON.parse( - readFileSync(join(__dirname, 'tankaverages.json')) as unknown as string, -) as TankAverages; +console.log('Caching tank averages...'); +export const tankAverages = fetch( + 'https://www.blitzstars.com/api/tankaverages.json', +) + .then((response) => response.json()) + .then((individualTankAverages) => { + const partialTankAverages: TankAverages = {}; + + (individualTankAverages as IndividualTankAverage[]).forEach( + (individualTankAverage) => { + partialTankAverages[individualTankAverage.tank_id] = + individualTankAverage; + }, + ); + + console.log('Tank averages cached'); + + return partialTankAverages; + }); diff --git a/src/core/discord/autocompleteTanks.ts b/src/core/discord/autocompleteTanks.ts index 8b45d8022..46fa638bc 100644 --- a/src/core/discord/autocompleteTanks.ts +++ b/src/core/discord/autocompleteTanks.ts @@ -15,14 +15,16 @@ export default async function autocompleteTanks( await interaction.respond( focusedOption.value - ? go(focusedOption.value, TANKS, { keys: ['name'], limit: 10 }).map( - (item) => - ({ - name: item.obj.name - ? item.obj.name - : resolveTankName(item.obj.tank_id), - value: `${item.obj.tank_id}`, - } satisfies ApplicationCommandOptionChoiceData), + ? await Promise.all( + go(focusedOption.value, TANKS, { keys: ['name'], limit: 10 }).map( + async (item) => + ({ + name: item.obj.name + ? item.obj.name + : await resolveTankName(item.obj.tank_id), + value: `${item.obj.tank_id}`, + } satisfies ApplicationCommandOptionChoiceData), + ), ) : [], ); diff --git a/src/renderers/evolution.tsx b/src/renderers/evolution.tsx index 0ccac742f..153d1a60b 100644 --- a/src/renderers/evolution.tsx +++ b/src/renderers/evolution.tsx @@ -38,8 +38,8 @@ export default async function evolution( ? `https://wotblitz-gc.gcdn.co/icons/clanEmblems1x/clan-icon-v2-${clan.emblem_set_id}.png` : undefined; } else { - nameDiscriminator = `(${resolveTankName(tankId!)})`; - image = tankopedia[tankId!].images.normal; + nameDiscriminator = `(${await resolveTankName(tankId!)})`; + image = (await tankopedia)[tankId!].images.normal; } let histories: Histories; diff --git a/src/renderers/stats.tsx b/src/renderers/stats.tsx index b11137e8d..03e0ef12f 100644 --- a/src/renderers/stats.tsx +++ b/src/renderers/stats.tsx @@ -22,6 +22,7 @@ import { SupplementaryStats, } from '../types/accountInfo.js'; import { PlayerClanData } from '../types/playerClanData.js'; +import { PossiblyPromise } from '../types/possiblyPromise.js'; export type StatType = 'player' | 'tank'; @@ -47,8 +48,8 @@ export default async function stats( ? `https://wotblitz-gc.gcdn.co/icons/clanEmblems1x/clan-icon-v2-${clan.emblem_set_id}.png` : undefined; } else if (type === 'tank') { - nameDiscriminator = `(${resolveTankName(tankId!)})`; - image = tankopedia[tankId!].images.normal; + nameDiscriminator = `(${await resolveTankName(tankId!)})`; + image = (await tankopedia)[tankId!].images.normal; } const tankStats = await getTankStatsDiffed(server, id, start, end); @@ -59,54 +60,61 @@ export default async function stats( if (type === 'player') { const entries = Object.entries(tankStats); stats = sumStats(entries.map(([, stats]) => stats)); - const battlesOfTanksWithAverages = entries.reduce( - (accumulator, [tankIdString, stats]) => { - const tankId = parseInt(tankIdString); - const tankAverage = tankAverages[tankId]; + const battlesOfTanksWithAverages = await entries.reduce< + PossiblyPromise + >(async (accumulator, [tankIdString, stats]) => { + const tankId = parseInt(tankIdString); + const tankAverage = (await tankAverages)[tankId]; - return tankAverage ? accumulator + stats.battles : accumulator; - }, - 0, - ); - const battlesOfTanksWithTankopediaEntry = entries.reduce( - (accumulator, [tankIdString, stats]) => { - const tankId = parseInt(tankIdString); - const tankopediaEntry = tankopedia[tankId]; + return tankAverage ? (await accumulator) + stats.battles : accumulator; + }, 0); + const battlesOfTanksWithTankopediaEntry = await entries.reduce< + PossiblyPromise + >(async (accumulator, [tankIdString, stats]) => { + const tankId = parseInt(tankIdString); + const tankopediaEntry = (await tankopedia)[tankId]; - return tankopediaEntry ? accumulator + stats.battles : accumulator; - }, - 0, - ); + return tankopediaEntry + ? (await accumulator) + stats.battles + : accumulator; + }, 0); supplementaryStats = { WN8: - entries.reduce((accumulator, [tankIdString, stats]) => { - const tankId = parseInt(tankIdString); - const tankAverage = tankAverages[tankId]; + (await entries.reduce>( + async (accumulator, [tankIdString, stats]) => { + const tankId = parseInt(tankIdString); + const tankAverage = (await tankAverages)[tankId]; - return tankAverage - ? accumulator + calculateWN8(tankAverage.all, stats) * stats.battles - : accumulator; - }, 0) / battlesOfTanksWithAverages, + return tankAverage + ? (await accumulator) + + calculateWN8(tankAverage.all, stats) * stats.battles + : accumulator; + }, + 0, + )) / battlesOfTanksWithAverages, tier: - entries.reduce((accumulator, [tankIdString, stats]) => { - const tankId = parseInt(tankIdString); - const tankopediaEntry = tankopedia[tankId]; + (await entries.reduce>( + async (accumulator, [tankIdString, stats]) => { + const tankId = parseInt(tankIdString); + const tankopediaEntry = (await tankopedia)[tankId]; - return tankopediaEntry - ? accumulator + tankopediaEntry.tier * stats.battles - : accumulator; - }, 0) / battlesOfTanksWithTankopediaEntry, + return tankopediaEntry + ? (await accumulator) + tankopediaEntry.tier * stats.battles + : accumulator; + }, + 0, + )) / battlesOfTanksWithTankopediaEntry, }; - tierWeights = entries.reduce( - (accumulator, [tankIdString, stats]) => { + tierWeights = await entries.reduce>( + async (accumulator, [tankIdString, stats]) => { const tankId = parseInt(tankIdString); - const tier = tankopedia[tankId].tier as Tier; + const tier = (await tankopedia)[tankId].tier as Tier; - if (accumulator[tier]) { - accumulator[tier]! += stats.battles; + if ((await accumulator)[tier]) { + (await accumulator)[tier]! += stats.battles; } else { - accumulator[tier] = stats.battles; + (await accumulator)[tier] = stats.battles; } return accumulator; @@ -118,9 +126,9 @@ export default async function stats( supplementaryStats = { WN8: stats - ? calculateWN8(tankAverages[tankId!].all, tankStats[tankId!]) + ? calculateWN8((await tankAverages)[tankId!].all, tankStats[tankId!]) : undefined, - tier: tankopedia[tankId!].tier, + tier: (await tankopedia)[tankId!].tier, }; } diff --git a/src/renderers/statsfull.tsx b/src/renderers/statsfull.tsx index a5617a208..1c867f9f9 100644 --- a/src/renderers/statsfull.tsx +++ b/src/renderers/statsfull.tsx @@ -21,6 +21,7 @@ import { SupplementaryStats, } from '../types/accountInfo.js'; import { PlayerClanData } from '../types/playerClanData.js'; +import { PossiblyPromise } from '../types/possiblyPromise.js'; export type StatType = 'player' | 'tank'; @@ -45,8 +46,8 @@ export default async function statsfull( ? `https://wotblitz-gc.gcdn.co/icons/clanEmblems1x/clan-icon-v2-${clan.emblem_set_id}.png` : undefined; } else if (type === 'tank') { - nameDiscriminator = `(${resolveTankName(tankId!)})`; - image = tankopedia[tankId!].images.normal; + nameDiscriminator = `(${await resolveTankName(tankId!)})`; + image = (await tankopedia)[tankId!].images.normal; } const tankStats = await getTankStatsDiffed(server, id, start, end); @@ -57,54 +58,61 @@ export default async function statsfull( if (type === 'player') { const entries = Object.entries(tankStats); stats = sumStats(entries.map(([, stats]) => stats)); - const battlesOfTanksWithAverages = entries.reduce( - (accumulator, [tankIdString, stats]) => { - const tankId = parseInt(tankIdString); - const tankAverage = tankAverages[tankId]; + const battlesOfTanksWithAverages = await entries.reduce< + PossiblyPromise + >(async (accumulator, [tankIdString, stats]) => { + const tankId = parseInt(tankIdString); + const tankAverage = (await tankAverages)[tankId]; - return tankAverage ? accumulator + stats.battles : accumulator; - }, - 0, - ); - const battlesOfTanksWithTankopediaEntry = entries.reduce( - (accumulator, [tankIdString, stats]) => { - const tankId = parseInt(tankIdString); - const tankopediaEntry = tankopedia[tankId]; + return tankAverage ? (await accumulator) + stats.battles : accumulator; + }, 0); + const battlesOfTanksWithTankopediaEntry = await entries.reduce< + PossiblyPromise + >(async (accumulator, [tankIdString, stats]) => { + const tankId = parseInt(tankIdString); + const tankopediaEntry = (await tankopedia)[tankId]; - return tankopediaEntry ? accumulator + stats.battles : accumulator; - }, - 0, - ); + return tankopediaEntry + ? (await accumulator) + stats.battles + : accumulator; + }, 0); supplementaryStats = { WN8: - entries.reduce((accumulator, [tankIdString, stats]) => { - const tankId = parseInt(tankIdString); - const tankAverage = tankAverages[tankId]; + (await entries.reduce>( + async (accumulator, [tankIdString, stats]) => { + const tankId = parseInt(tankIdString); + const tankAverage = (await tankAverages)[tankId]; - return tankAverage - ? accumulator + calculateWN8(tankAverage.all, stats) * stats.battles - : accumulator; - }, 0) / battlesOfTanksWithAverages, + return tankAverage + ? (await accumulator) + + calculateWN8(tankAverage.all, stats) * stats.battles + : accumulator; + }, + 0, + )) / battlesOfTanksWithAverages, tier: - entries.reduce((accumulator, [tankIdString, stats]) => { - const tankId = parseInt(tankIdString); - const tankopediaEntry = tankopedia[tankId]; + (await entries.reduce>( + async (accumulator, [tankIdString, stats]) => { + const tankId = parseInt(tankIdString); + const tankopediaEntry = (await tankopedia)[tankId]; - return tankopediaEntry - ? accumulator + tankopediaEntry.tier * stats.battles - : accumulator; - }, 0) / battlesOfTanksWithTankopediaEntry, + return tankopediaEntry + ? (await accumulator) + tankopediaEntry.tier * stats.battles + : accumulator; + }, + 0, + )) / battlesOfTanksWithTankopediaEntry, }; - tierWeights = entries.reduce( - (accumulator, [tankIdString, stats]) => { + tierWeights = await entries.reduce>( + async (accumulator, [tankIdString, stats]) => { const tankId = parseInt(tankIdString); - const tier = tankopedia[tankId].tier as Tier; + const tier = (await tankopedia)[tankId].tier as Tier; - if (accumulator[tier]) { - accumulator[tier]! += stats.battles; + if ((await accumulator)[tier]) { + (await accumulator)[tier]! += stats.battles; } else { - accumulator[tier] = stats.battles; + (await accumulator)[tier] = stats.battles; } return accumulator; @@ -115,8 +123,8 @@ export default async function statsfull( stats = tankStats[tankId!]; supplementaryStats = { - WN8: calculateWN8(tankAverages[tankId!].all, tankStats[tankId!]), - tier: tankopedia[tankId!].tier, + WN8: calculateWN8((await tankAverages)[tankId!].all, tankStats[tankId!]), + tier: (await tankopedia)[tankId!].tier, }; } diff --git a/src/renderers/today.tsx b/src/renderers/today.tsx index 021274e04..cd7f99a04 100644 --- a/src/renderers/today.tsx +++ b/src/renderers/today.tsx @@ -18,6 +18,7 @@ import { ResolvedPlayer } from '../core/discord/resolvePlayerFromCommand.js'; import { WARGAMING_APPLICATION_ID } from '../core/node/arguments.js'; import { AccountInfo, AllStats } from '../types/accountInfo.js'; import { PlayerClanData } from '../types/playerClanData.js'; +import { PossiblyPromise } from '../types/possiblyPromise.js'; export default async function today({ server, id }: ResolvedPlayer) { const tankStatsOverTime = await getTankStatsDiffed( @@ -52,33 +53,31 @@ export default async function today({ server, id }: ResolvedPlayer) { } const tankStatsOverTimeEntries = Object.entries(tankStatsOverTime); - const todayWN8s = tankStatsOverTimeEntries.reduce>( - (accumulator, [tankIdString, tankStats]) => { - const tankId = Number(tankIdString); + const todayWN8s = await tankStatsOverTimeEntries.reduce< + PossiblyPromise> + >(async (accumulator, [tankIdString, tankStats]) => { + const tankId = Number(tankIdString); - return tankId === 0 || tankAverages[tankId] === undefined - ? accumulator - : { - ...accumulator, - [tankId]: calculateWN8(tankAverages[tankId].all, tankStats), - }; - }, - {}, - ); - const careerWN8s = careerTankStatsRaw.reduce>( - (accumulator, { tank_id }) => { - return tank_id === 0 || tankAverages[tank_id] === undefined - ? accumulator - : { - ...accumulator, - [tank_id]: calculateWN8( - tankAverages[tank_id].all, - careerStats[tank_id], - ), - }; - }, - {}, - ); + return tankId === 0 || (await tankAverages)[tankId] === undefined + ? accumulator + : { + ...accumulator, + [tankId]: calculateWN8((await tankAverages)[tankId].all, tankStats), + }; + }, {}); + const careerWN8s = await careerTankStatsRaw.reduce< + PossiblyPromise> + >(async (accumulator, { tank_id }) => { + return tank_id === 0 || (await tankAverages)[tank_id] === undefined + ? accumulator + : { + ...accumulator, + [tank_id]: calculateWN8( + (await tankAverages)[tank_id].all, + careerStats[tank_id], + ), + }; + }, {}); const todayWN8sEntries = Object.entries(todayWN8s); const careerWN8sEntries = Object.entries(careerWN8s); @@ -109,32 +108,37 @@ export default async function today({ server, id }: ResolvedPlayer) { 0, ); - const rows = tankStatsOverTimeEntries.map(([tankIdString, tankStats]) => { - const tankId = Number(tankIdString); - const career = careerStats[tankId]; + const rows = await Promise.all( + tankStatsOverTimeEntries.map(async ([tankIdString, tankStats]) => { + const tankId = Number(tankIdString); + const career = careerStats[tankId]; - return ( - - ); - }); + return ( + + ); + }), + ); return ( diff --git a/src/routes/stats.tsx b/src/routes/stats.tsx index 71cd12053..43216240d 100644 --- a/src/routes/stats.tsx +++ b/src/routes/stats.tsx @@ -6,7 +6,7 @@ import { RouteRegistry } from '../server.js'; export const statsRoute: RouteRegistry = { route: '/stats/:type/:period', inProduction: true, - inDevelopment: false, + inDevelopment: true, async handler(req) { const type = req.params.type as StatType; diff --git a/src/types/possiblyPromise.ts b/src/types/possiblyPromise.ts new file mode 100644 index 000000000..005f03fa7 --- /dev/null +++ b/src/types/possiblyPromise.ts @@ -0,0 +1 @@ +export type PossiblyPromise = Promise | Type; \ No newline at end of file