mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
feat: nivo graph
This commit is contained in:
1 parent
499bcde320
commit
86d7007dc2
8 files changed
+102
-2
No files matched your search
Vendored
+1
@@ -102,6 +102,7 @@
|
||||
"NEGATIVEX",
|
||||
"NEGATIVEY",
|
||||
"NEGATIVEZ",
|
||||
"nivo",
|
||||
"nmatname",
|
||||
"noout",
|
||||
"normalmap",
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@gltf-transform/core": "^3.9.0",
|
||||
"@nivo/bar": "^0.87.0",
|
||||
"@octokit/plugin-throttling": "^8.1.3",
|
||||
"@octokit/rest": "^20.0.1",
|
||||
"@prisma/client": "^5.4.1",
|
||||
|
||||
@@ -16,7 +16,7 @@ export function Header() {
|
||||
const sort = useTankPerformanceSort();
|
||||
|
||||
return (
|
||||
<Table.Header style={{ whiteSpace: 'nowrap' }}>
|
||||
<Table.Header>
|
||||
<Table.Row align="center">
|
||||
<Table.ColumnHeaderCell>Tank</Table.ColumnHeaderCell>
|
||||
{tankPerformanceSortTypeNamesArray.map((type) => {
|
||||
@@ -24,6 +24,7 @@ export function Header() {
|
||||
|
||||
return (
|
||||
<Table.ColumnHeaderCell
|
||||
px="2"
|
||||
key={type}
|
||||
width="0"
|
||||
justify="center"
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
'use client';
|
||||
|
||||
import { ResponsiveBar } from '@nivo/bar';
|
||||
import { Box, Flex, Heading } from '@radix-ui/themes';
|
||||
import { times } from 'lodash';
|
||||
import { use } from 'react';
|
||||
import { TankClass } from '../../../../components/Tanks';
|
||||
import { TANK_CLASSES } from '../../../../components/Tanks/components/Item/constants';
|
||||
import { averageDefinitionsArray } from '../../../../core/blitzkit/averageDefinitions';
|
||||
import {
|
||||
tankDefinitions,
|
||||
Tier,
|
||||
} from '../../../../core/blitzkit/tankDefinitions';
|
||||
import { TIER_ROMAN_NUMERALS } from '../../../../core/blitzkit/tankDefinitions/constants';
|
||||
import { nivoTheme } from '../../../../core/nivo/theme';
|
||||
import strings from '../../../../lang/en-US.json';
|
||||
|
||||
export function TierBreakdown() {
|
||||
const awaitedAverageDefinitionsArray = use(averageDefinitionsArray);
|
||||
const awaitedTankDefinitions = use(tankDefinitions);
|
||||
const numberFormat = Intl.NumberFormat(undefined, { notation: 'compact' });
|
||||
|
||||
return (
|
||||
<Flex justify="center" py="6">
|
||||
<Flex direction="column" flexGrow="1" gap="4" maxWidth="640px">
|
||||
<Heading ml="2" size="4">
|
||||
Players (30d) per tier
|
||||
</Heading>
|
||||
|
||||
<Box height="320px" width="100%">
|
||||
<ResponsiveBar
|
||||
{...nivoTheme}
|
||||
data={times(10, (index) => {
|
||||
const tier = (index + 1) as Tier;
|
||||
const tierTanks = awaitedAverageDefinitionsArray.filter(
|
||||
({ id }) => awaitedTankDefinitions[id].tier === tier,
|
||||
);
|
||||
const populations: Record<TankClass, number> = {
|
||||
'AT-SPG': 0,
|
||||
heavyTank: 0,
|
||||
lightTank: 0,
|
||||
mediumTank: 0,
|
||||
};
|
||||
|
||||
tierTanks.forEach((stats) => {
|
||||
const tank = awaitedTankDefinitions[stats.id];
|
||||
populations[tank.class] += stats.mu.battles * stats.samples;
|
||||
});
|
||||
|
||||
TANK_CLASSES.forEach((tankClass) => {
|
||||
populations[tankClass] = Math.round(populations[tankClass]);
|
||||
});
|
||||
|
||||
return { tier: TIER_ROMAN_NUMERALS[tier], ...populations };
|
||||
})}
|
||||
keys={[...TANK_CLASSES].reverse()}
|
||||
indexBy="tier"
|
||||
colors={{ scheme: 'dark2' }}
|
||||
label={(d) => numberFormat.format(d.value as number)}
|
||||
margin={{ right: 96, bottom: 20, left: 40 }}
|
||||
legendLabel={(d) =>
|
||||
strings.common.tank_class_short[d.id as TankClass]
|
||||
}
|
||||
axisLeft={{
|
||||
tickSize: 0,
|
||||
format: (value) => numberFormat.format(value as number),
|
||||
}}
|
||||
axisBottom={{ tickSize: 0 }}
|
||||
legends={[
|
||||
{
|
||||
dataFrom: 'keys',
|
||||
anchor: 'bottom-right',
|
||||
direction: 'column',
|
||||
translateX: 120,
|
||||
itemsSpacing: 4,
|
||||
itemWidth: 100,
|
||||
itemHeight: 20,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
@@ -3,12 +3,14 @@ import { TankFiltersProvider } from '../../../stores/tankFilters';
|
||||
import { FilterControl } from '../tankopedia/components/FilterControl';
|
||||
import { Info } from './components/Info';
|
||||
import { TankTable } from './components/Table';
|
||||
import { TierBreakdown } from './components/TierBreakdown';
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<TankFiltersProvider>
|
||||
<PageWrapper color="jade" noMaxWidth>
|
||||
<Info />
|
||||
<TierBreakdown />
|
||||
<FilterControl />
|
||||
<TankTable />
|
||||
</PageWrapper>
|
||||
|
||||
@@ -111,7 +111,7 @@ export const tankPerformanceTool: Tool = {
|
||||
id: 'tank-performance',
|
||||
title: 'Tank performance',
|
||||
description: 'Tank performance statistics',
|
||||
pageDescription: 'Tank performance statistics in World of Tanks Blitz',
|
||||
pageDescription: 'Best tanks and their performances in World of Tanks Blitz',
|
||||
button: {
|
||||
text: 'View tanks',
|
||||
color: 'jade',
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Theme } from '@nivo/core';
|
||||
|
||||
export const nivoTheme = {
|
||||
theme: {
|
||||
text: { fill: 'var(--gray-11)' },
|
||||
grid: { line: { stroke: 'var(--gray-3)' } },
|
||||
} satisfies Theme,
|
||||
borderRadius: 2,
|
||||
innerPadding: 1,
|
||||
};
|
||||
Reference in new issue
Block a user