diff --git a/app/src/modules/simulation/analyzer/analyzer.tsx b/app/src/modules/simulation/analyzer/analyzer.tsx index ad86449..e45d64a 100644 --- a/app/src/modules/simulation/analyzer/analyzer.tsx +++ b/app/src/modules/simulation/analyzer/analyzer.tsx @@ -4,7 +4,7 @@ import { useAnimationPlaySpeed, usePlayButtonStore } from "../../../store/ui/use function Analyzer() { const { isPlaying } = usePlayButtonStore(); - const { conveyorStore, machineStore, armBotStore, humanStore, vehicleStore, craneStore, storageUnitStore, materialStore, analysisStore } = useSceneContext(); + const { conveyorStore, machineStore, armBotStore, humanStore, vehicleStore, craneStore, storageUnitStore, materialStore, analysisStore, humanEventManagerRef } = useSceneContext(); const { conveyors } = conveyorStore(); const { machines } = machineStore(); @@ -187,6 +187,9 @@ function Analyzer() { // Track previous actions for ArmBots to detect cycle completion const previousArmBotActionsRef = useRef>({}); + // Track previous action counts for Humans to detect completion from EventManager + const previousHumanCountsRef = useRef>>({}); + // Material lifecycle tracking const materialLifecycleRef = useRef< Record< @@ -219,6 +222,7 @@ function Analyzer() { bottleneckEventsRef.current = {}; previousAssetStatesRef.current = {}; previousArmBotActionsRef.current = {}; + previousHumanCountsRef.current = {}; materialLifecycleRef.current = {}; setAnalysis(null); setAnalyzing(false); @@ -2380,6 +2384,53 @@ function Analyzer() { }); }, [armBots, isPlaying]); + // Monitor Human action changes from EventManager + useEffect(() => { + if (!isPlaying || !humanEventManagerRef.current) return; + + const interval = setInterval(() => { + if (!humanEventManagerRef.current) return; + + humanEventManagerRef.current.humanStates.forEach((humanState) => { + const humanId = humanState.humanId; + + // Initialize tracking for this human if needed + if (!previousHumanCountsRef.current[humanId]) { + previousHumanCountsRef.current[humanId] = {}; + } + + humanState.actionQueue.forEach((action) => { + let lastCount = previousHumanCountsRef.current[humanId][action.actionUuid] || 0; + const currentCount = action.count || 0; + + // Handle reset case (new action instance with same UUID) + if (currentCount < lastCount) { + lastCount = 0; + previousHumanCountsRef.current[humanId][action.actionUuid] = 0; + } + + const delta = currentCount - lastCount; + + if (delta > 0) { + // Update total completions for this human + if (!completedActionsRef.current[humanId]) completedActionsRef.current[humanId] = 0; + completedActionsRef.current[humanId] += delta; + + // Update granular action type completions (e.g., worker, manufacturer) + const typeKey = `${humanId}_${action.actionType}`; + if (!completedActionsRef.current[typeKey]) completedActionsRef.current[typeKey] = 0; + completedActionsRef.current[typeKey] += delta; + + // Update the last known count + previousHumanCountsRef.current[humanId][action.actionUuid] = currentCount; + } + }); + }); + }, 100); + + return () => clearInterval(interval); + }, [isPlaying, humanEventManagerRef]); + // Periodic WIP and throughput snapshots useEffect(() => { if (!isPlaying) return;