diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/components/ActionsList.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/components/ActionsList.tsx index 09017de..8aae3b2 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/components/ActionsList.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/components/ActionsList.tsx @@ -35,7 +35,7 @@ const ActionsList: React.FC = ({ const handleRenameAction = (newName: string) => { if (!selectedAction.actionId) return; - const event = renameAction(selectedAction.actionId, newName); + const event = renameAction(selectedProduct.productId, selectedAction.actionId, newName); if (event) { upsertProductOrEventApi({ 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 f68b6b8..ded65af 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx @@ -72,7 +72,7 @@ function ConveyorMechanics() { const validOption = option as | "default" | "spawn" | "swap" | "delay" | "despawn"; setActiveOption(validOption); - const event = updateAction(selectedPointData.action.actionUuid, { + const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { actionType: validOption, }); @@ -88,7 +88,7 @@ function ConveyorMechanics() { const handleRenameAction = (newName: string) => { if (!selectedEventData || !selectedPointData) return; - const event = updateAction(selectedPointData.action.actionUuid, { actionName: newName }); + const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { actionName: newName }); if (event) { updateBackend( @@ -102,7 +102,7 @@ function ConveyorMechanics() { const handleSpawnCountChange = (value: string) => { if (!selectedEventData || !selectedPointData) return; - const event = updateAction(selectedPointData.action.actionUuid, { + const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { spawnCount: value === "inherit" ? "inherit" : parseFloat(value), }); @@ -118,7 +118,7 @@ function ConveyorMechanics() { const handleSpawnIntervalChange = (value: string) => { if (!selectedEventData || !selectedPointData) return; - const event = updateAction(selectedPointData.action.actionUuid, { + const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { spawnInterval: value === "inherit" ? "inherit" : parseFloat(value), }); @@ -134,7 +134,7 @@ function ConveyorMechanics() { const handleMaterialSelect = (material: string) => { if (!selectedEventData || !selectedPointData) return; - const event = updateAction(selectedPointData.action.actionUuid, { material }); + const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { material }); if (event) { updateBackend( @@ -148,7 +148,7 @@ function ConveyorMechanics() { const handleDelayChange = (value: string) => { if (!selectedEventData || !selectedPointData) return; - const event = updateAction(selectedPointData.action.actionUuid, { + const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { delay: value === "inherit" ? "inherit" : parseFloat(value), }); 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 1a03986..3e11e54 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx @@ -51,7 +51,7 @@ function MachineMechanics() { const validOption = option as "process"; setActiveOption(validOption); - const event = updateAction(selectedPointData.action.actionUuid, { + const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { actionType: validOption, }); @@ -67,19 +67,19 @@ function MachineMechanics() { const handleRenameAction = (newName: string) => { if (!selectedPointData) return; - const event = updateAction(selectedPointData.action.actionUuid, { actionName: newName }); + const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { actionName: newName }); }; const handleProcessTimeChange = (value: string) => { if (!selectedPointData) return; - const event = updateAction(selectedPointData.action.actionUuid, { + const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { processTime: parseFloat(value), }); }; const handleMaterialSelect = (material: string) => { if (!selectedPointData) return; - const event = updateAction(selectedPointData.action.actionUuid, { + const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { swapMaterial: material, }); }; diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx index e56741f..df5c358 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx @@ -59,7 +59,7 @@ function RoboticArmMechanics() { const handleRenameAction = (newName: string) => { if (!selectedAction.actionId) return; - const event = updateAction(selectedAction.actionId, { actionName: newName }); + const event = updateAction(selectedProduct.productId, selectedAction.actionId, { actionName: newName }); if (selectedPointData) { const updatedActions = selectedPointData.actions.map((action) => @@ -101,7 +101,7 @@ function RoboticArmMechanics() { if (!selectedAction.actionId || !selectedPointData) return; const [x, y, z] = value.split(",").map(Number); - const event = updateAction(selectedAction.actionId, { + const event = updateAction(selectedProduct.productId, selectedAction.actionId, { process: { startPoint: [x, y, z] as [number, number, number], endPoint: selectedPointData.actions.find((a) => a.actionUuid === selectedAction.actionId)?.process.endPoint || null, @@ -122,7 +122,7 @@ function RoboticArmMechanics() { if (!selectedAction.actionId || !selectedPointData) return; const [x, y, z] = value.split(",").map(Number); - const event = updateAction(selectedAction.actionId, { + const event = updateAction(selectedProduct.productId, selectedAction.actionId, { process: { startPoint: selectedPointData.actions.find((a) => a.actionUuid === selectedAction.actionId)?.process.startPoint || null, endPoint: [x, y, z] as [number, number, number], @@ -181,7 +181,7 @@ function RoboticArmMechanics() { const handleDeleteAction = (actionUuid: string) => { if (!selectedPointData) return; - const event = removeAction(actionUuid); + const event = removeAction(selectedProduct.productId, actionUuid); if (event) { updateBackend( 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 f782019..3273ce4 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx @@ -51,7 +51,7 @@ function StorageMechanics() { const validOption = option as "store" | "spawn"; setActiveOption(validOption); - const event = updateAction(selectedPointData.action.actionUuid, { + const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { actionType: validOption, }); @@ -67,7 +67,7 @@ function StorageMechanics() { const handleRenameAction = (newName: string) => { if (!selectedPointData) return; - const event = updateAction(selectedPointData.action.actionUuid, { actionName: newName }); + const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { actionName: newName }); if (event) { updateBackend( @@ -81,7 +81,7 @@ function StorageMechanics() { const handleCapacityChange = (value: string) => { if (!selectedPointData) return; - const event = updateAction(selectedPointData.action.actionUuid, { + const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { storageCapacity: parseInt(value), }); diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/vehicleMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/vehicleMechanics.tsx index 35c2821..7839168 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/vehicleMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/vehicleMechanics.tsx @@ -72,7 +72,7 @@ function VehicleMechanics() { const validOption = option as "travel"; setActiveOption(validOption); - const event = updateAction(selectedPointData.action.actionUuid, { + const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { actionType: validOption, }); @@ -88,7 +88,7 @@ function VehicleMechanics() { const handleRenameAction = (newName: string) => { if (!selectedPointData) return; - const event = updateAction(selectedPointData.action.actionUuid, { actionName: newName }); + const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { actionName: newName }); if (event) { updateBackend( @@ -102,7 +102,7 @@ function VehicleMechanics() { const handleLoadCapacityChange = (value: string) => { if (!selectedPointData) return; - const event = updateAction(selectedPointData.action.actionUuid, { + const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { loadCapacity: parseFloat(value), }); @@ -118,7 +118,7 @@ function VehicleMechanics() { const handleUnloadDurationChange = (value: string) => { if (!selectedPointData) return; - const event = updateAction(selectedPointData.action.actionUuid, { + const event = updateAction(selectedProduct.productId, selectedPointData.action.actionUuid, { unLoadDuration: parseFloat(value), }); diff --git a/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts b/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts index 27175ee..ee5c283 100644 --- a/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts +++ b/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts @@ -202,11 +202,11 @@ function processLoadedModel( rotation: [item.eventData.point?.rotation[0] || 0, item.eventData.point?.rotation[1] || 0, item.eventData.point?.rotation[2] || 0], action: { actionUuid: THREE.MathUtils.generateUUID(), - actionName: "Vehicle Action", + actionName: "Action 1", actionType: "travel", unLoadDuration: 5, loadCapacity: 10, - steeringAngle:0, + steeringAngle: 0, pickUpPoint: null, unLoadPoint: null, triggers: [] @@ -254,7 +254,7 @@ function processLoadedModel( rotation: [item.eventData.point?.rotation[0] || 0, item.eventData.point?.rotation[1] || 0, item.eventData.point?.rotation[2] || 0], action: { actionUuid: THREE.MathUtils.generateUUID(), - actionName: "Process Action", + actionName: "Action 1", actionType: "process", processTime: 10, swapMaterial: "material-id", @@ -279,7 +279,7 @@ function processLoadedModel( actions: [ { actionUuid: THREE.MathUtils.generateUUID(), - actionName: "Pick and Place", + actionName: "Action 1", actionType: "pickAndPlace", process: { startPoint: [0, 0, 0], diff --git a/app/src/modules/simulation/products/products.tsx b/app/src/modules/simulation/products/products.tsx index ee1ac42..921dd96 100644 --- a/app/src/modules/simulation/products/products.tsx +++ b/app/src/modules/simulation/products/products.tsx @@ -7,7 +7,7 @@ import { upsertProductOrEventApi } from '../../../services/simulation/UpsertProd import { getAllProductsApi } from '../../../services/simulation/getallProductsApi'; function Products() { - const { products, addProduct, setProducts } = useProductStore(); + const { addProduct, setProducts } = useProductStore(); const { setSelectedProduct } = useSelectedProduct(); useEffect(() => { @@ -27,9 +27,6 @@ function Products() { }) }, []) - useEffect(() => { - }, []) - return ( <> diff --git a/app/src/modules/simulation/triggers/connector/triggerConnector.tsx b/app/src/modules/simulation/triggers/connector/triggerConnector.tsx index 7eb0e81..5f83528 100644 --- a/app/src/modules/simulation/triggers/connector/triggerConnector.tsx +++ b/app/src/modules/simulation/triggers/connector/triggerConnector.tsx @@ -228,7 +228,7 @@ function TriggerConnector() { }; if (firstSelectedPoint.actionUuid) { - const event = addTrigger(firstSelectedPoint.actionUuid, trigger); + const event = addTrigger(selectedProduct.productId, firstSelectedPoint.actionUuid, trigger); if (event) { updateBackend( @@ -285,7 +285,7 @@ function TriggerConnector() { }; if (firstSelectedPoint.actionUuid) { - addTrigger(firstSelectedPoint.actionUuid, trigger); + addTrigger(selectedProduct.productId, firstSelectedPoint.actionUuid, trigger); } setFirstSelectedPoint(null); } @@ -373,9 +373,8 @@ function TriggerConnector() { const removeConnection = (connection: ConnectionLine) => { if (connection.trigger.triggerUuid) { - const event = removeTrigger(connection.trigger.triggerUuid); + const event = removeTrigger(selectedProduct.productId, connection.trigger.triggerUuid); if (event) { - console.log('event: ', event); updateBackend( selectedProduct.productName, selectedProduct.productId, diff --git a/app/src/modules/simulation/vehicle/vehicles.tsx b/app/src/modules/simulation/vehicle/vehicles.tsx index a4d72a1..19f049c 100644 --- a/app/src/modules/simulation/vehicle/vehicles.tsx +++ b/app/src/modules/simulation/vehicle/vehicles.tsx @@ -1,7 +1,6 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect } from "react"; import VehicleInstances from "./instances/vehicleInstances"; import { useVehicleStore } from "../../../store/simulation/useVehicleStore"; -import { useFloorItems } from "../../../store/store"; import { useSelectedEventData, useSelectedEventSphere, useSelectedProduct } from "../../../store/simulation/useSimulationStore"; import VehicleUI from "../ui/vehicle/vehicleUI"; import { usePlayButtonStore } from "../../../store/usePlayButtonStore"; @@ -10,49 +9,38 @@ import { useProductStore } from "../../../store/simulation/useProductStore"; function Vehicles() { const { products, getProductById } = useProductStore(); const { selectedProduct } = useSelectedProduct(); - const { vehicles, addVehicle, removeVehicle } = useVehicleStore(); + const { vehicles, addVehicle, clearvehicles } = useVehicleStore(); const { selectedEventSphere } = useSelectedEventSphere(); const { selectedEventData } = useSelectedEventData(); - const { floorItems } = useFloorItems(); const { isPlaying } = usePlayButtonStore(); useEffect(() => { if (selectedProduct.productId) { const product = getProductById(selectedProduct.productId); if (product) { + clearvehicles(); product.eventDatas.forEach(events => { if (events.type === 'vehicle') { - removeVehicle(events.modelUuid); addVehicle(selectedProduct.productId, events); } }); } } - }, [selectedProduct]); - - // useEffect(() => { - // vehicles.forEach(vehicle => { - // const product = getProductById(vehicle.productId); - // if (product) { - // const eventData = product.eventDatas.find(event => event.modelUuid === vehicle.modelUuid); - // if (eventData) { - // vehicle.eventData = eventData; - // } - // } - // }); - // }, [vehicles, products]); + }, [selectedProduct, products]); useEffect(() => { - // console.log('vehicles: ', vehicles); }, [vehicles]) return ( <> + + {selectedEventSphere && selectedEventData?.data.type === "vehicle" && !isPlaying && < VehicleUI /> } + ); } diff --git a/app/src/modules/visualization/RealTimeVisulization.tsx b/app/src/modules/visualization/RealTimeVisulization.tsx index caf37a1..56e3054 100644 --- a/app/src/modules/visualization/RealTimeVisulization.tsx +++ b/app/src/modules/visualization/RealTimeVisulization.tsx @@ -66,8 +66,7 @@ const RealTimeVisulization: React.FC = () => { const { selectedZone, setSelectedZone } = useSelectedZoneStore(); const { setRightSelect } = useRightSelected(); - const { editWidgetOptions, setEditWidgetOptions } = - useEditWidgetOptionsStore(); + const { editWidgetOptions, setEditWidgetOptions } = useEditWidgetOptionsStore(); const { rightClickSelected, setRightClickSelected } = useRightClickSelected(); const [openConfirmationPopup, setOpenConfirmationPopup] = useState(false); const { setFloatingWidget } = useFloatingWidget(); @@ -76,8 +75,6 @@ const RealTimeVisulization: React.FC = () => { const { setSelectedChartId } = useWidgetStore(); const [waitingPanels, setWaitingPanels] = useState(null); - console.log("waitingPanels: ", waitingPanels); - OuterClick({ contextClassName: [ "chart-container", diff --git a/app/src/store/simulation/useArmBotStore.ts b/app/src/store/simulation/useArmBotStore.ts index 642762f..3c54596 100644 --- a/app/src/store/simulation/useArmBotStore.ts +++ b/app/src/store/simulation/useArmBotStore.ts @@ -10,6 +10,7 @@ interface ArmBotStore { modelUuid: string, updates: Partial> ) => void; + clearArmBots: () => void; addCurrentAction: (modelUuid: string, actionUuid: string) => void; removeCurrentAction: (modelUuid: string) => void; @@ -39,14 +40,17 @@ export const useArmBotStore = create()( addArmBot: (productId, event) => { set((state) => { - state.armBots.push({ - ...event, - productId, - isActive: false, - idleTime: 0, - activeTime: 0, - state: 'idle', - }); + const exists = state.armBots.some(a => a.modelUuid === event.modelUuid); + if (!exists) { + state.armBots.push({ + ...event, + productId, + isActive: false, + idleTime: 0, + activeTime: 0, + state: 'idle', + }); + } }); }, @@ -65,6 +69,12 @@ export const useArmBotStore = create()( }); }, + clearArmBots: () => { + set((state) => { + state.armBots = []; + }); + }, + addCurrentAction: (modelUuid, actionUuid) => { set((state) => { const armBot = state.armBots.find(a => a.modelUuid === modelUuid); diff --git a/app/src/store/simulation/useConveyorStore.ts b/app/src/store/simulation/useConveyorStore.ts index 15dbf34..862ce79 100644 --- a/app/src/store/simulation/useConveyorStore.ts +++ b/app/src/store/simulation/useConveyorStore.ts @@ -10,6 +10,7 @@ interface ConveyorStore { modelUuid: string, updates: Partial> ) => void; + clearConveyors: () => void; setConveyorActive: (modelUuid: string, isActive: boolean) => void; setConveyorState: (modelUuid: string, newState: ConveyorStatus['state']) => void; @@ -30,14 +31,17 @@ export const useConveyorStore = create()( addConveyor: (productId, event) => { set((state) => { - state.conveyors.push({ - ...event, - productId, - isActive: false, - idleTime: 0, - activeTime: 0, - state: 'idle', - }); + const exists = state.conveyors.some(c => c.modelUuid === event.modelUuid); + if (!exists) { + state.conveyors.push({ + ...event, + productId, + isActive: false, + idleTime: 0, + activeTime: 0, + state: 'idle', + }); + } }); }, @@ -56,6 +60,12 @@ export const useConveyorStore = create()( }); }, + clearConveyors: () => { + set((state) => { + state.conveyors = []; + }); + }, + setConveyorActive: (modelUuid, isActive) => { set((state) => { const conveyor = state.conveyors.find(c => c.modelUuid === modelUuid); diff --git a/app/src/store/simulation/useEventsStore.ts b/app/src/store/simulation/useEventsStore.ts index 8fa6838..5580eb1 100644 --- a/app/src/store/simulation/useEventsStore.ts +++ b/app/src/store/simulation/useEventsStore.ts @@ -49,7 +49,9 @@ export const useEventsStore = create()( // Event-level actions addEvent: (event) => { set((state) => { - state.events.push(event); + if (!state.events.some(e => 'modelUuid' in e && e.modelUuid === event.modelUuid)) { + state.events.push(event); + } }); }, @@ -76,9 +78,14 @@ export const useEventsStore = create()( set((state) => { const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid); if (event && 'points' in event) { - (event as ConveyorEventSchema).points.push(point as ConveyorPointSchema); + const existingPoint = (event as ConveyorEventSchema).points.find(p => p.uuid === point.uuid); + if (!existingPoint) { + (event as ConveyorEventSchema).points.push(point as ConveyorPointSchema); + } } else if (event && 'point' in event) { - (event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point = point as any; + if (!(event as any).point || (event as any).point.uuid !== point.uuid) { + (event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point = point as any; + } } }); }, @@ -113,14 +120,15 @@ export const useEventsStore = create()( const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid); if (event && 'points' in event) { const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid); - if (point) { + if (point && (!point.action || point.action.actionUuid !== action.actionUuid)) { point.action = action as any; } } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) { - if ('action' in (event as any).point) { - (event as any).point.action = action; - } else if ('actions' in (event as any).point) { - (event as any).point.actions.push(action); + const point = (event as any).point; + if ('action' in point && (!point.action || point.action.actionUuid !== action.actionUuid)) { + point.action = action; + } else if ('actions' in point && !point.actions.some((a: any) => a.actionUuid === action.actionUuid)) { + point.actions.push(action); } } }); @@ -183,18 +191,22 @@ export const useEventsStore = create()( if ('points' in event) { for (const point of (event as ConveyorEventSchema).points) { if (point.action && point.action.actionUuid === actionUuid) { - point.action.triggers.push(trigger); + if (!point.action.triggers.some(t => t.triggerUuid === trigger.triggerUuid)) { + point.action.triggers.push(trigger); + } return; } } } else if ('point' in event) { - const point = (event as any).point; + const point: MachinePointSchema | VehiclePointSchema = (event as any).point; if ('action' in point && point.action.actionUuid === actionUuid) { - point.action.triggers.push(trigger); + if (!point.action.triggers.some(t => t.triggerUuid === trigger.triggerUuid)) { + point.action.triggers.push(trigger); + } return; } else if ('actions' in point) { - const action = point.actions.find((a: any) => a.actionUuid === actionUuid); - if (action) { + const action = (point as RoboticArmPointSchema).actions.find((a) => a.actionUuid === actionUuid); + if (action && !action.triggers.some(t => t.triggerUuid === trigger.triggerUuid)) { action.triggers.push(trigger); return; } diff --git a/app/src/store/simulation/useMachineStore.ts b/app/src/store/simulation/useMachineStore.ts index af7119c..9a564ac 100644 --- a/app/src/store/simulation/useMachineStore.ts +++ b/app/src/store/simulation/useMachineStore.ts @@ -4,26 +4,23 @@ import { immer } from 'zustand/middleware/immer'; interface MachineStore { machines: MachineStatus[]; - // Actions addMachine: (productId: string, machine: MachineEventSchema) => void; removeMachine: (modelUuid: string) => void; updateMachine: ( modelUuid: string, updates: Partial> ) => void; + clearMachines: () => void; addCurrentAction: (modelUuid: string, actionUuid: string) => void; removeCurrentAction: (modelUuid: string) => void; - // Status updates setMachineActive: (modelUuid: string, isActive: boolean) => void; setMachineState: (modelUuid: string, newState: MachineStatus['state']) => void; - // Time tracking incrementActiveTime: (modelUuid: string, incrementBy: number) => void; incrementIdleTime: (modelUuid: string, incrementBy: number) => void; - // Helpers getMachineById: (modelUuid: string) => MachineStatus | undefined; getMachinesByProduct: (productId: string) => MachineStatus[]; getMachinesBystate: (state: string) => MachineStatus[]; @@ -35,17 +32,19 @@ export const useMachineStore = create()( immer((set, get) => ({ machines: [], - // Actions addMachine: (productId, machine) => { set((state) => { - state.machines.push({ - ...machine, - productId, - isActive: false, - idleTime: 0, - activeTime: 0, - state: 'idle', - }); + const exists = state.machines.some(m => m.modelUuid === machine.modelUuid); + if (!exists) { + state.machines.push({ + ...machine, + productId, + isActive: false, + idleTime: 0, + activeTime: 0, + state: 'idle', + }); + } }); }, @@ -64,6 +63,11 @@ export const useMachineStore = create()( }); }, + clearMachines: () => { + set((state) => { + state.machines = []; + }); + }, addCurrentAction: (modelUuid) => { set((state) => { @@ -89,7 +93,6 @@ export const useMachineStore = create()( }); }, - // Status updates setMachineActive: (modelUuid, isActive) => { set((state) => { const machine = state.machines.find(m => m.modelUuid === modelUuid); @@ -108,7 +111,6 @@ export const useMachineStore = create()( }); }, - // Time tracking incrementActiveTime: (modelUuid, incrementBy) => { set((state) => { const machine = state.machines.find(m => m.modelUuid === modelUuid); @@ -127,7 +129,6 @@ export const useMachineStore = create()( }); }, - // Helpers getMachineById: (modelUuid) => { return get().machines.find(m => m.modelUuid === modelUuid); }, diff --git a/app/src/store/simulation/useProductStore.ts b/app/src/store/simulation/useProductStore.ts index a47bcdb..b7448f2 100644 --- a/app/src/store/simulation/useProductStore.ts +++ b/app/src/store/simulation/useProductStore.ts @@ -33,27 +33,30 @@ type ProductsStore = { pointUuid: string, action: ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] ) => EventsSchema | undefined; - removeAction: (actionUuid: string) => EventsSchema | undefined; + removeAction: (productId: string, actionUuid: string) => EventsSchema | undefined; updateAction: ( + productId: string, actionUuid: string, updates: Partial ) => EventsSchema | undefined; // Trigger-level actions addTrigger: ( + productId: string, actionUuid: string, trigger: TriggerSchema ) => EventsSchema | undefined; - removeTrigger: (triggerUuid: string) => EventsSchema | undefined; + removeTrigger: (productId: string, triggerUuid: string) => EventsSchema | undefined; updateTrigger: ( + productId: string, triggerUuid: string, updates: Partial ) => void; // Renaming functions renameProduct: (productId: string, newName: string) => void; - renameAction: (actionUuid: string, newName: string) => EventsSchema | undefined; - renameTrigger: (triggerUuid: string, newName: string) => void; + renameAction: (productId: string, actionUuid: string, newName: string) => EventsSchema | undefined; + renameTrigger: (productId: string, triggerUuid: string, newName: string) => void; // Helper functions getProductById: (productId: string) => { productName: string; productId: string; eventDatas: EventsSchema[] } | undefined; @@ -71,12 +74,15 @@ export const useProductStore = create()( // Product-level actions addProduct: (productName, productId) => { set((state) => { - const newProduct = { - productName, - productId: productId, - eventDatas: [] - }; - state.products.push(newProduct); + const existingProduct = state.products.find(p => p.productId === productId); + if (!existingProduct) { + const newProduct = { + productName, + productId: productId, + eventDatas: [] + }; + state.products.push(newProduct); + } }); }, @@ -106,7 +112,10 @@ export const useProductStore = create()( set((state) => { const product = state.products.find(p => p.productId === productId); if (product) { - product.eventDatas.push(event); + const existingEvent = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === event.modelUuid); + if (!existingEvent) { + product.eventDatas.push(event); + } } }); }, @@ -120,7 +129,7 @@ export const useProductStore = create()( }); }, - deleteEvent: (modelUuid: string) => { + deleteEvent: (modelUuid) => { set((state) => { for (const product of state.products) { product.eventDatas = product.eventDatas.filter(e => 'modelUuid' in e && e.modelUuid !== modelUuid); @@ -150,9 +159,15 @@ export const useProductStore = create()( if (product) { const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid); if (event && 'points' in event) { - (event as ConveyorEventSchema).points.push(point as ConveyorPointSchema); + const existingPoint = (event as ConveyorEventSchema).points.find(p => p.uuid === point.uuid); + if (!existingPoint) { + (event as ConveyorEventSchema).points.push(point as ConveyorPointSchema); + } } else if (event && 'point' in event) { - (event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point = point as any; + const existingPoint = (event as any).point?.uuid === point.uuid; + if (!existingPoint) { + (event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point = point as any; + } } } }); @@ -198,17 +213,22 @@ export const useProductStore = create()( const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid); if (event && 'points' in event) { const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid); - if (point) { + if (point && (!point.action || point.action.actionUuid !== action.actionUuid)) { point.action = action as any; updatedEvent = JSON.parse(JSON.stringify(event)); } } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) { if ('action' in (event as any).point) { - (event as any).point.action = action; - updatedEvent = JSON.parse(JSON.stringify(event)); + if (!(event as any).point.action || (event as any).point.action.actionUuid !== action.actionUuid) { + (event as any).point.action = action; + updatedEvent = JSON.parse(JSON.stringify(event)); + } } else if ('actions' in (event as any).point) { - (event as any).point.actions.push(action); - updatedEvent = JSON.parse(JSON.stringify(event)); + const existingAction = (event as any).point.actions.find((a: any) => a.actionUuid === action.actionUuid); + if (!existingAction) { + (event as any).point.actions.push(action); + updatedEvent = JSON.parse(JSON.stringify(event)); + } } } } @@ -216,10 +236,11 @@ export const useProductStore = create()( return updatedEvent; }, - removeAction: (actionUuid: string) => { + removeAction: (productId, actionUuid) => { let updatedEvent: EventsSchema | undefined; set((state) => { - for (const product of state.products) { + const product = state.products.find(p => p.productId === productId); + if (product) { for (const event of product.eventDatas) { if ('points' in event) { // Handle ConveyorEventSchema @@ -248,10 +269,11 @@ export const useProductStore = create()( return updatedEvent; }, - updateAction: (actionUuid, updates) => { + updateAction: (productId, actionUuid, updates) => { let updatedEvent: EventsSchema | undefined; set((state) => { - for (const product of state.products) { + const product = state.products.find(p => p.productId === productId); + if (product) { for (const event of product.eventDatas) { if ('points' in event) { for (const point of (event as ConveyorEventSchema).points) { @@ -283,30 +305,40 @@ export const useProductStore = create()( }, // Trigger-level actions - addTrigger: (actionUuid, trigger) => { + addTrigger: (productId, actionUuid, trigger) => { let updatedEvent: EventsSchema | undefined; set((state) => { - for (const product of state.products) { + const product = state.products.find(p => p.productId === productId); + if (product) { for (const event of product.eventDatas) { if ('points' in event) { for (const point of (event as ConveyorEventSchema).points) { if (point.action && point.action.actionUuid === actionUuid) { - point.action.triggers.push(trigger); - updatedEvent = JSON.parse(JSON.stringify(event)); + const existingTrigger = point.action.triggers.find(t => t.triggerUuid === trigger.triggerUuid); + if (!existingTrigger) { + point.action.triggers.push(trigger); + updatedEvent = JSON.parse(JSON.stringify(event)); + } return; } } } else if ('point' in event) { const point = (event as any).point; if ('action' in point && point.action.actionUuid === actionUuid) { - point.action.triggers.push(trigger); - updatedEvent = JSON.parse(JSON.stringify(event)); + const existingTrigger = point.action.triggers.find((t: any) => t.triggerUuid === trigger.triggerUuid); + if (!existingTrigger) { + point.action.triggers.push(trigger); + updatedEvent = JSON.parse(JSON.stringify(event)); + } return; } else if ('actions' in point) { const action = point.actions.find((a: any) => a.actionUuid === actionUuid); if (action) { - action.triggers.push(trigger); - updatedEvent = JSON.parse(JSON.stringify(event)); + const existingTrigger = action.triggers.find((t: any) => t.triggerUuid === trigger.triggerUuid); + if (!existingTrigger) { + action.triggers.push(trigger); + updatedEvent = JSON.parse(JSON.stringify(event)); + } return; } } @@ -317,28 +349,38 @@ export const useProductStore = create()( return updatedEvent; }, - removeTrigger: (triggerUuid) => { + removeTrigger: (productId, triggerUuid) => { let updatedEvent: EventsSchema | undefined; set((state) => { - for (const product of state.products) { + const product = state.products.find(p => p.productId === productId); + if (product) { for (const event of product.eventDatas) { if ('points' in event) { for (const point of (event as ConveyorEventSchema).points) { if (point.action && 'triggers' in point.action) { - point.action.triggers = point.action.triggers.filter(t => t.triggerUuid !== triggerUuid); - updatedEvent = JSON.parse(JSON.stringify(event)); + const Trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid); + if (Trigger) { + point.action.triggers = point.action.triggers.filter(t => t.triggerUuid !== triggerUuid); + updatedEvent = JSON.parse(JSON.stringify(event)); + } } } } else if ('point' in event) { const point = (event as any).point; if ('action' in point && 'triggers' in point.action) { - point.action.triggers = point.action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid); - updatedEvent = JSON.parse(JSON.stringify(event)); + const Trigger = point.action.triggers.find((t: any) => t.triggerUuid === triggerUuid); + if (Trigger) { + point.action.triggers = point.action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid); + updatedEvent = JSON.parse(JSON.stringify(event)); + } } else if ('actions' in point) { for (const action of point.actions) { if ('triggers' in action) { - action.triggers = action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid); - updatedEvent = JSON.parse(JSON.stringify(event)); + const Trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid); + if (Trigger) { + action.triggers = action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid); + updatedEvent = JSON.parse(JSON.stringify(event)); + } } } } @@ -349,9 +391,10 @@ export const useProductStore = create()( return updatedEvent; }, - updateTrigger: (triggerUuid, updates) => { + updateTrigger: (productId, triggerUuid, updates) => { set((state) => { - for (const product of state.products) { + const product = state.products.find(p => p.productId === productId); + if (product) { for (const event of product.eventDatas) { if ('points' in event) { for (const point of (event as ConveyorEventSchema).points) { @@ -398,10 +441,11 @@ export const useProductStore = create()( }); }, - renameAction: (actionUuid, newName) => { + renameAction: (productId, actionUuid, newName) => { let updatedEvent: EventsSchema | undefined; set((state) => { - for (const product of state.products) { + const product = state.products.find(p => p.productId === productId); + if (product) { for (const event of product.eventDatas) { if ('points' in event) { for (const point of (event as ConveyorEventSchema).points) { @@ -432,9 +476,10 @@ export const useProductStore = create()( return updatedEvent; }, - renameTrigger: (triggerUuid, newName) => { + renameTrigger: (productId, triggerUuid, newName) => { set((state) => { - for (const product of state.products) { + const product = state.products.find(p => p.productId === productId); + if (product) { for (const event of product.eventDatas) { if ('points' in event) { for (const point of (event as ConveyorEventSchema).points) { diff --git a/app/src/store/simulation/useStorageUnitStore.ts b/app/src/store/simulation/useStorageUnitStore.ts index d729708..aec2f12 100644 --- a/app/src/store/simulation/useStorageUnitStore.ts +++ b/app/src/store/simulation/useStorageUnitStore.ts @@ -4,26 +4,22 @@ import { immer } from 'zustand/middleware/immer'; interface StorageUnitStore { storageUnits: StorageUnitStatus[]; - // Actions addStorageUnit: (productId: string, storageUnit: StorageEventSchema) => void; removeStorageUnit: (modelUuid: string) => void; updateStorageUnit: ( modelUuid: string, updates: Partial> ) => void; + clearStorageUnits: () => void; - // Status updates setStorageUnitActive: (modelUuid: string, isActive: boolean) => void; setStorageUnitState: (modelUuid: string, newState: StorageUnitStatus['state']) => void; - // Load updates updateStorageUnitLoad: (modelUuid: string, incrementBy: number) => void; - // Time tracking incrementActiveTime: (modelUuid: string, incrementBy: number) => void; incrementIdleTime: (modelUuid: string, incrementBy: number) => void; - // Helpers getStorageUnitById: (modelUuid: string) => StorageUnitStatus | undefined; getStorageUnitsByProduct: (productId: string) => StorageUnitStatus[]; getStorageUnitsBystate: (state: string) => StorageUnitStatus[]; @@ -37,18 +33,20 @@ export const useStorageUnitStore = create()( immer((set, get) => ({ storageUnits: [], - // Actions addStorageUnit: (productId, storageUnit) => { set((state) => { - state.storageUnits.push({ - ...storageUnit, - productId, - isActive: false, - idleTime: 0, - activeTime: 0, - currentLoad: 0, - state: 'idle', - }); + const exists = state.storageUnits.some(s => s.modelUuid === storageUnit.modelUuid); + if (!exists) { + state.storageUnits.push({ + ...storageUnit, + productId, + isActive: false, + idleTime: 0, + activeTime: 0, + currentLoad: 0, + state: 'idle', + }); + } }); }, @@ -67,7 +65,12 @@ export const useStorageUnitStore = create()( }); }, - // Status updates + clearStorageUnits: () => { + set(() => ({ + storageUnits: [], + })); + }, + setStorageUnitActive: (modelUuid, isActive) => { set((state) => { const unit = state.storageUnits.find(s => s.modelUuid === modelUuid); @@ -86,7 +89,6 @@ export const useStorageUnitStore = create()( }); }, - // Load updates updateStorageUnitLoad: (modelUuid, incrementBy) => { set((state) => { const unit = state.storageUnits.find(s => s.modelUuid === modelUuid); @@ -96,7 +98,6 @@ export const useStorageUnitStore = create()( }); }, - // Time tracking incrementActiveTime: (modelUuid, incrementBy) => { set((state) => { const unit = state.storageUnits.find(s => s.modelUuid === modelUuid); @@ -115,7 +116,6 @@ export const useStorageUnitStore = create()( }); }, - // Helpers getStorageUnitById: (modelUuid) => { return get().storageUnits.find(s => s.modelUuid === modelUuid); }, diff --git a/app/src/store/simulation/useVehicleStore.ts b/app/src/store/simulation/useVehicleStore.ts index a5ea3be..ecef809 100644 --- a/app/src/store/simulation/useVehicleStore.ts +++ b/app/src/store/simulation/useVehicleStore.ts @@ -20,6 +20,7 @@ interface VehiclesStore { modelUuid: string, updates: Partial> ) => void; + clearvehicles: () => void; setVehicleActive: (modelUuid: string, isActive: boolean) => void; updateSteeringAngle: (modelUuid: string, steeringAngle: number) => void; @@ -41,15 +42,18 @@ export const useVehicleStore = create()( addVehicle: (productId, event) => { set((state) => { - state.vehicles.push({ - ...event, - productId, - isActive: false, - idleTime: 0, - activeTime: 0, - currentLoad: 0, - distanceTraveled: 0, - }); + const exists = state.vehicles.some(v => v.modelUuid === event.modelUuid); + if (!exists) { + state.vehicles.push({ + ...event, + productId, + isActive: false, + idleTime: 0, + activeTime: 0, + currentLoad: 0, + distanceTraveled: 0, + }); + } }); }, @@ -68,6 +72,12 @@ export const useVehicleStore = create()( }); }, + clearvehicles: () => { + set((state) => { + state.vehicles = []; + }); + }, + setVehicleActive: (modelUuid, isActive) => { 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 346e408..c7ccd8b 100644 --- a/app/src/types/simulationTypes.d.ts +++ b/app/src/types/simulationTypes.d.ts @@ -88,6 +88,7 @@ interface StoragePointSchema { actionType: "store"; materials: { materialName: string; materialId: string; }[]; storageCapacity: number; + triggers: TriggerSchema[]; }; }