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