feat: Add simulation analyzer component with comprehensive tracking and performance metrics.
This commit is contained in:
@@ -1,10 +1,13 @@
|
|||||||
import { useEffect, useCallback, useRef } from "react";
|
import { useEffect, useCallback, useRef } from "react";
|
||||||
import { useSceneContext } from "../../scene/sceneContext";
|
import { useSceneContext } from "../../scene/sceneContext";
|
||||||
import { useAnimationPlaySpeed, usePlayButtonStore } from "../../../store/ui/usePlayButtonStore";
|
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from "../../../store/ui/usePlayButtonStore";
|
||||||
|
|
||||||
function Analyzer() {
|
function Analyzer() {
|
||||||
|
const { isPaused } = usePauseButtonStore();
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
const { conveyorStore, machineStore, armBotStore, humanStore, vehicleStore, craneStore, storageUnitStore, materialStore, analysisStore, humanEventManagerRef } = useSceneContext();
|
const { speed } = useAnimationPlaySpeed();
|
||||||
|
const { conveyorStore, machineStore, armBotStore, humanStore, vehicleStore, craneStore, storageUnitStore, materialStore, analysisStore, humanEventManagerRef, getSimulationTime } =
|
||||||
|
useSceneContext();
|
||||||
|
|
||||||
const { conveyors } = conveyorStore();
|
const { conveyors } = conveyorStore();
|
||||||
const { machines } = machineStore();
|
const { machines } = machineStore();
|
||||||
@@ -14,10 +17,8 @@ function Analyzer() {
|
|||||||
const { cranes } = craneStore();
|
const { cranes } = craneStore();
|
||||||
const { storageUnits } = storageUnitStore();
|
const { storageUnits } = storageUnitStore();
|
||||||
const { materials, materialHistory, getMaterialsByModel } = materialStore();
|
const { materials, materialHistory, getMaterialsByModel } = materialStore();
|
||||||
const { speed } = useAnimationPlaySpeed();
|
|
||||||
|
|
||||||
const { setAnalysis, setAnalyzing, analysis } = analysisStore();
|
const { setAnalysis, setAnalyzing, analysis } = analysisStore();
|
||||||
const { getSimulationTime } = useSceneContext();
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// COMPREHENSIVE TRACKING REFS FOR PERFORMANCE METRICS
|
// COMPREHENSIVE TRACKING REFS FOR PERFORMANCE METRICS
|
||||||
@@ -2277,15 +2278,15 @@ function Analyzer() {
|
|||||||
|
|
||||||
// Trigger analysis when assets or materials change
|
// Trigger analysis when assets or materials change
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) return;
|
if (!isPlaying || isPaused) return;
|
||||||
|
|
||||||
// Perform analysis when any asset or material state changes
|
// Perform analysis when any asset or material state changes
|
||||||
performAnalysisRef.current();
|
performAnalysisRef.current();
|
||||||
}, [conveyors, vehicles, armBots, machines, humans, cranes, materials, isPlaying]);
|
}, [conveyors, vehicles, armBots, machines, humans, cranes, materials, isPlaying, isPaused]);
|
||||||
|
|
||||||
// Perform initial analysis and set up interval
|
// Perform initial analysis and set up interval
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) return;
|
if (!isPlaying || isPaused) return;
|
||||||
|
|
||||||
// Set up periodic analysis (every 1 second)
|
// Set up periodic analysis (every 1 second)
|
||||||
analysisIntervalRef.current = setInterval(() => {
|
analysisIntervalRef.current = setInterval(() => {
|
||||||
@@ -2297,11 +2298,11 @@ function Analyzer() {
|
|||||||
clearInterval(analysisIntervalRef.current);
|
clearInterval(analysisIntervalRef.current);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [isPlaying]);
|
}, [isPlaying, isPaused]);
|
||||||
|
|
||||||
// Monitor material changes and track additions/removals
|
// Monitor material changes and track additions/removals
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) return;
|
if (!isPlaying || isPaused) return;
|
||||||
|
|
||||||
// Track material movements by comparing current materials with previous state
|
// Track material movements by comparing current materials with previous state
|
||||||
materials.forEach((material) => {
|
materials.forEach((material) => {
|
||||||
@@ -2341,11 +2342,11 @@ function Analyzer() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [materials, isPlaying, trackMaterialAddition, trackMaterialRemoval]);
|
}, [materials, isPlaying, isPaused, trackMaterialAddition, trackMaterialRemoval]);
|
||||||
|
|
||||||
// Monitor asset state changes
|
// Monitor asset state changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) return;
|
if (!isPlaying || isPaused) return;
|
||||||
|
|
||||||
const allAssets = [
|
const allAssets = [
|
||||||
...conveyors.map((c) => ({ id: c.modelUuid, state: c.state, isActive: !c.isPaused, type: "conveyor" as const })),
|
...conveyors.map((c) => ({ id: c.modelUuid, state: c.state, isActive: !c.isPaused, type: "conveyor" as const })),
|
||||||
@@ -2378,11 +2379,11 @@ function Analyzer() {
|
|||||||
// Update previous state
|
// Update previous state
|
||||||
updatePreviousAssetState(asset.id, asset.state, asset.isActive, currentMaterialCount);
|
updatePreviousAssetState(asset.id, asset.state, asset.isActive, currentMaterialCount);
|
||||||
});
|
});
|
||||||
}, [conveyors, machines, armBots, vehicles, humans, cranes, storageUnits, isPlaying, getMaterialsByModel, trackStateChange, trackBottleneckEvent, updatePreviousAssetState]);
|
}, [conveyors, machines, armBots, vehicles, humans, cranes, storageUnits, isPlaying, isPaused, getMaterialsByModel, trackStateChange, trackBottleneckEvent, updatePreviousAssetState]);
|
||||||
|
|
||||||
// Monitor ArmBot action changes to track cycles
|
// Monitor ArmBot action changes to track cycles
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) return;
|
if (!isPlaying || isPaused) return;
|
||||||
|
|
||||||
armBots.forEach((armBot) => {
|
armBots.forEach((armBot) => {
|
||||||
const previousActionUuid = previousArmBotActionsRef.current[armBot.modelUuid];
|
const previousActionUuid = previousArmBotActionsRef.current[armBot.modelUuid];
|
||||||
@@ -2423,11 +2424,11 @@ function Analyzer() {
|
|||||||
|
|
||||||
previousArmBotActionsRef.current[armBot.modelUuid] = currentActionUuid;
|
previousArmBotActionsRef.current[armBot.modelUuid] = currentActionUuid;
|
||||||
});
|
});
|
||||||
}, [armBots, isPlaying]);
|
}, [armBots, isPlaying, isPaused]);
|
||||||
|
|
||||||
// Monitor Machine action changes to track cycles
|
// Monitor Machine action changes to track cycles
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) return;
|
if (!isPlaying || isPaused) return;
|
||||||
|
|
||||||
machines.forEach((machine) => {
|
machines.forEach((machine) => {
|
||||||
const previousActionUuid = previousMachineActionsRef.current[machine.modelUuid];
|
const previousActionUuid = previousMachineActionsRef.current[machine.modelUuid];
|
||||||
@@ -2450,11 +2451,11 @@ function Analyzer() {
|
|||||||
|
|
||||||
previousMachineActionsRef.current[machine.modelUuid] = currentActionUuid;
|
previousMachineActionsRef.current[machine.modelUuid] = currentActionUuid;
|
||||||
});
|
});
|
||||||
}, [machines, isPlaying]);
|
}, [machines, isPlaying, isPaused]);
|
||||||
|
|
||||||
// Monitor Storage load changes to track store/retrieve operations
|
// Monitor Storage load changes to track store/retrieve operations
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) return;
|
if (!isPlaying || isPaused) return;
|
||||||
|
|
||||||
storageUnits.forEach((storage) => {
|
storageUnits.forEach((storage) => {
|
||||||
const previousLoad = previousStorageLoadsRef.current[storage.modelUuid] || 0;
|
const previousLoad = previousStorageLoadsRef.current[storage.modelUuid] || 0;
|
||||||
@@ -2478,11 +2479,11 @@ function Analyzer() {
|
|||||||
|
|
||||||
previousStorageLoadsRef.current[storage.modelUuid] = currentLoad;
|
previousStorageLoadsRef.current[storage.modelUuid] = currentLoad;
|
||||||
});
|
});
|
||||||
}, [storageUnits, isPlaying]);
|
}, [storageUnits, isPlaying, isPaused]);
|
||||||
|
|
||||||
// Monitor Human action changes from EventManager
|
// Monitor Human action changes from EventManager
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying || !humanEventManagerRef.current) return;
|
if (!isPlaying || isPaused || !humanEventManagerRef.current) return;
|
||||||
|
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
if (!humanEventManagerRef.current) return;
|
if (!humanEventManagerRef.current) return;
|
||||||
@@ -2525,11 +2526,11 @@ function Analyzer() {
|
|||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
}, [isPlaying, humanEventManagerRef]);
|
}, [isPlaying, isPaused, humanEventManagerRef]);
|
||||||
|
|
||||||
// Periodic WIP and throughput snapshots
|
// Periodic WIP and throughput snapshots
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) return;
|
if (!isPlaying || isPaused) return;
|
||||||
|
|
||||||
const snapshotInterval = setInterval(() => {
|
const snapshotInterval = setInterval(() => {
|
||||||
const allAssetIds = [
|
const allAssetIds = [
|
||||||
@@ -2548,11 +2549,11 @@ function Analyzer() {
|
|||||||
}, 1000); // Every 1 seconds
|
}, 1000); // Every 1 seconds
|
||||||
|
|
||||||
return () => clearInterval(snapshotInterval);
|
return () => clearInterval(snapshotInterval);
|
||||||
}, [conveyors, machines, armBots, vehicles, humans, cranes, storageUnits, isPlaying, updateWIPSnapshot]);
|
}, [conveyors, machines, armBots, vehicles, humans, cranes, storageUnits, isPlaying, isPaused, updateWIPSnapshot]);
|
||||||
|
|
||||||
// Monitor Vehicle phase changes to track completed trips
|
// Monitor Vehicle phase changes to track completed trips
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) return;
|
if (!isPlaying || isPaused) return;
|
||||||
|
|
||||||
vehicles.forEach((vehicle) => {
|
vehicles.forEach((vehicle) => {
|
||||||
const previousPhase = previousVehiclePhasesRef.current[vehicle.modelUuid];
|
const previousPhase = previousVehiclePhasesRef.current[vehicle.modelUuid];
|
||||||
@@ -2574,11 +2575,11 @@ function Analyzer() {
|
|||||||
|
|
||||||
previousVehiclePhasesRef.current[vehicle.modelUuid] = currentPhase;
|
previousVehiclePhasesRef.current[vehicle.modelUuid] = currentPhase;
|
||||||
});
|
});
|
||||||
}, [vehicles, isPlaying]);
|
}, [vehicles, isPlaying, isPaused]);
|
||||||
|
|
||||||
// Monitor Crane phase changes to track completed cycles, loads, and lifts
|
// Monitor Crane phase changes to track completed cycles, loads, and lifts
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) return;
|
if (!isPlaying || isPaused) return;
|
||||||
|
|
||||||
cranes.forEach((crane) => {
|
cranes.forEach((crane) => {
|
||||||
const previousPhase = previousCranePhasesRef.current[crane.modelUuid];
|
const previousPhase = previousCranePhasesRef.current[crane.modelUuid];
|
||||||
@@ -2616,7 +2617,7 @@ function Analyzer() {
|
|||||||
|
|
||||||
previousCranePhasesRef.current[crane.modelUuid] = currentPhase;
|
previousCranePhasesRef.current[crane.modelUuid] = currentPhase;
|
||||||
});
|
});
|
||||||
}, [cranes, isPlaying]);
|
}, [cranes, isPlaying, isPaused]);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user