feat: Add comprehensive simulation analysis and performance tracking component with extensive metric collection and utility functions.
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user