feat: Add comprehensive simulation analysis and performance tracking component with extensive metric collection and utility functions.

This commit is contained in:
2025-12-22 14:38:42 +05:30
parent 02cb4b9c95
commit e531479f4f

View File

@@ -492,7 +492,7 @@ function Analyzer() {
* Track material addition to an asset * Track material addition to an asset
*/ */
const trackMaterialAddition = useCallback((assetId: string, materialId: string, materialType: string, fromAsset?: string) => { const trackMaterialAddition = useCallback((assetId: string, materialId: string, materialType: string, fromAsset?: string) => {
const timestamp = Date.now(); const timestamp = getSimulationTime();
if (!materialAdditionsRef.current[assetId]) { if (!materialAdditionsRef.current[assetId]) {
materialAdditionsRef.current[assetId] = []; materialAdditionsRef.current[assetId] = [];
@@ -538,7 +538,7 @@ function Analyzer() {
* Track material removal from an asset * Track material removal from an asset
*/ */
const trackMaterialRemoval = useCallback((assetId: string, materialId: string, materialType: string, toAsset?: string) => { const trackMaterialRemoval = useCallback((assetId: string, materialId: string, materialType: string, toAsset?: string) => {
const timestamp = Date.now(); const timestamp = getSimulationTime();
if (!materialRemovalsRef.current[assetId]) { if (!materialRemovalsRef.current[assetId]) {
materialRemovalsRef.current[assetId] = []; materialRemovalsRef.current[assetId] = [];
@@ -583,7 +583,7 @@ function Analyzer() {
* Track asset state change * Track asset state change
*/ */
const trackStateChange = useCallback((assetId: string, fromState: string, toState: string, context?: { actionName?: string }) => { const trackStateChange = useCallback((assetId: string, fromState: string, toState: string, context?: { actionName?: string }) => {
const timestamp = Date.now(); const timestamp = getSimulationTime();
// Increment error count if entering error state // Increment error count if entering error state
if (toState === "error") { if (toState === "error") {
@@ -642,7 +642,7 @@ function Analyzer() {
* Start a new cycle for an asset * Start a new cycle for an asset
*/ */
const startAssetCycle = useCallback((assetId: string, cycleType: string, materialsInvolved: string[] = []) => { const startAssetCycle = useCallback((assetId: string, cycleType: string, materialsInvolved: string[] = []) => {
const timestamp = Date.now(); const timestamp = getSimulationTime();
const cycleId = `${assetId}-${timestamp}`; const cycleId = `${assetId}-${timestamp}`;
if (!assetCyclesRef.current[assetId]) { if (!assetCyclesRef.current[assetId]) {
@@ -664,7 +664,7 @@ function Analyzer() {
* Complete a cycle for an asset * Complete a cycle for an asset
*/ */
const completeAssetCycle = useCallback((assetId: string, cycleId: string, success: boolean = true) => { const completeAssetCycle = useCallback((assetId: string, cycleId: string, success: boolean = true) => {
const timestamp = Date.now(); const timestamp = getSimulationTime();
const cycles = assetCyclesRef.current[assetId] || []; const cycles = assetCyclesRef.current[assetId] || [];
const cycle = cycles.find((c) => c.cycleId === cycleId); const cycle = cycles.find((c) => c.cycleId === cycleId);
@@ -678,7 +678,7 @@ function Analyzer() {
* Track action completion * Track action completion
*/ */
const trackActionCompletion = useCallback((assetId: string, actionId: string, actionType: string, startTime: number, success: boolean = true) => { const trackActionCompletion = useCallback((assetId: string, actionId: string, actionType: string, startTime: number, success: boolean = true) => {
const endTime = Date.now(); const endTime = getSimulationTime();
if (!actionCompletionTimesRef.current[assetId]) { if (!actionCompletionTimesRef.current[assetId]) {
actionCompletionTimesRef.current[assetId] = []; actionCompletionTimesRef.current[assetId] = [];
@@ -704,7 +704,7 @@ function Analyzer() {
*/ */
const updateWIPSnapshot = useCallback( const updateWIPSnapshot = useCallback(
(assetId: string) => { (assetId: string) => {
const timestamp = Date.now(); const timestamp = getSimulationTime();
const currentMaterials = getMaterialsByModel(assetId); const currentMaterials = getMaterialsByModel(assetId);
if (!wipSnapshotsRef.current[assetId]) { if (!wipSnapshotsRef.current[assetId]) {
@@ -730,7 +730,7 @@ function Analyzer() {
*/ */
const updateThroughputSnapshot = useCallback( const updateThroughputSnapshot = useCallback(
(assetId: string) => { (assetId: string) => {
const timestamp = Date.now(); const timestamp = getSimulationTime();
const timeWindow = 60; // 60 seconds const timeWindow = 60; // 60 seconds
if (!throughputSnapshotsRef.current[assetId]) { if (!throughputSnapshotsRef.current[assetId]) {
@@ -742,8 +742,7 @@ function Analyzer() {
const recentRemovals = removals.filter((r) => timestamp - r.timestamp <= timeWindow * 1000); const recentRemovals = removals.filter((r) => timestamp - r.timestamp <= timeWindow * 1000);
const itemsProcessed = recentRemovals.length; const itemsProcessed = recentRemovals.length;
// Normalize by speed // Normalize by speed
const currentSpeed = Math.max(1, speed); const rate = (itemsProcessed / timeWindow) * 3600; // items per hour
const rate = ((itemsProcessed / timeWindow) * 3600) / currentSpeed; // items per hour
throughputSnapshotsRef.current[assetId].push({ throughputSnapshotsRef.current[assetId].push({
timestamp, timestamp,
@@ -764,7 +763,7 @@ function Analyzer() {
* Update performance snapshot for an asset * Update performance snapshot for an asset
*/ */
const updatePerformanceSnapshot = useCallback((assetId: string, utilization: number, efficiency: number, quality: number, oee: number) => { const updatePerformanceSnapshot = useCallback((assetId: string, utilization: number, efficiency: number, quality: number, oee: number) => {
const timestamp = Date.now(); const timestamp = getSimulationTime();
if (!performanceSnapshotsRef.current[assetId]) { if (!performanceSnapshotsRef.current[assetId]) {
performanceSnapshotsRef.current[assetId] = []; performanceSnapshotsRef.current[assetId] = [];
@@ -788,7 +787,7 @@ function Analyzer() {
* Track bottleneck event * Track bottleneck event
*/ */
const trackBottleneckEvent = useCallback((assetId: string, queueLength: number, utilizationRate: number, waitingMaterials: string[]) => { const trackBottleneckEvent = useCallback((assetId: string, queueLength: number, utilizationRate: number, waitingMaterials: string[]) => {
const timestamp = Date.now(); const timestamp = getSimulationTime();
if (!bottleneckEventsRef.current[assetId]) { if (!bottleneckEventsRef.current[assetId]) {
bottleneckEventsRef.current[assetId] = []; bottleneckEventsRef.current[assetId] = [];
@@ -840,7 +839,7 @@ function Analyzer() {
const currentWIP = wipSnapshots.length > 0 ? wipSnapshots[wipSnapshots.length - 1].wipCount : 0; const currentWIP = wipSnapshots.length > 0 ? wipSnapshots[wipSnapshots.length - 1].wipCount : 0;
// Calculate throughput rate // Calculate throughput rate
const now = Date.now(); const now = getSimulationTime();
const oneHourAgo = now - 3600000; const oneHourAgo = now - 3600000;
const recentRemovals = removals.filter((r) => r.timestamp >= oneHourAgo); const recentRemovals = removals.filter((r) => r.timestamp >= oneHourAgo);
const throughputRate = recentRemovals.length; // items per hour const throughputRate = recentRemovals.length; // items per hour
@@ -907,7 +906,7 @@ function Analyzer() {
const energyMetrics = calculateEnergyMetrics("conveyor", conveyor.activeTime || 0); const energyMetrics = calculateEnergyMetrics("conveyor", conveyor.activeTime || 0);
// Update historical data // Update historical data
const timestamp = new Date().toISOString(); const timestamp = getSimulationTime();
const newEntry = { const newEntry = {
timestamp, timestamp,
isActive: !conveyor.isPaused, isActive: !conveyor.isPaused,
@@ -924,7 +923,7 @@ function Analyzer() {
// Calculate queue if applicable // Calculate queue if applicable
const queueLength = materialFlow.wip; const queueLength = materialFlow.wip;
const currentQueueData = queueLengthsRef.current[conveyor.modelUuid] || []; const currentQueueData = queueLengthsRef.current[conveyor.modelUuid] || [];
queueLengthsRef.current[conveyor.modelUuid] = [...currentQueueData, { timestamp: Date.now(), length: queueLength }].slice(-100); queueLengthsRef.current[conveyor.modelUuid] = [...currentQueueData, { timestamp: getSimulationTime(), length: queueLength }].slice(-100);
return { return {
assetId: conveyor.modelUuid, assetId: conveyor.modelUuid,
@@ -1051,7 +1050,7 @@ function Analyzer() {
const energyMetrics = calculateEnergyMetrics("vehicle", vehicle.activeTime || 0, actualDistance); const energyMetrics = calculateEnergyMetrics("vehicle", vehicle.activeTime || 0, actualDistance);
// Update historical data // Update historical data
const timestamp = new Date().toISOString(); const timestamp = getSimulationTime();
const currentData = historicalDataRef.current[vehicle.modelUuid] || []; const currentData = historicalDataRef.current[vehicle.modelUuid] || [];
historicalDataRef.current[vehicle.modelUuid] = [ historicalDataRef.current[vehicle.modelUuid] = [
...currentData, ...currentData,
@@ -1214,7 +1213,7 @@ function Analyzer() {
// Update historical data // Update historical data
const timestamp = new Date().toISOString(); const timestamp = getSimulationTime();
const newEntry = { const newEntry = {
timestamp, timestamp,
cycleTime: actualCycleTime, cycleTime: actualCycleTime,
@@ -1339,7 +1338,7 @@ function Analyzer() {
const scrapRate = defectRate * 0.7; // Assume 70% are scrapped const scrapRate = defectRate * 0.7; // Assume 70% are scrapped
// Update historical data // Update historical data
const timestamp = new Date().toISOString(); const timestamp = getSimulationTime();
const currentData = historicalDataRef.current[machine.modelUuid] || []; const currentData = historicalDataRef.current[machine.modelUuid] || [];
historicalDataRef.current[machine.modelUuid] = [ historicalDataRef.current[machine.modelUuid] = [
...currentData, ...currentData,
@@ -1452,7 +1451,7 @@ function Analyzer() {
const turnoverRate = timeMetrics.totalTime > 0 ? (totalOps / timeMetrics.totalTime) * 3600 : 0; const turnoverRate = timeMetrics.totalTime > 0 ? (totalOps / timeMetrics.totalTime) * 3600 : 0;
// Occupancy trends // Occupancy trends
const timestamp = new Date().toISOString(); const timestamp = getSimulationTime();
const currentData = historicalDataRef.current[storage.modelUuid] || []; const currentData = historicalDataRef.current[storage.modelUuid] || [];
historicalDataRef.current[storage.modelUuid] = [ historicalDataRef.current[storage.modelUuid] = [
...currentData, ...currentData,
@@ -1472,8 +1471,8 @@ function Analyzer() {
const averageOccupancy = occupancyData.length > 0 ? occupancyData.reduce((sum, d) => sum + d.utilizationRate, 0) / occupancyData.length : utilizationRate; const averageOccupancy = occupancyData.length > 0 ? occupancyData.reduce((sum, d) => sum + d.utilizationRate, 0) / occupancyData.length : utilizationRate;
// Calculate occupancy trends for the last hour // Calculate occupancy trends for the last hour
const hourAgo = Date.now() - 3600000; const hourAgo = getSimulationTime() - 3600000;
const recentOccupancy = occupancyData.filter((d) => new Date(d.timestamp).getTime() > hourAgo).map((d) => d.utilizationRate); const recentOccupancy = occupancyData.filter((d) => d.timestamp > hourAgo).map((d) => d.utilizationRate);
const occupancyTrend = recentOccupancy.length > 1 ? ((recentOccupancy[recentOccupancy.length - 1] - recentOccupancy[0]) / recentOccupancy[0]) * 100 : 0; const occupancyTrend = recentOccupancy.length > 1 ? ((recentOccupancy[recentOccupancy.length - 1] - recentOccupancy[0]) / recentOccupancy[0]) * 100 : 0;
const costMetrics = calculateCostMetrics(storage.modelUuid, "storage", storage.activeTime || 0, totalOps); const costMetrics = calculateCostMetrics(storage.modelUuid, "storage", storage.activeTime || 0, totalOps);
@@ -1614,7 +1613,7 @@ function Analyzer() {
const energyMetrics = calculateEnergyMetrics("human", human.activeTime || 0); const energyMetrics = calculateEnergyMetrics("human", human.activeTime || 0);
// Update historical data // Update historical data
const timestamp = new Date().toISOString(); const timestamp = getSimulationTime();
const newEntry = { const newEntry = {
timestamp, timestamp,
actionType: human.currentAction?.actionName || "unknown", actionType: human.currentAction?.actionName || "unknown",
@@ -1751,7 +1750,7 @@ function Analyzer() {
const movementEfficiency = liftSuccessRate * 0.8 + positioningAccuracy * 0.2; // Weighted average const movementEfficiency = liftSuccessRate * 0.8 + positioningAccuracy * 0.2; // Weighted average
// Update historical data // Update historical data
const timestamp = new Date().toISOString(); const timestamp = getSimulationTime();
const newEntry = { const newEntry = {
timestamp, timestamp,
cycleTime: actualCycleTime, cycleTime: actualCycleTime,