add simulations data

This commit is contained in:
2025-09-04 17:26:18 +05:30
parent 1cef2987a6
commit f6a63c20d7
11 changed files with 736 additions and 346 deletions

View File

@@ -0,0 +1,13 @@
interface SimulationData {
key: string;
data?: object | any;
}
export const saveSimulationData = ({ key, data }: SimulationData) => {
console.log("key: ", key);
localStorage.setItem(key, JSON.stringify(data));
};
export const getSimulationData = ({ key }: SimulationData) => {
const data = localStorage.getItem(key);
console.log("data: ", JSON.parse(data || "{}"));
};
export const clearSimulationData = ({ key, data }: SimulationData) => {};

View File

@@ -19,6 +19,7 @@ import { useProductContext } from "../../../../modules/simulation/products/produ
import { useParams } from "react-router-dom";
import { useVersionContext } from "../../../../modules/builder/version/versionContext";
import { useSceneContext } from "../../../../modules/scene/sceneContext";
import { getSimulationData } from "../../scenes/functions/simulationStorage";
interface Event {
modelName: string;
@@ -137,6 +138,7 @@ const Simulations: React.FC = () => {
if (selectedProductData) {
determineExecutionMachineSequences([selectedProductData]).then(
(sequences) => {
console.log('selectedProductData: ', selectedProductData);
sequences.forEach((sequence) => {
const events: Event[] =
sequence.map((event) => ({
@@ -151,6 +153,12 @@ const Simulations: React.FC = () => {
}
}, [selectedProduct.productUuid, products]);
//call when comparePopup is true
useEffect(() => {
if (comparePopUp || selectedProduct.productUuid) {
getSimulationData({ key: selectedProduct.productUuid });
}
}, [comparePopUp])
return (
<div className="simulations-container">

View File

@@ -1,6 +1,7 @@
import React, { useState, useRef, useEffect } from "react";
import { ExitIcon, PlayStopIcon, ResetIcon } from "../../icons/SimulationIcons";
import {
comparsionMaterialData,
useActiveTool,
useProcessBar,
useViewSceneStore,
@@ -32,6 +33,8 @@ import ROISummary from "../analysis/ROISummary";
import { usePlayerStore } from "../../../store/useUIToggleStore";
import { useComparisonProduct } from "../../../store/simulation/useSimulationStore";
import InputToggle from "../inputs/InputToggle";
import { saveSimulationData } from "../../layout/scenes/functions/simulationStorage";
import { useProductContext } from "../../../modules/simulation/products/productContext";
const SimulationPlayer: React.FC = () => {
const MAX_SPEED = 8; // Maximum speed
@@ -49,9 +52,11 @@ const SimulationPlayer: React.FC = () => {
const { subModule } = useSubModuleStore();
const { clearComparisonProduct } = useComparisonProduct();
const { viewSceneLabels, setViewSceneLabels } = useViewSceneStore();
const { materialData, setMaterialData } = comparsionMaterialData()
const { isPlaying } = usePlayButtonStore();
const { activeModule } = useModuleStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct, setSelectedProduct } = selectedProductStore();
useEffect(() => {
if (isReset) {
setTimeout(() => {
@@ -60,6 +65,12 @@ const SimulationPlayer: React.FC = () => {
}
}, [isReset, setReset]);
useEffect(() => {
if (materialData.length === 0) return;
console.log('materialData: ', materialData);
saveSimulationData({ key: selectedProduct.productUuid, data: materialData });
}, [materialData])
// Button functions
const handleReset = () => {
setReset(true);

View File

@@ -1,4 +1,5 @@
import { DepthOfField, Bloom, EffectComposer, N8AO } from "@react-three/postprocessing";
// import OutlineInstances from "./outlineInstances/outlineInstances";
import OutlineInstances from "./outlineInstances/outlineInstances";
import { useDeletableEventSphere, useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";

View File

@@ -1,8 +1,10 @@
import React, { useEffect } from 'react'
import { CompareProduct, useCompareProductDataStore, useInputValues, useMachineDowntime, useMachineUptime, useProductionCapacityData, useROISummaryData, useThroughPutData } from '../../../../store/builder/store';
import { CompareProduct, comparsionMaterialData, useCompareProductDataStore, useInputValues, useMachineDowntime, useMachineUptime, useProductionCapacityData, useROISummaryData, useThroughPutData } from '../../../../store/builder/store';
import { usePlayButtonStore } from '../../../../store/usePlayButtonStore';
import { useProductContext } from '../../products/productContext';
import { useSceneContext } from '../../../scene/sceneContext';
import { saveSimulationData } from '../../../../components/layout/scenes/functions/simulationStorage';
import { set } from 'immer/dist/internal';
export default function ROIData() {
const { selectedProductStore } = useProductContext();
@@ -17,6 +19,7 @@ export default function ROIData() {
const { machineActiveTime } = useMachineUptime();
const { machineIdleTime } = useMachineDowntime();
const { throughputData } = useThroughPutData()
const { materialData, setMaterialData } = comparsionMaterialData()
useEffect(() => {
if (isPlaying) return;
@@ -136,6 +139,22 @@ export default function ROIData() {
const Annual_net_profit = (Annual_units * (sellingPrice - materialCost - laborCost)) - (maintenanceCost + electricityCost + fixedCost) * workingDaysPerYear + (salvageValue * workingDaysPerYear)
const Payback_period_years = initialInvestment / Annual_net_profit;
const data = {
productName: selectedProduct.productName,
roiPercentage: ROI,
paybackPeriod: Payback_period_years,
totalCost: Total_cost,
revenueGenerated: Total_revenue,
netProfit: Net_profit > 0 ? Net_profit : 0,
netLoss: Net_profit < 0 ? -Net_profit : 0
}
console.log('selectedProduct.productUuid: ', selectedProduct.productUuid);
saveSimulationData({ key: selectedProduct.productUuid, data: data });
const datas = {
roi: data
}
setMaterialData(datas);
setRoiSummaryData({
productName: selectedProduct.productName,

View File

@@ -1,12 +1,15 @@
import { useEffect } from 'react'
import { useInputValues, useProductionCapacityData, useThroughPutData } from '../../../../store/builder/store'
import { comparsionMaterialData, useInputValues, useProductionCapacityData, useThroughPutData } from '../../../../store/builder/store'
import { usePlayButtonStore } from '../../../../store/usePlayButtonStore';
import { saveSimulationData } from '../../../../components/layout/scenes/functions/simulationStorage';
export default function ProductionCapacityData() {
const { throughputData } = useThroughPutData()
const { setProductionCapacityData } = useProductionCapacityData()
const { inputValues } = useInputValues();
const { isPlaying } = usePlayButtonStore();
const { materialData, setMaterialData } = comparsionMaterialData()
useEffect(() => {
if (!isPlaying) {
@@ -21,10 +24,12 @@ export default function ProductionCapacityData() {
if (!isNaN(workingDaysPerYear) && throughputData > 0) {
const Monthly_working_days = workingDaysPerYear / 12;
const Production_capacity_per_month = throughputData * Monthly_working_days;
const data = Number(Production_capacity_per_month.toFixed(2));
saveSimulationData({ key: 'productionCapacity', data: data });
setMaterialData({ ...materialData, productionCapacity: data });
setProductionCapacityData(Number(Production_capacity_per_month.toFixed(2)));
}
}, [throughputData, inputValues, isPlaying]);
}, [throughputData, inputValues, isPlaying, materialData]);
return (
<></>

View File

@@ -1,9 +1,10 @@
import { useEffect } from 'react';
import { determineExecutionMachineSequences } from '../../simulator/functions/determineExecutionMachineSequences';
import { useInputValues, useMachineCount, useMachineDowntime, useMachineUptime, useMaterialCycle, useProcessBar, useThroughPutData } from '../../../../store/builder/store';
import { comparsionMaterialData, useInputValues, useMachineCount, useMachineDowntime, useMachineUptime, useMaterialCycle, useProcessBar, useThroughPutData } from '../../../../store/builder/store';
import { usePlayButtonStore } from '../../../../store/usePlayButtonStore';
import { useSceneContext } from '../../../scene/sceneContext';
import { useProductContext } from '../../products/productContext';
import { saveSimulationData } from '../../../../components/layout/scenes/functions/simulationStorage';
export default function ThroughPutData() {
const { materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, productStore } = useSceneContext();
@@ -24,6 +25,7 @@ export default function ThroughPutData() {
const { setThroughputData } = useThroughPutData()
const { isPlaying } = usePlayButtonStore();
const { inputValues } = useInputValues();
const { materialData, setMaterialData } = comparsionMaterialData()
// Setting machine count
let totalItems = 0;
@@ -219,9 +221,13 @@ export default function ThroughPutData() {
const Units_per_shift = (shiftLength * 60) / (materialCycleTime / 60);
const Throughput_per_day = Units_per_shift * shiftsPerDay * (yieldRate / 100);
const data = Number(Throughput_per_day.toFixed(2))
saveSimulationData({ key: selectedProduct.productUuid, data: data });
setMaterialData({ ...materialData, throughput: data });
setThroughputData(Number(Throughput_per_day.toFixed(2))); // Keep as number
}
}, [materialCycleTime, machineCount, isPlaying, inputValues]);
}, [materialCycleTime, machineCount, isPlaying, inputValues, materialData]);
return (
<>

View File

@@ -0,0 +1,181 @@
import React, { useEffect } from 'react';
import { useSceneContext } from '../../scene/sceneContext';
import { useProductContext } from '../products/productContext';
import { determineExecutionMachineSequences } from './functions/determineExecutionMachineSequences';
import { usePlayButtonStore } from '../../../store/usePlayButtonStore';
import { useSimulationManager } from '../../../store/rough/useSimulationManagerStore';
import { useParams } from 'react-router-dom';
import { useVersionContext } from '../../builder/version/versionContext';
interface SimulationUsageRecord {
activeTime: number;
isActive: boolean;
idleTime: number;
type:
| "roboticArm"
| "vehicle"
| "transfer"
| "storageUnit"
| "crane"
| "human"
| "machine";
}
// Product → holds multiple usage records
interface ProductSimulation {
productId: string;
data: SimulationUsageRecord[];
}
// Version → holds multiple products
interface VersionSimulation {
versionId: string;
products: ProductSimulation[];
}
// Project → holds multiple versions
interface ProjectSimulation {
projectId: string | undefined;
versions: VersionSimulation[];
}
const SimulationHandler = () => {
const { materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, productStore, craneStore, humanStore } = useSceneContext();
const { armBots, getArmBotById } = armBotStore();
const { vehicles, getVehicleById } = vehicleStore();
const { getConveyorById } = conveyorStore();
const { materialHistory, materials } = materialStore();
const { getProductById } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { machines, getMachineById } = machineStore();
const { getHumanById } = humanStore();
const { getCraneById, } = craneStore();
const { getStorageUnitById } = storageUnitStore();
const { isPlaying, setIsPlaying } = usePlayButtonStore();
const { simulationData, addData } = useSimulationManager();
const { projectId } = useParams();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
useEffect(() => {
let checkTimer: ReturnType<typeof setTimeout>;
if (!projectId) return;
async function checkActiveMachines() {
const currentProduct = getProductById(selectedProduct.productUuid);
let hasActiveEntity = false;
if (currentProduct) {
const executionSequences = await determineExecutionMachineSequences([currentProduct]);
if (executionSequences?.length > 0) {
executionSequences.forEach(sequence => {
sequence.forEach(entity => {
if (entity.type === 'roboticArm') {
const roboticArm = getArmBotById(entity.modelUuid);
if (roboticArm?.isActive) {
hasActiveEntity = true;
}
}
if (entity.type === 'vehicle') {
const vehicle = getVehicleById(entity.modelUuid);
if (vehicle?.isActive) {
hasActiveEntity = true;
}
}
if (entity.type === 'machine') {
const machine = getMachineById(entity.modelUuid);
if (machine?.isActive) {
hasActiveEntity = true;
}
}
if (entity.type === 'human') {
const human = getHumanById(entity.modelUuid);
if (human?.isActive) {
hasActiveEntity = true;
}
}
if (entity.type === 'crane') {
const crane = getCraneById(entity.modelUuid);
if (crane?.isActive) {
hasActiveEntity = true;
}
}
if (entity.type === 'storageUnit') {
const storageUnit = getStorageUnitById(entity.modelUuid);
if (storageUnit?.isActive) {
hasActiveEntity = true;
}
}
if (entity.type === "transfer") {
const storageUnit = getConveyorById(entity.modelUuid);
if (storageUnit?.isActive) {
hasActiveEntity = true;
}
}
});
});
}
if (materials.length === 0 && materialHistory.length >= 0 && !hasActiveEntity) {
if (executionSequences?.length > 0) {
executionSequences.forEach((sequence) => {
sequence.forEach((entity) => {
const typeToGetter: Record<string, (id: string) => any> = {
roboticArm: getArmBotById,
vehicle: getVehicleById,
machine: getMachineById,
human: getHumanById,
crane: getCraneById,
storageUnit: getStorageUnitById,
transfer: getConveyorById,
};
const getter = typeToGetter[entity.type];
if (!getter) return; // skip unknown entity types
const obj = getter(entity.modelUuid);
if (!obj) return; // skip if not found
addData(
projectId,
selectedVersion?.versionId || "",
selectedProduct?.productUuid,
{
activeTime: obj.activeTime ?? 0,
isActive: obj.isActive ?? false,
idleTime: obj.idleTime ?? 0,
type: entity.type as
| "roboticArm"
| "vehicle"
| "machine"
| "human"
| "crane"
| "storageUnit"
| "transfer",
}
);
});
});
}
setIsPlaying(false);
}
}
}
if (isPlaying) {
checkTimer = setTimeout(() => {
checkActiveMachines();
}, 1500);
}
return () => {
if (checkTimer) clearTimeout(checkTimer);
};
}, [materials, materialHistory, selectedVersion, selectedProduct?.productUuid, isPlaying, armBots, vehicles, machines]);
return null;
}
export default SimulationHandler;

View File

@@ -4,6 +4,7 @@ import { usePlayButtonStore, useResetButtonStore } from '../../../store/usePlayB
import { determineExecutionOrder } from './functions/determineExecutionOrder';
import { useProductContext } from '../products/productContext';
import { useSceneContext } from '../../scene/sceneContext';
import SimulationHandler from './SimulationHandler';
function Simulator() {
const { selectedProductStore } = useProductContext();
@@ -32,6 +33,9 @@ function Simulator() {
<>
{/* <simulationHandler/> */}
<SimulationHandler />
</>
);

View File

@@ -377,10 +377,12 @@ interface ResourceManagementState {
setResourceManagementId: (id: string) => void;
}
export const useResourceManagementId = create<ResourceManagementState>((set) => ({
export const useResourceManagementId = create<ResourceManagementState>(
(set) => ({
resourceManagementId: "", // default value
setResourceManagementId: (id: string) => set({ resourceManagementId: id }),
}));
})
);
// version visible hidden
interface VersionHistoryState {
@@ -590,7 +592,6 @@ export const useContextActionStore = create<any>((set: any) => ({
setContextAction: (x: any) => set({ contextAction: x }),
}));
// Define the store's state and actions type
interface DecalStore {
selectedSubCategory: string | null;
@@ -599,6 +600,11 @@ interface DecalStore {
// Create the Zustand store with types
export const useDecalStore = create<DecalStore>((set) => ({
selectedSubCategory: 'Safety',
setSelectedSubCategory: (subCategory: string | null) => set({ selectedSubCategory: subCategory }),
selectedSubCategory: "Safety",
setSelectedSubCategory: (subCategory: string | null) =>
set({ selectedSubCategory: subCategory }),
}));
export const comparsionMaterialData = create<any>((set: any) => ({
materialData: [],
setMaterialData: (x: any) => set({ materialData: x }),
}));

View File

@@ -0,0 +1,136 @@
import { create } from "zustand";
interface SimulationUsageRecord {
activeTime: number;
isActive: boolean;
idleTime: number;
type:
| "roboticArm"
| "vehicle"
| "transfer"
| "storageUnit"
| "crane"
| "human"
| "machine";
}
// Product → holds multiple usage records
interface ProductSimulation {
productId: string;
data: SimulationUsageRecord[];
}
// Version → holds multiple products
interface VersionSimulation {
versionId: string;
products: ProductSimulation[];
}
// Project → holds multiple versions
interface ProjectSimulation {
projectId: string | undefined;
versions: VersionSimulation[];
}
// or same file
interface SimulationManagerStore {
simulationData: ProjectSimulation[];
addData: (
projectId: string | undefined,
versionId: string,
productId: string,
record: SimulationUsageRecord
) => void;
resetProductData: (
projectId: string,
versionId: string,
productId: string
) => void;
}
export const useSimulationManager = create<SimulationManagerStore>((set) => ({
simulationData: [],
addData: (projectId, versionId, productId, record) =>
set((state) => {
const projects = state.simulationData.map((project) => {
if (project.projectId !== projectId) return project;
return {
...project,
versions: project.versions.map((version) => {
if (version.versionId !== versionId) return version;
return {
...version,
products: version.products.map((product) =>
product.productId === productId
? { ...product, data: [...product.data, record] }
: product
),
};
}),
};
});
// If project doesn't exist, create it
if (!state.simulationData.find((p) => p.projectId === projectId)) {
projects.push({
projectId,
versions: [
{
versionId,
products: [{ productId, data: [record] }],
},
],
});
} else {
const project = projects.find((p) => p.projectId === projectId)!;
if (!project.versions.find((v) => v.versionId === versionId)) {
project.versions.push({
versionId,
products: [{ productId, data: [record] }],
});
} else {
const version = project.versions.find(
(v) => v.versionId === versionId
)!;
if (!version.products.find((p) => p.productId === productId)) {
version.products.push({ productId, data: [record] });
}
}
}
return { simulationData: projects };
}),
resetProductData: (projectId, versionId, productId) =>
set((state) => {
const projects = state.simulationData.map((project) => {
if (project.projectId !== projectId) return project;
return {
...project,
versions: project.versions.map((version) => {
if (version.versionId !== versionId) return version;
return {
...version,
products: version.products.map((product) =>
product.productId === productId
? { ...product, data: [] }
: product
),
};
}),
};
});
return { simulationData: projects };
}),
}));
///////////////////////////