mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 03:59:50 +02:00
feat: nivo graphs
This commit is contained in:
1 parent
f2da3994e4
commit
5e6f0e5d18
13 files changed
+157
-364
No files matched your search
-57
@@ -1,57 +0,0 @@
|
||||
import {
|
||||
TIERS,
|
||||
TIER_ROMAN_NUMERALS,
|
||||
fetchAverageDefinitions,
|
||||
fetchTankDefinitions,
|
||||
} from '@blitzkit/core';
|
||||
import { TankPerformanceEphemeral } from '../../../../stores/tankPerformanceEphemeral';
|
||||
import { EChart } from '../../../EChart';
|
||||
|
||||
const averageDefinitions = await fetchAverageDefinitions();
|
||||
const tankDefinitions = await fetchTankDefinitions();
|
||||
const averageDefinitionsArray = Object.entries(averageDefinitions.averages);
|
||||
|
||||
export function BattleDistributionAcrossTiers() {
|
||||
const playerCountPeriod = TankPerformanceEphemeral.use(
|
||||
(state) => state.playerCountPeriod,
|
||||
);
|
||||
|
||||
return (
|
||||
<EChart
|
||||
height="25rem"
|
||||
title="Battle distribution across tiers"
|
||||
option={{
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: TIERS.map((tier) => TIER_ROMAN_NUMERALS[tier]),
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: TIERS.map((tier) => {
|
||||
return averageDefinitionsArray.reduce(
|
||||
(accumulator, [idString, entry]) => {
|
||||
const id = Number(idString);
|
||||
const tank = tankDefinitions.tanks[id];
|
||||
|
||||
if (tank === undefined || tank.tier !== tier) {
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
return (
|
||||
accumulator +
|
||||
entry.mu.battles * entry.samples[playerCountPeriod]
|
||||
);
|
||||
},
|
||||
0,
|
||||
);
|
||||
}),
|
||||
type: 'bar',
|
||||
},
|
||||
],
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
import {
|
||||
TANK_CLASSES,
|
||||
TIERS,
|
||||
TIER_ROMAN_NUMERALS,
|
||||
fetchAverageDefinitions,
|
||||
fetchTankDefinitions,
|
||||
} from '@blitzkit/core';
|
||||
import strings from '@blitzkit/core/lang/en-US.json';
|
||||
import { TankPerformanceEphemeral } from '../../../../stores/tankPerformanceEphemeral';
|
||||
import { EChart } from '../../../EChart';
|
||||
|
||||
const averageDefinitions = await fetchAverageDefinitions();
|
||||
const tankDefinitions = await fetchTankDefinitions();
|
||||
const averageDefinitionsArray = Object.entries(averageDefinitions.averages);
|
||||
|
||||
export function BattleDistributionAcrossTiersByClass() {
|
||||
const playerCountPeriod = TankPerformanceEphemeral.use(
|
||||
(state) => state.playerCountPeriod,
|
||||
);
|
||||
|
||||
return (
|
||||
<EChart
|
||||
height="25rem"
|
||||
title="Battle distribution across tiers by class"
|
||||
option={{
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: TIERS.map((tier) => TIER_ROMAN_NUMERALS[tier]),
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
},
|
||||
legend: {
|
||||
data: TANK_CLASSES.map((c) => strings.common.tank_class_short[c]),
|
||||
},
|
||||
series: TANK_CLASSES.map((c) => ({
|
||||
name: strings.common.tank_class_short[c],
|
||||
data: TIERS.map((tier) => {
|
||||
return averageDefinitionsArray.reduce(
|
||||
(accumulator, [idString, entry]) => {
|
||||
const id = Number(idString);
|
||||
const tank = tankDefinitions.tanks[id];
|
||||
|
||||
if (
|
||||
tank === undefined ||
|
||||
tank.tier !== tier ||
|
||||
tank.class !== c
|
||||
) {
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
return (
|
||||
accumulator +
|
||||
entry.mu.battles * entry.samples[playerCountPeriod]
|
||||
);
|
||||
},
|
||||
0,
|
||||
);
|
||||
}),
|
||||
type: 'bar',
|
||||
})),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
import {
|
||||
fetchAverageDefinitions,
|
||||
fetchTankDefinitions,
|
||||
formatCompact,
|
||||
TANK_CLASSES,
|
||||
TankClass,
|
||||
TIER_ROMAN_NUMERALS,
|
||||
TIERS,
|
||||
} from '@blitzkit/core';
|
||||
import strings from '@blitzkit/core/lang/en-US.json';
|
||||
import { Box, Flex, Heading } from '@radix-ui/themes';
|
||||
import { useAveragesExclusionRatio } from '../../../../hooks/useAveragesExclusionRatio';
|
||||
import { TankPerformanceEphemeral } from '../../../../stores/tankPerformanceEphemeral';
|
||||
import { ThemedBar } from '../../../Nivo/ThemedBar';
|
||||
|
||||
const averageDefinitions = await fetchAverageDefinitions();
|
||||
const tankDefinitions = await fetchTankDefinitions();
|
||||
const averageDefinitionsArray = Object.entries(averageDefinitions.averages);
|
||||
|
||||
export function BattleDistributionAcrossTiers() {
|
||||
const playerCountPeriod = TankPerformanceEphemeral.use(
|
||||
(state) => state.playerCountPeriod,
|
||||
);
|
||||
const ratio = useAveragesExclusionRatio();
|
||||
|
||||
return (
|
||||
<Flex direction="column" gap="4">
|
||||
<Heading align="center">Players by tier & class</Heading>
|
||||
<Box height="25rem">
|
||||
<ThemedBar
|
||||
data={TIERS.map((tier) => {
|
||||
const players: Record<TankClass, number> = {
|
||||
0: 0,
|
||||
1: 0,
|
||||
2: 0,
|
||||
3: 0,
|
||||
};
|
||||
|
||||
averageDefinitionsArray.forEach(([idString, entry]) => {
|
||||
const id = Number(idString);
|
||||
const tank = tankDefinitions.tanks[id];
|
||||
|
||||
if (tank === undefined || tank.tier !== tier) return;
|
||||
|
||||
players[tank.class] += entry.samples[playerCountPeriod] * ratio;
|
||||
});
|
||||
|
||||
const bar: Record<string, number | string> = {
|
||||
tier: TIER_ROMAN_NUMERALS[tier],
|
||||
};
|
||||
|
||||
TANK_CLASSES.forEach((c) => {
|
||||
bar[strings.common.tank_class_short[c]] = players[c];
|
||||
});
|
||||
|
||||
return bar;
|
||||
})}
|
||||
keys={TANK_CLASSES.map((c) => strings.common.tank_class_short[c])}
|
||||
indexBy="tier"
|
||||
margin={{ right: 90, bottom: 50, left: 90 }}
|
||||
axisBottom={{
|
||||
legend: 'Tier',
|
||||
legendPosition: 'middle',
|
||||
legendOffset: 32,
|
||||
}}
|
||||
axisLeft={{
|
||||
legend: 'Players',
|
||||
legendPosition: 'middle',
|
||||
legendOffset: -60,
|
||||
format: formatCompact,
|
||||
}}
|
||||
legends={[
|
||||
{
|
||||
dataFrom: 'keys',
|
||||
anchor: 'bottom-right',
|
||||
direction: 'column',
|
||||
translateX: 120,
|
||||
itemWidth: 100,
|
||||
itemHeight: 20,
|
||||
},
|
||||
]}
|
||||
valueFormat={formatCompact}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
import { Flex } from '@radix-ui/themes';
|
||||
import { BattleDistributionAcrossTiers } from './components/BattleDistributionAcrossTiers';
|
||||
import { BattleDistributionAcrossTiersByClass } from './components/BattleDistributionAcrossTiersByClass';
|
||||
import { BattleDistributionAcrossTiers } from './components/BattleDistributionAcrossTiersNivo';
|
||||
|
||||
export function Charts() {
|
||||
return (
|
||||
<Flex justify="center">
|
||||
<Flex direction="column" maxWidth="45rem" flexGrow="1" py="6" gap="9">
|
||||
<BattleDistributionAcrossTiers />
|
||||
<BattleDistributionAcrossTiersByClass />
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Flex, Select, Text } from '@radix-ui/themes';
|
||||
import {
|
||||
PlayerCountPeriod,
|
||||
TankPerformanceEphemeral,
|
||||
type PlayerCountPeriod,
|
||||
} from '../../stores/tankPerformanceEphemeral';
|
||||
|
||||
export function PlayerCountControl() {
|
||||
@@ -23,24 +23,13 @@ export function PlayerCountControl() {
|
||||
>
|
||||
<Select.Trigger />
|
||||
<Select.Content>
|
||||
<Select.Item value={PlayerCountPeriod.Past120Days}>
|
||||
Past 120 days
|
||||
</Select.Item>
|
||||
<Select.Item value={PlayerCountPeriod.Past90Days}>
|
||||
Past 90 days
|
||||
</Select.Item>
|
||||
<Select.Item value={PlayerCountPeriod.Past60Days}>
|
||||
Past 60 days
|
||||
</Select.Item>
|
||||
<Select.Item value={PlayerCountPeriod.ThisMonth}>
|
||||
This month
|
||||
</Select.Item>
|
||||
<Select.Item value={PlayerCountPeriod.ThisWeek}>
|
||||
This week
|
||||
</Select.Item>
|
||||
<Select.Item value={PlayerCountPeriod.Yesterday}>
|
||||
Yesterday
|
||||
</Select.Item>
|
||||
<Select.Item value="total">Total</Select.Item>
|
||||
<Select.Item value="d_120">Past 120 days</Select.Item>
|
||||
<Select.Item value="d_90">Past 90 days</Select.Item>
|
||||
<Select.Item value="d_60">Past 60 days</Select.Item>
|
||||
<Select.Item value="d_30">This month</Select.Item>
|
||||
<Select.Item value="d_7">This week</Select.Item>
|
||||
<Select.Item value="d_1">Yesterday</Select.Item>
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
</Flex>
|
||||
|
||||
Reference in new issue
Block a user