diff --git a/app/src/modules/simulation/machine/eventManager/useMachineEventManager.ts b/app/src/modules/simulation/machine/eventManager/useMachineEventManager.ts new file mode 100644 index 0000000..e6edaf3 --- /dev/null +++ b/app/src/modules/simulation/machine/eventManager/useMachineEventManager.ts @@ -0,0 +1,65 @@ +import { useEffect, useRef } from 'react'; +import { useFrame } from '@react-three/fiber'; +import { useMachineStore } from '../../../../store/simulation/useMachineStore'; + +type MachineCallback = { + machineId: string; + callback: () => void; +}; + +export function useMachineEventManager() { + const { getMachineById } = useMachineStore(); + const callbacksRef = useRef([]); + const isMonitoringRef = useRef(false); + + // Add a new machine to monitor + const addMachineToMonitor = (machineId: string, callback: () => void) => { + // Avoid duplicates + if (!callbacksRef.current.some((entry) => entry.machineId === machineId)) { + callbacksRef.current.push({ machineId, callback }); + } + + // Start monitoring if not already running + if (!isMonitoringRef.current) { + isMonitoringRef.current = true; + } + }; + + // Remove a machine from monitoring + const removeMachineFromMonitor = (machineId: string) => { + callbacksRef.current = callbacksRef.current.filter( + (entry) => entry.machineId !== machineId + ); + + // Stop monitoring if no more machines to track + if (callbacksRef.current.length === 0) { + isMonitoringRef.current = false; + } + }; + + // Check machine states every frame + useFrame(() => { + if (!isMonitoringRef.current || callbacksRef.current.length === 0) return; + + callbacksRef.current.forEach(({ machineId, callback }) => { + const machine = getMachineById(machineId); + if (machine && machine.isActive === false && machine.state === 'idle' && !machine.currentAction) { + callback(); + removeMachineFromMonitor(machineId); // Remove after triggering + } + }); + }); + + // Cleanup on unmount + useEffect(() => { + return () => { + callbacksRef.current = []; + isMonitoringRef.current = false; + }; + }, []); + + return { + addMachineToMonitor, + removeMachineFromMonitor, + }; +} \ 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 67fecdb..a5d5372 100644 --- a/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts +++ b/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts @@ -10,6 +10,8 @@ import { useStorageUnitStore } from '../../../../store/simulation/useStorageUnit import { useArmBotEventManager } from '../../roboticArm/eventManager/useArmBotEventManager'; import { useConveyorStore } from '../../../../store/simulation/useConveyorStore'; import { useConveyorEventManager } from '../../conveyor/eventManager/useConveyorEventManager'; +import { useVehicleEventManager } from '../../vehicle/instances/eventManager/useVehicleEventManager'; +import { useMachineEventManager } from '../../machine/eventManager/useMachineEventManager'; export function useTriggerHandler() { const { handleAction } = useActionHandler(); @@ -19,6 +21,8 @@ export function useTriggerHandler() { const { getConveyorById } = useConveyorStore(); const { addArmBotToMonitor } = useArmBotEventManager(); const { addConveyorToMonitor } = useConveyorEventManager(); + const { addVehicleToMonitor } = useVehicleEventManager(); + const { addMachineToMonitor } = useMachineEventManager(); const { getVehicleById } = useVehicleStore(); const { getMachineById } = useMachineStore(); const { getStorageUnitById } = useStorageUnitStore(); @@ -89,7 +93,7 @@ export function useTriggerHandler() { if (vehicle) { - if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.currentLoad < vehicle.point.action.loadCapacity) { + if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) { setIsVisible(materialId, false); @@ -98,8 +102,10 @@ export function useTriggerHandler() { } else { - // Event Manager Needed - + // Handle current action using Event Manager + addVehicleToMonitor(vehicle.modelUuid, () => { + handleAction(action, materialId); + }) } } } @@ -140,21 +146,110 @@ export function useTriggerHandler() { if (action) { if (armBot) { + if (action && action.triggers.length > 0 && + action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid && + action.triggers[0]?.triggeredAsset?.triggeredAction?.actionUuid && + action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid) { + const model = getEventByModelUuid(selectedProduct.productId, action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid); - if (armBot.isActive === false && armBot.state === 'idle') { + if (model?.type === 'vehicle') { + const vehicle = getVehicleById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid); + if (vehicle) { + if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) { + // Handle current action from vehicle + setIsPaused(materialId, true); + handleAction(action, materialId); - // Handle current action from arm bot - setIsPaused(materialId, true); - handleAction(action, materialId); + } else { + // Handle current action using Event Manager + setIsPaused(materialId, true); + + addVehicleToMonitor(vehicle.modelUuid, + () => { + handleAction(action, materialId); + } + ) + } + } + } else if (model?.type === 'machine') { + const armBot = getArmBotById(trigger.triggeredAsset?.triggeredModel.modelUuid); + if (armBot) { + if (armBot.isActive === false && armBot.state === 'idle') { + const machine = getMachineById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid); + if (machine) { + if (machine.isActive === false && machine.state === 'idle' && !machine.currentAction) { + setIsPaused(materialId, true); + handleAction(action, materialId); + } else { + + // Handle current action using Event Manager + setIsPaused(materialId, true); + + addMachineToMonitor(machine.modelUuid, + () => { + handleAction(action, materialId); + } + ) + } + } + } else { + addArmBotToMonitor(armBot.modelUuid, + () => { + const machine = getMachineById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || ''); + if (machine) { + if (machine.isActive === false && machine.state === 'idle' && !machine.currentAction) { + setIsPaused(materialId, true); + handleAction(action, materialId); + } else { + + // Handle current action using Event Manager + setIsPaused(materialId, true); + + addMachineToMonitor(machine.modelUuid, + () => { + handleAction(action, materialId); + } + ) + } + } + } + ); + } + } + } else { + if (armBot.isActive === false && armBot.state === 'idle') { + + // Handle current action from arm bot + setIsPaused(materialId, true); + handleAction(action, materialId); + + } else { + + // Handle current action using Event Manager + setIsPaused(materialId, true); + addArmBotToMonitor(armBot.modelUuid, + () => handleAction(action, materialId) + ); + + } + } } else { + if (armBot.isActive === false && armBot.state === 'idle') { - // Event Manager Needed - setIsPaused(materialId, true); - addArmBotToMonitor(armBot.modelUuid, - () => handleAction(action, materialId) - ); + // Handle current action from arm bot + setIsPaused(materialId, true); + handleAction(action, materialId); + } else { + + // Handle current action using Event Manager + setIsPaused(materialId, true); + addArmBotToMonitor(armBot.modelUuid, + () => handleAction(action, materialId) + ); + + } } } } @@ -334,11 +429,20 @@ export function useTriggerHandler() { if (model?.type === 'transfer') { const conveyor = getConveyorById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || ''); if (conveyor) { - addConveyorToMonitor(conveyor.modelUuid, - () => { + const previousModel = getEventByModelUuid(selectedProduct.productId, material.previous?.modelUuid || ''); + if (previousModel) { + if (previousModel.type === 'transfer' && previousModel.modelUuid === model.modelUuid) { handleAction(action, materialId) + } else { + addConveyorToMonitor(conveyor.modelUuid, + () => { + handleAction(action, materialId) + } + ) } - ) + } else { + handleAction(action, materialId) + } // handleAction(action, materialId) } } else { @@ -347,18 +451,28 @@ export function useTriggerHandler() { } else { - // Event Manager Needed + // Handle current action using Event Manager + addArmBotToMonitor(armBot.modelUuid, () => { const model = getEventByModelUuid(selectedProduct.productId, action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || ''); if (model?.type === 'transfer') { const conveyor = getConveyorById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || ''); if (conveyor) { - addConveyorToMonitor(conveyor.modelUuid, - () => { + const previousModel = getEventByModelUuid(selectedProduct.productId, material.previous?.modelUuid || ''); + if (previousModel) { + if (previousModel.type === 'transfer' && previousModel.modelUuid === model.modelUuid) { handleAction(action, materialId) + } else { + addConveyorToMonitor(conveyor.modelUuid, + () => { + handleAction(action, materialId) + } + ) } - ) + } else { + handleAction(action, materialId) + } // handleAction(action, materialId) } } else { @@ -432,17 +546,54 @@ export function useTriggerHandler() { if (vehicle) { - if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.currentLoad < vehicle.point.action.loadCapacity) { + if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) { + + setPreviousLocation(material.materialId, { + modelUuid: material.current.modelUuid, + pointUuid: material.current.pointUuid, + actionUuid: material.current.actionUuid, + }) + + setCurrentLocation(material.materialId, { + modelUuid: action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '', + pointUuid: action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid || '', + actionUuid: action.triggers[0]?.triggeredAsset?.triggeredAction?.actionUuid || '', + }); + + setNextLocation(material.materialId, null); setIsVisible(materialId, false); + setIsPaused(materialId, false); // Handle current action from vehicle handleAction(nextAction, materialId); } else { - // Event Manager Needed + // Handle current action using Event Manager + setIsPaused(materialId, true); + addVehicleToMonitor(vehicle.modelUuid, + () => { + setPreviousLocation(material.materialId, { + modelUuid: material.current.modelUuid, + pointUuid: material.current.pointUuid, + actionUuid: material.current.actionUuid, + }) + + setCurrentLocation(material.materialId, { + modelUuid: action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '', + pointUuid: action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid || '', + actionUuid: action.triggers[0]?.triggeredAsset?.triggeredAction?.actionUuid || '', + }); + + setNextLocation(material.materialId, null); + + setIsPaused(materialId, false); + setIsVisible(materialId, false); + handleAction(nextAction, materialId); + } + ) } } } @@ -491,7 +642,7 @@ export function useTriggerHandler() { if (vehicle) { - if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.currentLoad < vehicle.point.action.loadCapacity) { + if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) { setIsVisible(materialId, false); diff --git a/app/src/modules/simulation/vehicle/instances/eventManager/useVehicleEventManager.ts b/app/src/modules/simulation/vehicle/instances/eventManager/useVehicleEventManager.ts new file mode 100644 index 0000000..7cc8c58 --- /dev/null +++ b/app/src/modules/simulation/vehicle/instances/eventManager/useVehicleEventManager.ts @@ -0,0 +1,65 @@ +import { useEffect, useRef } from 'react'; +import { useFrame } from '@react-three/fiber'; +import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore'; + +type VehicleCallback = { + vehicleId: string; + callback: () => void; +}; + +export function useVehicleEventManager() { + const { getVehicleById } = useVehicleStore(); + const callbacksRef = useRef([]); + const isMonitoringRef = useRef(false); + + // Add a new vehicle to monitor + const addVehicleToMonitor = (vehicleId: string, callback: () => void) => { + // Avoid duplicates + if (!callbacksRef.current.some((entry) => entry.vehicleId === vehicleId)) { + callbacksRef.current.push({ vehicleId, callback }); + } + + // Start monitoring if not already running + if (!isMonitoringRef.current) { + isMonitoringRef.current = true; + } + }; + + // Remove a vehicle from monitoring + const removeVehicleFromMonitor = (vehicleId: string) => { + callbacksRef.current = callbacksRef.current.filter( + (entry) => entry.vehicleId !== vehicleId + ); + + // Stop monitoring if no more vehicles to track + if (callbacksRef.current.length === 0) { + isMonitoringRef.current = false; + } + }; + + // Check vehicle states every frame + useFrame(() => { + if (!isMonitoringRef.current || callbacksRef.current.length === 0) return; + + callbacksRef.current.forEach(({ vehicleId, callback }) => { + const vehicle = getVehicleById(vehicleId); + if (vehicle && vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) { + callback(); + removeVehicleFromMonitor(vehicleId); // Remove after triggering + } + }); + }); + + // Cleanup on unmount + useEffect(() => { + return () => { + callbacksRef.current = []; + isMonitoringRef.current = false; + }; + }, []); + + return { + addVehicleToMonitor, + removeVehicleFromMonitor, + }; +} \ No newline at end of file