feat: next safe generalization

This commit is contained in:
TrèsAbhi committed 2024-07-08 19:36:28 -05:00
1 parent eb87463f08
commit dae902fe03
19 files changed
+163 -155

No files matched your search

@@ -10,7 +10,7 @@ export function Info() {
const awaitedAverageDefinitions = use(averageDefinitions);
const numberFormat = Intl.NumberFormat(undefined, { notation: 'compact' });
const ratio = useAveragesExclusionRatio();
const samples = ratio * awaitedAverageDefinitions.sampled_players;
const samples = ratio * awaitedAverageDefinitions.samples.d_120;
return (
<Flex justify="center">
@@ -24,11 +24,11 @@ export const TankRow = memo<TankRowProps>(
{((averages.mu.wins / averages.mu.battles) * 100).toFixed(1)}%
</Table.Cell>
<Table.Cell align="center">
{numberFormat.format(Math.round(ratio * averages.samples))}
{numberFormat.format(Math.round(ratio * averages.samples.d_30))}
</Table.Cell>
<Table.Cell align="center">
{numberFormat.format(
Math.round(ratio * averages.mu.battles * averages.samples),
Math.round(ratio * averages.mu.battles * averages.samples.total),
)}
</Table.Cell>
<Table.Cell align="center">
@@ -6,7 +6,7 @@ import { Suspense, use, useEffect, useMemo, useState } from 'react';
import { averageDefinitionsArray } from '../../../../core/blitzkit/averageDefinitions';
import { filterTank } from '../../../../core/blitzkit/filterTank';
import { tankDefinitions } from '../../../../core/blitzkit/tankDefinitions';
import { useTankFilters } from '../../../../stores/tankFilters';
import * as TankFilters from '../../../../stores/tankFilters';
import { useTankPerformanceSort } from '../../../../stores/tankPerformanceSort';
import { RowLoader } from './RowLoader';
import { TankRow } from './TankRow';
@@ -18,7 +18,7 @@ const DEFAULT_LOADED_ROWS = 25;
export function Tanks() {
const awaitedTankDefinitions = use(tankDefinitions);
const awaitedAverageDefinitionsArray = use(averageDefinitionsArray);
const filters = useTankFilters();
const filters = TankFilters.use();
const sort = useTankPerformanceSort();
const tanksSorted = useMemo(() => {
switch (sort.type) {
@@ -31,7 +31,7 @@ export function Tanks() {
return awaitedAverageDefinitionsArray.sort(
(a, b) =>
sort.direction *
(a.samples * a.mu.battles - b.samples * b.mu.battles),
(a.samples.total * a.mu.battles - b.samples.total * b.mu.battles),
);
case 'capturePoints':
return awaitedAverageDefinitionsArray.sort(
@@ -81,7 +81,7 @@ export function Tanks() {
);
case 'players':
return awaitedAverageDefinitionsArray.sort(
(a, b) => sort.direction * (a.samples - b.samples),
(a, b) => sort.direction * (a.samples.d_30 - b.samples.d_30),
);
case 'spots':
return awaitedAverageDefinitionsArray.sort(
@@ -44,7 +44,8 @@ export function TierBreakdown() {
tierTanks.forEach((stats) => {
const tank = awaitedTankDefinitions[stats.id];
populations[tank.class] += stats.mu.battles * stats.samples;
populations[tank.class] +=
stats.mu.battles * stats.samples.d_30;
});
TANK_CLASSES.forEach((tankClass) => {
@@ -18,7 +18,7 @@ export const Total = memo<TotalProps>(
const sum = useCallback(
(slice: (tank: AverageDefinitionsAllStats) => number) => {
return tanks.reduce(
(acc, tank) => acc + tank.samples * slice(tank.mu),
(acc, tank) => acc + tank.samples.total * slice(tank.mu),
0,
);
},
+3 -3
View File
@@ -1,5 +1,5 @@
import PageWrapper from '../../../components/PageWrapper';
import { TankFiltersProvider } from '../../../stores/tankFilters';
import * as TankFilters from '../../../stores/tankFilters';
import { FilterControl } from '../tankopedia/components/FilterControl';
import { Info } from './components/Info';
import { TankTable } from './components/Table';
@@ -7,13 +7,13 @@ import { TierBreakdown } from './components/TierBreakdown';
export default function Page() {
return (
<TankFiltersProvider>
<TankFilters.Provider>
<PageWrapper color="jade" noMaxWidth>
<Info />
<TierBreakdown />
<FilterControl />
<TankTable />
</PageWrapper>
</TankFiltersProvider>
</TankFilters.Provider>
);
}
@@ -14,11 +14,7 @@ import { asset } from '../../../../core/blitzkit/asset';
import { gameDefinitions } from '../../../../core/blitzkit/gameDefinitions';
import { Tier } from '../../../../core/blitzkit/tankDefinitions';
import { TIER_ROMAN_NUMERALS } from '../../../../core/blitzkit/tankDefinitions/constants';
import {
useTankFilters,
useTankFiltersContext,
useTankFiltersMutation,
} from '../../../../stores/tankFilters';
import * as TankFilters from '../../../../stores/tankFilters';
interface FilterControlProps {
compact?: boolean;
@@ -26,9 +22,9 @@ interface FilterControlProps {
export function FilterControl({ compact }: FilterControlProps) {
const awaitedGameDefinitions = use(gameDefinitions);
const filters = useTankFilters();
const mutateTankFilters = useTankFiltersMutation();
const tankFiltersContext = useTankFiltersContext();
const filters = TankFilters.use();
const mutateTankFilters = TankFilters.useMutation();
const tankFiltersStore = TankFilters.useStore();
return (
<Flex height="fit-content" gap="2" align="start" justify="center">
@@ -325,10 +321,7 @@ export function FilterControl({ compact }: FilterControlProps) {
<IconButton
color="red"
onClick={() => {
tankFiltersContext.setState(
tankFiltersContext.getInitialState(),
true,
);
tankFiltersStore.setState(tankFiltersStore.getInitialState(), true);
}}
>
<ReloadIcon />
@@ -1,12 +1,12 @@
import { Flex, Link, Text } from '@radix-ui/themes';
import { useTankFiltersContext } from '../../../../stores/tankFilters';
import * as TankFilters from '../../../../stores/tankFilters';
interface NoResultsProps {
type?: 'filters' | 'search';
}
export function NoResults({ type = 'filters' }: NoResultsProps) {
const tankFiltersContext = useTankFiltersContext();
const tankFiltersStore = TankFilters.useStore();
return (
<Flex flexGrow="1" align="center" justify="center">
@@ -17,10 +17,7 @@ export function NoResults({ type = 'filters' }: NoResultsProps) {
underline="always"
color="red"
onClick={() =>
tankFiltersContext.setState(
tankFiltersContext.getInitialState(),
true,
)
tankFiltersStore.setState(tankFiltersStore.getInitialState(), true)
}
>
{type === 'filters' ? 'Try clearing filters' : 'Try searching again'}
@@ -1,15 +1,15 @@
import { CaretRightIcon } from '@radix-ui/react-icons';
import { Button, Link, TextField } from '@radix-ui/themes';
import { TankDefinition } from '../../../../core/blitzkit/tankDefinitions';
import { useTankFilters } from '../../../../stores/tankFilters';
import * as TankFilters from '../../../../stores/tankFilters';
interface QuickLinkProps {
topResult?: TankDefinition;
}
export function QuickLink({ topResult }: QuickLinkProps) {
const search = useTankFilters((state) => state.search);
const searching = useTankFilters((state) => state.searching);
const search = TankFilters.use((state) => state.search);
const searching = TankFilters.use((state) => state.searching);
if (!search || !topResult || searching) return null;
@@ -4,10 +4,7 @@ import { debounce } from 'lodash';
import { useRouter } from 'next/navigation';
import { KeyboardEventHandler, useCallback, useRef } from 'react';
import { TankDefinition } from '../../../../core/blitzkit/tankDefinitions';
import {
useTankFilters,
useTankFiltersContext,
} from '../../../../stores/tankFilters';
import * as TankFilters from '../../../../stores/tankFilters';
import { QuickLink } from './QuickLink';
import { Sort } from './Sort';
@@ -17,27 +14,27 @@ interface SearchBarProps {
}
export function SearchBar({ topResult, onSelect }: SearchBarProps) {
const tankFiltersContext = useTankFiltersContext();
const tankFiltersStore = TankFilters.useStore();
const router = useRouter();
const input = useRef<HTMLInputElement>(null);
const searching = useTankFilters((state) => state.searching);
const searching = TankFilters.use((state) => state.searching);
const performSearch = useCallback(
debounce(() => {
tankFiltersContext.setState({ searching: false });
tankFiltersStore.setState({ searching: false });
if (!input.current) return;
const sanitized = input.current.value.trim();
tankFiltersContext.setState({
tankFiltersStore.setState({
search: sanitized.length === 0 ? undefined : sanitized,
});
}, 500),
[],
);
const handleChange = useCallback(() => {
if (!tankFiltersContext.getState().searching) {
tankFiltersContext.setState({ searching: true });
if (!tankFiltersStore.getState().searching) {
tankFiltersStore.setState({ searching: true });
}
performSearch();
@@ -20,7 +20,7 @@ import {
} from '../../../../../core/blitzkit/tankDefinitions';
import { unionBoundingBox } from '../../../../../core/blitzkit/unionBoundingBox';
import { useAdExempt } from '../../../../../hooks/useAdExempt';
import { useTankFilters } from '../../../../../stores/tankFilters';
import * as TankFilters from '../../../../../stores/tankFilters';
import { SORT_NAMES, SORT_UNITS } from '../../../../../stores/tankopedia';
import { useTankopediaSort } from '../../../../../stores/tankopediaSort';
import { FilterControl } from '../FilterControl';
@@ -45,7 +45,7 @@ export const TankSearch = memo<TankSearchProps>(
const awaitedTankDefinitions = use(tankDefinitions);
const awaitedTanksDefinitionsArray = use(tanksDefinitionsArray);
const awaitedTankNames = use(tankNames);
const filters = useTankFilters();
const filters = TankFilters.use();
const sort = useTankopediaSort();
const tanks = useMemo(() => {
if (filters.search === undefined) {
@@ -3,17 +3,14 @@ import { times } from 'lodash';
import { memo } from 'react';
import { Tier } from '../../../../core/blitzkit/tankDefinitions';
import { TIER_ROMAN_NUMERALS } from '../../../../core/blitzkit/tankDefinitions/constants';
import {
useTankFilters,
useTankFiltersMutation,
} from '../../../../stores/tankFilters';
import * as TankFilters from '../../../../stores/tankFilters';
import { useTankopediaSort } from '../../../../stores/tankopediaSort';
export const TierFilter = memo(() => {
const tierFilter = useTankFilters((state) => state.tiers);
const tierFilter = TankFilters.use((state) => state.tiers);
const sort = useTankopediaSort();
const search = useTankFilters((state) => state.search);
const mutateTankFilters = useTankFiltersMutation();
const search = TankFilters.use((state) => state.search);
const mutateTankFilters = TankFilters.useMutation();
if (sort.by !== 'meta.none' || search) return null;
+3 -3
View File
@@ -3,18 +3,18 @@
import { AdMidSectionResponsive } from '../../../components/AdMidSectionResponsive';
import PageWrapper from '../../../components/PageWrapper';
import { useAdExempt } from '../../../hooks/useAdExempt';
import { TankFiltersProvider } from '../../../stores/tankFilters';
import * as TankFilters from '../../../stores/tankFilters';
import { TankSearch } from './components/TankSearch';
export default function Page() {
const exempt = useAdExempt();
return (
<TankFiltersProvider>
<TankFilters.Provider>
<PageWrapper color="purple" size={1028}>
<TankSearch />
{!exempt && <AdMidSectionResponsive />}
</PageWrapper>
</TankFiltersProvider>
</TankFilters.Provider>
);
}