From d161b70537456c325a6a8515d276688f8bfe8631 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Tue, 22 Apr 2025 17:24:30 +0530 Subject: [PATCH] feat: Refactor vehicle management and update storage unit load handling; remove unused vehicle component and enhance vehicle status types --- .../users/functions/getAvatarColor.ts | 13 +- .../modules/scene/tools/measurementTool.tsx | 419 +++++++++--------- app/src/modules/simulation/simulation.tsx | 2 + .../instances/animator/vehicleAnimator.tsx | 7 +- .../modules/simulation/vehicle/vehicle.tsx | 14 - .../modules/simulation/vehicle/vehicles.tsx | 133 ++++++ .../widgets/3d/Dropped3dWidget.tsx | 50 +-- .../store/simulation/useStorageUnitStore.ts | 6 +- app/src/store/simulation/useVehicleStore.ts | 5 - app/src/types/simulationTypes.d.ts | 13 +- 10 files changed, 380 insertions(+), 282 deletions(-) delete mode 100644 app/src/modules/simulation/vehicle/vehicle.tsx create mode 100644 app/src/modules/simulation/vehicle/vehicles.tsx diff --git a/app/src/functions/users/functions/getAvatarColor.ts b/app/src/functions/users/functions/getAvatarColor.ts index f2bd816..d9a5d37 100644 --- a/app/src/functions/users/functions/getAvatarColor.ts +++ b/app/src/functions/users/functions/getAvatarColor.ts @@ -25,19 +25,8 @@ const avatarColors: string[] = [ export function getAvatarColor(index: number, name?: string): string { // Check if the color is already stored in localStorage const localStorageKey = "userAvatarColors"; - // Helper function to check if local storage is available - function isLocalStorageAvailable(): boolean { - try { - const testKey = "__test__"; - localStorage.setItem(testKey, "test"); - localStorage.removeItem(testKey); - return true; - } catch (e) { - return false; - } - } // Check if local storage is available - if (isLocalStorageAvailable() && name) { + if (name) { let userColors = JSON.parse(localStorage.getItem(localStorageKey) || "{}"); // Check if the user already has an assigned color diff --git a/app/src/modules/scene/tools/measurementTool.tsx b/app/src/modules/scene/tools/measurementTool.tsx index 9f9fa03..9a30da3 100644 --- a/app/src/modules/scene/tools/measurementTool.tsx +++ b/app/src/modules/scene/tools/measurementTool.tsx @@ -5,240 +5,225 @@ import { useToolMode } from "../../../store/store"; import { Html } from "@react-three/drei"; const MeasurementTool = () => { - const { gl, raycaster, pointer, camera, scene } = useThree(); - const { toolMode } = useToolMode(); + const { gl, raycaster, pointer, camera, scene } = useThree(); + const { toolMode } = useToolMode(); - const [points, setPoints] = useState([]); - const [tubeGeometry, setTubeGeometry] = useState( - null - ); - const groupRef = useRef(null); - const [startConePosition, setStartConePosition] = - useState(null); - const [endConePosition, setEndConePosition] = useState( - null - ); - const [startConeQuaternion, setStartConeQuaternion] = useState( - new THREE.Quaternion() - ); - const [endConeQuaternion, setEndConeQuaternion] = useState( - new THREE.Quaternion() - ); - const [coneSize, setConeSize] = useState({ radius: 0.2, height: 0.5 }); + const [points, setPoints] = useState([]); + const [tubeGeometry, setTubeGeometry] = useState( + null + ); + const groupRef = useRef(null); + const [startConePosition, setStartConePosition] = + useState(null); + const [endConePosition, setEndConePosition] = useState( + null + ); + const [startConeQuaternion, setStartConeQuaternion] = useState( + new THREE.Quaternion() + ); + const [endConeQuaternion, setEndConeQuaternion] = useState( + new THREE.Quaternion() + ); + const [coneSize, setConeSize] = useState({ radius: 0.2, height: 0.5 }); - const MIN_RADIUS = 0.001, - MAX_RADIUS = 0.1; - const MIN_CONE_RADIUS = 0.01, - MAX_CONE_RADIUS = 0.4; - const MIN_CONE_HEIGHT = 0.035, - MAX_CONE_HEIGHT = 2.0; + const MIN_RADIUS = 0.001, MAX_RADIUS = 0.1; + const MIN_CONE_RADIUS = 0.01, MAX_CONE_RADIUS = 0.4; + const MIN_CONE_HEIGHT = 0.035, MAX_CONE_HEIGHT = 2.0; - useEffect(() => { - const canvasElement = gl.domElement; - let drag = false; - let isLeftMouseDown = false; + useEffect(() => { + const canvasElement = gl.domElement; + let drag = false; + let isLeftMouseDown = false; - const onMouseDown = () => { - isLeftMouseDown = true; - drag = false; - }; + const onMouseDown = () => { + isLeftMouseDown = true; + drag = false; + }; - const onMouseUp = (evt: any) => { - isLeftMouseDown = false; - if (evt.button === 0 && !drag) { - raycaster.setFromCamera(pointer, camera); - const intersects = raycaster - .intersectObjects(scene.children, true) - .filter( - (intersect) => - !intersect.object.name.includes("Roof") && - !intersect.object.name.includes("MeasurementReference") && - !intersect.object.name.includes("agv-collider") && - !(intersect.object.type === "GridHelper") - ); + const onMouseUp = (evt: any) => { + isLeftMouseDown = false; + if (evt.button === 0 && !drag) { + raycaster.setFromCamera(pointer, camera); + const intersects = raycaster + .intersectObjects(scene.children, true) + .filter( + (intersect) => + !intersect.object.name.includes("Roof") && + !intersect.object.name.includes("MeasurementReference") && + !intersect.object.name.includes("agv-collider") && + !(intersect.object.type === "GridHelper") + ); - if (intersects.length > 0) { - const intersectionPoint = intersects[0].point.clone(); - if (points.length < 2) { - setPoints([...points, intersectionPoint]); - } else { - setPoints([intersectionPoint]); - } + if (intersects.length > 0) { + const intersectionPoint = intersects[0].point.clone(); + if (points.length < 2) { + setPoints([...points, intersectionPoint]); + } else { + setPoints([intersectionPoint]); + } + } + } + }; + + const onMouseMove = () => { + if (isLeftMouseDown) drag = true; + }; + + const onContextMenu = (evt: any) => { + evt.preventDefault(); + if (!drag) { + evt.preventDefault(); + setPoints([]); + setTubeGeometry(null); + } + }; + + if (toolMode === "MeasurementScale") { + canvasElement.addEventListener("pointerdown", onMouseDown); + canvasElement.addEventListener("pointermove", onMouseMove); + canvasElement.addEventListener("pointerup", onMouseUp); + canvasElement.addEventListener("contextmenu", onContextMenu); + } else { + resetMeasurement(); + setPoints([]); } - } + + return () => { + canvasElement.removeEventListener("pointerdown", onMouseDown); + canvasElement.removeEventListener("pointermove", onMouseMove); + canvasElement.removeEventListener("pointerup", onMouseUp); + canvasElement.removeEventListener("contextmenu", onContextMenu); + }; + }, [toolMode, camera, raycaster, pointer, scene, points]); + + useFrame(() => { + if (points.length === 1) { + raycaster.setFromCamera(pointer, camera); + const intersects = raycaster + .intersectObjects(scene.children, true) + .filter( + (intersect) => + !intersect.object.name.includes("Roof") && + !intersect.object.name.includes("MeasurementReference") && + !intersect.object.name.includes("agv-collider") && + !(intersect.object.type === "GridHelper") + ); + + if (intersects.length > 0) { + updateMeasurement(points[0], intersects[0].point); + } + } else if (points.length === 2) { + updateMeasurement(points[0], points[1]); + } else { + resetMeasurement(); + } + }); + + const updateMeasurement = (start: THREE.Vector3, end: THREE.Vector3) => { + const distance = start.distanceTo(end); + + const radius = THREE.MathUtils.clamp(distance * 0.02, MIN_RADIUS, MAX_RADIUS); + const coneRadius = THREE.MathUtils.clamp(distance * 0.05, MIN_CONE_RADIUS, MAX_CONE_RADIUS); + const coneHeight = THREE.MathUtils.clamp(distance * 0.2, MIN_CONE_HEIGHT, MAX_CONE_HEIGHT); + + setConeSize({ radius: coneRadius, height: coneHeight }); + + const direction = new THREE.Vector3().subVectors(end, start).normalize(); + + const offset = direction.clone().multiplyScalar(coneHeight * 0.5); + + let tubeStart = start.clone().add(offset); + let tubeEnd = end.clone().sub(offset); + + tubeStart.y = Math.max(tubeStart.y, 0); + tubeEnd.y = Math.max(tubeEnd.y, 0); + + const curve = new THREE.CatmullRomCurve3([tubeStart, tubeEnd]); + setTubeGeometry(new THREE.TubeGeometry(curve, 20, radius, 8, false)); + + setStartConePosition(tubeStart); + setEndConePosition(tubeEnd); + setStartConeQuaternion(getArrowOrientation(start, end)); + setEndConeQuaternion(getArrowOrientation(end, start)); }; - const onMouseMove = () => { - if (isLeftMouseDown) drag = true; - }; - - const onContextMenu = (evt: any) => { - evt.preventDefault(); - if (!drag) { - evt.preventDefault(); - setPoints([]); + const resetMeasurement = () => { setTubeGeometry(null); - } + setStartConePosition(null); + setEndConePosition(null); }; - if (toolMode === "MeasurementScale") { - canvasElement.addEventListener("pointerdown", onMouseDown); - canvasElement.addEventListener("pointermove", onMouseMove); - canvasElement.addEventListener("pointerup", onMouseUp); - canvasElement.addEventListener("contextmenu", onContextMenu); - } else { - resetMeasurement(); - setPoints([]); - } - - return () => { - canvasElement.removeEventListener("pointerdown", onMouseDown); - canvasElement.removeEventListener("pointermove", onMouseMove); - canvasElement.removeEventListener("pointerup", onMouseUp); - canvasElement.removeEventListener("contextmenu", onContextMenu); + const getArrowOrientation = (start: THREE.Vector3, end: THREE.Vector3) => { + const direction = new THREE.Vector3() + .subVectors(end, start) + .normalize() + .negate(); + const quaternion = new THREE.Quaternion(); + quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), direction); + return quaternion; }; - }, [toolMode, camera, raycaster, pointer, scene, points]); - useFrame(() => { - if (points.length === 1) { - raycaster.setFromCamera(pointer, camera); - const intersects = raycaster - .intersectObjects(scene.children, true) - .filter( - (intersect) => - !intersect.object.name.includes("Roof") && - !intersect.object.name.includes("MeasurementReference") && - !intersect.object.name.includes("agv-collider") && - !(intersect.object.type === "GridHelper") - ); + useEffect(() => { + if (points.length === 2) { + // console.log(points[0].distanceTo(points[1])); + } + }, [points]); - if (intersects.length > 0) { - updateMeasurement(points[0], intersects[0].point); - } - } else if (points.length === 2) { - updateMeasurement(points[0], points[1]); - } else { - resetMeasurement(); - } - }); + return ( + + {startConePosition && ( + + + + + )} + {endConePosition && ( + + + + + )} + {tubeGeometry && ( + + + + )} - const updateMeasurement = (start: THREE.Vector3, end: THREE.Vector3) => { - const distance = start.distanceTo(end); - - const radius = THREE.MathUtils.clamp( - distance * 0.02, - MIN_RADIUS, - MAX_RADIUS + {startConePosition && endConePosition && ( + +
+ {startConePosition.distanceTo(endConePosition).toFixed(2)} m +
+ + )} +
); - const coneRadius = THREE.MathUtils.clamp( - distance * 0.05, - MIN_CONE_RADIUS, - MAX_CONE_RADIUS - ); - const coneHeight = THREE.MathUtils.clamp( - distance * 0.2, - MIN_CONE_HEIGHT, - MAX_CONE_HEIGHT - ); - - setConeSize({ radius: coneRadius, height: coneHeight }); - - const direction = new THREE.Vector3().subVectors(end, start).normalize(); - - const offset = direction.clone().multiplyScalar(coneHeight * 0.5); - - let tubeStart = start.clone().add(offset); - let tubeEnd = end.clone().sub(offset); - - tubeStart.y = Math.max(tubeStart.y, 0); - tubeEnd.y = Math.max(tubeEnd.y, 0); - - const curve = new THREE.CatmullRomCurve3([tubeStart, tubeEnd]); - setTubeGeometry(new THREE.TubeGeometry(curve, 20, radius, 8, false)); - - setStartConePosition(tubeStart); - setEndConePosition(tubeEnd); - setStartConeQuaternion(getArrowOrientation(start, end)); - setEndConeQuaternion(getArrowOrientation(end, start)); - }; - - const resetMeasurement = () => { - setTubeGeometry(null); - setStartConePosition(null); - setEndConePosition(null); - }; - - const getArrowOrientation = (start: THREE.Vector3, end: THREE.Vector3) => { - const direction = new THREE.Vector3() - .subVectors(end, start) - .normalize() - .negate(); - const quaternion = new THREE.Quaternion(); - quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), direction); - return quaternion; - }; - - useEffect(() => { - if (points.length === 2) { - console.log(points[0].distanceTo(points[1])); - } - }, [points]); - - return ( - - {startConePosition && ( - - - - - )} - {endConePosition && ( - - - - - )} - {tubeGeometry && ( - - - - )} - - {startConePosition && endConePosition && ( - -
- {startConePosition.distanceTo(endConePosition).toFixed(2)} m -
- - )} -
- ); }; export default MeasurementTool; diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx index 3599803..1f30e00 100644 --- a/app/src/modules/simulation/simulation.tsx +++ b/app/src/modules/simulation/simulation.tsx @@ -1,6 +1,7 @@ import React, { useEffect } from 'react'; import { useEventsStore } from '../../store/simulation/useEventsStore'; import { useProductStore } from '../../store/simulation/useProductStore'; +import Vehicles from './vehicle/vehicles'; function Simulation() { const { events } = useEventsStore(); @@ -16,6 +17,7 @@ function Simulation() { return ( <> + ) } diff --git a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx index 92c1d44..14cb6fa 100644 --- a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx +++ b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx @@ -1,9 +1,10 @@ import React from 'react' function VehicleAnimator() { - return ( -
VehicleAnimator
- ) + return ( + <> + + ) } export default VehicleAnimator \ No newline at end of file diff --git a/app/src/modules/simulation/vehicle/vehicle.tsx b/app/src/modules/simulation/vehicle/vehicle.tsx deleted file mode 100644 index e51effc..0000000 --- a/app/src/modules/simulation/vehicle/vehicle.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react' -import VehicleInstances from './instances/vehicleInstances'; - -function Vehicle() { - return ( - <> - - - - - ) -} - -export default Vehicle \ No newline at end of file diff --git a/app/src/modules/simulation/vehicle/vehicles.tsx b/app/src/modules/simulation/vehicle/vehicles.tsx new file mode 100644 index 0000000..7a270d4 --- /dev/null +++ b/app/src/modules/simulation/vehicle/vehicles.tsx @@ -0,0 +1,133 @@ +import React, { useEffect } from 'react' +import VehicleInstances from './instances/vehicleInstances'; + +import { useVehicleStore } from '../../../store/simulation/useVehicleStore'; + +function Vehicles() { + + const { vehicles, addVehicle } = useVehicleStore(); + + const vehicleStatusSample: VehicleStatus[] = [ + { + modelUuid: "veh-123", + modelName: "Autonomous Truck A1", + position: [10, 0, 5], + rotation: [0, 0, 0], + state: "idle", + type: "vehicle", + speed: 2.5, + point: { + uuid: "point-789", + position: [0, 1, 0], + rotation: [0, 0, 0], + action: { + actionUuid: "action-456", + actionName: "Deliver to Zone A", + actionType: "travel", + material: "crate", + unLoadDuration: 15, + loadCapacity: 5, + pickUpPoint: { x: 5, y: 0, z: 3 }, + unLoadPoint: { x: 20, y: 0, z: 10 }, + triggers: [ + { + triggerUuid: "trig-001", + triggerName: "Start Travel", + triggerType: "onComplete", + delay: 0, + triggeredAsset: { + triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" }, + triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" }, + triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" } + } + }, + { + triggerUuid: "trig-002", + triggerName: "Complete Travel", + triggerType: "onComplete", + delay: 2, + triggeredAsset: null + } + ] + } + }, + productId: "prod-890", + isActive: false, + idleTime: 0, + activeTime: 0, + currentLoad: 0, + distanceTraveled: 0 + }, + { + modelUuid: "veh-123", + modelName: "Autonomous Truck A1", + position: [10, 0, 5], + rotation: [0, 0, 0], + state: "idle", + type: "vehicle", + speed: 2.5, + point: { + uuid: "point-789", + position: [0, 1, 0], + rotation: [0, 0, 0], + action: { + actionUuid: "action-456", + actionName: "Deliver to Zone A", + actionType: "travel", + material: "crate", + unLoadDuration: 15, + loadCapacity: 5, + pickUpPoint: { x: 5, y: 0, z: 3 }, + unLoadPoint: { x: 20, y: 0, z: 10 }, + triggers: [ + { + triggerUuid: "trig-001", + triggerName: "Start Travel", + triggerType: "onStart", + delay: 0, + triggeredAsset: { + triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" }, + triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" }, + triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" } + } + }, + { + triggerUuid: "trig-002", + triggerName: "Complete Travel", + triggerType: "onComplete", + delay: 2, + triggeredAsset: null + } + ] + } + }, + productId: "prod-890", + isActive: false, + idleTime: 0, + activeTime: 0, + currentLoad: 0, + distanceTraveled: 0 + } + ]; + + + useEffect(() => { + addVehicle('123', vehicleStatusSample[0]); + addVehicle('123', vehicleStatusSample[1]); + }, []) + + useEffect(() => { + console.log('vehicles: ', vehicles); + }, [vehicles]) + + + return ( + <> + + + + + ) +} + +export default Vehicles; \ No newline at end of file diff --git a/app/src/modules/visualization/widgets/3d/Dropped3dWidget.tsx b/app/src/modules/visualization/widgets/3d/Dropped3dWidget.tsx index d09a88f..4ca3c31 100644 --- a/app/src/modules/visualization/widgets/3d/Dropped3dWidget.tsx +++ b/app/src/modules/visualization/widgets/3d/Dropped3dWidget.tsx @@ -44,7 +44,7 @@ export default function Dropped3dWidgets() { const rotationStartRef = useRef<[number, number, number]>([0, 0, 0]); const mouseStartRef = useRef<{ x: number; y: number }>({ x: 0, y: 0 }); const { setSelectedChartId } = useWidgetStore(); - const { measurements, duration} = useChartStore(); + const { measurements, duration } = useChartStore(); let [floorPlanesVertical, setFloorPlanesVertical] = useState( new THREE.Plane(new THREE.Vector3(0, 1, 0)) ); @@ -117,7 +117,6 @@ export default function Dropped3dWidgets() { !intersect.object.name.includes("Roof") && !intersect.object.name.includes("agv-collider") && !intersect.object.name.includes("MeasurementReference") && - !intersect.object.userData.isPathObject && !(intersect.object.type === "GridHelper") ); @@ -154,7 +153,6 @@ export default function Dropped3dWidgets() { !intersect.object.name.includes("Roof") && !intersect.object.name.includes("agv-collider") && !intersect.object.name.includes("MeasurementReference") && - !intersect.object.userData.isPathObject && !(intersect.object.type === "GridHelper") ); // Update widget's position in memory @@ -169,28 +167,28 @@ export default function Dropped3dWidgets() { const onDrop = (event: any) => { event.preventDefault(); event.stopPropagation(); - + hasEntered.current = false; - + const email = localStorage.getItem("email") || ""; const organization = email?.split("@")[1]?.split(".")[0]; - + const newWidget = createdWidgetRef.current; if (!newWidget || !widgetSelect.startsWith("ui")) return; - + // ✅ Extract 2D drop position let [x, y, z] = newWidget.position; - + // ✅ Clamp Y to at least 0 y = Math.max(y, 0); newWidget.position = [x, y, z]; - + // ✅ Prepare polygon from selectedZone.points const points3D = selectedZone.points as Array<[number, number, number]>; const zonePolygonXZ = points3D.map(([x, , z]) => [x, z] as [number, number]); - + const isInside = isPointInPolygon([x, z], zonePolygonXZ); - + // ✅ Remove temp widget const prevWidgets = useZoneWidgetStore.getState().zoneWidgetData[selectedZone.zoneId] || []; const cleanedWidgets = prevWidgets.filter(w => w.id !== newWidget.id); @@ -200,29 +198,29 @@ export default function Dropped3dWidgets() { [selectedZone.zoneId]: cleanedWidgets, }, })); - + // (Optional) Prevent adding if dropped outside zone // if (!isInside) { // createdWidgetRef.current = null; // return; // } - + // ✅ Add widget addWidget(selectedZone.zoneId, newWidget); - + const add3dWidget = { organization, widget: newWidget, zoneId: selectedZone.zoneId, }; - + if (visualizationSocket) { visualizationSocket.emit("v2:viz-3D-widget:add", add3dWidget); } - + createdWidgetRef.current = null; }; - + canvasElement.addEventListener("dragenter", handleDragEnter); @@ -258,7 +256,7 @@ export default function Dropped3dWidgets() { widgetToDuplicate.position[2] + 0.5, ], rotation: widgetToDuplicate.rotation || [0, 0, 0], - Data:{ + Data: { measurements: measurements, duration: duration }, @@ -365,7 +363,7 @@ export default function Dropped3dWidgets() { // floorPlanesVertical, // planeIntersect.current // ); - + // setintersectcontextmenu(intersect1.y); if (rightSelect === "RotateX" || rightSelect === "RotateY") { @@ -385,7 +383,7 @@ export default function Dropped3dWidgets() { rotationStartRef.current = selectedWidget.rotation || [0, 0, 0]; } } - + }; const handleMouseMove = (event: MouseEvent) => { @@ -429,7 +427,7 @@ export default function Dropped3dWidgets() { intersect.z + horizontalZ, ]; - + updateWidgetPosition(selectedZoneId, rightClickSelected, newPosition); } } @@ -437,24 +435,24 @@ export default function Dropped3dWidgets() { if (rightSelect === "Vertical Move") { const intersect = raycaster.ray.intersectPlane(floorPlanesVertical, planeIntersect.current); - + if (intersect && typeof intersectcontextmenu === "number") { const diff = intersect.y - intersectcontextmenu; const unclampedY = selectedWidget.position[1] + diff; const newY = Math.max(0, unclampedY); // Prevent going below floor (y=0) - + setintersectcontextmenu(intersect.y); - + const newPosition: [number, number, number] = [ selectedWidget.position[0], newY, selectedWidget.position[2], ]; - + updateWidgetPosition(selectedZoneId, rightClickSelected, newPosition); } } - + if (rightSelect?.startsWith("Rotate")) { const axis = rightSelect.slice(-1).toLowerCase(); // "x", "y", or "z" const currentX = event.pageX; diff --git a/app/src/store/simulation/useStorageUnitStore.ts b/app/src/store/simulation/useStorageUnitStore.ts index 52e4185..04b4db0 100644 --- a/app/src/store/simulation/useStorageUnitStore.ts +++ b/app/src/store/simulation/useStorageUnitStore.ts @@ -25,7 +25,7 @@ interface StorageUnitStore { setStorageUnitState: (modelUuid: string, newState: StorageUnitStatus['state']) => void; // Load updates - updateStorageUnitLoad: (modelUuid: string, load: number) => void; + updateStorageUnitLoad: (modelUuid: string, incrementBy: number) => void; // Time tracking incrementActiveTime: (modelUuid: string, incrementBy: number) => void; @@ -95,11 +95,11 @@ export const useStorageUnitStore = create()( }, // Load updates - updateStorageUnitLoad: (modelUuid, load) => { + updateStorageUnitLoad: (modelUuid, incrementBy) => { set((state) => { const unit = state.storageUnits.find(s => s.modelUuid === modelUuid); if (unit) { - unit.currentLoad = load; + unit.currentLoad += incrementBy; } }); }, diff --git a/app/src/store/simulation/useVehicleStore.ts b/app/src/store/simulation/useVehicleStore.ts index 4eba3f5..9f7ac50 100644 --- a/app/src/store/simulation/useVehicleStore.ts +++ b/app/src/store/simulation/useVehicleStore.ts @@ -30,7 +30,6 @@ interface VehiclesStore { getVehiclesByProduct: (productId: string) => VehicleStatus[]; getVehiclesByState: (state: string) => VehicleStatus[]; getActiveVehicles: () => VehicleStatus[]; - getIdleVehicles: () => VehicleStatus[]; } export const useVehicleStore = create()( @@ -125,10 +124,6 @@ export const useVehicleStore = create()( getActiveVehicles: () => { return get().vehicles.filter(v => v.isActive); - }, - - getIdleVehicles: () => { - return get().vehicles.filter(v => !v.isActive && v.currentLoad > 0); } })) ); diff --git a/app/src/types/simulationTypes.d.ts b/app/src/types/simulationTypes.d.ts index 8f0c180..3d75662 100644 --- a/app/src/types/simulationTypes.d.ts +++ b/app/src/types/simulationTypes.d.ts @@ -42,7 +42,7 @@ interface VehiclePointSchema { actionUuid: string; actionName: string; actionType: "travel"; - material: string; + material: string | null; unLoadDuration: number; loadCapacity: number; pickUpPoint: { x: number; y: number, z: number } | null; @@ -125,4 +125,13 @@ type productsSchema = { productName: string; productId: string; eventsData: EventsSchema[]; -}[] \ No newline at end of file +}[] + +interface VehicleStatus extends VehicleEventSchema { + productId: string; + isActive: boolean; + idleTime: number; + activeTime: number; + currentLoad: number; + distanceTraveled: number; +} \ No newline at end of file