feat: Implement Zustand stores for machine, simulation, storage unit, vehicle, and visualization management
- Added `useMachineStore` for managing machine statuses, including actions for adding, removing, and updating machines. - Introduced `useSimulationStore` to handle product and event management with actions for adding, removing, and updating products and events. - Created `useStorageUnitStore` for managing storage unit statuses, including load tracking and state updates. - Developed `useVehicleStore` for vehicle management, including load and state updates. - Implemented `useChartStore` for managing measurement data and visualization settings. - Added `useDroppedObjectsStore` for handling dropped objects in visualization zones, including object manipulation actions. - Created `useZone3DWidgetStore` for managing 3D widget data in zones, including position and rotation updates. - Introduced `useZoneStore` for managing selected zone states and widget configurations.
This commit is contained in:
@@ -192,12 +192,13 @@ const Assets: React.FC = () => {
|
|||||||
src={asset?.thumbnail}
|
src={asset?.thumbnail}
|
||||||
alt={asset.filename}
|
alt={asset.filename}
|
||||||
className="asset-image"
|
className="asset-image"
|
||||||
onPointerDown={() =>
|
onPointerDown={() => {
|
||||||
setSelectedItem({
|
setSelectedItem({
|
||||||
name: asset.filename,
|
name: asset.filename,
|
||||||
id: asset.AssetID,
|
id: asset.AssetID,
|
||||||
|
type: asset.type === "undefined" ? undefined : asset.type
|
||||||
})
|
})
|
||||||
}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="asset-name">
|
<div className="asset-name">
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import RenameInput from "../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../ui/inputs/RenameInput";
|
||||||
import Vector3Input from "../customInput/Vector3Input";
|
import Vector3Input from "../customInput/Vector3Input";
|
||||||
import { useSelectedZoneStore } from "../../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../../store/visualization/useZoneStore";
|
||||||
import { useEditPosition, usezonePosition, useZones, usezoneTarget } from "../../../../store/store";
|
import { useEditPosition, usezonePosition, useZones, usezoneTarget } from "../../../../store/store";
|
||||||
import { zoneCameraUpdate } from "../../../../services/visulization/zone/zoneCameraUpdation";
|
import { zoneCameraUpdate } from "../../../../services/visulization/zone/zoneCameraUpdation";
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import React, { useEffect, useState } from "react";
|
|||||||
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
||||||
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
||||||
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useSelectedZoneStore } from "../../../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../../../store/visualization/useZoneStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import RenameInput from "../../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../../ui/inputs/RenameInput";
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import React, { useEffect, useState } from "react";
|
|||||||
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
||||||
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
||||||
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useSelectedZoneStore } from "../../../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../../../store/visualization/useZoneStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import RenameInput from "../../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../../ui/inputs/RenameInput";
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import React, { useEffect, useState } from "react";
|
|||||||
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
||||||
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
||||||
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useSelectedZoneStore } from "../../../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../../../store/visualization/useZoneStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import RenameInput from "../../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../../ui/inputs/RenameInput";
|
||||||
|
|||||||
@@ -121,8 +121,8 @@ import React, { useEffect, useState } from "react";
|
|||||||
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
||||||
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
||||||
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useSelectedZoneStore } from "../../../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../../../store/visualization/useZoneStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import RenameInput from "../../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../../ui/inputs/RenameInput";
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import React, { useEffect, useState } from "react";
|
|||||||
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
||||||
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
||||||
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useSelectedZoneStore } from "../../../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../../../store/visualization/useZoneStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import RenameInput from "../../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../../ui/inputs/RenameInput";
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import React, { useEffect, useState } from "react";
|
|||||||
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
||||||
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
||||||
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useSelectedZoneStore } from "../../../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../../../store/visualization/useZoneStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import RenameInput from "../../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../../ui/inputs/RenameInput";
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import React, { useEffect, useState } from "react";
|
|||||||
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
||||||
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
||||||
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useSelectedZoneStore } from "../../../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../../../store/visualization/useZoneStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import RenameInput from "../../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../../ui/inputs/RenameInput";
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import React, { useEffect, useState } from "react";
|
|||||||
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
||||||
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
||||||
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useSelectedZoneStore } from "../../../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../../../store/visualization/useZoneStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import RenameInput from "../../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../../ui/inputs/RenameInput";
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import React, { useEffect, useState } from "react";
|
|||||||
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
||||||
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
||||||
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useSelectedZoneStore } from "../../../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../../../store/visualization/useZoneStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import RenameInput from "../../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../../ui/inputs/RenameInput";
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import React, { useEffect, useState } from "react";
|
|||||||
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
||||||
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
||||||
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useSelectedZoneStore } from "../../../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../../../store/visualization/useZoneStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import RenameInput from "../../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../../ui/inputs/RenameInput";
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import React, { useEffect, useState } from "react";
|
|||||||
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown";
|
||||||
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
import { AddIcon } from "../../../../icons/ExportCommonIcons";
|
||||||
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useSelectedZoneStore } from "../../../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../../../store/visualization/useZoneStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import RenameInput from "../../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../../ui/inputs/RenameInput";
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import useModuleStore, { useThreeDStore } from "../../store/useModuleStore";
|
|||||||
import { handleSaveTemplate } from "../../modules//visualization/functions/handleSaveTemplate";
|
import { handleSaveTemplate } from "../../modules//visualization/functions/handleSaveTemplate";
|
||||||
import { usePlayButtonStore } from "../../store/usePlayButtonStore";
|
import { usePlayButtonStore } from "../../store/usePlayButtonStore";
|
||||||
import useTemplateStore from "../../store/useTemplateStore";
|
import useTemplateStore from "../../store/useTemplateStore";
|
||||||
import { useSelectedZoneStore } from "../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
|
||||||
import {
|
import {
|
||||||
useActiveTool,
|
useActiveTool,
|
||||||
useAddAction,
|
useAddAction,
|
||||||
@@ -38,7 +38,7 @@ import {
|
|||||||
use3DWidget,
|
use3DWidget,
|
||||||
useDroppedObjectsStore,
|
useDroppedObjectsStore,
|
||||||
useFloatingWidget,
|
useFloatingWidget,
|
||||||
} from "../../store/useDroppedObjectsStore";
|
} from "../../store/visualization/useDroppedObjectsStore";
|
||||||
|
|
||||||
const Tools: React.FC = () => {
|
const Tools: React.FC = () => {
|
||||||
const { templates } = useTemplateStore();
|
const { templates } = useTemplateStore();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import List from "./List";
|
|||||||
import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons";
|
import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons";
|
||||||
import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect";
|
import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect";
|
||||||
import { useFloorItems, useZones } from "../../../store/store";
|
import { useFloorItems, useZones } from "../../../store/store";
|
||||||
import { useSelectedZoneStore } from "../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../store/visualization/useZoneStore";
|
||||||
|
|
||||||
interface DropDownListProps {
|
interface DropDownListProps {
|
||||||
value?: string; // Value to display in the DropDownList
|
value?: string; // Value to display in the DropDownList
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import RenameInput from "../inputs/RenameInput";
|
import RenameInput from "../inputs/RenameInput";
|
||||||
|
|
||||||
import { useSelectedZoneStore } from "../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../store/visualization/useZoneStore";
|
||||||
import { getZoneData } from "../../../services/visulization/zone/getZones";
|
import { getZoneData } from "../../../services/visulization/zone/getZones";
|
||||||
import useModuleStore, {
|
import useModuleStore, {
|
||||||
useSubModuleStore,
|
useSubModuleStore,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
useRightClickSelected,
|
useRightClickSelected,
|
||||||
useRightSelected,
|
useRightSelected,
|
||||||
useTopData,
|
useTopData,
|
||||||
} from "../../../store/useZone3DWidgetStore";
|
} from "../../../store/visualization/useZone3DWidgetStore";
|
||||||
|
|
||||||
interface EditWidgetOptionProps {
|
interface EditWidgetOptionProps {
|
||||||
options: string[];
|
options: string[];
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ import DrieHtmlTemp from "..//visualization/mqttTemp/drieHtmlTemp";
|
|||||||
import ZoneGroup from "./groups/zoneGroup";
|
import ZoneGroup from "./groups/zoneGroup";
|
||||||
import useModuleStore from "../../store/useModuleStore";
|
import useModuleStore from "../../store/useModuleStore";
|
||||||
import MeasurementTool from "../scene/tools/measurementTool";
|
import MeasurementTool from "../scene/tools/measurementTool";
|
||||||
|
import NavMesh from "../simulation/vehicle/navMesh/navMesh";
|
||||||
|
|
||||||
export default function Builder() {
|
export default function Builder() {
|
||||||
const state = useThree<Types.ThreeState>(); // Importing the state from the useThree hook, which contains the scene, camera, and other Three.js elements.
|
const state = useThree<Types.ThreeState>(); // Importing the state from the useThree hook, which contains the scene, camera, and other Three.js elements.
|
||||||
@@ -347,6 +348,8 @@ export default function Builder() {
|
|||||||
|
|
||||||
<MeasurementTool />
|
<MeasurementTool />
|
||||||
|
|
||||||
|
<NavMesh lines={lines} />
|
||||||
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { retrieveGLTF, storeGLTF } from '../../../../utils/indexDB/idbUtils';
|
|||||||
import { Socket } from 'socket.io-client';
|
import { Socket } from 'socket.io-client';
|
||||||
import * as CONSTANTS from '../../../../types/world/worldConstants';
|
import * as CONSTANTS from '../../../../types/world/worldConstants';
|
||||||
import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||||
|
import PointsCalculator from '../../../simulation/events/points/pointsCalculator';
|
||||||
|
|
||||||
async function addAssetModel(
|
async function addAssetModel(
|
||||||
raycaster: THREE.Raycaster,
|
raycaster: THREE.Raycaster,
|
||||||
@@ -23,6 +24,7 @@ async function addAssetModel(
|
|||||||
socket: Socket<any>,
|
socket: Socket<any>,
|
||||||
selectedItem: any,
|
selectedItem: any,
|
||||||
setSelectedItem: any,
|
setSelectedItem: any,
|
||||||
|
addEvent: (event: EventsSchema) => void,
|
||||||
plane: Types.RefMesh,
|
plane: Types.RefMesh,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
|
||||||
@@ -63,7 +65,7 @@ async function addAssetModel(
|
|||||||
const cachedModel = THREE.Cache.get(selectedItem.id);
|
const cachedModel = THREE.Cache.get(selectedItem.id);
|
||||||
if (cachedModel) {
|
if (cachedModel) {
|
||||||
// console.log(`[Cache] Fetching ${selectedItem.name}`);
|
// console.log(`[Cache] Fetching ${selectedItem.name}`);
|
||||||
handleModelLoad(cachedModel, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, socket);
|
handleModelLoad(cachedModel, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, addEvent, socket);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
const cachedModelBlob = await retrieveGLTF(selectedItem.id);
|
const cachedModelBlob = await retrieveGLTF(selectedItem.id);
|
||||||
@@ -76,7 +78,7 @@ async function addAssetModel(
|
|||||||
URL.revokeObjectURL(blobUrl);
|
URL.revokeObjectURL(blobUrl);
|
||||||
THREE.Cache.remove(blobUrl);
|
THREE.Cache.remove(blobUrl);
|
||||||
THREE.Cache.add(selectedItem.id, gltf);
|
THREE.Cache.add(selectedItem.id, gltf);
|
||||||
handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, socket);
|
handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, addEvent, socket);
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
TempLoader(intersectPoint!, isTempLoader, tempLoader, itemsGroup);
|
TempLoader(intersectPoint!, isTempLoader, tempLoader, itemsGroup);
|
||||||
@@ -88,7 +90,7 @@ async function addAssetModel(
|
|||||||
const modelBlob = await fetch(`${url_Backend_dwinzo}/api/v2/AssetFile/${selectedItem.id}`).then((res) => res.blob());
|
const modelBlob = await fetch(`${url_Backend_dwinzo}/api/v2/AssetFile/${selectedItem.id}`).then((res) => res.blob());
|
||||||
await storeGLTF(selectedItem.id, modelBlob);
|
await storeGLTF(selectedItem.id, modelBlob);
|
||||||
THREE.Cache.add(selectedItem.id, gltf);
|
THREE.Cache.add(selectedItem.id, gltf);
|
||||||
await handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, socket);
|
await handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, addEvent, socket);
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
TempLoader(intersectPoint!, isTempLoader, tempLoader, itemsGroup);
|
TempLoader(intersectPoint!, isTempLoader, tempLoader, itemsGroup);
|
||||||
@@ -111,6 +113,7 @@ async function handleModelLoad(
|
|||||||
tempLoader: Types.RefMesh,
|
tempLoader: Types.RefMesh,
|
||||||
isTempLoader: Types.RefBoolean,
|
isTempLoader: Types.RefBoolean,
|
||||||
setFloorItems: Types.setFloorItemSetState,
|
setFloorItems: Types.setFloorItemSetState,
|
||||||
|
addEvent: (event: EventsSchema) => void,
|
||||||
socket: Socket<any>
|
socket: Socket<any>
|
||||||
) {
|
) {
|
||||||
const model = gltf.scene.clone();
|
const model = gltf.scene.clone();
|
||||||
@@ -173,6 +176,58 @@ async function handleModelLoad(
|
|||||||
socketId: socket.id
|
socketId: socket.id
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (selectedItem.type) {
|
||||||
|
const data = PointsCalculator(
|
||||||
|
selectedItem.type,
|
||||||
|
gltf.scene.clone(),
|
||||||
|
new THREE.Vector3(...model.rotation)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!data || !data.points) return;
|
||||||
|
console.log('data: ', data);
|
||||||
|
|
||||||
|
const createMarker = (point: THREE.Vector3) => {
|
||||||
|
const sphere = new THREE.SphereGeometry(0.1, 15);
|
||||||
|
const material = new THREE.MeshStandardMaterial();
|
||||||
|
const mesh = new THREE.Mesh(sphere, material);
|
||||||
|
mesh.position.copy(point);
|
||||||
|
return mesh;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (data.points && data.points.length > 0) {
|
||||||
|
data.points.forEach((Point) => {
|
||||||
|
model.add(createMarker(Point));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedItem.type === "Conveyor") {
|
||||||
|
const event: ConveyorEventSchema = {
|
||||||
|
modelUuid: newFloorItem.modeluuid,
|
||||||
|
modelName: newFloorItem.modelname,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
|
state: "idle",
|
||||||
|
type: 'transfer',
|
||||||
|
speed: 1,
|
||||||
|
points: data.points.map((point: THREE.Vector3, index: number) => ({
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
position: [point.x, point.y, point.z],
|
||||||
|
rotation: [0, 0, 0],
|
||||||
|
action: {
|
||||||
|
actionUuid: THREE.MathUtils.generateUUID(),
|
||||||
|
actionName: `Action ${index}`,
|
||||||
|
actionType: 'default',
|
||||||
|
material: 'inherit',
|
||||||
|
delay: 0,
|
||||||
|
spawnInterval: 5,
|
||||||
|
spawnCount: 1,
|
||||||
|
triggers: []
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
addEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setFloorItems((prevItems) => {
|
setFloorItems((prevItems) => {
|
||||||
const updatedItems = [...(prevItems || []), newFloorItem];
|
const updatedItems = [...(prevItems || []), newFloorItem];
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ import useModuleStore from "../../../store/useModuleStore";
|
|||||||
const assetManagerWorker = new Worker(new URL("../../../services/factoryBuilder/webWorkers/assetManagerWorker.js", import.meta.url));
|
const assetManagerWorker = new Worker(new URL("../../../services/factoryBuilder/webWorkers/assetManagerWorker.js", import.meta.url));
|
||||||
const gltfLoaderWorker = new Worker(new URL("../../../services/factoryBuilder/webWorkers/gltfLoaderWorker.js", import.meta.url));
|
const gltfLoaderWorker = new Worker(new URL("../../../services/factoryBuilder/webWorkers/gltfLoaderWorker.js", import.meta.url));
|
||||||
|
|
||||||
|
import { useEventsStore } from "../../../store/simulation/useEventsStore";
|
||||||
|
|
||||||
const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject, floorGroup, tempLoader, isTempLoader, plane, }: any) => {
|
const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject, floorGroup, tempLoader, isTempLoader, plane, }: any) => {
|
||||||
const state: Types.ThreeState = useThree();
|
const state: Types.ThreeState = useThree();
|
||||||
const { raycaster, controls }: any = state;
|
const { raycaster, controls }: any = state;
|
||||||
@@ -37,6 +39,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
|
|||||||
const { socket } = useSocketStore();
|
const { socket } = useSocketStore();
|
||||||
const loader = new GLTFLoader();
|
const loader = new GLTFLoader();
|
||||||
const dracoLoader = new DRACOLoader();
|
const dracoLoader = new DRACOLoader();
|
||||||
|
const { addEvent } = useEventsStore();
|
||||||
|
|
||||||
dracoLoader.setDecoderPath("https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/");
|
dracoLoader.setDecoderPath("https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/");
|
||||||
loader.setDRACOLoader(dracoLoader);
|
loader.setDRACOLoader(dracoLoader);
|
||||||
@@ -275,7 +278,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
|
|||||||
if (!event.dataTransfer?.files[0]) return;
|
if (!event.dataTransfer?.files[0]) return;
|
||||||
|
|
||||||
if (selectedItem.id !== "" && event.dataTransfer?.files[0]) {
|
if (selectedItem.id !== "" && event.dataTransfer?.files[0]) {
|
||||||
addAssetModel(raycaster, state.camera, state.pointer, floorGroup, setFloorItems, itemsGroup, isTempLoader, tempLoader, socket, selectedItem, setSelectedItem, plane);
|
addAssetModel(raycaster, state.camera, state.pointer, floorGroup, setFloorItems, itemsGroup, isTempLoader, tempLoader, socket, selectedItem, setSelectedItem, addEvent, plane);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -311,14 +314,14 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
|
|||||||
useFrame(() => {
|
useFrame(() => {
|
||||||
if (controls)
|
if (controls)
|
||||||
// assetVisibility(itemsGroup, state.camera.position, renderDistance);
|
// assetVisibility(itemsGroup, state.camera.position, renderDistance);
|
||||||
if (deleteTool && activeModule === "builder") {
|
if (deleteTool && activeModule === "builder") {
|
||||||
DeletableHoveredFloorItems(state, itemsGroup, hoveredDeletableFloorItem, setDeletableFloorItem);
|
DeletableHoveredFloorItems(state, itemsGroup, hoveredDeletableFloorItem, setDeletableFloorItem);
|
||||||
} else if (!deleteTool) {
|
} else if (!deleteTool) {
|
||||||
if (hoveredDeletableFloorItem.current) {
|
if (hoveredDeletableFloorItem.current) {
|
||||||
hoveredDeletableFloorItem.current = undefined;
|
hoveredDeletableFloorItem.current = undefined;
|
||||||
setDeletableFloorItem(null);
|
setDeletableFloorItem(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return <group ref={itemsGroup} name="itemsGroup"></group>;
|
return <group ref={itemsGroup} name="itemsGroup"></group>;
|
||||||
|
|||||||
47
app/src/modules/simulation/events/points/pointsCalculator.ts
Normal file
47
app/src/modules/simulation/events/points/pointsCalculator.ts
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import * as THREE from 'three';
|
||||||
|
import { Group } from '../../../../types/world/worldTypes';
|
||||||
|
|
||||||
|
function PointsCalculator(
|
||||||
|
type: string,
|
||||||
|
model: Group,
|
||||||
|
rotation: THREE.Vector3 = new THREE.Vector3()
|
||||||
|
): { points?: THREE.Vector3[] } | null {
|
||||||
|
if (!model) return null;
|
||||||
|
|
||||||
|
const box = new THREE.Box3().setFromObject(model);
|
||||||
|
|
||||||
|
const size = new THREE.Vector3();
|
||||||
|
box.getSize(size);
|
||||||
|
const center = new THREE.Vector3();
|
||||||
|
box.getCenter(center);
|
||||||
|
|
||||||
|
const rotationMatrix = new THREE.Matrix4().makeRotationFromEuler(new THREE.Euler(rotation.x, rotation.y, rotation.z));
|
||||||
|
|
||||||
|
const localTopMiddle = new THREE.Vector3(0, size.y / 2, 0);
|
||||||
|
const worldTopMiddle = localTopMiddle.clone().applyMatrix4(rotationMatrix).add(center);
|
||||||
|
|
||||||
|
if (type === 'Conveyor') {
|
||||||
|
const isWidthLonger = size.x > size.z;
|
||||||
|
const longerSize = isWidthLonger ? size.x : size.z;
|
||||||
|
const shorterSize = isWidthLonger ? size.z : size.x;
|
||||||
|
const halfLongerSize = longerSize / 2;
|
||||||
|
const halfShorterSize = shorterSize / 2;
|
||||||
|
|
||||||
|
const localEndPoint1 = new THREE.Vector3(isWidthLonger ? -halfLongerSize + halfShorterSize : 0, size.y / 2, isWidthLonger ? 0 : -halfLongerSize + halfShorterSize);
|
||||||
|
|
||||||
|
const localEndPoint2 = new THREE.Vector3(isWidthLonger ? halfLongerSize - halfShorterSize : 0, size.y / 2, isWidthLonger ? 0 : halfLongerSize - halfShorterSize);
|
||||||
|
|
||||||
|
const worldEndPoint1 = localEndPoint1.applyMatrix4(rotationMatrix).add(center);
|
||||||
|
const worldEndPoint2 = localEndPoint2.applyMatrix4(rotationMatrix).add(center);
|
||||||
|
|
||||||
|
return {
|
||||||
|
points: [worldEndPoint1, worldTopMiddle, worldEndPoint2]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
points: [worldTopMiddle]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PointsCalculator;
|
||||||
@@ -1,10 +1,23 @@
|
|||||||
import React from 'react'
|
import React, { useEffect } from 'react';
|
||||||
|
import { useEventsStore } from '../../store/simulation/useEventsStore';
|
||||||
|
import { useProductStore } from '../../store/simulation/useSimulationStore';
|
||||||
|
|
||||||
function Simulation() {
|
function Simulation() {
|
||||||
return (
|
const { events } = useEventsStore();
|
||||||
<>
|
const { products } = useProductStore();
|
||||||
</>
|
|
||||||
)
|
useEffect(() => {
|
||||||
|
console.log('events: ', events);
|
||||||
|
}, [events])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('products: ', products);
|
||||||
|
}, [products])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Simulation
|
export default Simulation
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
function VehicleAnimator() {
|
||||||
|
return (
|
||||||
|
<div>VehicleAnimator</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default VehicleAnimator
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import VehicleAnimator from '../animator/vehicleAnimator'
|
||||||
|
|
||||||
|
function VehicleInstance() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<VehicleAnimator />
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default VehicleInstance
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import VehicleInstance from './instance/vehicleInstance'
|
||||||
|
|
||||||
|
function VehicleInstances() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<VehicleInstance />
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default VehicleInstances
|
||||||
31
app/src/modules/simulation/vehicle/navMesh/navMesh.tsx
Normal file
31
app/src/modules/simulation/vehicle/navMesh/navMesh.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { useRef } from "react";
|
||||||
|
import { useNavMesh } from "../../../../store/store";
|
||||||
|
import PolygonGenerator from "./polygonGenerator";
|
||||||
|
import NavMeshDetails from "./navMeshDetails";
|
||||||
|
import * as CONSTANTS from "../../../../types/world/worldConstants";
|
||||||
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
|
|
||||||
|
type NavMeshProps = {
|
||||||
|
lines: Types.RefLines
|
||||||
|
};
|
||||||
|
|
||||||
|
function NavMesh({ lines }: NavMeshProps) {
|
||||||
|
let groupRef = useRef() as Types.RefGroup;
|
||||||
|
const { setNavMesh } = useNavMesh();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PolygonGenerator groupRef={groupRef} lines={lines} />
|
||||||
|
<NavMeshDetails lines={lines} setNavMesh={setNavMesh} groupRef={groupRef} />
|
||||||
|
|
||||||
|
<group ref={groupRef} visible={false} name="Meshes">
|
||||||
|
<mesh rotation-x={CONSTANTS.planeConfig.rotation} position={CONSTANTS.planeConfig.position3D} receiveShadow>
|
||||||
|
<planeGeometry args={[300, 300]} />
|
||||||
|
<meshBasicMaterial color={CONSTANTS.planeConfig.color} />
|
||||||
|
</mesh>
|
||||||
|
</group>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NavMesh
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import React, { useEffect } from "react";
|
||||||
|
import { init as initRecastNavigation } from "@recast-navigation/core";
|
||||||
|
import { generateSoloNavMesh } from "@recast-navigation/generators";
|
||||||
|
import { DebugDrawer, getPositionsAndIndices } from "@recast-navigation/three";
|
||||||
|
import { useThree } from "@react-three/fiber";
|
||||||
|
import * as THREE from "three";
|
||||||
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
|
|
||||||
|
interface NavMeshDetailsProps {
|
||||||
|
setNavMesh: (navMesh: any) => void;
|
||||||
|
groupRef: React.MutableRefObject<THREE.Group | null>;
|
||||||
|
lines: Types.RefLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function NavMeshDetails({
|
||||||
|
lines,
|
||||||
|
setNavMesh,
|
||||||
|
groupRef,
|
||||||
|
}: NavMeshDetailsProps) {
|
||||||
|
const { scene } = useThree();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const initializeNavigation = async () => {
|
||||||
|
try {
|
||||||
|
await initRecastNavigation();
|
||||||
|
|
||||||
|
if (!groupRef.current || groupRef.current.children.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const meshes = groupRef?.current?.children as THREE.Mesh[];
|
||||||
|
|
||||||
|
const [positions, indices] = getPositionsAndIndices(meshes);
|
||||||
|
|
||||||
|
const cellSize = 0.2;
|
||||||
|
const cellHeight = 0.7;
|
||||||
|
const walkableRadius = 0.5;
|
||||||
|
const { success, navMesh } = generateSoloNavMesh(positions, indices, {
|
||||||
|
cs: cellSize,
|
||||||
|
ch: cellHeight,
|
||||||
|
walkableRadius: Math.round(walkableRadius / cellHeight),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!success || !navMesh) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setNavMesh(navMesh);
|
||||||
|
|
||||||
|
scene.children
|
||||||
|
.filter((child) => child instanceof DebugDrawer)
|
||||||
|
.forEach((child) => scene.remove(child));
|
||||||
|
|
||||||
|
const debugDrawer = new DebugDrawer();
|
||||||
|
debugDrawer.drawNavMesh(navMesh);
|
||||||
|
// scene.add(debugDrawer);
|
||||||
|
} catch (error) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
initializeNavigation();
|
||||||
|
}, [scene, groupRef, lines.current]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
119
app/src/modules/simulation/vehicle/navMesh/polygonGenerator.tsx
Normal file
119
app/src/modules/simulation/vehicle/navMesh/polygonGenerator.tsx
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
import * as THREE from "three";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import * as turf from "@turf/turf";
|
||||||
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
|
import arrayLinesToObject from "../../../builder/geomentries/lines/lineConvertions/arrayLinesToObject";
|
||||||
|
|
||||||
|
interface PolygonGeneratorProps {
|
||||||
|
groupRef: React.MutableRefObject<THREE.Group | null>;
|
||||||
|
lines: Types.RefLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PolygonGenerator({
|
||||||
|
groupRef,
|
||||||
|
lines,
|
||||||
|
}: PolygonGeneratorProps) {
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let allLines = arrayLinesToObject(lines.current);
|
||||||
|
const wallLines = allLines?.filter((line) => line?.type === "WallLine");
|
||||||
|
const aisleLines = allLines?.filter((line) => line?.type === "AisleLine");
|
||||||
|
|
||||||
|
const wallPoints = wallLines
|
||||||
|
.map((pair) => pair?.line.map((vals) => vals.position))
|
||||||
|
.filter((wall): wall is THREE.Vector3[] => !!wall);
|
||||||
|
|
||||||
|
const result = aisleLines.map((pair) =>
|
||||||
|
pair?.line.map((point) => ({
|
||||||
|
position: [point.position.x, point.position.z],
|
||||||
|
uuid: point.uuid,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!result || result.some((line) => !line)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lineFeatures = result?.map((line: any) =>
|
||||||
|
turf.lineString(line.map((p: any) => p?.position))
|
||||||
|
);
|
||||||
|
|
||||||
|
const polygons = turf.polygonize(turf.featureCollection(lineFeatures));
|
||||||
|
renderWallGeometry(wallPoints);
|
||||||
|
|
||||||
|
if (polygons.features.length > 1) {
|
||||||
|
polygons.features.forEach((feature) => {
|
||||||
|
if (feature.geometry.type === "Polygon") {
|
||||||
|
|
||||||
|
const shape = new THREE.Shape();
|
||||||
|
const coords = feature.geometry.coordinates[0];
|
||||||
|
|
||||||
|
shape.moveTo(coords[0][0], coords[0][1]);
|
||||||
|
|
||||||
|
for (let i = 1; i < coords.length; i++) {
|
||||||
|
shape.lineTo(coords[i][0], coords[i][1]);
|
||||||
|
}
|
||||||
|
shape.lineTo(coords[0][0], coords[0][1]);
|
||||||
|
|
||||||
|
const extrudeSettings = {
|
||||||
|
depth: 5,
|
||||||
|
bevelEnabled: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
|
||||||
|
|
||||||
|
const material = new THREE.MeshBasicMaterial({ color: "blue", transparent: true, opacity: 0.5 });
|
||||||
|
const mesh = new THREE.Mesh(geometry, material);
|
||||||
|
mesh.rotateX(Math.PI / 2);
|
||||||
|
mesh.name = "agv-collider";
|
||||||
|
mesh.position.y = 5;
|
||||||
|
|
||||||
|
mesh.receiveShadow = true;
|
||||||
|
groupRef.current?.add(mesh);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [lines.current]);
|
||||||
|
|
||||||
|
const renderWallGeometry = (walls: THREE.Vector3[][]) => {
|
||||||
|
walls.forEach((wall) => {
|
||||||
|
if (wall.length < 2) return;
|
||||||
|
|
||||||
|
for (let i = 0; i < wall.length - 1; i++) {
|
||||||
|
const start = new THREE.Vector3(wall[i].x, wall[i].y, wall[i].z);
|
||||||
|
const end = new THREE.Vector3(
|
||||||
|
wall[i + 1].x,
|
||||||
|
wall[i + 1].y,
|
||||||
|
wall[i + 1].z
|
||||||
|
);
|
||||||
|
|
||||||
|
const wallHeight = 10;
|
||||||
|
const direction = new THREE.Vector3().subVectors(end, start);
|
||||||
|
const length = direction.length();
|
||||||
|
direction.normalize();
|
||||||
|
|
||||||
|
const wallGeometry = new THREE.BoxGeometry(length, wallHeight);
|
||||||
|
const wallMaterial = new THREE.MeshBasicMaterial({
|
||||||
|
color: "#aaa",
|
||||||
|
transparent: true,
|
||||||
|
opacity: 0.5,
|
||||||
|
});
|
||||||
|
|
||||||
|
const wallMesh = new THREE.Mesh(wallGeometry, wallMaterial);
|
||||||
|
const midPoint = new THREE.Vector3()
|
||||||
|
.addVectors(start, end)
|
||||||
|
.multiplyScalar(0.5);
|
||||||
|
wallMesh.position.set(midPoint.x, wallHeight / 2, midPoint.z);
|
||||||
|
|
||||||
|
const quaternion = new THREE.Quaternion();
|
||||||
|
quaternion.setFromUnitVectors(new THREE.Vector3(1, 0, 0), direction);
|
||||||
|
wallMesh.quaternion.copy(quaternion);
|
||||||
|
|
||||||
|
groupRef.current?.add(wallMesh);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
14
app/src/modules/simulation/vehicle/vehicle.tsx
Normal file
14
app/src/modules/simulation/vehicle/vehicle.tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import VehicleInstances from './instances/vehicleInstances';
|
||||||
|
|
||||||
|
function Vehicle() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<VehicleInstances />
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Vehicle
|
||||||
@@ -2,7 +2,7 @@ import React, { useEffect, useState, useRef } from "react";
|
|||||||
import { usePlayButtonStore } from "../../store/usePlayButtonStore";
|
import { usePlayButtonStore } from "../../store/usePlayButtonStore";
|
||||||
import Panel from "./widgets/panel/Panel";
|
import Panel from "./widgets/panel/Panel";
|
||||||
import AddButtons from "./widgets/panel/AddButtons";
|
import AddButtons from "./widgets/panel/AddButtons";
|
||||||
import { useSelectedZoneStore } from "../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
|
||||||
import DisplayZone from "./zone/DisplayZone";
|
import DisplayZone from "./zone/DisplayZone";
|
||||||
import Scene from "../scene/scene";
|
import Scene from "../scene/scene";
|
||||||
import useModuleStore from "../../store/useModuleStore";
|
import useModuleStore from "../../store/useModuleStore";
|
||||||
@@ -10,7 +10,7 @@ import useModuleStore from "../../store/useModuleStore";
|
|||||||
import {
|
import {
|
||||||
useDroppedObjectsStore,
|
useDroppedObjectsStore,
|
||||||
useFloatingWidget,
|
useFloatingWidget,
|
||||||
} from "../../store/useDroppedObjectsStore";
|
} from "../../store/visualization/useDroppedObjectsStore";
|
||||||
import {
|
import {
|
||||||
useAsset3dWidget,
|
useAsset3dWidget,
|
||||||
useSocketStore,
|
useSocketStore,
|
||||||
@@ -30,7 +30,7 @@ import {
|
|||||||
useEditWidgetOptionsStore,
|
useEditWidgetOptionsStore,
|
||||||
useRightClickSelected,
|
useRightClickSelected,
|
||||||
useRightSelected,
|
useRightSelected,
|
||||||
} from "../../store/useZone3DWidgetStore";
|
} from "../../store/visualization/useZone3DWidgetStore";
|
||||||
import OuterClick from "../../utils/outerClick";
|
import OuterClick from "../../utils/outerClick";
|
||||||
import { useWidgetStore } from "../../store/useWidgetStore";
|
import { useWidgetStore } from "../../store/useWidgetStore";
|
||||||
import { getActiveProperties } from "./functions/getActiveProperties";
|
import { getActiveProperties } from "./functions/getActiveProperties";
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useSocketStore } from "../../../store/store";
|
import { useSocketStore } from "../../../store/store";
|
||||||
import { useSelectedZoneStore } from "../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../store/visualization/useZoneStore";
|
||||||
import { useDroppedObjectsStore } from "../../../store/useDroppedObjectsStore";
|
import { useDroppedObjectsStore } from "../../../store/visualization/useDroppedObjectsStore";
|
||||||
import { useZoneWidgetStore } from "../../../store/useZone3DWidgetStore";
|
import { useZoneWidgetStore } from "../../../store/visualization/useZone3DWidgetStore";
|
||||||
import useTemplateStore from "../../../store/useTemplateStore";
|
import useTemplateStore from "../../../store/useTemplateStore";
|
||||||
|
|
||||||
type WidgetData = {
|
type WidgetData = {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import useTemplateStore from "../../../store/useTemplateStore";
|
import useTemplateStore from "../../../store/useTemplateStore";
|
||||||
import { useSelectedZoneStore } from "../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../store/visualization/useZoneStore";
|
||||||
import { useSocketStore } from "../../../store/store";
|
import { useSocketStore } from "../../../store/store";
|
||||||
import { getTemplateData } from "../../../services/visulization/zone/getTemplate";
|
import { getTemplateData } from "../../../services/visulization/zone/getTemplate";
|
||||||
import { useDroppedObjectsStore } from "../../../store/useDroppedObjectsStore";
|
import { useDroppedObjectsStore } from "../../../store/visualization/useDroppedObjectsStore";
|
||||||
import RenameInput from "../../../components/ui/inputs/RenameInput";
|
import RenameInput from "../../../components/ui/inputs/RenameInput";
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import { useClickOutside } from "../../functions/handleWidgetsOuterClick";
|
|||||||
import { useSocketStore } from "../../../../store/store";
|
import { useSocketStore } from "../../../../store/store";
|
||||||
import { usePlayButtonStore } from "../../../../store/usePlayButtonStore";
|
import { usePlayButtonStore } from "../../../../store/usePlayButtonStore";
|
||||||
import OuterClick from "../../../../utils/outerClick";
|
import OuterClick from "../../../../utils/outerClick";
|
||||||
import useChartStore from "../../../../store/useChartStore";
|
import useChartStore from "../../../../store/visualization/useChartStore";
|
||||||
|
|
||||||
type Side = "top" | "bottom" | "left" | "right";
|
type Side = "top" | "bottom" | "left" | "right";
|
||||||
|
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ import io from "socket.io-client";
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { useThemeStore } from "../../../../../store/useThemeStore";
|
import { useThemeStore } from "../../../../../store/useThemeStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
|
|
||||||
interface ChartComponentProps {
|
interface ChartComponentProps {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import io from "socket.io-client";
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { useThemeStore } from "../../../../../store/useThemeStore";
|
import { useThemeStore } from "../../../../../store/useThemeStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
|
|
||||||
interface ChartComponentProps {
|
interface ChartComponentProps {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import io from "socket.io-client";
|
|||||||
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { useThemeStore } from "../../../../../store/useThemeStore";
|
import { useThemeStore } from "../../../../../store/useThemeStore";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
|
|
||||||
interface ChartComponentProps {
|
interface ChartComponentProps {
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ import io from "socket.io-client";
|
|||||||
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { useThemeStore } from "../../../../../store/useThemeStore";
|
import { useThemeStore } from "../../../../../store/useThemeStore";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
|
|
||||||
interface ChartComponentProps {
|
interface ChartComponentProps {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import io from "socket.io-client";
|
|||||||
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { useThemeStore } from "../../../../../store/useThemeStore";
|
import { useThemeStore } from "../../../../../store/useThemeStore";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
|
|
||||||
interface ChartComponentProps {
|
interface ChartComponentProps {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Line } from "react-chartjs-2";
|
|||||||
import io from "socket.io-client";
|
import io from "socket.io-client";
|
||||||
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import { StockIncreseIcon } from "../../../../../components/icons/RealTimeVisulationIcons";
|
import { StockIncreseIcon } from "../../../../../components/icons/RealTimeVisulationIcons";
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Line } from "react-chartjs-2";
|
|||||||
import io from "socket.io-client";
|
import io from "socket.io-client";
|
||||||
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import { StockIncreseIcon } from "../../../../../components/icons/RealTimeVisulationIcons";
|
import { StockIncreseIcon } from "../../../../../components/icons/RealTimeVisulationIcons";
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import React, { useEffect, useRef, useState } from "react";
|
|||||||
import { useAsset3dWidget, useSocketStore, useWidgetSubOption } from "../../../../store/store";
|
import { useAsset3dWidget, useSocketStore, useWidgetSubOption } from "../../../../store/store";
|
||||||
import useModuleStore from "../../../../store/useModuleStore";
|
import useModuleStore from "../../../../store/useModuleStore";
|
||||||
import { ThreeState } from "../../../../types/world/worldTypes";
|
import { ThreeState } from "../../../../types/world/worldTypes";
|
||||||
import { useSelectedZoneStore } from "../../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../../store/visualization/useZoneStore";
|
||||||
import { useEditWidgetOptionsStore, useLeftData, useRightClickSelected, useRightSelected, useTopData, useZoneWidgetStore } from "../../../../store/useZone3DWidgetStore";
|
import { useEditWidgetOptionsStore, useLeftData, useRightClickSelected, useRightSelected, useTopData, useZoneWidgetStore } from "../../../../store/visualization/useZone3DWidgetStore";
|
||||||
import { use3DWidget } from "../../../../store/useDroppedObjectsStore";
|
import { use3DWidget } from "../../../../store/visualization/useDroppedObjectsStore";
|
||||||
import { get3dWidgetZoneData } from "../../../../services/visulization/zone/get3dWidgetData";
|
import { get3dWidgetZoneData } from "../../../../services/visulization/zone/get3dWidgetData";
|
||||||
import { generateUniqueId } from "../../../../functions/generateUniqueId";
|
import { generateUniqueId } from "../../../../functions/generateUniqueId";
|
||||||
import ProductionCapacity from "./cards/ProductionCapacity";
|
import ProductionCapacity from "./cards/ProductionCapacity";
|
||||||
@@ -14,7 +14,7 @@ import ReturnOfInvestment from "./cards/ReturnOfInvestment";
|
|||||||
import StateWorking from "./cards/StateWorking";
|
import StateWorking from "./cards/StateWorking";
|
||||||
import Throughput from "./cards/Throughput";
|
import Throughput from "./cards/Throughput";
|
||||||
import { useWidgetStore } from "../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../store/useWidgetStore";
|
||||||
import useChartStore from "../../../../store/useChartStore";
|
import useChartStore from "../../../../store/visualization/useChartStore";
|
||||||
|
|
||||||
type WidgetData = {
|
type WidgetData = {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import io from "socket.io-client";
|
import io from "socket.io-client";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
|
|
||||||
// Register ChartJS components
|
// Register ChartJS components
|
||||||
ChartJS.register(
|
ChartJS.register(
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import io from "socket.io-client";
|
import io from "socket.io-client";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { WavyIcon } from "../../../../../components/icons/3dChartIcons";
|
import { WavyIcon } from "../../../../../components/icons/3dChartIcons";
|
||||||
|
|
||||||
// Register Chart.js components
|
// Register Chart.js components
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import React, { useEffect, useMemo, useState } from "react";
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import io from "socket.io-client";
|
import io from "socket.io-client";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
|
|
||||||
// import image from "../../../../assets/image/temp/image.png";
|
// import image from "../../../../assets/image/temp/image.png";
|
||||||
interface StateWorkingProps {
|
interface StateWorkingProps {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import {
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import io from "socket.io-client";
|
import io from "socket.io-client";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { ThroughputIcon } from "../../../../../components/icons/3dChartIcons";
|
import { ThroughputIcon } from "../../../../../components/icons/3dChartIcons";
|
||||||
|
|
||||||
// Register Chart.js components
|
// Register Chart.js components
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { useEffect, useRef, useState } from "react";
|
|||||||
import {
|
import {
|
||||||
useDroppedObjectsStore,
|
useDroppedObjectsStore,
|
||||||
Zones,
|
Zones,
|
||||||
} from "../../../../store/useDroppedObjectsStore";
|
} from "../../../../store/visualization/useDroppedObjectsStore";
|
||||||
import useModuleStore from "../../../../store/useModuleStore";
|
import useModuleStore from "../../../../store/useModuleStore";
|
||||||
import { determinePosition } from "../../functions/determinePosition";
|
import { determinePosition } from "../../functions/determinePosition";
|
||||||
import { getActiveProperties } from "../../functions/getActiveProperties";
|
import { getActiveProperties } from "../../functions/getActiveProperties";
|
||||||
@@ -23,7 +23,7 @@ import { useWidgetStore } from "../../../../store/useWidgetStore";
|
|||||||
import { useSocketStore } from "../../../../store/store";
|
import { useSocketStore } from "../../../../store/store";
|
||||||
import { useClickOutside } from "../../functions/handleWidgetsOuterClick";
|
import { useClickOutside } from "../../functions/handleWidgetsOuterClick";
|
||||||
import { usePlayButtonStore } from "../../../../store/usePlayButtonStore";
|
import { usePlayButtonStore } from "../../../../store/usePlayButtonStore";
|
||||||
import { useSelectedZoneStore } from "../../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../../store/visualization/useZoneStore";
|
||||||
interface DraggingState {
|
interface DraggingState {
|
||||||
zone: string;
|
zone: string;
|
||||||
index: number;
|
index: number;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Line } from "react-chartjs-2";
|
import { Line } from "react-chartjs-2";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import io from "socket.io-client";
|
import io from "socket.io-client";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Line } from "react-chartjs-2";
|
import { Line } from "react-chartjs-2";
|
||||||
import useChartStore from "../../../../../store/useChartStore";
|
import useChartStore from "../../../../../store/visualization/useChartStore";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import io from "socket.io-client";
|
import io from "socket.io-client";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import { Line } from 'react-chartjs-2'
|
import { Line } from 'react-chartjs-2'
|
||||||
import useChartStore from '../../../../../store/useChartStore';
|
import useChartStore from '../../../../../store/visualization/useChartStore';
|
||||||
import { useWidgetStore } from '../../../../../store/useWidgetStore';
|
import { useWidgetStore } from '../../../../../store/useWidgetStore';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import io from "socket.io-client";
|
import io from "socket.io-client";
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useWidgetStore, Widget } from "../../../store/useWidgetStore";
|
|||||||
import {
|
import {
|
||||||
useDroppedObjectsStore,
|
useDroppedObjectsStore,
|
||||||
useFloatingWidget,
|
useFloatingWidget,
|
||||||
} from "../../../store/useDroppedObjectsStore";
|
} from "../../../store/visualization/useDroppedObjectsStore";
|
||||||
import { getSelect2dZoneData } from "../../../services/visulization/zone/getSelect2dZoneData";
|
import { getSelect2dZoneData } from "../../../services/visulization/zone/getSelect2dZoneData";
|
||||||
import { getFloatingZoneData } from "../../../services/visulization/zone/getFloatingData";
|
import { getFloatingZoneData } from "../../../services/visulization/zone/getFloatingData";
|
||||||
import { get3dWidgetZoneData } from "../../../services/visulization/zone/get3dWidgetData";
|
import { get3dWidgetZoneData } from "../../../services/visulization/zone/get3dWidgetData";
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useMemo, useRef, useState } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { useFrame, useThree } from "@react-three/fiber";
|
import { useFrame, useThree } from "@react-three/fiber";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { useSelectedZoneStore } from "../../../store/useZoneStore";
|
import { useSelectedZoneStore } from "../../../store/visualization/useZoneStore";
|
||||||
import { useEditPosition, usezonePosition, usezoneTarget } from "../../../store/store";
|
import { useEditPosition, usezonePosition, usezoneTarget } from "../../../store/store";
|
||||||
|
|
||||||
export default function ZoneCentreTarget() {
|
export default function ZoneCentreTarget() {
|
||||||
|
|||||||
172
app/src/store/simulation/useArmBotStore.ts
Normal file
172
app/src/store/simulation/useArmBotStore.ts
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
import { create } from 'zustand';
|
||||||
|
import { immer } from 'zustand/middleware/immer';
|
||||||
|
|
||||||
|
interface ArmBotStatus extends RoboticArmSchemaEvent {
|
||||||
|
productId: string;
|
||||||
|
isActive: boolean;
|
||||||
|
idleTime: number;
|
||||||
|
activeTime: number;
|
||||||
|
currentAction?: {
|
||||||
|
actionUuid: string;
|
||||||
|
actionName: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ArmBotStore {
|
||||||
|
armBots: Record<string, ArmBotStatus>;
|
||||||
|
|
||||||
|
// ArmBot actions
|
||||||
|
addArmBot: (productId: string, event: RoboticArmSchemaEvent) => void;
|
||||||
|
removeArmBot: (modelUuid: string) => void;
|
||||||
|
updateArmBot: (
|
||||||
|
modelUuid: string,
|
||||||
|
updates: Partial<Omit<ArmBotStatus, 'modelUuid' | 'productId'>>
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
// Action management
|
||||||
|
startAction: (modelUuid: string, actionUuid: string) => void;
|
||||||
|
completeAction: (modelUuid: string) => void;
|
||||||
|
cancelAction: (modelUuid: string) => void;
|
||||||
|
|
||||||
|
// Status updates
|
||||||
|
setArmBotActive: (modelUuid: string, isActive: boolean) => void;
|
||||||
|
|
||||||
|
// Time tracking
|
||||||
|
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
|
||||||
|
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
|
||||||
|
|
||||||
|
// Helper functions
|
||||||
|
getArmBotById: (modelUuid: string) => ArmBotStatus | undefined;
|
||||||
|
getArmBotsByProduct: (productId: string) => ArmBotStatus[];
|
||||||
|
getActiveArmBots: () => ArmBotStatus[];
|
||||||
|
getIdleArmBots: () => ArmBotStatus[];
|
||||||
|
getArmBotsByCurrentAction: (actionUuid: string) => ArmBotStatus[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useArmBotStore = create<ArmBotStore>()(
|
||||||
|
immer((set, get) => ({
|
||||||
|
armBots: {},
|
||||||
|
|
||||||
|
// ArmBot actions
|
||||||
|
addArmBot: (productId, event) => {
|
||||||
|
set((state) => {
|
||||||
|
state.armBots[event.modelUuid] = {
|
||||||
|
...event,
|
||||||
|
productId,
|
||||||
|
isActive: false,
|
||||||
|
idleTime: 0,
|
||||||
|
activeTime: 0,
|
||||||
|
state: 'idle'
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeArmBot: (modelUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
delete state.armBots[modelUuid];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
updateArmBot: (modelUuid, updates) => {
|
||||||
|
set((state) => {
|
||||||
|
const armBot = state.armBots[modelUuid];
|
||||||
|
if (armBot) {
|
||||||
|
Object.assign(armBot, updates);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Action management
|
||||||
|
startAction: (modelUuid, actionUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
const armBot = state.armBots[modelUuid];
|
||||||
|
if (armBot) {
|
||||||
|
const action = armBot.point.actions.find(a => a.actionUuid === actionUuid);
|
||||||
|
if (action) {
|
||||||
|
armBot.currentAction = {
|
||||||
|
actionUuid: action.actionUuid,
|
||||||
|
actionName: action.actionName
|
||||||
|
};
|
||||||
|
armBot.isActive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
completeAction: (modelUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
const armBot = state.armBots[modelUuid];
|
||||||
|
if (armBot && armBot.currentAction) {
|
||||||
|
armBot.currentAction = undefined;
|
||||||
|
armBot.isActive = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
cancelAction: (modelUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
const armBot = state.armBots[modelUuid];
|
||||||
|
if (armBot) {
|
||||||
|
armBot.currentAction = undefined;
|
||||||
|
armBot.isActive = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Status updates
|
||||||
|
setArmBotActive: (modelUuid, isActive) => {
|
||||||
|
set((state) => {
|
||||||
|
const armBot = state.armBots[modelUuid];
|
||||||
|
if (armBot) {
|
||||||
|
armBot.isActive = isActive;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Time tracking
|
||||||
|
incrementActiveTime: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const armBot = state.armBots[modelUuid];
|
||||||
|
if (armBot) {
|
||||||
|
armBot.activeTime += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
incrementIdleTime: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const armBot = state.armBots[modelUuid];
|
||||||
|
if (armBot) {
|
||||||
|
armBot.idleTime += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Helper functions
|
||||||
|
getArmBotById: (modelUuid) => {
|
||||||
|
return get().armBots[modelUuid];
|
||||||
|
},
|
||||||
|
|
||||||
|
getArmBotsByProduct: (productId) => {
|
||||||
|
return Object.values(get().armBots).filter(
|
||||||
|
a => a.productId === productId
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
getActiveArmBots: () => {
|
||||||
|
return Object.values(get().armBots).filter(a => a.isActive);
|
||||||
|
},
|
||||||
|
|
||||||
|
getIdleArmBots: () => {
|
||||||
|
return Object.values(get().armBots).filter(
|
||||||
|
a => !a.isActive && a.state === 'idle'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
getArmBotsByCurrentAction: (actionUuid) => {
|
||||||
|
return Object.values(get().armBots).filter(
|
||||||
|
a => a.currentAction?.actionUuid === actionUuid
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
);
|
||||||
129
app/src/store/simulation/useConveyorStore.ts
Normal file
129
app/src/store/simulation/useConveyorStore.ts
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
import { create } from 'zustand';
|
||||||
|
import { immer } from 'zustand/middleware/immer';
|
||||||
|
|
||||||
|
interface ConveyorStatus extends ConveyorEventSchema {
|
||||||
|
productId: string;
|
||||||
|
isActive: boolean;
|
||||||
|
idleTime: number;
|
||||||
|
activeTime: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ConveyorStore {
|
||||||
|
conveyors: Record<string, ConveyorStatus>;
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
addConveyor: (productId: string, event: ConveyorEventSchema) => void;
|
||||||
|
removeConveyor: (modelUuid: string) => void;
|
||||||
|
updateConveyor: (
|
||||||
|
modelUuid: string,
|
||||||
|
updates: Partial<Omit<ConveyorStatus, 'modelUuid' | 'productId'>>
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
// Status updates
|
||||||
|
setConveyorActive: (modelUuid: string, isActive: boolean) => void;
|
||||||
|
setConveyorState: (modelUuid: string, newState: ConveyorStatus['state']) => void;
|
||||||
|
|
||||||
|
// Time tracking
|
||||||
|
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
|
||||||
|
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
|
||||||
|
|
||||||
|
// Helper functions
|
||||||
|
getConveyorById: (modelUuid: string) => ConveyorStatus | undefined;
|
||||||
|
getConveyorsByProduct: (productId: string) => ConveyorStatus[];
|
||||||
|
getActiveConveyors: () => ConveyorStatus[];
|
||||||
|
getIdleConveyors: () => ConveyorStatus[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useConveyorStore = create<ConveyorStore>()(
|
||||||
|
immer((set, get) => ({
|
||||||
|
conveyors: {},
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
addConveyor: (productId, event) => {
|
||||||
|
set((state) => {
|
||||||
|
state.conveyors[event.modelUuid] = {
|
||||||
|
...event,
|
||||||
|
productId,
|
||||||
|
isActive: false,
|
||||||
|
idleTime: 0,
|
||||||
|
activeTime: 0,
|
||||||
|
state: 'idle',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeConveyor: (modelUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
delete state.conveyors[modelUuid];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
updateConveyor: (modelUuid, updates) => {
|
||||||
|
set((state) => {
|
||||||
|
const conveyor = state.conveyors[modelUuid];
|
||||||
|
if (conveyor) {
|
||||||
|
Object.assign(conveyor, updates);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Status updates
|
||||||
|
setConveyorActive: (modelUuid, isActive) => {
|
||||||
|
set((state) => {
|
||||||
|
const conveyor = state.conveyors[modelUuid];
|
||||||
|
if (conveyor) {
|
||||||
|
conveyor.isActive = isActive;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setConveyorState: (modelUuid, newState) => {
|
||||||
|
set((state) => {
|
||||||
|
const conveyor = state.conveyors[modelUuid];
|
||||||
|
if (conveyor) {
|
||||||
|
conveyor.state = newState;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Time tracking
|
||||||
|
incrementActiveTime: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const conveyor = state.conveyors[modelUuid];
|
||||||
|
if (conveyor) {
|
||||||
|
conveyor.activeTime += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
incrementIdleTime: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const conveyor = state.conveyors[modelUuid];
|
||||||
|
if (conveyor) {
|
||||||
|
conveyor.idleTime += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Helper functions
|
||||||
|
getConveyorById: (modelUuid) => {
|
||||||
|
return get().conveyors[modelUuid];
|
||||||
|
},
|
||||||
|
|
||||||
|
getConveyorsByProduct: (productId) => {
|
||||||
|
return Object.values(get().conveyors).filter(
|
||||||
|
c => c.productId === productId
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
getActiveConveyors: () => {
|
||||||
|
return Object.values(get().conveyors).filter(c => c.isActive);
|
||||||
|
},
|
||||||
|
|
||||||
|
getIdleConveyors: () => {
|
||||||
|
return Object.values(get().conveyors).filter(
|
||||||
|
c => !c.isActive && c.state === 'idle'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
);
|
||||||
@@ -1,37 +1,33 @@
|
|||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { immer } from 'zustand/middleware/immer';
|
import { immer } from 'zustand/middleware/immer';
|
||||||
import { useProductStore } from './useSimulationStore';
|
|
||||||
|
|
||||||
type EventsStore = {
|
type EventsStore = {
|
||||||
events: EventsSchema[];
|
events: EventsSchema[];
|
||||||
|
|
||||||
// Sync with product store
|
|
||||||
syncFromProducts: (products: productsSchema) => void;
|
|
||||||
|
|
||||||
// Event-level actions
|
// Event-level actions
|
||||||
addEvent: (event: EventsSchema) => void;
|
addEvent: (event: EventsSchema) => void;
|
||||||
removeEvent: (modelUuid: string) => void;
|
removeEvent: (modelUuid: string) => void;
|
||||||
updateEvent: (modelUuid: string, updates: Partial<EventsSchema>) => void;
|
updateEvent: (modelUuid: string, updates: Partial<EventsSchema>) => void;
|
||||||
|
|
||||||
// Point-level actions
|
// Point-level actions
|
||||||
addPoint: (modelUuid: string, point: TransferPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema) => void;
|
addPoint: (modelUuid: string, point: ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema) => void;
|
||||||
removePoint: (modelUuid: string, pointUuid: string) => void;
|
removePoint: (modelUuid: string, pointUuid: string) => void;
|
||||||
updatePoint: (
|
updatePoint: (
|
||||||
modelUuid: string,
|
modelUuid: string,
|
||||||
pointUuid: string,
|
pointUuid: string,
|
||||||
updates: Partial<TransferPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema>
|
updates: Partial<ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema>
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
// Action-level actions
|
// Action-level actions
|
||||||
addAction: (
|
addAction: (
|
||||||
modelUuid: string,
|
modelUuid: string,
|
||||||
pointUuid: string,
|
pointUuid: string,
|
||||||
action: TransferPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']
|
action: ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']
|
||||||
) => void;
|
) => void;
|
||||||
removeAction: (actionUuid: string) => void;
|
removeAction: (actionUuid: string) => void;
|
||||||
updateAction: (
|
updateAction: (
|
||||||
actionUuid: string,
|
actionUuid: string,
|
||||||
updates: Partial<TransferPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']>
|
updates: Partial<ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']>
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
// Trigger-level actions
|
// Trigger-level actions
|
||||||
@@ -41,8 +37,8 @@ type EventsStore = {
|
|||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
getEventByModelUuid: (modelUuid: string) => EventsSchema | undefined;
|
getEventByModelUuid: (modelUuid: string) => EventsSchema | undefined;
|
||||||
getPointByUuid: (modelUuid: string, pointUuid: string) => TransferPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | undefined;
|
getPointByUuid: (modelUuid: string, pointUuid: string) => ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | undefined;
|
||||||
getActionByUuid: (actionUuid: string) => (TransferPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']) | undefined;
|
getActionByUuid: (actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']) | undefined;
|
||||||
getTriggerByUuid: (triggerUuid: string) => TriggerSchema | undefined;
|
getTriggerByUuid: (triggerUuid: string) => TriggerSchema | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,13 +46,6 @@ export const useEventsStore = create<EventsStore>()(
|
|||||||
immer((set, get) => ({
|
immer((set, get) => ({
|
||||||
events: [],
|
events: [],
|
||||||
|
|
||||||
// Sync events from products store
|
|
||||||
syncFromProducts: (products) => {
|
|
||||||
set((state) => {
|
|
||||||
state.events = products.flatMap(product => product.eventsData);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// Event-level actions
|
// Event-level actions
|
||||||
addEvent: (event) => {
|
addEvent: (event) => {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
@@ -84,7 +73,7 @@ export const useEventsStore = create<EventsStore>()(
|
|||||||
set((state) => {
|
set((state) => {
|
||||||
const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||||
if (event && 'points' in event) {
|
if (event && 'points' in event) {
|
||||||
(event as TransferEventSchema).points.push(point as TransferPointSchema);
|
(event as ConveyorEventSchema).points.push(point as ConveyorPointSchema);
|
||||||
} else if (event && 'point' in event) {
|
} else if (event && 'point' in event) {
|
||||||
(event as VehicleSchemaEvent | RoboticArmSchemaEvent | MachineSchemaEvent | StorageSchemaEvent).point = point as any;
|
(event as VehicleSchemaEvent | RoboticArmSchemaEvent | MachineSchemaEvent | StorageSchemaEvent).point = point as any;
|
||||||
}
|
}
|
||||||
@@ -95,7 +84,7 @@ export const useEventsStore = create<EventsStore>()(
|
|||||||
set((state) => {
|
set((state) => {
|
||||||
const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||||
if (event && 'points' in event) {
|
if (event && 'points' in event) {
|
||||||
(event as TransferEventSchema).points = (event as TransferEventSchema).points.filter(p => p.uuid !== pointUuid);
|
(event as ConveyorEventSchema).points = (event as ConveyorEventSchema).points.filter(p => p.uuid !== pointUuid);
|
||||||
}
|
}
|
||||||
// For single-point events, you might want to handle differently
|
// For single-point events, you might want to handle differently
|
||||||
});
|
});
|
||||||
@@ -105,7 +94,7 @@ export const useEventsStore = create<EventsStore>()(
|
|||||||
set((state) => {
|
set((state) => {
|
||||||
const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||||
if (event && 'points' in event) {
|
if (event && 'points' in event) {
|
||||||
const point = (event as TransferEventSchema).points.find(p => p.uuid === pointUuid);
|
const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
|
||||||
if (point) {
|
if (point) {
|
||||||
Object.assign(point, updates);
|
Object.assign(point, updates);
|
||||||
}
|
}
|
||||||
@@ -120,7 +109,7 @@ export const useEventsStore = create<EventsStore>()(
|
|||||||
set((state) => {
|
set((state) => {
|
||||||
const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||||
if (event && 'points' in event) {
|
if (event && 'points' in event) {
|
||||||
const point = (event as TransferEventSchema).points.find(p => p.uuid === pointUuid);
|
const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
|
||||||
if (point) {
|
if (point) {
|
||||||
point.action = action as any;
|
point.action = action as any;
|
||||||
}
|
}
|
||||||
@@ -138,7 +127,7 @@ export const useEventsStore = create<EventsStore>()(
|
|||||||
set((state) => {
|
set((state) => {
|
||||||
for (const event of state.events) {
|
for (const event of state.events) {
|
||||||
if ('points' in event) {
|
if ('points' in event) {
|
||||||
for (const point of (event as TransferEventSchema).points) {
|
for (const point of (event as ConveyorEventSchema).points) {
|
||||||
if (point.action && point.action.actionUuid === actionUuid) {
|
if (point.action && point.action.actionUuid === actionUuid) {
|
||||||
// Handle removal for single action points
|
// Handle removal for single action points
|
||||||
}
|
}
|
||||||
@@ -161,7 +150,7 @@ export const useEventsStore = create<EventsStore>()(
|
|||||||
set((state) => {
|
set((state) => {
|
||||||
for (const event of state.events) {
|
for (const event of state.events) {
|
||||||
if ('points' in event) {
|
if ('points' in event) {
|
||||||
for (const point of (event as TransferEventSchema).points) {
|
for (const point of (event as ConveyorEventSchema).points) {
|
||||||
if (point.action && point.action.actionUuid === actionUuid) {
|
if (point.action && point.action.actionUuid === actionUuid) {
|
||||||
Object.assign(point.action, updates);
|
Object.assign(point.action, updates);
|
||||||
return;
|
return;
|
||||||
@@ -189,7 +178,7 @@ export const useEventsStore = create<EventsStore>()(
|
|||||||
set((state) => {
|
set((state) => {
|
||||||
for (const event of state.events) {
|
for (const event of state.events) {
|
||||||
if ('points' in event) {
|
if ('points' in event) {
|
||||||
for (const point of (event as TransferEventSchema).points) {
|
for (const point of (event as ConveyorEventSchema).points) {
|
||||||
if (point.action && point.action.actionUuid === actionUuid) {
|
if (point.action && point.action.actionUuid === actionUuid) {
|
||||||
point.action.triggers.push(trigger);
|
point.action.triggers.push(trigger);
|
||||||
return;
|
return;
|
||||||
@@ -216,7 +205,7 @@ export const useEventsStore = create<EventsStore>()(
|
|||||||
set((state) => {
|
set((state) => {
|
||||||
for (const event of state.events) {
|
for (const event of state.events) {
|
||||||
if ('points' in event) {
|
if ('points' in event) {
|
||||||
for (const point of (event as TransferEventSchema).points) {
|
for (const point of (event as ConveyorEventSchema).points) {
|
||||||
if (point.action && 'triggers' in point.action) {
|
if (point.action && 'triggers' in point.action) {
|
||||||
point.action.triggers = point.action.triggers.filter(t => t.triggerUuid !== triggerUuid);
|
point.action.triggers = point.action.triggers.filter(t => t.triggerUuid !== triggerUuid);
|
||||||
}
|
}
|
||||||
@@ -241,7 +230,7 @@ export const useEventsStore = create<EventsStore>()(
|
|||||||
set((state) => {
|
set((state) => {
|
||||||
for (const event of state.events) {
|
for (const event of state.events) {
|
||||||
if ('points' in event) {
|
if ('points' in event) {
|
||||||
for (const point of (event as TransferEventSchema).points) {
|
for (const point of (event as ConveyorEventSchema).points) {
|
||||||
if (point.action && 'triggers' in point.action) {
|
if (point.action && 'triggers' in point.action) {
|
||||||
const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
|
const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
|
||||||
if (trigger) {
|
if (trigger) {
|
||||||
@@ -282,7 +271,7 @@ export const useEventsStore = create<EventsStore>()(
|
|||||||
getPointByUuid: (modelUuid, pointUuid) => {
|
getPointByUuid: (modelUuid, pointUuid) => {
|
||||||
const event = get().events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
const event = get().events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||||
if (event && 'points' in event) {
|
if (event && 'points' in event) {
|
||||||
return (event as TransferEventSchema).points.find(p => p.uuid === pointUuid);
|
return (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
|
||||||
} else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
|
} else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
|
||||||
return (event as any).point;
|
return (event as any).point;
|
||||||
}
|
}
|
||||||
@@ -293,7 +282,7 @@ export const useEventsStore = create<EventsStore>()(
|
|||||||
const state = get();
|
const state = get();
|
||||||
for (const event of state.events) {
|
for (const event of state.events) {
|
||||||
if ('points' in event) {
|
if ('points' in event) {
|
||||||
for (const point of (event as TransferEventSchema).points) {
|
for (const point of (event as ConveyorEventSchema).points) {
|
||||||
if (point.action && point.action.actionUuid === actionUuid) {
|
if (point.action && point.action.actionUuid === actionUuid) {
|
||||||
return point.action;
|
return point.action;
|
||||||
}
|
}
|
||||||
@@ -315,7 +304,7 @@ export const useEventsStore = create<EventsStore>()(
|
|||||||
const state = get();
|
const state = get();
|
||||||
for (const event of state.events) {
|
for (const event of state.events) {
|
||||||
if ('points' in event) {
|
if ('points' in event) {
|
||||||
for (const point of (event as TransferEventSchema).points) {
|
for (const point of (event as ConveyorEventSchema).points) {
|
||||||
if (point.action && 'triggers' in point.action) {
|
if (point.action && 'triggers' in point.action) {
|
||||||
const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
|
const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
|
||||||
if (trigger) return trigger;
|
if (trigger) return trigger;
|
||||||
@@ -340,10 +329,3 @@ export const useEventsStore = create<EventsStore>()(
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
// Set up automatic syncing between stores
|
|
||||||
useProductStore.subscribe(
|
|
||||||
(state) => {
|
|
||||||
useEventsStore.getState().syncFromProducts(state.products);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
129
app/src/store/simulation/useMachineStore.ts
Normal file
129
app/src/store/simulation/useMachineStore.ts
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
import { create } from 'zustand';
|
||||||
|
import { immer } from 'zustand/middleware/immer';
|
||||||
|
|
||||||
|
interface MachineStatus extends MachineSchemaEvent {
|
||||||
|
productId: string;
|
||||||
|
isActive: boolean;
|
||||||
|
idleTime: number;
|
||||||
|
activeTime: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MachineStore {
|
||||||
|
machines: Record<string, MachineStatus>;
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
addMachine: (productId: string, machine: MachineSchemaEvent) => void;
|
||||||
|
removeMachine: (modelUuid: string) => void;
|
||||||
|
updateMachine: (
|
||||||
|
modelUuid: string,
|
||||||
|
updates: Partial<Omit<MachineStatus, 'modelUuid' | 'productId'>>
|
||||||
|
) => 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[];
|
||||||
|
getActiveMachines: () => MachineStatus[];
|
||||||
|
getIdleMachines: () => MachineStatus[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useMachineStore = create<MachineStore>()(
|
||||||
|
immer((set, get) => ({
|
||||||
|
machines: {},
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
addMachine: (productId, machine) => {
|
||||||
|
set((state) => {
|
||||||
|
state.machines[machine.modelUuid] = {
|
||||||
|
...machine,
|
||||||
|
productId,
|
||||||
|
isActive: false,
|
||||||
|
idleTime: 0,
|
||||||
|
activeTime: 0,
|
||||||
|
state: 'idle',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeMachine: (modelUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
delete state.machines[modelUuid];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
updateMachine: (modelUuid, updates) => {
|
||||||
|
set((state) => {
|
||||||
|
const machine = state.machines[modelUuid];
|
||||||
|
if (machine) {
|
||||||
|
Object.assign(machine, updates);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Status updates
|
||||||
|
setMachineActive: (modelUuid, isActive) => {
|
||||||
|
set((state) => {
|
||||||
|
const machine = state.machines[modelUuid];
|
||||||
|
if (machine) {
|
||||||
|
machine.isActive = isActive;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setMachineState: (modelUuid, newState) => {
|
||||||
|
set((state) => {
|
||||||
|
const machine = state.machines[modelUuid];
|
||||||
|
if (machine) {
|
||||||
|
machine.state = newState;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Time tracking
|
||||||
|
incrementActiveTime: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const machine = state.machines[modelUuid];
|
||||||
|
if (machine) {
|
||||||
|
machine.activeTime += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
incrementIdleTime: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const machine = state.machines[modelUuid];
|
||||||
|
if (machine) {
|
||||||
|
machine.idleTime += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
getMachineById: (modelUuid) => {
|
||||||
|
return get().machines[modelUuid];
|
||||||
|
},
|
||||||
|
|
||||||
|
getMachinesByProduct: (productId) => {
|
||||||
|
return Object.values(get().machines).filter(
|
||||||
|
m => m.productId === productId
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
getActiveMachines: () => {
|
||||||
|
return Object.values(get().machines).filter(m => m.isActive);
|
||||||
|
},
|
||||||
|
|
||||||
|
getIdleMachines: () => {
|
||||||
|
return Object.values(get().machines).filter(
|
||||||
|
m => !m.isActive && m.state === 'idle'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
);
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { immer } from 'zustand/middleware/immer';
|
import { immer } from 'zustand/middleware/immer';
|
||||||
|
|
||||||
type Store = {
|
type ProductsStore = {
|
||||||
products: productsSchema;
|
products: productsSchema;
|
||||||
|
|
||||||
// Product-level actions
|
// Product-level actions
|
||||||
@@ -15,13 +15,13 @@ type Store = {
|
|||||||
updateEvent: (productId: string, modelUuid: string, updates: Partial<EventsSchema>) => void;
|
updateEvent: (productId: string, modelUuid: string, updates: Partial<EventsSchema>) => void;
|
||||||
|
|
||||||
// Point-level actions
|
// Point-level actions
|
||||||
addPoint: (productId: string, modelUuid: string, point: TransferPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema) => void;
|
addPoint: (productId: string, modelUuid: string, point: ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema) => void;
|
||||||
removePoint: (productId: string, modelUuid: string, pointUuid: string) => void;
|
removePoint: (productId: string, modelUuid: string, pointUuid: string) => void;
|
||||||
updatePoint: (
|
updatePoint: (
|
||||||
productId: string,
|
productId: string,
|
||||||
modelUuid: string,
|
modelUuid: string,
|
||||||
pointUuid: string,
|
pointUuid: string,
|
||||||
updates: Partial<TransferPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema>
|
updates: Partial<ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema>
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
// Action-level actions
|
// Action-level actions
|
||||||
@@ -29,12 +29,12 @@ type Store = {
|
|||||||
productId: string,
|
productId: string,
|
||||||
modelUuid: string,
|
modelUuid: string,
|
||||||
pointUuid: string,
|
pointUuid: string,
|
||||||
action: TransferPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']
|
action: ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']
|
||||||
) => void;
|
) => void;
|
||||||
removeAction: (actionUuid: string) => void;
|
removeAction: (actionUuid: string) => void;
|
||||||
updateAction: (
|
updateAction: (
|
||||||
actionUuid: string,
|
actionUuid: string,
|
||||||
updates: Partial<TransferPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']>
|
updates: Partial<ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']>
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
// Trigger-level actions
|
// Trigger-level actions
|
||||||
@@ -52,7 +52,7 @@ type Store = {
|
|||||||
getProductById: (productId: string) => { productName: string; productId: string; eventsData: EventsSchema[] } | undefined;
|
getProductById: (productId: string) => { productName: string; productId: string; eventsData: EventsSchema[] } | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useProductStore = create<Store>()(
|
export const useProductStore = create<ProductsStore>()(
|
||||||
immer((set, get) => ({
|
immer((set, get) => ({
|
||||||
products: [],
|
products: [],
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ export const useProductStore = create<Store>()(
|
|||||||
if (product) {
|
if (product) {
|
||||||
const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||||
if (event && 'points' in event) {
|
if (event && 'points' in event) {
|
||||||
(event as TransferEventSchema).points.push(point as TransferPointSchema);
|
(event as ConveyorEventSchema).points.push(point as ConveyorPointSchema);
|
||||||
} else if (event && 'point' in event) {
|
} else if (event && 'point' in event) {
|
||||||
(event as VehicleSchemaEvent | RoboticArmSchemaEvent | MachineSchemaEvent | StorageSchemaEvent).point = point as any;
|
(event as VehicleSchemaEvent | RoboticArmSchemaEvent | MachineSchemaEvent | StorageSchemaEvent).point = point as any;
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ export const useProductStore = create<Store>()(
|
|||||||
if (product) {
|
if (product) {
|
||||||
const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||||
if (event && 'points' in event) {
|
if (event && 'points' in event) {
|
||||||
(event as TransferEventSchema).points = (event as TransferEventSchema).points.filter(p => p.uuid !== pointUuid);
|
(event as ConveyorEventSchema).points = (event as ConveyorEventSchema).points.filter(p => p.uuid !== pointUuid);
|
||||||
} else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
|
} else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
|
||||||
// For events with single point, we can't remove it, only reset to empty
|
// For events with single point, we can't remove it, only reset to empty
|
||||||
}
|
}
|
||||||
@@ -149,7 +149,7 @@ export const useProductStore = create<Store>()(
|
|||||||
if (product) {
|
if (product) {
|
||||||
const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||||
if (event && 'points' in event) {
|
if (event && 'points' in event) {
|
||||||
const point = (event as TransferEventSchema).points.find(p => p.uuid === pointUuid);
|
const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
|
||||||
if (point) {
|
if (point) {
|
||||||
Object.assign(point, updates);
|
Object.assign(point, updates);
|
||||||
}
|
}
|
||||||
@@ -167,7 +167,7 @@ export const useProductStore = create<Store>()(
|
|||||||
if (product) {
|
if (product) {
|
||||||
const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||||
if (event && 'points' in event) {
|
if (event && 'points' in event) {
|
||||||
const point = (event as TransferEventSchema).points.find(p => p.uuid === pointUuid);
|
const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
|
||||||
if (point) {
|
if (point) {
|
||||||
point.action = action as any;
|
point.action = action as any;
|
||||||
}
|
}
|
||||||
@@ -187,8 +187,8 @@ export const useProductStore = create<Store>()(
|
|||||||
for (const product of state.products) {
|
for (const product of state.products) {
|
||||||
for (const event of product.eventsData) {
|
for (const event of product.eventsData) {
|
||||||
if ('points' in event) {
|
if ('points' in event) {
|
||||||
// Handle TransferEventSchema
|
// Handle ConveyorEventSchema
|
||||||
for (const point of (event as TransferEventSchema).points) {
|
for (const point of (event as ConveyorEventSchema).points) {
|
||||||
}
|
}
|
||||||
} else if ('point' in event) {
|
} else if ('point' in event) {
|
||||||
const point = (event as any).point;
|
const point = (event as any).point;
|
||||||
@@ -211,7 +211,7 @@ export const useProductStore = create<Store>()(
|
|||||||
for (const product of state.products) {
|
for (const product of state.products) {
|
||||||
for (const event of product.eventsData) {
|
for (const event of product.eventsData) {
|
||||||
if ('points' in event) {
|
if ('points' in event) {
|
||||||
for (const point of (event as TransferEventSchema).points) {
|
for (const point of (event as ConveyorEventSchema).points) {
|
||||||
if (point.action && point.action.actionUuid === actionUuid) {
|
if (point.action && point.action.actionUuid === actionUuid) {
|
||||||
Object.assign(point.action, updates);
|
Object.assign(point.action, updates);
|
||||||
return;
|
return;
|
||||||
@@ -241,7 +241,7 @@ export const useProductStore = create<Store>()(
|
|||||||
for (const product of state.products) {
|
for (const product of state.products) {
|
||||||
for (const event of product.eventsData) {
|
for (const event of product.eventsData) {
|
||||||
if ('points' in event) {
|
if ('points' in event) {
|
||||||
for (const point of (event as TransferEventSchema).points) {
|
for (const point of (event as ConveyorEventSchema).points) {
|
||||||
if (point.action && point.action.actionUuid === actionUuid) {
|
if (point.action && point.action.actionUuid === actionUuid) {
|
||||||
point.action.triggers.push(trigger);
|
point.action.triggers.push(trigger);
|
||||||
return;
|
return;
|
||||||
@@ -270,7 +270,7 @@ export const useProductStore = create<Store>()(
|
|||||||
for (const product of state.products) {
|
for (const product of state.products) {
|
||||||
for (const event of product.eventsData) {
|
for (const event of product.eventsData) {
|
||||||
if ('points' in event) {
|
if ('points' in event) {
|
||||||
for (const point of (event as TransferEventSchema).points) {
|
for (const point of (event as ConveyorEventSchema).points) {
|
||||||
if (point.action && 'triggers' in point.action) {
|
if (point.action && 'triggers' in point.action) {
|
||||||
point.action.triggers = point.action.triggers.filter(t => t.triggerUuid !== triggerUuid);
|
point.action.triggers = point.action.triggers.filter(t => t.triggerUuid !== triggerUuid);
|
||||||
}
|
}
|
||||||
@@ -297,7 +297,7 @@ export const useProductStore = create<Store>()(
|
|||||||
for (const product of state.products) {
|
for (const product of state.products) {
|
||||||
for (const event of product.eventsData) {
|
for (const event of product.eventsData) {
|
||||||
if ('points' in event) {
|
if ('points' in event) {
|
||||||
for (const point of (event as TransferEventSchema).points) {
|
for (const point of (event as ConveyorEventSchema).points) {
|
||||||
if (point.action && 'triggers' in point.action) {
|
if (point.action && 'triggers' in point.action) {
|
||||||
const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
|
const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
|
||||||
if (trigger) {
|
if (trigger) {
|
||||||
@@ -336,4 +336,4 @@ export const useProductStore = create<Store>()(
|
|||||||
return get().products.find(p => p.productId === productId);
|
return get().products.find(p => p.productId === productId);
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
158
app/src/store/simulation/useStorageUnitStore.ts
Normal file
158
app/src/store/simulation/useStorageUnitStore.ts
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
import { create } from 'zustand';
|
||||||
|
import { immer } from 'zustand/middleware/immer';
|
||||||
|
|
||||||
|
interface StorageUnitStatus extends StorageSchemaEvent {
|
||||||
|
productId: string;
|
||||||
|
isActive: boolean;
|
||||||
|
idleTime: number;
|
||||||
|
activeTime: number;
|
||||||
|
currentLoad: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface StorageUnitStore {
|
||||||
|
storageUnits: Record<string, StorageUnitStatus>;
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
addStorageUnit: (productId: string, storageUnit: StorageSchemaEvent) => void;
|
||||||
|
removeStorageUnit: (modelUuid: string) => void;
|
||||||
|
updateStorageUnit: (
|
||||||
|
modelUuid: string,
|
||||||
|
updates: Partial<Omit<StorageUnitStatus, 'modelUuid' | 'productId'>>
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
// Status updates
|
||||||
|
setStorageUnitActive: (modelUuid: string, isActive: boolean) => void;
|
||||||
|
setStorageUnitState: (modelUuid: string, newState: StorageUnitStatus['state']) => void;
|
||||||
|
|
||||||
|
// Load updates
|
||||||
|
updateStorageUnitLoad: (modelUuid: string, load: 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[];
|
||||||
|
getActiveStorageUnits: () => StorageUnitStatus[];
|
||||||
|
getIdleStorageUnits: () => StorageUnitStatus[];
|
||||||
|
getFullStorageUnits: () => StorageUnitStatus[];
|
||||||
|
getEmptyStorageUnits: () => StorageUnitStatus[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useStorageUnitStore = create<StorageUnitStore>()(
|
||||||
|
immer((set, get) => ({
|
||||||
|
storageUnits: {},
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
addStorageUnit: (productId, storageUnit) => {
|
||||||
|
set((state) => {
|
||||||
|
state.storageUnits[storageUnit.modelUuid] = {
|
||||||
|
...storageUnit,
|
||||||
|
productId,
|
||||||
|
isActive: false,
|
||||||
|
idleTime: 0,
|
||||||
|
activeTime: 0,
|
||||||
|
currentLoad: 0, // Initialize currentLoad to 0
|
||||||
|
state: 'idle',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeStorageUnit: (modelUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
delete state.storageUnits[modelUuid];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
updateStorageUnit: (modelUuid, updates) => {
|
||||||
|
set((state) => {
|
||||||
|
const storageUnit = state.storageUnits[modelUuid];
|
||||||
|
if (storageUnit) {
|
||||||
|
Object.assign(storageUnit, updates);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Status updates
|
||||||
|
setStorageUnitActive: (modelUuid, isActive) => {
|
||||||
|
set((state) => {
|
||||||
|
const storageUnit = state.storageUnits[modelUuid];
|
||||||
|
if (storageUnit) {
|
||||||
|
storageUnit.isActive = isActive;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setStorageUnitState: (modelUuid, newState) => {
|
||||||
|
set((state) => {
|
||||||
|
const storageUnit = state.storageUnits[modelUuid];
|
||||||
|
if (storageUnit) {
|
||||||
|
storageUnit.state = newState;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Load updates
|
||||||
|
updateStorageUnitLoad: (modelUuid, load) => {
|
||||||
|
set((state) => {
|
||||||
|
const storageUnit = state.storageUnits[modelUuid];
|
||||||
|
if (storageUnit) {
|
||||||
|
storageUnit.currentLoad = load;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Time tracking
|
||||||
|
incrementActiveTime: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const storageUnit = state.storageUnits[modelUuid];
|
||||||
|
if (storageUnit) {
|
||||||
|
storageUnit.activeTime += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
incrementIdleTime: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const storageUnit = state.storageUnits[modelUuid];
|
||||||
|
if (storageUnit) {
|
||||||
|
storageUnit.idleTime += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
getStorageUnitById: (modelUuid) => {
|
||||||
|
return get().storageUnits[modelUuid];
|
||||||
|
},
|
||||||
|
|
||||||
|
getStorageUnitsByProduct: (productId) => {
|
||||||
|
return Object.values(get().storageUnits).filter(
|
||||||
|
s => s.productId === productId
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
getActiveStorageUnits: () => {
|
||||||
|
return Object.values(get().storageUnits).filter(s => s.isActive);
|
||||||
|
},
|
||||||
|
|
||||||
|
getIdleStorageUnits: () => {
|
||||||
|
return Object.values(get().storageUnits).filter(
|
||||||
|
s => !s.isActive && s.state === 'idle'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
getFullStorageUnits: () => {
|
||||||
|
return Object.values(get().storageUnits).filter(
|
||||||
|
s => s.currentLoad >= s.point.action.storageCapacity
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
getEmptyStorageUnits: () => {
|
||||||
|
return Object.values(get().storageUnits).filter(
|
||||||
|
s => s.currentLoad === 0
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
);
|
||||||
149
app/src/store/simulation/useVehicleStore.ts
Normal file
149
app/src/store/simulation/useVehicleStore.ts
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
import { create } from 'zustand';
|
||||||
|
import { immer } from 'zustand/middleware/immer';
|
||||||
|
|
||||||
|
interface VehicleStatus extends VehicleSchemaEvent {
|
||||||
|
productId: string;
|
||||||
|
isActive: boolean;
|
||||||
|
idleTime: number;
|
||||||
|
activeTime: number;
|
||||||
|
currentLoad: number;
|
||||||
|
distanceTraveled: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface VehiclesStore {
|
||||||
|
vehicles: Record<string, VehicleStatus>;
|
||||||
|
|
||||||
|
// Vehicle actions
|
||||||
|
addVehicle: (productId: string, event: VehicleSchemaEvent) => void;
|
||||||
|
removeVehicle: (modelUuid: string) => void;
|
||||||
|
updateVehicle: (
|
||||||
|
modelUuid: string,
|
||||||
|
updates: Partial<Omit<VehicleStatus, 'modelUuid' | 'productId'>>
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
// Status updates
|
||||||
|
setVehicleActive: (modelUuid: string, isActive: boolean) => void;
|
||||||
|
updateVehicleLoad: (modelUuid: string, load: number) => void;
|
||||||
|
|
||||||
|
// State management
|
||||||
|
setVehicleState: (modelUuid: string, newState: VehicleStatus['state']) => void;
|
||||||
|
|
||||||
|
// Time tracking
|
||||||
|
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
|
||||||
|
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
|
||||||
|
|
||||||
|
// Helper functions
|
||||||
|
getVehicleById: (modelUuid: string) => VehicleStatus | undefined;
|
||||||
|
getVehiclesByProduct: (productId: string) => VehicleStatus[];
|
||||||
|
getActiveVehicles: () => VehicleStatus[];
|
||||||
|
getIdleVehicles: () => VehicleStatus[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useVehicleStore = create<VehiclesStore>()(
|
||||||
|
immer((set, get) => ({
|
||||||
|
vehicles: {},
|
||||||
|
|
||||||
|
addVehicle: (productId, event) => {
|
||||||
|
set((state) => {
|
||||||
|
state.vehicles[event.modelUuid] = {
|
||||||
|
...event,
|
||||||
|
isActive: false,
|
||||||
|
productId,
|
||||||
|
idleTime: 0,
|
||||||
|
activeTime: 0,
|
||||||
|
currentLoad: 0,
|
||||||
|
distanceTraveled: 0,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeVehicle: (modelUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
delete state.vehicles[modelUuid];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
updateVehicle: (modelUuid, updates) => {
|
||||||
|
set((state) => {
|
||||||
|
const vehicle = state.vehicles[modelUuid];
|
||||||
|
if (vehicle) {
|
||||||
|
Object.assign(vehicle, updates);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Status updates
|
||||||
|
setVehicleActive: (modelUuid, isActive) => {
|
||||||
|
set((state) => {
|
||||||
|
const vehicle = state.vehicles[modelUuid];
|
||||||
|
if (vehicle) {
|
||||||
|
vehicle.isActive = isActive;
|
||||||
|
if (isActive) {
|
||||||
|
vehicle.state = 'running';
|
||||||
|
} else {
|
||||||
|
vehicle.state = vehicle.currentLoad > 0 ? 'idle' : 'stopped';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
updateVehicleLoad: (modelUuid, load) => {
|
||||||
|
set((state) => {
|
||||||
|
const vehicle = state.vehicles[modelUuid];
|
||||||
|
if (vehicle) {
|
||||||
|
vehicle.currentLoad = load;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// State management
|
||||||
|
setVehicleState: (modelUuid, newState) => {
|
||||||
|
set((state) => {
|
||||||
|
const vehicle = state.vehicles[modelUuid];
|
||||||
|
if (vehicle) {
|
||||||
|
vehicle.state = newState;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Time tracking
|
||||||
|
incrementActiveTime: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const vehicle = state.vehicles[modelUuid];
|
||||||
|
if (vehicle) {
|
||||||
|
vehicle.activeTime += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
incrementIdleTime: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const vehicle = state.vehicles[modelUuid];
|
||||||
|
if (vehicle) {
|
||||||
|
vehicle.idleTime += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
getVehicleById: (modelUuid) => {
|
||||||
|
return get().vehicles[modelUuid];
|
||||||
|
},
|
||||||
|
|
||||||
|
getVehiclesByProduct: (productId) => {
|
||||||
|
return Object.values(get().vehicles).filter(
|
||||||
|
v => v.productId === productId
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
getActiveVehicles: () => {
|
||||||
|
return Object.values(get().vehicles).filter(v => v.isActive);
|
||||||
|
},
|
||||||
|
|
||||||
|
getIdleVehicles: () => {
|
||||||
|
return Object.values(get().vehicles).filter(
|
||||||
|
v => !v.isActive && v.currentLoad > 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
);
|
||||||
@@ -85,10 +85,15 @@ export const useZonePoints = create<ZonePointsState>((set) => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
export const useSelectedItem = create<any>((set: any) => ({
|
export const useSelectedItem = create<any>((set: any) => ({
|
||||||
selectedItem: { name: "", id: "" },
|
selectedItem: { name: "", id: "", type: undefined },
|
||||||
setSelectedItem: (x: any) => set(() => ({ selectedItem: x })),
|
setSelectedItem: (x: any) => set(() => ({ selectedItem: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
export const useNavMesh = create<any>((set: any) => ({
|
||||||
|
navMesh: null,
|
||||||
|
setNavMesh: (x: any) => set({ navMesh: x }),
|
||||||
|
}));
|
||||||
|
|
||||||
export const useSelectedAssets = create<any>((set: any) => ({
|
export const useSelectedAssets = create<any>((set: any) => ({
|
||||||
selectedAssets: [],
|
selectedAssets: [],
|
||||||
setSelectedAssets: (x: any) => set(() => ({ selectedAssets: x })),
|
setSelectedAssets: (x: any) => set(() => ({ selectedAssets: x })),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { addingFloatingWidgets } from "../services/visulization/zone/addFloatingWidgets";
|
import { addingFloatingWidgets } from "../../services/visulization/zone/addFloatingWidgets";
|
||||||
import { useSocketStore } from "./store";
|
import { useSocketStore } from "../store";
|
||||||
import useChartStore from "./useChartStore";
|
import useChartStore from "./useChartStore";
|
||||||
|
|
||||||
type DroppedObject = {
|
type DroppedObject = {
|
||||||
@@ -1,53 +1,53 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
|
|
||||||
type Side = "top" | "bottom" | "left" | "right";
|
type Side = "top" | "bottom" | "left" | "right";
|
||||||
|
|
||||||
interface Widget {
|
interface Widget {
|
||||||
id: string;
|
id: string;
|
||||||
type: string;
|
type: string;
|
||||||
title: string;
|
title: string;
|
||||||
panel: Side;
|
panel: Side;
|
||||||
data: any;
|
data: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SelectedZoneState {
|
interface SelectedZoneState {
|
||||||
zoneName: string;
|
zoneName: string;
|
||||||
activeSides: Side[];
|
activeSides: Side[];
|
||||||
panelOrder: Side[];
|
panelOrder: Side[];
|
||||||
points: []
|
points: []
|
||||||
lockedPanels: Side[];
|
lockedPanels: Side[];
|
||||||
zoneId: string;
|
zoneId: string;
|
||||||
zoneViewPortTarget: number[];
|
zoneViewPortTarget: number[];
|
||||||
zoneViewPortPosition: number[];
|
zoneViewPortPosition: number[];
|
||||||
widgets: Widget[];
|
widgets: Widget[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SelectedZoneStore {
|
interface SelectedZoneStore {
|
||||||
selectedZone: SelectedZoneState;
|
selectedZone: SelectedZoneState;
|
||||||
setSelectedZone: (
|
setSelectedZone: (
|
||||||
zone:
|
zone:
|
||||||
| Partial<SelectedZoneState>
|
| Partial<SelectedZoneState>
|
||||||
| ((prev: SelectedZoneState) => SelectedZoneState)
|
| ((prev: SelectedZoneState) => SelectedZoneState)
|
||||||
) => void;
|
) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useSelectedZoneStore = create<SelectedZoneStore>((set) => ({
|
export const useSelectedZoneStore = create<SelectedZoneStore>((set) => ({
|
||||||
selectedZone: {
|
selectedZone: {
|
||||||
zoneName: "", // Empty string initially
|
zoneName: "", // Empty string initially
|
||||||
activeSides: [], // Empty array
|
activeSides: [], // Empty array
|
||||||
panelOrder: [], // Empty array
|
panelOrder: [], // Empty array
|
||||||
lockedPanels: [], // Empty array
|
lockedPanels: [], // Empty array
|
||||||
points: [],
|
points: [],
|
||||||
zoneId: "",
|
zoneId: "",
|
||||||
zoneViewPortTarget: [],
|
zoneViewPortTarget: [],
|
||||||
zoneViewPortPosition: [],
|
zoneViewPortPosition: [],
|
||||||
widgets: [], // Empty array
|
widgets: [], // Empty array
|
||||||
},
|
},
|
||||||
setSelectedZone: (zone) =>
|
setSelectedZone: (zone) =>
|
||||||
set((state) => ({
|
set((state) => ({
|
||||||
selectedZone:
|
selectedZone:
|
||||||
typeof zone === "function"
|
typeof zone === "function"
|
||||||
? zone(state.selectedZone) // Handle functional updates
|
? zone(state.selectedZone) // Handle functional updates
|
||||||
: { ...state.selectedZone, ...zone }, // Handle partial updates
|
: { ...state.selectedZone, ...zone }, // Handle partial updates
|
||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
17
app/src/types/simulationTypes.d.ts
vendored
17
app/src/types/simulationTypes.d.ts
vendored
@@ -13,11 +13,12 @@ interface TriggerSchema {
|
|||||||
delay: number;
|
delay: number;
|
||||||
triggeredAsset: {
|
triggeredAsset: {
|
||||||
triggeredModel: { modelName: string, modelUuid: string };
|
triggeredModel: { modelName: string, modelUuid: string };
|
||||||
|
triggeredPoint: { pointName: string, pointUuid: string };
|
||||||
triggeredAction: { actionName: string, actionUuid: string };
|
triggeredAction: { actionName: string, actionUuid: string };
|
||||||
} | null;
|
} | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TransferPointSchema {
|
interface ConveyorPointSchema {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
position: [number, number, number];
|
position: [number, number, number];
|
||||||
rotation: [number, number, number];
|
rotation: [number, number, number];
|
||||||
@@ -25,7 +26,7 @@ interface TransferPointSchema {
|
|||||||
actionUuid: string;
|
actionUuid: string;
|
||||||
actionName: string;
|
actionName: string;
|
||||||
actionType: "default" | "spawn" | "swap" | "despawn";
|
actionType: "default" | "spawn" | "swap" | "despawn";
|
||||||
material: string | "inherit";
|
material: string;
|
||||||
delay: number | "inherit";
|
delay: number | "inherit";
|
||||||
spawnInterval: number | "inherit";
|
spawnInterval: number | "inherit";
|
||||||
spawnCount: number | "inherit";
|
spawnCount: number | "inherit";
|
||||||
@@ -44,8 +45,8 @@ interface VehiclePointSchema {
|
|||||||
material: string;
|
material: string;
|
||||||
unLoadDuration: number;
|
unLoadDuration: number;
|
||||||
loadCapacity: number;
|
loadCapacity: number;
|
||||||
pickUpPoint: { x: number; y: number, z: number } | {};
|
pickUpPoint: { x: number; y: number, z: number } | null;
|
||||||
unLoadPoint: { x: number; y: number, z: number } | {};
|
unLoadPoint: { x: number; y: number, z: number } | null;
|
||||||
triggers: TriggerSchema[];
|
triggers: TriggerSchema[];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -85,15 +86,15 @@ interface StoragePointSchema {
|
|||||||
actionUuid: string;
|
actionUuid: string;
|
||||||
actionName: string;
|
actionName: string;
|
||||||
actionType: "storage";
|
actionType: "storage";
|
||||||
materials: { materialName: string; materialId: string; quantity: number }[];
|
materials: { materialName: string; materialId: string; }[];
|
||||||
storageCapacity: number;
|
storageCapacity: number;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TransferEventSchema extends AssetEventSchema {
|
interface ConveyorEventSchema extends AssetEventSchema {
|
||||||
type: "transfer";
|
type: "transfer";
|
||||||
speed: number;
|
speed: number;
|
||||||
points: TransferPointSchema[];
|
points: ConveyorPointSchema[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface VehicleSchemaEvent extends AssetEventSchema {
|
interface VehicleSchemaEvent extends AssetEventSchema {
|
||||||
@@ -118,7 +119,7 @@ interface StorageSchemaEvent extends AssetEventSchema {
|
|||||||
point: StoragePointSchema;
|
point: StoragePointSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
type EventsSchema = TransferEventSchema | VehicleSchemaEvent | RoboticArmSchemaEvent | MachineSchemaEvent | StorageSchemaEvent | [];
|
type EventsSchema = ConveyorEventSchema | VehicleSchemaEvent | RoboticArmSchemaEvent | MachineSchemaEvent | StorageSchemaEvent | [];
|
||||||
|
|
||||||
type productsSchema = {
|
type productsSchema = {
|
||||||
productName: string;
|
productName: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user