mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 20:19:49 +02:00
feat: complete sort labels
This commit is contained in:
1 parent
77105b514e
commit
8bcd74262c
10 files changed
+200
-177
No files matched your search
@@ -343,7 +343,7 @@ export function Characteristics() {
|
|||||||
{stats.dispersion}
|
{stats.dispersion}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta
|
<InfoWithDelta
|
||||||
prefix="+ "
|
prefix="+"
|
||||||
decimals={3}
|
decimals={3}
|
||||||
indent
|
indent
|
||||||
name="Moving"
|
name="Moving"
|
||||||
@@ -353,7 +353,7 @@ export function Characteristics() {
|
|||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta
|
<InfoWithDelta
|
||||||
decimals={3}
|
decimals={3}
|
||||||
prefix="+ "
|
prefix="+"
|
||||||
indent
|
indent
|
||||||
name="Hull traversing"
|
name="Hull traversing"
|
||||||
deltaType="lowerIsBetter"
|
deltaType="lowerIsBetter"
|
||||||
@@ -362,7 +362,7 @@ export function Characteristics() {
|
|||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta
|
<InfoWithDelta
|
||||||
decimals={3}
|
decimals={3}
|
||||||
prefix="+ "
|
prefix="+"
|
||||||
indent
|
indent
|
||||||
name="Turret traversing"
|
name="Turret traversing"
|
||||||
deltaType="lowerIsBetter"
|
deltaType="lowerIsBetter"
|
||||||
@@ -371,7 +371,7 @@ export function Characteristics() {
|
|||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta
|
<InfoWithDelta
|
||||||
decimals={3}
|
decimals={3}
|
||||||
prefix="+ "
|
prefix="+"
|
||||||
indent
|
indent
|
||||||
name="After shooting"
|
name="After shooting"
|
||||||
deltaType="lowerIsBetter"
|
deltaType="lowerIsBetter"
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export function FilterControl() {
|
|||||||
highContrast
|
highContrast
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
mutateTankopediaFilters((draft) => {
|
mutateTankopediaFilters((draft) => {
|
||||||
draft.tier = tier;
|
draft.tier = draft.tier === tier ? undefined : tier;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -65,7 +65,7 @@ export function FilterControl() {
|
|||||||
highContrast
|
highContrast
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
mutateTankopediaFilters((draft) => {
|
mutateTankopediaFilters((draft) => {
|
||||||
draft.tier = tier;
|
draft.tier = draft.tier === tier ? undefined : tier;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ import { go } from 'fuzzysort';
|
|||||||
import { times } from 'lodash';
|
import { times } from 'lodash';
|
||||||
import { memo, use, useMemo } from 'react';
|
import { memo, use, useMemo } from 'react';
|
||||||
import { ExperimentIcon } from '../../../../components/ExperimentIcon';
|
import { ExperimentIcon } from '../../../../components/ExperimentIcon';
|
||||||
|
import { TANK_CLASSES } from '../../../../components/Tanks/components/Item/constants';
|
||||||
import { resolveNearPenetration } from '../../../../core/blitz/resolveNearPenetration';
|
import { resolveNearPenetration } from '../../../../core/blitz/resolveNearPenetration';
|
||||||
|
import { gameDefinitions } from '../../../../core/blitzkit/gameDefinitions';
|
||||||
import { modelDefinitions } from '../../../../core/blitzkit/modelDefinitions';
|
import { modelDefinitions } from '../../../../core/blitzkit/modelDefinitions';
|
||||||
import { normalizeBoundingBox } from '../../../../core/blitzkit/normalizeBoundingBox';
|
import { normalizeBoundingBox } from '../../../../core/blitzkit/normalizeBoundingBox';
|
||||||
import { resolveDpm } from '../../../../core/blitzkit/resolveDpm';
|
import { resolveDpm } from '../../../../core/blitzkit/resolveDpm';
|
||||||
@@ -14,6 +16,7 @@ import {
|
|||||||
tankNames,
|
tankNames,
|
||||||
tanksDefinitionsArray,
|
tanksDefinitionsArray,
|
||||||
} from '../../../../core/blitzkit/tankDefinitions';
|
} from '../../../../core/blitzkit/tankDefinitions';
|
||||||
|
import { tankopediaFilterTank } from '../../../../core/blitzkit/tankopediaFilterTank';
|
||||||
import { unionBoundingBox } from '../../../../core/blitzkit/unionBoundingBox';
|
import { unionBoundingBox } from '../../../../core/blitzkit/unionBoundingBox';
|
||||||
import { useTankopediaFilters } from '../../../../stores/tankopediaFilters';
|
import { useTankopediaFilters } from '../../../../stores/tankopediaFilters';
|
||||||
import { FilterControl } from './FilterControl';
|
import { FilterControl } from './FilterControl';
|
||||||
@@ -22,35 +25,41 @@ import { SearchBar } from './SearchBar';
|
|||||||
import { SkeletonTankCard } from './SkeletonTankCard';
|
import { SkeletonTankCard } from './SkeletonTankCard';
|
||||||
import { TankCard } from './TankCard';
|
import { TankCard } from './TankCard';
|
||||||
import { TankCardWrapper } from './TankCardWrapper';
|
import { TankCardWrapper } from './TankCardWrapper';
|
||||||
import { TierCard } from './TierCard';
|
import { treeTypeOrder } from './TankSearch/constants';
|
||||||
|
|
||||||
export const Results = memo(() => {
|
export const Results = memo(() => {
|
||||||
|
const awaitedGameDefinitions = use(gameDefinitions);
|
||||||
const awaitedModelDefinitions = use(modelDefinitions);
|
const awaitedModelDefinitions = use(modelDefinitions);
|
||||||
const awaitedTankDefinitions = use(tankDefinitions);
|
const awaitedTankDefinitions = use(tankDefinitions);
|
||||||
const awaitedTanksDefinitionsArray = use(tanksDefinitionsArray);
|
const awaitedTanksDefinitionsArray = use(tanksDefinitionsArray);
|
||||||
const awaitedTankNames = use(tankNames);
|
const awaitedTankNames = use(tankNames);
|
||||||
const testing = useTankopediaFilters((state) => state.testing);
|
const filters = useTankopediaFilters();
|
||||||
const search = useTankopediaFilters((state) => state.search);
|
const tanks = useMemo(() => {
|
||||||
const tier = useTankopediaFilters((state) => state.tier);
|
if (filters.search === undefined) {
|
||||||
const sort = useTankopediaFilters((state) => state.sort);
|
const filtered = awaitedTanksDefinitionsArray.filter((tank) =>
|
||||||
const searching = useTankopediaFilters((state) => state.searching);
|
tankopediaFilterTank(filters, tank),
|
||||||
const searchedTanks = useMemo(() => {
|
|
||||||
if (search !== undefined) {
|
|
||||||
const searchedRaw = go(search, awaitedTankNames, {
|
|
||||||
key: 'combined',
|
|
||||||
limit: 25,
|
|
||||||
});
|
|
||||||
const searchedTanks = searchedRaw.map(
|
|
||||||
(result) => awaitedTankDefinitions[result.obj.id],
|
|
||||||
);
|
);
|
||||||
return searchedTanks;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sort.by !== 'meta.tier') {
|
|
||||||
const filtered = awaitedTanksDefinitionsArray;
|
|
||||||
let sorted: TankDefinition[];
|
let sorted: TankDefinition[];
|
||||||
|
|
||||||
switch (sort.by) {
|
switch (filters.sort.by) {
|
||||||
|
case 'meta.none':
|
||||||
|
sorted = filtered
|
||||||
|
.sort(
|
||||||
|
(a, b) =>
|
||||||
|
treeTypeOrder.indexOf(b.treeType) -
|
||||||
|
treeTypeOrder.indexOf(a.treeType),
|
||||||
|
)
|
||||||
|
.sort(
|
||||||
|
(a, b) =>
|
||||||
|
TANK_CLASSES.indexOf(b.class) - TANK_CLASSES.indexOf(a.class),
|
||||||
|
)
|
||||||
|
.sort(
|
||||||
|
(a, b) =>
|
||||||
|
awaitedGameDefinitions.nations.indexOf(b.nation) -
|
||||||
|
awaitedGameDefinitions.nations.indexOf(a.nation),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'survivability.health': {
|
case 'survivability.health': {
|
||||||
sorted = filtered.sort((a, b) => {
|
sorted = filtered.sort((a, b) => {
|
||||||
const aHealth = a.health + a.turrets.at(-1)!.health;
|
const aHealth = a.health + a.turrets.at(-1)!.health;
|
||||||
@@ -82,8 +91,10 @@ export const Results = memo(() => {
|
|||||||
case 'survivability.camouflageShooting':
|
case 'survivability.camouflageShooting':
|
||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.camouflageLoss -
|
a.camouflage.still *
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.camouflageLoss,
|
a.turrets.at(-1)!.guns.at(-1)!.camouflageLoss -
|
||||||
|
b.camouflage.still *
|
||||||
|
b.turrets.at(-1)!.guns.at(-1)!.camouflageLoss,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -187,16 +198,10 @@ export const Results = memo(() => {
|
|||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
resolveNearPenetration(
|
resolveNearPenetration(
|
||||||
(
|
a.turrets.at(-1)!.guns.at(-1)!.shells[1]?.penetration ?? 0,
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.shells[1] ??
|
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.shells[0]
|
|
||||||
).penetration,
|
|
||||||
) -
|
) -
|
||||||
resolveNearPenetration(
|
resolveNearPenetration(
|
||||||
(
|
b.turrets.at(-1)!.guns.at(-1)!.shells[1]?.penetration ?? 0,
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.shells[1] ??
|
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.shells[0]
|
|
||||||
).penetration,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@@ -246,23 +251,26 @@ export const Results = memo(() => {
|
|||||||
(a, b) =>
|
(a, b) =>
|
||||||
awaitedModelDefinitions[a.id].turrets[a.turrets.at(-1)!.id].guns[
|
awaitedModelDefinitions[a.id].turrets[a.turrets.at(-1)!.id].guns[
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.id
|
a.turrets.at(-1)!.guns.at(-1)!.id
|
||||||
].pitch.max -
|
].pitch.max +
|
||||||
|
(awaitedModelDefinitions[a.id].turretRotation?.pitch ?? 0) -
|
||||||
awaitedModelDefinitions[b.id].turrets[b.turrets.at(-1)!.id].guns[
|
awaitedModelDefinitions[b.id].turrets[b.turrets.at(-1)!.id].guns[
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.id
|
b.turrets.at(-1)!.guns.at(-1)!.id
|
||||||
].pitch.max,
|
].pitch.max -
|
||||||
|
(awaitedModelDefinitions[b.id].turretRotation?.pitch ?? 0),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'fire.gunElevation':
|
case 'fire.gunElevation':
|
||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
// reversed because of negative values
|
|
||||||
awaitedModelDefinitions[b.id].turrets[b.turrets.at(-1)!.id].guns[
|
awaitedModelDefinitions[b.id].turrets[b.turrets.at(-1)!.id].guns[
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.id
|
b.turrets.at(-1)!.guns.at(-1)!.id
|
||||||
].pitch.min -
|
].pitch.min +
|
||||||
|
(awaitedModelDefinitions[b.id].turretRotation?.pitch ?? 0) -
|
||||||
awaitedModelDefinitions[a.id].turrets[a.turrets.at(-1)!.id].guns[
|
awaitedModelDefinitions[a.id].turrets[a.turrets.at(-1)!.id].guns[
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.id
|
a.turrets.at(-1)!.guns.at(-1)!.id
|
||||||
].pitch.min,
|
].pitch.min -
|
||||||
|
(awaitedModelDefinitions[a.id].turretRotation?.pitch ?? 0),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -324,19 +332,26 @@ export const Results = memo(() => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sort.direction === 'ascending' ? sorted : sorted.reverse();
|
return filters.sort.direction === 'ascending' ? sorted : sorted.reverse();
|
||||||
|
} else {
|
||||||
|
const searchedRaw = go(filters.search, awaitedTankNames, {
|
||||||
|
key: 'combined',
|
||||||
|
limit: 25,
|
||||||
|
});
|
||||||
|
const searchedTanks = searchedRaw.map(
|
||||||
|
(result) => awaitedTankDefinitions[result.obj.id],
|
||||||
|
);
|
||||||
|
return searchedTanks;
|
||||||
}
|
}
|
||||||
|
}, [filters]);
|
||||||
return undefined;
|
|
||||||
}, [search, sort]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex direction="column" gap="4" flexGrow="1">
|
<Flex direction="column" gap="4" flexGrow="1">
|
||||||
<SearchBar topResult={searchedTanks?.[0]} />
|
<SearchBar topResult={tanks?.[0]} />
|
||||||
|
|
||||||
{!search && !searching && <FilterControl />}
|
{!filters.search && !filters.searching && <FilterControl />}
|
||||||
|
|
||||||
{testing === 'only' && (
|
{filters.testing === 'only' && (
|
||||||
<Flex justify="center" mt="4">
|
<Flex justify="center" mt="4">
|
||||||
<Callout.Root color="amber">
|
<Callout.Root color="amber">
|
||||||
<Callout.Icon>
|
<Callout.Icon>
|
||||||
@@ -350,25 +365,21 @@ export const Results = memo(() => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!search && sort.by === 'meta.tier' && !searching && (
|
{!filters.searching && (
|
||||||
<TierCard tier={tier} />
|
|
||||||
)}
|
|
||||||
|
|
||||||
{(search || sort.by !== 'meta.tier') && !searching && searchedTanks && (
|
|
||||||
<>
|
<>
|
||||||
{searchedTanks.length > 0 && (
|
{tanks.length > 0 && (
|
||||||
<TankCardWrapper>
|
<TankCardWrapper>
|
||||||
{searchedTanks.map((tank) => (
|
{tanks.map((tank) => (
|
||||||
<TankCard key={tank.id} tank={tank} />
|
<TankCard key={tank.id} tank={tank} />
|
||||||
))}
|
))}
|
||||||
</TankCardWrapper>
|
</TankCardWrapper>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{searchedTanks.length === 0 && <NoResults type="search" />}
|
{tanks.length === 0 && <NoResults type="search" />}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{searching && (
|
{filters.searching && (
|
||||||
<TankCardWrapper>
|
<TankCardWrapper>
|
||||||
{times(Math.round(10 + 10 * Math.random()), (index) => (
|
{times(Math.round(10 + 10 * Math.random()), (index) => (
|
||||||
<SkeletonTankCard key={index} />
|
<SkeletonTankCard key={index} />
|
||||||
|
|||||||
@@ -19,23 +19,18 @@ export function Sort() {
|
|||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
|
|
||||||
<DropdownMenu.Content align="end">
|
<DropdownMenu.Content align="end">
|
||||||
<DropdownMenu.Label>Sort by</DropdownMenu.Label>
|
<DropdownMenu.CheckboxItem
|
||||||
|
checked={sort.by === 'meta.none'}
|
||||||
|
onClick={() => {
|
||||||
|
mutateTankopediaFilters((draft) => {
|
||||||
|
draft.sort.by = 'meta.none';
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
No sort
|
||||||
|
</DropdownMenu.CheckboxItem>
|
||||||
|
|
||||||
<DropdownMenu.Sub>
|
<DropdownMenu.Label>Sort by</DropdownMenu.Label>
|
||||||
<DropdownMenu.SubTrigger>Meta</DropdownMenu.SubTrigger>
|
|
||||||
<DropdownMenu.SubContent>
|
|
||||||
<DropdownMenu.CheckboxItem
|
|
||||||
checked={sort.by === 'meta.tier'}
|
|
||||||
onClick={() => {
|
|
||||||
mutateTankopediaFilters((draft) => {
|
|
||||||
draft.sort.by = 'meta.tier';
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Tier
|
|
||||||
</DropdownMenu.CheckboxItem>
|
|
||||||
</DropdownMenu.SubContent>
|
|
||||||
</DropdownMenu.Sub>
|
|
||||||
|
|
||||||
<DropdownMenu.Sub>
|
<DropdownMenu.Sub>
|
||||||
<DropdownMenu.SubTrigger>Fire</DropdownMenu.SubTrigger>
|
<DropdownMenu.SubTrigger>Fire</DropdownMenu.SubTrigger>
|
||||||
@@ -305,8 +300,6 @@ export function Sort() {
|
|||||||
</DropdownMenu.SubContent>
|
</DropdownMenu.SubContent>
|
||||||
</DropdownMenu.Sub>
|
</DropdownMenu.Sub>
|
||||||
|
|
||||||
<DropdownMenu.Separator />
|
|
||||||
|
|
||||||
<DropdownMenu.Label>Direction</DropdownMenu.Label>
|
<DropdownMenu.Label>Direction</DropdownMenu.Label>
|
||||||
<DropdownMenu.RadioGroup
|
<DropdownMenu.RadioGroup
|
||||||
value={sort.direction}
|
value={sort.direction}
|
||||||
|
|||||||
@@ -1,10 +1,18 @@
|
|||||||
import { Flex, Text } from '@radix-ui/themes';
|
import { Flex, Text } from '@radix-ui/themes';
|
||||||
import { Icon } from '@radix-ui/themes/dist/cjs/components/callout';
|
|
||||||
import { assignInlineVars } from '@vanilla-extract/dynamic';
|
import { assignInlineVars } from '@vanilla-extract/dynamic';
|
||||||
|
import { use, useMemo } from 'react';
|
||||||
|
import { classIcons } from '../../../../components/ClassIcon';
|
||||||
import { Link } from '../../../../components/Link';
|
import { Link } from '../../../../components/Link';
|
||||||
|
import { resolveNearPenetration } from '../../../../core/blitz/resolveNearPenetration';
|
||||||
import { asset } from '../../../../core/blitzkit/asset';
|
import { asset } from '../../../../core/blitzkit/asset';
|
||||||
|
import { modelDefinitions } from '../../../../core/blitzkit/modelDefinitions';
|
||||||
|
import { normalizeBoundingBox } from '../../../../core/blitzkit/normalizeBoundingBox';
|
||||||
|
import { resolveDpm } from '../../../../core/blitzkit/resolveDpm';
|
||||||
|
import { resolveReload } from '../../../../core/blitzkit/resolveReload';
|
||||||
import { TankDefinition } from '../../../../core/blitzkit/tankDefinitions';
|
import { TankDefinition } from '../../../../core/blitzkit/tankDefinitions';
|
||||||
import { tankIcon } from '../../../../core/blitzkit/tankIcon';
|
import { tankIcon } from '../../../../core/blitzkit/tankIcon';
|
||||||
|
import { unionBoundingBox } from '../../../../core/blitzkit/unionBoundingBox';
|
||||||
|
import { useTankopediaFilters } from '../../../../stores/tankopediaFilters';
|
||||||
import * as styles from './TankCard.css';
|
import * as styles from './TankCard.css';
|
||||||
|
|
||||||
interface TankCardProps {
|
interface TankCardProps {
|
||||||
@@ -12,47 +20,114 @@ interface TankCardProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function TankCard({ tank }: TankCardProps) {
|
export function TankCard({ tank }: TankCardProps) {
|
||||||
// const awaitedModelDefinitions = use(modelDefinitions);
|
const awaitedModelDefinitions = use(modelDefinitions);
|
||||||
// const Icon = classIcons[tank.class];
|
const Icon = classIcons[tank.class];
|
||||||
// const link = useRef<HTMLAnchorElement>(null);
|
// const link = useRef<HTMLAnchorElement>(null);
|
||||||
// const sortBy = useTankopediaFilters((state) => state.sort.by);
|
const sortBy = useTankopediaFilters((state) => state.sort.by);
|
||||||
// const discriminator = useMemo(() => {
|
const discriminator = useMemo(() => {
|
||||||
// if (sortBy.startsWith('meta')) return undefined;
|
if (sortBy.startsWith('meta')) return undefined;
|
||||||
|
|
||||||
// const turret = tank.turrets.at(-1)!;
|
const turret = tank.turrets.at(-1)!;
|
||||||
// const gun = turret.guns.at(-1)!;
|
const gun = turret.guns.at(-1)!;
|
||||||
// const shell = gun.shells[0];
|
const shell0 = gun.shells[0];
|
||||||
// const tracks = tank.tracks.at(-1)!;
|
const shell1 = gun.shells[1];
|
||||||
// const tankModelDefinition = awaitedModelDefinitions[tank.id];
|
const tracks = tank.tracks.at(-1)!;
|
||||||
|
const engine = tank.engines.at(-1)!;
|
||||||
|
const tankModelDefinition = awaitedModelDefinitions[tank.id];
|
||||||
|
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
||||||
|
const gunModelDefinition = turretModelDefinition.guns[gun.id];
|
||||||
|
|
||||||
// switch (sortBy) {
|
switch (sortBy) {
|
||||||
// case 'fire.aimTime':
|
case 'fire.aimTime':
|
||||||
// return `${gun.aimTime.toFixed(2)}s`;
|
return gun.aimTime.toFixed(2);
|
||||||
// case 'fire.caliber':
|
case 'fire.caliber':
|
||||||
// return `${shell.caliber.toFixed(0)}mm`;
|
return shell0.caliber.toFixed(0);
|
||||||
// case 'fire.damage':
|
case 'fire.damage':
|
||||||
// return `${shell.damage.armor.toFixed(0)}hp`;
|
return shell0.damage.armor.toFixed(0);
|
||||||
// case 'fire.dispersionMoving':
|
case 'fire.dispersionMoving':
|
||||||
// return `+ ${tracks.dispersion.move.toFixed(3)}`;
|
return tracks.dispersion.move.toFixed(3);
|
||||||
// case 'fire.dispersionStill':
|
case 'fire.dispersionStill':
|
||||||
// return gun.dispersion.base.toFixed(3);
|
return gun.dispersion.base.toFixed(3);
|
||||||
// case 'fire.dpm':
|
case 'fire.dpm':
|
||||||
// return resolveDpm(gun, shell).toFixed(0);
|
return resolveDpm(gun, shell0).toFixed(0);
|
||||||
// case 'fire.gunDepression':
|
case 'fire.reload':
|
||||||
// return awaitedModelDefinitions;
|
return resolveReload(gun).toFixed(2);
|
||||||
// }
|
case 'fire.standardPenetration':
|
||||||
// }, [sortBy]);
|
return resolveNearPenetration(shell0.penetration).toFixed(0);
|
||||||
|
case 'fire.premiumPenetration':
|
||||||
|
return shell1
|
||||||
|
? resolveNearPenetration(shell1.penetration).toFixed(0)
|
||||||
|
: '--';
|
||||||
|
case 'fire.shellVelocity':
|
||||||
|
return shell0.speed.toFixed(0);
|
||||||
|
case 'fire.gunDepression':
|
||||||
|
return (
|
||||||
|
gunModelDefinition.pitch.max +
|
||||||
|
(tankModelDefinition.turretRotation?.pitch ?? 0)
|
||||||
|
).toFixed(1);
|
||||||
|
case 'fire.gunElevation':
|
||||||
|
return (
|
||||||
|
-gunModelDefinition.pitch.min -
|
||||||
|
(tankModelDefinition.turretRotation?.pitch ?? 0)
|
||||||
|
).toFixed(1);
|
||||||
|
case 'maneuverability.forwardsSpeed':
|
||||||
|
return tank.speed.forwards.toFixed(0);
|
||||||
|
case 'maneuverability.backwardsSpeed':
|
||||||
|
return tank.speed.backwards.toFixed(0);
|
||||||
|
case 'maneuverability.power':
|
||||||
|
return engine.power.toFixed(0);
|
||||||
|
case 'maneuverability.powerToWeight':
|
||||||
|
return (
|
||||||
|
(1000 * engine.power) /
|
||||||
|
(tank.weight +
|
||||||
|
engine.weight +
|
||||||
|
tracks.weight +
|
||||||
|
turret.weight +
|
||||||
|
gun.weight)
|
||||||
|
).toFixed(1);
|
||||||
|
case 'maneuverability.weight':
|
||||||
|
return (
|
||||||
|
(tank.weight +
|
||||||
|
engine.weight +
|
||||||
|
tracks.weight +
|
||||||
|
turret.weight +
|
||||||
|
gun.weight) /
|
||||||
|
1000
|
||||||
|
).toFixed(1);
|
||||||
|
case 'maneuverability.traverseSpeed':
|
||||||
|
return tracks.traverseSpeed.toFixed(1);
|
||||||
|
case 'survivability.health':
|
||||||
|
return (tank.health + turret.health).toFixed(0);
|
||||||
|
case 'survivability.viewRange':
|
||||||
|
return turret.viewRange.toFixed(0);
|
||||||
|
case 'survivability.camouflageStill':
|
||||||
|
return (tank.camouflage.still * 100).toFixed(0);
|
||||||
|
case 'survivability.camouflageMoving':
|
||||||
|
return (tank.camouflage.moving * 100).toFixed(0);
|
||||||
|
case 'survivability.camouflageShooting':
|
||||||
|
return (tank.camouflage.still * gun.camouflageLoss * 100).toFixed(0);
|
||||||
|
case 'survivability.volume': {
|
||||||
|
const dimensions = normalizeBoundingBox(
|
||||||
|
unionBoundingBox(
|
||||||
|
tankModelDefinition.boundingBox,
|
||||||
|
turretModelDefinition.boundingBox,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
// useEffect(() => {
|
return (dimensions[0] * dimensions[1] * dimensions[2]).toFixed(0);
|
||||||
// const unsubscribe = useTankopediaFilters.subscribe((filters) => {
|
}
|
||||||
// if (!link.current) return;
|
|
||||||
|
|
||||||
// const visible = tankopediaFilterTank(filters, tank);
|
case 'survivability.length':
|
||||||
// link.current.style.display = visible ? 'flex' : 'none';
|
return Math.max(
|
||||||
// });
|
...normalizeBoundingBox(
|
||||||
|
unionBoundingBox(
|
||||||
// return unsubscribe;
|
tankModelDefinition.boundingBox,
|
||||||
// }, []);
|
turretModelDefinition.boundingBox,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).toFixed(0);
|
||||||
|
}
|
||||||
|
}, [sortBy]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
@@ -89,7 +164,7 @@ export function TankCard({ tank }: TankCardProps) {
|
|||||||
</Text>
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
{/* {discriminator && (
|
{discriminator && (
|
||||||
<Text
|
<Text
|
||||||
mt="-2"
|
mt="-2"
|
||||||
color="gray"
|
color="gray"
|
||||||
@@ -102,7 +177,7 @@ export function TankCard({ tank }: TankCardProps) {
|
|||||||
>
|
>
|
||||||
{discriminator}
|
{discriminator}
|
||||||
</Text>
|
</Text>
|
||||||
)} */}
|
)}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,7 @@ export function TankSearch({
|
|||||||
let sorted: TankDefinition[] = [];
|
let sorted: TankDefinition[] = [];
|
||||||
|
|
||||||
switch (sort.by) {
|
switch (sort.by) {
|
||||||
case 'meta.tier':
|
case 'meta.none':
|
||||||
sorted = filtered.sort((a, b) => a.tier - b.tier);
|
sorted = filtered.sort((a, b) => a.tier - b.tier);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -475,7 +475,7 @@ export function TankSearch({
|
|||||||
page: 0,
|
page: 0,
|
||||||
},
|
},
|
||||||
sort: {
|
sort: {
|
||||||
by: 'meta.tier',
|
by: 'meta.none',
|
||||||
direction: 'descending',
|
direction: 'descending',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
import { memo, use, useMemo } from 'react';
|
|
||||||
import { TANK_CLASSES } from '../../../../components/Tanks/components/Item/constants';
|
|
||||||
import { gameDefinitions } from '../../../../core/blitzkit/gameDefinitions';
|
|
||||||
import {
|
|
||||||
Tier,
|
|
||||||
tanksDefinitionsArray,
|
|
||||||
} from '../../../../core/blitzkit/tankDefinitions';
|
|
||||||
import { tankopediaFilterTank } from '../../../../core/blitzkit/tankopediaFilterTank';
|
|
||||||
import { useTankopediaFilters } from '../../../../stores/tankopediaFilters';
|
|
||||||
import { NoResults } from './NoResults';
|
|
||||||
import { TankCard } from './TankCard';
|
|
||||||
import { TankCardWrapper } from './TankCardWrapper';
|
|
||||||
import { treeTypeOrder } from './TankSearch/constants';
|
|
||||||
|
|
||||||
interface TierCardProps {
|
|
||||||
tier: Tier;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const TierCard = memo(
|
|
||||||
({ tier }: TierCardProps) => {
|
|
||||||
const awaitedGameDefinitions = use(gameDefinitions);
|
|
||||||
const awaitedTanksDefinitionsArray = use(tanksDefinitionsArray);
|
|
||||||
const filters = useTankopediaFilters();
|
|
||||||
const tanks = useMemo(
|
|
||||||
() =>
|
|
||||||
awaitedTanksDefinitionsArray
|
|
||||||
.filter((tank) => tankopediaFilterTank(filters, tank))
|
|
||||||
.sort(
|
|
||||||
(a, b) =>
|
|
||||||
treeTypeOrder.indexOf(a.treeType) -
|
|
||||||
treeTypeOrder.indexOf(b.treeType),
|
|
||||||
)
|
|
||||||
.sort(
|
|
||||||
(a, b) =>
|
|
||||||
TANK_CLASSES.indexOf(a.class) - TANK_CLASSES.indexOf(b.class),
|
|
||||||
)
|
|
||||||
.sort(
|
|
||||||
(a, b) =>
|
|
||||||
awaitedGameDefinitions.nations.indexOf(a.nation) -
|
|
||||||
awaitedGameDefinitions.nations.indexOf(b.nation),
|
|
||||||
),
|
|
||||||
[tier, filters],
|
|
||||||
);
|
|
||||||
|
|
||||||
if (tanks.length === 0) return <NoResults />;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TankCardWrapper>
|
|
||||||
{tanks.map((tank) => (
|
|
||||||
<TankCard key={tank.id} tank={tank} />
|
|
||||||
))}
|
|
||||||
</TankCardWrapper>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
(prev, next) => prev.tier === next.tier,
|
|
||||||
);
|
|
||||||
@@ -13,7 +13,7 @@ export const TierFilter = memo(() => {
|
|||||||
const sort = useTankopediaFilters((state) => state.sort);
|
const sort = useTankopediaFilters((state) => state.sort);
|
||||||
const search = useTankopediaFilters((state) => state.search);
|
const search = useTankopediaFilters((state) => state.search);
|
||||||
|
|
||||||
if (sort.by !== 'meta.tier' || search) return null;
|
if (sort.by !== 'meta.none' || search) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex justify="center">
|
<Flex justify="center">
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ export type ArmorPiercingLayer =
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const SORT_NAMES = {
|
export const SORT_NAMES = {
|
||||||
'meta.tier': 'tier',
|
'meta.none': 'none',
|
||||||
'survivability.health': 'health',
|
'survivability.health': 'health',
|
||||||
'survivability.viewRange': 'view range',
|
'survivability.viewRange': 'view range',
|
||||||
'survivability.camouflageStill': 'camouflage still',
|
'survivability.camouflageStill': 'camouflage still',
|
||||||
@@ -150,7 +150,7 @@ export const useTankopediaPersistent = create<TankopediaPersistent>()(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
sort: {
|
sort: {
|
||||||
by: 'meta.tier',
|
by: 'meta.none',
|
||||||
direction: 'descending',
|
direction: 'descending',
|
||||||
},
|
},
|
||||||
filters: {
|
filters: {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { Tier } from '../core/blitzkit/tankDefinitions';
|
|||||||
import { TankopediaSortBy, TankopediaSortDirection } from './tankopedia';
|
import { TankopediaSortBy, TankopediaSortDirection } from './tankopedia';
|
||||||
|
|
||||||
export interface TankopediaFilters {
|
export interface TankopediaFilters {
|
||||||
tier: Tier;
|
tier?: Tier;
|
||||||
nation?: string;
|
nation?: string;
|
||||||
class?: TankClass;
|
class?: TankClass;
|
||||||
type?: TreeType;
|
type?: TreeType;
|
||||||
@@ -21,7 +21,7 @@ export interface TankopediaFilters {
|
|||||||
export const useTankopediaFilters = create<TankopediaFilters>()(() => ({
|
export const useTankopediaFilters = create<TankopediaFilters>()(() => ({
|
||||||
testing: 'include',
|
testing: 'include',
|
||||||
sort: {
|
sort: {
|
||||||
by: 'meta.tier',
|
by: 'meta.none',
|
||||||
direction: 'descending',
|
direction: 'descending',
|
||||||
},
|
},
|
||||||
tier: 10,
|
tier: 10,
|
||||||
|
|||||||
Reference in new issue
Block a user