mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 20:19:49 +02:00
feat: total bar
This commit is contained in:
1 parent
b556f5f7e8
commit
a7f68364f3
6 files changed
+109
-14
No files matched your search
@@ -4,15 +4,12 @@ import { InfoCircledIcon } from '@radix-ui/react-icons';
|
|||||||
import { Callout, Flex } from '@radix-ui/themes';
|
import { Callout, Flex } from '@radix-ui/themes';
|
||||||
import { use } from 'react';
|
import { use } from 'react';
|
||||||
import { averageDefinitions } from '../../../../core/blitzkit/averageDefinitions';
|
import { averageDefinitions } from '../../../../core/blitzkit/averageDefinitions';
|
||||||
import { discoveredIdsDefinitions } from '../../../../core/blitzkit/discoveredIdDefinitions';
|
import { useAveragesExclusionRatio } from '../../../../hooks/useAveragesExclusionRatio';
|
||||||
|
|
||||||
export function Info() {
|
export function Info() {
|
||||||
const awaitedAverageDefinitions = use(averageDefinitions);
|
const awaitedAverageDefinitions = use(averageDefinitions);
|
||||||
const awaitedDiscoveredIdsDefinitions = use(discoveredIdsDefinitions);
|
|
||||||
const numberFormat = Intl.NumberFormat(undefined, { notation: 'compact' });
|
const numberFormat = Intl.NumberFormat(undefined, { notation: 'compact' });
|
||||||
const ratio =
|
const ratio = useAveragesExclusionRatio();
|
||||||
awaitedDiscoveredIdsDefinitions.count /
|
|
||||||
awaitedAverageDefinitions.scanned_players;
|
|
||||||
const samples = ratio * awaitedAverageDefinitions.sampled_players;
|
const samples = ratio * awaitedAverageDefinitions.sampled_players;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { Table } from '@radix-ui/themes';
|
|||||||
import { memo, use } from 'react';
|
import { memo, use } from 'react';
|
||||||
import { TankRowHeaderCell } from '../../../../components/TankRowHeaderCell';
|
import { TankRowHeaderCell } from '../../../../components/TankRowHeaderCell';
|
||||||
import { averageDefinitions } from '../../../../core/blitzkit/averageDefinitions';
|
import { averageDefinitions } from '../../../../core/blitzkit/averageDefinitions';
|
||||||
import { discoveredIdsDefinitions } from '../../../../core/blitzkit/discoveredIdDefinitions';
|
|
||||||
import { TankDefinition } from '../../../../core/blitzkit/tankDefinitions';
|
import { TankDefinition } from '../../../../core/blitzkit/tankDefinitions';
|
||||||
|
import { useAveragesExclusionRatio } from '../../../../hooks/useAveragesExclusionRatio';
|
||||||
|
|
||||||
interface TankRowProps {
|
interface TankRowProps {
|
||||||
tank: TankDefinition;
|
tank: TankDefinition;
|
||||||
@@ -11,13 +11,10 @@ interface TankRowProps {
|
|||||||
|
|
||||||
export const TankRow = memo<TankRowProps>(
|
export const TankRow = memo<TankRowProps>(
|
||||||
({ tank }) => {
|
({ tank }) => {
|
||||||
const awaitedDiscoveredIdsDefinitions = use(discoveredIdsDefinitions);
|
|
||||||
const awaitedAverageDefinitions = use(averageDefinitions);
|
const awaitedAverageDefinitions = use(averageDefinitions);
|
||||||
const averages = awaitedAverageDefinitions.averages[tank.id];
|
const averages = awaitedAverageDefinitions.averages[tank.id];
|
||||||
const numberFormat = Intl.NumberFormat(undefined, { notation: 'compact' });
|
const numberFormat = Intl.NumberFormat(undefined, { notation: 'compact' });
|
||||||
const ratio =
|
const ratio = useAveragesExclusionRatio();
|
||||||
awaitedDiscoveredIdsDefinitions.count /
|
|
||||||
awaitedAverageDefinitions.scanned_players;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { useTankFilters } from '../../../../stores/tankFilters';
|
|||||||
import { useTankPerformanceSort } from '../../../../stores/tankPerformanceSort';
|
import { useTankPerformanceSort } from '../../../../stores/tankPerformanceSort';
|
||||||
import { RowLoader } from './RowLoader';
|
import { RowLoader } from './RowLoader';
|
||||||
import { TankRow } from './TankRow';
|
import { TankRow } from './TankRow';
|
||||||
|
import { Total } from './Total';
|
||||||
|
|
||||||
const PREVIEW_COUNT = 10;
|
const PREVIEW_COUNT = 10;
|
||||||
const DEFAULT_LOADED_ROWS = 25;
|
const DEFAULT_LOADED_ROWS = 25;
|
||||||
@@ -121,6 +122,8 @@ export function Tanks() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Table.Body>
|
<Table.Body>
|
||||||
|
<Total tanks={tanks} />
|
||||||
|
|
||||||
{tanks.slice(0, loadedRows).map((averages) => {
|
{tanks.slice(0, loadedRows).map((averages) => {
|
||||||
const tank = awaitedTankDefinitions[averages.id];
|
const tank = awaitedTankDefinitions[averages.id];
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -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<TotalProps>(
|
||||||
|
({ 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 (
|
||||||
|
<Table.Row>
|
||||||
|
<Table.RowHeaderCell>Total</Table.RowHeaderCell>
|
||||||
|
<Table.Cell align="center">{(winrate * 100).toFixed(1)}%</Table.Cell>
|
||||||
|
<Table.Cell align="center">
|
||||||
|
{numberFormat.format(ratio * players)}
|
||||||
|
</Table.Cell>
|
||||||
|
<Table.Cell align="center">
|
||||||
|
{numberFormat.format(ratio * battles)}
|
||||||
|
</Table.Cell>
|
||||||
|
<Table.Cell align="center">
|
||||||
|
{Math.round(damage).toLocaleString()}
|
||||||
|
</Table.Cell>
|
||||||
|
<Table.Cell align="center">
|
||||||
|
{Math.round(survival * 100).toFixed(1)}%
|
||||||
|
</Table.Cell>
|
||||||
|
<Table.Cell align="center">
|
||||||
|
{Math.round(xp).toLocaleString()}
|
||||||
|
</Table.Cell>
|
||||||
|
<Table.Cell align="center">{kills.toFixed(2)}</Table.Cell>
|
||||||
|
<Table.Cell align="center">{spots.toFixed(2)}</Table.Cell>
|
||||||
|
<Table.Cell align="center">{(accuracy * 100).toFixed(0)}%</Table.Cell>
|
||||||
|
<Table.Cell align="center">{shots.toFixed(1)}</Table.Cell>
|
||||||
|
<Table.Cell align="center">{hits.toFixed(1)}</Table.Cell>
|
||||||
|
<Table.Cell align="center">{damageRatio.toFixed(2)}</Table.Cell>
|
||||||
|
<Table.Cell align="center">
|
||||||
|
{Math.round(damageReceived).toLocaleString()}
|
||||||
|
</Table.Cell>
|
||||||
|
<Table.Cell align="center">{capturePoints.toFixed(2)}</Table.Cell>
|
||||||
|
</Table.Row>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(prev, next) => prev.tanks === next.tanks,
|
||||||
|
);
|
||||||
@@ -13,6 +13,10 @@ export interface AverageDefinitionsEntry {
|
|||||||
r: AverageDefinitionsAllStats;
|
r: AverageDefinitionsAllStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AverageDefinitionsEntryWithId extends AverageDefinitionsEntry {
|
||||||
|
id: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface AverageDefinitionsEntrySubPartial {
|
export interface AverageDefinitionsEntrySubPartial {
|
||||||
samples: number;
|
samples: number;
|
||||||
mu: Partial<AverageDefinitionsAllStats>;
|
mu: Partial<AverageDefinitionsAllStats>;
|
||||||
@@ -36,8 +40,11 @@ export const averageDefinitions = fetch(asset('definitions/averages.pb'))
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const averageDefinitionsArray = averageDefinitions.then((data) =>
|
export const averageDefinitionsArray = averageDefinitions.then((data) =>
|
||||||
Object.entries(data.averages).map(([key, value]) => ({
|
Object.entries(data.averages).map(
|
||||||
id: Number(key),
|
([key, value]) =>
|
||||||
...(value as AverageDefinitionsEntry),
|
({
|
||||||
})),
|
id: Number(key),
|
||||||
|
...(value as AverageDefinitionsEntry),
|
||||||
|
}) satisfies AverageDefinitionsEntryWithId,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
@@ -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
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user