diff --git a/.vscode/settings.json b/.vscode/settings.json index ce9ffc450..7ccf745d0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -28,6 +28,7 @@ "playerinfo", "ratingsleaderboard", "ratingsplot", + "researchable", "Resvg", "roboto", "searchclans", diff --git a/package.json b/package.json index 43982a098..1605e113d 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "build:website": "next build", "build:docs": "vitepress build docs", "build:ratingsleaderboard": "vite-node --script scripts/buildRatingsLeaderboard", - "build:tankopedia": "vite-node --script scripts/buildTankopedia", + "build:assets": "vite-node --script scripts/buildAssets", "build:ratingsplot": "vite-node --script scripts/buildRatingsPlot", "dev:bot": "yarn build:bot && yarn start:bot", "dev:docs": "vitepress dev docs", diff --git a/scripts/buildTankopedia.ts b/scripts/buildAssets.ts similarity index 54% rename from scripts/buildTankopedia.ts rename to scripts/buildAssets.ts index 56dc51b30..e8604ba44 100644 --- a/scripts/buildTankopedia.ts +++ b/scripts/buildAssets.ts @@ -2,13 +2,16 @@ import { Octokit } from '@octokit/rest'; import decompress from 'decompress'; import { config } from 'dotenv'; import { writeFileSync } from 'fs'; -import { cp, mkdir, readFile, readdir, rm, writeFile } from 'fs/promises'; +import { readFile, readdir, rm } from 'fs/promises'; import { load } from 'js-yaml'; import { argv, env } from 'process'; import { ElementCompact, xml2js } from 'xml-js'; import { parse } from 'yaml'; import { NATION_IDS } from '../src/constants/nations'; -import { BlitzkriegTankopedia, Tier } from '../src/core/blitzkrieg/tankopedia'; +import { + TankDefinitions, + Tier, +} from '../src/core/blitzkrieg/definitions/tanks'; import commitMultipleFiles, { FileChange } from './commitMultipleFiles'; config(); @@ -34,27 +37,19 @@ const directoriesOfInterest = { }; const directoriesOfInterestArray = Object.values(directoriesOfInterest); -console.log('Removing old tankopedia files...'); -await rm('dist/tankopedia', { recursive: true, force: true }); if (!noRewrite) { - console.log('Removing old temp files...'); await rm(TEMP, { recursive: true, force: true }); - - console.log('Extracting Blitz files...'); await decompress(apkFile, TEMP, { filter: (file) => directoriesOfInterestArray.some((dir) => file.path.startsWith(dir)), }); } -console.log('Creating new tankopedia folder'); -await mkdir('dist/tankopedia'); - const strings = await readFile( `${TEMP}/${directoriesOfInterest.strings}/${LANGUAGE}.yaml`, 'utf-8', ).then((data) => load(data) as Record); -const tankopedia: BlitzkriegTankopedia = {}; +const tankDefinitions: TankDefinitions = {}; const tankIds: number[] = []; const images: Record = {}; const nations = await readdir( @@ -76,7 +71,6 @@ Promise.all( await Promise.all( Object.entries(list.root).map( async ([vehicle, vehicleData]) => { - // Tankopedia const nationVehicleId = parseInt(list.root[vehicle].id._text); const id = (nationVehicleId << 8) + (NATION_IDS[nation] << 4) + 1; const name = strings[vehicleData.userString._text]; @@ -94,7 +88,7 @@ Promise.all( } tankIds.push(id); - tankopedia[id] = { + tankDefinitions[id] = { id, name, name_short, @@ -121,101 +115,91 @@ Promise.all( .replace(/~res:\//, '') .replace(/\..+/, '')}.packed.webp`, }; - - if (!publish) { - cp(images[id].small, `dist/tankopedia/icons/small/${id}.webp`); - cp(images[id].big, `dist/tankopedia/icons/big/${id}.webp`); - } }, ), ); }), ).then(async () => { - if (publish) { - const octokit = new Octokit({ auth: env.GH_TOKEN }); - // const tankopediaChange: FileChange = { - // content: JSON.stringify(tankopedia), - // path: 'tankopedia.json', - // encoding: 'utf-8', - // }; - // const iconsChange = ( - // await Promise.all( - // tankIds.map(async (id) => { - // try { - // const [contentSmall, contentBig] = await Promise.all([ - // readFile(images[id].small, { encoding: 'base64' }), - // readFile(images[id].big, { encoding: 'base64' }), - // ]); + if (!publish) return; - // return [ - // { - // content: contentBig, - // path: `icons/big/${id}.webp`, - // encoding: 'base64', - // }, - // { - // content: contentSmall, - // path: `icons/small/${id}.webp`, - // encoding: 'base64', - // }, - // ]; - // } catch (error) { - // console.log(error); - // return undefined; - // } - // }), - // ) - // ).flat() as FileChange[]; - const flags = await readdir(`${TEMP}/${directoriesOfInterest.flags}`); - // const scratchedFlags = await Promise.all( - // flags - // .filter((flag) => flag.startsWith('flag_tutor-tank_')) - // .map(async (flag) => { - // const content = await readFile( - // `${TEMP}/${directoriesOfInterest.flags}/${flag}`, - // { encoding: 'base64' }, - // ); - // const name = flag.match(/flag_tutor-tank_(.+)\.packed\.webp/)![1]; + const octokit = new Octokit({ auth: env.GH_TOKEN }); + // const tankDefinitionsChange: FileChange = { + // content: JSON.stringify(tankDefinitions), + // path: 'definitions/tanks.json', + // encoding: 'utf-8', + // }; + // const iconsChange = ( + // await Promise.all( + // tankIds.map(async (id) => { + // try { + // const [contentSmall, contentBig] = await Promise.all([ + // readFile(images[id].small, { encoding: 'base64' }), + // readFile(images[id].big, { encoding: 'base64' }), + // ]); - // return { - // content, - // encoding: 'base64', - // path: `flags/scratched/${name}.webp`, - // } satisfies FileChange; - // }), - // ); - const circleFlags = await Promise.all( - flags - .filter((flag) => flag.startsWith('flag_profile-stat_')) - .map(async (flag) => { - const content = await readFile( - `${TEMP}/${directoriesOfInterest.flags}/${flag}`, - { encoding: 'base64' }, - ); - const name = flag.match(/flag_profile-stat_(.+)\.packed\.webp/)![1]; + // return [ + // { + // content: contentBig, + // path: `icons/big/${id}.webp`, + // encoding: 'base64', + // }, + // { + // content: contentSmall, + // path: `icons/small/${id}.webp`, + // encoding: 'base64', + // }, + // ]; + // } catch (error) { + // console.log(error); + // return undefined; + // } + // }), + // ) + // ).flat() as FileChange[]; + const flags = await readdir(`${TEMP}/${directoriesOfInterest.flags}`); + // const scratchedFlags = await Promise.all( + // flags + // .filter((flag) => flag.startsWith('flag_tutor-tank_')) + // .map(async (flag) => { + // const content = await readFile( + // `${TEMP}/${directoriesOfInterest.flags}/${flag}`, + // { encoding: 'base64' }, + // ); + // const name = flag.match(/flag_tutor-tank_(.+)\.packed\.webp/)![1]; - return { - content, - encoding: 'base64', - path: `flags/circle/${name}.webp`, - } satisfies FileChange; - }), - ); + // return { + // content, + // encoding: 'base64', + // path: `flags/scratched/${name}.webp`, + // } satisfies FileChange; + // }), + // ); + const circleFlags = await Promise.all( + flags + .filter((flag) => flag.startsWith('flag_profile-stat_')) + .map(async (flag) => { + const content = await readFile( + `${TEMP}/${directoriesOfInterest.flags}/${flag}`, + { encoding: 'base64' }, + ); + const name = flag.match(/flag_profile-stat_(.+)\.packed\.webp/)![1]; - console.log('Writing files...'); - await commitMultipleFiles( - octokit, - 'tresabhi', - 'blitzkrieg-assets', - 'main', - new Date().toString(), - circleFlags, - true, - ); - } else { - writeFile( - 'dist/tankopedia/tankopedia.json', - JSON.stringify(tankopedia, null, 2), - ); - } + return { + content, + encoding: 'base64', + path: `flags/circle/${name}.webp`, + } satisfies FileChange; + }), + ); + + console.log('Writing files...'); + await commitMultipleFiles( + octokit, + 'tresabhi', + 'blitzkrieg-assets', + 'main', + new Date().toString(), + circleFlags, + true, + ); }); diff --git a/src/app/embeds/session/page.tsx b/src/app/embeds/session/page.tsx index e722836a5..7d50336d0 100644 --- a/src/app/embeds/session/page.tsx +++ b/src/app/embeds/session/page.tsx @@ -7,9 +7,9 @@ import { TreeTypeEnum } from '../../../components/Tanks'; import { WARGAMING_APPLICATION_ID } from '../../../constants/wargamingApplicationID'; import fetchBlitz from '../../../core/blitz/fetchBlitz'; import { - BlitzkriegTankopediaEntry, - tankopedia, -} from '../../../core/blitzkrieg/tankopedia'; + TankDefinition, + tankDefinitions, +} from '../../../core/blitzkrieg/definitions/tanks'; import { tankAverages } from '../../../core/blitzstars/tankAverages'; import calculateWN8 from '../../../core/statistics/calculateWN8'; import { deltaTankStats } from '../../../core/statistics/deltaTankStats'; @@ -30,7 +30,7 @@ export default function SessionPage() { list: { stats: IndividualTankStats; - tankopedia?: BlitzkriegTankopediaEntry; + tankDefinitions?: TankDefinition; career: IndividualTankStats; currentWN8?: number; careerWN8?: number; @@ -88,7 +88,7 @@ export default function SessionPage() { }), {}, ); - const awaitedTankopedia = await tankopedia; + const awaitedTankDefinitions = await tankDefinitions; const awaitedTankAverages = await tankAverages; const careerWN8 = careerRaw[id].reduce( @@ -119,7 +119,7 @@ export default function SessionPage() { ).map((stats) => { return { stats, - tankopedia: awaitedTankopedia[stats.tank_id], + tankDefinitions: awaitedTankDefinitions[stats.tank_id], career: career[stats.tank_id], currentWN8: awaitedTankAverages[stats.tank_id] ? calculateWN8( @@ -238,95 +238,97 @@ export default function SessionPage() { .sort( (a, b) => b.stats.last_battle_time - a.stats.last_battle_time, ) - .map(({ stats, tankopedia, career, careerWN8, currentWN8 }) => { - const rowStats: Record< - CustomColumnDisplay, - Breakdown.RowStatItem | undefined - > = { - battles: { - title: 'Battles', - current: stats.all.battles.toLocaleString(), - career: career.all.battles.toLocaleString(), - }, - winrate: { - title: 'Winrate', - current: `${( - 100 * - (stats.all.wins / stats.all.battles) - ).toFixed(2)}%`, - career: `${( - 100 * - (career.all.wins / career.all.battles) - ).toFixed(2)}%`, - delta: - stats.all.wins / stats.all.battles - - career.all.wins / career.all.battles, - }, - wn8: { - title: 'WN8', - current: - currentWN8 === undefined - ? undefined - : Math.round(currentWN8).toLocaleString(), - career: - careerWN8 === undefined - ? undefined - : Math.round(careerWN8).toLocaleString(), - percentile: - currentWN8 === undefined - ? undefined - : getWN8Percentile(currentWN8), - }, - damage: { - title: 'Damage', - current: Math.round( - stats.all.damage_dealt / stats.all.battles, - ).toLocaleString(), - career: Math.round( - career.all.damage_dealt / career.all.battles, - ).toLocaleString(), - delta: - stats.all.damage_dealt / stats.all.battles - - career.all.damage_dealt / career.all.battles, - }, - none: undefined, - }; + .map( + ({ stats, tankDefinitions, career, careerWN8, currentWN8 }) => { + const rowStats: Record< + CustomColumnDisplay, + Breakdown.RowStatItem | undefined + > = { + battles: { + title: 'Battles', + current: stats.all.battles.toLocaleString(), + career: career.all.battles.toLocaleString(), + }, + winrate: { + title: 'Winrate', + current: `${( + 100 * + (stats.all.wins / stats.all.battles) + ).toFixed(2)}%`, + career: `${( + 100 * + (career.all.wins / career.all.battles) + ).toFixed(2)}%`, + delta: + stats.all.wins / stats.all.battles - + career.all.wins / career.all.battles, + }, + wn8: { + title: 'WN8', + current: + currentWN8 === undefined + ? undefined + : Math.round(currentWN8).toLocaleString(), + career: + careerWN8 === undefined + ? undefined + : Math.round(careerWN8).toLocaleString(), + percentile: + currentWN8 === undefined + ? undefined + : getWN8Percentile(currentWN8), + }, + damage: { + title: 'Damage', + current: Math.round( + stats.all.damage_dealt / stats.all.battles, + ).toLocaleString(), + career: Math.round( + career.all.damage_dealt / career.all.battles, + ).toLocaleString(), + delta: + stats.all.damage_dealt / stats.all.battles - + career.all.damage_dealt / career.all.battles, + }, + none: undefined, + }; - return ( - { - if (tankopedia?.tree_type === 'collector') - return TreeTypeEnum.Collector; - if (tankopedia?.tree_type === 'premium') - return TreeTypeEnum.Premium; - })()} - stats={session.customColumns.map((customColumn) => { - const rowStat = rowStats[customColumn.display]; + return ( + { + if (tankDefinitions?.tree_type === 'collector') + return TreeTypeEnum.Collector; + if (tankDefinitions?.tree_type === 'premium') + return TreeTypeEnum.Premium; + })()} + stats={session.customColumns.map((customColumn) => { + const rowStat = rowStats[customColumn.display]; - if (!rowStat) return undefined; + if (!rowStat) return undefined; - return { - ...rowStat, - delta: - customColumn.showDelta && - rowStat.percentile === undefined - ? rowStat.delta - : undefined, - }; - })} - /> - ); - })} + return { + ...rowStat, + delta: + customColumn.showDelta && + rowStat.percentile === undefined + ? rowStat.delta + : undefined, + }; + })} + /> + ); + }, + )} diff --git a/src/app/tools/tankopedia/components/Options.tsx b/src/app/tools/tankopedia/components/Options.tsx index 53e91a419..0b03484d4 100644 --- a/src/app/tools/tankopedia/components/Options.tsx +++ b/src/app/tools/tankopedia/components/Options.tsx @@ -15,7 +15,7 @@ import { NATIONS, TIERS, TIER_ROMAN_NUMERALS, -} from '../../../../core/blitzkrieg/tankopedia'; +} from '../../../../core/blitzkrieg/definitions/tanks'; import mutateTankopedia, { TankopediaSortBy, TankopediaSortDirection, diff --git a/src/app/tools/tankopedia/components/PageTurner.tsx b/src/app/tools/tankopedia/components/PageTurner.tsx index 95d9e8fc2..533268263 100644 --- a/src/app/tools/tankopedia/components/PageTurner.tsx +++ b/src/app/tools/tankopedia/components/PageTurner.tsx @@ -1,12 +1,12 @@ import { CaretLeftIcon, CaretRightIcon } from '@radix-ui/react-icons'; import { Button, Flex, TextField } from '@radix-ui/themes'; import { useEffect, useRef } from 'react'; -import { BlitzkriegTankopediaEntry } from '../../../../core/blitzkrieg/tankopedia'; +import { TankDefinition } from '../../../../core/blitzkrieg/definitions/tanks'; interface PageTurnerProps { page: number; setPage: (page: number) => void; - searchedList: BlitzkriegTankopediaEntry[]; + searchedList: TankDefinition[]; tanksPerPage: number; } diff --git a/src/app/tools/tankopedia/page.tsx b/src/app/tools/tankopedia/page.tsx index 23deba60f..02ececfc3 100644 --- a/src/app/tools/tankopedia/page.tsx +++ b/src/app/tools/tankopedia/page.tsx @@ -7,15 +7,15 @@ import { go } from 'fuzzysort'; import { Suspense, use, useEffect, useMemo, useRef, useState } from 'react'; import PageWrapper from '../../../components/PageWrapper'; import { asset } from '../../../core/blitzkrieg/asset'; -import { tankIcon } from '../../../core/blitzkrieg/tankIcon'; import { - BlitzkriegTankopediaEntry, TANK_ICONS, TANK_ICONS_COLLECTOR, TANK_ICONS_PREMIUM, TIER_ROMAN_NUMERALS, - tanks, -} from '../../../core/blitzkrieg/tankopedia'; + TankDefinition, + tanksDefinitionsArray, +} from '../../../core/blitzkrieg/definitions/tanks'; +import { tankIcon } from '../../../core/blitzkrieg/tankIcon'; import { theme } from '../../../stitches.config'; import { useTankopedia } from '../../../stores/tankopedia'; import { Options } from './components/Options'; @@ -26,7 +26,7 @@ const TANKS_PER_PAGE = 3 * 2 ** 4; export default function Page() { const tankopediaState = useTankopedia(); - const awaitedTanks = use(tanks); + const awaitedTanks = use(tanksDefinitionsArray); const input = useRef(null); const searchableTanks = useMemo( () => @@ -102,7 +102,7 @@ export default function Page() { 'name', 'name_short', 'id', - ] satisfies (keyof BlitzkriegTankopediaEntry)[], + ] satisfies (keyof TankDefinition)[], }).map(({ obj }) => obj), ); } diff --git a/src/commands/breakdown.tsx b/src/commands/breakdown.tsx index 694eb951e..bd843f41e 100644 --- a/src/commands/breakdown.tsx +++ b/src/commands/breakdown.tsx @@ -9,8 +9,8 @@ import { getClanAccountInfo } from '../core/blitz/getClanAccountInfo'; import getTankStats from '../core/blitz/getTankStats'; import getTreeType from '../core/blitz/getTreeType'; import resolveTankName from '../core/blitz/resolveTankName'; +import { tankDefinitions } from '../core/blitzkrieg/definitions/tanks'; import { filtersToDescription } from '../core/blitzkrieg/filtersToDescription'; -import { tankopedia } from '../core/blitzkrieg/tankopedia'; import { getBlitzStarsLinkButton } from '../core/blitzstars/getBlitzStarsLinkButton'; import getStatsInPeriod from '../core/blitzstars/getStatsInPeriod'; import { tankAverages } from '../core/blitzstars/tankAverages'; @@ -44,7 +44,7 @@ async function render( { start, end, name }: ResolvedPeriod, filters: StatFilters, ) { - const awaitedTankopedia = await tankopedia; + const awaitedTankDefinitions = await tankDefinitions; const awaitedTankAverages = await tankAverages; const statsInPeriod = await getStatsInPeriod(region, id, start, end); const { filteredOrder } = await filterStats(statsInPeriod, filters); @@ -183,7 +183,7 @@ async function render( await Promise.all( filteredOrder.map(async (id, index) => { - const tankopediaEntry = awaitedTankopedia[id]; + const tankDefinition = awaitedTankDefinitions[id]; const current = orderedCurrentStats[index]; const career = orderedCareerStats[index]; const currentWN8 = orderedCurrentWN8[index]; @@ -193,8 +193,8 @@ async function render( >( async (accumulator, [tankIdString, stats]) => { const tankId = parseInt(tankIdString); - const tankopediaEntry = (await tankopedia)[tankId]; + const tankDefinition = (await tankDefinitions)[tankId]; - if (!tankopediaEntry) return accumulator; + if (!tankDefinition) return accumulator; - const tankTier = tankopediaEntry.tier; + const tankTier = tankDefinition.tier; return (await accumulator) + tankTier * stats.battles; }, @@ -79,9 +79,9 @@ export const eligibleCommand: CommandRegistry = { (await entries.reduce>( async (accumulator, [tankIdString, stats]) => { const tankId = parseInt(tankIdString); - const tankopediaEntry = (await tankopedia)[tankId]; + const tankDefinition = (await tankDefinitions)[tankId]; - if (!tankopediaEntry) return accumulator; + if (!tankDefinition) return accumulator; return stats.battles; }, @@ -110,7 +110,7 @@ export const eligibleCommand: CommandRegistry = { async (accumulator, [tankIdString, stats]) => { const tankId = parseInt(tankIdString); - if ((await tankopedia)[tankId]?.tier === 10) { + if ((await tankDefinitions)[tankId]?.tier === 10) { const tankStats = diffed[tankId]; return (await accumulator) + tankStats.damage_dealt; } else return accumulator; @@ -121,7 +121,7 @@ export const eligibleCommand: CommandRegistry = { async (accumulator, [tankIdString, stats]) => { const tankId = parseInt(tankIdString); - if ((await tankopedia)[tankId]?.tier === 10) { + if ((await tankDefinitions)[tankId]?.tier === 10) { const tankStats = diffed[tankId]; return (await accumulator) + tankStats.battles; } else return accumulator; diff --git a/src/commands/ownedTanks.tsx b/src/commands/ownedTanks.tsx index 007355a03..22526695f 100644 --- a/src/commands/ownedTanks.tsx +++ b/src/commands/ownedTanks.tsx @@ -3,20 +3,20 @@ import NoData, { NoDataType } from '../components/NoData'; import * as Tanks from '../components/Tanks'; import TitleBar from '../components/TitleBar'; import Wrapper from '../components/Wrapper'; +import { encyclopediaInfo } from '../core/blitz/encyclopediaInfo'; import { getAccountInfo } from '../core/blitz/getAccountInfo'; import { getClanAccountInfo } from '../core/blitz/getClanAccountInfo'; import getTankStats from '../core/blitz/getTankStats'; import getTreeType from '../core/blitz/getTreeType'; import resolveTankName from '../core/blitz/resolveTankName'; -import { tankopediaInfo } from '../core/blitz/tankopediaInfo'; +import { + TIER_ROMAN_NUMERALS, + TankDefinition, + Tier, + tankDefinitions, +} from '../core/blitzkrieg/definitions/tanks'; import { emblemIdToURL } from '../core/blitzkrieg/emblemIdToURL'; import { tankIcon } from '../core/blitzkrieg/tankIcon'; -import { - BlitzkriegTankopediaEntry, - TIER_ROMAN_NUMERALS, - Tier, - tankopedia, -} from '../core/blitzkrieg/tankopedia'; import addTierChoices from '../core/discord/addTierChoices'; import addUsernameChoices from '../core/discord/addUsernameChoices'; import autocompleteUsername from '../core/discord/autocompleteUsername'; @@ -42,21 +42,21 @@ export const ownedTanksCommand: CommandRegistry = { const filteredTanks = ( await Promise.all( tankStats.map(async (tankData) => ({ - tankopedia: (await tankopedia)[tankData.tank_id]!, + tankDefinitions: (await tankDefinitions)[tankData.tank_id]!, id: tankData.tank_id, })), ) - ).filter((tank) => tank.tankopedia?.tier === tier); + ).filter((tank) => tank.tankDefinitions?.tier === tier); const clanAccountInfo = await getClanAccountInfo(server, id, ['clan']); - const groupedTanks: Record = {}; + const groupedTanks: Record = {}; const nations: string[] = []; filteredTanks.forEach((tank) => { - if (groupedTanks[tank.tankopedia.nation] === undefined) { - groupedTanks[tank.tankopedia.nation] = [tank.tankopedia]; - nations.push(tank.tankopedia.nation); + if (groupedTanks[tank.tankDefinitions.nation] === undefined) { + groupedTanks[tank.tankDefinitions.nation] = [tank.tankDefinitions]; + nations.push(tank.tankDefinitions.nation); } else { - groupedTanks[tank.tankopedia.nation].push(tank.tankopedia); + groupedTanks[tank.tankDefinitions.nation].push(tank.tankDefinitions); } }); @@ -87,7 +87,7 @@ export const ownedTanksCommand: CommandRegistry = { return ( - {(await tankopediaInfo).vehicle_nations[nation]} + {(await encyclopediaInfo).vehicle_nations[nation]} diff --git a/src/commands/searchTanks.ts b/src/commands/searchTanks.ts index 99bc0e113..cb2f1e089 100644 --- a/src/commands/searchTanks.ts +++ b/src/commands/searchTanks.ts @@ -1,7 +1,7 @@ import { SlashCommandBuilder } from 'discord.js'; import { go } from 'fuzzysort'; import markdownEscape from 'markdown-escape'; -import { tankNamesDiacritics } from '../core/blitzkrieg/tankopedia'; +import { tankNamesDiacritics } from '../core/blitzkrieg/definitions/tanks'; import addTankChoices from '../core/discord/addTankChoices'; import embedInfo from '../core/discord/embedInfo'; import { CommandRegistry } from '../events/interactionCreate'; diff --git a/src/components/Tanks/components/Item.tsx b/src/components/Tanks/components/Item.tsx index 2fed154c5..d7de2cc98 100644 --- a/src/components/Tanks/components/Item.tsx +++ b/src/components/Tanks/components/Item.tsx @@ -2,7 +2,7 @@ import { TANK_ICONS, TANK_ICONS_COLLECTOR, TANK_ICONS_PREMIUM, -} from '../../../core/blitzkrieg/tankopedia'; +} from '../../../core/blitzkrieg/definitions/tanks'; import { theme } from '../../../stitches.config'; export enum TreeTypeEnum { diff --git a/src/components/TierWeights.tsx b/src/components/TierWeights.tsx index 355edbce6..3fe2149b6 100644 --- a/src/components/TierWeights.tsx +++ b/src/components/TierWeights.tsx @@ -1,4 +1,4 @@ -import { Tier } from '../core/blitzkrieg/tankopedia'; +import { Tier } from '../core/blitzkrieg/definitions/tanks'; import { theme } from '../stitches.config'; export type TierWeightsRecord = Partial>; diff --git a/src/core/blitz/tankopediaInfo.ts b/src/core/blitz/encyclopediaInfo.ts similarity index 82% rename from src/core/blitz/tankopediaInfo.ts rename to src/core/blitz/encyclopediaInfo.ts index cc9855fea..e27f70593 100644 --- a/src/core/blitz/tankopediaInfo.ts +++ b/src/core/blitz/encyclopediaInfo.ts @@ -1,7 +1,7 @@ import { WARGAMING_APPLICATION_ID } from '../../constants/wargamingApplicationID'; import fetchBlitz from './fetchBlitz'; -export interface TankopediaInfo { +export interface EncyclopediaInfo { achievement_sections: Record; tanks_updated_at: number; languages: Record; @@ -10,6 +10,6 @@ export interface TankopediaInfo { game_version: string; } -export const tankopediaInfo = fetchBlitz( +export const encyclopediaInfo = fetchBlitz( `https://api.wotblitz.com/wotb/encyclopedia/info/?application_id=${WARGAMING_APPLICATION_ID}`, ); diff --git a/src/core/blitz/getTreeType.ts b/src/core/blitz/getTreeType.ts index 6f784129d..b8aedd82d 100644 --- a/src/core/blitz/getTreeType.ts +++ b/src/core/blitz/getTreeType.ts @@ -1,8 +1,8 @@ import { TreeTypeEnum } from '../../components/Tanks'; -import { tankopedia } from '../blitzkrieg/tankopedia'; +import { tankDefinitions } from '../blitzkrieg/definitions/tanks'; export default async function getTreeType(id: number) { - const entry = (await tankopedia)[id]; + const entry = (await tankDefinitions)[id]; if (entry.tree_type === 'collector') return TreeTypeEnum.Collector; if (entry.tree_type === 'premium') return TreeTypeEnum.Premium; diff --git a/src/core/blitz/resolveTankId.ts b/src/core/blitz/resolveTankId.ts index a360e2f83..c110ee3a2 100644 --- a/src/core/blitz/resolveTankId.ts +++ b/src/core/blitz/resolveTankId.ts @@ -1,12 +1,15 @@ import { go } from 'fuzzysort'; -import { tankopedia, tanks } from '../blitzkrieg/tankopedia'; +import { + tankDefinitions, + tanksDefinitionsArray, +} from '../blitzkrieg/definitions/tanks'; import { UserError } from '../blitzkrieg/userError'; export default async function resolveTankId(tank: string | number) { const number = typeof tank === 'string' ? parseInt(tank) : tank; if (Number.isNaN(number)) { - const searchResult = go(`${tank}`, await tanks, { + const searchResult = go(`${tank}`, await tanksDefinitionsArray, { keys: ['name'], limit: 1, }); @@ -19,7 +22,7 @@ export default async function resolveTankId(tank: string | number) { return searchResult[0].obj.id; } } else { - if ((await tankopedia)[number]) { + if ((await tankDefinitions)[number]) { return number; } else { throw new UserError('Tank not found', { diff --git a/src/core/blitz/resolveTankName.ts b/src/core/blitz/resolveTankName.ts index c0760926a..b08e8ad0a 100644 --- a/src/core/blitz/resolveTankName.ts +++ b/src/core/blitz/resolveTankName.ts @@ -1,8 +1,8 @@ -import { tankopedia } from '../blitzkrieg/tankopedia'; +import { tankDefinitions } from '../blitzkrieg/definitions/tanks'; export default async function resolveTankName(tankId: number) { - const awaitedTankopedia = await tankopedia; - const entry = awaitedTankopedia[tankId]; + const awaitedTankDefinitions = await tankDefinitions; + const entry = awaitedTankDefinitions[tankId]; return entry?.name_short ?? entry?.name ?? `Unknown Tank ${tankId}`; } diff --git a/src/core/blitzkrieg/tankopedia.ts b/src/core/blitzkrieg/definitions/tanks.ts similarity index 65% rename from src/core/blitzkrieg/tankopedia.ts rename to src/core/blitzkrieg/definitions/tanks.ts index f60049af6..f691489a5 100644 --- a/src/core/blitzkrieg/tankopedia.ts +++ b/src/core/blitzkrieg/definitions/tanks.ts @@ -1,24 +1,8 @@ import { deburr } from 'lodash'; -import { TankType, TreeTypeString } from '../../components/Tanks'; -import { asset } from './asset'; +import { TankType, TreeTypeString } from '../../../components/Tanks'; +import { asset } from '../asset'; -export interface TankopediaEntry { - name: string; - nation: string; - is_premium: boolean; - is_collectible: boolean; - tier: Tier; - cost: { price_credit: number; price_gold: number }; - images: { preview: string; normal: string }; - tank_id: number; - type: string; - description: string; -} -export interface Tankopedia { - [id: number]: TankopediaEntry | undefined; -} - -export interface BlitzkriegTankopediaEntry { +export interface TankDefinition { id: number; nation: string; name: string; @@ -28,15 +12,16 @@ export interface BlitzkriegTankopediaEntry { type: TankType; } -export type BlitzkriegTankopedia = Record; +export type TankDefinitions = Record; -export const tankopedia = fetch(asset('tankopedia.json'), { +export const tankDefinitions = fetch(asset('definitions/tanks.json'), { cache: 'no-store', -}).then(async (response) => response.json() as Promise); -const entries = new Promise(async (resolve) => { - resolve(Object.entries(await tankopedia).map(([, entry]) => entry)); +}).then(async (response) => response.json() as Promise); + +const entries = new Promise(async (resolve) => { + resolve(Object.entries(await tankDefinitions).map(([, entry]) => entry)); }); -export const tanks = new Promise( +export const tanksDefinitionsArray = new Promise( async (resolve) => { resolve((await entries).map((entry) => entry)); }, @@ -47,7 +32,7 @@ export const tankNames = new Promise(async (resolve) => { export const tankNamesDiacritics = tankNames.then((tankNames) => Promise.all( tankNames.map(async (tankName, index) => { - const { id } = (await tanks)[index]; + const { id } = (await tanksDefinitionsArray)[index]; const name = tankName ?? `Unknown Tank ${id}`; const diacriticless = deburr(name); @@ -99,7 +84,7 @@ export const TIER_ROMAN_NUMERALS: Record = { 10: 'X', }; -export const NATIONS = tanks.then((tanks) => { +export const NATIONS = tanksDefinitionsArray.then((tanks) => { const nationsObject: Record = {}; tanks.forEach(({ nation }) => { diff --git a/src/core/blitzkrieg/filtersToDescription.ts b/src/core/blitzkrieg/filtersToDescription.ts index 32c5f8ec5..949cb8fe5 100644 --- a/src/core/blitzkrieg/filtersToDescription.ts +++ b/src/core/blitzkrieg/filtersToDescription.ts @@ -1,8 +1,8 @@ import { TREE_TYPE_NAMES } from '../../components/Tanks'; +import { encyclopediaInfo } from '../blitz/encyclopediaInfo'; import resolveTankName from '../blitz/resolveTankName'; -import { tankopediaInfo } from '../blitz/tankopediaInfo'; import { StatFilters } from '../statistics/filterStats'; -import { TIER_ROMAN_NUMERALS, Tier } from './tankopedia'; +import { TIER_ROMAN_NUMERALS, Tier } from './definitions/tanks'; export async function filtersToDescription({ nation, @@ -11,13 +11,13 @@ export async function filtersToDescription({ treeType, tank, }: StatFilters) { - const awaitedTankopediaInfo = await tankopediaInfo; + const awaitedEncyclopediaInfo = await encyclopediaInfo; const info: string[] = []; if (tank) return await resolveTankName(tank); - if (nation) info.push(awaitedTankopediaInfo.vehicle_nations[nation]); + if (nation) info.push(awaitedEncyclopediaInfo.vehicle_nations[nation]); if (tier) info.push(`Tier ${TIER_ROMAN_NUMERALS[tier as Tier]}`); - if (tankType) info.push(awaitedTankopediaInfo.vehicle_types[tankType]); + if (tankType) info.push(awaitedEncyclopediaInfo.vehicle_types[tankType]); if (treeType) info.push(TREE_TYPE_NAMES[treeType]); return info.length === 0 ? 'No filters' : info.join(', '); diff --git a/src/core/blitzstars/tankAverages.ts b/src/core/blitzstars/tankAverages.ts index 110e1db84..1ed7d87a3 100644 --- a/src/core/blitzstars/tankAverages.ts +++ b/src/core/blitzstars/tankAverages.ts @@ -1,6 +1,6 @@ import { AllStats } from '../blitz/getAccountInfo'; import { context } from '../blitzkrieg/context'; -import { tankopedia } from '../blitzkrieg/tankopedia'; +import { tankDefinitions } from '../blitzkrieg/definitions/tanks'; export interface SpecialStats { winrate: number; @@ -80,7 +80,7 @@ export interface IndividualTankAverage { last_update: number; } -tankopedia; +tankDefinitions; export type TankAverages = Record; diff --git a/src/core/discord/addFilterOptions.ts b/src/core/discord/addFilterOptions.ts index 94d8eef42..2c45a612d 100644 --- a/src/core/discord/addFilterOptions.ts +++ b/src/core/discord/addFilterOptions.ts @@ -4,7 +4,7 @@ import { SlashCommandSubcommandGroupBuilder, } from 'discord.js'; import { TREE_TYPE_NAMES, TreeTypeString } from '../../components/Tanks'; -import { tankopediaInfo } from '../blitz/tankopediaInfo'; +import { encyclopediaInfo } from '../blitz/encyclopediaInfo'; import addPeriodSubCommands from './addPeriodSubCommands'; import addTankChoices from './addTankChoices'; import addTierChoices from './addTierChoices'; @@ -17,7 +17,7 @@ export default async function addFilterOptions< option: SlashCommandSubcommandBuilder, ) => SlashCommandSubcommandBuilder = (option) => option, ): Promise { - const awaitedTankopediaInfo = await tankopediaInfo; + const awaitedEncyclopediaInfo = await encyclopediaInfo; addPeriodSubCommands(option, (option) => { extra(option); @@ -28,7 +28,7 @@ export default async function addFilterOptions< .setName('nation') .setDescription('Nation') .addChoices( - ...Object.entries(awaitedTankopediaInfo.vehicle_nations).map( + ...Object.entries(awaitedEncyclopediaInfo.vehicle_nations).map( ([type, name]) => ({ name, value: type }), ), ) @@ -40,7 +40,7 @@ export default async function addFilterOptions< .setName('tank-type') .setDescription('Tank type') .addChoices( - ...Object.entries(awaitedTankopediaInfo.vehicle_types).map( + ...Object.entries(awaitedEncyclopediaInfo.vehicle_types).map( ([type, name]) => ({ name: name.replace(' Tank', ''), value: type, diff --git a/src/core/discord/autocompleteTanks.ts b/src/core/discord/autocompleteTanks.ts index 1765a3bb9..78f1b17ab 100644 --- a/src/core/discord/autocompleteTanks.ts +++ b/src/core/discord/autocompleteTanks.ts @@ -4,7 +4,7 @@ import { CacheType, } from 'discord.js'; import { go } from 'fuzzysort'; -import { tankNamesDiacritics } from '../blitzkrieg/tankopedia'; +import { tankNamesDiacritics } from '../blitzkrieg/definitions/tanks'; import { DISCORD_CHOICES_MAX_NAME_SIZE, OVERFLOW_SUFFIX, diff --git a/src/core/statistics/filterStats.ts b/src/core/statistics/filterStats.ts index e371bca55..c48ce83c5 100644 --- a/src/core/statistics/filterStats.ts +++ b/src/core/statistics/filterStats.ts @@ -1,5 +1,5 @@ import { TreeTypeString } from '../../components/Tanks'; -import { tankopedia } from '../blitzkrieg/tankopedia'; +import { tankDefinitions } from '../blitzkrieg/definitions/tanks'; import { DiffedTankStats } from '../blitzstars/getStatsInPeriod'; import { tankAverages } from '../blitzstars/tankAverages'; import calculateWN8 from './calculateWN8'; @@ -20,10 +20,10 @@ export async function filterStats( // tank, if provided, takes priority over all other filters if (filters.tank) filters = { tank: filters.tank }; - const awaitedTankopedia = await tankopedia; + const awaitedTankDefinitions = await tankDefinitions; const awaitedTankAverages = await tankAverages; const filteredOrder = order.filter((id) => { - const entry = awaitedTankopedia[id]; + const entry = awaitedTankDefinitions[id]; return ( entry && @@ -44,9 +44,9 @@ export async function filterStats( awaitedTankAverages[id] ? accumulator + diff[id].battles : accumulator, 0, ); - const battlesOfTanksWithTankopediaEntry = filteredOrder.reduce( + const battlesOfTanksWithTankDefinition = filteredOrder.reduce( (accumulator, id) => - awaitedTankopedia[id] ? accumulator + diff[id].battles : accumulator, + awaitedTankDefinitions[id] ? accumulator + diff[id].battles : accumulator, 0, ); const supplementary = { @@ -63,11 +63,11 @@ export async function filterStats( tier: filteredOrder.reduce( (accumulator, id) => - awaitedTankopedia[id] - ? accumulator + awaitedTankopedia[id]!.tier * diff[id].battles + awaitedTankDefinitions[id] + ? accumulator + awaitedTankDefinitions[id]!.tier * diff[id].battles : accumulator, 0, - ) / battlesOfTanksWithTankopediaEntry, + ) / battlesOfTanksWithTankDefinition, }; return { stats, supplementary, filteredOrder }; diff --git a/src/core/statistics/getTierWeights.ts b/src/core/statistics/getTierWeights.ts index 020ea7e6b..933bd30ee 100644 --- a/src/core/statistics/getTierWeights.ts +++ b/src/core/statistics/getTierWeights.ts @@ -1,16 +1,16 @@ import { TierWeightsRecord } from '../../components/TierWeights'; import { AllStats } from '../blitz/getAccountInfo'; -import { tankopedia } from '../blitzkrieg/tankopedia'; +import { tankDefinitions } from '../blitzkrieg/definitions/tanks'; export async function getTierWeights( stats: Record, order: number[] = Object.keys(stats).map(parseInt), ) { - const awaitedTankopedia = await tankopedia; + const awaitedTankDefinitions = await tankDefinitions; const tierWeights: TierWeightsRecord = {}; order.forEach((id) => { - const entry = awaitedTankopedia[id]; + const entry = awaitedTankDefinitions[id]; if (!entry) return; if (!tierWeights[entry.tier]) tierWeights[entry.tier] = 0; diff --git a/src/stores/tankopedia.ts b/src/stores/tankopedia.ts index 0dc2ccbeb..4f060706d 100644 --- a/src/stores/tankopedia.ts +++ b/src/stores/tankopedia.ts @@ -2,7 +2,7 @@ import { produce } from 'immer'; import { create } from 'zustand'; import { devtools, persist } from 'zustand/middleware'; import { TankType, TreeTypeString } from '../components/Tanks'; -import { Tier } from '../core/blitzkrieg/tankopedia'; +import { Tier } from '../core/blitzkrieg/definitions/tanks'; export type TankopediaSortBy = 'tier' | 'name'; export type TankopediaSortDirection = 'ascending' | 'descending';