feat: Implement human simulation features
- Added human event handling in the simulation, including the ability to add, update, and remove human instances. - Introduced a new Human store to manage human states and actions. - Updated the simulation context to include human management. - Enhanced the Points and TriggerConnector components to support human interactions. - Refactored existing components to integrate human-related functionalities. - Added HumanInstance and HumanInstances components for rendering human entities in the simulation. - Updated TypeScript definitions to include human-related types and actions.
This commit is contained in:
@@ -51,9 +51,8 @@ const AssetProperties: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleAnimationClick = (animation: string) => {
|
const handleAnimationClick = (animation: string) => {
|
||||||
if (selectedFloorItem && selectedFloorItem.animationState) {
|
if (selectedFloorItem) {
|
||||||
const isPlaying = selectedFloorItem.animationState?.playing || false;
|
setCurrentAnimation(selectedFloorItem.uuid, animation, true);
|
||||||
setCurrentAnimation(selectedFloorItem.uuid, animation, !isPlaying);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ const VersionHistory = () => {
|
|||||||
const handleSelectVersion = (version: Version) => {
|
const handleSelectVersion = (version: Version) => {
|
||||||
if (!projectId) return;
|
if (!projectId) return;
|
||||||
|
|
||||||
getVersionDataApi(projectId, version.versionId).then((verdionData) => {
|
getVersionDataApi(projectId, version.versionId).then((versionData) => {
|
||||||
setSelectedVersion(version);
|
setSelectedVersion(version);
|
||||||
// console.log(verdionData);
|
// console.log(versionData);
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
// console.log(err);
|
// console.log(err);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,12 +3,14 @@ import { useEffect, useMemo, useRef, useState } from 'react'
|
|||||||
import { useThree } from '@react-three/fiber';
|
import { useThree } from '@react-three/fiber';
|
||||||
import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from '../../../../store/builder/store';
|
import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from '../../../../store/builder/store';
|
||||||
import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
|
import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
|
||||||
import { upsertAisleApi } from '../../../../services/factoryBuilder/aisle/upsertAisleApi';
|
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { useVersionContext } from '../../version/versionContext';
|
import { useVersionContext } from '../../version/versionContext';
|
||||||
import { useSceneContext } from '../../../scene/sceneContext';
|
import { useSceneContext } from '../../../scene/sceneContext';
|
||||||
import ReferenceAisle from './referenceAisle';
|
import ReferenceAisle from './referenceAisle';
|
||||||
import ReferencePoint from '../../point/reference/referencePoint';
|
import ReferencePoint from '../../point/reference/referencePoint';
|
||||||
|
import { getUserData } from '../../../../functions/getUserData';
|
||||||
|
|
||||||
|
// import { upsertAisleApi } from '../../../../services/factoryBuilder/aisle/upsertAisleApi';
|
||||||
|
|
||||||
function AisleCreator() {
|
function AisleCreator() {
|
||||||
const { scene, camera, raycaster, gl, pointer } = useThree();
|
const { scene, camera, raycaster, gl, pointer } = useThree();
|
||||||
@@ -23,6 +25,7 @@ function AisleCreator() {
|
|||||||
const isLeftMouseDown = useRef(false);
|
const isLeftMouseDown = useRef(false);
|
||||||
const { selectedVersionStore } = useVersionContext();
|
const { selectedVersionStore } = useVersionContext();
|
||||||
const { selectedVersion } = selectedVersionStore();
|
const { selectedVersion } = selectedVersionStore();
|
||||||
|
const { userId, organization } = getUserData();
|
||||||
const { projectId } = useParams();
|
const { projectId } = useParams();
|
||||||
|
|
||||||
const [tempPoints, setTempPoints] = useState<Point[]>([]);
|
const [tempPoints, setTempPoints] = useState<Point[]>([]);
|
||||||
@@ -106,7 +109,22 @@ function AisleCreator() {
|
|||||||
};
|
};
|
||||||
addAisle(aisle);
|
addAisle(aisle);
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
socket.emit('v1:model-aisle:add', {
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization,
|
||||||
|
aisleUuid: aisle.aisleUuid,
|
||||||
|
points: aisle.points,
|
||||||
|
type: aisle.type
|
||||||
|
})
|
||||||
}
|
}
|
||||||
setTempPoints([newPoint]);
|
setTempPoints([newPoint]);
|
||||||
}
|
}
|
||||||
@@ -129,7 +147,22 @@ function AisleCreator() {
|
|||||||
};
|
};
|
||||||
addAisle(aisle);
|
addAisle(aisle);
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
socket.emit('v1:model-aisle:add', {
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization,
|
||||||
|
aisleUuid: aisle.aisleUuid,
|
||||||
|
points: aisle.points,
|
||||||
|
type: aisle.type
|
||||||
|
})
|
||||||
}
|
}
|
||||||
setTempPoints([newPoint]);
|
setTempPoints([newPoint]);
|
||||||
}
|
}
|
||||||
@@ -151,7 +184,22 @@ function AisleCreator() {
|
|||||||
};
|
};
|
||||||
addAisle(aisle);
|
addAisle(aisle);
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
socket.emit('v1:model-aisle:add', {
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization,
|
||||||
|
aisleUuid: aisle.aisleUuid,
|
||||||
|
points: aisle.points,
|
||||||
|
type: aisle.type
|
||||||
|
})
|
||||||
}
|
}
|
||||||
setTempPoints([newPoint]);
|
setTempPoints([newPoint]);
|
||||||
}
|
}
|
||||||
@@ -172,7 +220,22 @@ function AisleCreator() {
|
|||||||
};
|
};
|
||||||
addAisle(aisle);
|
addAisle(aisle);
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
socket.emit('v1:model-aisle:add', {
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization,
|
||||||
|
aisleUuid: aisle.aisleUuid,
|
||||||
|
points: aisle.points,
|
||||||
|
type: aisle.type
|
||||||
|
})
|
||||||
}
|
}
|
||||||
setTempPoints([newPoint]);
|
setTempPoints([newPoint]);
|
||||||
}
|
}
|
||||||
@@ -195,7 +258,22 @@ function AisleCreator() {
|
|||||||
};
|
};
|
||||||
addAisle(aisle);
|
addAisle(aisle);
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
socket.emit('v1:model-aisle:add', {
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization,
|
||||||
|
aisleUuid: aisle.aisleUuid,
|
||||||
|
points: aisle.points,
|
||||||
|
type: aisle.type
|
||||||
|
})
|
||||||
}
|
}
|
||||||
setTempPoints([newPoint]);
|
setTempPoints([newPoint]);
|
||||||
}
|
}
|
||||||
@@ -217,7 +295,22 @@ function AisleCreator() {
|
|||||||
};
|
};
|
||||||
addAisle(aisle);
|
addAisle(aisle);
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
socket.emit('v1:model-aisle:add', {
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization,
|
||||||
|
aisleUuid: aisle.aisleUuid,
|
||||||
|
points: aisle.points,
|
||||||
|
type: aisle.type
|
||||||
|
})
|
||||||
}
|
}
|
||||||
setTempPoints([newPoint]);
|
setTempPoints([newPoint]);
|
||||||
}
|
}
|
||||||
@@ -238,7 +331,22 @@ function AisleCreator() {
|
|||||||
};
|
};
|
||||||
addAisle(aisle);
|
addAisle(aisle);
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
socket.emit('v1:model-aisle:add', {
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization,
|
||||||
|
aisleUuid: aisle.aisleUuid,
|
||||||
|
points: aisle.points,
|
||||||
|
type: aisle.type
|
||||||
|
})
|
||||||
}
|
}
|
||||||
setTempPoints([newPoint]);
|
setTempPoints([newPoint]);
|
||||||
}
|
}
|
||||||
@@ -260,7 +368,22 @@ function AisleCreator() {
|
|||||||
};
|
};
|
||||||
addAisle(aisle);
|
addAisle(aisle);
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
socket.emit('v1:model-aisle:add', {
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization,
|
||||||
|
aisleUuid: aisle.aisleUuid,
|
||||||
|
points: aisle.points,
|
||||||
|
type: aisle.type
|
||||||
|
})
|
||||||
}
|
}
|
||||||
setTempPoints([newPoint]);
|
setTempPoints([newPoint]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -360,6 +360,40 @@ async function handleModelLoad(
|
|||||||
position: storageEvent.point.position,
|
position: storageEvent.point.position,
|
||||||
rotation: storageEvent.point.rotation,
|
rotation: storageEvent.point.rotation,
|
||||||
};
|
};
|
||||||
|
} else if (selectedItem.type === "Human") {
|
||||||
|
const humanEvent: HumanEventSchema = {
|
||||||
|
modelUuid: newFloorItem.modelUuid,
|
||||||
|
modelName: newFloorItem.modelName,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: newFloorItem.rotation,
|
||||||
|
state: "idle",
|
||||||
|
type: "human",
|
||||||
|
point: {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
position: [data.points[0].x, data.points[0].y, data.points[0].z],
|
||||||
|
rotation: [0, 0, 0],
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionUuid: THREE.MathUtils.generateUUID(),
|
||||||
|
actionName: "Action 1",
|
||||||
|
actionType: "animation",
|
||||||
|
animation: null,
|
||||||
|
loadCapacity: 1,
|
||||||
|
travelPoints: {
|
||||||
|
startPoint: null,
|
||||||
|
endPoint: null,
|
||||||
|
},
|
||||||
|
triggers: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addEvent(humanEvent);
|
||||||
|
eventData.point = {
|
||||||
|
uuid: humanEvent.point.uuid,
|
||||||
|
position: humanEvent.point.position,
|
||||||
|
rotation: humanEvent.point.rotation,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const completeData = {
|
const completeData = {
|
||||||
|
|||||||
@@ -301,20 +301,21 @@ function Model({ asset }: { readonly asset: Asset }) {
|
|||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handlePlay = (clipName: string) => {
|
|
||||||
|
if (asset.animationState && asset.animationState.playing) {
|
||||||
if (!mixerRef.current) return;
|
if (!mixerRef.current) return;
|
||||||
|
|
||||||
Object.values(actions.current).forEach((action) => action.stop());
|
Object.values(actions.current).forEach((action) => action.stop());
|
||||||
|
|
||||||
const action = actions.current[clipName];
|
const action = actions.current[asset.animationState.current];
|
||||||
if (action && asset.animationState?.playing) {
|
if (action && asset.animationState?.playing) {
|
||||||
action.reset().setLoop(THREE.LoopOnce, 1).play();
|
action.reset().setLoop(THREE.LoopOnce, 1).play();
|
||||||
}
|
}
|
||||||
};
|
} else {
|
||||||
|
Object.values(actions.current).forEach((action) => action.stop());
|
||||||
|
}
|
||||||
|
|
||||||
handlePlay(asset.animationState?.current || '');
|
}, [asset.animationState])
|
||||||
|
|
||||||
}, [asset])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group
|
<group
|
||||||
@@ -362,17 +363,6 @@ function Model({ asset }: { readonly asset: Asset }) {
|
|||||||
<AssetBoundingBox boundingBox={boundingBox} />
|
<AssetBoundingBox boundingBox={boundingBox} />
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
{/* <group >
|
|
||||||
<Html>
|
|
||||||
<div style={{ position: 'absolute', }}>
|
|
||||||
{animationNames.map((name) => (
|
|
||||||
<button key={name} onClick={() => handlePlay(name)} style={{ margin: 4 }}>
|
|
||||||
{name}
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</Html>
|
|
||||||
</group> */}
|
|
||||||
</group >
|
</group >
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import { useParams } from 'react-router-dom';
|
|||||||
import { useVersionContext } from '../version/versionContext';
|
import { useVersionContext } from '../version/versionContext';
|
||||||
import { useSceneContext } from '../../scene/sceneContext';
|
import { useSceneContext } from '../../scene/sceneContext';
|
||||||
|
|
||||||
import { upsertAisleApi } from '../../../services/factoryBuilder/aisle/upsertAisleApi';
|
// import { upsertAisleApi } from '../../../services/factoryBuilder/aisle/upsertAisleApi';
|
||||||
import { deleteAisleApi } from '../../../services/factoryBuilder/aisle/deleteAisleApi';
|
// import { deleteAisleApi } from '../../../services/factoryBuilder/aisle/deleteAisleApi';
|
||||||
// import { upsertWallApi } from '../../../services/factoryBuilder/wall/upsertWallApi';
|
// import { upsertWallApi } from '../../../services/factoryBuilder/wall/upsertWallApi';
|
||||||
// import { deleteWallApi } from '../../../services/factoryBuilder/wall/deleteWallApi';
|
// import { deleteWallApi } from '../../../services/factoryBuilder/wall/deleteWallApi';
|
||||||
// import { upsertFloorApi } from '../../../services/factoryBuilder/floor/upsertFloorApi';
|
// import { upsertFloorApi } from '../../../services/factoryBuilder/floor/upsertFloorApi';
|
||||||
@@ -159,7 +159,22 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
const updatedAisles = getAislesByPointId(point.pointUuid);
|
const updatedAisles = getAislesByPointId(point.pointUuid);
|
||||||
if (updatedAisles.length > 0 && projectId) {
|
if (updatedAisles.length > 0 && projectId) {
|
||||||
updatedAisles.forEach((updatedAisle) => {
|
updatedAisles.forEach((updatedAisle) => {
|
||||||
upsertAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId, selectedVersion?.versionId || '')
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId, selectedVersion?.versionId || '');
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
socket.emit('v1:model-aisle:add', {
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization,
|
||||||
|
aisleUuid: updatedAisle.aisleUuid,
|
||||||
|
points: updatedAisle.points,
|
||||||
|
type: updatedAisle.type
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if (point.pointType === 'Wall') {
|
} else if (point.pointType === 'Wall') {
|
||||||
@@ -238,7 +253,22 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
if (removedAisles.length > 0) {
|
if (removedAisles.length > 0) {
|
||||||
removedAisles.forEach(aisle => {
|
removedAisles.forEach(aisle => {
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
deleteAisleApi(aisle.aisleUuid, projectId, selectedVersion?.versionId || '')
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// deleteAisleApi(aisle.aisleUuid, projectId, selectedVersion?.versionId || '');
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization,
|
||||||
|
aisleUuid: aisle.aisleUuid
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v1:model-aisle:delete', data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
setHoveredPoint(null);
|
setHoveredPoint(null);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export default function SocketResponses() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
socket.on("v1:model-asset:response:add", (data: any) => {
|
socket.on("v1:model-asset:response:add", (data: any) => {
|
||||||
console.log('data: ', data);
|
// console.log('data: ', data);
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { createMachineStore, MachineStoreType } from '../../store/simulation/use
|
|||||||
import { createConveyorStore, ConveyorStoreType } from '../../store/simulation/useConveyorStore';
|
import { createConveyorStore, ConveyorStoreType } from '../../store/simulation/useConveyorStore';
|
||||||
import { createVehicleStore, VehicleStoreType } from '../../store/simulation/useVehicleStore';
|
import { createVehicleStore, VehicleStoreType } from '../../store/simulation/useVehicleStore';
|
||||||
import { createStorageUnitStore, StorageUnitStoreType } from '../../store/simulation/useStorageUnitStore';
|
import { createStorageUnitStore, StorageUnitStoreType } from '../../store/simulation/useStorageUnitStore';
|
||||||
|
import { createHumanStore, HumanStoreType } from '../../store/simulation/useHumanStore';
|
||||||
|
|
||||||
type SceneContextValue = {
|
type SceneContextValue = {
|
||||||
|
|
||||||
@@ -35,6 +36,7 @@ type SceneContextValue = {
|
|||||||
conveyorStore: ConveyorStoreType;
|
conveyorStore: ConveyorStoreType;
|
||||||
vehicleStore: VehicleStoreType;
|
vehicleStore: VehicleStoreType;
|
||||||
storageUnitStore: StorageUnitStoreType;
|
storageUnitStore: StorageUnitStoreType;
|
||||||
|
humanStore: HumanStoreType;
|
||||||
|
|
||||||
clearStores: () => void;
|
clearStores: () => void;
|
||||||
|
|
||||||
@@ -67,6 +69,7 @@ export function SceneProvider({
|
|||||||
const conveyorStore = useMemo(() => createConveyorStore(), []);
|
const conveyorStore = useMemo(() => createConveyorStore(), []);
|
||||||
const vehicleStore = useMemo(() => createVehicleStore(), []);
|
const vehicleStore = useMemo(() => createVehicleStore(), []);
|
||||||
const storageUnitStore = useMemo(() => createStorageUnitStore(), []);
|
const storageUnitStore = useMemo(() => createStorageUnitStore(), []);
|
||||||
|
const humanStore = useMemo(() => createHumanStore(), []);
|
||||||
|
|
||||||
const clearStores = useMemo(() => () => {
|
const clearStores = useMemo(() => () => {
|
||||||
assetStore.getState().clearAssets();
|
assetStore.getState().clearAssets();
|
||||||
@@ -83,7 +86,8 @@ export function SceneProvider({
|
|||||||
conveyorStore.getState().clearConveyors();
|
conveyorStore.getState().clearConveyors();
|
||||||
vehicleStore.getState().clearVehicles();
|
vehicleStore.getState().clearVehicles();
|
||||||
storageUnitStore.getState().clearStorageUnits();
|
storageUnitStore.getState().clearStorageUnits();
|
||||||
}, [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, floorStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore]);
|
humanStore.getState().clearHumans();
|
||||||
|
}, [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, floorStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore]);
|
||||||
|
|
||||||
const contextValue = useMemo(() => (
|
const contextValue = useMemo(() => (
|
||||||
{
|
{
|
||||||
@@ -101,10 +105,11 @@ export function SceneProvider({
|
|||||||
conveyorStore,
|
conveyorStore,
|
||||||
vehicleStore,
|
vehicleStore,
|
||||||
storageUnitStore,
|
storageUnitStore,
|
||||||
|
humanStore,
|
||||||
clearStores,
|
clearStores,
|
||||||
layout
|
layout
|
||||||
}
|
}
|
||||||
), [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, floorStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, clearStores, layout]);
|
), [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, floorStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, clearStores, layout]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SceneContext.Provider value={contextValue}>
|
<SceneContext.Provider value={contextValue}>
|
||||||
|
|||||||
@@ -1,19 +1,15 @@
|
|||||||
import React, { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { useInputValues, useProductionCapacityData, useThroughPutData } from '../../../../store/builder/store'
|
import { useInputValues, useProductionCapacityData, useThroughPutData } from '../../../../store/builder/store'
|
||||||
import { usePlayButtonStore } from '../../../../store/usePlayButtonStore';
|
import { usePlayButtonStore } from '../../../../store/usePlayButtonStore';
|
||||||
import { useProductContext } from '../../products/productContext';
|
|
||||||
|
|
||||||
export default function ProductionCapacityData() {
|
export default function ProductionCapacityData() {
|
||||||
const { throughputData } = useThroughPutData()
|
const { throughputData } = useThroughPutData()
|
||||||
const { productionCapacityData, setProductionCapacityData } = useProductionCapacityData()
|
const { setProductionCapacityData } = useProductionCapacityData()
|
||||||
const { inputValues } = useInputValues();
|
const { inputValues } = useInputValues();
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
const { selectedProductStore } = useProductContext();
|
|
||||||
const { selectedProduct } = selectedProductStore();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) {
|
if (!isPlaying) {
|
||||||
|
|
||||||
setProductionCapacityData(0);
|
setProductionCapacityData(0);
|
||||||
}
|
}
|
||||||
}, [isPlaying]);
|
}, [isPlaying]);
|
||||||
@@ -26,8 +22,6 @@ export default function ProductionCapacityData() {
|
|||||||
const Monthly_working_days = workingDaysPerYear / 12;
|
const Monthly_working_days = workingDaysPerYear / 12;
|
||||||
const Production_capacity_per_month = throughputData * Monthly_working_days;
|
const Production_capacity_per_month = throughputData * Monthly_working_days;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setProductionCapacityData(Number(Production_capacity_per_month.toFixed(2)));
|
setProductionCapacityData(Number(Production_capacity_per_month.toFixed(2)));
|
||||||
}
|
}
|
||||||
}, [throughputData, inputValues, isPlaying]);
|
}, [throughputData, inputValues, isPlaying]);
|
||||||
|
|||||||
@@ -1,18 +1,9 @@
|
|||||||
import React, { useEffect } from 'react'
|
|
||||||
import { usePlayButtonStore } from '../../../store/usePlayButtonStore'
|
|
||||||
import ProductionCapacityData from './productionCapacity/productionCapacityData'
|
import ProductionCapacityData from './productionCapacity/productionCapacityData'
|
||||||
import ThroughPutData from './throughPut/throughPutData'
|
import ThroughPutData from './throughPut/throughPutData'
|
||||||
import ROIData from './ROI/roiData'
|
import ROIData from './ROI/roiData'
|
||||||
|
|
||||||
function SimulationAnalysis() {
|
function SimulationAnalysis() {
|
||||||
const { isPlaying } = usePlayButtonStore()
|
|
||||||
// useEffect(()=>{
|
|
||||||
// if (isPlaying) {
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// },[isPlaying])
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ThroughPutData />
|
<ThroughPutData />
|
||||||
|
|||||||
@@ -352,6 +352,37 @@ function PointsCreator() {
|
|||||||
</mesh>
|
</mesh>
|
||||||
</group>
|
</group>
|
||||||
);
|
);
|
||||||
|
} else if (usedEvent.type === "human") {
|
||||||
|
const point = usedEvent.point;
|
||||||
|
return (
|
||||||
|
<group
|
||||||
|
key={`${index}-${usedEvent.modelUuid}`}
|
||||||
|
position={usedEvent.position}
|
||||||
|
rotation={usedEvent.rotation}
|
||||||
|
>
|
||||||
|
<mesh
|
||||||
|
name="Event-Sphere"
|
||||||
|
uuid={point.uuid}
|
||||||
|
ref={(el) => (sphereRefs.current[point.uuid] = el!)}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (toolMode === 'cursor') {
|
||||||
|
setSelectedEventSphere(
|
||||||
|
sphereRefs.current[point.uuid]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
position={new THREE.Vector3(...point.position)}
|
||||||
|
userData={{
|
||||||
|
modelUuid: usedEvent.modelUuid,
|
||||||
|
pointUuid: point.uuid,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<sphereGeometry args={[0.1, 16, 16]} />
|
||||||
|
<meshStandardMaterial color="white" />
|
||||||
|
</mesh>
|
||||||
|
</group>
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react'
|
|
||||||
import PointsCreator from './creator/pointsCreator'
|
import PointsCreator from './creator/pointsCreator'
|
||||||
|
|
||||||
function Points() {
|
function Points() {
|
||||||
|
|||||||
@@ -152,6 +152,22 @@ function TriggerConnector() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Handle Human point
|
||||||
|
else if (event.type === "human" && 'point' in event) {
|
||||||
|
const point = event.point;
|
||||||
|
point.actions?.forEach(action => {
|
||||||
|
action.triggers?.forEach(trigger => {
|
||||||
|
if (trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint) {
|
||||||
|
newConnections.push({
|
||||||
|
id: `${point.uuid}-${trigger.triggeredAsset.triggeredPoint.pointUuid}-${trigger.triggerUuid}`,
|
||||||
|
startPointUuid: point.uuid,
|
||||||
|
endPointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
|
||||||
|
trigger
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setConnections(newConnections);
|
setConnections(newConnections);
|
||||||
|
|||||||
13
app/src/modules/simulation/human/human.tsx
Normal file
13
app/src/modules/simulation/human/human.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import HumanInstances from './instances/humanInstances'
|
||||||
|
|
||||||
|
function Human() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<HumanInstances />
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Human
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import HumanInstance from './instance/humanInstance';
|
||||||
|
import { useSceneContext } from '../../../scene/sceneContext';
|
||||||
|
|
||||||
|
function HumanInstances() {
|
||||||
|
const { humanStore } = useSceneContext();
|
||||||
|
const { humans } = humanStore();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{humans.map((human: HumanStatus) => (
|
||||||
|
<React.Fragment key={human.modelUuid}>
|
||||||
|
<HumanInstance human={human} />
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HumanInstances
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
|
function HumanInstance({ human }: { human: HumanStatus }) {
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('human: ', human);
|
||||||
|
}, [human])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HumanInstance
|
||||||
@@ -10,7 +10,7 @@ import { useParams } from 'react-router-dom';
|
|||||||
import { useVersionContext } from '../../builder/version/versionContext';
|
import { useVersionContext } from '../../builder/version/versionContext';
|
||||||
|
|
||||||
function Products() {
|
function Products() {
|
||||||
const { armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, layout, productStore } = useSceneContext();
|
const { armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, layout, productStore } = useSceneContext();
|
||||||
const { products, getProductById, addProduct, setProducts } = productStore();
|
const { products, getProductById, addProduct, setProducts } = productStore();
|
||||||
const { selectedProductStore } = useProductContext();
|
const { selectedProductStore } = useProductContext();
|
||||||
const { setMainProduct } = useMainProduct();
|
const { setMainProduct } = useMainProduct();
|
||||||
@@ -20,6 +20,7 @@ function Products() {
|
|||||||
const { addMachine, clearMachines } = machineStore();
|
const { addMachine, clearMachines } = machineStore();
|
||||||
const { addConveyor, clearConveyors } = conveyorStore();
|
const { addConveyor, clearConveyors } = conveyorStore();
|
||||||
const { setCurrentMaterials, clearStorageUnits, updateCurrentLoad, addStorageUnit } = storageUnitStore();
|
const { setCurrentMaterials, clearStorageUnits, updateCurrentLoad, addStorageUnit } = storageUnitStore();
|
||||||
|
const { addHuman, clearHumans } = humanStore();
|
||||||
const { isReset } = useResetButtonStore();
|
const { isReset } = useResetButtonStore();
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
const { mainProduct } = useMainProduct();
|
const { mainProduct } = useMainProduct();
|
||||||
@@ -153,6 +154,20 @@ function Products() {
|
|||||||
}
|
}
|
||||||
}, [selectedProduct, products, isReset, isPlaying]);
|
}, [selectedProduct, products, isReset, isPlaying]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedProduct.productUuid) {
|
||||||
|
const product = getProductById(selectedProduct.productUuid);
|
||||||
|
if (product) {
|
||||||
|
clearHumans();
|
||||||
|
product.eventDatas.forEach(events => {
|
||||||
|
if (events.type === 'human') {
|
||||||
|
addHuman(selectedProduct.productUuid, events);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [selectedProduct, products, isReset, isPlaying]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import Vehicles from './vehicle/vehicles';
|
import Vehicles from './vehicle/vehicles';
|
||||||
import Points from './events/points/points';
|
import Points from './events/points/points';
|
||||||
import Conveyor from './conveyor/conveyor';
|
import Conveyor from './conveyor/conveyor';
|
||||||
@@ -6,6 +6,7 @@ import RoboticArm from './roboticArm/roboticArm';
|
|||||||
import Materials from './materials/materials';
|
import Materials from './materials/materials';
|
||||||
import Machine from './machine/machine';
|
import Machine from './machine/machine';
|
||||||
import StorageUnit from './storageUnit/storageUnit';
|
import StorageUnit from './storageUnit/storageUnit';
|
||||||
|
import Human from './human/human';
|
||||||
import Simulator from './simulator/simulator';
|
import Simulator from './simulator/simulator';
|
||||||
import Products from './products/products';
|
import Products from './products/products';
|
||||||
import Trigger from './triggers/trigger';
|
import Trigger from './triggers/trigger';
|
||||||
@@ -52,6 +53,8 @@ function Simulation() {
|
|||||||
|
|
||||||
<StorageUnit />
|
<StorageUnit />
|
||||||
|
|
||||||
|
<Human />
|
||||||
|
|
||||||
<Simulator />
|
<Simulator />
|
||||||
|
|
||||||
<SimulationAnalysis />
|
<SimulationAnalysis />
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { usePlayButtonStore, useResetButtonStore } from '../../../store/usePlayB
|
|||||||
import { determineExecutionOrder } from './functions/determineExecutionOrder';
|
import { determineExecutionOrder } from './functions/determineExecutionOrder';
|
||||||
import { useProductContext } from '../products/productContext';
|
import { useProductContext } from '../products/productContext';
|
||||||
import { useSceneContext } from '../../scene/sceneContext';
|
import { useSceneContext } from '../../scene/sceneContext';
|
||||||
import { useCompareProductDataStore } from '../../../store/builder/store';
|
|
||||||
|
|
||||||
function Simulator() {
|
function Simulator() {
|
||||||
const { selectedProductStore } = useProductContext();
|
const { selectedProductStore } = useProductContext();
|
||||||
|
|||||||
239
app/src/store/simulation/useHumanStore.ts
Normal file
239
app/src/store/simulation/useHumanStore.ts
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
import { create } from "zustand";
|
||||||
|
import { immer } from "zustand/middleware/immer";
|
||||||
|
|
||||||
|
interface HumansStore {
|
||||||
|
humans: HumanStatus[];
|
||||||
|
|
||||||
|
addHuman: (productUuid: string, event: HumanEventSchema) => void;
|
||||||
|
removeHuman: (modelUuid: string) => void;
|
||||||
|
updateHuman: (
|
||||||
|
modelUuid: string,
|
||||||
|
updates: Partial<Omit<HumanStatus, "modelUuid" | "productUuid">>
|
||||||
|
) => void;
|
||||||
|
clearHumans: () => void;
|
||||||
|
|
||||||
|
setHumanActive: (modelUuid: string, isActive: boolean) => void;
|
||||||
|
setHumanPicking: (modelUuid: string, isPicking: boolean) => void;
|
||||||
|
setHumanLoad: (modelUuid: string, load: number) => void;
|
||||||
|
incrementHumanLoad: (modelUuid: string, incrementBy: number) => void;
|
||||||
|
decrementHumanLoad: (modelUuid: string, decrementBy: number) => void;
|
||||||
|
|
||||||
|
addCurrentMaterial: (modelUuid: string, materialType: string, materialId: string) => void;
|
||||||
|
setCurrentMaterials: (modelUuid: string, materials: { materialType: string; materialId: string }[]) => void;
|
||||||
|
removeLastMaterial: (modelUuid: string) => { materialType: string; materialId: string } | undefined;
|
||||||
|
getLastMaterial: (modelUuid: string) => { materialType: string; materialId: string } | undefined;
|
||||||
|
clearCurrentMaterials: (modelUuid: string) => void;
|
||||||
|
|
||||||
|
setCurrentAction: (
|
||||||
|
modelUuid: string,
|
||||||
|
action: HumanStatus["currentAction"]
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
|
||||||
|
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
|
||||||
|
incrementDistanceTraveled: (modelUuid: string, incrementBy: number) => void;
|
||||||
|
resetTime: (modelUuid: string) => void;
|
||||||
|
|
||||||
|
getHumanById: (modelUuid: string) => HumanStatus | undefined;
|
||||||
|
getHumansByProduct: (productUuid: string) => HumanStatus[];
|
||||||
|
getActiveHumans: () => HumanStatus[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createHumanStore = () => {
|
||||||
|
return create<HumansStore>()(
|
||||||
|
immer((set, get) => ({
|
||||||
|
humans: [],
|
||||||
|
|
||||||
|
addHuman: (productUuid, event) => {
|
||||||
|
set((state) => {
|
||||||
|
const exists = state.humans.some(h => h.modelUuid === event.modelUuid);
|
||||||
|
if (!exists) {
|
||||||
|
state.humans.push({
|
||||||
|
...event,
|
||||||
|
productUuid,
|
||||||
|
isActive: false,
|
||||||
|
isPicking: false,
|
||||||
|
idleTime: 0,
|
||||||
|
activeTime: 0,
|
||||||
|
currentLoad: 0,
|
||||||
|
currentMaterials: [],
|
||||||
|
distanceTraveled: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeHuman: (modelUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
state.humans = state.humans.filter(h => h.modelUuid !== modelUuid);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
updateHuman: (modelUuid, updates) => {
|
||||||
|
set((state) => {
|
||||||
|
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||||
|
if (human) {
|
||||||
|
Object.assign(human, updates);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
clearHumans: () => {
|
||||||
|
set((state) => {
|
||||||
|
state.humans = [];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setHumanActive: (modelUuid, isActive) => {
|
||||||
|
set((state) => {
|
||||||
|
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||||
|
if (human) {
|
||||||
|
human.isActive = isActive;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setHumanPicking: (modelUuid, isPicking) => {
|
||||||
|
set((state) => {
|
||||||
|
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||||
|
if (human) {
|
||||||
|
human.isPicking = isPicking;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setHumanLoad: (modelUuid, load) => {
|
||||||
|
set((state) => {
|
||||||
|
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||||
|
if (human) {
|
||||||
|
human.currentLoad = load;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
incrementHumanLoad: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||||
|
if (human) {
|
||||||
|
human.currentLoad += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
decrementHumanLoad: (modelUuid, decrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||||
|
if (human) {
|
||||||
|
human.currentLoad -= decrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
addCurrentMaterial: (modelUuid, materialType, materialId) => {
|
||||||
|
set((state) => {
|
||||||
|
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||||
|
if (human) {
|
||||||
|
human.currentMaterials.push({ materialType, materialId });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setCurrentMaterials: (modelUuid, materials) => {
|
||||||
|
set((state) => {
|
||||||
|
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||||
|
if (human) {
|
||||||
|
human.currentMaterials = materials;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeLastMaterial: (modelUuid) => {
|
||||||
|
let removed;
|
||||||
|
set((state) => {
|
||||||
|
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||||
|
if (human && human.currentMaterials.length > 0) {
|
||||||
|
removed = human.currentMaterials.pop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return removed;
|
||||||
|
},
|
||||||
|
|
||||||
|
getLastMaterial: (modelUuid) => {
|
||||||
|
const human = get().humans.find(h => h.modelUuid === modelUuid);
|
||||||
|
if (human && human.currentMaterials.length > 0) {
|
||||||
|
return human.currentMaterials[human.currentMaterials.length - 1];
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
|
||||||
|
clearCurrentMaterials: (modelUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||||
|
if (human) {
|
||||||
|
human.currentMaterials = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setCurrentAction: (modelUuid, action) => {
|
||||||
|
set((state) => {
|
||||||
|
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||||
|
if (human) {
|
||||||
|
human.currentAction = action;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
incrementActiveTime: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||||
|
if (human) {
|
||||||
|
human.activeTime += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
incrementIdleTime: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||||
|
if (human) {
|
||||||
|
human.idleTime += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
incrementDistanceTraveled: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||||
|
if (human) {
|
||||||
|
human.distanceTraveled += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
resetTime: (modelUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||||
|
if (human) {
|
||||||
|
human.activeTime = 0;
|
||||||
|
human.idleTime = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getHumanById: (modelUuid) => {
|
||||||
|
return get().humans.find(h => h.modelUuid === modelUuid);
|
||||||
|
},
|
||||||
|
|
||||||
|
getHumansByProduct: (productUuid) => {
|
||||||
|
return get().humans.filter(h => h.productUuid === productUuid);
|
||||||
|
},
|
||||||
|
|
||||||
|
getActiveHumans: () => {
|
||||||
|
return get().humans.filter(h => h.isActive);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export type HumanStoreType = ReturnType<typeof createHumanStore>;
|
||||||
188
app/src/types/simulationTypes.d.ts
vendored
188
app/src/types/simulationTypes.d.ts
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
// Base Types
|
||||||
interface AssetEventSchema {
|
interface AssetEventSchema {
|
||||||
modelUuid: string;
|
modelUuid: string;
|
||||||
modelName: string;
|
modelName: string;
|
||||||
@@ -18,69 +19,7 @@ interface TriggerSchema {
|
|||||||
} | null;
|
} | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ConveyorPointSchema {
|
// Actions
|
||||||
uuid: string;
|
|
||||||
position: [number, number, number];
|
|
||||||
rotation: [number, number, number];
|
|
||||||
action: ConveyorAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface VehiclePointSchema {
|
|
||||||
uuid: string;
|
|
||||||
position: [number, number, number];
|
|
||||||
rotation: [number, number, number];
|
|
||||||
action: VehicleAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface RoboticArmPointSchema {
|
|
||||||
uuid: string;
|
|
||||||
position: [number, number, number];
|
|
||||||
rotation: [number, number, number];
|
|
||||||
actions: RoboticArmAction[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface MachinePointSchema {
|
|
||||||
uuid: string;
|
|
||||||
position: [number, number, number];
|
|
||||||
rotation: [number, number, number];
|
|
||||||
action: MachineAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface StoragePointSchema {
|
|
||||||
uuid: string;
|
|
||||||
position: [number, number, number];
|
|
||||||
rotation: [number, number, number];
|
|
||||||
action: StorageAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ConveyorEventSchema extends AssetEventSchema {
|
|
||||||
type: "transfer";
|
|
||||||
speed: number;
|
|
||||||
points: ConveyorPointSchema[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface VehicleEventSchema extends AssetEventSchema {
|
|
||||||
type: "vehicle";
|
|
||||||
speed: number;
|
|
||||||
point: VehiclePointSchema;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface RoboticArmEventSchema extends AssetEventSchema {
|
|
||||||
type: "roboticArm";
|
|
||||||
speed: number;
|
|
||||||
point: RoboticArmPointSchema;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface MachineEventSchema extends AssetEventSchema {
|
|
||||||
type: "machine";
|
|
||||||
point: MachinePointSchema;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface StorageEventSchema extends AssetEventSchema {
|
|
||||||
type: "storageUnit";
|
|
||||||
point: StoragePointSchema;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ConveyorAction {
|
interface ConveyorAction {
|
||||||
actionUuid: string;
|
actionUuid: string;
|
||||||
actionName: string;
|
actionName: string;
|
||||||
@@ -130,19 +69,100 @@ interface StorageAction {
|
|||||||
triggers: TriggerSchema[];
|
triggers: TriggerSchema[];
|
||||||
}
|
}
|
||||||
|
|
||||||
type Action = ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction;
|
interface HumanAction {
|
||||||
|
actionUuid: string;
|
||||||
|
actionName: string;
|
||||||
|
actionType: "animation" | "animatedTravel";
|
||||||
|
animation: string | null;
|
||||||
|
loadCapacity: number;
|
||||||
|
travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; }
|
||||||
|
triggers: TriggerSchema[];
|
||||||
|
}
|
||||||
|
|
||||||
type PointsScheme = ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema;
|
type Action = ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction | HumanAction;
|
||||||
|
|
||||||
type EventsSchema = ConveyorEventSchema | VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema;
|
// Points
|
||||||
|
interface ConveyorPointSchema {
|
||||||
|
uuid: string;
|
||||||
|
position: [number, number, number];
|
||||||
|
rotation: [number, number, number];
|
||||||
|
action: ConveyorAction;
|
||||||
|
}
|
||||||
|
|
||||||
type productsSchema = {
|
interface VehiclePointSchema {
|
||||||
productName: string;
|
uuid: string;
|
||||||
productUuid: string;
|
position: [number, number, number];
|
||||||
eventDatas: EventsSchema[];
|
rotation: [number, number, number];
|
||||||
}[]
|
action: VehicleAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RoboticArmPointSchema {
|
||||||
|
uuid: string;
|
||||||
|
position: [number, number, number];
|
||||||
|
rotation: [number, number, number];
|
||||||
|
actions: RoboticArmAction[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MachinePointSchema {
|
||||||
|
uuid: string;
|
||||||
|
position: [number, number, number];
|
||||||
|
rotation: [number, number, number];
|
||||||
|
action: MachineAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface StoragePointSchema {
|
||||||
|
uuid: string;
|
||||||
|
position: [number, number, number];
|
||||||
|
rotation: [number, number, number];
|
||||||
|
action: StorageAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HumanPointSchema {
|
||||||
|
uuid: string;
|
||||||
|
position: [number, number, number];
|
||||||
|
rotation: [number, number, number];
|
||||||
|
actions: HumanAction[];
|
||||||
|
}
|
||||||
|
|
||||||
|
type PointsScheme = | ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | HumanPointSchema;
|
||||||
|
|
||||||
|
// Events
|
||||||
|
interface ConveyorEventSchema extends AssetEventSchema {
|
||||||
|
type: "transfer";
|
||||||
|
speed: number;
|
||||||
|
points: ConveyorPointSchema[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface VehicleEventSchema extends AssetEventSchema {
|
||||||
|
type: "vehicle";
|
||||||
|
speed: number;
|
||||||
|
point: VehiclePointSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RoboticArmEventSchema extends AssetEventSchema {
|
||||||
|
type: "roboticArm";
|
||||||
|
speed: number;
|
||||||
|
point: RoboticArmPointSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MachineEventSchema extends AssetEventSchema {
|
||||||
|
type: "machine";
|
||||||
|
point: MachinePointSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface StorageEventSchema extends AssetEventSchema {
|
||||||
|
type: "storageUnit";
|
||||||
|
point: StoragePointSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HumanEventSchema extends AssetEventSchema {
|
||||||
|
type: "human";
|
||||||
|
point: HumanPointSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
type EventsSchema = | ConveyorEventSchema | VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema | HumanEventSchema;
|
||||||
|
|
||||||
|
// Statuses
|
||||||
interface ConveyorStatus extends ConveyorEventSchema {
|
interface ConveyorStatus extends ConveyorEventSchema {
|
||||||
productUuid: string;
|
productUuid: string;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
@@ -197,6 +217,24 @@ interface StorageUnitStatus extends StorageEventSchema {
|
|||||||
currentMaterials: { materialType: string; materialId: string; }[];
|
currentMaterials: { materialType: string; materialId: string; }[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface HumanStatus extends HumanEventSchema {
|
||||||
|
productUuid: string;
|
||||||
|
isActive: boolean;
|
||||||
|
isPicking: boolean;
|
||||||
|
idleTime: number;
|
||||||
|
activeTime: number;
|
||||||
|
currentLoad: number;
|
||||||
|
currentMaterials: { materialType: string; materialId: string; }[];
|
||||||
|
distanceTraveled: number;
|
||||||
|
currentAction?: {
|
||||||
|
actionUuid: string;
|
||||||
|
actionName: string;
|
||||||
|
materialType?: string | null;
|
||||||
|
materialId?: string | null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Materials
|
||||||
interface MaterialSchema {
|
interface MaterialSchema {
|
||||||
materialId: string;
|
materialId: string;
|
||||||
materialName: string;
|
materialName: string;
|
||||||
@@ -230,6 +268,14 @@ interface MaterialSchema {
|
|||||||
|
|
||||||
type MaterialsSchema = MaterialSchema[];
|
type MaterialsSchema = MaterialSchema[];
|
||||||
|
|
||||||
|
// Products
|
||||||
|
type productsSchema = {
|
||||||
|
productName: string;
|
||||||
|
productUuid: string;
|
||||||
|
eventDatas: EventsSchema[];
|
||||||
|
}[];
|
||||||
|
|
||||||
|
// Material History
|
||||||
interface MaterialHistoryEntry {
|
interface MaterialHistoryEntry {
|
||||||
material: MaterialSchema;
|
material: MaterialSchema;
|
||||||
removedAt: string;
|
removedAt: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user