From 7dd795af57688d9ba60f0dd63ca632c374cf18c2 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Sat, 20 Dec 2025 15:30:10 +0530 Subject: [PATCH] feat: Add simulation analyzer with comprehensive metric tracking and a utility for calculating minimum block size. --- .../functions/block/calculateMinBlockSize.ts | 8 +++- .../modules/simulation/analyzer/analyzer.tsx | 47 +++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/app/src/components/SimulationDashboard/functions/block/calculateMinBlockSize.ts b/app/src/components/SimulationDashboard/functions/block/calculateMinBlockSize.ts index 4a5cbe0..f0816e9 100644 --- a/app/src/components/SimulationDashboard/functions/block/calculateMinBlockSize.ts +++ b/app/src/components/SimulationDashboard/functions/block/calculateMinBlockSize.ts @@ -4,6 +4,7 @@ export const calculateMinBlockSize = (block: Block): Size => { let minWidth = 100; let minHeight = 50; let stackedHeight = 0; // Track cumulative height for stacked elements + let stackedElementCount = 0; // Track number of stacked elements for gap calculation block.elements.forEach((element) => { if (element.positionType === "absolute") { @@ -17,12 +18,15 @@ export const calculateMinBlockSize = (block: Block): Size => { minWidth = Math.max(minWidth, (element.size?.width || 200) + 40); // Height: sum them up since they stack stackedHeight += element.size?.height || 60; + stackedElementCount++; } }); - // Add padding to stacked height and compare with minHeight from absolute elements + // Add padding to stacked height and gaps between elements if (stackedHeight > 0) { - minHeight = Math.max(minHeight, stackedHeight + 40); + // Add 10px gap between each pair of stacked elements + const gapsBetweenElements = Math.max(0, stackedElementCount - 1) * 5; + minHeight = Math.max(minHeight, stackedHeight + gapsBetweenElements + 40); } return { width: minWidth, height: minHeight }; diff --git a/app/src/modules/simulation/analyzer/analyzer.tsx b/app/src/modules/simulation/analyzer/analyzer.tsx index 9cb2273..28a3d09 100644 --- a/app/src/modules/simulation/analyzer/analyzer.tsx +++ b/app/src/modules/simulation/analyzer/analyzer.tsx @@ -193,6 +193,9 @@ function Analyzer() { // Track previous vehicle phases to detect trip completion const previousVehiclePhasesRef = useRef>({}); + // Track previous crane phases to detect cycle completion + const previousCranePhasesRef = useRef>({}); + // Material lifecycle tracking const materialLifecycleRef = useRef< Record< @@ -227,6 +230,7 @@ function Analyzer() { previousArmBotActionsRef.current = {}; previousHumanCountsRef.current = {}; previousVehiclePhasesRef.current = {}; + previousCranePhasesRef.current = {}; materialLifecycleRef.current = {}; setAnalysis(null); setAnalyzing(false); @@ -2487,6 +2491,49 @@ function Analyzer() { }); }, [vehicles, isPlaying]); + // Monitor Crane phase changes to track completed cycles, loads, and lifts + useEffect(() => { + if (!isPlaying) return; + + cranes.forEach((crane) => { + const previousPhase = previousCranePhasesRef.current[crane.modelUuid]; + const currentPhase = crane.currentPhase; + + // Check for transition from 'pickup-drop' to 'init' (Cycle completed) + if (previousPhase === "pickup-drop" && currentPhase === "init") { + // Increment cycles completed + if (!completedActionsRef.current[crane.modelUuid]) { + completedActionsRef.current[crane.modelUuid] = 0; + } + completedActionsRef.current[crane.modelUuid]++; + + // Track loads handled (number of materials carried in this cycle) + const loadsInCycle = crane.currentMaterials?.length || 1; + if (!completedActionsRef.current[`${crane.modelUuid}_loads`]) { + completedActionsRef.current[`${crane.modelUuid}_loads`] = 0; + } + completedActionsRef.current[`${crane.modelUuid}_loads`] += loadsInCycle; + } + + // Track lifts (picking phase indicates a lift operation) + if (previousPhase !== "picking" && currentPhase === "picking") { + if (!completedActionsRef.current[`${crane.modelUuid}_lifts`]) { + completedActionsRef.current[`${crane.modelUuid}_lifts`] = 0; + } + completedActionsRef.current[`${crane.modelUuid}_lifts`]++; + + // Track lift height (assuming a default lift height of 5 meters for now) + // In a real scenario, this would be calculated from crane constraints + if (!completedActionsRef.current[`${crane.modelUuid}_lift_height`]) { + completedActionsRef.current[`${crane.modelUuid}_lift_height`] = 0; + } + completedActionsRef.current[`${crane.modelUuid}_lift_height`] += 5; + } + + previousCranePhasesRef.current[crane.modelUuid] = currentPhase; + }); + }, [cranes, isPlaying]); + return null; }