diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx index 4f96674..046eefa 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx @@ -237,7 +237,7 @@ function ConveyorMechanics() { {activeOption === "spawn" && ( diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx index be50990..0b5b63b 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx @@ -129,7 +129,7 @@ function MachineMechanics() { max={60} defaultValue="1" onChange={handleProcessTimeChange} - swapOptions={["Default material", "Material 1", "Material 2"]} + swapOptions={["Default material", "Material 1", "Material 2", "Material 3"]} swapDefaultOption={currentMaterial} onSwapSelect={handleMaterialSelect} /> diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/trigger/Trigger.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/trigger/Trigger.tsx index f0d2692..3b2bb1a 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/trigger/Trigger.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/trigger/Trigger.tsx @@ -359,7 +359,8 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => { diff --git a/app/src/modules/simulation/actions/conveyor/actionHandler/useSpawnHandler.ts b/app/src/modules/simulation/actions/conveyor/actionHandler/useSpawnHandler.ts index 776b539..20d82bf 100644 --- a/app/src/modules/simulation/actions/conveyor/actionHandler/useSpawnHandler.ts +++ b/app/src/modules/simulation/actions/conveyor/actionHandler/useSpawnHandler.ts @@ -27,7 +27,7 @@ export function useSpawnHandler() { }, []); const spawnLogStatus = (materialUuid: string, status: string) => { - console.log(`${materialUuid}, ${status}`); + // console.log(`${materialUuid}, ${status}`); } const createNewMaterial = useCallback((materialType: string, action: ConveyorAction) => { @@ -51,6 +51,17 @@ export function useSpawnHandler() { cost: 1 }; + if (action.triggers[0].triggeredAsset?.triggeredModel.modelUuid && + action.triggers[0].triggeredAsset?.triggeredPoint?.pointUuid && + action.triggers[0].triggeredAsset?.triggeredAction?.actionUuid + ) { + newMaterial.next = { + modelUuid: action.triggers[0].triggeredAsset?.triggeredModel.modelUuid, + pointUuid: action.triggers[0].triggeredAsset?.triggeredPoint?.pointUuid, + actionUuid: action.triggers[0].triggeredAsset?.triggeredAction?.actionUuid + } + } + addMaterial(newMaterial); return newMaterial; }, [addMaterial]); diff --git a/app/src/modules/simulation/actions/conveyor/useConveyorActions.ts b/app/src/modules/simulation/actions/conveyor/useConveyorActions.ts index a61e3c4..744ff4c 100644 --- a/app/src/modules/simulation/actions/conveyor/useConveyorActions.ts +++ b/app/src/modules/simulation/actions/conveyor/useConveyorActions.ts @@ -5,7 +5,7 @@ export function useConveyorActions() { const { handleSpawn, clearCurrentSpawn } = useSpawnHandler(); const handleDefaultAction = useCallback((action: ConveyorAction) => { - console.log(`Default conveyor action ${action.actionUuid}`); + // console.log(`Default conveyor action ${action.actionUuid}`); }, []); const handleSpawnAction = useCallback((action: ConveyorAction) => { diff --git a/app/src/modules/simulation/actions/useActionHandler.ts b/app/src/modules/simulation/actions/useActionHandler.ts index dbffd69..bf1a41c 100644 --- a/app/src/modules/simulation/actions/useActionHandler.ts +++ b/app/src/modules/simulation/actions/useActionHandler.ts @@ -6,14 +6,12 @@ import { useVehicleActions } from "./vehicle/useVehicleActions"; import { useCallback, useEffect } from "react"; export function useActionHandler() { - // Initialize all action handlers const { handleConveyorAction, cleanup: cleanupConveyor } = useConveyorActions(); const { handleVehicleAction, cleanup: cleanupVehicle } = useVehicleActions(); const { handleRoboticArmAction, cleanup: cleanupRoboticArm } = useRoboticArmActions(); const { handleMachineAction, cleanup: cleanupMachine } = useMachineActions(); const { handleStorageAction, cleanup: cleanupStorage } = useStorageActions(); - // Main handler function const handleAction = useCallback((action: Action) => { if (!action) return; @@ -39,32 +37,17 @@ export function useActionHandler() { } } catch (error) { console.error('Error handling action:', error); - // Consider adding error recovery or notification here } - }, [ - handleConveyorAction, - handleVehicleAction, - handleRoboticArmAction, - handleMachineAction, - handleStorageAction - ]); + }, [handleConveyorAction, handleVehicleAction, handleRoboticArmAction, handleMachineAction, handleStorageAction]); - // Cleanup all actions const cleanup = useCallback(() => { cleanupConveyor(); cleanupVehicle(); cleanupRoboticArm(); cleanupMachine(); cleanupStorage(); - }, [ - cleanupConveyor, - cleanupVehicle, - cleanupRoboticArm, - cleanupMachine, - cleanupStorage - ]); + }, [cleanupConveyor, cleanupVehicle, cleanupRoboticArm, cleanupMachine, cleanupStorage]); - // Auto cleanup on unmount useEffect(() => { return () => { cleanup(); diff --git a/app/src/modules/simulation/materials/instances/animator/materialAnimator.tsx b/app/src/modules/simulation/materials/instances/animator/materialAnimator.tsx index 1445e70..07c0ee0 100644 --- a/app/src/modules/simulation/materials/instances/animator/materialAnimator.tsx +++ b/app/src/modules/simulation/materials/instances/animator/materialAnimator.tsx @@ -1,9 +1,74 @@ -import React from 'react' +import React, { useEffect, useState, useRef } from 'react'; +import * as THREE from 'three'; +import { useFrame, useThree } from '@react-three/fiber'; -function MaterialAnimator() { - return ( - <> - ) +interface MaterialAnimatorProps { + matRef: React.RefObject; + material: MaterialSchema; + speed: number; // units per second + onAnimationComplete?: () => void; } -export default MaterialAnimator \ No newline at end of file +function MaterialAnimator({ + matRef, + material, + speed, + onAnimationComplete +}: MaterialAnimatorProps) { + const { scene } = useThree(); + const [targetPosition, setTargetPosition] = useState(null); + const [isAnimating, setIsAnimating] = useState(false); + const animationStartTime = useRef(0); + const startPosition = useRef(new THREE.Vector3()); + const totalDistance = useRef(0); + + const getWorldPosition = (uuid: string): THREE.Vector3 | null => { + const obj = scene.getObjectByProperty('uuid', uuid); + if (!obj) return null; + const position = new THREE.Vector3(); + obj.getWorldPosition(position); + return position; + }; + + useEffect(() => { + if (!material.next?.pointUuid) { + setTargetPosition(null); + setIsAnimating(false); + return; + } + + const newTarget = getWorldPosition(material.next.pointUuid); + if (newTarget && matRef.current) { + startPosition.current.copy(matRef.current.position); + totalDistance.current = startPosition.current.distanceTo(newTarget); + animationStartTime.current = performance.now(); + setTargetPosition(newTarget); + setIsAnimating(true); + } + }, [material.next?.pointUuid]); + + useFrame(() => { + if (!matRef.current || !targetPosition || !isAnimating) return; + + // Calculate exact position based on constant speed + const elapsed = (performance.now() - animationStartTime.current) / 1000; + const progress = Math.min(1, (speed * elapsed) / totalDistance.current); + + matRef.current.position.lerpVectors( + startPosition.current, + targetPosition, + progress + ); + + // Check if animation is complete + if (progress >= 1) { + matRef.current.position.copy(targetPosition); + setIsAnimating(false); + onAnimationComplete?.(); + } + }); + + return null; +} + +export default React.memo(MaterialAnimator); \ No newline at end of file diff --git a/app/src/modules/simulation/materials/instances/instance/materialInstance.tsx b/app/src/modules/simulation/materials/instances/instance/materialInstance.tsx index 01a5e43..8e2706a 100644 --- a/app/src/modules/simulation/materials/instances/instance/materialInstance.tsx +++ b/app/src/modules/simulation/materials/instances/instance/materialInstance.tsx @@ -1,10 +1,82 @@ -import React, { useEffect, useState } from 'react' +import React, { useEffect, useMemo, useRef, useState } from 'react' import * as THREE from 'three'; -import MaterialAnimator from '../animator/materialAnimator' +import MaterialAnimator from '../animator/materialAnimator'; +import { useProductStore } from '../../../../../store/simulation/useProductStore'; +import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore'; +import { MaterialModel } from '../material/materialModel'; +import { useThree } from '@react-three/fiber'; function MaterialInstance({ material }: { material: MaterialSchema }) { - const [position, setPosition] = useState(); - const [rotation, setRotation] = useState(); + const matRef: any = useRef(); + const { scene } = useThree(); + const { getModelUuidByPointUuid, getPointByUuid, getEventByModelUuid } = useProductStore(); + const { selectedProduct } = useSelectedProduct(); + + const getWorldPositionFromScene = (pointUuid: string): THREE.Vector3 | null => { + const pointObj = scene.getObjectByProperty("uuid", pointUuid); + if (!pointObj) return null; + + const worldPosition = new THREE.Vector3(); + pointObj.getWorldPosition(worldPosition); + return worldPosition; + }; + + const { position, rotation, speed } = useMemo(() => { + if (!material.current?.pointUuid) { + return { position: new THREE.Vector3(0, 0, 0), rotation: new THREE.Vector3(0, 0, 0), speed: 1 }; + } + + const modelUuid = getModelUuidByPointUuid(selectedProduct.productId, material.current.pointUuid); + if (!modelUuid) { + return { position: new THREE.Vector3(0, 0, 0), rotation: new THREE.Vector3(0, 0, 0), speed: 1 }; + } + + const speed = getCurrentSpeed(selectedProduct.productId, modelUuid); + + const point = getPointByUuid(selectedProduct.productId, modelUuid, material.current.pointUuid); + if (!point) { + return { position: new THREE.Vector3(0, 0, 0), rotation: new THREE.Vector3(0, 0, 0), speed: 1 }; + } + + const position = getWorldPositionFromScene(point.uuid); + if (position) { + return { position: position, rotation: new THREE.Vector3(0, 0, 0), speed: 1 }; + } + + return { + position: new THREE.Vector3(...point.position), + rotation: new THREE.Vector3(...point.rotation), + speed: speed || 1 + }; + }, [material, getPointByUuid]); + + function getCurrentSpeed(productId: string, modelUuid: string) { + const event = getEventByModelUuid(productId, modelUuid) + if (event) { + if (event.type === 'transfer') { + return event.speed; + } + + if (event.type === 'vehicle') { + return event.speed; + } + + if (event.type === 'machine') { + return 1; + } + + if (event.type === 'roboticArm') { + return event.speed; + } + + if (event.type === 'storageUnit') { + return 1; + } + + } else { + return 1; + } + } useEffect(() => { // console.log('material: ', material); @@ -13,8 +85,14 @@ function MaterialInstance({ material }: { material: MaterialSchema }) { return ( <> - + + { console.log('123');}} + /> ) } diff --git a/app/src/modules/simulation/materials/instances/material/materialModel.tsx b/app/src/modules/simulation/materials/instances/material/materialModel.tsx new file mode 100644 index 0000000..f27541b --- /dev/null +++ b/app/src/modules/simulation/materials/instances/material/materialModel.tsx @@ -0,0 +1,43 @@ +import { useGLTF } from '@react-three/drei' +import { useMemo } from 'react'; +import * as THREE from 'three'; + +import defaultMaterial from '../../../../../assets/gltf-glb/default.glb'; +import material1 from '../../../../../assets/gltf-glb/material1.glb'; +import material2 from '../../../../../assets/gltf-glb/material2.glb'; +import material3 from '../../../../../assets/gltf-glb/material3.glb'; + +const modelPaths: Record = { + 'Default material': defaultMaterial, + 'Material 1': material1, + 'Material 2': material2, + 'Material 3': material3, +}; + +type ModelType = keyof typeof modelPaths; + +interface ModelProps extends React.ComponentProps<'group'> { + materialType: ModelType; + matRef: React.Ref> +} + +export function MaterialModel({ materialType, matRef, ...props }: ModelProps) { + const path = modelPaths[materialType] || modelPaths['Default material']; + const gltf = useGLTF(path); + const cloned = useMemo(() => gltf?.scene.clone(), [gltf]); + + if (!cloned) return null; + + return ( + + + + ); +} + +Object.values(modelPaths).forEach((path) => { + useGLTF.preload(path); +}); \ No newline at end of file diff --git a/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts b/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts index 6e1f095..e29f9eb 100644 --- a/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts +++ b/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts @@ -1,10 +1,35 @@ -import { useCallback } from 'react'; +import { useCallback, useEffect, useRef } from 'react'; import { useActionHandler } from '../../actions/useActionHandler'; +import { useProductStore } from '../../../../store/simulation/useProductStore'; export function useTriggerHandler() { + const { getActionByUuid } = useProductStore(); + const { handleAction } = useActionHandler(); - const triggerPointActions = useCallback((point: PointsScheme) => { - if (!point) return; + const handleTrigger = (trigger: TriggerSchema) => { + + } + + const triggerPointActions = useCallback((action: Action) => { + if (!action) return; + + action.triggers.forEach(trigger => { + switch (trigger.triggerType) { + case 'onStart': + break; + case 'onComplete': + handleTrigger(trigger); + break; + case 'onStop': + break; + case 'onError': + break; + case 'delay': + break; + default: + console.warn(`Unknown trigger type: ${trigger.triggerType}`); + } + }); }, []); return { diff --git a/app/src/store/simulation/useArmBotStore.ts b/app/src/store/simulation/useArmBotStore.ts index 3c54596..79ad835 100644 --- a/app/src/store/simulation/useArmBotStore.ts +++ b/app/src/store/simulation/useArmBotStore.ts @@ -84,6 +84,7 @@ export const useArmBotStore = create()( armBot.currentAction = { actionUuid: action.actionUuid, actionName: action.actionName, + materialType: null }; } } diff --git a/app/src/store/simulation/useMachineStore.ts b/app/src/store/simulation/useMachineStore.ts index 9a564ac..5754da3 100644 --- a/app/src/store/simulation/useMachineStore.ts +++ b/app/src/store/simulation/useMachineStore.ts @@ -78,6 +78,7 @@ export const useMachineStore = create()( armBot.currentAction = { actionUuid: action.actionUuid, actionName: action.actionName, + materialType: null }; } } diff --git a/app/src/store/simulation/useProductStore.ts b/app/src/store/simulation/useProductStore.ts index 3ed534e..bf99007 100644 --- a/app/src/store/simulation/useProductStore.ts +++ b/app/src/store/simulation/useProductStore.ts @@ -63,6 +63,7 @@ type ProductsStore = { getEventByModelUuid: (productId: string, modelUuid: string) => EventsSchema | undefined; getPointByUuid: (productId: string, modelUuid: string, pointUuid: string) => ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | undefined; getActionByUuid: (productId: string, actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']) | undefined; + getModelUuidByPointUuid: (productId: string, actionUuid: string) => (string) | undefined; getModelUuidByActionUuid: (productId: string, actionUuid: string) => (string) | undefined; getPointUuidByActionUuid: (productId: string, actionUuid: string) => (string) | undefined; getTriggerByUuid: (productId: string, triggerUuid: string) => TriggerSchema | undefined; @@ -575,6 +576,27 @@ export const useProductStore = create()( return undefined; }, + getModelUuidByPointUuid: (productId, pointUuid) => { + const product = get().products.find(p => p.productId === productId); + if (!product) return undefined; + + for (const event of product.eventDatas) { + if ('points' in event) { + for (const point of (event as ConveyorEventSchema).points) { + if (point.uuid === pointUuid) { + return event.modelUuid; + } + } + } else if ('point' in event) { + const point = (event as any).point; + if (point.uuid === pointUuid) { + return event.modelUuid; + } + } + } + return undefined; + }, + getModelUuidByActionUuid: (productId, actionUuid) => { const product = get().products.find(p => p.productId === productId); if (!product) return undefined; diff --git a/app/src/store/simulation/useVehicleStore.ts b/app/src/store/simulation/useVehicleStore.ts index ecef809..63ca0d0 100644 --- a/app/src/store/simulation/useVehicleStore.ts +++ b/app/src/store/simulation/useVehicleStore.ts @@ -2,15 +2,6 @@ import { create } from 'zustand'; import { immer } from 'zustand/middleware/immer'; -interface VehicleStatus extends VehicleEventSchema { - productId: string; - isActive: boolean; - idleTime: number; - activeTime: number; - currentLoad: number; - distanceTraveled: number; -} - interface VehiclesStore { vehicles: VehicleStatus[]; @@ -27,6 +18,7 @@ interface VehiclesStore { incrementVehicleLoad: (modelUuid: string, incrementBy: number) => void; decrementVehicleLoad: (modelUuid: string, decrementBy: number) => void; setVehicleState: (modelUuid: string, newState: VehicleStatus['state']) => void; + setMaterialType: (modelUuid: string, materialType: string | null) => void; incrementActiveTime: (modelUuid: string, incrementBy: number) => void; incrementIdleTime: (modelUuid: string, incrementBy: number) => void; @@ -51,6 +43,7 @@ export const useVehicleStore = create()( idleTime: 0, activeTime: 0, currentLoad: 0, + materialType: null, distanceTraveled: 0, }); } @@ -123,6 +116,15 @@ export const useVehicleStore = create()( }); }, + setMaterialType: (modelUuid, materialType) => { + set((state) => { + const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid); + if (vehicle) { + vehicle.materialType = materialType; + } + }); + }, + incrementActiveTime: (modelUuid, incrementBy) => { set((state) => { const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid); diff --git a/app/src/types/simulationTypes.d.ts b/app/src/types/simulationTypes.d.ts index 3cd7267..f863c1e 100644 --- a/app/src/types/simulationTypes.d.ts +++ b/app/src/types/simulationTypes.d.ts @@ -22,74 +22,35 @@ interface ConveyorPointSchema { uuid: string; position: [number, number, number]; rotation: [number, number, number]; - action: { - actionUuid: string; - actionName: string; - actionType: "default" | "spawn" | "swap" | "delay" | "despawn"; - material: string; - delay: number; - spawnInterval: number; - spawnCount: number; - triggers: TriggerSchema[]; - }; + action: ConveyorAction; } interface VehiclePointSchema { uuid: string; position: [number, number, number]; rotation: [number, number, number]; - action: { - actionUuid: string; - actionName: string; - actionType: "travel"; - unLoadDuration: number; - loadCapacity: number; - steeringAngle: number; - pickUpPoint: { position: { x: number; y: number, z: number }, rotation: { x: number; y: number, z: number } } | null; - unLoadPoint: { position: { x: number; y: number, z: number }, rotation: { x: number; y: number, z: number } } | null; - triggers: TriggerSchema[]; - }; + action: VehicleAction; } interface RoboticArmPointSchema { uuid: string; position: [number, number, number]; rotation: [number, number, number]; - actions: { - actionUuid: string; - actionName: string; - actionType: "pickAndPlace"; - process: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; }; - triggers: TriggerSchema[]; - }[]; + actions: RoboticArmAction[]; } interface MachinePointSchema { uuid: string; position: [number, number, number]; rotation: [number, number, number]; - action: { - actionUuid: string; - actionName: string; - actionType: "process"; - processTime: number; - swapMaterial: string; - triggers: TriggerSchema[]; - }; + action: MachineAction; } interface StoragePointSchema { uuid: string; position: [number, number, number]; rotation: [number, number, number]; - action: { - actionUuid: string; - actionName: string; - actionType: "store"; - materials: { materialName: string; materialId: string; }[]; - storageCapacity: number; - triggers: TriggerSchema[]; - }; + action: StorageAction; } interface ConveyorEventSchema extends AssetEventSchema { @@ -120,92 +81,6 @@ interface StorageEventSchema extends AssetEventSchema { point: StoragePointSchema; } -type PointsScheme = ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema; - -type EventsSchema = ConveyorEventSchema | VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema; - -type productsSchema = { - productName: string; - productId: string; - eventDatas: EventsSchema[]; -}[] - - -interface ConveyorStatus extends ConveyorEventSchema { - productId: string; - isActive: boolean; - idleTime: number; - activeTime: number; - -} - -interface MachineStatus extends MachineEventSchema { - productId: string; - isActive: boolean; - idleTime: number; - activeTime: number; - currentAction?: { - actionUuid: string; - actionName: string; - }; -} - -interface ArmBotStatus extends RoboticArmEventSchema { - productId: string; - isActive: boolean; - idleTime: number; - activeTime: number; - currentAction?: { - actionUuid: string; - actionName: string; - }; -} - -interface VehicleStatus extends VehicleEventSchema { - productId: string; - isActive: boolean; - idleTime: number; - activeTime: number; - currentLoad: number; - distanceTraveled: number; -} - -interface StorageUnitStatus extends StorageEventSchema { - productId: string; - isActive: boolean; - idleTime: number; - activeTime: number; - currentLoad: number; -} - -interface MaterialSchema { - materialId: string; - materialName: stri9ng; - materialType: string; - isActive: boolean; - isVisible: boolean; - isRendered: boolean; - startTime?: string; - endTime?: string; - cost?: number; - weight?: number; - - current: { - modelUuid: string; - pointUuid: string; - actionUuid: string; - }; - - next?: { - modelUuid: string; - pointUuid: string; - actionUuid: string; - }; -} - -type MaterialsSchema = MaterialSchema[]; - - interface ConveyorAction { actionUuid: string; actionName: string; @@ -256,3 +131,90 @@ interface StorageAction { } type Action = ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction; + +type PointsScheme = ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema; + +type EventsSchema = ConveyorEventSchema | VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema; + +type productsSchema = { + productName: string; + productId: string; + eventDatas: EventsSchema[]; +}[] + + +interface ConveyorStatus extends ConveyorEventSchema { + productId: string; + isActive: boolean; + idleTime: number; + activeTime: number; +} + +interface MachineStatus extends MachineEventSchema { + productId: string; + isActive: boolean; + idleTime: number; + activeTime: number; + currentAction?: { + actionUuid: string; + actionName: string; + materialType: string | null; + }; +} + +interface ArmBotStatus extends RoboticArmEventSchema { + productId: string; + isActive: boolean; + idleTime: number; + activeTime: number; + currentAction?: { + actionUuid: string; + actionName: string; + materialType: string | null; + }; +} + +interface VehicleStatus extends VehicleEventSchema { + productId: string; + isActive: boolean; + idleTime: number; + activeTime: number; + currentLoad: number; + materialType: string | null; + distanceTraveled: number; +} + +interface StorageUnitStatus extends StorageEventSchema { + productId: string; + isActive: boolean; + idleTime: number; + activeTime: number; + currentLoad: number; +} + +interface MaterialSchema { + materialId: string; + materialName: stri9ng; + materialType: string; + isActive: boolean; + isVisible: boolean; + isRendered: boolean; + startTime?: string; + endTime?: string; + cost?: number; + weight?: number; + + current: { + modelUuid: string; + pointUuid: string; + actionUuid: string; + }; + + next?: { + modelUuid: string; + pointUuid: string; + actionUuid: string; + }; +} + +type MaterialsSchema = MaterialSchema[]; \ No newline at end of file