diff --git a/app/src/modules/market/Card.tsx b/app/src/modules/market/Card.tsx index b1b5faa..ba2c58d 100644 --- a/app/src/modules/market/Card.tsx +++ b/app/src/modules/market/Card.tsx @@ -17,7 +17,6 @@ interface CardProps { image: string; description: string; AssetID: string - modelUrl: string onSelectCard: (cardData: { assetName: string; uploadedOn: number; @@ -38,13 +37,10 @@ const Card: React.FC = ({ image, description, AssetID, - modelUrl, onSelectCard, }) => { const handleCardSelect = () => { - console.log('assetName: ', assetName); - console.log('AssetID: ', AssetID); onSelectCard({ assetName, uploadedOn, price, rating, views, description, AssetID diff --git a/app/src/modules/market/CardsContainer.tsx b/app/src/modules/market/CardsContainer.tsx index 5612b6b..e1766f2 100644 --- a/app/src/modules/market/CardsContainer.tsx +++ b/app/src/modules/market/CardsContainer.tsx @@ -45,7 +45,7 @@ const CardsContainer: React.FC = ({ models }) => { }) => { setSelectedCard(cardData); const res = await fetchGltfUrl(cardData.assetName, cardData.AssetID); - console.log("res: ", res); + // console.log("res: ", res); setModelUrl(res.url); }; return ( @@ -66,7 +66,6 @@ const CardsContainer: React.FC = ({ models }) => { AssetID={assetDetail.AssetID} image={assetDetail.thumbnail} description={assetDetail.description} - modelUrl={modelUrl} /> ))} diff --git a/app/src/modules/market/MarketPlace.tsx b/app/src/modules/market/MarketPlace.tsx index 8440467..c76baa3 100644 --- a/app/src/modules/market/MarketPlace.tsx +++ b/app/src/modules/market/MarketPlace.tsx @@ -33,7 +33,6 @@ const MarketPlace = () => { try { const filt = await getAssetImages("67d934ad0f42a1fdadb19aa6"); setModels(filt.items); - console.log('filt.items: ', filt.items); setFilteredModels(filt.items); setisLoading(false); } catch { diff --git a/app/src/modules/simulation/machine/instances/machineInstance/machineInstance.tsx b/app/src/modules/simulation/machine/instances/machineInstance/machineInstance.tsx index 525c9c9..a985248 100644 --- a/app/src/modules/simulation/machine/instances/machineInstance/machineInstance.tsx +++ b/app/src/modules/simulation/machine/instances/machineInstance/machineInstance.tsx @@ -1,6 +1,6 @@ import { useEffect, useRef, useState } from 'react' import { useMachineStore } from '../../../../../store/simulation/useMachineStore'; -import { usePlayButtonStore } from '../../../../../store/usePlayButtonStore'; +import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore'; import MachineAnimator from '../animator/machineAnimator'; import { useProductStore } from '../../../../../store/simulation/useProductStore'; import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore'; @@ -9,22 +9,94 @@ import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHa function MachineInstance({ machineDetail }: { machineDetail: MachineStatus }) { const [currentPhase, setCurrentPhase] = useState('idle'); let isIncrememtable = useRef(true); + const idleTimeRef = useRef(0); + const activeTimeRef = useRef(0); + const previousTimeRef = useRef(null); + const animationFrameIdRef = useRef(null); + const isSpeedRef = useRef(0); + const isPausedRef = useRef(false); const { isPlaying } = usePlayButtonStore(); - const { machines, setMachineState, setMachineActive } = useMachineStore(); + const { machines, setMachineState, setMachineActive, incrementIdleTime, incrementActiveTime, resetTime } = useMachineStore(); const { selectedProduct } = useSelectedProduct(); const { getActionByUuid } = useProductStore(); const { triggerPointActions } = useTriggerHandler(); + const { speed } = useAnimationPlaySpeed(); + const { isPaused } = usePauseButtonStore(); + useEffect(() => { + isPausedRef.current = isPaused; + }, [isPaused]); + + useEffect(() => { + isSpeedRef.current = speed; + }, [speed]); const reset = () => { setCurrentPhase("idle"); + console.log("exit"); setMachineState(machineDetail.modelUuid, 'idle'); setMachineActive(machineDetail.modelUuid, false); isIncrememtable.current = true; + isPausedRef.current = false; + resetTime(machineDetail.modelUuid) + activeTimeRef.current = 0 + idleTimeRef.current = 0 + previousTimeRef.current = null + if (animationFrameIdRef.current !== null) { + cancelAnimationFrame(animationFrameIdRef.current) + animationFrameIdRef.current = null + } } function machineStatus(modelId: string, status: string) { // console.log(`${modelId} , ${status}`); } + function animate(currentTime: number) { + if (previousTimeRef.current === null) { + previousTimeRef.current = currentTime; + } + + const deltaTime = (currentTime - previousTimeRef.current) / 1000; + previousTimeRef.current = currentTime; + + if (machineDetail.isActive) { + if (!isPausedRef.current) { + activeTimeRef.current += deltaTime * isSpeedRef.current; + // console.log(' activeTimeRef.current: ', activeTimeRef.current); + } + } else { + if (!isPausedRef.current) { + idleTimeRef.current += deltaTime * isSpeedRef.current; + // console.log('idleTimeRef.curre: ', idleTimeRef.current); + } + } + animationFrameIdRef.current = requestAnimationFrame(animate); + } + + useEffect(() => { + if (!isPlaying) return + if (!machineDetail.isActive) { + const roundedActiveTime = Math.round(activeTimeRef.current); + // console.log('Final Active Time:', roundedActiveTime, 'seconds'); + incrementActiveTime(machineDetail.modelUuid, roundedActiveTime); + activeTimeRef.current = 0; + } else { + const roundedIdleTime = Math.round(idleTimeRef.current); + // console.log('Final Idle Time:', roundedIdleTime, 'seconds'); + incrementIdleTime(machineDetail.modelUuid, roundedIdleTime); + idleTimeRef.current = 0; + } + + if (animationFrameIdRef.current === null) { + animationFrameIdRef.current = requestAnimationFrame(animate); + } + + return () => { + if (animationFrameIdRef.current !== null) { + cancelAnimationFrame(animationFrameIdRef.current); + animationFrameIdRef.current = null; + } + }; + }, [machineDetail, isPlaying]); useEffect(() => { if (isPlaying) { diff --git a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx index 4031713..e648f86 100644 --- a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx +++ b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx @@ -11,10 +11,7 @@ import { useProductStore } from '../../../../../store/simulation/useProductStore import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore'; import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler'; import MaterialAnimator from '../animator/materialAnimator'; -type Timer = { - start: number | null; - active: boolean; -}; + function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) { const { navMesh } = useNavMesh(); const { isPlaying } = usePlayButtonStore(); @@ -23,20 +20,29 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) const { triggerPointActions } = useTriggerHandler(); const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = useProductStore(); const { selectedProduct } = useSelectedProduct(); - const { vehicles, setVehicleActive, setVehicleState, setVehiclePicking, clearCurrentMaterials, setVehicleLoad, decrementVehicleLoad, removeLastMaterial } = useVehicleStore(); + const { vehicles, setVehicleActive, setVehicleState, setVehiclePicking, clearCurrentMaterials, setVehicleLoad, decrementVehicleLoad, removeLastMaterial, incrementIdleTime, incrementActiveTime, resetTime } = useVehicleStore(); const [currentPhase, setCurrentPhase] = useState('stationed'); const [path, setPath] = useState<[number, number, number][]>([]); const pauseTimeRef = useRef(null); + const idleTimeRef = useRef(0); + const activeTimeRef = useRef(0); const isPausedRef = useRef(false); + const isSpeedRef = useRef(0); let startTime: number; let fixedInterval: number; const { speed } = useAnimationPlaySpeed(); const { isPaused } = usePauseButtonStore(); + const previousTimeRef = useRef(null); + const animationFrameIdRef = useRef(null); useEffect(() => { isPausedRef.current = isPaused; }, [isPaused]); + useEffect(() => { + isSpeedRef.current = speed; + }, [speed]); + const computePath = useCallback( (start: any, end: any) => { try { @@ -54,7 +60,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) ); function vehicleStatus(modelId: string, status: string) { - // + // console.log(`${modelId} , ${status}`); } // Function to reset everything @@ -68,6 +74,14 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) startTime = 0; isPausedRef.current = false; pauseTimeRef.current = 0; + resetTime(agvDetail.modelUuid) + activeTimeRef.current = 0 + idleTimeRef.current = 0 + previousTimeRef.current = null + if (animationFrameIdRef.current !== null) { + cancelAnimationFrame(animationFrameIdRef.current) + animationFrameIdRef.current = null + } } useEffect(() => { @@ -115,12 +129,61 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) vehicleStatus(agvDetail.modelUuid, 'Started from dropping point, heading to pickup point'); } } - } else { + } + else { reset() } // eslint-disable-next-line react-hooks/exhaustive-deps }, [vehicles, currentPhase, path, isPlaying]); + + function animate(currentTime: number) { + if (previousTimeRef.current === null) { + previousTimeRef.current = currentTime; + } + + const deltaTime = (currentTime - previousTimeRef.current) / 1000; + previousTimeRef.current = currentTime; + + if (agvDetail.isActive) { + if (!isPausedRef.current) { + activeTimeRef.current += deltaTime * isSpeedRef.current; + } + } else { + if (!isPausedRef.current) { + idleTimeRef.current += deltaTime * isSpeedRef.current; // Scale idle time by speed + } + } + animationFrameIdRef.current = requestAnimationFrame(animate); + } + + useEffect(() => { + if (!isPlaying) return + if (!agvDetail.isActive) { + const roundedActiveTime = Math.round(activeTimeRef.current); + // console.log('Final Active Time:', roundedActiveTime, 'seconds'); + incrementActiveTime(agvDetail.modelUuid, roundedActiveTime); + activeTimeRef.current = 0; + } else { + const roundedIdleTime = Math.round(idleTimeRef.current); + // console.log('Final Idle Time:', roundedIdleTime, 'seconds'); + incrementIdleTime(agvDetail.modelUuid, roundedIdleTime); + idleTimeRef.current = 0; + } + + if (animationFrameIdRef.current === null) { + animationFrameIdRef.current = requestAnimationFrame(animate); + } + + return () => { + if (animationFrameIdRef.current !== null) { + cancelAnimationFrame(animationFrameIdRef.current); + animationFrameIdRef.current = null; + } + }; + }, [agvDetail, isPlaying]); + + function handleCallBack() { if (currentPhase === 'stationed-pickup') { setCurrentPhase('picking'); @@ -147,9 +210,6 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) } } - - - function startUnloadingProcess() { if (agvDetail.point.action.triggers.length > 0) { const trigger = getTriggerByUuid(selectedProduct.productId, agvDetail.point.action.triggers[0].triggerUuid); @@ -213,7 +273,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) action: VehicleAction ) { startTime = performance.now(); - const fixedInterval = ((unLoadDuration / vehicleCurrentLoad) * (1000 / speed)); + const fixedInterval = ((unLoadDuration / vehicleCurrentLoad) * (1000 / isSpeedRef.current)); const unloadLoop = () => { if (isPausedRef.current) { @@ -295,7 +355,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) const elapsedTime = performance.now() - startTime; const unLoadDuration = agvDetail.point.action.unLoadDuration; - fixedInterval = ((unLoadDuration / agvDetail.currentLoad) * (1000 / speed)); + fixedInterval = ((unLoadDuration / agvDetail.currentLoad) * (1000 / isSpeedRef.current)); if (elapsedTime >= fixedInterval) { let droppedMat = droppedMaterial - 1; @@ -332,4 +392,10 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) ); } -export default VehicleInstance; \ No newline at end of file +export default VehicleInstance; + + + + + + diff --git a/app/src/store/simulation/useMachineStore.ts b/app/src/store/simulation/useMachineStore.ts index 2c4c98a..df480e0 100644 --- a/app/src/store/simulation/useMachineStore.ts +++ b/app/src/store/simulation/useMachineStore.ts @@ -1,154 +1,176 @@ -import { create } from 'zustand'; -import { immer } from 'zustand/middleware/immer'; +import { create } from "zustand"; +import { immer } from "zustand/middleware/immer"; interface MachineStore { - machines: MachineStatus[]; + machines: MachineStatus[]; - addMachine: (productId: string, machine: MachineEventSchema) => void; - removeMachine: (modelUuid: string) => void; - updateMachine: ( - modelUuid: string, - updates: Partial> - ) => void; - clearMachines: () => void; + addMachine: (productId: string, machine: MachineEventSchema) => void; + removeMachine: (modelUuid: string) => void; + updateMachine: ( + modelUuid: string, + updates: Partial> + ) => void; + clearMachines: () => void; - addCurrentAction: (modelUuid: string, actionUuid: string, materialType: string, materialId: string) => void; - removeCurrentAction: (modelUuid: string) => void; + addCurrentAction: ( + modelUuid: string, + actionUuid: string, + materialType: string, + materialId: string + ) => void; + removeCurrentAction: (modelUuid: string) => void; - setMachineActive: (modelUuid: string, isActive: boolean) => void; - setMachineState: (modelUuid: string, newState: MachineStatus['state']) => void; + setMachineActive: (modelUuid: string, isActive: boolean) => void; + setMachineState: ( + modelUuid: string, + newState: MachineStatus["state"] + ) => void; - incrementActiveTime: (modelUuid: string, incrementBy: number) => void; - incrementIdleTime: (modelUuid: string, incrementBy: number) => void; + incrementActiveTime: (modelUuid: string, incrementBy: number) => void; + incrementIdleTime: (modelUuid: string, incrementBy: number) => void; + resetTime: (modelUuid: string) => void; - getMachineById: (modelUuid: string) => MachineStatus | undefined; - getMachinesByProduct: (productId: string) => MachineStatus[]; - getMachinesBystate: (state: string) => MachineStatus[]; - getActiveMachines: () => MachineStatus[]; - getIdleMachines: () => MachineStatus[]; + getMachineById: (modelUuid: string) => MachineStatus | undefined; + getMachinesByProduct: (productId: string) => MachineStatus[]; + getMachinesBystate: (state: string) => MachineStatus[]; + getActiveMachines: () => MachineStatus[]; + getIdleMachines: () => MachineStatus[]; } export const useMachineStore = create()( - immer((set, get) => ({ - machines: [], + immer((set, get) => ({ + machines: [], - addMachine: (productId, machine) => { - set((state) => { - 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', - }); - } - }); - }, + addMachine: (productId, machine) => { + set((state) => { + 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", + }); + } + }); + }, - removeMachine: (modelUuid) => { - set((state) => { - state.machines = state.machines.filter(m => m.modelUuid !== modelUuid); - }); - }, + removeMachine: (modelUuid) => { + set((state) => { + state.machines = state.machines.filter( + (m) => m.modelUuid !== modelUuid + ); + }); + }, - updateMachine: (modelUuid, updates) => { - set((state) => { - const machine = state.machines.find(m => m.modelUuid === modelUuid); - if (machine) { - Object.assign(machine, updates); - } - }); - }, + updateMachine: (modelUuid, updates) => { + set((state) => { + const machine = state.machines.find((m) => m.modelUuid === modelUuid); + if (machine) { + Object.assign(machine, updates); + } + }); + }, - clearMachines: () => { - set((state) => { - state.machines = []; - }); - }, + clearMachines: () => { + set((state) => { + state.machines = []; + }); + }, - addCurrentAction: (modelUuid, actionUuid, materialType, materialId) => { - set((state) => { - const armBot = state.machines.find(a => a.modelUuid === modelUuid); - if (armBot) { - const action = armBot.point.action; - if (action) { - armBot.currentAction = { - actionUuid: actionUuid, - actionName: action.actionName, - materialType: materialType, - materialId: materialId - }; - } - } - }); - }, + addCurrentAction: (modelUuid, actionUuid, materialType, materialId) => { + set((state) => { + const armBot = state.machines.find((a) => a.modelUuid === modelUuid); + if (armBot) { + const action = armBot.point.action; + if (action) { + armBot.currentAction = { + actionUuid: actionUuid, + actionName: action.actionName, + materialType: materialType, + materialId: materialId, + }; + } + } + }); + }, - removeCurrentAction: (modelUuid) => { - set((state) => { - const armBot = state.machines.find(a => a.modelUuid === modelUuid); - if (armBot) { - armBot.currentAction = undefined; - } - }); - }, + removeCurrentAction: (modelUuid) => { + set((state) => { + const armBot = state.machines.find((a) => a.modelUuid === modelUuid); + if (armBot) { + armBot.currentAction = undefined; + } + }); + }, - setMachineActive: (modelUuid, isActive) => { - set((state) => { - const machine = state.machines.find(m => m.modelUuid === modelUuid); - if (machine) { - machine.isActive = isActive; - } - }); - }, + setMachineActive: (modelUuid, isActive) => { + set((state) => { + const machine = state.machines.find((m) => m.modelUuid === modelUuid); + if (machine) { + machine.isActive = isActive; + } + }); + }, - setMachineState: (modelUuid, newState) => { - set((state) => { - const machine = state.machines.find(m => m.modelUuid === modelUuid); - if (machine) { - machine.state = newState; - } - }); - }, + setMachineState: (modelUuid, newState) => { + set((state) => { + const machine = state.machines.find((m) => m.modelUuid === modelUuid); + if (machine) { + machine.state = newState; + } + }); + }, - incrementActiveTime: (modelUuid, incrementBy) => { - set((state) => { - const machine = state.machines.find(m => m.modelUuid === modelUuid); - if (machine) { - machine.activeTime += incrementBy; - } - }); - }, + incrementActiveTime: (modelUuid, incrementBy) => { + set((state) => { + const machine = state.machines.find((m) => m.modelUuid === modelUuid); + if (machine) { + machine.activeTime += incrementBy; + } + }); + }, - incrementIdleTime: (modelUuid, incrementBy) => { - set((state) => { - const machine = state.machines.find(m => m.modelUuid === modelUuid); - if (machine) { - machine.idleTime += incrementBy; - } - }); - }, + incrementIdleTime: (modelUuid, incrementBy) => { + set((state) => { + const machine = state.machines.find((m) => m.modelUuid === modelUuid); + if (machine) { + machine.idleTime += incrementBy; + } + }); + }, + resetTime: (modelUuid) => { + set((state) => { + const machine = state.machines.find((m) => m.modelUuid === modelUuid); + if (machine) { + machine.activeTime = 0; + machine.idleTime = 0; + } + }); + }, - getMachineById: (modelUuid) => { - return get().machines.find(m => m.modelUuid === modelUuid); - }, + getMachineById: (modelUuid) => { + return get().machines.find((m) => m.modelUuid === modelUuid); + }, - getMachinesByProduct: (productId) => { - return get().machines.filter(m => m.productId === productId); - }, + getMachinesByProduct: (productId) => { + return get().machines.filter((m) => m.productId === productId); + }, - getMachinesBystate: (state) => { - return get().machines.filter(m => m.state === state); - }, + getMachinesBystate: (state) => { + return get().machines.filter((m) => m.state === state); + }, - getActiveMachines: () => { - return get().machines.filter(m => m.isActive); - }, + getActiveMachines: () => { + return get().machines.filter((m) => m.isActive); + }, - getIdleMachines: () => { - return get().machines.filter(m => !m.isActive && m.state === 'idle'); - }, - })) + getIdleMachines: () => { + return get().machines.filter((m) => !m.isActive && m.state === "idle"); + }, + })) ); diff --git a/app/src/store/simulation/useVehicleStore.ts b/app/src/store/simulation/useVehicleStore.ts index e69c233..13b4b0a 100644 --- a/app/src/store/simulation/useVehicleStore.ts +++ b/app/src/store/simulation/useVehicleStore.ts @@ -28,6 +28,7 @@ interface VehiclesStore { clearCurrentMaterials: (modelUuid: string) => void; incrementActiveTime: (modelUuid: string, incrementBy: number) => void; incrementIdleTime: (modelUuid: string, incrementBy: number) => void; + resetTime: (modelUuid: string) => void; getVehicleById: (modelUuid: string) => VehicleStatus | undefined; getVehiclesByProduct: (productId: string) => VehicleStatus[]; @@ -206,6 +207,16 @@ export const useVehicleStore = create()( }); }, + resetTime: (modelUuid) => { + set((state) => { + const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid); + if (vehicle) { + vehicle.activeTime = 0; + vehicle.idleTime = 0; + } + }); + }, + getVehicleById: (modelUuid) => { return get().vehicles.find((v) => v.modelUuid === modelUuid); },