From efc28f7e367115e5ccbf3e3173a457b67476c08c Mon Sep 17 00:00:00 2001 From: calli Date: Tue, 22 Apr 2025 17:35:16 +0300 Subject: [PATCH] move exclusion directly to planet list and add more info to simulation --- .../PlanetConfig/PlanetConfigDialog.tsx | 32 +------- .../ExtractionSimulation.ts | 1 + .../ExtractionSimulationDisplay.tsx | 26 +++++-- .../PlanetaryInteraction/PlanetTableRow.tsx | 36 ++++++--- .../ProductionChainVisualization.tsx | 77 +++++++++++++++---- src/planets.ts | 13 +++- 6 files changed, 120 insertions(+), 65 deletions(-) diff --git a/src/app/components/PlanetConfig/PlanetConfigDialog.tsx b/src/app/components/PlanetConfig/PlanetConfigDialog.tsx index 2fa313e..f229f6d 100644 --- a/src/app/components/PlanetConfig/PlanetConfigDialog.tsx +++ b/src/app/components/PlanetConfig/PlanetConfigDialog.tsx @@ -3,8 +3,6 @@ import { planetCalculations } from "@/planets"; import { AccessToken, PlanetWithInfo } from "@/types"; import { Card, - Checkbox, - FormControlLabel, Table, TableBody, TableCell, @@ -20,12 +18,6 @@ import Image from "next/image"; import { ColorContext, SessionContext } from "@/app/context/Context"; import { useContext } from "react"; -export type PlanetConfig = { - characterId: number; - planetId: number; - excludeFromTotals: boolean; -}; - export const PlanetConfigDialog = ({ planet, character, @@ -35,14 +27,9 @@ export const PlanetConfigDialog = ({ }) => { const theme = useTheme(); const { colors } = useContext(ColorContext); - const { piPrices, readPlanetConfig, updatePlanetConfig } = - useContext(SessionContext); + const { piPrices } = useContext(SessionContext); const { extractors, localProduction, localImports, localExports } = planetCalculations(planet); - const planetConfig = readPlanetConfig({ - characterId: character.character.characterId, - planetId: planet.planet_id, - }); return ( @@ -189,23 +176,6 @@ export const PlanetConfigDialog = ({ - - Planet configuration - - updatePlanetConfig({ - ...planetConfig, - excludeFromTotals: !planetConfig.excludeFromTotals, - }) - } - /> - } - label="Consumed by production chain" - /> - ); }; diff --git a/src/app/components/PlanetaryInteraction/ExtractionSimulation.ts b/src/app/components/PlanetaryInteraction/ExtractionSimulation.ts index 5abb0f7..f56a8ae 100644 --- a/src/app/components/PlanetaryInteraction/ExtractionSimulation.ts +++ b/src/app/components/PlanetaryInteraction/ExtractionSimulation.ts @@ -65,6 +65,7 @@ export interface ProductionNode { quantity: number; }>; cycleTime: number; + factoryCount: number; } export interface ProductionChainBalance { diff --git a/src/app/components/PlanetaryInteraction/ExtractionSimulationDisplay.tsx b/src/app/components/PlanetaryInteraction/ExtractionSimulationDisplay.tsx index a91cdaa..7849b46 100644 --- a/src/app/components/PlanetaryInteraction/ExtractionSimulationDisplay.tsx +++ b/src/app/components/PlanetaryInteraction/ExtractionSimulationDisplay.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { Box, Paper, Typography, Stack } from '@mui/material'; import { Line } from 'react-chartjs-2'; -import { useTheme } from '@mui/material'; import { getProgramOutputPrediction, ProductionNode } from './ExtractionSimulation'; import { PI_TYPES_MAP } from '@/const'; import { ProductionChainVisualization } from './ProductionChainVisualization'; @@ -15,6 +14,8 @@ import { Tooltip, Legend } from 'chart.js'; +import { DateTime } from 'luxon'; +import Countdown from 'react-countdown'; ChartJS.register( CategoryScale, @@ -43,6 +44,7 @@ export const ExtractionSimulationDisplay: React.FC { + const CYCLE_TIME = 30 * 60; // 30 minutes in seconds // Calculate program duration and cycles for each extractor @@ -57,6 +59,7 @@ export const ExtractionSimulationDisplay: React.FC e.cycles)); // Get output predictions for each extractor @@ -156,10 +159,14 @@ export const ExtractionSimulationDisplay: React.FC node.schematicId))); // Create factories array with correct counts - const factories = installedSchematicIds.map(schematicId => ({ - schematic_id: schematicId, - count: productionNodes.filter(node => node.schematicId === schematicId).length - })); + const factories = installedSchematicIds.map(schematicId => { + const node = productionNodes.find(n => n.schematicId === schematicId); + if (!node) return { schematic_id: schematicId, count: 0 }; + return { + schematic_id: schematicId, + count: node.factoryCount + }; + }); return ( @@ -191,6 +198,12 @@ export const ExtractionSimulationDisplay: React.FC • Expiry Time: {new Date(expiryTime).toLocaleString()} + + • Factory Count: {factories.find(f => f.schematic_id === typeId)?.count ?? 0} + + + • Expires in: + ))} @@ -204,7 +217,8 @@ export const ExtractionSimulationDisplay: React.FC ({ typeId: e.typeId, baseValue: e.baseValue, - cycleTime: CYCLE_TIME + cycleTime: CYCLE_TIME, + expiryTime: e.expiryTime }))} factories={factories} extractorTotals={extractorTotals} diff --git a/src/app/components/PlanetaryInteraction/PlanetTableRow.tsx b/src/app/components/PlanetaryInteraction/PlanetTableRow.tsx index 7d2dec8..1d97dd9 100644 --- a/src/app/components/PlanetaryInteraction/PlanetTableRow.tsx +++ b/src/app/components/PlanetaryInteraction/PlanetTableRow.tsx @@ -4,7 +4,7 @@ import { planetCalculations } from "@/planets"; import { AccessToken, PlanetWithInfo } from "@/types"; import CloseIcon from "@mui/icons-material/Close"; import MoreVertIcon from '@mui/icons-material/MoreVert'; -import { Button, Tooltip, Typography, useTheme, Menu, MenuItem, IconButton } from "@mui/material"; +import { Button, Tooltip, Typography, useTheme, Menu, MenuItem, IconButton, Checkbox, FormControlLabel } from "@mui/material"; import AppBar from "@mui/material/AppBar"; import Dialog from "@mui/material/Dialog"; import Slide from "@mui/material/Slide"; @@ -72,14 +72,15 @@ export const PlanetTableRow = ({ setPlanetConfigOpen(false); }; - const { piPrices, alertMode } = useContext(SessionContext); + const { piPrices, alertMode, updatePlanetConfig, readPlanetConfig } = useContext(SessionContext); const planetInfo = planet.info; const planetInfoUniverse = planet.infoUniverse; const { expired, extractors, localProduction, localImports, localExports } = planetCalculations(planet); - const planetConfig = character.planetConfig.find( - (p) => p.planetId === planet.planet_id, - ); + const planetConfig = readPlanetConfig({ + characterId: character.character.characterId, + planetId: planet.planet_id, + }); const { colors } = useContext(ColorContext); // Convert local production to ProductionNode array for simulation const productionNodes: ProductionNode[] = Array.from(localProduction).map(([schematicId, schematic]) => ({ @@ -94,7 +95,8 @@ export const PlanetTableRow = ({ typeId: output.type_id, quantity: output.quantity })), - cycleTime: schematic.cycle_time + cycleTime: schematic.cycle_time, + factoryCount: schematic.count || 1 })); const storageFacilities = planetInfo.pins.filter(pin => @@ -130,6 +132,13 @@ export const PlanetTableRow = ({ }; }; + const handleExcludeChange = (event: React.ChangeEvent) => { + updatePlanetConfig({ + ...planetConfig, + excludeFromTotals: event.target.checked, + }); + }; + return ( <>
{localExports.map((exports) => ( - - {planetConfig?.excludeFromTotals ? "ex" : ""} - + control={ + + } + label="" + /> ))}
diff --git a/src/app/components/PlanetaryInteraction/ProductionChainVisualization.tsx b/src/app/components/PlanetaryInteraction/ProductionChainVisualization.tsx index 71c2615..d1381fd 100644 --- a/src/app/components/PlanetaryInteraction/ProductionChainVisualization.tsx +++ b/src/app/components/PlanetaryInteraction/ProductionChainVisualization.tsx @@ -1,7 +1,9 @@ import React from 'react'; -import { Box, Paper, Typography, Grid, Stack, Divider } from '@mui/material'; +import { Box, Paper, Typography, Grid, Stack, Divider, Tooltip } from '@mui/material'; import { EVE_IMAGE_URL } from '@/const'; import { PI_TYPES_MAP } from '@/const'; +import { DateTime } from 'luxon'; +import Countdown from 'react-countdown'; interface Factory { schematic_id: number; @@ -29,6 +31,7 @@ interface ProductionChainVisualizationProps { typeId: number; baseValue: number; cycleTime: number; + expiryTime: string; }>; factories: Factory[]; extractorTotals: Map; @@ -39,8 +42,10 @@ export const ProductionChainVisualization: React.FC { + // Get all type IDs involved in the production chain const allTypeIds = new Set(); const requiredInputs = new Set(); @@ -214,9 +219,15 @@ export const ProductionChainVisualization: React.FC { - const node = nodesByOutput.get(typeId); - if (!node) return 0; - return factories.find(f => f.schematic_id === node.schematicId)?.count ?? 0; + // First find the node that produces this type + const producingNode = productionNodes.find(node => + node.outputs.some(output => output.typeId === typeId) + ); + + if (!producingNode) return 0; + + // Then find the factory count for this schematic + return factories.find(f => f.schematic_id === producingNode.schematicId)?.count ?? 0; }; // Get input requirements for a type @@ -232,6 +243,11 @@ export const ProductionChainVisualization: React.FC { + return extractors.find(e => e.typeId === typeId)?.expiryTime; + }; + return ( @@ -258,6 +274,7 @@ export const ProductionChainVisualization: React.FC @@ -292,19 +309,49 @@ export const ProductionChainVisualization: React.FC - {production > 0 && ( - <> - - Production: {production.toFixed(1)} units total + {factoryCount > 0 && ( + + Factories: {factoryCount} + + )} + {inputs.length > 0 && ( + + + Inputs: - + {inputs.map(input => ( + + {PI_TYPES_MAP[input.typeId]?.name}: {input.quantity * factoryCount}/cycle + + ))} + + )} + {expiryTime && ( + + + Extractor expires in: + + + + + + )} + {production > 0 && ( + + Production: {production.toFixed(1)} units total + )} {consumption > 0 && ( - <> - - Consumption: {consumption.toFixed(1)} units total - - + + Consumption: {consumption.toFixed(1)} units total + )} {isImported && ( <> diff --git a/src/planets.ts b/src/planets.ts index 55ae177..5982905 100644 --- a/src/planets.ts +++ b/src/planets.ts @@ -61,10 +61,19 @@ export const planetCalculations = (planet: PlanetWithInfo) => { const schematic = PI_SCHEMATICS.find( (s) => s.schematic_id == f.schematic_id, ); - if (schematic) acc.set(f.schematic_id, schematic); + if (schematic) { + const existing = acc.get(f.schematic_id); + if (existing) { + // If we already have this schematic, increment its count + existing.count = (existing.count || 0) + 1; + } else { + // First time seeing this schematic, set count to 1 + acc.set(f.schematic_id, { ...schematic, count: 1 }); + } + } } return acc; - }, new Map()); + }, new Map()); const locallyProduced = Array.from(localProduction) .flatMap((p) => p[1].outputs)