From 6ef0448d9f8b224df76f10ae94441564c1f13a0d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com>
Date: Fri, 9 Feb 2024 18:47:53 -0600
Subject: [PATCH] feat: deltas
---
.../Characteristics/components/Info.tsx | 30 +-
.../components/InfoWithDelta.tsx | 20 ++
.../[id]/components/Characteristics/index.tsx | 322 ++++++++++--------
3 files changed, 230 insertions(+), 142 deletions(-)
create mode 100644 src/app/tools/tankopedia/[id]/components/Characteristics/components/InfoWithDelta.tsx
diff --git a/src/app/tools/tankopedia/[id]/components/Characteristics/components/Info.tsx b/src/app/tools/tankopedia/[id]/components/Characteristics/components/Info.tsx
index a364447fa..aa13d7507 100644
--- a/src/app/tools/tankopedia/[id]/components/Characteristics/components/Info.tsx
+++ b/src/app/tools/tankopedia/[id]/components/Characteristics/components/Info.tsx
@@ -1,13 +1,17 @@
+import { CaretDownIcon, CaretUpIcon } from '@radix-ui/react-icons';
import { Flex, Text } from '@radix-ui/themes';
import { ReactNode } from 'react';
import { theme } from '../../../../../../../stitches.config';
-interface InfoProps {
+export interface InfoProps {
name: ReactNode;
children?: ReactNode;
unit?: string;
indent?: boolean;
highlight?: boolean;
+ delta?: number;
+ decimals?: number;
+ prefix?: string;
}
export function Info({
@@ -16,6 +20,9 @@ export function Info({
unit,
indent = false,
highlight,
+ delta,
+ decimals,
+ prefix,
}: InfoProps) {
return (
{children}
+
+ {delta !== undefined && delta !== 0 && (
+ <>
+ 0 ? 'green' : 'tomato'}>
+ {decimals !== undefined
+ ? Math.abs(delta).toFixed(decimals)
+ : Math.abs(delta)}
+
+ 0 ? 'green' : 'tomato'}>
+ {delta > 0 ? : }
+
+ >
+ )}
+
+ {prefix}
+ {decimals !== undefined && typeof children === 'number'
+ ? children.toFixed(decimals)
+ : children}
+
+
)}
);
diff --git a/src/app/tools/tankopedia/[id]/components/Characteristics/components/InfoWithDelta.tsx b/src/app/tools/tankopedia/[id]/components/Characteristics/components/InfoWithDelta.tsx
new file mode 100644
index 000000000..acbc8fc3a
--- /dev/null
+++ b/src/app/tools/tankopedia/[id]/components/Characteristics/components/InfoWithDelta.tsx
@@ -0,0 +1,20 @@
+import { useEffect, useRef } from 'react';
+import { Info, InfoProps } from './Info';
+
+interface InfoWithDeltaProps extends InfoProps {
+ children: number;
+}
+
+export function InfoWithDelta({ children, ...props }: InfoWithDeltaProps) {
+ const lastValue = useRef(children);
+
+ useEffect(() => {
+ lastValue.current = children;
+ });
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx b/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx
index 17da50b50..d578be26c 100644
--- a/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx
+++ b/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx
@@ -12,6 +12,7 @@ import { unionBoundingBox } from '../../../../../../core/blitzkrieg/unionBoundin
import { useEquipment } from '../../../../../../core/blitzkrieg/useEquipmentEquipped';
import { useDuel } from '../../../../../../stores/duel';
import { Info } from './components/Info';
+import { InfoWithDelta } from './components/InfoWithDelta';
export function Characteristics() {
const awaitedModelDefinitions = use(modelDefinitions);
@@ -47,68 +48,65 @@ export function Characteristics() {
Survivability
-
+
{tank.health + turret.health}
-
-
+
+
{Math.round(engine.fireChance * 100)}
-
-
+
+
{turret.viewRange}
-
+
-
- {(tank.camouflage.still * 100).toFixed(2)}
-
-
- {(tank.camouflage.moving * 100).toFixed(2)}
-
-
- {(tank.camouflage.still * gun.camouflageLoss * 100).toFixed(2)}
-
-
- {(tank.camouflage.moving * gun.camouflageLoss * 100).toFixed(2)}
-
-
- {(tank.camouflage.onFire * tank.camouflage.still * 100).toFixed(2)}
-
+
+ {tank.camouflage.still * 100}
+
+
+ {tank.camouflage.moving * 100}
+
+
+ {tank.camouflage.still * gun.camouflageLoss * 100}
+
+
+ {tank.camouflage.moving * gun.camouflageLoss * 100}
+
+
+ {tank.camouflage.onFire * tank.camouflage.still * 100}
+
- {size.map((component) => component.toFixed(2)).join(' x ')}
+ {size[0].toFixed(2)} x {size[2].toFixed(2)} x {size[1].toFixed(2)}
Fire
{GUN_TYPE_NAMES[gun.type]}
-
- {resolveDpm(gun, shell, hasRammer).toFixed(0)}
-
+
+ {resolveDpm(gun, shell, hasRammer)}
+
{gun.type === 'autoReloader' && (
<>
-
+
{gun.reload.at(-1)! < gun.reload.at(-2)!
- ? (
- (shell.damage.armor /
- (gun.reload.at(-1)! + gun.interClip)) *
- 60
- ).toFixed(0)
- : ((shell.damage.armor / gun.reload[0]) * 60).toFixed(0)}
-
-
+ ? (shell.damage.armor / (gun.reload.at(-1)! + gun.interClip)) *
+ 60
+ : (shell.damage.armor / gun.reload[0]) * 60}
+
+
{gun.reload.at(-1)! < gun.reload.at(-2)!
- ? (
- (shell.damage.armor /
- (gun.reload.at(-1)! + gun.interClip)) *
- (60 -
- (gun.reload.slice(0, -1).length - 1) * gun.interClip) +
- shell.damage.armor * gun.reload.slice(0, -1).length
- ).toFixed(0)
- : (
- (shell.damage.armor / (gun.reload[0] + gun.interClip)) *
- (60 - (gun.reload.slice(1).length - 1) * gun.interClip) +
- shell.damage.armor * gun.reload.slice(1).length
- ).toFixed(0)}
-
+ ? (shell.damage.armor / (gun.reload.at(-1)! + gun.interClip)) *
+ (60 -
+ (gun.reload.slice(0, -1).length - 1) * gun.interClip) +
+ shell.damage.armor * gun.reload.slice(0, -1).length
+ : (shell.damage.armor / (gun.reload[0] + gun.interClip)) *
+ (60 - (gun.reload.slice(1).length - 1) * gun.interClip) +
+ shell.damage.armor * gun.reload.slice(1).length}
+
(
- 0}
name={index > 0 ? `Shell ${index + 1}` : 'Reload on shell 1'}
unit="s"
+ decimals={2}
>
- {reload.toFixed(2)}
-
+ {reload}
+
))
) : (
-
- {(gun.reload * (hasRammer ? 0.93 : 1)).toFixed(2)}
-
+
+ {gun.reload * (hasRammer ? 0.93 : 1)}
+
)}
-
+
{shell.caliber}
-
+
{gun.shells.map((shell) => (
-
+
{resolveNearPenetration(shell.penetration)}
-
+
))}
{gun.shells.map((shell) => (
-
+
{shell.damage.armor}
-
+
))}
{gun.shells.map((shell, index) => (
-
+
{shell.damage.module}
-
+
))}
- {gun.shells.map((shell, index) => (
-
+ {gun.shells.map((shell) => (
+
{shell.speed}
-
+
))}
-
- {gun.aimTime.toFixed(2)}
-
+
+ {gun.aimTime}
+
-
- {gun.dispersion.base.toFixed(3)}
-
-
- + {track.dispersion.move.toFixed(3)}
-
-
- + {track.dispersion.traverse.toFixed(3)}
-
-
- + {gun.dispersion.traverse.toFixed(3)}
-
-
- + {gun.dispersion.shot.toFixed(3)}
-
-
- x {gun.dispersion.damaged.toFixed(3)}
-
+
+ {gun.dispersion.base}
+
+
+ {track.dispersion.move}
+
+
+ {track.dispersion.traverse}
+
+
+ {gun.dispersion.traverse}
+
+
+ {gun.dispersion.shot}
+
+
+ {gun.dispersion.damaged}
+
-
- {gunModelDefinition.pitch.max.toFixed(1)}
-
-
- {(-gunModelDefinition.pitch.min).toFixed(1)}
-
+
+ {gunModelDefinition.pitch.max}
+
+
+ {-gunModelDefinition.pitch.min}
+
{gunModelDefinition.pitch.front && (
<>
-
+
{gunModelDefinition.pitch.front.max}
-
-
+
+
{-gunModelDefinition.pitch.front.min}
-
+
>
)}
{gunModelDefinition.pitch.back && (
<>
-
+
{gunModelDefinition.pitch.back.max}
-
-
+
+
{-gunModelDefinition.pitch.back.min}
-
+
>
)}
{turretModelDefinition.yaw && (
-
- {-turretModelDefinition.yaw.min}, {turretModelDefinition.yaw.max}
-
+ <>
+
+ {-turretModelDefinition.yaw.min}
+
+
+ {turretModelDefinition.yaw.max}
+
+ >
)}
Maneuverability
-
- {tank.speed.forwards.toFixed(0)}
-
-
- {tank.speed.backwards.toFixed(0)}
-
-
+
+ {tank.speed.forwards}
+
+
+ {tank.speed.backwards}
+
+
{engine.power}
-
+
-
- {(engine.power / weightMt / track.resistance.hard).toFixed(1)}
-
-
- {(engine.power / weightMt / track.resistance.medium).toFixed(1)}
-
-
- {(engine.power / weightMt / track.resistance.soft).toFixed(1)}
-
-
- {weightMt.toFixed(1)}
-
+
+ {engine.power / weightMt / track.resistance.hard}
+
+
+ {engine.power / weightMt / track.resistance.medium}
+
+
+ {engine.power / weightMt / track.resistance.soft}
+
+
+ {weightMt}
+
-
- {(
- (engine.power / stockEngine.power) *
+
+ {(engine.power / stockEngine.power) *
track.traverseSpeed *
(track.resistance.hard / track.resistance.hard) *
- (stockWeight / weight)
- ).toFixed(1)}
-
-
- {(
- (engine.power / stockEngine.power) *
+ (stockWeight / weight)}
+
+
+ {(engine.power / stockEngine.power) *
track.traverseSpeed *
(track.resistance.hard / track.resistance.medium) *
- (stockWeight / weight)
- ).toFixed(1)}
-
-
- {(
- (engine.power / stockEngine.power) *
+ (stockWeight / weight)}
+
+
+ {(engine.power / stockEngine.power) *
track.traverseSpeed *
(track.resistance.hard / track.resistance.soft) *
- (stockWeight / weight)
- ).toFixed(1)}
-
+ (stockWeight / weight)}
+
);