From 9a686230c6cc558f512f230840d2f683521d78c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sun, 25 Aug 2024 21:06:56 -0500 Subject: [PATCH] feat: battle count --- .../Model/TechTreeSection/components/Node.tsx | 37 +++++++++-- .../Model/TechTreeSection/index.tsx | 62 ++++++++++++++++--- src/stores/tankopediaEphemeral.ts | 3 + 3 files changed, 89 insertions(+), 13 deletions(-) diff --git a/src/app/tools/tankopedia/[id]/components/Model/TechTreeSection/components/Node.tsx b/src/app/tools/tankopedia/[id]/components/Model/TechTreeSection/components/Node.tsx index be6df1460..8dade4fd4 100644 --- a/src/app/tools/tankopedia/[id]/components/Model/TechTreeSection/components/Node.tsx +++ b/src/app/tools/tankopedia/[id]/components/Model/TechTreeSection/components/Node.tsx @@ -2,13 +2,36 @@ import { Box, Flex, Text } from '@radix-ui/themes'; import Link from 'next/link'; import { use } from 'react'; import { asset } from '../../../../../../../../core/blitzkit/asset'; +import { averageDefinitions } from '../../../../../../../../core/blitzkit/averageDefinitions'; import { tankDefinitions } from '../../../../../../../../core/blitzkit/tankDefinitions'; import { TIER_ROMAN_NUMERALS } from '../../../../../../../../core/blitzkit/tankDefinitions/constants'; import { formatCompact } from '../../../../../../../../core/math/formatCompact'; +import * as TankopediaEphemeral from '../../../../../../../../stores/tankopediaEphemeral'; -export function Node({ id, highlight }: { id: number; highlight?: boolean }) { +interface NodeProps { + id: number; + nextIds?: number[]; + highlight?: boolean; +} + +export function Node({ id, highlight, nextIds }: NodeProps) { + const xpMultiplier = TankopediaEphemeral.use((state) => state.xpMultiplier); const awaitedTankDefinitions = use(tankDefinitions); const tank = awaitedTankDefinitions[id]; + const nextTanks = nextIds?.map((id) => awaitedTankDefinitions[id]); + const awaitedAverageDefinitions = use(averageDefinitions); + const thisTankXp = + tank.xp === undefined || tank.tier === 1 ? 0 : tank.xp! / xpMultiplier; + const nextTanksXp = nextTanks?.reduce( + (xp, tank) => + xp + + (tank.xp === undefined || tank.tier === 1 ? 0 : tank.xp! / xpMultiplier), + 0, + ); + const averages = awaitedAverageDefinitions.averages[tank.id]?.mu; + const averageXp = averages ? averages.xp / averages.battles : undefined; + const games = + averages && nextTanks ? Math.round(nextTanksXp! / averageXp!) : undefined; return ( {tank.name} - @@ -74,12 +96,9 @@ export function Node({ id, highlight }: { id: number; highlight?: boolean }) { objectPosition: 'center', }} /> - {tank.xp === undefined || tank.tier === 1 - ? 0 - : formatCompact(tank.xp!)} + {formatCompact(thisTankXp)} - + + {averages && nextTanks && ( + + {games!} {games === 1 ? 'battle' : 'battles'} + + )} diff --git a/src/app/tools/tankopedia/[id]/components/Model/TechTreeSection/index.tsx b/src/app/tools/tankopedia/[id]/components/Model/TechTreeSection/index.tsx index c7eeaabf6..18c467b8b 100644 --- a/src/app/tools/tankopedia/[id]/components/Model/TechTreeSection/index.tsx +++ b/src/app/tools/tankopedia/[id]/components/Model/TechTreeSection/index.tsx @@ -2,14 +2,20 @@ import { CaretLeftIcon, CaretRightIcon, PlusIcon } from '@radix-ui/react-icons'; import { Flex, Heading, IconButton, ScrollArea, Text } from '@radix-ui/themes'; import { use, useEffect, useMemo, useRef, useState } from 'react'; import { asset } from '../../../../../../../core/blitzkit/asset'; +import { imgur } from '../../../../../../../core/blitzkit/imgur'; import { tankDefinitions } from '../../../../../../../core/blitzkit/tankDefinitions'; import * as Duel from '../../../../../../../stores/duel'; +import * as TankopediaEphemeral from '../../../../../../../stores/tankopediaEphemeral'; import { Arrow } from './components/Arrow'; import { Node } from './components/Node'; type Line = number[]; +export const XP_MULTIPLIERS = [1, 2, 3, 4, 5, 10]; + export function TechTreeSection() { + const xpMultiplier = TankopediaEphemeral.use((state) => state.xpMultiplier); + const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation(); const master = Duel.use((state) => state.protagonist.tank); const awaitedTankDefinitions = use(tankDefinitions); const container = useRef(null); @@ -94,7 +100,7 @@ export function TechTreeSection() { objectPosition: 'center', }} /> - {totalXp.toLocaleString()} + {Math.round(totalXp / xpMultiplier).toLocaleString()} @@ -115,16 +121,58 @@ export function TechTreeSection() { )} + + + {XP_MULTIPLIERS.map((multiplier) => { + const selected = xpMultiplier === multiplier; + + return ( + { + mutateTankopediaEphemeral((draft) => { + draft.xpMultiplier = multiplier; + }); + }} + key={multiplier} + width="2.5rem" + justify="center" + align="center" + pt="1" + pl="1" + > + x{multiplier} + + ); + })} + - {line.map((id, index) => ( - <> - {index > 0 && } - - - ))} + {line.map((id, index) => { + const last = index === line.length - 1; + const tank = awaitedTankDefinitions[id]; + + return ( + <> + {index > 0 && } + + + ); + })} {master.tier < 10 && ( <> diff --git a/src/stores/tankopediaEphemeral.ts b/src/stores/tankopediaEphemeral.ts index f91d435c2..02de4153b 100644 --- a/src/stores/tankopediaEphemeral.ts +++ b/src/stores/tankopediaEphemeral.ts @@ -3,6 +3,7 @@ import { Vector3 } from 'three'; import { create } from 'zustand'; import { subscribeWithSelector } from 'zustand/middleware'; +import { XP_MULTIPLIERS } from '../app/tools/tankopedia/[id]/components/Model/TechTreeSection'; import { ArmorType } from '../components/Armor/components/SpacedArmorScene'; import { ExternalModuleVariant } from '../components/Armor/components/SpacedArmorSceneComponent'; import { ModelDefinition } from '../core/blitzkit/modelDefinitions'; @@ -28,6 +29,7 @@ interface TankopediaEphemeral { } | { type: ArmorType.External } ); + xpMultiplier: (typeof XP_MULTIPLIERS)[number]; } export interface ShotLayerBase { @@ -97,6 +99,7 @@ export const { Provider, use, useMutation, useStore } = createNextSafeStore( skills: {}, model, controlsEnabled: true, + xpMultiplier: 1, })), ), );