diff --git a/src/app/tools/compare/page.tsx b/src/app/tools/compare/page.tsx index 909de294c..47293ca9b 100644 --- a/src/app/tools/compare/page.tsx +++ b/src/app/tools/compare/page.tsx @@ -1,10 +1,26 @@ 'use client'; -import { PlusIcon } from '@radix-ui/react-icons'; -import { Button, Dialog, Flex, Table, Text } from '@radix-ui/themes'; +import { + CaretLeftIcon, + CaretRightIcon, + PlusIcon, + ShuffleIcon, + TrashIcon, +} from '@radix-ui/react-icons'; +import { + Button, + Dialog, + Flex, + IconButton, + Table, + Text, +} from '@radix-ui/themes'; import { usePathname, useRouter, useSearchParams } from 'next/navigation'; import { use, useCallback, useEffect, useMemo, useState } from 'react'; import PageWrapper from '../../../components/PageWrapper'; +import { equipmentDefinitions } from '../../../core/blitzkrieg/equipmentDefinitions'; +import { modelDefinitions } from '../../../core/blitzkrieg/modelDefinitions'; +import { provisionDefinitions } from '../../../core/blitzkrieg/provisionDefinitions'; import { tankCharacteristics } from '../../../core/blitzkrieg/tankCharacteristics'; import { tankDefinitions } from '../../../core/blitzkrieg/tankDefinitions'; import { tankIcon } from '../../../core/blitzkrieg/tankIcon'; @@ -22,22 +38,29 @@ export default function Page() { const searchParams = useSearchParams(); const tanks = useCompare((state) => state.tanks); const [addTankDialogOpen, setAddTankDialogOpen] = useState(false); - const statsPromise = useMemo( + const awaitedModelDefinitions = use(modelDefinitions); + const awaitedEquipmentDefinitions = use(equipmentDefinitions); + const awaitedProvisionDefinitions = use(provisionDefinitions); + const stats = useMemo( () => - Promise.all( - tanks.map((item) => - tankCharacteristics({ + tanks.map((item) => + tankCharacteristics( + { ...item, stockEngine: item.tank.engines[0], stockGun: item.tank.turrets[0].guns[0], stockTrack: item.tank.tracks[0], stockTurret: item.tank.turrets[0], - }), + }, + { + equipmentDefinitions: awaitedEquipmentDefinitions, + modelDefinitions: awaitedModelDefinitions, + provisionDefinitions: awaitedProvisionDefinitions, + }, ), ), [tanks], ); - const stats = use(statsPromise); const createQueryString = useCallback( (name: string, value: string) => { const params = new URLSearchParams(searchParams.toString()); @@ -50,6 +73,13 @@ export default function Page() { const hasNonRegularGun = tanks.some(({ gun }) => gun.type !== 'regular'); + useEffect(() => { + router.push( + pathname + + '?' + + createQueryString('tanks', tanks.map(({ tank }) => tank.id).join(',')), + ); + }, [tanks]); useEffect(() => { const tanksParam = searchParams.get('tanks'); @@ -164,15 +194,6 @@ export default function Page() { ...tankToDuelMember(tank), crewSkills: {}, }); - - router.push( - pathname + - '?' + - createQueryString( - 'tanks', - draft.tanks.map(({ tank }) => tank.id).join(','), - ), - ); }); setAddTankDialogOpen(false); @@ -192,6 +213,93 @@ export default function Page() { maxWidth: '100%', }} > + + + + + {tanks.map(({ tank }, index) => { + return ( + + + {index !== 0 && ( + { + mutateCompare((draft) => { + const item = draft.tanks[index]; + draft.tanks.splice(index, 1); + draft.tanks.splice(index - 1, 0, item); + }); + }} + > + + + )} + { + mutateCompare((draft) => { + draft.tanks.splice(index, 1); + }); + }} + > + + + + + + + + + + + + + { + mutateCompare((draft) => { + draft.tanks[index] = { + ...tankToDuelMember(tank), + crewSkills: {}, + }; + }); + setAddTankDialogOpen(false); + }} + /> + + + + + {index !== tanks.length - 1 && ( + { + mutateCompare((draft) => { + const item = draft.tanks[index]; + draft.tanks.splice(index, 1); + draft.tanks.splice(index + 1, 0, item); + }); + }} + > + + + )} + + + ); + })} + + + @@ -199,7 +307,13 @@ export default function Page() { {tanks.map(({ tank }) => { return ( - + ; - camouflage: boolean; -}) { - const awaitedModelDefinitions = await modelDefinitions; - const awaitedEquipmentDefinitions = await equipmentDefinitions; - const awaitedProvisionDefinitions = await provisionDefinitions; - const presetRows = awaitedEquipmentDefinitions.presets[tank.equipment]; - const tankModelDefinition = awaitedModelDefinitions[tank.id]; +export function tankCharacteristics( + { + tank, + turret, + gun, + shell, + consumables, + equipmentMatrix, + crewMastery, + provisions, + engine, + crewSkills, + camouflage, + track, + stockEngine, + stockTrack, + stockTurret, + stockGun, + }: { + tank: TankDefinition; + turret: TurretDefinition; + gun: GunDefinition; + shell: ShellDefinition; + track: TrackDefinition; + engine: EngineDefinition; + stockEngine: EngineDefinition; + stockTrack: TrackDefinition; + stockTurret: TurretDefinition; + stockGun: GunDefinition; + consumables: number[]; + equipmentMatrix: EquipmentMatrix; + crewMastery: number; + provisions: number[]; + crewSkills: Record; + camouflage: boolean; + }, + { + modelDefinitions, + equipmentDefinitions, + provisionDefinitions, + }: { + modelDefinitions: ModelDefinitions; + equipmentDefinitions: EquipmentDefinitions; + provisionDefinitions: ProvisionDefinitions; + }, +) { + const presetRows = equipmentDefinitions.presets[tank.equipment]; + const tankModelDefinition = modelDefinitions[tank.id]; const turretModelDefinition = tankModelDefinition.turrets[turret.id]; const gunModelDefinition = turretModelDefinition.guns[gun.id]; @@ -115,8 +123,8 @@ export async function tankCharacteristics({ const provisionCrewBonus = provisions.reduce( (total, provision) => - awaitedProvisionDefinitions[provision].crew - ? total + awaitedProvisionDefinitions[provision].crew! / 100 + provisionDefinitions[provision].crew + ? total + provisionDefinitions[provision].crew! / 100 : total, 0, ) + (hasImprovedVentilation ? 0.05 : 0);