Enhance simulation components with time tracking and performance metrics
- Added idle and active time tracking to ConveyorInstance, PillarJibInstance, HumanInstance, RoboticArmInstance, and StorageUnitInstance. - Integrated animation play speed and pause functionality into simulation components. - Updated simulation types to include cost and energy metrics for various analyses. - Improved performance tracking with additional metrics such as load utilization and efficiency calculations.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,8 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
import { useFrame } from "@react-three/fiber";
|
import { useFrame } from "@react-three/fiber";
|
||||||
import { useSceneContext } from "../../../../scene/sceneContext";
|
import { useSceneContext } from "../../../../scene/sceneContext";
|
||||||
|
import { usePauseButtonStore } from "../../../../../store/ui/usePlayButtonStore";
|
||||||
|
import { useAnimationPlaySpeed, usePlayButtonStore } from "../../../../../store/ui/usePlayButtonStore";
|
||||||
|
|
||||||
// import { findConveyorSubsequence } from '../../../simulator/functions/getConveyorSequencesInProduct';
|
// import { findConveyorSubsequence } from '../../../simulator/functions/getConveyorSequencesInProduct';
|
||||||
|
|
||||||
@@ -8,7 +10,70 @@ function ConveyorInstance({ conveyor }: { readonly conveyor: ConveyorStatus }) {
|
|||||||
const { materialStore, conveyorStore, productStore } = useSceneContext();
|
const { materialStore, conveyorStore, productStore } = useSceneContext();
|
||||||
const { getProductById, selectedProduct } = productStore();
|
const { getProductById, selectedProduct } = productStore();
|
||||||
const { getMaterialsByCurrentModelUuid } = materialStore();
|
const { getMaterialsByCurrentModelUuid } = materialStore();
|
||||||
const { setConveyorPaused } = conveyorStore();
|
const { setConveyorPaused, conveyors, incrementActiveTime, incrementIdleTime } = conveyorStore();
|
||||||
|
const { isPlaying } = usePlayButtonStore();
|
||||||
|
|
||||||
|
const idleTimeRef = useRef<number>(0);
|
||||||
|
const activeTimeRef = useRef<number>(0);
|
||||||
|
const previousTimeRef = useRef<number | null>(null);
|
||||||
|
const animationFrameIdRef = useRef<number | null>(null);
|
||||||
|
const isSpeedRef = useRef<number>(0);
|
||||||
|
const isPausedRef = useRef<boolean>(false);
|
||||||
|
|
||||||
|
const { speed } = useAnimationPlaySpeed();
|
||||||
|
const { isPaused } = usePauseButtonStore();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
isPausedRef.current = isPaused;
|
||||||
|
}, [isPaused]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
isSpeedRef.current = speed;
|
||||||
|
}, [speed]);
|
||||||
|
|
||||||
|
function animate(currentTime: number) {
|
||||||
|
if (previousTimeRef.current === null) {
|
||||||
|
previousTimeRef.current = currentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
const deltaTime = (currentTime - previousTimeRef.current) / 1000;
|
||||||
|
previousTimeRef.current = currentTime;
|
||||||
|
|
||||||
|
if (!conveyor.isPaused) {
|
||||||
|
if (!isPausedRef.current) {
|
||||||
|
activeTimeRef.current += deltaTime * isSpeedRef.current;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!isPausedRef.current) {
|
||||||
|
idleTimeRef.current += deltaTime * isSpeedRef.current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
animationFrameIdRef.current = requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isPlaying) return;
|
||||||
|
if (!conveyor.isPaused) {
|
||||||
|
const roundedActiveTime = Math.round(activeTimeRef.current);
|
||||||
|
incrementActiveTime(conveyor.modelUuid, roundedActiveTime);
|
||||||
|
activeTimeRef.current = 0;
|
||||||
|
} else {
|
||||||
|
const roundedIdleTime = Math.round(idleTimeRef.current);
|
||||||
|
incrementIdleTime(conveyor.modelUuid, roundedIdleTime);
|
||||||
|
idleTimeRef.current = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animationFrameIdRef.current === null) {
|
||||||
|
animationFrameIdRef.current = requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (animationFrameIdRef.current !== null) {
|
||||||
|
cancelAnimationFrame(animationFrameIdRef.current);
|
||||||
|
animationFrameIdRef.current = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [conveyor, conveyors, isPlaying]);
|
||||||
|
|
||||||
useFrame(() => {
|
useFrame(() => {
|
||||||
const product = getProductById(selectedProduct.productUuid);
|
const product = getProductById(selectedProduct.productUuid);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { usePlayButtonStore } from "../../../../../store/ui/usePlayButtonStore";
|
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from "../../../../../store/ui/usePlayButtonStore";
|
||||||
import { useSceneContext } from "../../../../scene/sceneContext";
|
import { useSceneContext } from "../../../../scene/sceneContext";
|
||||||
import { useTriggerHandler } from "../../../triggers/triggerHandler/useTriggerHandler";
|
import { useTriggerHandler } from "../../../triggers/triggerHandler/useTriggerHandler";
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ function PillarJibInstance({ crane }: { readonly crane: CraneStatus }) {
|
|||||||
const { craneStore, productStore, humanStore, assetStore } = useSceneContext();
|
const { craneStore, productStore, humanStore, assetStore } = useSceneContext();
|
||||||
const { triggerPointActions } = useTriggerHandler();
|
const { triggerPointActions } = useTriggerHandler();
|
||||||
const { getActionByUuid, selectedProduct } = productStore();
|
const { getActionByUuid, selectedProduct } = productStore();
|
||||||
const { setCurrentPhase, setCraneActive, setIsCaryying, removeCurrentAction, removeLastMaterial, decrementCraneLoad } = craneStore();
|
const { cranes, setCurrentPhase, setCraneActive, setIsCaryying, removeCurrentAction, removeLastMaterial, decrementCraneLoad, incrementActiveTime, incrementIdleTime } = craneStore();
|
||||||
const { setCurrentPhase: setCurrentPhaseHuman, setHumanActive, setHumanState, getHumanById } = humanStore();
|
const { setCurrentPhase: setCurrentPhaseHuman, setHumanActive, setHumanState, getHumanById } = humanStore();
|
||||||
const { setCurrentAnimation, getAssetById } = assetStore();
|
const { setCurrentAnimation, getAssetById } = assetStore();
|
||||||
const [animationPhase, setAnimationPhase] = useState<string>("idle");
|
const [animationPhase, setAnimationPhase] = useState<string>("idle");
|
||||||
@@ -24,6 +24,68 @@ function PillarJibInstance({ crane }: { readonly crane: CraneStatus }) {
|
|||||||
const humanAsset = getAssetById(humanId || "");
|
const humanAsset = getAssetById(humanId || "");
|
||||||
const humanAction = getActionByUuid(selectedProduct.productUuid, actionTriggers?.[0]?.triggeredAsset?.triggeredAction?.actionUuid ?? "");
|
const humanAction = getActionByUuid(selectedProduct.productUuid, actionTriggers?.[0]?.triggeredAsset?.triggeredAction?.actionUuid ?? "");
|
||||||
|
|
||||||
|
const idleTimeRef = useRef<number>(0);
|
||||||
|
const activeTimeRef = useRef<number>(0);
|
||||||
|
const previousTimeRef = useRef<number | null>(null);
|
||||||
|
const animationFrameIdRef = useRef<number | null>(null);
|
||||||
|
const isSpeedRef = useRef<number>(0);
|
||||||
|
const isPausedRef = useRef<boolean>(false);
|
||||||
|
|
||||||
|
const { speed } = useAnimationPlaySpeed();
|
||||||
|
const { isPaused } = usePauseButtonStore();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
isPausedRef.current = isPaused;
|
||||||
|
}, [isPaused]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
isSpeedRef.current = speed;
|
||||||
|
}, [speed]);
|
||||||
|
|
||||||
|
function animate(currentTime: number) {
|
||||||
|
if (previousTimeRef.current === null) {
|
||||||
|
previousTimeRef.current = currentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
const deltaTime = (currentTime - previousTimeRef.current) / 1000;
|
||||||
|
previousTimeRef.current = currentTime;
|
||||||
|
|
||||||
|
if (crane.isActive) {
|
||||||
|
if (!isPausedRef.current) {
|
||||||
|
activeTimeRef.current += deltaTime * isSpeedRef.current;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!isPausedRef.current) {
|
||||||
|
idleTimeRef.current += deltaTime * isSpeedRef.current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
animationFrameIdRef.current = requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isPlaying) return;
|
||||||
|
if (crane.isActive) {
|
||||||
|
const roundedActiveTime = Math.round(activeTimeRef.current);
|
||||||
|
incrementActiveTime(crane.modelUuid, roundedActiveTime);
|
||||||
|
activeTimeRef.current = 0;
|
||||||
|
} else {
|
||||||
|
const roundedIdleTime = Math.round(idleTimeRef.current);
|
||||||
|
incrementIdleTime(crane.modelUuid, roundedIdleTime);
|
||||||
|
idleTimeRef.current = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animationFrameIdRef.current === null) {
|
||||||
|
animationFrameIdRef.current = requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (animationFrameIdRef.current !== null) {
|
||||||
|
cancelAnimationFrame(animationFrameIdRef.current);
|
||||||
|
animationFrameIdRef.current = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [crane, cranes, isPlaying]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isPlaying) {
|
if (isPlaying) {
|
||||||
const human = getHumanById(humanId || "");
|
const human = getHumanById(humanId || "");
|
||||||
@@ -42,7 +104,13 @@ function PillarJibInstance({ crane }: { readonly crane: CraneStatus }) {
|
|||||||
setHumanState(humanId, "running");
|
setHumanState(humanId, "running");
|
||||||
setCurrentAnimation(humanId, "working_standing", true, false, false);
|
setCurrentAnimation(humanId, "working_standing", true, false, false);
|
||||||
}
|
}
|
||||||
} else if (crane.currentPhase === "dropping" && crane.currentMaterials.length > 0 && action.maxPickUpCount <= crane.currentMaterials.length && crane.isCarrying && human.currentPhase === "hooking") {
|
} else if (
|
||||||
|
crane.currentPhase === "dropping" &&
|
||||||
|
crane.currentMaterials.length > 0 &&
|
||||||
|
action.maxPickUpCount <= crane.currentMaterials.length &&
|
||||||
|
crane.isCarrying &&
|
||||||
|
human.currentPhase === "hooking"
|
||||||
|
) {
|
||||||
setCurrentPhaseHuman(humanId, "loadPoint-unloadPoint");
|
setCurrentPhaseHuman(humanId, "loadPoint-unloadPoint");
|
||||||
} else if (human.state === "running" && human.currentPhase === "unhooking") {
|
} else if (human.state === "running" && human.currentPhase === "unhooking") {
|
||||||
if (humanAsset?.animationState?.current === "working_standing" && humanAsset?.animationState?.isCompleted) {
|
if (humanAsset?.animationState?.current === "working_standing" && humanAsset?.animationState?.isCompleted) {
|
||||||
@@ -83,7 +151,15 @@ function PillarJibInstance({ crane }: { readonly crane: CraneStatus }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PillarJibAnimator key={crane.modelUuid} crane={crane} points={points} setPoints={setPoints} animationPhase={animationPhase} setAnimationPhase={setAnimationPhase} onAnimationComplete={handleAnimationComplete} />
|
<PillarJibAnimator
|
||||||
|
key={crane.modelUuid}
|
||||||
|
crane={crane}
|
||||||
|
points={points}
|
||||||
|
setPoints={setPoints}
|
||||||
|
animationPhase={animationPhase}
|
||||||
|
setAnimationPhase={setAnimationPhase}
|
||||||
|
onAnimationComplete={handleAnimationComplete}
|
||||||
|
/>
|
||||||
|
|
||||||
<MaterialAnimator crane={crane} />
|
<MaterialAnimator crane={crane} />
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ function HumanInstance({ human }: { readonly human: HumanStatus }) {
|
|||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
const { humanStore, productStore } = useSceneContext();
|
const { humanStore, productStore } = useSceneContext();
|
||||||
const { getActionByUuid, selectedProduct } = productStore();
|
const { getActionByUuid, selectedProduct } = productStore();
|
||||||
const { incrementIdleTime, incrementActiveTime } = humanStore();
|
const { incrementIdleTime, incrementActiveTime, humans } = humanStore();
|
||||||
|
|
||||||
const idleTimeRef = useRef<number>(0);
|
const idleTimeRef = useRef<number>(0);
|
||||||
const activeTimeRef = useRef<number>(0);
|
const activeTimeRef = useRef<number>(0);
|
||||||
@@ -73,7 +73,7 @@ function HumanInstance({ human }: { readonly human: HumanStatus }) {
|
|||||||
animationFrameIdRef.current = null;
|
animationFrameIdRef.current = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [human, isPlaying]);
|
}, [human, humans, isPlaying]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
|
|||||||
|
|
||||||
const { materialStore, armBotStore, vehicleStore, storageUnitStore, productStore, assetStore } = useSceneContext();
|
const { materialStore, armBotStore, vehicleStore, storageUnitStore, productStore, assetStore } = useSceneContext();
|
||||||
const { resetAsset } = assetStore();
|
const { resetAsset } = assetStore();
|
||||||
const { setArmBotActive, setArmBotState, removeCurrentAction, incrementActiveTime, incrementIdleTime } = armBotStore();
|
const { setArmBotActive, setArmBotState, removeCurrentAction, incrementActiveTime, incrementIdleTime, armBots } = armBotStore();
|
||||||
const { decrementVehicleLoad, removeLastMaterial } = vehicleStore();
|
const { decrementVehicleLoad, removeLastMaterial } = vehicleStore();
|
||||||
const { removeLastMaterial: removeLastStorageMaterial, updateCurrentLoad } = storageUnitStore();
|
const { removeLastMaterial: removeLastStorageMaterial, updateCurrentLoad } = storageUnitStore();
|
||||||
const { getMaterialById, setIsVisible } = materialStore();
|
const { getMaterialById, setIsVisible } = materialStore();
|
||||||
@@ -186,7 +186,7 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
|
|||||||
animationFrameIdRef.current = null; // Reset the animation frame ID
|
animationFrameIdRef.current = null; // Reset the animation frame ID
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [armBot, currentPhase, isPlaying]);
|
}, [armBot, armBots, currentPhase, isPlaying]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const targetBones = ikSolver?.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
|
const targetBones = ikSolver?.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
|
||||||
@@ -320,7 +320,15 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
|
|||||||
{!isReset && isPlaying && (
|
{!isReset && isPlaying && (
|
||||||
<>
|
<>
|
||||||
<IKInstance setIkSolver={setIkSolver} armBot={armBot} />
|
<IKInstance setIkSolver={setIkSolver} armBot={armBot} />
|
||||||
<RoboticArmAnimator HandleCallback={HandleCallback} restPosition={restPosition} ikSolver={ikSolver} targetBone={targetBone} armBot={armBot} path={path} currentPhase={currentPhase} />
|
<RoboticArmAnimator
|
||||||
|
HandleCallback={HandleCallback}
|
||||||
|
restPosition={restPosition}
|
||||||
|
ikSolver={ikSolver}
|
||||||
|
targetBone={targetBone}
|
||||||
|
armBot={armBot}
|
||||||
|
path={path}
|
||||||
|
currentPhase={currentPhase}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<MaterialAnimator ikSolver={ikSolver} armBot={armBot} currentPhase={currentPhase} />
|
<MaterialAnimator ikSolver={ikSolver} armBot={armBot} currentPhase={currentPhase} />
|
||||||
|
|||||||
@@ -1,15 +1,80 @@
|
|||||||
import { useEffect } from 'react'
|
import { useEffect, useRef } from "react";
|
||||||
import MaterialAnimator from '../animator/MaterialAnimator'
|
import MaterialAnimator from "../animator/MaterialAnimator";
|
||||||
|
import { useSceneContext } from "../../../../scene/sceneContext";
|
||||||
|
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from "../../../../../store/ui/usePlayButtonStore";
|
||||||
|
|
||||||
function StorageUnitInstance({ storageUnit }: Readonly<{ storageUnit: StorageUnitStatus }>) {
|
function StorageUnitInstance({ storageUnit }: Readonly<{ storageUnit: StorageUnitStatus }>) {
|
||||||
|
const { storageUnitStore } = useSceneContext();
|
||||||
|
const { storageUnits, incrementActiveTime, incrementIdleTime } = storageUnitStore();
|
||||||
|
const { isPlaying } = usePlayButtonStore();
|
||||||
|
|
||||||
|
const idleTimeRef = useRef<number>(0);
|
||||||
|
const activeTimeRef = useRef<number>(0);
|
||||||
|
const previousTimeRef = useRef<number | null>(null);
|
||||||
|
const animationFrameIdRef = useRef<number | null>(null);
|
||||||
|
const isSpeedRef = useRef<number>(0);
|
||||||
|
const isPausedRef = useRef<boolean>(false);
|
||||||
|
|
||||||
|
const { speed } = useAnimationPlaySpeed();
|
||||||
|
const { isPaused } = usePauseButtonStore();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
isPausedRef.current = isPaused;
|
||||||
|
}, [isPaused]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
isSpeedRef.current = speed;
|
||||||
|
}, [speed]);
|
||||||
|
|
||||||
|
function animate(currentTime: number) {
|
||||||
|
if (previousTimeRef.current === null) {
|
||||||
|
previousTimeRef.current = currentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
const deltaTime = (currentTime - previousTimeRef.current) / 1000;
|
||||||
|
previousTimeRef.current = currentTime;
|
||||||
|
|
||||||
|
if (storageUnit.isActive) {
|
||||||
|
if (!isPausedRef.current) {
|
||||||
|
activeTimeRef.current += deltaTime * isSpeedRef.current;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!isPausedRef.current) {
|
||||||
|
idleTimeRef.current += deltaTime * isSpeedRef.current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
animationFrameIdRef.current = requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isPlaying) return;
|
||||||
|
if (storageUnit.isActive) {
|
||||||
|
const roundedActiveTime = Math.round(activeTimeRef.current);
|
||||||
|
incrementActiveTime(storageUnit.modelUuid, roundedActiveTime);
|
||||||
|
activeTimeRef.current = 0;
|
||||||
|
} else {
|
||||||
|
const roundedIdleTime = Math.round(idleTimeRef.current);
|
||||||
|
incrementIdleTime(storageUnit.modelUuid, roundedIdleTime);
|
||||||
|
idleTimeRef.current = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animationFrameIdRef.current === null) {
|
||||||
|
animationFrameIdRef.current = requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (animationFrameIdRef.current !== null) {
|
||||||
|
cancelAnimationFrame(animationFrameIdRef.current);
|
||||||
|
animationFrameIdRef.current = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [storageUnit, storageUnits, isPlaying]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// console.log('storageUnit: ', storageUnit);
|
// console.log('storageUnit: ', storageUnit);
|
||||||
}, [storageUnit])
|
}, [storageUnit]);
|
||||||
|
|
||||||
return (
|
return <MaterialAnimator storage={storageUnit} />;
|
||||||
<MaterialAnimator storage={storageUnit} />
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default StorageUnitInstance
|
export default StorageUnitInstance;
|
||||||
|
|||||||
66
app/src/types/simulationTypes.d.ts
vendored
66
app/src/types/simulationTypes.d.ts
vendored
@@ -736,6 +736,14 @@ interface RoboticArmAnalysis {
|
|||||||
placeAccuracy: number;
|
placeAccuracy: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Cost
|
||||||
|
costMetrics: CostMetrics;
|
||||||
|
|
||||||
|
// Energy
|
||||||
|
energyMetrics: EnergyMetrics & {
|
||||||
|
energyPerUnit: number; // Energy per item processed
|
||||||
|
};
|
||||||
|
|
||||||
// Historical Data
|
// Historical Data
|
||||||
historicalData: {
|
historicalData: {
|
||||||
timestamp: string;
|
timestamp: string;
|
||||||
@@ -784,6 +792,17 @@ interface MachineAnalysis {
|
|||||||
quality: QualityMetrics & {
|
quality: QualityMetrics & {
|
||||||
defectRate: number;
|
defectRate: number;
|
||||||
reworkRate: number;
|
reworkRate: number;
|
||||||
|
scrapRate: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cost
|
||||||
|
costMetrics: CostMetrics & {
|
||||||
|
costPerUnit: number; // Cost per item processed
|
||||||
|
};
|
||||||
|
|
||||||
|
// Energy
|
||||||
|
energyMetrics: EnergyMetrics & {
|
||||||
|
energyPerUnit: number; // Energy per item processed
|
||||||
};
|
};
|
||||||
|
|
||||||
// Historical Data
|
// Historical Data
|
||||||
@@ -821,6 +840,7 @@ interface StorageAnalysis {
|
|||||||
averageOccupancy: number;
|
averageOccupancy: number;
|
||||||
peakOccupancy: number;
|
peakOccupancy: number;
|
||||||
turnoverRate: number; // Store/retrieve frequency
|
turnoverRate: number; // Store/retrieve frequency
|
||||||
|
occupancyTrend: number; // Change in occupancy over time
|
||||||
};
|
};
|
||||||
|
|
||||||
// Throughput
|
// Throughput
|
||||||
@@ -838,6 +858,17 @@ interface StorageAnalysis {
|
|||||||
// Quality
|
// Quality
|
||||||
quality: QualityMetrics;
|
quality: QualityMetrics;
|
||||||
|
|
||||||
|
// Cost
|
||||||
|
costMetrics: CostMetrics & {
|
||||||
|
costPerUnit: number; // Cost per item processed
|
||||||
|
costPerStorageHour: number; // Cost per hour of storage
|
||||||
|
};
|
||||||
|
|
||||||
|
// Energy
|
||||||
|
energyMetrics: EnergyMetrics & {
|
||||||
|
energyPerUnit: number; // Energy per item processed
|
||||||
|
};
|
||||||
|
|
||||||
// Occupancy Trends
|
// Occupancy Trends
|
||||||
occupancyTrends: {
|
occupancyTrends: {
|
||||||
timestamp: string;
|
timestamp: string;
|
||||||
@@ -871,6 +902,7 @@ interface HumanAnalysis {
|
|||||||
actionUuid: string;
|
actionUuid: string;
|
||||||
actionName: string;
|
actionName: string;
|
||||||
} | null;
|
} | null;
|
||||||
|
loadUtilization: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Time Metrics
|
// Time Metrics
|
||||||
@@ -887,6 +919,8 @@ interface HumanAnalysis {
|
|||||||
actionsPerHour: number;
|
actionsPerHour: number;
|
||||||
averageActionTime: number;
|
averageActionTime: number;
|
||||||
distanceTraveled: number;
|
distanceTraveled: number;
|
||||||
|
averageSpeed: number;
|
||||||
|
loadEfficiency: number; // Current load / max capacity
|
||||||
};
|
};
|
||||||
|
|
||||||
// Workload Distribution
|
// Workload Distribution
|
||||||
@@ -906,6 +940,17 @@ interface HumanAnalysis {
|
|||||||
// Quality
|
// Quality
|
||||||
quality: QualityMetrics;
|
quality: QualityMetrics;
|
||||||
|
|
||||||
|
// Cost
|
||||||
|
costMetrics: CostMetrics & {
|
||||||
|
costPerAction: number; // Cost per action performed
|
||||||
|
costPerHour: number; // Cost per hour of labor
|
||||||
|
};
|
||||||
|
|
||||||
|
// Energy
|
||||||
|
energyMetrics: EnergyMetrics & {
|
||||||
|
energyPerAction: number; // Energy per action performed
|
||||||
|
};
|
||||||
|
|
||||||
// Historical Data
|
// Historical Data
|
||||||
historicalData: {
|
historicalData: {
|
||||||
timestamp: string;
|
timestamp: string;
|
||||||
@@ -935,6 +980,7 @@ interface CraneAnalysis {
|
|||||||
materialType: string | null;
|
materialType: string | null;
|
||||||
materialId: string | null;
|
materialId: string | null;
|
||||||
} | null;
|
} | null;
|
||||||
|
loadUtilization: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Time Metrics
|
// Time Metrics
|
||||||
@@ -957,6 +1003,8 @@ interface CraneAnalysis {
|
|||||||
totalLifts: number;
|
totalLifts: number;
|
||||||
averageLiftHeight: number;
|
averageLiftHeight: number;
|
||||||
movementEfficiency: number;
|
movementEfficiency: number;
|
||||||
|
loadEfficiency: number;
|
||||||
|
cycleEfficiency: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Efficiency
|
// Efficiency
|
||||||
@@ -971,6 +1019,17 @@ interface CraneAnalysis {
|
|||||||
positioningAccuracy: number;
|
positioningAccuracy: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Cost
|
||||||
|
costMetrics: CostMetrics & {
|
||||||
|
costPerLift: number; // Cost per lift operation
|
||||||
|
costPerCycle: number; // Cost per operational cycle
|
||||||
|
};
|
||||||
|
|
||||||
|
// Energy
|
||||||
|
energyMetrics: EnergyMetrics & {
|
||||||
|
energyPerLift: number; // Energy per lift operation
|
||||||
|
};
|
||||||
|
|
||||||
// Historical Data
|
// Historical Data
|
||||||
historicalData: {
|
historicalData: {
|
||||||
timestamp: string;
|
timestamp: string;
|
||||||
@@ -1033,8 +1092,10 @@ interface SystemPerformance {
|
|||||||
activeAssets: number;
|
activeAssets: number;
|
||||||
totalAssets: number;
|
totalAssets: number;
|
||||||
assetsInError: number;
|
assetsInError: number;
|
||||||
|
assetsIdle: number;
|
||||||
averageIdleTime: number;
|
averageIdleTime: number;
|
||||||
totalDowntime: number;
|
totalDowntime: number;
|
||||||
|
systemUptime: number;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1095,5 +1156,10 @@ interface AnalysisSchema {
|
|||||||
lastUpdated: string;
|
lastUpdated: string;
|
||||||
dataPoints: number;
|
dataPoints: number;
|
||||||
analysisVersion: string;
|
analysisVersion: string;
|
||||||
|
totalCost: number;
|
||||||
|
totalValueAdded: number;
|
||||||
|
totalEnergyConsumed: number;
|
||||||
|
energyCost: number;
|
||||||
|
carbonFootprint: number;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user