diff --git a/app/package-lock.json b/app/package-lock.json
index d9ce5b7..91c994b 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -2031,7 +2031,7 @@
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
- "dev": true,
+ "devOptional": true,
"dependencies": {
"@jridgewell/trace-mapping": "0.3.9"
},
@@ -2043,7 +2043,7 @@
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
- "dev": true,
+ "devOptional": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
@@ -4242,6 +4242,26 @@
"url": "https://github.com/sponsors/gregberge"
}
},
+ "node_modules/@testing-library/dom": {
+ "version": "10.4.1",
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz",
+ "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/runtime": "^7.12.5",
+ "@types/aria-query": "^5.0.1",
+ "aria-query": "5.3.0",
+ "dom-accessibility-api": "^0.5.9",
+ "lz-string": "^1.5.0",
+ "picocolors": "1.1.1",
+ "pretty-format": "^27.0.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@testing-library/jest-dom": {
"version": "5.17.0",
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz",
@@ -4353,25 +4373,25 @@
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
"integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
- "dev": true
+ "devOptional": true
},
"node_modules/@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
- "dev": true
+ "devOptional": true
},
"node_modules/@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
- "dev": true
+ "devOptional": true
},
"node_modules/@tsconfig/node16": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
- "dev": true
+ "devOptional": true
},
"node_modules/@turf/along": {
"version": "7.2.0",
@@ -9213,7 +9233,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
- "dev": true
+ "devOptional": true
},
"node_modules/cross-env": {
"version": "7.0.3",
@@ -10229,7 +10249,7 @@
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
- "dev": true,
+ "devOptional": true,
"engines": {
"node": ">=0.3.1"
}
@@ -15632,7 +15652,7 @@
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
- "dev": true
+ "devOptional": true
},
"node_modules/makeerror": {
"version": "1.0.12",
@@ -21288,7 +21308,7 @@
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
- "dev": true,
+ "devOptional": true,
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
@@ -21331,7 +21351,7 @@
"version": "8.3.4",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
- "dev": true,
+ "devOptional": true,
"dependencies": {
"acorn": "^8.11.0"
},
@@ -21343,7 +21363,7 @@
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
- "dev": true
+ "devOptional": true
},
"node_modules/tsconfig-paths": {
"version": "3.15.0",
@@ -21839,7 +21859,7 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
- "dev": true
+ "devOptional": true
},
"node_modules/v8-to-istanbul": {
"version": "8.1.1",
@@ -22932,7 +22952,7 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
- "dev": true,
+ "devOptional": true,
"engines": {
"node": ">=6"
}
diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx
index 7a6962d..8f1e22d 100644
--- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx
+++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx
@@ -62,7 +62,7 @@ function StorageMechanics() {
const handleActionTypeChange = (option: string) => {
if (!selectedAction.actionId || !selectedPointData) return;
- const event = peekUpdateAction(selectedProduct.productUuid, selectedAction.actionId, { actionType: option as "store" | "retrieve" });
+ const event = peekUpdateAction(selectedProduct.productUuid, selectedAction.actionId, { actionType: option === "store" ? "store" : "retrieve" } as StorageAction);
if (event) {
updateBackend(event);
@@ -184,7 +184,13 @@ function StorageMechanics() {
-
+
diff --git a/app/src/modules/scene/sceneContext.tsx b/app/src/modules/scene/sceneContext.tsx
index 2967ee9..2cec554 100644
--- a/app/src/modules/scene/sceneContext.tsx
+++ b/app/src/modules/scene/sceneContext.tsx
@@ -29,6 +29,7 @@ import { createHumanStore, HumanStoreType } from "../../store/simulation/useHuma
import { createCraneStore, CraneStoreType } from "../../store/simulation/useCraneStore";
import { createSimulationDashboardStore, SimulationDashboardStoreType } from "../../store/simulation/useSimulationDashBoardStore";
+import { createAnalysisStore, AnalysisStoreType } from "../../store/simulation/useAnalysisStore";
import { createThreadsStore, ThreadStoreType } from "../../store/collaboration/useThreadStore";
@@ -66,6 +67,7 @@ type SceneContextValue = {
craneStore: CraneStoreType;
simulationDashBoardStore: SimulationDashboardStoreType;
+ analysisStore: AnalysisStoreType;
threadStore: ThreadStoreType;
@@ -123,6 +125,7 @@ export function SceneProvider({
const craneStore = useMemo(() => createCraneStore(), []);
const simulationDashBoardStore = useMemo(() => createSimulationDashboardStore(), []);
+ const analysisStore = useMemo(() => createAnalysisStore(), []);
const threadStore = useMemo(() => createThreadsStore(), []);
@@ -157,6 +160,7 @@ export function SceneProvider({
humanStore.getState().clearHumans();
craneStore.getState().clearCranes();
simulationDashBoardStore.getState().clearBlocks();
+ analysisStore.getState().clearAnalysis();
threadStore.getState().clearThreads();
collabUsersStore.getState().clearCollabUsers();
humanEventManagerRef.current.humanStates = [];
@@ -184,6 +188,7 @@ export function SceneProvider({
humanStore,
craneStore,
simulationDashBoardStore,
+ analysisStore,
threadStore,
collabUsersStore,
]
@@ -215,6 +220,7 @@ export function SceneProvider({
humanStore,
craneStore,
simulationDashBoardStore,
+ analysisStore,
threadStore,
collabUsersStore,
humanEventManagerRef,
@@ -248,6 +254,7 @@ export function SceneProvider({
humanStore,
craneStore,
simulationDashBoardStore,
+ analysisStore,
threadStore,
collabUsersStore,
clearStores,
diff --git a/app/src/modules/simulation/analysis/simulationAnalysis.tsx b/app/src/modules/simulation/analysis/simulationAnalysis.tsx
index 2cfda53..efc02e1 100644
--- a/app/src/modules/simulation/analysis/simulationAnalysis.tsx
+++ b/app/src/modules/simulation/analysis/simulationAnalysis.tsx
@@ -1,16 +1,15 @@
-import ProductionCapacityData from './productionCapacity/productionCapacityData'
-import ThroughPutData from './throughPut/throughPutData'
-import ROIData from './ROI/roiData'
+import ProductionCapacityData from "./productionCapacity/productionCapacityData";
+import ThroughPutData from "./throughPut/throughPutData";
+import ROIData from "./ROI/roiData";
function SimulationAnalysis() {
-
return (
<>
>
- )
+ );
}
-export default SimulationAnalysis
+export default SimulationAnalysis;
diff --git a/app/src/modules/simulation/analyzer/analyzer.tsx b/app/src/modules/simulation/analyzer/analyzer.tsx
new file mode 100644
index 0000000..1d6e597
--- /dev/null
+++ b/app/src/modules/simulation/analyzer/analyzer.tsx
@@ -0,0 +1,700 @@
+import { useEffect, useCallback, useRef } from "react";
+import { useSceneContext } from "../../scene/sceneContext";
+import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore";
+
+function Analyzer() {
+ const { isPlaying } = usePlayButtonStore();
+ const { conveyorStore, machineStore, armBotStore, humanStore, vehicleStore, craneStore, storageUnitStore, analysisStore } = useSceneContext();
+
+ const { conveyors } = conveyorStore();
+ const { machines } = machineStore();
+ const { armBots } = armBotStore();
+ const { humans } = humanStore();
+ const { vehicles } = vehicleStore();
+ const { cranes } = craneStore();
+ const { storageUnits } = storageUnitStore();
+
+ const { setAnalysis, setAnalyzing } = analysisStore();
+
+ const analysisIntervalRef = useRef
(null);
+ const startTimeRef = useRef(new Date().toISOString());
+
+ // ============================================================================
+ // CALCULATION UTILITIES
+ // ============================================================================
+
+ const calculateTimeMetrics = (idleTime: number, activeTime: number, totalErrors: number = 0) => {
+ const totalTime = idleTime + activeTime;
+ const uptime = totalTime > 0 ? (activeTime / totalTime) * 100 : 0;
+ const downtime = idleTime;
+ const utilizationRate = uptime / 100;
+
+ return {
+ uptime,
+ downtime,
+ utilizationRate,
+ mtbf: totalErrors > 0 ? totalTime / totalErrors : totalTime,
+ mttr: totalErrors > 0 ? downtime / totalErrors : 0,
+ };
+ };
+
+ const calculateOEE = (availability: number, performance: number, quality: number) => {
+ return (availability * performance * quality) / 10000; // All in percentages
+ };
+
+ // ============================================================================
+ // CONVEYOR ANALYSIS
+ // ============================================================================
+
+ const analyzeConveyor = useCallback((conveyor: any): ConveyorAnalysis => {
+ const timeMetrics = calculateTimeMetrics(conveyor.idleTime || 0, conveyor.activeTime || 0);
+
+ const totalTime = (conveyor.idleTime || 0) + (conveyor.activeTime || 0);
+ const materialsProcessed = conveyor.materialsProcessed || 0;
+
+ return {
+ assetId: conveyor.modelUuid,
+ assetName: conveyor.modelName,
+ assetType: "conveyor",
+
+ currentStatus: {
+ isActive: conveyor.isActive || false,
+ isPaused: conveyor.isPaused || false,
+ state: conveyor.state || "idle",
+ speed: conveyor.speed || 0,
+ currentProduct: conveyor.productUuid || null,
+ },
+
+ timeMetrics: {
+ ...timeMetrics,
+ idleTime: conveyor.idleTime || 0,
+ activeTime: conveyor.activeTime || 0,
+ totalTime,
+ },
+
+ throughput: {
+ itemsPerHour: totalTime > 0 ? (materialsProcessed / totalTime) * 3600 : 0,
+ itemsPerDay: totalTime > 0 ? (materialsProcessed / totalTime) * 86400 : 0,
+ materialFlowRate: conveyor.speed || 0,
+ capacityUtilization: timeMetrics.utilizationRate * 100,
+ materialsProcessed,
+ averageProcessingTime: materialsProcessed > 0 ? totalTime / materialsProcessed : 0,
+ },
+
+ efficiency: {
+ overallEffectiveness: calculateOEE(timeMetrics.uptime, 100, 100),
+ availability: timeMetrics.uptime,
+ performance: 100,
+ quality: 100,
+ },
+
+ quality: {
+ errorRate: 0,
+ errorFrequency: 0,
+ successRate: 100,
+ stateTransitions: [],
+ },
+
+ historicalData: [],
+ };
+ }, []);
+
+ // ============================================================================
+ // VEHICLE ANALYSIS
+ // ============================================================================
+
+ const analyzeVehicle = useCallback((vehicle: any): VehicleAnalysis => {
+ const timeMetrics = calculateTimeMetrics(vehicle.idleTime || 0, vehicle.activeTime || 0);
+
+ const totalTime = (vehicle.idleTime || 0) + (vehicle.activeTime || 0);
+ const tripsCompleted = vehicle.tripsCompleted || 0;
+
+ return {
+ assetId: vehicle.modelUuid,
+ assetName: vehicle.modelName,
+ assetType: "vehicle",
+
+ currentStatus: {
+ isActive: vehicle.isActive || false,
+ isPicking: vehicle.isPicking || false,
+ currentPhase: vehicle.currentPhase || "idle",
+ state: vehicle.state || "idle",
+ speed: vehicle.speed || 0,
+ currentLoad: vehicle.currentLoad || 0,
+ currentMaterials: vehicle.currentMaterials || [],
+ },
+
+ timeMetrics: {
+ ...timeMetrics,
+ idleTime: vehicle.idleTime || 0,
+ activeTime: vehicle.activeTime || 0,
+ totalTime,
+ averageTripTime: tripsCompleted > 0 ? totalTime / tripsCompleted : 0,
+ },
+
+ throughput: {
+ itemsPerHour: totalTime > 0 ? ((vehicle.currentLoad || 0) / totalTime) * 3600 : 0,
+ itemsPerDay: totalTime > 0 ? ((vehicle.currentLoad || 0) / totalTime) * 86400 : 0,
+ materialFlowRate: vehicle.speed || 0,
+ capacityUtilization: timeMetrics.utilizationRate * 100,
+ tripsCompleted,
+ averageLoadsPerTrip: tripsCompleted > 0 ? (vehicle.totalLoadsDelivered || 0) / tripsCompleted : 0,
+ totalLoadsDelivered: vehicle.totalLoadsDelivered || 0,
+ },
+
+ movementMetrics: {
+ distanceTraveled: vehicle.distanceTraveled || 0,
+ averageSpeedActual: totalTime > 0 ? (vehicle.distanceTraveled || 0) / totalTime : 0,
+ fuelEfficiency: 0,
+ routeEfficiency: 100,
+ },
+
+ efficiency: {
+ overallEffectiveness: calculateOEE(timeMetrics.uptime, 100, 100),
+ availability: timeMetrics.uptime,
+ performance: 100,
+ quality: 100,
+ loadUtilization: vehicle.point?.action?.loadCapacity > 0 ? ((vehicle.currentLoad || 0) / vehicle.point.action.loadCapacity) * 100 : 0,
+ },
+
+ quality: {
+ errorRate: 0,
+ errorFrequency: 0,
+ successRate: 100,
+ stateTransitions: [],
+ },
+
+ historicalData: [],
+ };
+ }, []);
+
+ // ============================================================================
+ // ROBOTIC ARM ANALYSIS
+ // ============================================================================
+
+ const analyzeRoboticArm = useCallback((armBot: any): RoboticArmAnalysis => {
+ const timeMetrics = calculateTimeMetrics(armBot.idleTime || 0, armBot.activeTime || 0);
+
+ const totalTime = (armBot.idleTime || 0) + (armBot.activeTime || 0);
+ const cyclesCompleted = armBot.cyclesCompleted || 0;
+
+ return {
+ assetId: armBot.modelUuid,
+ assetName: armBot.modelName,
+ assetType: "roboticArm",
+
+ currentStatus: {
+ isActive: armBot.isActive || false,
+ state: armBot.state || "idle",
+ speed: armBot.speed || 0,
+ currentAction: armBot.currentAction || null,
+ },
+
+ timeMetrics: {
+ ...timeMetrics,
+ idleTime: armBot.idleTime || 0,
+ activeTime: armBot.activeTime || 0,
+ totalTime,
+ averageCycleTime: cyclesCompleted > 0 ? totalTime / cyclesCompleted : 0,
+ },
+
+ throughput: {
+ itemsPerHour: totalTime > 0 ? (cyclesCompleted / totalTime) * 3600 : 0,
+ itemsPerDay: totalTime > 0 ? (cyclesCompleted / totalTime) * 86400 : 0,
+ materialFlowRate: armBot.speed || 0,
+ capacityUtilization: timeMetrics.utilizationRate * 100,
+ cyclesCompleted,
+ pickAndPlaceCount: cyclesCompleted,
+ },
+
+ efficiency: {
+ overallEffectiveness: calculateOEE(timeMetrics.uptime, 100, 100),
+ availability: timeMetrics.uptime,
+ performance: 100,
+ quality: 100,
+ cycleTimeEfficiency: 100,
+ },
+
+ quality: {
+ errorRate: 0,
+ errorFrequency: 0,
+ successRate: 100,
+ stateTransitions: [],
+ pickSuccessRate: 100,
+ placeAccuracy: 100,
+ },
+
+ historicalData: [],
+ };
+ }, []);
+
+ // ============================================================================
+ // MACHINE ANALYSIS
+ // ============================================================================
+
+ const analyzeMachine = useCallback((machine: any): MachineAnalysis => {
+ const timeMetrics = calculateTimeMetrics(machine.idleTime || 0, machine.activeTime || 0);
+
+ const totalTime = (machine.idleTime || 0) + (machine.activeTime || 0);
+ const cyclesCompleted = machine.cyclesCompleted || 0;
+
+ return {
+ assetId: machine.modelUuid,
+ assetName: machine.modelName,
+ assetType: "machine",
+
+ currentStatus: {
+ isActive: machine.isActive || false,
+ state: machine.state || "idle",
+ currentAction: machine.currentAction || null,
+ },
+
+ timeMetrics: {
+ ...timeMetrics,
+ idleTime: machine.idleTime || 0,
+ activeTime: machine.activeTime || 0,
+ totalTime,
+ averageProcessTime: cyclesCompleted > 0 ? totalTime / cyclesCompleted : 0,
+ },
+
+ throughput: {
+ itemsPerHour: totalTime > 0 ? (cyclesCompleted / totalTime) * 3600 : 0,
+ itemsPerDay: totalTime > 0 ? (cyclesCompleted / totalTime) * 86400 : 0,
+ materialFlowRate: 1,
+ capacityUtilization: timeMetrics.utilizationRate * 100,
+ cyclesCompleted,
+ partsProcessed: cyclesCompleted,
+ },
+
+ efficiency: {
+ overallEffectiveness: calculateOEE(timeMetrics.uptime, 100, 100),
+ availability: timeMetrics.uptime,
+ performance: 100,
+ quality: 100,
+ targetVsActual: 100,
+ },
+
+ quality: {
+ errorRate: 0,
+ errorFrequency: 0,
+ successRate: 100,
+ stateTransitions: [],
+ defectRate: 0,
+ reworkRate: 0,
+ },
+
+ historicalData: [],
+ };
+ }, []);
+
+ // ============================================================================
+ // STORAGE ANALYSIS
+ // ============================================================================
+
+ const analyzeStorage = useCallback((storage: any): StorageAnalysis => {
+ const timeMetrics = calculateTimeMetrics(storage.idleTime || 0, storage.activeTime || 0);
+
+ const utilizationRate = storage.storageCapacity > 0 ? (storage.currentLoad / storage.storageCapacity) * 100 : 0;
+
+ return {
+ assetId: storage.modelUuid,
+ assetName: storage.modelName,
+ assetType: "storage",
+
+ currentStatus: {
+ isActive: storage.isActive || false,
+ state: storage.state || "idle",
+ currentLoad: storage.currentLoad || 0,
+ storageCapacity: storage.storageCapacity || 0,
+ currentMaterials: storage.currentMaterials || [],
+ },
+
+ timeMetrics: {
+ ...timeMetrics,
+ idleTime: storage.idleTime || 0,
+ activeTime: storage.activeTime || 0,
+ totalTime: (storage.idleTime || 0) + (storage.activeTime || 0),
+ },
+
+ capacityMetrics: {
+ utilizationRate,
+ averageOccupancy: utilizationRate,
+ peakOccupancy: storage.peakOccupancy || utilizationRate,
+ turnoverRate: 0,
+ },
+
+ throughput: {
+ itemsPerHour: 0,
+ itemsPerDay: 0,
+ materialFlowRate: 0,
+ capacityUtilization: utilizationRate,
+ storeOperations: storage.storeOperations || 0,
+ retrieveOperations: storage.retrieveOperations || 0,
+ totalOperations: (storage.storeOperations || 0) + (storage.retrieveOperations || 0),
+ },
+
+ efficiency: {
+ overallEffectiveness: calculateOEE(timeMetrics.uptime, utilizationRate, 100),
+ availability: timeMetrics.uptime,
+ performance: utilizationRate,
+ quality: 100,
+ spaceUtilization: utilizationRate,
+ },
+
+ quality: {
+ errorRate: 0,
+ errorFrequency: 0,
+ successRate: 100,
+ stateTransitions: [],
+ },
+
+ occupancyTrends: [],
+ historicalData: [],
+ };
+ }, []);
+
+ // ============================================================================
+ // HUMAN ANALYSIS
+ // ============================================================================
+
+ const analyzeHuman = useCallback((human: any): HumanAnalysis => {
+ const timeMetrics = calculateTimeMetrics(human.idleTime || 0, human.activeTime || 0);
+
+ const totalTime = (human.idleTime || 0) + (human.activeTime || 0);
+ const actionsCompleted = human.actionsCompleted || 0;
+
+ return {
+ assetId: human.modelUuid,
+ assetName: human.modelName,
+ assetType: "human",
+
+ currentStatus: {
+ isActive: human.isActive || false,
+ isScheduled: human.isScheduled || false,
+ currentPhase: human.currentPhase || "idle",
+ state: human.state || "idle",
+ speed: human.speed || 0,
+ currentLoad: human.currentLoad || 0,
+ currentMaterials: human.currentMaterials || [],
+ currentAction: human.currentAction || null,
+ },
+
+ timeMetrics: {
+ ...timeMetrics,
+ idleTime: human.idleTime || 0,
+ activeTime: human.activeTime || 0,
+ totalTime,
+ scheduledTime: totalTime,
+ },
+
+ productivityMetrics: {
+ actionsCompleted,
+ actionsPerHour: totalTime > 0 ? (actionsCompleted / totalTime) * 3600 : 0,
+ averageActionTime: actionsCompleted > 0 ? totalTime / actionsCompleted : 0,
+ distanceTraveled: human.distanceTraveled || 0,
+ },
+
+ workloadDistribution: [],
+
+ efficiency: {
+ overallEffectiveness: calculateOEE(timeMetrics.uptime, 100, 100),
+ availability: timeMetrics.uptime,
+ performance: 100,
+ quality: 100,
+ laborProductivity: totalTime > 0 ? actionsCompleted / (totalTime / 3600) : 0,
+ utilizationRate: timeMetrics.utilizationRate * 100,
+ },
+
+ quality: {
+ errorRate: 0,
+ errorFrequency: 0,
+ successRate: 100,
+ stateTransitions: [],
+ },
+
+ historicalData: [],
+ };
+ }, []);
+
+ // ============================================================================
+ // CRANE ANALYSIS
+ // ============================================================================
+
+ const analyzeCrane = useCallback((crane: any): CraneAnalysis => {
+ const timeMetrics = calculateTimeMetrics(crane.idleTime || 0, crane.activeTime || 0);
+
+ const totalTime = (crane.idleTime || 0) + (crane.activeTime || 0);
+ const cyclesCompleted = crane.cyclesCompleted || 0;
+
+ return {
+ assetId: crane.modelUuid,
+ assetName: crane.modelName,
+ assetType: "crane",
+
+ currentStatus: {
+ isActive: crane.isActive || false,
+ isScheduled: crane.isScheduled || false,
+ isCarrying: crane.isCarrying || false,
+ currentPhase: crane.currentPhase || "idle",
+ state: crane.state || "idle",
+ currentLoad: crane.currentLoad || 0,
+ currentMaterials: crane.currentMaterials || [],
+ currentAction: crane.currentAction || null,
+ },
+
+ timeMetrics: {
+ ...timeMetrics,
+ idleTime: crane.idleTime || 0,
+ activeTime: crane.activeTime || 0,
+ totalTime,
+ averageCycleTime: cyclesCompleted > 0 ? totalTime / cyclesCompleted : 0,
+ },
+
+ throughput: {
+ itemsPerHour: totalTime > 0 ? (cyclesCompleted / totalTime) * 3600 : 0,
+ itemsPerDay: totalTime > 0 ? (cyclesCompleted / totalTime) * 86400 : 0,
+ materialFlowRate: 1,
+ capacityUtilization: timeMetrics.utilizationRate * 100,
+ cyclesCompleted,
+ loadsHandled: crane.loadsHandled || 0,
+ averageLoadsPerCycle: cyclesCompleted > 0 ? (crane.loadsHandled || 0) / cyclesCompleted : 0,
+ },
+
+ movementMetrics: {
+ totalLifts: crane.totalLifts || 0,
+ averageLiftHeight: crane.averageLiftHeight || 0,
+ movementEfficiency: 100,
+ },
+
+ efficiency: {
+ overallEffectiveness: calculateOEE(timeMetrics.uptime, 100, 100),
+ availability: timeMetrics.uptime,
+ performance: 100,
+ quality: 100,
+ loadUtilization: 0,
+ cycleTimeEfficiency: 100,
+ },
+
+ quality: {
+ errorRate: 0,
+ errorFrequency: 0,
+ successRate: 100,
+ stateTransitions: [],
+ liftSuccessRate: 100,
+ positioningAccuracy: 100,
+ },
+
+ historicalData: [],
+ };
+ }, []);
+
+ // ============================================================================
+ // SYSTEM-WIDE ANALYSIS
+ // ============================================================================
+
+ const analyzeSystem = useCallback((allAssets: AssetAnalysis[]): AnalysisSchema => {
+ // Calculate system-wide metrics
+ const totalAssets = allAssets.length;
+ const activeAssets = allAssets.filter((a) => a.currentStatus.isActive).length;
+ const assetsInError = allAssets.filter((a) => a.currentStatus.state === "error").length;
+
+ const avgOEE = allAssets.reduce((sum, a) => sum + a.efficiency.overallEffectiveness, 0) / totalAssets;
+ const avgUtilization = allAssets.reduce((sum, a) => sum + a.timeMetrics.utilizationRate, 0) / totalAssets;
+ const avgIdleTime = allAssets.reduce((sum, a) => sum + a.timeMetrics.idleTime, 0) / totalAssets;
+ const totalDowntime = allAssets.reduce((sum, a) => sum + a.timeMetrics.downtime, 0);
+
+ // Helper to get throughput safely
+ const getThroughput = (asset: AssetAnalysis): number => {
+ if ("throughput" in asset) {
+ return asset.throughput.itemsPerHour;
+ } else if ("productivityMetrics" in asset) {
+ return asset.productivityMetrics.actionsPerHour;
+ }
+ return 0;
+ };
+
+ // Group by asset type
+ const assetTypeGroups = allAssets.reduce((acc, asset) => {
+ if (!acc[asset.assetType]) {
+ acc[asset.assetType] = [];
+ }
+ acc[asset.assetType].push(asset);
+ return acc;
+ }, {} as Record);
+
+ const assetTypePerformance = Object.entries(assetTypeGroups).map(([type, assets]) => ({
+ assetType: type,
+ count: assets.length,
+ averageOEE: assets.reduce((sum, a) => sum + a.efficiency.overallEffectiveness, 0) / assets.length,
+ averageUtilization: (assets.reduce((sum, a) => sum + a.timeMetrics.utilizationRate, 0) / assets.length) * 100,
+ totalThroughput: assets.reduce((sum, a) => sum + getThroughput(a), 0),
+ }));
+
+ // Identify bottlenecks (high utilization + low throughput)
+ const bottlenecks = allAssets
+ .filter((a) => a.timeMetrics.utilizationRate > 0.8)
+ .map((a) => ({
+ assetId: a.assetId,
+ assetName: a.assetName,
+ severity:
+ a.timeMetrics.utilizationRate > 0.95
+ ? ("critical" as const)
+ : a.timeMetrics.utilizationRate > 0.9
+ ? ("high" as const)
+ : a.timeMetrics.utilizationRate > 0.85
+ ? ("medium" as const)
+ : ("low" as const),
+ utilizationRate: a.timeMetrics.utilizationRate * 100,
+ queueLength: 0,
+ impactScore: a.timeMetrics.utilizationRate * 100,
+ }))
+ .sort((a, b) => b.impactScore - a.impactScore);
+
+ return {
+ assets: allAssets,
+
+ systemPerformance: {
+ overallOEE: avgOEE,
+ systemThroughput: allAssets.reduce((sum, a) => sum + getThroughput(a), 0),
+ systemUtilization: avgUtilization * 100,
+ assetTypePerformance,
+ criticalMetrics: {
+ activeAssets,
+ totalAssets,
+ assetsInError,
+ averageIdleTime: avgIdleTime,
+ totalDowntime,
+ },
+ },
+
+ materialFlow: {
+ totalMaterialsInSystem: 0,
+ materialsCompleted: 0,
+ averageResidenceTime: 0,
+ queueLengths: [],
+ bottlenecks,
+ flowContinuity: {
+ overallFlowRate: 0,
+ varianceCoefficient: 0,
+ steadyStateDeviation: 0,
+ },
+ },
+
+ predictiveInsights: {
+ maintenanceAlerts: [],
+ optimizationOpportunities: [],
+ trendAnalysis: [],
+ },
+
+ analysisTimeRange: {
+ startTime: startTimeRef.current,
+ endTime: new Date().toISOString(),
+ duration: Date.now() - new Date(startTimeRef.current).getTime(),
+ },
+
+ metadata: {
+ lastUpdated: new Date().toISOString(),
+ dataPoints: allAssets.length,
+ analysisVersion: "1.0.0",
+ },
+ };
+ }, []);
+
+ // ============================================================================
+ // MAIN ANALYSIS FUNCTION
+ // ============================================================================
+
+ const performAnalysis = useCallback(() => {
+ setAnalyzing(true);
+
+ try {
+ const allAssets: AssetAnalysis[] = [];
+
+ // Analyze all conveyors
+ conveyors.forEach((conveyor) => {
+ allAssets.push(analyzeConveyor(conveyor));
+ });
+
+ // Analyze all vehicles
+ vehicles.forEach((vehicle) => {
+ allAssets.push(analyzeVehicle(vehicle));
+ });
+
+ // Analyze all robotic arms
+ armBots.forEach((armBot) => {
+ allAssets.push(analyzeRoboticArm(armBot));
+ });
+
+ // Analyze all machines
+ machines.forEach((machine) => {
+ allAssets.push(analyzeMachine(machine));
+ });
+
+ // Analyze all storage units
+ storageUnits.forEach((storage) => {
+ allAssets.push(analyzeStorage(storage));
+ });
+
+ // Analyze all humans
+ humans.forEach((human) => {
+ allAssets.push(analyzeHuman(human));
+ });
+
+ // Analyze all cranes
+ cranes.forEach((crane) => {
+ allAssets.push(analyzeCrane(crane));
+ });
+
+ // Perform system-wide analysis
+ const completeAnalysis = analyzeSystem(allAssets);
+
+ setAnalysis(completeAnalysis);
+ } catch (error) {
+ console.error("Analysis error:", error);
+ } finally {
+ setAnalyzing(false);
+ }
+ }, [
+ conveyors,
+ vehicles,
+ armBots,
+ machines,
+ humans,
+ cranes,
+ analyzeConveyor,
+ analyzeVehicle,
+ analyzeRoboticArm,
+ analyzeMachine,
+ analyzeHuman,
+ analyzeCrane,
+ analyzeSystem,
+ setAnalysis,
+ setAnalyzing,
+ ]);
+
+ // ============================================================================
+ // EFFECTS
+ // ============================================================================
+
+ // Perform initial analysis and set up interval
+ useEffect(() => {
+ if (!isPlaying) return;
+ // Initial analysis
+ performAnalysis();
+
+ // Set up periodic analysis (every 5 seconds)
+ analysisIntervalRef.current = setInterval(() => {
+ performAnalysis();
+ }, 5000);
+
+ return () => {
+ if (analysisIntervalRef.current) {
+ clearInterval(analysisIntervalRef.current);
+ }
+ };
+ }, [performAnalysis, isPlaying]);
+
+ return null;
+}
+
+export default Analyzer;
diff --git a/app/src/modules/simulation/human/instances/instance/actions/workerInstance.tsx b/app/src/modules/simulation/human/instances/instance/actions/workerInstance.tsx
index 6711c07..7a41ce9 100644
--- a/app/src/modules/simulation/human/instances/instance/actions/workerInstance.tsx
+++ b/app/src/modules/simulation/human/instances/instance/actions/workerInstance.tsx
@@ -144,6 +144,7 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
setPath(toDrop);
setCurrentPhase(human.modelUuid, "pickup-drop");
setHumanState(human.modelUuid, "running");
+ setHumanActive(human.modelUuid, true);
setCurrentAnimation(human.modelUuid, "walk_with_box", true, true, true);
humanStatus(human.modelUuid, "Started from pickup point, heading to drop point");
}
diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx
index 65fa29b..cefba91 100644
--- a/app/src/modules/simulation/simulation.tsx
+++ b/app/src/modules/simulation/simulation.tsx
@@ -15,12 +15,18 @@ import useModuleStore from "../../store/ui/useModuleStore";
import SimulationAnalysis from "./analysis/simulationAnalysis";
import { useSceneContext } from "../scene/sceneContext";
import HeatMap from "./heatMap/heatMap";
+import Analyzer from "./analyzer/analyzer";
function Simulation() {
const { activeModule } = useModuleStore();
- const { eventStore, productStore } = useSceneContext();
+ const { eventStore, productStore, analysisStore } = useSceneContext();
const { events } = eventStore();
const { products } = productStore();
+ const { analysis } = analysisStore();
+
+ useEffect(() => {
+ console.log("analysis: ", analysis);
+ }, [analysis]);
useEffect(() => {
// console.log('events: ', events);
@@ -58,6 +64,8 @@ function Simulation() {
+
+
diff --git a/app/src/modules/simulation/simulator/functions/generateHeatmapOutput.ts b/app/src/modules/simulation/simulator/functions/generateHeatmapOutput.ts
index 933ca5e..e2357ff 100644
--- a/app/src/modules/simulation/simulator/functions/generateHeatmapOutput.ts
+++ b/app/src/modules/simulation/simulator/functions/generateHeatmapOutput.ts
@@ -93,6 +93,5 @@ export async function generateHeatmapOutput({
})
);
- console.log('fileResults: ', fileResults);
return fileResults;
}
diff --git a/app/src/modules/simulation/simulator/simulationHandler.tsx b/app/src/modules/simulation/simulator/simulationHandler.tsx
index 1cfb70e..4fb5984 100644
--- a/app/src/modules/simulation/simulator/simulationHandler.tsx
+++ b/app/src/modules/simulation/simulator/simulationHandler.tsx
@@ -170,15 +170,14 @@ const SimulationHandler = () => {
width,
height,
version: selectedVersion.versionId,
- download: true,
+ download: false,
}).then((bakedResult) => {
- console.log("bakedResult: ", bakedResult);
heatMapImageApi(
projectId || "",
selectedVersion?.versionId || "",
selectedProduct?.productUuid,
bakedResult
- ).then((img) => console.log("getImg: ", img));
+ );
});
}
}
diff --git a/app/src/pages/Project.tsx b/app/src/pages/Project.tsx
index ed44aa4..a8856fc 100644
--- a/app/src/pages/Project.tsx
+++ b/app/src/pages/Project.tsx
@@ -80,7 +80,6 @@ const Project: React.FC = () => {
if (projectId) {
echo.warn("Validating token");
initializeBuilderSocket(projectId);
- initializeSimulationSocket(projectId);
echo.success("Builder socket initialized");
} else {
navigate("/");
diff --git a/app/src/services/simulation/products/heatMapImageApi.ts b/app/src/services/simulation/products/heatMapImageApi.ts
index c3e9191..19ad9d3 100644
--- a/app/src/services/simulation/products/heatMapImageApi.ts
+++ b/app/src/services/simulation/products/heatMapImageApi.ts
@@ -6,7 +6,6 @@ export const heatMapImageApi = async (
productUuid: string,
heatmaps: any
) => {
- console.log('heatmaps: ', heatmaps);
try {
const response = await fetch(`${url_Backend_dwinzo}/api/V1/SimulatedImage`, {
method: "PATCH",
diff --git a/app/src/store/simulation/useAnalysisStore.ts b/app/src/store/simulation/useAnalysisStore.ts
new file mode 100644
index 0000000..f3d6c31
--- /dev/null
+++ b/app/src/store/simulation/useAnalysisStore.ts
@@ -0,0 +1,131 @@
+import { create } from "zustand";
+import { immer } from "zustand/middleware/immer";
+
+interface AnalysisStore {
+ analysis: AnalysisSchema | null;
+ isAnalyzing: boolean;
+ lastUpdateTime: string | null;
+
+ // Actions
+ setAnalysis: (analysis: AnalysisSchema) => void;
+ updateAssetAnalysis: (assetId: string, assetAnalysis: AssetAnalysis) => void;
+ addHistoricalDataPoint: (assetId: string, dataPoint: any) => void;
+ clearAnalysis: () => void;
+ setAnalyzing: (isAnalyzing: boolean) => void;
+
+ // Getters
+ getAssetAnalysis: (assetId: string) => AssetAnalysis | undefined;
+ getAssetsByType: (assetType: string) => AssetAnalysis[];
+ getBottlenecks: () => any[];
+ getCriticalAssets: () => AssetAnalysis[];
+ getSystemMetrics: () => any;
+}
+
+export const createAnalysisStore = () => {
+ return create()(
+ immer((set, get) => ({
+ analysis: null,
+ isAnalyzing: false,
+ lastUpdateTime: null,
+
+ // Set complete analysis
+ setAnalysis: (analysis: AnalysisSchema) => {
+ set((state) => {
+ state.analysis = analysis;
+ state.lastUpdateTime = new Date().toISOString();
+ });
+ },
+
+ // Update single asset analysis
+ updateAssetAnalysis: (assetId: string, assetAnalysis: AssetAnalysis) => {
+ set((state) => {
+ if (state.analysis) {
+ const index = state.analysis.assets.findIndex((a) => a.assetId === assetId);
+ if (index !== -1) {
+ state.analysis.assets[index] = assetAnalysis;
+ } else {
+ state.analysis.assets.push(assetAnalysis);
+ }
+ state.lastUpdateTime = new Date().toISOString();
+ }
+ });
+ },
+
+ // Add historical data point to asset
+ addHistoricalDataPoint: (assetId: string, dataPoint: any) => {
+ set((state) => {
+ if (state.analysis) {
+ const asset = state.analysis.assets.find((a) => a.assetId === assetId);
+ if (asset) {
+ asset.historicalData.push(dataPoint);
+
+ // Keep only last 1000 data points
+ if (asset.historicalData.length > 1000) {
+ asset.historicalData.shift();
+ }
+ }
+ }
+ });
+ },
+
+ // Clear all analysis
+ clearAnalysis: () => {
+ set((state) => {
+ state.analysis = null;
+ state.lastUpdateTime = null;
+ });
+ },
+
+ // Set analyzing state
+ setAnalyzing: (isAnalyzing: boolean) => {
+ set((state) => {
+ state.isAnalyzing = isAnalyzing;
+ });
+ },
+
+ // Get analysis for specific asset
+ getAssetAnalysis: (assetId: string) => {
+ const state = get();
+ return state.analysis?.assets.find((a) => a.assetId === assetId);
+ },
+
+ // Get all assets of a specific type
+ getAssetsByType: (assetType: string) => {
+ const state = get();
+ return state.analysis?.assets.filter((a) => a.assetType === assetType) || [];
+ },
+
+ // Get bottlenecks
+ getBottlenecks: () => {
+ const state = get();
+ return state.analysis?.materialFlow.bottlenecks || [];
+ },
+
+ // Get critical assets (in error state or low efficiency)
+ getCriticalAssets: () => {
+ const state = get();
+ if (!state.analysis) return [];
+
+ return state.analysis.assets.filter((asset) => {
+ return asset.currentStatus.state === "error" || asset.efficiency.overallEffectiveness < 50;
+ });
+ },
+
+ // Get system-wide metrics summary
+ getSystemMetrics: () => {
+ const state = get();
+ if (!state.analysis) return null;
+
+ return {
+ systemPerformance: state.analysis.systemPerformance,
+ materialFlow: state.analysis.materialFlow,
+ predictiveInsights: state.analysis.predictiveInsights,
+ criticalAssets: get().getCriticalAssets().length,
+ bottlenecks: state.analysis.materialFlow.bottlenecks.length,
+ };
+ },
+ }))
+ );
+};
+
+export type AnalysisStoreType = ReturnType;
diff --git a/app/src/styles/components/simulationDashboard/_simulationDashBoard.scss b/app/src/styles/components/simulationDashboard/_simulationDashBoard.scss
index 84fba4e..73aac03 100644
--- a/app/src/styles/components/simulationDashboard/_simulationDashBoard.scss
+++ b/app/src/styles/components/simulationDashboard/_simulationDashBoard.scss
@@ -10,6 +10,11 @@
position: absolute;
top: 0;
left: 0;
+ pointer-events: none;
+
+ * > {
+ pointer-events: auto;
+ }
.control-panel {
margin-bottom: 20px;
@@ -111,7 +116,6 @@
.element-button-container {
position: relative;
-
}
.element-container {
@@ -261,8 +265,6 @@
padding: 20px;
color: #ffffff;
-
-
background: var(--background-color);
backdrop-filter: blur(20px);
border-radius: 20px;
@@ -294,7 +296,6 @@
}
}
-
&.data-model-panel {
left: 20px;
top: 50px;
@@ -325,9 +326,6 @@
min-width: 300px;
max-height: 84vh;
overflow: auto;
-
-
-
}
}
@@ -344,7 +342,6 @@
justify-content: space-between;
align-items: center;
gap: 6px;
-
}
.form-label {
@@ -536,4 +533,4 @@
background-color: rgba(85, 85, 85, 1);
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/types/simulationTypes.d.ts b/app/src/types/simulationTypes.d.ts
index caca98d..cab572e 100644
--- a/app/src/types/simulationTypes.d.ts
+++ b/app/src/types/simulationTypes.d.ts
@@ -468,3 +468,550 @@ type PillarJibCrane = {
};
type CraneConstraints = PillarJibCrane;
+
+// Analysis Schema Types
+
+// ============================================================================
+// BASE METRIC TYPES
+// ============================================================================
+
+interface TimeMetrics {
+ uptime: number; // Percentage
+ downtime: number; // Total time in seconds
+ utilizationRate: number; // activeTime / totalTime
+ mtbf: number; // Mean Time Between Failures
+ mttr: number; // Mean Time To Repair
+}
+
+interface ThroughputMetrics {
+ itemsPerHour: number;
+ itemsPerDay: number;
+ materialFlowRate: number;
+ capacityUtilization: number; // Percentage
+}
+
+interface EfficiencyMetrics {
+ overallEffectiveness: number; // OEE percentage
+ availability: number; // Percentage
+ performance: number; // Percentage
+ quality: number; // Percentage
+}
+
+interface QualityMetrics {
+ errorRate: number; // Errors per total actions
+ errorFrequency: number; // Errors per time unit
+ successRate: number; // Successful completions percentage
+ stateTransitions: {
+ fromState: string;
+ toState: string;
+ count: number;
+ averageTime: number;
+ }[];
+}
+
+// ============================================================================
+// ASSET-SPECIFIC ANALYSIS
+// ============================================================================
+
+interface ConveyorAnalysis {
+ assetId: string;
+ assetName: string;
+ assetType: "conveyor";
+
+ // Real-time Status
+ currentStatus: {
+ isActive: boolean;
+ isPaused: boolean;
+ state: string;
+ speed: number;
+ currentProduct: string | null;
+ };
+
+ // Time Metrics
+ timeMetrics: TimeMetrics & {
+ idleTime: number;
+ activeTime: number;
+ totalTime: number;
+ };
+
+ // Throughput
+ throughput: ThroughputMetrics & {
+ materialsProcessed: number;
+ averageProcessingTime: number;
+ };
+
+ // Efficiency
+ efficiency: EfficiencyMetrics;
+
+ // Quality
+ quality: QualityMetrics;
+
+ // Historical Data
+ historicalData: {
+ timestamp: string;
+ isActive: boolean;
+ speed: number;
+ materialsCount: number;
+ }[];
+}
+
+interface VehicleAnalysis {
+ assetId: string;
+ assetName: string;
+ assetType: "vehicle";
+
+ // Real-time Status
+ currentStatus: {
+ isActive: boolean;
+ isPicking: boolean;
+ currentPhase: string;
+ state: string;
+ speed: number;
+ currentLoad: number;
+ currentMaterials: { materialType: string; materialId: string }[];
+ };
+
+ // Time Metrics
+ timeMetrics: TimeMetrics & {
+ idleTime: number;
+ activeTime: number;
+ totalTime: number;
+ averageTripTime: number;
+ };
+
+ // Throughput
+ throughput: ThroughputMetrics & {
+ tripsCompleted: number;
+ averageLoadsPerTrip: number;
+ totalLoadsDelivered: number;
+ };
+
+ // Movement Metrics
+ movementMetrics: {
+ distanceTraveled: number;
+ averageSpeedActual: number;
+ fuelEfficiency: number; // Distance per energy unit
+ routeEfficiency: number; // Actual vs optimal distance
+ };
+
+ // Efficiency
+ efficiency: EfficiencyMetrics & {
+ loadUtilization: number; // Average load / max capacity
+ };
+
+ // Quality
+ quality: QualityMetrics;
+
+ // Historical Data
+ historicalData: {
+ timestamp: string;
+ phase: string;
+ load: number;
+ distanceTraveled: number;
+ }[];
+}
+
+interface RoboticArmAnalysis {
+ assetId: string;
+ assetName: string;
+ assetType: "roboticArm";
+
+ // Real-time Status
+ currentStatus: {
+ isActive: boolean;
+ state: string;
+ speed: number;
+ currentAction: {
+ actionUuid: string;
+ actionName: string;
+ materialType: string | null;
+ materialId: string | null;
+ } | null;
+ };
+
+ // Time Metrics
+ timeMetrics: TimeMetrics & {
+ idleTime: number;
+ activeTime: number;
+ totalTime: number;
+ averageCycleTime: number;
+ };
+
+ // Throughput
+ throughput: ThroughputMetrics & {
+ cyclesCompleted: number;
+ pickAndPlaceCount: number;
+ };
+
+ // Efficiency
+ efficiency: EfficiencyMetrics & {
+ cycleTimeEfficiency: number; // Actual vs target cycle time
+ };
+
+ // Quality
+ quality: QualityMetrics & {
+ pickSuccessRate: number;
+ placeAccuracy: number;
+ };
+
+ // Historical Data
+ historicalData: {
+ timestamp: string;
+ cycleTime: number;
+ actionType: string;
+ }[];
+}
+
+interface MachineAnalysis {
+ assetId: string;
+ assetName: string;
+ assetType: "machine";
+
+ // Real-time Status
+ currentStatus: {
+ isActive: boolean;
+ state: string;
+ currentAction: {
+ actionUuid: string;
+ actionName: string;
+ materialType: string | null;
+ materialId: string | null;
+ } | null;
+ };
+
+ // Time Metrics
+ timeMetrics: TimeMetrics & {
+ idleTime: number;
+ activeTime: number;
+ totalTime: number;
+ averageProcessTime: number;
+ };
+
+ // Throughput
+ throughput: ThroughputMetrics & {
+ cyclesCompleted: number;
+ partsProcessed: number;
+ };
+
+ // Efficiency
+ efficiency: EfficiencyMetrics & {
+ targetVsActual: number; // Actual process time vs target
+ };
+
+ // Quality
+ quality: QualityMetrics & {
+ defectRate: number;
+ reworkRate: number;
+ };
+
+ // Historical Data
+ historicalData: {
+ timestamp: string;
+ processTime: number;
+ partsProcessed: number;
+ }[];
+}
+
+interface StorageAnalysis {
+ assetId: string;
+ assetName: string;
+ assetType: "storage";
+
+ // Real-time Status
+ currentStatus: {
+ isActive: boolean;
+ state: string;
+ currentLoad: number;
+ storageCapacity: number;
+ currentMaterials: { materialType: string; materialId: string }[];
+ };
+
+ // Time Metrics
+ timeMetrics: TimeMetrics & {
+ idleTime: number;
+ activeTime: number;
+ totalTime: number;
+ };
+
+ // Capacity Metrics
+ capacityMetrics: {
+ utilizationRate: number; // currentLoad / capacity
+ averageOccupancy: number;
+ peakOccupancy: number;
+ turnoverRate: number; // Store/retrieve frequency
+ };
+
+ // Throughput
+ throughput: ThroughputMetrics & {
+ storeOperations: number;
+ retrieveOperations: number;
+ totalOperations: number;
+ };
+
+ // Efficiency
+ efficiency: EfficiencyMetrics & {
+ spaceUtilization: number;
+ };
+
+ // Quality
+ quality: QualityMetrics;
+
+ // Occupancy Trends
+ occupancyTrends: {
+ timestamp: string;
+ occupancy: number;
+ utilizationRate: number;
+ }[];
+
+ // Historical Data
+ historicalData: {
+ timestamp: string;
+ currentLoad: number;
+ operation: "store" | "retrieve";
+ }[];
+}
+
+interface HumanAnalysis {
+ assetId: string;
+ assetName: string;
+ assetType: "human";
+
+ // Real-time Status
+ currentStatus: {
+ isActive: boolean;
+ isScheduled: boolean;
+ currentPhase: string;
+ state: string;
+ speed: number;
+ currentLoad: number;
+ currentMaterials: { materialType: string; materialId: string }[];
+ currentAction: {
+ actionUuid: string;
+ actionName: string;
+ } | null;
+ };
+
+ // Time Metrics
+ timeMetrics: TimeMetrics & {
+ idleTime: number;
+ activeTime: number;
+ totalTime: number;
+ scheduledTime: number;
+ };
+
+ // Productivity Metrics
+ productivityMetrics: {
+ actionsCompleted: number;
+ actionsPerHour: number;
+ averageActionTime: number;
+ distanceTraveled: number;
+ };
+
+ // Workload Distribution
+ workloadDistribution: {
+ actionType: string;
+ count: number;
+ totalTime: number;
+ percentage: number;
+ }[];
+
+ // Efficiency
+ efficiency: EfficiencyMetrics & {
+ laborProductivity: number; // Output per hour
+ utilizationRate: number; // Active / scheduled time
+ };
+
+ // Quality
+ quality: QualityMetrics;
+
+ // Historical Data
+ historicalData: {
+ timestamp: string;
+ actionType: string;
+ duration: number;
+ distanceTraveled: number;
+ }[];
+}
+
+interface CraneAnalysis {
+ assetId: string;
+ assetName: string;
+ assetType: "crane";
+
+ // Real-time Status
+ currentStatus: {
+ isActive: boolean;
+ isScheduled: boolean;
+ isCarrying: boolean;
+ currentPhase: string;
+ state: string;
+ currentLoad: number;
+ currentMaterials: { materialType: string; materialId: string }[];
+ currentAction: {
+ actionUuid: string;
+ actionName: string;
+ materialType: string | null;
+ materialId: string | null;
+ } | null;
+ };
+
+ // Time Metrics
+ timeMetrics: TimeMetrics & {
+ idleTime: number;
+ activeTime: number;
+ totalTime: number;
+ averageCycleTime: number;
+ };
+
+ // Throughput
+ throughput: ThroughputMetrics & {
+ cyclesCompleted: number;
+ loadsHandled: number;
+ averageLoadsPerCycle: number;
+ };
+
+ // Movement Metrics
+ movementMetrics: {
+ totalLifts: number;
+ averageLiftHeight: number;
+ movementEfficiency: number;
+ };
+
+ // Efficiency
+ efficiency: EfficiencyMetrics & {
+ loadUtilization: number;
+ cycleTimeEfficiency: number;
+ };
+
+ // Quality
+ quality: QualityMetrics & {
+ liftSuccessRate: number;
+ positioningAccuracy: number;
+ };
+
+ // Historical Data
+ historicalData: {
+ timestamp: string;
+ cycleTime: number;
+ loadsHandled: number;
+ }[];
+}
+
+// ============================================================================
+// SYSTEM-WIDE ANALYSIS
+// ============================================================================
+
+interface MaterialFlowAnalysis {
+ totalMaterialsInSystem: number;
+ materialsCompleted: number;
+ averageResidenceTime: number; // Time materials spend in system
+
+ // Queue Analysis
+ queueLengths: {
+ assetId: string;
+ assetName: string;
+ queueLength: number;
+ averageWaitTime: number;
+ }[];
+
+ // Bottleneck Identification
+ bottlenecks: {
+ assetId: string;
+ assetName: string;
+ severity: "critical" | "high" | "medium" | "low";
+ utilizationRate: number;
+ queueLength: number;
+ impactScore: number;
+ }[];
+
+ // Flow Continuity
+ flowContinuity: {
+ overallFlowRate: number;
+ varianceCoefficient: number;
+ steadyStateDeviation: number;
+ };
+}
+
+interface SystemPerformance {
+ overallOEE: number;
+ systemThroughput: number;
+ systemUtilization: number;
+
+ // By Asset Type
+ assetTypePerformance: {
+ assetType: string;
+ count: number;
+ averageOEE: number;
+ averageUtilization: number;
+ totalThroughput: number;
+ }[];
+
+ // Critical Metrics
+ criticalMetrics: {
+ activeAssets: number;
+ totalAssets: number;
+ assetsInError: number;
+ averageIdleTime: number;
+ totalDowntime: number;
+ };
+}
+
+interface PredictiveInsights {
+ maintenanceAlerts: {
+ assetId: string;
+ assetName: string;
+ assetType: string;
+ alertType: "preventive" | "predictive" | "critical";
+ estimatedTimeToFailure: number;
+ confidence: number;
+ recommendation: string;
+ }[];
+
+ optimizationOpportunities: {
+ area: "throughput" | "efficiency" | "quality" | "cost";
+ description: string;
+ potentialImprovement: number;
+ priority: "high" | "medium" | "low";
+ }[];
+
+ trendAnalysis: {
+ metric: string;
+ trend: "increasing" | "decreasing" | "stable";
+ changeRate: number;
+ forecast: number[];
+ }[];
+}
+
+// ============================================================================
+// MAIN ANALYSIS SCHEMA
+// ============================================================================
+
+type AssetAnalysis = ConveyorAnalysis | VehicleAnalysis | RoboticArmAnalysis | MachineAnalysis | StorageAnalysis | HumanAnalysis | CraneAnalysis;
+
+interface AnalysisSchema {
+ // Individual Asset Analysis
+ assets: AssetAnalysis[];
+
+ // System-Wide Metrics
+ systemPerformance: SystemPerformance;
+
+ // Material Flow
+ materialFlow: MaterialFlowAnalysis;
+
+ // Predictive Insights
+ predictiveInsights: PredictiveInsights;
+
+ // Time Range
+ analysisTimeRange: {
+ startTime: string;
+ endTime: string;
+ duration: number;
+ };
+
+ // Metadata
+ metadata: {
+ lastUpdated: string;
+ dataPoints: number;
+ analysisVersion: string;
+ };
+}
diff --git a/package-lock.json b/package-lock.json
deleted file mode 100644
index fd879bc..0000000
--- a/package-lock.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "Dwinzo_Demo",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {}
-}