From 03ce75c15d24af3110f46a486612235d2f4b9017 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com>
Date: Fri, 12 Jul 2024 13:53:11 -0500
Subject: [PATCH] feat: variable player count
---
docs/changelogs/1.21.0.md | 15 ++++++
package.json | 2 +-
public/assets/versions.json | 2 +-
.../tank-performance/components/Controls.tsx | 11 +++++
.../tank-performance/components/Header.tsx | 8 ++--
.../components/PlayerCountControl.tsx | 48 +++++++++++++++++++
.../tank-performance/components/RowLoader.tsx | 4 +-
.../tank-performance/components/TankRow.tsx | 8 +++-
.../tank-performance/components/Total.tsx | 20 +++++---
src/app/tools/tank-performance/layout.tsx | 9 ++--
src/app/tools/tank-performance/page.tsx | 4 +-
.../tankPerformancePersistent/constants.ts | 8 ++++
src/stores/tankPerformancePersistent/index.ts | 23 +++++++++
src/stores/tankPerformanceSort/constants.ts | 11 +++--
src/stores/tankPerformanceSort/index.ts | 4 +-
15 files changed, 149 insertions(+), 28 deletions(-)
create mode 100644 docs/changelogs/1.21.0.md
create mode 100644 src/app/tools/tank-performance/components/Controls.tsx
create mode 100644 src/app/tools/tank-performance/components/PlayerCountControl.tsx
create mode 100644 src/stores/tankPerformancePersistent/constants.ts
create mode 100644 src/stores/tankPerformancePersistent/index.ts
diff --git a/docs/changelogs/1.21.0.md b/docs/changelogs/1.21.0.md
new file mode 100644
index 000000000..41433d8a2
--- /dev/null
+++ b/docs/changelogs/1.21.0.md
@@ -0,0 +1,15 @@
+# BlitzKit 1.21.0
+
+Introducing the Tank performance tool!
+
+
+
+## Features
+
+- Added the Tank performance tool
+- The tankopedia search page now loads much faster
+ - Not all tanks are loaded at once; rather, more tanks are loaded as you scroll down the page
+
+## Fixes
+
+- The footer is now better centered
diff --git a/package.json b/package.json
index 76c3e4176..fde4d6437 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "blitzkit",
- "version": "1.20.5",
+ "version": "1.21.0",
"description": "🎉 Tools for everything World of Tanks Blitz",
"main": "src/server.ts",
"type": "module",
diff --git a/public/assets/versions.json b/public/assets/versions.json
index 92635bc2f..bd566573f 100644
--- a/public/assets/versions.json
+++ b/public/assets/versions.json
@@ -1 +1 @@
-["1.10.0","1.10.1","1.10.2","1.11.0","1.12.0","1.12.1","1.12.2","1.12.3","1.12.4","1.12.5","1.12.6","1.12.7","1.12.8","1.12.9","1.13.0","1.13.1","1.13.2","1.13.3","1.14.0","1.14.1","1.14.2","1.14.3","1.14.4","1.15.0","1.15.1","1.15.10","1.15.11","1.15.12","1.15.13","1.15.2","1.15.3","1.15.4","1.15.5","1.15.6","1.15.7","1.15.8","1.15.9","1.16.0","1.16.1","1.16.2","1.16.3","1.16.4","1.17.0","1.17.1","1.17.2","1.18.0","1.18.1","1.18.2","1.18.3","1.19.0","1.19.1","1.19.2","1.19.3","1.19.4","1.19.5","1.19.6","1.20.0","1.20.1","1.20.2","1.20.3","1.20.4","1.20.5","1.3.0","1.3.1","1.3.2","1.3.3","1.4.0","1.4.1","1.5.0","1.5.1","1.5.2","1.5.3","1.5.4","1.6.0","1.7.0","1.7.1","1.7.2","1.7.3-1.7.4","1.7.5","1.7.6","1.7.7","1.8.0","1.8.1","1.9.0","1.9.1","1.9.2","1.9.3","1.9.4","1.9.5"]
\ No newline at end of file
+["1.10.0","1.10.1","1.10.2","1.11.0","1.12.0","1.12.1","1.12.2","1.12.3","1.12.4","1.12.5","1.12.6","1.12.7","1.12.8","1.12.9","1.13.0","1.13.1","1.13.2","1.13.3","1.14.0","1.14.1","1.14.2","1.14.3","1.14.4","1.15.0","1.15.1","1.15.10","1.15.11","1.15.12","1.15.13","1.15.2","1.15.3","1.15.4","1.15.5","1.15.6","1.15.7","1.15.8","1.15.9","1.16.0","1.16.1","1.16.2","1.16.3","1.16.4","1.17.0","1.17.1","1.17.2","1.18.0","1.18.1","1.18.2","1.18.3","1.19.0","1.19.1","1.19.2","1.19.3","1.19.4","1.19.5","1.19.6","1.20.0","1.20.1","1.20.2","1.20.3","1.20.4","1.20.5","1.21.0","1.3.0","1.3.1","1.3.2","1.3.3","1.4.0","1.4.1","1.5.0","1.5.1","1.5.2","1.5.3","1.5.4","1.6.0","1.7.0","1.7.1","1.7.2","1.7.3-1.7.4","1.7.5","1.7.6","1.7.7","1.8.0","1.8.1","1.9.0","1.9.1","1.9.2","1.9.3","1.9.4","1.9.5"]
\ No newline at end of file
diff --git a/src/app/tools/tank-performance/components/Controls.tsx b/src/app/tools/tank-performance/components/Controls.tsx
new file mode 100644
index 000000000..86a34b01d
--- /dev/null
+++ b/src/app/tools/tank-performance/components/Controls.tsx
@@ -0,0 +1,11 @@
+import { FilterControl } from '../../tankopedia/components/FilterControl';
+import { PlayerCountControl } from './PlayerCountControl';
+
+export function Controls() {
+ return (
+ <>
+
+
+ >
+ );
+}
diff --git a/src/app/tools/tank-performance/components/Header.tsx b/src/app/tools/tank-performance/components/Header.tsx
index d4cf02e22..3c3693ffc 100644
--- a/src/app/tools/tank-performance/components/Header.tsx
+++ b/src/app/tools/tank-performance/components/Header.tsx
@@ -9,8 +9,8 @@ import { Flex, IconButton, Table } from '@radix-ui/themes';
import { StickyColumnHeaderCell } from '../../../../components/StickyColumnHeaderCell';
import * as TankPerformanceSort from '../../../../stores/tankPerformanceSort';
import {
- tankPerformanceSortTypeNames,
- tankPerformanceSortTypeNamesArray,
+ TankPerformanceSortTypeNames,
+ TankPerformanceSortTypeNamesArray,
} from '../../../../stores/tankPerformanceSort/constants';
export function Header() {
@@ -21,7 +21,7 @@ export function Header() {
Tank
- {tankPerformanceSortTypeNamesArray.map((type) => {
+ {TankPerformanceSortTypeNamesArray.map((type) => {
const isSelected = sort.type === type;
return (
@@ -32,7 +32,7 @@ export function Header() {
justify="center"
>
- {tankPerformanceSortTypeNames[type]}
+ {TankPerformanceSortTypeNames[type]}
state.playerCountPeriod,
+ );
+ const mutateTankPerformanceSort = TankPerformancePersistent.useMutation();
+
+ return (
+
+ Player count
+ {
+ mutateTankPerformanceSort((draft) => {
+ draft.playerCountPeriod = period as PlayerCountPeriod;
+ });
+ }}
+ >
+
+
+
+ Past 120 days
+
+
+ Past 90 days
+
+
+ Past 60 days
+
+
+ This month
+
+
+ This week
+
+
+ Yesterday
+
+
+
+
+ );
+}
diff --git a/src/app/tools/tank-performance/components/RowLoader.tsx b/src/app/tools/tank-performance/components/RowLoader.tsx
index bf0b9ad6e..a019b5285 100644
--- a/src/app/tools/tank-performance/components/RowLoader.tsx
+++ b/src/app/tools/tank-performance/components/RowLoader.tsx
@@ -2,7 +2,7 @@ import { Skeleton, Table } from '@radix-ui/themes';
import { times } from 'lodash';
import { memo, useRef } from 'react';
import { useIntersection } from '../../../../hooks/useIntersection';
-import { tankPerformanceSortTypeNamesArray } from '../../../../stores/tankPerformanceSort/constants';
+import { TankPerformanceSortTypeNamesArray } from '../../../../stores/tankPerformanceSort/constants';
interface RowLoaderProps {
onIntersection?: () => void;
@@ -21,7 +21,7 @@ export const RowLoader = memo(({ onIntersection }) => {
- {times(tankPerformanceSortTypeNamesArray.length, (index) => (
+ {times(TankPerformanceSortTypeNamesArray.length, (index) => (
diff --git a/src/app/tools/tank-performance/components/TankRow.tsx b/src/app/tools/tank-performance/components/TankRow.tsx
index 06d7df79e..c39a891c9 100644
--- a/src/app/tools/tank-performance/components/TankRow.tsx
+++ b/src/app/tools/tank-performance/components/TankRow.tsx
@@ -5,6 +5,7 @@ import { averageDefinitions } from '../../../../core/blitzkit/averageDefinitions
import { TankDefinition } from '../../../../core/blitzkit/tankDefinitions';
import { formatCompact } from '../../../../core/math/formatCompact';
import { useAveragesExclusionRatio } from '../../../../hooks/useAveragesExclusionRatio';
+import * as TankPerformancePersistent from '../../../../stores/tankPerformancePersistent';
interface TankRowProps {
tank: TankDefinition;
@@ -15,6 +16,9 @@ export const TankRow = memo(
const awaitedAverageDefinitions = use(averageDefinitions);
const averages = awaitedAverageDefinitions.averages[tank.id];
const ratio = useAveragesExclusionRatio();
+ const playerCountPeriod = TankPerformancePersistent.use(
+ (state) => state.playerCountPeriod,
+ );
return (
@@ -24,7 +28,9 @@ export const TankRow = memo(
{((averages.mu.wins / averages.mu.battles) * 100).toFixed(1)}%
- {formatCompact(Math.round(ratio * averages.samples.d_30))}
+ {formatCompact(
+ Math.round(ratio * averages.samples[playerCountPeriod]),
+ )}
{formatCompact(
diff --git a/src/app/tools/tank-performance/components/Total.tsx b/src/app/tools/tank-performance/components/Total.tsx
index 4a2656763..543800ba0 100644
--- a/src/app/tools/tank-performance/components/Total.tsx
+++ b/src/app/tools/tank-performance/components/Total.tsx
@@ -1,12 +1,14 @@
import { Table } from '@radix-ui/themes';
-import { memo, useCallback } from 'react';
+import { memo, use, useCallback } from 'react';
import { StickyRowHeaderCell } from '../../../../components/StickyRowHeaderCell';
import {
+ averageDefinitions,
AverageDefinitionsAllStats,
AverageDefinitionsEntryWithId,
} from '../../../../core/blitzkit/averageDefinitions';
import { formatCompact } from '../../../../core/math/formatCompact';
import { useAveragesExclusionRatio } from '../../../../hooks/useAveragesExclusionRatio';
+import * as TankPerformancePersistent from '../../../../stores/tankPerformancePersistent';
interface TotalProps {
tanks: AverageDefinitionsEntryWithId[];
@@ -14,6 +16,10 @@ interface TotalProps {
export const Total = memo(
({ tanks }) => {
+ const awaitedAverageDefinitions = use(averageDefinitions);
+ const playerCountPeriod = TankPerformancePersistent.use(
+ (state) => state.playerCountPeriod,
+ );
const ratio = useAveragesExclusionRatio();
const sum = useCallback(
(slice: (tank: AverageDefinitionsAllStats) => number) => {
@@ -25,7 +31,6 @@ export const Total = memo(
[tanks],
);
- const players = sum(() => 1);
const battles = sum(({ battles }) => battles);
const winrate = sum(({ wins }) => wins) / battles;
const damage = sum(({ damage_dealt }) => damage_dealt) / battles;
@@ -43,14 +48,15 @@ export const Total = memo(
return (
-
+
Total
{(winrate * 100).toFixed(1)}%
- {formatCompact(ratio * players)}
+
+ {formatCompact(
+ ratio * awaitedAverageDefinitions.samples[playerCountPeriod],
+ )}
+
{formatCompact(ratio * battles)}
{Math.round(damage).toLocaleString()}
diff --git a/src/app/tools/tank-performance/layout.tsx b/src/app/tools/tank-performance/layout.tsx
index 8a0c5b6b2..21c9944c7 100644
--- a/src/app/tools/tank-performance/layout.tsx
+++ b/src/app/tools/tank-performance/layout.tsx
@@ -1,11 +1,14 @@
import { ReactNode } from 'react';
import * as TankFilters from '../../../stores/tankFilters';
+import * as TankPerformancePersistent from '../../../stores/tankPerformancePersistent';
import * as TankPerformanceSort from '../../../stores/tankPerformanceSort';
export default function Layout({ children }: { children: ReactNode }) {
return (
-
- {children}
-
+
+
+ {children}
+
+
);
}
diff --git a/src/app/tools/tank-performance/page.tsx b/src/app/tools/tank-performance/page.tsx
index 9a119a1f5..0a7538698 100644
--- a/src/app/tools/tank-performance/page.tsx
+++ b/src/app/tools/tank-performance/page.tsx
@@ -1,5 +1,5 @@
import PageWrapper from '../../../components/PageWrapper';
-import { FilterControl } from '../tankopedia/components/FilterControl';
+import { Controls } from './components/Controls';
import { Info } from './components/Info';
import { TankTable } from './components/Table';
@@ -8,7 +8,7 @@ export default function Page() {
{/* */}
-
+
);
diff --git a/src/stores/tankPerformancePersistent/constants.ts b/src/stores/tankPerformancePersistent/constants.ts
new file mode 100644
index 000000000..34d2c4e07
--- /dev/null
+++ b/src/stores/tankPerformancePersistent/constants.ts
@@ -0,0 +1,8 @@
+export enum PlayerCountPeriod {
+ Past120Days = 'd_120',
+ Past90Days = 'd_90',
+ Past60Days = 'd_60',
+ ThisMonth = 'd_30',
+ ThisWeek = 'd_7',
+ Yesterday = 'd_1',
+}
diff --git a/src/stores/tankPerformancePersistent/index.ts b/src/stores/tankPerformancePersistent/index.ts
new file mode 100644
index 000000000..6cebe3476
--- /dev/null
+++ b/src/stores/tankPerformancePersistent/index.ts
@@ -0,0 +1,23 @@
+'use client';
+
+import { merge } from 'lodash';
+import { create } from 'zustand';
+import { persist, subscribeWithSelector } from 'zustand/middleware';
+import { createNextSafeStore } from '../../core/zustand/createNextSafeStore';
+import { PlayerCountPeriod } from './constants';
+
+export interface TankPerformancePersistent {
+ playerCountPeriod: PlayerCountPeriod;
+}
+
+export const { Provider, use, useMutation, useStore } = createNextSafeStore(
+ () =>
+ create()(
+ persist(
+ subscribeWithSelector(() => ({
+ playerCountPeriod: PlayerCountPeriod.ThisMonth,
+ })),
+ { name: 'tank-performance', merge: (a, b) => merge(b, a) },
+ ),
+ ),
+);
diff --git a/src/stores/tankPerformanceSort/constants.ts b/src/stores/tankPerformanceSort/constants.ts
index 461fd4a5c..01f23929a 100644
--- a/src/stores/tankPerformanceSort/constants.ts
+++ b/src/stores/tankPerformanceSort/constants.ts
@@ -1,9 +1,9 @@
import { TankPerformanceSortType } from '.';
-export const tankPerformanceSortTypeNames = {
+export const TankPerformanceSortTypeNames = {
winrate: 'Winrate',
- players: 'Players (30d)',
- battles: 'Battles (career)',
+ players: 'Players',
+ battles: 'Battles (total)',
damage: 'Damage',
survival: 'Survival',
xp: 'XP',
@@ -16,6 +16,7 @@ export const tankPerformanceSortTypeNames = {
damageTaken: 'Dmg. taken',
capturePoints: 'Cap points',
} as const;
-export const tankPerformanceSortTypeNamesArray = Object.keys(
- tankPerformanceSortTypeNames,
+
+export const TankPerformanceSortTypeNamesArray = Object.keys(
+ TankPerformanceSortTypeNames,
) as TankPerformanceSortType[];
diff --git a/src/stores/tankPerformanceSort/index.ts b/src/stores/tankPerformanceSort/index.ts
index 76fe22353..86893965d 100644
--- a/src/stores/tankPerformanceSort/index.ts
+++ b/src/stores/tankPerformanceSort/index.ts
@@ -2,9 +2,9 @@
import { create } from 'zustand';
import { createNextSafeStore } from '../../core/zustand/createNextSafeStore';
-import { tankPerformanceSortTypeNames } from './constants';
+import { TankPerformanceSortTypeNames } from './constants';
-export type TankPerformanceSortType = keyof typeof tankPerformanceSortTypeNames;
+export type TankPerformanceSortType = keyof typeof TankPerformanceSortTypeNames;
export interface TankPerformanceSort {
type: TankPerformanceSortType;