added comparsion data

This commit is contained in:
2025-09-05 15:06:35 +05:30
parent f6a63c20d7
commit b3a4c03ba0
7 changed files with 584 additions and 351 deletions

View File

@@ -1,15 +1,103 @@
import { useProductContext } from '../../../modules/simulation/products/productContext' import { useProductContext } from "../../../modules/simulation/products/productContext";
import RegularDropDown from '../../ui/inputs/RegularDropDown'; import RegularDropDown from "../../ui/inputs/RegularDropDown";
import { useCompareProductDataStore, useLoadingProgress, useSaveVersion } from '../../../store/builder/store'; import { useCompareProductDataStore, useLoadingProgress, useSaveVersion } from "../../../store/builder/store";
import useModuleStore from '../../../store/useModuleStore'; import useModuleStore from "../../../store/useModuleStore";
import CompareLayOut from '../../ui/compareVersion/CompareLayOut'; import CompareLayOut from "../../ui/compareVersion/CompareLayOut";
import ComparisonResult from '../../ui/compareVersion/ComparisonResult'; import ComparisonResult from "../../ui/compareVersion/ComparisonResult";
import { useComparisonProduct, useMainProduct } from '../../../store/simulation/useSimulationStore'; import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore";
import { usePlayButtonStore } from '../../../store/usePlayButtonStore'; import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
import { useEffect, useState } from 'react'; import { useEffect, useState } from "react";
import { useVersionHistoryStore } from '../../../store/builder/useVersionHistoryStore'; import { useVersionHistoryStore } from "../../../store/builder/useVersionHistoryStore";
import { useVersionContext } from '../../../modules/builder/version/versionContext'; import { useVersionContext } from "../../../modules/builder/version/versionContext";
import { useSceneContext } from '../../../modules/scene/sceneContext'; import { useSceneContext } from "../../../modules/scene/sceneContext";
import { useSimulationManager } from "../../../store/rough/useSimulationManagerStore";
import { useParams } from "react-router-dom";
export interface CompareProduct {
productUuid: string;
productName: string;
simulationData: {
roiPercentage: number;
netProfit: number;
productionCapacity: number;
paybackPeriod: number;
machineIdleTime: number;
machineActiveTime: number;
throughputData: number;
simulationTime?: number;
simulationCost?: number;
efficiencyScore?: number;
};
}
type AssetData = {
activeTime: number;
idleTime: number;
type: string;
assetId: string;
};
const calculateSimulationData = (assets: AssetData[]) => {
let totalActiveTime = 0;
let totalIdleTime = 0;
let throughput = 0;
let productionCapacity = 0;
let simulationCost = 0;
// Cost weight per type (example values, adjust as needed)
const costWeight: Record<string, number> = {
roboticArm: 50,
machine: 100,
human: 30,
transfer: 20,
storageUnit: 10,
};
assets.forEach((asset) => {
totalActiveTime += asset.activeTime;
totalIdleTime += asset.idleTime;
if (asset.activeTime > 0) throughput += 1;
productionCapacity += asset.activeTime;
simulationCost += asset.activeTime * (costWeight[asset.type] || 10);
});
const machineActiveTime = assets.filter((a) => a.type === "machine").reduce((acc, a) => acc + a.activeTime, 0);
const machineIdleTime = assets.filter((a) => a.type === "machine").reduce((acc, a) => acc + a.idleTime, 0);
const simulationTime = totalActiveTime + totalIdleTime;
// --- Efficiency Score ---
// Weighted formula: lower cost + lower time => higher score
// Example formula (normalize to 0100):
const efficiencyScore = Math.max(
0,
100 -
(simulationTime / 1000) * 0.5 - // weight 0.5 for time
(simulationCost / 1000) * 0.5 // weight 0.5 for cost
);
return {
throughputData: throughput,
machineActiveTime,
machineIdleTime,
productionCapacity,
netProfit: 0, // placeholder
roiPercentage: 0, // placeholder
paybackPeriod: 0, // placeholder
simulationTime,
simulationCost,
efficiencyScore,
};
};
export const createCompareProduct = (productUuid: string, productName: string, assets: AssetData[]): CompareProduct => ({
productUuid,
productName,
simulationData: calculateSimulationData(assets),
});
function ComparisonScene() { function ComparisonScene() {
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
@@ -27,6 +115,8 @@ function ComparisonScene() {
const { versionHistory } = useVersionHistoryStore(); const { versionHistory } = useVersionHistoryStore();
const { selectedVersionStore } = useVersionContext(); const { selectedVersionStore } = useVersionContext();
const { selectedVersion, setSelectedVersion } = selectedVersionStore(); const { selectedVersion, setSelectedVersion } = selectedVersionStore();
const { simulationRecords } = useSimulationManager();
const { projectId } = useParams();
const handleSelectVersion = (option: string) => { const handleSelectVersion = (option: string) => {
const version = versionHistory.find((version) => version.versionName === option); const version = versionHistory.find((version) => version.versionName === option);
@@ -79,27 +169,53 @@ function ComparisonScene() {
// ]) // ])
// }, []); // }, []);
// useEffect(() => {
// console.log('mainProduct: ', mainProduct);
// console.log('comparisonProduct: ', comparisonProduct);
// if (mainProduct && comparisonProduct) {
// // if (mainProduct && comparisonProduct && compareProductsData.length > 1) {
// // console.log('compareProductsData: ', compareProductsData);
// const hasMain = compareProductsData.some(val => val.productUuid === mainProduct.productUuid);
// const hasComparison = compareProductsData.some(val => val.productUuid === comparisonProduct.productUuid);
// console.log('hasMain: ', hasMain);
// console.log('hasComparison: ', hasComparison);
// if (hasMain && hasComparison) {
// setShouldShowComparisonResult(true);
// } else {
// setShouldShowComparisonResult(false);
// }
// }
// }, [compareProductsData, mainProduct, comparisonProduct]);
useEffect(() => { useEffect(() => {
if (mainProduct && comparisonProduct && compareProductsData.length > 1) { if (mainProduct && comparisonProduct && selectedVersion) {
// console.log('compareProductsData: ', compareProductsData); const product1 = useSimulationManager.getState().getProductById(projectId, selectedVersion?.versionId, mainProduct.productUuid);
const hasMain = compareProductsData.some(val => val.productUuid === mainProduct.productUuid);
const hasComparison = compareProductsData.some(val => val.productUuid === comparisonProduct.productUuid); const product2 = useSimulationManager.getState().getProductById(projectId, selectedVersion?.versionId, comparisonProduct.productUuid);
if (hasMain && hasComparison && mainProduct.productUuid !== comparisonProduct.productUuid) {
const compareProduct1 = createCompareProduct(product1?.productId ?? "", mainProduct.productName, product1?.data || []);
const compareProduct2 = createCompareProduct(product2?.productId ?? "", comparisonProduct.productName, product2?.data || []);
const comparedArray = [compareProduct1, compareProduct2];
if (product1 == undefined || product2 === undefined) {
setShouldShowComparisonResult(false);
} else if (comparedArray.length === 2) {
console.log("comparedArray: ", comparedArray);
setCompareProductsData(comparedArray);
setShouldShowComparisonResult(true); setShouldShowComparisonResult(true);
} else {
setShouldShowComparisonResult(false);
} }
} else { } else {
setShouldShowComparisonResult(false); setShouldShowComparisonResult(false);
} }
}, [compareProductsData, mainProduct, comparisonProduct]); }, [mainProduct, comparisonProduct, simulationRecords]);
return ( return (
<> <>
{isVersionSaved && activeModule === "simulation" && selectedProduct && ( {isVersionSaved && activeModule === "simulation" && selectedProduct && (
<> <>
{selectedVersion && !isPlaying && {selectedVersion && !isPlaying && (
<div className="initial-selectLayout-wrapper"> <div className="initial-selectLayout-wrapper">
<RegularDropDown <RegularDropDown
header={selectedVersion.versionName} header={selectedVersion.versionName}
@@ -115,14 +231,13 @@ function ComparisonScene() {
search={false} search={false}
/> />
</div> </div>
} )}
<CompareLayOut /> <CompareLayOut />
{shouldShowComparisonResult && !loadingProgress && compareProductsData && <ComparisonResult />}
{(shouldShowComparisonResult && !loadingProgress) && <ComparisonResult />}
</> </>
)} )}
</> </>
) );
} }
export default ComparisonScene; export default ComparisonScene;

View File

@@ -9,5 +9,6 @@ export const saveSimulationData = ({ key, data }: SimulationData) => {
export const getSimulationData = ({ key }: SimulationData) => { export const getSimulationData = ({ key }: SimulationData) => {
const data = localStorage.getItem(key); const data = localStorage.getItem(key);
console.log("data: ", JSON.parse(data || "{}")); console.log("data: ", JSON.parse(data || "{}"));
return data;
}; };
export const clearSimulationData = ({ key, data }: SimulationData) => {}; export const clearSimulationData = ({ key, data }: SimulationData) => {};

View File

@@ -2,9 +2,25 @@ import React, { useEffect, useMemo, useState } from "react";
import PerformanceResult from "./result-card/PerformanceResult"; import PerformanceResult from "./result-card/PerformanceResult";
import EnergyUsage from "./result-card/EnergyUsage"; import EnergyUsage from "./result-card/EnergyUsage";
import { Bar, Line, Pie } from "react-chartjs-2"; import { Bar, Line, Pie } from "react-chartjs-2";
import { CompareProduct, useCompareProductDataStore } from "../../../store/builder/store"; import { useCompareProductDataStore } from "../../../store/builder/store";
// import { CompareProduct, useCompareProductDataStore } from "../../../store/builder/store";
import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore"; import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore";
export interface CompareProduct {
productUuid: string;
productName: string;
simulationData: {
roiPercentage: number;
netProfit: number;
productionCapacity: number;
paybackPeriod: number;
machineIdleTime: number;
machineActiveTime: number;
throughputData: number;
simulationTime?: number;
simulationCost?: number;
efficiencyScore?: number;
};
}
const ComparisonResult = () => { const ComparisonResult = () => {
const { compareProductsData, setCompareProductsData } = useCompareProductDataStore(); const { compareProductsData, setCompareProductsData } = useCompareProductDataStore();
const { comparisonProduct, setComparisonProduct } = useComparisonProduct(); const { comparisonProduct, setComparisonProduct } = useComparisonProduct();
@@ -13,12 +29,8 @@ const ComparisonResult = () => {
useEffect(() => { useEffect(() => {
if (compareProductsData.length > 0 && mainProduct && comparisonProduct) { if (compareProductsData.length > 0 && mainProduct && comparisonProduct) {
const mainProductData = compareProductsData.find( const mainProductData = compareProductsData.find((product) => product.productUuid === mainProduct.productUuid);
(product) => product.productUuid === mainProduct.productUuid const comparisonProductData = compareProductsData.find((product) => product.productUuid === comparisonProduct.productUuid);
);
const comparisonProductData = compareProductsData.find(
(product) => product.productUuid === comparisonProduct.productUuid
);
if (mainProductData && comparisonProductData) { if (mainProductData && comparisonProductData) {
setComparedProducts([mainProductData, comparisonProductData]); setComparedProducts([mainProductData, comparisonProductData]);
@@ -32,7 +44,6 @@ const ComparisonResult = () => {
useEffect(() => { useEffect(() => {
if (comparedProducts.length === 2) { if (comparedProducts.length === 2) {
} }
}, [comparedProducts]); }, [comparedProducts]);
@@ -71,7 +82,6 @@ const ComparisonResult = () => {
], ],
}; };
const cycleTimePieData = { const cycleTimePieData = {
labels: [comparedProducts[0]?.productName, comparedProducts[1]?.productName], labels: [comparedProducts[0]?.productName, comparedProducts[1]?.productName],
datasets: [ datasets: [
@@ -115,25 +125,17 @@ const ComparisonResult = () => {
const highestProductivityProduct = (comparedProducts[0]?.simulationData?.productionCapacity ?? 0) > (comparedProducts[1]?.simulationData?.productionCapacity ?? 0) ? comparedProducts[0] : comparedProducts[1]; const highestProductivityProduct = (comparedProducts[0]?.simulationData?.productionCapacity ?? 0) > (comparedProducts[1]?.simulationData?.productionCapacity ?? 0) ? comparedProducts[0] : comparedProducts[1];
const product1CyclePercentage = (comparedProducts[0]?.simulationData?.machineActiveTime ?? 0) / const product1CyclePercentage = ((comparedProducts[0]?.simulationData?.machineActiveTime ?? 0) / ((compareProductsData[0]?.simulationData?.machineActiveTime ?? 0) + (compareProductsData[0]?.simulationData?.machineIdleTime ?? 0))) * 100;
((compareProductsData[0]?.simulationData?.machineActiveTime ?? 0) + const product2CyclePercentage = ((comparedProducts[1]?.simulationData?.machineActiveTime ?? 0) / ((compareProductsData[1]?.simulationData?.machineActiveTime ?? 0) + (compareProductsData[1]?.simulationData?.machineIdleTime ?? 0))) * 100;
(compareProductsData[0]?.simulationData?.machineIdleTime ?? 0)) * 100;
const product2CyclePercentage = ((comparedProducts[1]?.simulationData?.machineActiveTime ?? 0) /
((compareProductsData[1]?.simulationData?.machineActiveTime ?? 0) +
(compareProductsData[1]?.simulationData?.machineIdleTime ?? 0))) * 100;
const product1IdlePercentage = (comparedProducts[0]?.simulationData?.machineIdleTime ?? 0) / const product1IdlePercentage = ((comparedProducts[0]?.simulationData?.machineIdleTime ?? 0) / ((compareProductsData[0]?.simulationData?.machineActiveTime ?? 0) + (compareProductsData[0]?.simulationData?.machineIdleTime ?? 0))) * 100;
((compareProductsData[0]?.simulationData?.machineActiveTime ?? 0) + const product2IdlePercentage = ((comparedProducts[1]?.simulationData?.machineIdleTime ?? 0) / ((compareProductsData[1]?.simulationData?.machineActiveTime ?? 0) + (compareProductsData[1]?.simulationData?.machineIdleTime ?? 0))) * 100;
(compareProductsData[0]?.simulationData?.machineIdleTime ?? 0)) * 100;
const product2IdlePercentage = ((comparedProducts[1]?.simulationData?.machineIdleTime ?? 0) /
((compareProductsData[1]?.simulationData?.machineActiveTime ?? 0) +
(compareProductsData[1]?.simulationData?.machineIdleTime ?? 0))) * 100;
return ( return (
<div className="compare-result-container"> <div className="compare-result-container">
<div className="header">Performance Comparison</div> <div className="header">Performance Comparison</div>
<div className="compare-result-wrapper"> <div className="compare-result-wrapper">
<EnergyUsage comparedProducts={comparedProducts}/> <EnergyUsage comparedProducts={comparedProducts} />
<div className="throughPutCard-container comparisionCard"> <div className="throughPutCard-container comparisionCard">
<h4>Throughput (units/hr)</h4> <h4>Throughput (units/hr)</h4>
<div className="layers-wrapper"> <div className="layers-wrapper">
@@ -159,14 +161,16 @@ const ComparisonResult = () => {
<div className="layer-name">{comparedProducts[0]?.productName}</div> <div className="layer-name">{comparedProducts[0]?.productName}</div>
<div className="layer-time">{compareProductsData[0]?.simulationData.machineActiveTime} Sec</div> <div className="layer-time">{compareProductsData[0]?.simulationData.machineActiveTime} Sec</div>
<div className="layer-profit"> <div className="layer-profit">
<span></span>{(100 - product1CyclePercentage).toFixed(2)}% <span></span>
{(100 - product1CyclePercentage).toFixed(2)}%
</div> </div>
</div> </div>
<div className="layers"> <div className="layers">
<div className="layer-name">{comparedProducts[1]?.productName}</div> <div className="layer-name">{comparedProducts[1]?.productName}</div>
<div className="layer-time">{compareProductsData[1]?.simulationData.machineActiveTime} Sec</div> <div className="layer-time">{compareProductsData[1]?.simulationData.machineActiveTime} Sec</div>
<div className="layer-profit"> <div className="layer-profit">
<span></span>{(100 - product2CyclePercentage).toFixed(2)}% <span></span>
{(100 - product2CyclePercentage).toFixed(2)}%
</div> </div>
</div> </div>
</div> </div>
@@ -184,14 +188,16 @@ const ComparisonResult = () => {
<div className="layer-name">{comparedProducts[0]?.productName}</div> <div className="layer-name">{comparedProducts[0]?.productName}</div>
<div className="layer-time">{compareProductsData[0]?.simulationData.machineIdleTime} Sec</div> <div className="layer-time">{compareProductsData[0]?.simulationData.machineIdleTime} Sec</div>
<div className="layer-profit"> <div className="layer-profit">
<span></span>{(100 - product1IdlePercentage).toFixed(2)}% <span></span>
{(100 - product1IdlePercentage).toFixed(2)}%
</div> </div>
</div> </div>
<div className="layers"> <div className="layers">
<div className="layer-name">{comparedProducts[1]?.productName}</div> <div className="layer-name">{comparedProducts[1]?.productName}</div>
<div className="layer-time">{compareProductsData[1]?.simulationData.machineIdleTime} Sec</div> <div className="layer-time">{compareProductsData[1]?.simulationData.machineIdleTime} Sec</div>
<div className="layer-profit"> <div className="layer-profit">
<span></span>{(100 - product2IdlePercentage).toFixed(2)}% <span></span>
{(100 - product2IdlePercentage).toFixed(2)}%
</div> </div>
</div> </div>
</div> </div>
@@ -200,7 +206,7 @@ const ComparisonResult = () => {
<Pie data={downtimeData} options={options} /> <Pie data={downtimeData} options={options} />
</div> </div>
</div> </div>
{/* {/*
<div className="overallDowntime-container comparisionCard"> <div className="overallDowntime-container comparisionCard">
<h4 className="overallDowntime-header">Overall Downtime</h4> <h4 className="overallDowntime-header">Overall Downtime</h4>
<div className="totalDownTime-wrapper"> <div className="totalDownTime-wrapper">
@@ -234,7 +240,7 @@ const ComparisonResult = () => {
</div> </div>
</div> </div>
{ comparedProducts.length === 2 &&<PerformanceResult comparedProducts={comparedProducts}/>} {comparedProducts.length === 2 && <PerformanceResult comparedProducts={comparedProducts} />}
</div> </div>
</div> </div>
); );

View File

@@ -222,6 +222,7 @@ export default function ThroughPutData() {
const Throughput_per_day = Units_per_shift * shiftsPerDay * (yieldRate / 100); const Throughput_per_day = Units_per_shift * shiftsPerDay * (yieldRate / 100);
const data = Number(Throughput_per_day.toFixed(2)) const data = Number(Throughput_per_day.toFixed(2))
console.log('data: ', data);
saveSimulationData({ key: selectedProduct.productUuid, data: data }); saveSimulationData({ key: selectedProduct.productUuid, data: data });
setMaterialData({ ...materialData, throughput: data }); setMaterialData({ ...materialData, throughput: data });

View File

@@ -1,11 +1,13 @@
import React, { useEffect } from 'react'; import React, { useEffect } from "react";
import { useSceneContext } from '../../scene/sceneContext'; import { useSceneContext } from "../../scene/sceneContext";
import { useProductContext } from '../products/productContext'; import { useProductContext } from "../products/productContext";
import { determineExecutionMachineSequences } from './functions/determineExecutionMachineSequences'; import { determineExecutionMachineSequences } from "./functions/determineExecutionMachineSequences";
import { usePlayButtonStore } from '../../../store/usePlayButtonStore'; import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
import { useSimulationManager } from '../../../store/rough/useSimulationManagerStore'; import { useSimulationManager } from "../../../store/rough/useSimulationManagerStore";
import { useParams } from 'react-router-dom'; import { useParams } from "react-router-dom";
import { useVersionContext } from '../../builder/version/versionContext'; import { useVersionContext } from "../../builder/version/versionContext";
import { getSimulationData, saveSimulationData } from "../../../components/layout/scenes/functions/simulationStorage";
import { get } from "http";
interface SimulationUsageRecord { interface SimulationUsageRecord {
activeTime: number; activeTime: number;
isActive: boolean; isActive: boolean;
@@ -38,7 +40,17 @@ interface ProjectSimulation {
versions: VersionSimulation[]; versions: VersionSimulation[];
} }
const SimulationHandler = () => { const SimulationHandler = () => {
const { materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, productStore, craneStore, humanStore } = useSceneContext(); const {
materialStore,
armBotStore,
machineStore,
conveyorStore,
vehicleStore,
storageUnitStore,
productStore,
craneStore,
humanStore,
} = useSceneContext();
const { armBots, getArmBotById } = armBotStore(); const { armBots, getArmBotById } = armBotStore();
const { vehicles, getVehicleById } = vehicleStore(); const { vehicles, getVehicleById } = vehicleStore();
const { getConveyorById } = conveyorStore(); const { getConveyorById } = conveyorStore();
@@ -48,16 +60,106 @@ const SimulationHandler = () => {
const { selectedProduct } = selectedProductStore(); const { selectedProduct } = selectedProductStore();
const { machines, getMachineById } = machineStore(); const { machines, getMachineById } = machineStore();
const { getHumanById } = humanStore(); const { getHumanById } = humanStore();
const { getCraneById, } = craneStore(); const { getCraneById } = craneStore();
const { getStorageUnitById } = storageUnitStore(); const { getStorageUnitById } = storageUnitStore();
const { isPlaying, setIsPlaying } = usePlayButtonStore(); const { isPlaying, setIsPlaying } = usePlayButtonStore();
const { simulationData, addData } = useSimulationManager(); const { simulationRecords, addSimulationRecord } = useSimulationManager();
const { projectId } = useParams(); const { projectId } = useParams();
const { selectedVersionStore } = useVersionContext(); const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore(); const { selectedVersion } = selectedVersionStore();
const COST_RATES: Record<SimulationUsageRecord["type"], number> = {
roboticArm: 5,
vehicle: 2,
transfer: 1,
storageUnit: 1,
crane: 6,
human: 4,
machine: 3,
};
// Calculate totals for one product
function calculateProductMetrics(product: ProductSimulation) {
let totalActiveTime = 0;
let totalIdleTime = 0;
let totalCost = 0;
product.data.forEach((record) => {
const resourceTime = record.activeTime + record.idleTime;
const costRate = COST_RATES[record.type] || 0;
totalActiveTime += record.activeTime;
totalIdleTime += record.idleTime;
totalCost += resourceTime * costRate;
});
return {
totalTime: totalActiveTime + totalIdleTime,
totalActiveTime,
totalIdleTime,
totalCost,
};
}
// Calculate totals for a version
function calculateVersionMetrics(version: VersionSimulation) {
return version.products.reduce(
(acc, product) => {
const metrics = calculateProductMetrics(product);
acc.totalTime += metrics.totalTime;
acc.totalActiveTime += metrics.totalActiveTime;
acc.totalIdleTime += metrics.totalIdleTime;
acc.totalCost += metrics.totalCost;
return acc;
},
{ totalTime: 0, totalActiveTime: 0, totalIdleTime: 0, totalCost: 0 }
);
}
// Efficiency score (compare across versions)
function calculateEfficiencyScores(versions: VersionSimulation[]) {
const versionMetrics = versions.map((v) => ({
versionId: v.versionId,
...calculateVersionMetrics(v),
}));
const minTime = Math.min(...versionMetrics.map((m) => m.totalTime));
const minCost = Math.min(...versionMetrics.map((m) => m.totalCost));
return versionMetrics.map((m) => {
const timeFactor = minTime / m.totalTime;
const costFactor = minCost / m.totalCost;
const efficiencyScore = 0.5 * timeFactor + 0.5 * costFactor;
return { ...m, efficiencyScore };
});
}
useEffect(() => {
console.log('simulationRecords: ', simulationRecords);
if (!projectId || !selectedVersion || !selectedProduct.productUuid || simulationRecords.length === 0) return;
const project = simulationRecords[0];
if (project) {
const scores = calculateEfficiencyScores(project.versions);
console.log("Version Comparisons:", scores);
}
saveSimulationData({
key: selectedProduct.productUuid,
data: simulationRecords,
});
}, [simulationRecords]);
useEffect(() => {
const simData = getSimulationData({ key: selectedProduct.productUuid });
if (simData) {
useSimulationManager.getState().setSimulationRecords(JSON.parse(simData));
// Parse and set in the store
} else { }
}, [])
useEffect(() => { useEffect(() => {
let checkTimer: ReturnType<typeof setTimeout>; let checkTimer: ReturnType<typeof setTimeout>;
@@ -67,41 +169,43 @@ const SimulationHandler = () => {
let hasActiveEntity = false; let hasActiveEntity = false;
if (currentProduct) { if (currentProduct) {
const executionSequences = await determineExecutionMachineSequences([currentProduct]); const executionSequences = await determineExecutionMachineSequences([
currentProduct,
]);
if (executionSequences?.length > 0) { if (executionSequences?.length > 0) {
executionSequences.forEach(sequence => { executionSequences.forEach((sequence) => {
sequence.forEach(entity => { sequence.forEach((entity) => {
if (entity.type === 'roboticArm') { if (entity.type === "roboticArm") {
const roboticArm = getArmBotById(entity.modelUuid); const roboticArm = getArmBotById(entity.modelUuid);
if (roboticArm?.isActive) { if (roboticArm?.isActive) {
hasActiveEntity = true; hasActiveEntity = true;
} }
} }
if (entity.type === 'vehicle') { if (entity.type === "vehicle") {
const vehicle = getVehicleById(entity.modelUuid); const vehicle = getVehicleById(entity.modelUuid);
if (vehicle?.isActive) { if (vehicle?.isActive) {
hasActiveEntity = true; hasActiveEntity = true;
} }
} }
if (entity.type === 'machine') { if (entity.type === "machine") {
const machine = getMachineById(entity.modelUuid); const machine = getMachineById(entity.modelUuid);
if (machine?.isActive) { if (machine?.isActive) {
hasActiveEntity = true; hasActiveEntity = true;
} }
} }
if (entity.type === 'human') { if (entity.type === "human") {
const human = getHumanById(entity.modelUuid); const human = getHumanById(entity.modelUuid);
if (human?.isActive) { if (human?.isActive) {
hasActiveEntity = true; hasActiveEntity = true;
} }
} }
if (entity.type === 'crane') { if (entity.type === "crane") {
const crane = getCraneById(entity.modelUuid); const crane = getCraneById(entity.modelUuid);
if (crane?.isActive) { if (crane?.isActive) {
hasActiveEntity = true; hasActiveEntity = true;
} }
} }
if (entity.type === 'storageUnit') { if (entity.type === "storageUnit") {
const storageUnit = getStorageUnitById(entity.modelUuid); const storageUnit = getStorageUnitById(entity.modelUuid);
if (storageUnit?.isActive) { if (storageUnit?.isActive) {
hasActiveEntity = true; hasActiveEntity = true;
@@ -117,8 +221,11 @@ const SimulationHandler = () => {
}); });
} }
if (materials.length === 0 && materialHistory.length >= 0 && !hasActiveEntity) { if (
materials.length === 0 &&
materialHistory.length >= 0 &&
!hasActiveEntity
) {
if (executionSequences?.length > 0) { if (executionSequences?.length > 0) {
executionSequences.forEach((sequence) => { executionSequences.forEach((sequence) => {
sequence.forEach((entity) => { sequence.forEach((entity) => {
@@ -138,7 +245,7 @@ const SimulationHandler = () => {
const obj = getter(entity.modelUuid); const obj = getter(entity.modelUuid);
if (!obj) return; // skip if not found if (!obj) return; // skip if not found
addData( addSimulationRecord(
projectId, projectId,
selectedVersion?.versionId || "", selectedVersion?.versionId || "",
selectedProduct?.productUuid, selectedProduct?.productUuid,
@@ -154,6 +261,7 @@ const SimulationHandler = () => {
| "crane" | "crane"
| "storageUnit" | "storageUnit"
| "transfer", | "transfer",
assetId: entity.modelUuid,
} }
); );
}); });
@@ -173,9 +281,18 @@ const SimulationHandler = () => {
return () => { return () => {
if (checkTimer) clearTimeout(checkTimer); if (checkTimer) clearTimeout(checkTimer);
}; };
}, [materials, materialHistory, selectedVersion, selectedProduct?.productUuid, isPlaying, armBots, vehicles, machines]); }, [
materials,
materialHistory,
selectedVersion,
selectedProduct?.productUuid,
isPlaying,
armBots,
vehicles,
machines,
]);
return null; return null;
} };
export default SimulationHandler; export default SimulationHandler;

View File

@@ -1,19 +1,11 @@
import { create } from "zustand"; import { create } from "zustand";
interface SimulationUsageRecord { interface SimulationUsageRecord {
activeTime: number; activeTime: number;
isActive: boolean; isActive: boolean;
idleTime: number; idleTime: number;
type: type: "roboticArm" | "vehicle" | "transfer" | "storageUnit" | "crane" | "human" | "machine";
| "roboticArm" assetId: string;
| "vehicle"
| "transfer"
| "storageUnit"
| "crane"
| "human"
| "machine";
} }
// Product → holds multiple usage records // Product → holds multiple usage records
@@ -36,28 +28,22 @@ interface ProjectSimulation {
// or same file // or same file
interface SimulationManagerStore { interface SimulationManagerStore {
simulationData: ProjectSimulation[]; simulationRecords: ProjectSimulation[];
setSimulationRecords: (data: ProjectSimulation[]) => void;
addSimulationRecord: (projectId: string | undefined, versionId: string, productId: string, record: SimulationUsageRecord) => void;
addData: ( resetProductRecords: (projectId: string, versionId: string, productId: string) => void;
projectId: string | undefined, getProjectById: (projectId: string | undefined) => ProjectSimulation | undefined;
versionId: string, getVersionById: (projectId: string | undefined, versionId: string) => VersionSimulation | undefined;
productId: string, getProductById: (projectId: string | undefined, versionId: string, productId: string) => ProductSimulation | undefined;
record: SimulationUsageRecord
) => void;
resetProductData: (
projectId: string,
versionId: string,
productId: string
) => void;
} }
export const useSimulationManager = create<SimulationManagerStore>((set) => ({ export const useSimulationManager = create<SimulationManagerStore>((set, get) => ({
simulationData: [], simulationRecords: [],
addData: (projectId, versionId, productId, record) => addSimulationRecord: (projectId, versionId, productId, record) =>
set((state) => { set((state) => {
const projects = state.simulationData.map((project) => { const projects = state.simulationRecords.map((project) => {
if (project.projectId !== projectId) return project; if (project.projectId !== projectId) return project;
return { return {
@@ -67,18 +53,14 @@ export const useSimulationManager = create<SimulationManagerStore>((set) => ({
return { return {
...version, ...version,
products: version.products.map((product) => products: version.products.map((product) => (product.productId === productId ? { ...product, data: [...product.data, record] } : product)),
product.productId === productId
? { ...product, data: [...product.data, record] }
: product
),
}; };
}), }),
}; };
}); });
// If project doesn't exist, create it // If project doesn't exist, create it
if (!state.simulationData.find((p) => p.projectId === projectId)) { if (!state.simulationRecords.find((p) => p.projectId === projectId)) {
projects.push({ projects.push({
projectId, projectId,
versions: [ versions: [
@@ -96,21 +78,19 @@ export const useSimulationManager = create<SimulationManagerStore>((set) => ({
products: [{ productId, data: [record] }], products: [{ productId, data: [record] }],
}); });
} else { } else {
const version = project.versions.find( const version = project.versions.find((v) => v.versionId === versionId)!;
(v) => v.versionId === versionId
)!;
if (!version.products.find((p) => p.productId === productId)) { if (!version.products.find((p) => p.productId === productId)) {
version.products.push({ productId, data: [record] }); version.products.push({ productId, data: [record] });
} }
} }
} }
return { simulationData: projects }; return { simulationRecords: projects };
}), }),
resetProductData: (projectId, versionId, productId) => resetProductRecords: (projectId, versionId, productId) =>
set((state) => { set((state) => {
const projects = state.simulationData.map((project) => { const projects = state.simulationRecords.map((project) => {
if (project.projectId !== projectId) return project; if (project.projectId !== projectId) return project;
return { return {
@@ -120,17 +100,30 @@ export const useSimulationManager = create<SimulationManagerStore>((set) => ({
return { return {
...version, ...version,
products: version.products.map((product) => products: version.products.map((product) => (product.productId === productId ? { ...product, data: [] } : product)),
product.productId === productId
? { ...product, data: [] }
: product
),
}; };
}), }),
}; };
}); });
return { simulationData: projects }; return { simulationRecords: projects };
}), }),
setSimulationRecords: (data) => {
set({ simulationRecords: data });
},
getProjectById: (projectId: string | undefined) => {
return get().simulationRecords.find((p: ProjectSimulation) => p.projectId === projectId);
},
getVersionById: (projectId: string | undefined, versionId: string) => {
const project = get().simulationRecords.find((p: ProjectSimulation) => p.projectId === projectId);
return project?.versions.find((v: VersionSimulation) => v.versionId === versionId);
},
getProductById: (projectId: string | undefined, versionId: string, productId: string) => {
const project = get().simulationRecords.find((p: ProjectSimulation) => p.projectId === projectId);
const version = project?.versions.find((v: VersionSimulation) => v.versionId === versionId);
return version?.products.find((p: ProductSimulation) => p.productId === productId);
},
})); }));
/////////////////////////// ///////////////////////////

View File

@@ -305,7 +305,7 @@
background-color: #b7b7c6; background-color: #b7b7c6;
// Custom polygon shape (adjust if needed) // Custom polygon shape (adjust if needed)
clipPath: polygon(96% 52%, clip-path: polygon(96% 52%,
96% 54%, 96% 54%,
45% 53%, 45% 53%,
3% 100%, 3% 100%,