From eb95230a5f4e7f1cbc37ddf9723f00ff57957738 Mon Sep 17 00:00:00 2001
From: tresabhi <43380238+tresabhi@users.noreply.github.com>
Date: Mon, 23 Dec 2024 12:48:52 -0600
Subject: [PATCH] feat: start of charts
---
.../src/components/Charts/ChartsControl.tsx | 32 ++++++
.../src/components/Charts/PlayersInPeriod.tsx | 99 +++++++++++++++++
.../components/PlayersByTierAndClass.tsx | 100 ------------------
.../components/Performance/Charts/index.tsx | 12 ---
.../components/Performance/ModeSwitcher.tsx | 31 ------
packages/website/src/constants/tools.ts | 7 +-
.../website/src/pages/tools/charts/_index.tsx | 29 +++++
.../src/pages/tools/charts/index.astro | 9 ++
.../src/pages/tools/performance/_index.tsx | 16 +--
packages/website/src/stores/charts.ts | 15 +++
.../src/stores/tankPerformanceEphemeral.ts | 7 --
11 files changed, 192 insertions(+), 165 deletions(-)
create mode 100644 packages/website/src/components/Charts/ChartsControl.tsx
create mode 100644 packages/website/src/components/Charts/PlayersInPeriod.tsx
delete mode 100644 packages/website/src/components/Performance/Charts/components/PlayersByTierAndClass.tsx
delete mode 100644 packages/website/src/components/Performance/Charts/index.tsx
delete mode 100644 packages/website/src/components/Performance/ModeSwitcher.tsx
create mode 100644 packages/website/src/pages/tools/charts/_index.tsx
create mode 100644 packages/website/src/pages/tools/charts/index.astro
create mode 100644 packages/website/src/stores/charts.ts
diff --git a/packages/website/src/components/Charts/ChartsControl.tsx b/packages/website/src/components/Charts/ChartsControl.tsx
new file mode 100644
index 000000000..8c019dd77
--- /dev/null
+++ b/packages/website/src/components/Charts/ChartsControl.tsx
@@ -0,0 +1,32 @@
+import { Flex, Select, Text } from '@radix-ui/themes';
+import { Charts, type ChartsPeriod } from '../../stores/charts';
+
+export function ChartsControl() {
+ const period = Charts.use((state) => state.period);
+ const mutateCharts = Charts.useMutation();
+
+ return (
+
+ Player count
+ {
+ mutateCharts((draft) => {
+ draft.period = period as ChartsPeriod;
+ });
+ }}
+ >
+
+
+ Total
+ Past 120 days
+ Past 90 days
+ Past 60 days
+ This month
+ This week
+ Yesterday
+
+
+
+ );
+}
diff --git a/packages/website/src/components/Charts/PlayersInPeriod.tsx b/packages/website/src/components/Charts/PlayersInPeriod.tsx
new file mode 100644
index 000000000..7d109ca99
--- /dev/null
+++ b/packages/website/src/components/Charts/PlayersInPeriod.tsx
@@ -0,0 +1,99 @@
+import {
+ TANK_CLASSES,
+ TIERS,
+ TIER_ROMAN_NUMERALS,
+ TankClass,
+ formatCompact,
+} from '@blitzkit/core';
+import strings from '@blitzkit/core/lang/en-US.json';
+import { useStore } from '@nanostores/react';
+import { Box, Flex, Heading } from '@radix-ui/themes';
+import { awaitableAverageDefinitions } from '../../core/awaitables/averageDefinitions';
+import { awaitableTankDefinitions } from '../../core/awaitables/tankDefinitions';
+import { filterTank } from '../../core/blitzkit/filterTank';
+import { useAveragesExclusionRatio } from '../../hooks/useAveragesExclusionRatio';
+import { Charts } from '../../stores/charts';
+import { $tankFilters } from '../../stores/tankFilters';
+import { ThemedBar } from '../Nivo/ThemedBar';
+
+const [tankDefinitions, averageDefinitions] = await Promise.all([
+ awaitableTankDefinitions,
+ awaitableAverageDefinitions,
+]);
+
+const averageDefinitionsArray = Object.entries(averageDefinitions.averages);
+
+export function PlayersInPeriod() {
+ const period = Charts.use((state) => state.period);
+ const ratio = useAveragesExclusionRatio();
+ const filters = useStore($tankFilters);
+ const data = TIERS.map((tier) => {
+ const players: Record = {
+ 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 ||
+ !filterTank(filters, tank)
+ ) {
+ return;
+ }
+
+ players[tank.class] += entry.samples[period] * ratio;
+ });
+
+ const bar: Record = {
+ tier: TIER_ROMAN_NUMERALS[tier],
+ };
+
+ TANK_CLASSES.forEach((c) => {
+ bar[strings.common.tank_class_short[c]] = players[c];
+ });
+
+ return bar;
+ });
+
+ return (
+
+ Players by tier & class
+
+ 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}
+ />
+
+
+ );
+}
diff --git a/packages/website/src/components/Performance/Charts/components/PlayersByTierAndClass.tsx b/packages/website/src/components/Performance/Charts/components/PlayersByTierAndClass.tsx
deleted file mode 100644
index d60694082..000000000
--- a/packages/website/src/components/Performance/Charts/components/PlayersByTierAndClass.tsx
+++ /dev/null
@@ -1,100 +0,0 @@
-import {
- formatCompact,
- TANK_CLASSES,
- TankClass,
- TIER_ROMAN_NUMERALS,
- TIERS,
-} from '@blitzkit/core';
-import strings from '@blitzkit/core/lang/en-US.json';
-import { useStore } from '@nanostores/react';
-import { Box, Flex, Heading } from '@radix-ui/themes';
-import { awaitableAverageDefinitions } from '../../../../core/awaitables/averageDefinitions';
-import { awaitableTankDefinitions } from '../../../../core/awaitables/tankDefinitions';
-import { filterTank } from '../../../../core/blitzkit/filterTank';
-import { useAveragesExclusionRatio } from '../../../../hooks/useAveragesExclusionRatio';
-import { $tankFilters } from '../../../../stores/tankFilters';
-import { TankPerformanceEphemeral } from '../../../../stores/tankPerformanceEphemeral';
-import { ThemedBar } from '../../../Nivo/ThemedBar';
-
-const [tankDefinitions, averageDefinitions] = await Promise.all([
- awaitableTankDefinitions,
- awaitableAverageDefinitions,
-]);
-
-const averageDefinitionsArray = Object.entries(averageDefinitions.averages);
-
-export function PlayersByTierAndClass() {
- const playerCountPeriod = TankPerformanceEphemeral.use(
- (state) => state.playerCountPeriod,
- );
- const ratio = useAveragesExclusionRatio();
- const filters = useStore($tankFilters);
-
- return (
-
- Players by tier & class
-
- {
- const players: Record = {
- 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 ||
- !filterTank(filters, tank)
- ) {
- return;
- }
-
- players[tank.class] += entry.samples[playerCountPeriod] * ratio;
- });
-
- const bar: Record = {
- 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}
- />
-
-
- );
-}
diff --git a/packages/website/src/components/Performance/Charts/index.tsx b/packages/website/src/components/Performance/Charts/index.tsx
deleted file mode 100644
index 8c936d257..000000000
--- a/packages/website/src/components/Performance/Charts/index.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import { Flex } from '@radix-ui/themes';
-import { PlayersByTierAndClass } from './components/PlayersByTierAndClass';
-
-export function Charts() {
- return (
-
-
-
-
-
- );
-}
diff --git a/packages/website/src/components/Performance/ModeSwitcher.tsx b/packages/website/src/components/Performance/ModeSwitcher.tsx
deleted file mode 100644
index ede901745..000000000
--- a/packages/website/src/components/Performance/ModeSwitcher.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import { Tabs } from '@radix-ui/themes';
-import {
- TankPerformanceEphemeral,
- TankPerformanceMode,
-} from '../../stores/tankPerformanceEphemeral';
-
-export function ModeSwitcher() {
- const mode = TankPerformanceEphemeral.use((state) => state.mode);
- const mutateTankPerformanceMode = TankPerformanceEphemeral.useMutation();
-
- return (
- {
- mutateTankPerformanceMode((draft) => {
- draft.mode = Number(value) as TankPerformanceMode;
- });
- }}
- mb="5"
- >
-
-
- Table
-
-
- Charts
-
-
-
- );
-}
diff --git a/packages/website/src/constants/tools.ts b/packages/website/src/constants/tools.ts
index 7c16e3dc0..e2a2d7358 100644
--- a/packages/website/src/constants/tools.ts
+++ b/packages/website/src/constants/tools.ts
@@ -179,14 +179,14 @@ export const tierListTool: Tool = {
export const chartsTool: Tool = {
id: 'charts',
title: 'Charts',
- description: 'Lots of Blitz charts',
+ description: 'Lots of graphs',
pageDescription:
'Charts and graphs on anything and everything about tanks, players, and events in World of Tanks Blitz',
button: {
text: 'Nerd out',
- color: 'yellow',
+ color: 'bronze',
},
- image: '9s68NwR',
+ image: '6fhkljA',
branches: ['main', 'dev', 'opentest', 'preview'],
};
@@ -194,6 +194,7 @@ export const TOOLS: Tool[] = [
tankopediaTool,
compareTool,
performanceTool,
+ chartsTool,
galleryTool,
sessionTool,
tierListTool,
diff --git a/packages/website/src/pages/tools/charts/_index.tsx b/packages/website/src/pages/tools/charts/_index.tsx
new file mode 100644
index 000000000..1dcd37693
--- /dev/null
+++ b/packages/website/src/pages/tools/charts/_index.tsx
@@ -0,0 +1,29 @@
+import { Flex } from '@radix-ui/themes';
+import { ChartsControl } from '../../../components/Charts/ChartsControl';
+import { PlayersInPeriod } from '../../../components/Charts/PlayersInPeriod';
+import { PageWrapper } from '../../../components/PageWrapper';
+import { FilterControl } from '../../../components/TankSearch/components/FilterControl';
+import { Charts } from '../../../stores/charts';
+
+export function Page() {
+ return (
+
+
+
+ );
+}
+
+function Content() {
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/website/src/pages/tools/charts/index.astro b/packages/website/src/pages/tools/charts/index.astro
new file mode 100644
index 000000000..bf78728e5
--- /dev/null
+++ b/packages/website/src/pages/tools/charts/index.astro
@@ -0,0 +1,9 @@
+---
+import { chartsTool } from '../../../constants/tools';
+import ToolLayout from '../../../layouts/ToolLayout.astro';
+import { Page } from './_index';
+---
+
+
+
+
diff --git a/packages/website/src/pages/tools/performance/_index.tsx b/packages/website/src/pages/tools/performance/_index.tsx
index 77d42815f..86aea4d74 100644
--- a/packages/website/src/pages/tools/performance/_index.tsx
+++ b/packages/website/src/pages/tools/performance/_index.tsx
@@ -1,12 +1,9 @@
import { PageWrapper } from '../../../components/PageWrapper';
-import { Charts } from '../../../components/Performance/Charts';
+import { PerformanceInfo } from '../../../components/Performance/PerformanceInfo';
import { PlayerCountControl } from '../../../components/Performance/PlayerCountControl';
import { TankTable } from '../../../components/Performance/Table';
import { FilterControl } from '../../../components/TankSearch/components/FilterControl';
-import {
- TankPerformanceEphemeral,
- TankPerformanceMode,
-} from '../../../stores/tankPerformanceEphemeral';
+import { TankPerformanceEphemeral } from '../../../stores/tankPerformanceEphemeral';
import { TankPerformanceSort } from '../../../stores/tankPerformanceSort';
import type { MaybeSkeletonComponentProps } from '../../../types/maybeSkeletonComponentProps';
@@ -21,18 +18,13 @@ export function Page({ skeleton }: MaybeSkeletonComponentProps) {
}
function Content({ skeleton }: MaybeSkeletonComponentProps) {
- const mode = TankPerformanceEphemeral.use((state) => state.mode);
-
return (
- {/* */}
-
- {/* */}
+
- {mode === TankPerformanceMode.Table && }
- {mode === TankPerformanceMode.Charts && }
+
);
}
diff --git a/packages/website/src/stores/charts.ts b/packages/website/src/stores/charts.ts
new file mode 100644
index 000000000..862bc552b
--- /dev/null
+++ b/packages/website/src/stores/charts.ts
@@ -0,0 +1,15 @@
+import type { Samples } from '@blitzkit/core';
+import { create } from 'zustand';
+import { createContextualStore } from '../core/zustand/createContextualStore';
+
+export interface Charts {
+ period: ChartsPeriod;
+}
+
+export type ChartsPeriod = keyof Samples;
+
+export const Charts = createContextualStore(() =>
+ create()(() => ({
+ period: 'd_30',
+ })),
+);
diff --git a/packages/website/src/stores/tankPerformanceEphemeral.ts b/packages/website/src/stores/tankPerformanceEphemeral.ts
index 912d141f5..1ec8714d3 100644
--- a/packages/website/src/stores/tankPerformanceEphemeral.ts
+++ b/packages/website/src/stores/tankPerformanceEphemeral.ts
@@ -4,12 +4,6 @@ import { createContextualStore } from '../core/zustand/createContextualStore';
export interface TankPerformanceEphemeral {
playerCountPeriod: PlayerCountPeriod;
- mode: TankPerformanceMode;
-}
-
-export enum TankPerformanceMode {
- Table,
- Charts,
}
export type PlayerCountPeriod = keyof Samples;
@@ -17,6 +11,5 @@ export type PlayerCountPeriod = keyof Samples;
export const TankPerformanceEphemeral = createContextualStore(() =>
create()(() => ({
playerCountPeriod: 'd_30',
- mode: TankPerformanceMode.Table,
})),
);