feat: implement a comprehensive simulation analyzer module for tracking and calculating performance metrics.

This commit is contained in:
2025-12-20 10:52:27 +05:30
parent 14bf0896a7
commit a032c47e62

View File

@@ -184,6 +184,9 @@ function Analyzer() {
> >
>({}); >({});
// Track previous actions for ArmBots to detect cycle completion
const previousArmBotActionsRef = useRef<Record<string, string | undefined>>({});
// Material lifecycle tracking // Material lifecycle tracking
const materialLifecycleRef = useRef< const materialLifecycleRef = useRef<
Record< Record<
@@ -215,6 +218,7 @@ function Analyzer() {
performanceSnapshotsRef.current = {}; performanceSnapshotsRef.current = {};
bottleneckEventsRef.current = {}; bottleneckEventsRef.current = {};
previousAssetStatesRef.current = {}; previousAssetStatesRef.current = {};
previousArmBotActionsRef.current = {};
materialLifecycleRef.current = {}; materialLifecycleRef.current = {};
setAnalysis(null); setAnalysis(null);
setAnalyzing(false); setAnalyzing(false);
@@ -554,6 +558,14 @@ function Analyzer() {
const trackStateChange = useCallback((assetId: string, fromState: string, toState: string) => { const trackStateChange = useCallback((assetId: string, fromState: string, toState: string) => {
const timestamp = Date.now(); const timestamp = Date.now();
// Increment error count if entering error state
if (toState === "error") {
if (!errorCountsRef.current[assetId]) {
errorCountsRef.current[assetId] = 0;
}
errorCountsRef.current[assetId]++;
}
if (!assetStateChangesRef.current[assetId]) { if (!assetStateChangesRef.current[assetId]) {
assetStateChangesRef.current[assetId] = []; assetStateChangesRef.current[assetId] = [];
} }
@@ -1126,7 +1138,7 @@ function Analyzer() {
const materialFlow = calculateMaterialFlowMetricsForAsset(armBot.modelUuid); const materialFlow = calculateMaterialFlowMetricsForAsset(armBot.modelUuid);
const cyclesCompleted = completedActionsRef.current[armBot.modelUuid] || 0; const cyclesCompleted = completedActionsRef.current[armBot.modelUuid] || 0;
const pickAndPlaceCount = completedActionsRef.current[`${armBot.modelUuid}_pickplace`] || cyclesCompleted; const pickAndPlaceCount = completedActionsRef.current[`${armBot.modelUuid}_pickplace`] || cyclesCompleted;
const defects = errorCountsRef.current[`${armBot.modelUuid}_defects`] || 0; const defects = errorCount; // Use main error count directly
const qualityMetrics = calculateQualityMetrics(armBot.modelUuid, pickAndPlaceCount, defects); const qualityMetrics = calculateQualityMetrics(armBot.modelUuid, pickAndPlaceCount, defects);
@@ -1143,7 +1155,7 @@ function Analyzer() {
const energyMetrics = calculateEnergyMetrics("roboticArm", armBot.activeTime || 0); const energyMetrics = calculateEnergyMetrics("roboticArm", armBot.activeTime || 0);
// Calculate success rates // Calculate success rates
const pickAttempts = pickAndPlaceCount + (errorCountsRef.current[armBot.modelUuid] || 0); const pickAttempts = pickAndPlaceCount + errorCount;
const pickSuccessRate = pickAttempts > 0 ? (pickAndPlaceCount / pickAttempts) * 100 : 100; const pickSuccessRate = pickAttempts > 0 ? (pickAndPlaceCount / pickAttempts) * 100 : 100;
const placeAccuracy = pickSuccessRate * 0.98; // Assuming 98% of successful picks are placed correctly const placeAccuracy = pickSuccessRate * 0.98; // Assuming 98% of successful picks are placed correctly
@@ -2297,6 +2309,33 @@ function Analyzer() {
}); });
}, [conveyors, machines, armBots, vehicles, humans, cranes, storageUnits, isPlaying, getMaterialsByModel, trackStateChange, trackBottleneckEvent, updatePreviousAssetState]); }, [conveyors, machines, armBots, vehicles, humans, cranes, storageUnits, isPlaying, getMaterialsByModel, trackStateChange, trackBottleneckEvent, updatePreviousAssetState]);
// Monitor ArmBot action changes to track cycles
useEffect(() => {
if (!isPlaying) return;
armBots.forEach((armBot) => {
const previousActionUuid = previousArmBotActionsRef.current[armBot.modelUuid];
const currentActionUuid = armBot.currentAction?.actionUuid;
// Check if action completed (transition from an action to no action or different action)
if (previousActionUuid && previousActionUuid !== currentActionUuid) {
// Action completed
if (!completedActionsRef.current[armBot.modelUuid]) {
completedActionsRef.current[armBot.modelUuid] = 0;
}
completedActionsRef.current[armBot.modelUuid]++;
// Also update pick and place count which is used in analysis
if (!completedActionsRef.current[`${armBot.modelUuid}_pickplace`]) {
completedActionsRef.current[`${armBot.modelUuid}_pickplace`] = 0;
}
completedActionsRef.current[`${armBot.modelUuid}_pickplace`]++;
}
previousArmBotActionsRef.current[armBot.modelUuid] = currentActionUuid;
});
}, [armBots, isPlaying]);
// Periodic WIP and throughput snapshots // Periodic WIP and throughput snapshots
useEffect(() => { useEffect(() => {
if (!isPlaying) return; if (!isPlaying) return;