From a7f68364f3f3bd16c09a1d60b4bcd9925bfff2f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sun, 7 Jul 2024 18:56:49 -0500 Subject: [PATCH] feat: total bar --- .../tank-performance/components/Info.tsx | 7 +- .../tank-performance/components/TankRow.tsx | 7 +- .../tank-performance/components/Tanks.tsx | 3 + .../tank-performance/components/Total.tsx | 78 +++++++++++++++++++ src/core/blitzkit/averageDefinitions/index.ts | 15 +++- src/hooks/useAveragesExclusionRatio.ts | 13 ++++ 6 files changed, 109 insertions(+), 14 deletions(-) create mode 100644 src/app/tools/tank-performance/components/Total.tsx create mode 100644 src/hooks/useAveragesExclusionRatio.ts diff --git a/src/app/tools/tank-performance/components/Info.tsx b/src/app/tools/tank-performance/components/Info.tsx index e856736fc..442d1386d 100644 --- a/src/app/tools/tank-performance/components/Info.tsx +++ b/src/app/tools/tank-performance/components/Info.tsx @@ -4,15 +4,12 @@ import { InfoCircledIcon } from '@radix-ui/react-icons'; import { Callout, Flex } from '@radix-ui/themes'; import { use } from 'react'; import { averageDefinitions } from '../../../../core/blitzkit/averageDefinitions'; -import { discoveredIdsDefinitions } from '../../../../core/blitzkit/discoveredIdDefinitions'; +import { useAveragesExclusionRatio } from '../../../../hooks/useAveragesExclusionRatio'; export function Info() { const awaitedAverageDefinitions = use(averageDefinitions); - const awaitedDiscoveredIdsDefinitions = use(discoveredIdsDefinitions); const numberFormat = Intl.NumberFormat(undefined, { notation: 'compact' }); - const ratio = - awaitedDiscoveredIdsDefinitions.count / - awaitedAverageDefinitions.scanned_players; + const ratio = useAveragesExclusionRatio(); const samples = ratio * awaitedAverageDefinitions.sampled_players; return ( diff --git a/src/app/tools/tank-performance/components/TankRow.tsx b/src/app/tools/tank-performance/components/TankRow.tsx index 94a35058b..52cb2e10b 100644 --- a/src/app/tools/tank-performance/components/TankRow.tsx +++ b/src/app/tools/tank-performance/components/TankRow.tsx @@ -2,8 +2,8 @@ import { Table } from '@radix-ui/themes'; import { memo, use } from 'react'; import { TankRowHeaderCell } from '../../../../components/TankRowHeaderCell'; import { averageDefinitions } from '../../../../core/blitzkit/averageDefinitions'; -import { discoveredIdsDefinitions } from '../../../../core/blitzkit/discoveredIdDefinitions'; import { TankDefinition } from '../../../../core/blitzkit/tankDefinitions'; +import { useAveragesExclusionRatio } from '../../../../hooks/useAveragesExclusionRatio'; interface TankRowProps { tank: TankDefinition; @@ -11,13 +11,10 @@ interface TankRowProps { export const TankRow = memo( ({ tank }) => { - const awaitedDiscoveredIdsDefinitions = use(discoveredIdsDefinitions); const awaitedAverageDefinitions = use(averageDefinitions); const averages = awaitedAverageDefinitions.averages[tank.id]; const numberFormat = Intl.NumberFormat(undefined, { notation: 'compact' }); - const ratio = - awaitedDiscoveredIdsDefinitions.count / - awaitedAverageDefinitions.scanned_players; + const ratio = useAveragesExclusionRatio(); return ( diff --git a/src/app/tools/tank-performance/components/Tanks.tsx b/src/app/tools/tank-performance/components/Tanks.tsx index 859d1cb19..15c08f094 100644 --- a/src/app/tools/tank-performance/components/Tanks.tsx +++ b/src/app/tools/tank-performance/components/Tanks.tsx @@ -10,6 +10,7 @@ import { useTankFilters } from '../../../../stores/tankFilters'; import { useTankPerformanceSort } from '../../../../stores/tankPerformanceSort'; import { RowLoader } from './RowLoader'; import { TankRow } from './TankRow'; +import { Total } from './Total'; const PREVIEW_COUNT = 10; const DEFAULT_LOADED_ROWS = 25; @@ -121,6 +122,8 @@ export function Tanks() { return ( + + {tanks.slice(0, loadedRows).map((averages) => { const tank = awaitedTankDefinitions[averages.id]; return ( diff --git a/src/app/tools/tank-performance/components/Total.tsx b/src/app/tools/tank-performance/components/Total.tsx new file mode 100644 index 000000000..7fb048268 --- /dev/null +++ b/src/app/tools/tank-performance/components/Total.tsx @@ -0,0 +1,78 @@ +import { Table } from '@radix-ui/themes'; +import { memo, use, useCallback } from 'react'; +import { + averageDefinitions, + AverageDefinitionsAllStats, + AverageDefinitionsEntryWithId, +} from '../../../../core/blitzkit/averageDefinitions'; +import { useAveragesExclusionRatio } from '../../../../hooks/useAveragesExclusionRatio'; + +interface TotalProps { + tanks: AverageDefinitionsEntryWithId[]; +} + +export const Total = memo( + ({ tanks }) => { + const awaitedAverageDefinitions = use(averageDefinitions); + const ratio = useAveragesExclusionRatio(); + const numberFormat = Intl.NumberFormat(undefined, { notation: 'compact' }); + const sum = useCallback( + (slice: (tank: AverageDefinitionsAllStats) => number) => { + return tanks.reduce( + (acc, tank) => acc + tank.samples * slice(tank.mu), + 0, + ); + }, + [tanks], + ); + + const players = sum(() => 1); + const battles = sum(({ battles }) => battles); + const winrate = sum(({ wins }) => wins) / battles; + const damage = sum(({ damage_dealt }) => damage_dealt) / battles; + const survival = sum(({ survived_battles }) => survived_battles) / battles; + const xp = sum(({ xp }) => xp) / battles; + const kills = sum(({ frags }) => frags) / battles; + const spots = sum(({ spotted }) => spotted) / battles; + const hits = sum(({ hits }) => hits) / battles; + const shots = sum(({ shots }) => shots) / battles; + const accuracy = hits / shots; + const damageReceived = + sum(({ damage_received }) => damage_received) / battles; + const damageRatio = damage / damageReceived; + const capturePoints = sum(({ capture_points }) => capture_points) / battles; + + return ( + + Total + {(winrate * 100).toFixed(1)}% + + {numberFormat.format(ratio * players)} + + + {numberFormat.format(ratio * battles)} + + + {Math.round(damage).toLocaleString()} + + + {Math.round(survival * 100).toFixed(1)}% + + + {Math.round(xp).toLocaleString()} + + {kills.toFixed(2)} + {spots.toFixed(2)} + {(accuracy * 100).toFixed(0)}% + {shots.toFixed(1)} + {hits.toFixed(1)} + {damageRatio.toFixed(2)} + + {Math.round(damageReceived).toLocaleString()} + + {capturePoints.toFixed(2)} + + ); + }, + (prev, next) => prev.tanks === next.tanks, +); diff --git a/src/core/blitzkit/averageDefinitions/index.ts b/src/core/blitzkit/averageDefinitions/index.ts index 25428a34f..4ff8a8c04 100644 --- a/src/core/blitzkit/averageDefinitions/index.ts +++ b/src/core/blitzkit/averageDefinitions/index.ts @@ -13,6 +13,10 @@ export interface AverageDefinitionsEntry { r: AverageDefinitionsAllStats; } +export interface AverageDefinitionsEntryWithId extends AverageDefinitionsEntry { + id: number; +} + export interface AverageDefinitionsEntrySubPartial { samples: number; mu: Partial; @@ -36,8 +40,11 @@ export const averageDefinitions = fetch(asset('definitions/averages.pb')) }); export const averageDefinitionsArray = averageDefinitions.then((data) => - Object.entries(data.averages).map(([key, value]) => ({ - id: Number(key), - ...(value as AverageDefinitionsEntry), - })), + Object.entries(data.averages).map( + ([key, value]) => + ({ + id: Number(key), + ...(value as AverageDefinitionsEntry), + }) satisfies AverageDefinitionsEntryWithId, + ), ); diff --git a/src/hooks/useAveragesExclusionRatio.ts b/src/hooks/useAveragesExclusionRatio.ts new file mode 100644 index 000000000..413c7b9df --- /dev/null +++ b/src/hooks/useAveragesExclusionRatio.ts @@ -0,0 +1,13 @@ +import { use } from 'react'; +import { averageDefinitions } from '../core/blitzkit/averageDefinitions'; +import { discoveredIdsDefinitions } from '../core/blitzkit/discoveredIdDefinitions'; + +export function useAveragesExclusionRatio() { + const awaitedDiscoveredIdsDefinitions = use(discoveredIdsDefinitions); + const awaitedAverageDefinitions = use(averageDefinitions); + + return ( + awaitedDiscoveredIdsDefinitions.count / + awaitedAverageDefinitions.scanned_players + ); +}