diff --git a/packages/website/src/components/CompareCell.tsx b/packages/website/src/components/CompareCell.tsx index 16812803d..28f768a57 100644 --- a/packages/website/src/components/CompareCell.tsx +++ b/packages/website/src/components/CompareCell.tsx @@ -16,7 +16,7 @@ export function CompareCell({ value, truth, style, - direction, + direction = CompareCellDirection.HIGHER_IS_BETTER, ...props }: CompareCellProps) { const percentage = value / truth - 1; diff --git a/packages/website/src/components/Performance/TankRow.tsx b/packages/website/src/components/Performance/TankRow.tsx index 9137bdecd..6ceb47392 100644 --- a/packages/website/src/components/Performance/TankRow.tsx +++ b/packages/website/src/components/Performance/TankRow.tsx @@ -1,24 +1,26 @@ -import { TankDefinition, formatCompact } from '@blitzkit/core'; -import { Table } from '@radix-ui/themes'; -import { memo } from 'react'; -import { awaitableAverageDefinitions } from '../../core/awaitables/averageDefinitions'; -import { useAveragesExclusionRatio } from '../../hooks/useAveragesExclusionRatio'; -import { useLocale } from '../../hooks/useLocale'; -import { Performance } from '../../stores/performance'; -import { TankRowHeaderCell } from '../TankRowHeaderCell'; +import { TankDefinition, formatCompact } from "@blitzkit/core"; +import { Table } from "@radix-ui/themes"; +import { memo } from "react"; +import { awaitableAverageDefinitions } from "../../core/awaitables/averageDefinitions"; +import { useAveragesExclusionRatio } from "../../hooks/useAveragesExclusionRatio"; +import { useLocale } from "../../hooks/useLocale"; +import { Performance } from "../../stores/performance"; +import { CompareCell, CompareCellDirection } from "../CompareCell"; +import { TankRowHeaderCell } from "../TankRowHeaderCell"; interface TankRowProps { tank: TankDefinition; + average: Record; } const averageDefinitions = await awaitableAverageDefinitions; export const TankRow = memo( - ({ tank }) => { + ({ tank, average }) => { const averages = averageDefinitions.averages[tank.id]; const ratio = useAveragesExclusionRatio(); const playerCountPeriod = Performance.use( - (state) => state.playerCountPeriod, + (state) => state.playerCountPeriod ); const { locale } = useLocale(); @@ -26,59 +28,108 @@ export const TankRow = memo( - + {((averages.mu.wins / averages.mu.battles) * 100).toFixed(1)}% - + {formatCompact( locale, - Math.round(ratio * averages.samples[playerCountPeriod]), + Math.round(ratio * averages.samples[playerCountPeriod]) )} - + {Math.round( - averages.mu.damage_dealt / averages.mu.battles, + averages.mu.damage_dealt / averages.mu.battles ).toLocaleString(locale)} - - + + {Math.round( - (averages.mu.survived_battles / averages.mu.battles) * 100, + (averages.mu.survived_battles / averages.mu.battles) * 100 )} % - - + + {Math.round(averages.mu.xp / averages.mu.battles).toLocaleString( - locale, + locale )} - - + + {(averages.mu.frags / averages.mu.battles).toFixed(2)} - - + + {(averages.mu.spotted / averages.mu.battles).toFixed(2)} - - + + {Math.round((averages.mu.hits / averages.mu.shots) * 100)}% - - + + {(averages.mu.shots / averages.mu.battles).toFixed(1)} - - + + {(averages.mu.hits / averages.mu.battles).toFixed(1)} - - + + {(averages.mu.damage_dealt / averages.mu.damage_received).toFixed(2)} - - + + {Math.round( - averages.mu.damage_received / averages.mu.battles, + averages.mu.damage_received / averages.mu.battles ).toLocaleString(locale)} - - + + {(averages.mu.capture_points / averages.mu.battles).toFixed(2)} - + ); }, - (prev, next) => prev.tank.id === next.tank.id, + (prev, next) => prev.tank.id === next.tank.id ); diff --git a/packages/website/src/components/Performance/Tanks.tsx b/packages/website/src/components/Performance/Tanks.tsx index 8c095c0b0..8e67de851 100644 --- a/packages/website/src/components/Performance/Tanks.tsx +++ b/packages/website/src/components/Performance/Tanks.tsx @@ -1,17 +1,27 @@ +import { formatCompact, type BlitzkitStats } from "@blitzkit/core"; import { Table } from "@radix-ui/themes"; import { times } from "lodash-es"; -import { Fragment, Suspense, useEffect, useMemo, useState } from "react"; +import { + Fragment, + Suspense, + useCallback, + useEffect, + useMemo, + useState, +} from "react"; import usePromise from "react-promise-suspense"; import { awaitableAverageDefinitions } from "../../core/awaitables/averageDefinitions"; import { awaitableTankDefinitions } from "../../core/awaitables/tankDefinitions"; import { filterTanks } from "../../core/blitzkit/filterTanks"; +import { useAveragesExclusionRatio } from "../../hooks/useAveragesExclusionRatio"; +import { useLocale } from "../../hooks/useLocale"; import { Performance } from "../../stores/performance"; import { TankFilters } from "../../stores/tankFilters"; import { TankPerformanceSort } from "../../stores/tankPerformanceSort"; import type { MaybeSkeletonComponentProps } from "../../types/maybeSkeletonComponentProps"; +import { StickyRowHeaderCell } from "../StickyRowHeaderCell"; import { RowLoader } from "./RowLoader"; import { TankRow } from "./TankRow"; -import { Total } from "./Total"; const PREVIEW_COUNT = 10; const DEFAULT_LOADED_ROWS = 25; @@ -145,9 +155,83 @@ export function Tanks({ skeleton }: MaybeSkeletonComponentProps) { setLoadedRows(DEFAULT_LOADED_ROWS); }, [filters, sort]); + const playerCountPeriod = Performance.use((state) => state.playerCountPeriod); + const { strings, locale } = useLocale(); + const ratio = useAveragesExclusionRatio(); + const sum = useCallback( + (slice: (tank: BlitzkitStats) => number) => { + return tanksSorted.reduce( + (acc, tank) => acc + tank.samples[playerCountPeriod] * slice(tank.mu), + 0 + ); + }, + [tanksSorted] + ); + + 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; + + const average = { + battles, + winrate, + damage, + survival, + xp, + kills, + spots, + hits, + shots, + accuracy, + damageReceived, + damageRatio, + capturePoints, + }; + return ( - + + + {strings.website.tools.performance.table.tanks.total} + + {(winrate * 100).toFixed(1)}% + + {formatCompact( + locale, + ratio * averageDefinitions.samples[playerCountPeriod] + )} + + + {Math.round(damage).toLocaleString(locale)} + + + {Math.round(survival * 100).toFixed(1)}% + + + {Math.round(xp).toLocaleString(locale)} + + {kills.toFixed(2)} + {spots.toFixed(2)} + {(accuracy * 100).toFixed(0)}% + {shots.toFixed(1)} + {hits.toFixed(1)} + {damageRatio.toFixed(2)} + + {Math.round(damageReceived).toLocaleString(locale)} + + {capturePoints.toFixed(2)} + {tanksSorted.slice(0, loadedRows).map((averages) => { const tank = tankDefinitions.tanks[averages.id]; @@ -157,7 +241,7 @@ export function Tanks({ skeleton }: MaybeSkeletonComponentProps) { return ( }> - + ); diff --git a/packages/website/src/components/Performance/Total.tsx b/packages/website/src/components/Performance/Total.tsx deleted file mode 100644 index dbb544ddf..000000000 --- a/packages/website/src/components/Performance/Total.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import { - AverageDefinitionsEntry, - formatCompact, - type BlitzkitStats, -} from "@blitzkit/core"; -import { Table } from "@radix-ui/themes"; -import { memo, useCallback } from "react"; -import { awaitableAverageDefinitions } from "../../core/awaitables/averageDefinitions"; -import { useAveragesExclusionRatio } from "../../hooks/useAveragesExclusionRatio"; -import { useLocale } from "../../hooks/useLocale"; -import { Performance } from "../../stores/performance"; -import { StickyRowHeaderCell } from "../StickyRowHeaderCell"; - -export interface AverageDefinitionsEntryWithId extends AverageDefinitionsEntry { - id: number; -} - -interface TotalProps { - tanks: AverageDefinitionsEntryWithId[]; -} - -const averageDefinitions = await awaitableAverageDefinitions; - -export const Total = memo( - ({ tanks }) => { - const playerCountPeriod = Performance.use( - (state) => state.playerCountPeriod - ); - const { strings, locale } = useLocale(); - const ratio = useAveragesExclusionRatio(); - const sum = useCallback( - (slice: (tank: BlitzkitStats) => number) => { - return tanks.reduce( - (acc, tank) => acc + tank.samples[playerCountPeriod] * slice(tank.mu), - 0 - ); - }, - [tanks] - ); - - 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 ( - - - {strings.website.tools.performance.table.tanks.total} - - {(winrate * 100).toFixed(1)}% - - {formatCompact( - locale, - ratio * averageDefinitions.samples[playerCountPeriod] - )} - - - {Math.round(damage).toLocaleString(locale)} - - - {Math.round(survival * 100).toFixed(1)}% - - - {Math.round(xp).toLocaleString(locale)} - - {kills.toFixed(2)} - {spots.toFixed(2)} - {(accuracy * 100).toFixed(0)}% - {shots.toFixed(1)} - {hits.toFixed(1)} - {damageRatio.toFixed(2)} - - {Math.round(damageReceived).toLocaleString(locale)} - - {capturePoints.toFixed(2)} - - ); - }, - (prev, next) => prev.tanks === next.tanks -);