Merge remote-tracking branch 'origin/feature/layout-comparison-version' into dev-heatmap
This commit is contained in:
@@ -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) => {};
|
||||||
@@ -17,6 +17,7 @@ import { useCompareStore, useIsComparing } from "../../../../store/builder/store
|
|||||||
import { useToggleStore } from "../../../../store/ui/useUIToggleStore";
|
import { useToggleStore } from "../../../../store/ui/useUIToggleStore";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { useSceneContext } from "../../../../modules/scene/sceneContext";
|
import { useSceneContext } from "../../../../modules/scene/sceneContext";
|
||||||
|
import { getSimulationData } from "../../scenes/functions/simulationStorage";
|
||||||
|
|
||||||
interface Event {
|
interface Event {
|
||||||
modelName: string;
|
modelName: string;
|
||||||
@@ -124,6 +125,12 @@ const Simulations: React.FC = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [selectedProduct.productUuid, products]);
|
}, [selectedProduct.productUuid, products]);
|
||||||
|
//call when comparePopup is true
|
||||||
|
useEffect(() => {
|
||||||
|
if (comparePopUp || selectedProduct.productUuid) {
|
||||||
|
getSimulationData({ key: selectedProduct.productUuid });
|
||||||
|
}
|
||||||
|
}, [comparePopUp])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="simulations-container">
|
<div className="simulations-container">
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useRef, useEffect } from "react";
|
import React, { useState, useRef, useEffect } from "react";
|
||||||
import { ExitIcon, PlayStopIcon, ResetIcon } from "../../icons/SimulationIcons";
|
import { ExitIcon, PlayStopIcon, ResetIcon } from "../../icons/SimulationIcons";
|
||||||
import {
|
import {
|
||||||
|
comparsionMaterialData,
|
||||||
useActiveTool,
|
useActiveTool,
|
||||||
useProcessBar,
|
useProcessBar,
|
||||||
useViewSceneStore,
|
useViewSceneStore,
|
||||||
@@ -32,6 +33,8 @@ import ROISummary from "../analysis/ROISummary";
|
|||||||
import { usePlayerStore } from "../../../store/ui/useUIToggleStore";
|
import { usePlayerStore } from "../../../store/ui/useUIToggleStore";
|
||||||
import { useComparisonProduct } from "../../../store/simulation/useSimulationStore";
|
import { useComparisonProduct } from "../../../store/simulation/useSimulationStore";
|
||||||
import InputToggle from "../inputs/InputToggle";
|
import InputToggle from "../inputs/InputToggle";
|
||||||
|
import { saveSimulationData } from "../../layout/scenes/functions/simulationStorage";
|
||||||
|
import { useSceneContext } from "../../../modules/scene/sceneContext";
|
||||||
|
|
||||||
const SimulationPlayer: React.FC = () => {
|
const SimulationPlayer: React.FC = () => {
|
||||||
const MAX_SPEED = 8; // Maximum speed
|
const MAX_SPEED = 8; // Maximum speed
|
||||||
@@ -49,9 +52,11 @@ const SimulationPlayer: React.FC = () => {
|
|||||||
const { subModule } = useSubModuleStore();
|
const { subModule } = useSubModuleStore();
|
||||||
const { clearComparisonProduct } = useComparisonProduct();
|
const { clearComparisonProduct } = useComparisonProduct();
|
||||||
const { viewSceneLabels, setViewSceneLabels } = useViewSceneStore();
|
const { viewSceneLabels, setViewSceneLabels } = useViewSceneStore();
|
||||||
|
const { materialData, setMaterialData } = comparsionMaterialData()
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
|
const { productStore } = useSceneContext();
|
||||||
|
const { selectedProduct, setSelectedProduct } = productStore();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isReset) {
|
if (isReset) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -60,6 +65,12 @@ const SimulationPlayer: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}, [isReset, setReset]);
|
}, [isReset, setReset]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (materialData.length === 0) return;
|
||||||
|
console.log('materialData: ', materialData);
|
||||||
|
saveSimulationData({ key: selectedProduct.productUuid, data: materialData });
|
||||||
|
}, [materialData])
|
||||||
|
|
||||||
// Button functions
|
// Button functions
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
setReset(true);
|
setReset(true);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { EffectComposer, N8AO } from "@react-three/postprocessing";
|
import { DepthOfField, Bloom, EffectComposer, N8AO } from "@react-three/postprocessing";
|
||||||
|
// import OutlineInstances from "./outlineInstances/outlineInstances";
|
||||||
import OutlineInstances from "./outlineInstances/outlineInstances";
|
import OutlineInstances from "./outlineInstances/outlineInstances";
|
||||||
import { useDeletableEventSphere, useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";
|
import { useDeletableEventSphere, useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { useEffect } from "react";
|
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/ui/usePlayButtonStore";
|
import { useSceneContext } from '../../../scene/sceneContext';
|
||||||
import { useSceneContext } from "../../../scene/sceneContext";
|
import { saveSimulationData } from '../../../../components/layout/scenes/functions/simulationStorage';
|
||||||
|
import { set } from 'immer/dist/internal';
|
||||||
|
import { usePlayButtonStore } from '../../../../store/ui/usePlayButtonStore';
|
||||||
|
|
||||||
export default function ROIData() {
|
export default function ROIData() {
|
||||||
const { inputValues } = useInputValues();
|
const { inputValues } = useInputValues();
|
||||||
@@ -13,7 +15,8 @@ export default function ROIData() {
|
|||||||
const { compareProductsData, setCompareProductsData } = useCompareProductDataStore();
|
const { compareProductsData, setCompareProductsData } = useCompareProductDataStore();
|
||||||
const { machineActiveTime } = useMachineUptime();
|
const { machineActiveTime } = useMachineUptime();
|
||||||
const { machineIdleTime } = useMachineDowntime();
|
const { machineIdleTime } = useMachineDowntime();
|
||||||
const { throughputData } = useThroughPutData();
|
const { throughputData } = useThroughPutData()
|
||||||
|
const { materialData, setMaterialData } = comparsionMaterialData()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isPlaying) return;
|
if (isPlaying) return;
|
||||||
@@ -129,6 +132,22 @@ export default function ROIData() {
|
|||||||
|
|
||||||
const Annual_net_profit = Annual_units * (sellingPrice - materialCost - laborCost) - (maintenanceCost + electricityCost + fixedCost) * workingDaysPerYear + salvageValue * workingDaysPerYear;
|
const Annual_net_profit = Annual_units * (sellingPrice - materialCost - laborCost) - (maintenanceCost + electricityCost + fixedCost) * workingDaysPerYear + salvageValue * workingDaysPerYear;
|
||||||
const Payback_period_years = initialInvestment / Annual_net_profit;
|
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({
|
setRoiSummaryData({
|
||||||
productName: selectedProduct.productName,
|
productName: selectedProduct.productName,
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
import { useEffect } from "react";
|
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/ui/usePlayButtonStore";
|
|
||||||
|
import { saveSimulationData } from '../../../../components/layout/scenes/functions/simulationStorage';
|
||||||
|
import { usePlayButtonStore } from '../../../../store/ui/usePlayButtonStore';
|
||||||
|
|
||||||
export default function ProductionCapacityData() {
|
export default function ProductionCapacityData() {
|
||||||
const { throughputData } = useThroughPutData();
|
const { throughputData } = useThroughPutData();
|
||||||
const { setProductionCapacityData } = useProductionCapacityData();
|
const { setProductionCapacityData } = useProductionCapacityData();
|
||||||
const { inputValues } = useInputValues();
|
const { inputValues } = useInputValues();
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
|
const { materialData, setMaterialData } = comparsionMaterialData()
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) {
|
if (!isPlaying) {
|
||||||
@@ -21,10 +25,12 @@ export default function ProductionCapacityData() {
|
|||||||
if (!isNaN(workingDaysPerYear) && throughputData > 0) {
|
if (!isNaN(workingDaysPerYear) && throughputData > 0) {
|
||||||
const Monthly_working_days = workingDaysPerYear / 12;
|
const Monthly_working_days = workingDaysPerYear / 12;
|
||||||
const Production_capacity_per_month = throughputData * Monthly_working_days;
|
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)));
|
setProductionCapacityData(Number(Production_capacity_per_month.toFixed(2)));
|
||||||
}
|
}
|
||||||
}, [throughputData, inputValues, isPlaying]);
|
}, [throughputData, inputValues, isPlaying, materialData]);
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from 'react';
|
||||||
import { determineExecutionMachineSequences } from "../../simulator/functions/determineExecutionMachineSequences";
|
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/ui/usePlayButtonStore";
|
import { useSceneContext } from '../../../scene/sceneContext';
|
||||||
import { useSceneContext } from "../../../scene/sceneContext";
|
import { saveSimulationData } from '../../../../components/layout/scenes/functions/simulationStorage';
|
||||||
|
import { usePlayButtonStore } from '../../../../store/ui/usePlayButtonStore';
|
||||||
|
|
||||||
export default function ThroughPutData() {
|
export default function ThroughPutData() {
|
||||||
const { materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, productStore } = useSceneContext();
|
const { materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, productStore } = useSceneContext();
|
||||||
@@ -21,6 +22,7 @@ export default function ThroughPutData() {
|
|||||||
const { setThroughputData } = useThroughPutData();
|
const { setThroughputData } = useThroughPutData();
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
const { inputValues } = useInputValues();
|
const { inputValues } = useInputValues();
|
||||||
|
const { materialData, setMaterialData } = comparsionMaterialData()
|
||||||
|
|
||||||
// Setting machine count
|
// Setting machine count
|
||||||
let totalItems = 0;
|
let totalItems = 0;
|
||||||
@@ -218,9 +220,13 @@ export default function ThroughPutData() {
|
|||||||
const Units_per_shift = (shiftLength * 60) / (materialCycleTime / 60);
|
const Units_per_shift = (shiftLength * 60) / (materialCycleTime / 60);
|
||||||
|
|
||||||
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))
|
||||||
|
saveSimulationData({ key: selectedProduct.productUuid, data: data });
|
||||||
|
|
||||||
|
setMaterialData({ ...materialData, throughput: data });
|
||||||
setThroughputData(Number(Throughput_per_day.toFixed(2))); // Keep as number
|
setThroughputData(Number(Throughput_per_day.toFixed(2))); // Keep as number
|
||||||
}
|
}
|
||||||
}, [materialCycleTime, machineCount, isPlaying, inputValues]);
|
}, [materialCycleTime, machineCount, isPlaying, inputValues, materialData]);
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|||||||
177
app/src/modules/simulation/simulator/SimulationHandler.tsx
Normal file
177
app/src/modules/simulation/simulator/SimulationHandler.tsx
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import { useSceneContext } from '../../scene/sceneContext';
|
||||||
|
import { determineExecutionMachineSequences } from './functions/determineExecutionMachineSequences';
|
||||||
|
import { usePlayButtonStore } from '../../../store/ui/usePlayButtonStore';
|
||||||
|
import { useSimulationManager } from '../../../store/rough/useSimulationManagerStore';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
|
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, versionStore } = useSceneContext();
|
||||||
|
const { armBots, getArmBotById } = armBotStore();
|
||||||
|
const { vehicles, getVehicleById } = vehicleStore();
|
||||||
|
const { getConveyorById } = conveyorStore();
|
||||||
|
const { materialHistory, materials } = materialStore();
|
||||||
|
const { getProductById, selectedProduct } = productStore();
|
||||||
|
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 { selectedVersion } = versionStore();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
@@ -3,6 +3,7 @@ import { useActionHandler } from "../actions/useActionHandler";
|
|||||||
import { usePlayButtonStore, useResetButtonStore } from "../../../store/ui/usePlayButtonStore";
|
import { usePlayButtonStore, useResetButtonStore } from "../../../store/ui/usePlayButtonStore";
|
||||||
import { determineExecutionOrder } from "./functions/determineExecutionOrder";
|
import { determineExecutionOrder } from "./functions/determineExecutionOrder";
|
||||||
import { useSceneContext } from "../../scene/sceneContext";
|
import { useSceneContext } from "../../scene/sceneContext";
|
||||||
|
import SimulationHandler from "./SimulationHandler";
|
||||||
|
|
||||||
function Simulator() {
|
function Simulator() {
|
||||||
const { productStore } = useSceneContext();
|
const { productStore } = useSceneContext();
|
||||||
@@ -24,7 +25,17 @@ function Simulator() {
|
|||||||
});
|
});
|
||||||
}, [products, isPlaying, isReset, selectedProduct]);
|
}, [products, isPlaying, isReset, selectedProduct]);
|
||||||
|
|
||||||
return <></>;
|
|
||||||
|
return (
|
||||||
|
|
||||||
|
<>
|
||||||
|
|
||||||
|
{/* <simulationHandler/> */}
|
||||||
|
<SimulationHandler />
|
||||||
|
|
||||||
|
</>
|
||||||
|
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Simulator;
|
export default Simulator;
|
||||||
|
|||||||
@@ -2,50 +2,56 @@ import { create } from "zustand";
|
|||||||
import { io } from "socket.io-client";
|
import { io } from "socket.io-client";
|
||||||
import * as CONSTANTS from "../../types/world/worldConstants";
|
import * as CONSTANTS from "../../types/world/worldConstants";
|
||||||
|
|
||||||
type SocketStore = {
|
export const useSocketStore = create<any>((set: any, get: any) => ({
|
||||||
socket: ReturnType<typeof io> | null;
|
|
||||||
visualizationSocket?: ReturnType<typeof io> | null;
|
|
||||||
dashBoardSocket?: ReturnType<typeof io> | null;
|
|
||||||
projectSocket?: ReturnType<typeof io> | null;
|
|
||||||
threadSocket?: ReturnType<typeof io> | null;
|
|
||||||
initializeSocket: (email?: string, organization?: string, token?: string, refreshToken?: string) => void;
|
|
||||||
disconnectSocket: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useSocketStore = create<SocketStore>((set, get) => ({
|
|
||||||
socket: null,
|
socket: null,
|
||||||
visualizationSocket: null,
|
initializeSocket: (
|
||||||
dashBoardSocket: null,
|
email?: string,
|
||||||
projectSocket: null,
|
organization?: string,
|
||||||
threadSocket: null,
|
token?: string,
|
||||||
initializeSocket: (email?: string, organization?: string, token?: string, refreshToken?: string) => {
|
refreshToken?: string
|
||||||
|
) => {
|
||||||
const existingSocket = get().socket;
|
const existingSocket = get().socket;
|
||||||
if (existingSocket) {
|
if (existingSocket) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const socket = io(`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder_v1`, {
|
const socket = io(
|
||||||
|
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder_v1`,
|
||||||
|
{
|
||||||
reconnection: true,
|
reconnection: true,
|
||||||
auth: { token, refreshToken },
|
auth: { token, refreshToken },
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const visualizationSocket = io(`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization_v1`, {
|
const visualizationSocket = io(
|
||||||
|
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization_v1`,
|
||||||
|
{
|
||||||
reconnection: true,
|
reconnection: true,
|
||||||
auth: { token, refreshToken },
|
auth: { token, refreshToken },
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const dashBoardSocket = io(`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/dashboard`, {
|
const dashBoardSocket = io(
|
||||||
|
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/dashboard`,
|
||||||
|
{
|
||||||
reconnection: true,
|
reconnection: true,
|
||||||
auth: { token, refreshToken },
|
auth: { token, refreshToken },
|
||||||
});
|
}
|
||||||
const projectSocket = io(`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/project`, {
|
);
|
||||||
|
const projectSocket = io(
|
||||||
|
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/project`,
|
||||||
|
{
|
||||||
reconnection: true,
|
reconnection: true,
|
||||||
auth: { token, refreshToken },
|
auth: { token, refreshToken },
|
||||||
});
|
}
|
||||||
const threadSocket = io(`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/thread`, {
|
);
|
||||||
|
const threadSocket = io(
|
||||||
|
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/thread`,
|
||||||
|
{
|
||||||
reconnection: true,
|
reconnection: true,
|
||||||
auth: { token, refreshToken },
|
auth: { token, refreshToken },
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
set({
|
set({
|
||||||
socket,
|
socket,
|
||||||
@@ -56,19 +62,13 @@ export const useSocketStore = create<SocketStore>((set, get) => ({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
disconnectSocket: () => {
|
disconnectSocket: () => {
|
||||||
set((state) => {
|
set((state: any) => {
|
||||||
state.socket?.disconnect();
|
state.socket?.disconnect();
|
||||||
state.visualizationSocket?.disconnect();
|
state.visualizationSocket?.disconnect();
|
||||||
state.dashBoardSocket?.disconnect();
|
state.dashBoardSocket?.disconnect();
|
||||||
state.projectSocket?.disconnect();
|
state.projectSocket?.disconnect();
|
||||||
state.threadSocket?.disconnect();
|
state.threadSocket?.disconnect();
|
||||||
return {
|
return { socket: null };
|
||||||
socket: null,
|
|
||||||
visualizationSocket: null,
|
|
||||||
dashBoardSocket: null,
|
|
||||||
projectSocket: null,
|
|
||||||
threadSocket: null,
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
@@ -81,6 +81,11 @@ export const useLoadingProgress = create<{
|
|||||||
setLoadingProgress: (x: number) => set({ loadingProgress: x }),
|
setLoadingProgress: (x: number) => set({ loadingProgress: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
export const useOrganization = create<any>((set: any) => ({
|
||||||
|
organization: "",
|
||||||
|
setOrganization: (x: any) => set(() => ({ organization: x })),
|
||||||
|
}));
|
||||||
|
|
||||||
export const useToggleView = create<any>((set: any) => ({
|
export const useToggleView = create<any>((set: any) => ({
|
||||||
toggleView: false,
|
toggleView: false,
|
||||||
setToggleView: (x: any) => set(() => ({ toggleView: x })),
|
setToggleView: (x: any) => set(() => ({ toggleView: x })),
|
||||||
@@ -102,16 +107,51 @@ export const useSelectedItem = create<any>((set: any) => ({
|
|||||||
setSelectedItem: (x: any) => set(() => ({ selectedItem: x })),
|
setSelectedItem: (x: any) => set(() => ({ selectedItem: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
type DroppedDecalType = {
|
||||||
|
category: string;
|
||||||
|
decalName: string;
|
||||||
|
decalImage: string;
|
||||||
|
decalId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useDroppedDecal = create<{
|
||||||
|
droppedDecal: DroppedDecalType | null;
|
||||||
|
setDroppedDecal: (x: DroppedDecalType | null) => void;
|
||||||
|
}>((set) => ({
|
||||||
|
droppedDecal: null,
|
||||||
|
setDroppedDecal: (x) => set({ droppedDecal: x }),
|
||||||
|
}));
|
||||||
|
|
||||||
export const useNavMesh = create<any>((set: any) => ({
|
export const useNavMesh = create<any>((set: any) => ({
|
||||||
navMesh: null,
|
navMesh: null,
|
||||||
setNavMesh: (x: any) => set({ navMesh: x }),
|
setNavMesh: (x: any) => set({ navMesh: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
export const useLayers = create<any>((set: any) => ({
|
||||||
|
Layers: 1,
|
||||||
|
setLayers: (x: any) => set(() => ({ Layers: x })),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const useCamPosition = create<any>((set: any) => ({
|
||||||
|
camPosition: { x: undefined, y: undefined, z: undefined },
|
||||||
|
setCamPosition: (newCamPosition: any) => set({ camPosition: newCamPosition }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const useMenuVisible = create<any>((set: any) => ({
|
||||||
|
menuVisible: false,
|
||||||
|
setMenuVisible: (x: any) => set(() => ({ menuVisible: x })),
|
||||||
|
}));
|
||||||
|
|
||||||
export const useToolMode = create<any>((set: any) => ({
|
export const useToolMode = create<any>((set: any) => ({
|
||||||
toolMode: null,
|
toolMode: null,
|
||||||
setToolMode: (x: any) => set(() => ({ toolMode: x })),
|
setToolMode: (x: any) => set(() => ({ toolMode: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
export const useSetScale = create<any>((set: any) => ({
|
||||||
|
scale: null,
|
||||||
|
setScale: (x: any) => set(() => ({ scale: x })),
|
||||||
|
}));
|
||||||
|
|
||||||
export const useRoofVisibility = create<any>((set: any) => ({
|
export const useRoofVisibility = create<any>((set: any) => ({
|
||||||
roofVisibility: false,
|
roofVisibility: false,
|
||||||
setRoofVisibility: (x: any) => set(() => ({ roofVisibility: x })),
|
setRoofVisibility: (x: any) => set(() => ({ roofVisibility: x })),
|
||||||
@@ -129,7 +169,18 @@ export const useShadows = create<any>((set: any) => ({
|
|||||||
|
|
||||||
export const useSunPosition = create<any>((set: any) => ({
|
export const useSunPosition = create<any>((set: any) => ({
|
||||||
sunPosition: { x: undefined, y: undefined, z: undefined },
|
sunPosition: { x: undefined, y: undefined, z: undefined },
|
||||||
setSunPosition: (newSuntPosition: any) => set({ sunPosition: newSuntPosition }),
|
setSunPosition: (newSuntPosition: any) =>
|
||||||
|
set({ sunPosition: newSuntPosition }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const useRemoveLayer = create<any>((set: any) => ({
|
||||||
|
removeLayer: false,
|
||||||
|
setRemoveLayer: (x: any) => set(() => ({ removeLayer: x })),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const useRemovedLayer = create<any>((set: any) => ({
|
||||||
|
removedLayer: null,
|
||||||
|
setRemovedLayer: (x: any) => set(() => ({ removedLayer: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useProjectName = create<any>((set: any) => ({
|
export const useProjectName = create<any>((set: any) => ({
|
||||||
@@ -285,6 +336,12 @@ export const useTileDistance = create<any>((set: any) => ({
|
|||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
export const usePlayAgv = create<any>((set, get) => ({
|
||||||
|
PlayAgv: [],
|
||||||
|
setPlayAgv: (updateFn: (prev: any[]) => any[]) =>
|
||||||
|
set({ PlayAgv: updateFn(get().PlayAgv) }),
|
||||||
|
}));
|
||||||
|
|
||||||
// Define the Asset type
|
// Define the Asset type
|
||||||
type Asset = {
|
type Asset = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -310,10 +367,12 @@ interface ResourceManagementState {
|
|||||||
setResourceManagementId: (id: string) => void;
|
setResourceManagementId: (id: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useResourceManagementId = create<ResourceManagementState>((set) => ({
|
export const useResourceManagementId = create<ResourceManagementState>(
|
||||||
|
(set) => ({
|
||||||
resourceManagementId: "", // default value
|
resourceManagementId: "", // default value
|
||||||
setResourceManagementId: (id: string) => set({ resourceManagementId: id }),
|
setResourceManagementId: (id: string) => set({ resourceManagementId: id }),
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
|
|
||||||
// version visible hidden
|
// version visible hidden
|
||||||
interface VersionHistoryState {
|
interface VersionHistoryState {
|
||||||
@@ -526,3 +585,20 @@ export const useContextActionStore = create<any>((set: any) => ({
|
|||||||
contextAction: null,
|
contextAction: null,
|
||||||
setContextAction: (x: any) => set({ contextAction: x }),
|
setContextAction: (x: any) => set({ contextAction: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Define the store's state and actions type
|
||||||
|
interface DecalStore {
|
||||||
|
selectedSubCategory: string | null;
|
||||||
|
setSelectedSubCategory: (subCategory: string | null) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the Zustand store with types
|
||||||
|
export const useDecalStore = create<DecalStore>((set) => ({
|
||||||
|
selectedSubCategory: "Safety",
|
||||||
|
setSelectedSubCategory: (subCategory: string | null) =>
|
||||||
|
set({ selectedSubCategory: subCategory }),
|
||||||
|
}));
|
||||||
|
export const comparsionMaterialData = create<any>((set: any) => ({
|
||||||
|
materialData: [],
|
||||||
|
setMaterialData: (x: any) => set({ materialData: x }),
|
||||||
|
}));
|
||||||
|
|||||||
136
app/src/store/rough/useSimulationManagerStore.ts
Normal file
136
app/src/store/rough/useSimulationManagerStore.ts
Normal 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 };
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
///////////////////////////
|
||||||
Reference in New Issue
Block a user