From dc73c1a50bdceb476841049aa5947e09d6659aad Mon Sep 17 00:00:00 2001 From: Poovizhi99 Date: Fri, 28 Mar 2025 16:25:53 +0530 Subject: [PATCH 1/4] completed some features in market place --- app/src/modules/market/AssetPreview.tsx | 50 ++++++- app/src/modules/market/Card.tsx | 5 +- app/src/modules/market/CardsContainer.tsx | 132 +----------------- app/src/modules/market/FilterSearch.tsx | 58 +++++++- app/src/modules/market/GltfLoader.tsx | 79 +++++++++++ app/src/modules/market/MarketPlace.tsx | 40 +++++- .../services/marketplace/fetchAssetDetails.ts | 22 +++ app/src/services/marketplace/fetchAssets.ts | 2 + app/src/services/marketplace/fetchGltfUrl.ts | 7 + .../services/marketplace/getAssetDownload.ts | 4 + .../services/marketplace/getSortedAssets.ts | 25 ++++ .../components/marketPlace/marketPlace.scss | 4 +- 12 files changed, 286 insertions(+), 142 deletions(-) create mode 100644 app/src/modules/market/GltfLoader.tsx create mode 100644 app/src/services/marketplace/fetchAssetDetails.ts create mode 100644 app/src/services/marketplace/fetchGltfUrl.ts create mode 100644 app/src/services/marketplace/getAssetDownload.ts create mode 100644 app/src/services/marketplace/getSortedAssets.ts diff --git a/app/src/modules/market/AssetPreview.tsx b/app/src/modules/market/AssetPreview.tsx index be474a2..864c5e5 100644 --- a/app/src/modules/market/AssetPreview.tsx +++ b/app/src/modules/market/AssetPreview.tsx @@ -1,11 +1,15 @@ -import React from "react"; +import React, { Suspense, useEffect } from "react"; import assetImage from "../../assets/image/image.png"; import { FiileedStarsIconSmall } from "../../components/icons/marketPlaceIcons"; +import { Canvas, useThree } from "@react-three/fiber"; +import { ContactShadows, OrbitControls, Text } from "@react-three/drei"; +import GltfLoader from "./GltfLoader"; +import * as THREE from "three"; // Define the shape of the selected card interface SelectedCard { assetName: string; - uploadedOn: string; + uploadedOn: number; price: number; rating: number; views: number; @@ -17,6 +21,14 @@ interface AssetPreviewProps { setSelectedCard: React.Dispatch>; // Type for setter function } +function Ui() { + return ( + + Loading your model... + + ); +} + const AssetPreview: React.FC = ({ selectedCard, setSelectedCard, @@ -27,8 +39,6 @@ const AssetPreview: React.FC = ({ Math.min(5, isNaN(selectedCard.rating) ? 0 : selectedCard.rating) ); - console.log("selectedCard: ", selectedCard); - // Ensure that the rating is a valid positive integer for array length const starsArray = Array.from({ length: rating }, (_, index) => index); @@ -36,8 +46,38 @@ const AssetPreview: React.FC = ({
- + {/* */} {/* Add canvas here */} +
+ { + scene.background = new THREE.Color(0xffffff); + }} + > + }> + {selectedCard.assetName && ( + + )} + + + + +
diff --git a/app/src/modules/market/Card.tsx b/app/src/modules/market/Card.tsx index b872dc0..4188447 100644 --- a/app/src/modules/market/Card.tsx +++ b/app/src/modules/market/Card.tsx @@ -8,6 +8,7 @@ import { } from "../../components/icons/marketPlaceIcons"; import assetImage from "../../assets/image/image.png"; +import { getAssetDownload } from "../../services/marketplace/getAssetDownload"; interface CardProps { assetName: string; @@ -40,9 +41,9 @@ const Card: React.FC = ({ return (
-
+ {/* -
+ */}
{assetName}
diff --git a/app/src/modules/market/CardsContainer.tsx b/app/src/modules/market/CardsContainer.tsx index 67bf849..50da667 100644 --- a/app/src/modules/market/CardsContainer.tsx +++ b/app/src/modules/market/CardsContainer.tsx @@ -16,109 +16,11 @@ interface ModelData { uploadDate: number; _id: string; } +interface ModelsProps { + models: ModelData[]; +} -const CardsContainer: React.FC = () => { - const [models, setModels] = useState([]); - - const array = [ - { - id: 1, - name: "Asset 1", - uploadedOn: "12 Jan 23", - price: 36500, - rating: 4.5, - views: 500, - }, - { - id: 2, - name: "Asset 2", - uploadedOn: "14 Jan 23", - price: 45000, - rating: 4.0, - views: 500, - }, - { - id: 3, - name: "Asset 3", - uploadedOn: "15 Jan 23", - price: 52000, - rating: 4.8, - views: 500, - }, - { - id: 4, - name: "Asset 4", - uploadedOn: "18 Jan 23", - price: 37000, - rating: 3.9, - views: 500, - }, - { - id: 5, - name: "Asset 5", - uploadedOn: "20 Jan 23", - price: 60000, - rating: 5.0, - views: 500, - }, - { - id: 6, - name: "Asset 6", - uploadedOn: "22 Jan 23", - price: 46000, - rating: 4.2, - views: 500, - }, - { - id: 7, - name: "Asset 7", - uploadedOn: "25 Jan 23", - price: 38000, - rating: 4.3, - views: 500, - }, - { - id: 8, - name: "Asset 8", - uploadedOn: "27 Jan 23", - price: 41000, - rating: 4.1, - views: 500, - }, - { - id: 9, - name: "Asset 9", - uploadedOn: "30 Jan 23", - price: 55000, - rating: 4.6, - views: 500, - }, - { - id: 10, - name: "Asset 10", - uploadedOn: "2 Feb 23", - price: 49000, - rating: 4.4, - views: 500, - }, - { - id: 11, - name: "Asset 11", - uploadedOn: "5 Feb 23", - price: 62000, - rating: 5.0, - views: 500, - }, - { - id: 12, - name: "Asset 12", - uploadedOn: "7 Feb 23", - price: 53000, - rating: 4.7, - views: 500, - }, - ]; - +const CardsContainer: React.FC = ({ models }) => { const [selectedCard, setSelectedCard] = useState<{ assetName: string; uploadedOn: number; @@ -136,33 +38,11 @@ const CardsContainer: React.FC = () => { }) => { setSelectedCard(cardData); }; - const getAllAssets = async () => { - try { - const assetsData = await fetchAssets(); - const reversedData = [...assetsData]?.reverse().slice(0, 8); - setModels(reversedData); - } catch (error) { - } finally { - } - }; - useEffect(() => { - getAllAssets(); - }, []); + return (
Products You May Like
- {/* {array.map((asset) => ( - - ))} */} {models.length > 0 && models.map((assetDetail) => ( { uploadedOn={assetDetail.uploadDate} price={36500} rating={4.5} - views={500} + views={800} onSelectCard={handleCardSelect} image={assetDetail.thumbnail} /> diff --git a/app/src/modules/market/FilterSearch.tsx b/app/src/modules/market/FilterSearch.tsx index 11a2cbf..08103ba 100644 --- a/app/src/modules/market/FilterSearch.tsx +++ b/app/src/modules/market/FilterSearch.tsx @@ -1,19 +1,69 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; // import RegularDropDown from "./ui/inputs/RegularDropDown"; import Search from "../../components/ui/inputs/Search"; import { StarsIcon } from "../../components/icons/marketPlaceIcons"; import RegularDropDown from "../../components/ui/inputs/RegularDropDown"; - -const FilterSearch: React.FC = () => { +import { getSortedAssets } from "../../services/marketplace/getSortedAssets"; +interface ModelData { + CreatedBy: string; + animated: string | null; + category: string; + description: string; + filename: string; + isArchieve: boolean; + modelfileID: string; + tags: string; + thumbnail: string; + uploadDate: number; + _id: string; +} +interface ModelsProps { + models: ModelData[]; + setModels: React.Dispatch>; + filteredModels: ModelData[]; +} +const FilterSearch: React.FC = ({ + models, + setModels, + filteredModels, +}) => { const [activeOption, setActiveOption] = useState("Sort by"); // State for active option + console.log("filteredModels: ", filteredModels); const handleSelect = (option: string) => { setActiveOption(option); + console.log("option: ", option); + // Alphabet ascending + // Alphabet descending + // All }; + useEffect(() => { + if (activeOption == "Alphabet ascending") { + let ascending = models + ?.slice() + .sort((a, b) => a.filename.localeCompare(b.filename)) + .map((val) => val); + setModels(ascending); + } else if (activeOption == "Alphabet descending") { + let descending = models + ?.slice() + .sort((a, b) => b.filename.localeCompare(a.filename)) + .map((val) => val); + setModels(descending); + } + }, [activeOption]); + const handleSearch = (val: string) => { + const filteredModel = filteredModels?.filter((model) => + model.filename.toLowerCase().includes(val.toLowerCase()) + ); + + setModels(filteredModel); + }; + return (
- {}} /> + void; + selectedAnimation?: string; + setSelectedAnimation?: (animation: string) => void; +} + +// const getGLTFUrl = (url: string) => url; // Placeholder for your actual function + +const GltfLoader: React.FC = ({ + glbdata, + fromServer, + setAnimations, + selectedAnimation, +}) => { + const modelUrl: any = fromServer ? fetchGltfUrl(fromServer) : glbdata; + const { scene, animations } = useGLTF(modelUrl ?? "") as { + scene: Object3D; + animations: THREE.AnimationClip[]; + }; + + const mixer = useRef( + scene ? new AnimationMixer(scene) : null + ); + const actions = useRef>({}); + + useEffect(() => { + if (animations.length > 0 && mixer.current && setAnimations) { + const animationNames = animations.map((animation) => animation.name); + setAnimations(animationNames); + + animations.forEach((animation) => { + const action = mixer.current!.clipAction(animation); + actions.current[animation.name] = action; + }); + } else { + setAnimations && setAnimations([]); + } + }, [animations, setAnimations]); + + useEffect(() => { + if (actions.current && selectedAnimation) { + const action = actions.current[selectedAnimation]; + if (action) { + action.reset().fadeIn(0.5).play(); + return () => { + action.fadeOut(0.5); + }; + } + } + }, [selectedAnimation]); + + useFrame((_, delta) => { + if (mixer.current) { + mixer.current.update(delta); + } + }); + + return ( + + + + ); +}; + +export default GltfLoader; diff --git a/app/src/modules/market/MarketPlace.tsx b/app/src/modules/market/MarketPlace.tsx index 71dc0a5..d830576 100644 --- a/app/src/modules/market/MarketPlace.tsx +++ b/app/src/modules/market/MarketPlace.tsx @@ -1,14 +1,46 @@ -import React from "react"; +import React, { useEffect, useState } from "react"; import FilterSearch from "./FilterSearch"; import CardsContainer from "./CardsContainer"; - +import { fetchAssets } from "../../services/marketplace/fetchAssets"; +import { getAssetImages } from "../../services/factoryBuilder/assest/assets/getAssetImages"; +interface ModelData { + CreatedBy: string; + animated: string | null; + category: string; + description: string; + filename: string; + isArchieve: boolean; + modelfileID: string; + tags: string; + thumbnail: string; + uploadDate: number; + _id: string; +} const MarketPlace = () => { + const [models, setModels] = useState([]); + const [filteredModels, setFilteredModels] = useState([]); + + useEffect(() => { + const filteredAssets = async () => { + try { + const filt = await getAssetImages("67d934ad0f42a1fdadb19aa6"); + setModels(filt.items); + setFilteredModels(filt.items); + } catch {} + }; + filteredAssets(); + }, []); + return (
- - + +
diff --git a/app/src/services/marketplace/fetchAssetDetails.ts b/app/src/services/marketplace/fetchAssetDetails.ts new file mode 100644 index 0000000..b14fd3f --- /dev/null +++ b/app/src/services/marketplace/fetchAssetDetails.ts @@ -0,0 +1,22 @@ +let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; +export const getAssetDetails = async (filename: string) => { + try { + const response = await fetch(`${BackEnd_url}/api/v1/assetDetails`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ filename }), + }); + + if (!response.ok) { + throw new Error("Failed to fetch asset details"); + } + + const result = await response.json(); + return result; + } catch (error: any) { + // console.error("Error fetching category:", error.message); + throw new Error(error.message); + } +}; diff --git a/app/src/services/marketplace/fetchAssets.ts b/app/src/services/marketplace/fetchAssets.ts index 3408252..e434a2b 100644 --- a/app/src/services/marketplace/fetchAssets.ts +++ b/app/src/services/marketplace/fetchAssets.ts @@ -6,6 +6,8 @@ export const fetchAssets = async () => { throw new Error("Network response was not ok"); } const result = await response.json(); + const last10Assets = result.slice(-10); + console.log('last10Assets: ', last10Assets); return result; } catch (error) { console.log("error: ", error); diff --git a/app/src/services/marketplace/fetchGltfUrl.ts b/app/src/services/marketplace/fetchGltfUrl.ts new file mode 100644 index 0000000..3916c9e --- /dev/null +++ b/app/src/services/marketplace/fetchGltfUrl.ts @@ -0,0 +1,7 @@ +let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; +export const fetchGltfUrl = (filename: string) => { + if (filename) { + return `${BackEnd_url}/api/v1/getAssetFile/${filename}`; + } + return null; // or handle the case when filename is not provided +}; diff --git a/app/src/services/marketplace/getAssetDownload.ts b/app/src/services/marketplace/getAssetDownload.ts new file mode 100644 index 0000000..dea6d14 --- /dev/null +++ b/app/src/services/marketplace/getAssetDownload.ts @@ -0,0 +1,4 @@ +let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; +export const getAssetDownload = (filename: any) => { + return `${BackEnd_url}/api/v1/getAssetFile/${filename}.gltf`; +}; diff --git a/app/src/services/marketplace/getSortedAssets.ts b/app/src/services/marketplace/getSortedAssets.ts new file mode 100644 index 0000000..3bbbfbe --- /dev/null +++ b/app/src/services/marketplace/getSortedAssets.ts @@ -0,0 +1,25 @@ +let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; +export const getSortedAssets = async (category: any, orders: any) => { + try { + const response = await fetch( + `${BackEnd_url}/api/v1/categoryWise/${category}?sortBy=${orders}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); + + if (!response.ok) { + throw new Error(`Error: ${response.statusText}`); + } + + const result = await response.json(); + + return result; // Return the result to be used later + } catch (error: any) { + console.error("Error fetching category:", error.message); + throw new Error(error.message); + } +}; diff --git a/app/src/styles/components/marketPlace/marketPlace.scss b/app/src/styles/components/marketPlace/marketPlace.scss index 8df0896..71f5897 100644 --- a/app/src/styles/components/marketPlace/marketPlace.scss +++ b/app/src/styles/components/marketPlace/marketPlace.scss @@ -126,6 +126,8 @@ display: flex; max-height: 180px; justify-content: center; + border-radius: #{$border-radius-medium}; + overflow: hidden; img{ height: inherit; width: 100%; @@ -211,7 +213,7 @@ background-color: var(--background-color); display: flex; gap: 12px; - z-index: 100; + overflow: hidden; border-radius: 20px; } From 49af0ea3c9b644121dc352fb06bdf7042772ae53 Mon Sep 17 00:00:00 2001 From: gabriel Date: Fri, 28 Mar 2025 18:17:45 +0530 Subject: [PATCH 2/4] added dynamic input based on graph --- app/.env | 3 + app/package-lock.json | 187 +++++++++-- app/package.json | 1 + .../visualization/widgets/Widgets2D.tsx | 2 +- .../IotInputCards/LineGrapInput.tsx | 304 +++++++++++------ .../IotInputCards/PieChartInput.tsx | 3 +- .../ui/componets/DraggableWidget.tsx | 48 +-- .../realTimeVis/charts/BarGraphComponent.tsx | 302 +++++++++++++++-- .../realTimeVis/charts/LineGraphComponent.tsx | 260 ++++----------- .../realTimeVis/charts/PieGraphComponent.tsx | 309 ++++++++++++++++-- .../factoryBuilder/mqtt/mqttEvents.ts | 2 +- app/src/store/useChartStore.ts | 7 +- 12 files changed, 1022 insertions(+), 406 deletions(-) diff --git a/app/.env b/app/.env index db5ccb6..dd5a41d 100644 --- a/app/.env +++ b/app/.env @@ -9,3 +9,6 @@ REACT_APP_SERVER_REST_API_BASE_URL=185.100.212.76:5000 # Base URL for the server marketplace API. REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011 + +# base url for IoT socket server +REACT_APP_IOT_SOCKET_SERVER_URL =185.100.212.76:5010 diff --git a/app/package-lock.json b/app/package-lock.json index 20fa0fc..9a7d772 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -14,6 +14,7 @@ "@react-three/drei": "^9.113.0", "@react-three/fiber": "^8.17.7", "@react-three/postprocessing": "^2.16.3", + "@recast-navigation/core": "^0.39.0", "@recast-navigation/three": "^0.39.0", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", @@ -3760,6 +3761,7 @@ "version": "0.39.0", "resolved": "https://registry.npmjs.org/@recast-navigation/core/-/core-0.39.0.tgz", "integrity": "sha512-l48GHrimIUR+9ugAsjIecdUh5ohHULrFYUn5EqClafV5HJB/cPFBbN4n9HV2jDamCjGRGEhtSpId7NpkhoF0qQ==", + "license": "MIT", "dependencies": { "@recast-navigation/wasm": "0.39.0" } @@ -3768,6 +3770,7 @@ "version": "0.39.0", "resolved": "https://registry.npmjs.org/@recast-navigation/generators/-/generators-0.39.0.tgz", "integrity": "sha512-ymiacmEWK4SGY/FUlr6/n9/FgvA9NikPR57JyCGbteScEG10UYByrPGXJQU/UXuzUhUbmtKlPJAk2KP+MLgxJA==", + "license": "MIT", "dependencies": { "@recast-navigation/core": "0.39.0", "@recast-navigation/wasm": "0.39.0" @@ -3777,6 +3780,7 @@ "version": "0.39.0", "resolved": "https://registry.npmjs.org/@recast-navigation/three/-/three-0.39.0.tgz", "integrity": "sha512-zk2EnZSoMY1P2uYexGFnfoOG92kUD94B1R+7pz4MMOjcryqCKzGhTSalThyY8SbNi9r4MrKe7Xd50W4vS/1k8A==", + "license": "MIT", "dependencies": { "@recast-navigation/core": "0.39.0", "@recast-navigation/generators": "0.39.0" @@ -3789,7 +3793,8 @@ "node_modules/@recast-navigation/wasm": { "version": "0.39.0", "resolved": "https://registry.npmjs.org/@recast-navigation/wasm/-/wasm-0.39.0.tgz", - "integrity": "sha512-1P/8pqXtwJSVseLBtO0AOdqQe1XnhPFTVvG9FMORFVFunYqkKXxULgni8x3fsutkQisyY+X7YQoIMLvZR4lKFA==" + "integrity": "sha512-1P/8pqXtwJSVseLBtO0AOdqQe1XnhPFTVvG9FMORFVFunYqkKXxULgni8x3fsutkQisyY+X7YQoIMLvZR4lKFA==", + "license": "MIT" }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", @@ -4132,6 +4137,7 @@ "version": "10.4.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "license": "MIT", "peer": true, "dependencies": { "@babel/code-frame": "^7.10.4", @@ -4282,6 +4288,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/along/-/along-7.2.0.tgz", "integrity": "sha512-Cf+d2LozABdb0TJoIcJwFKB+qisJY4nMUW9z6PAuZ9UCH7AR//hy2Z06vwYCKFZKP4a7DRPkOMBadQABCyoYuw==", + "license": "MIT", "dependencies": { "@turf/bearing": "^7.2.0", "@turf/destination": "^7.2.0", @@ -4299,6 +4306,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/angle/-/angle-7.2.0.tgz", "integrity": "sha512-b28rs1NO8Dt/MXadFhnpqH7GnEWRsl+xF5JeFtg9+eM/+l/zGrdliPYMZtAj12xn33w22J1X4TRprAI0rruvVQ==", + "license": "MIT", "dependencies": { "@turf/bearing": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -4315,6 +4323,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/area/-/area-7.2.0.tgz", "integrity": "sha512-zuTTdQ4eoTI9nSSjerIy4QwgvxqwJVciQJ8tOPuMHbXJ9N/dNjI7bU8tasjhxas/Cx3NE9NxVHtNpYHL0FSzoA==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/meta": "^7.2.0", @@ -4329,6 +4338,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/bbox/-/bbox-7.2.0.tgz", "integrity": "sha512-wzHEjCXlYZiDludDbXkpBSmv8Zu6tPGLmJ1sXQ6qDwpLE1Ew3mcWqt8AaxfTP5QwDNQa3sf2vvgTEzNbPQkCiA==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/meta": "^7.2.0", @@ -4343,6 +4353,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/bbox-clip/-/bbox-clip-7.2.0.tgz", "integrity": "sha512-q6RXTpqeUQAYLAieUL1n3J6ukRGsNVDOqcYtfzaJbPW+0VsAf+1cI16sN700t0sekbeU1DH/RRVAHhpf8+36wA==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -4357,6 +4368,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/bbox-polygon/-/bbox-polygon-7.2.0.tgz", "integrity": "sha512-Aj4G1GAAy26fmOqMjUk0Z+Lcax5VQ9g1xYDbHLQWXvfTsaueBT+RzdH6XPnZ/seEEnZkio2IxE8V5af/osupgA==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@types/geojson": "^7946.0.10", @@ -4370,6 +4382,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/bearing/-/bearing-7.2.0.tgz", "integrity": "sha512-Jm0Xt3GgHjRrWvBtAGvgfnADLm+4exud2pRlmCYx8zfiKuNXQFkrcTZcOiJOgTfG20Agq28iSh15uta47jSIbg==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -4384,6 +4397,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/bezier-spline/-/bezier-spline-7.2.0.tgz", "integrity": "sha512-7BPkc3ufYB9KLvcaTpTsnpXzh9DZoENxCS0Ms9XUwuRXw45TpevwUpOsa3atO76iKQ5puHntqFO4zs8IUxBaaA==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -4398,6 +4412,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/boolean-clockwise/-/boolean-clockwise-7.2.0.tgz", "integrity": "sha512-0fJeFSARxy6ealGBM4Gmgpa1o8msQF87p2Dx5V6uSqzT8VPDegX1NSWl4b7QgXczYa9qv7IAABttdWP0K7Q7eQ==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -4412,6 +4427,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/boolean-concave/-/boolean-concave-7.2.0.tgz", "integrity": "sha512-v3dTN04dfO6VqctQj1a+pjDHb6+/Ev90oAR2QjJuAntY4ubhhr7vKeJdk/w+tWNSMKULnYwfe65Du3EOu3/TeA==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -4426,6 +4442,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/boolean-contains/-/boolean-contains-7.2.0.tgz", "integrity": "sha512-dgRQm4uVO5XuLee4PLVH7CFQZKdefUBMIXTPITm2oRIDmPLJKHDOFKQTNkGJ73mDKKBR2lmt6eVH3br6OYrEYg==", + "license": "MIT", "dependencies": { "@turf/bbox": "^7.2.0", "@turf/boolean-point-in-polygon": "^7.2.0", @@ -4443,6 +4460,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/boolean-crosses/-/boolean-crosses-7.2.0.tgz", "integrity": "sha512-9GyM4UUWFKQOoNhHVSfJBf5XbPy8Fxfz9djjJNAnm/IOl8NmFUSwFPAjKlpiMcr6yuaAoc9R/1KokS9/eLqPvA==", + "license": "MIT", "dependencies": { "@turf/boolean-point-in-polygon": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -4460,6 +4478,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/boolean-disjoint/-/boolean-disjoint-7.2.0.tgz", "integrity": "sha512-xdz+pYKkLMuqkNeJ6EF/3OdAiJdiHhcHCV0ykX33NIuALKIEpKik0+NdxxNsZsivOW6keKwr61SI+gcVtHYcnQ==", + "license": "MIT", "dependencies": { "@turf/boolean-point-in-polygon": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -4477,6 +4496,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/boolean-equal/-/boolean-equal-7.2.0.tgz", "integrity": "sha512-TmjKYLsxXqEmdDtFq3QgX4aSogiISp3/doeEtDOs3NNSR8susOtBEZkmvwO6DLW+g/rgoQJIBR6iVoWiRqkBxw==", + "license": "MIT", "dependencies": { "@turf/clean-coords": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -4493,6 +4513,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/boolean-intersects/-/boolean-intersects-7.2.0.tgz", "integrity": "sha512-GLRyLQgK3F14drkK5Qi9Mv7Z9VT1bgQUd9a3DB3DACTZWDSwfh8YZUFn/HBwRkK8dDdgNEXaavggQHcPi1k9ow==", + "license": "MIT", "dependencies": { "@turf/boolean-disjoint": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -4508,6 +4529,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/boolean-overlap/-/boolean-overlap-7.2.0.tgz", "integrity": "sha512-ieM5qIE4anO+gUHIOvEN7CjyowF+kQ6v20/oNYJCp63TVS6eGMkwgd+I4uMzBXfVW66nVHIXjODdUelU+Xyctw==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -4526,6 +4548,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/boolean-parallel/-/boolean-parallel-7.2.0.tgz", "integrity": "sha512-iOtuzzff8nmwv05ROkSvyeGLMrfdGkIi+3hyQ+DH4IVyV37vQbqR5oOJ0Nt3Qq1Tjrq9fvF8G3OMdAv3W2kY9w==", + "license": "MIT", "dependencies": { "@turf/clean-coords": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -4542,6 +4565,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-7.2.0.tgz", "integrity": "sha512-lvEOjxeXIp+wPXgl9kJA97dqzMfNexjqHou+XHVcfxQgolctoJiRYmcVCWGpiZ9CBf/CJha1KmD1qQoRIsjLaA==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -4557,6 +4581,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/boolean-point-on-line/-/boolean-point-on-line-7.2.0.tgz", "integrity": "sha512-H/bXX8+2VYeSyH8JWrOsu8OGmeA9KVZfM7M6U5/fSqGsRHXo9MyYJ94k39A9kcKSwI0aWiMXVD2UFmiWy8423Q==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -4571,6 +4596,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/boolean-touches/-/boolean-touches-7.2.0.tgz", "integrity": "sha512-8qb1CO+cwFATGRGFgTRjzL9aibfsbI91pdiRl7KIEkVdeN/H9k8FDrUA1neY7Yq48IaciuwqjbbojQ16FD9b0w==", + "license": "MIT", "dependencies": { "@turf/boolean-point-in-polygon": "^7.2.0", "@turf/boolean-point-on-line": "^7.2.0", @@ -4587,6 +4613,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/boolean-valid/-/boolean-valid-7.2.0.tgz", "integrity": "sha512-xb7gdHN8VV6ivPJh6rPpgxmAEGReiRxqY+QZoEZVGpW2dXcmU1BdY6FA6G/cwvggXAXxJBREoANtEDgp/0ySbA==", + "license": "MIT", "dependencies": { "@turf/bbox": "^7.2.0", "@turf/boolean-crosses": "^7.2.0", @@ -4609,6 +4636,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/boolean-within/-/boolean-within-7.2.0.tgz", "integrity": "sha512-zB3AiF59zQZ27Dp1iyhp9mVAKOFHat8RDH45TZhLY8EaqdEPdmLGvwMFCKfLryQcUDQvmzP8xWbtUR82QM5C4g==", + "license": "MIT", "dependencies": { "@turf/bbox": "^7.2.0", "@turf/boolean-point-in-polygon": "^7.2.0", @@ -4626,6 +4654,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/buffer/-/buffer-7.2.0.tgz", "integrity": "sha512-QH1FTr5Mk4z1kpQNztMD8XBOZfpOXPOtlsxaSAj2kDIf5+LquA6HtJjZrjUngnGtzG5+XwcfyRL4ImvLnFjm5Q==", + "license": "MIT", "dependencies": { "@turf/bbox": "^7.2.0", "@turf/center": "^7.2.0", @@ -4644,6 +4673,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/center/-/center-7.2.0.tgz", "integrity": "sha512-UTNp9abQ2kuyRg5gCIGDNwwEQeF3NbpYsd1Q0KW9lwWuzbLVNn0sOwbxjpNF4J2HtMOs5YVOcqNvYyuoa2XrXw==", + "license": "MIT", "dependencies": { "@turf/bbox": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -4658,6 +4688,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/center-mean/-/center-mean-7.2.0.tgz", "integrity": "sha512-NaW6IowAooTJ35O198Jw3U4diZ6UZCCeJY+4E+WMLpks3FCxMDSHEfO2QjyOXQMGWZnVxVelqI5x9DdniDbQ+A==", + "license": "MIT", "dependencies": { "@turf/bbox": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -4673,6 +4704,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/center-median/-/center-median-7.2.0.tgz", "integrity": "sha512-/CgVyHNG4zAoZpvkl7qBCe4w7giWNVtLyTU5PoIfg1vWM4VpYw+N7kcBBH46bbzvVBn0vhmZr586r543EwdC/A==", + "license": "MIT", "dependencies": { "@turf/center-mean": "^7.2.0", "@turf/centroid": "^7.2.0", @@ -4690,6 +4722,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/center-of-mass/-/center-of-mass-7.2.0.tgz", "integrity": "sha512-ij3pmG61WQPHGTQvOziPOdIgwTMegkYTwIc71Gl7xn4C0vWH6KLDSshCphds9xdWSXt2GbHpUs3tr4XGntHkEQ==", + "license": "MIT", "dependencies": { "@turf/centroid": "^7.2.0", "@turf/convex": "^7.2.0", @@ -4707,6 +4740,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/centroid/-/centroid-7.2.0.tgz", "integrity": "sha512-yJqDSw25T7P48au5KjvYqbDVZ7qVnipziVfZ9aSo7P2/jTE7d4BP21w0/XLi3T/9bry/t9PR1GDDDQljN4KfDw==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/meta": "^7.2.0", @@ -4721,6 +4755,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/circle/-/circle-7.2.0.tgz", "integrity": "sha512-1AbqBYtXhstrHmnW6jhLwsv7TtmT0mW58Hvl1uZXEDM1NCVXIR50yDipIeQPjrCuJ/Zdg/91gU8+4GuDCAxBGA==", + "license": "MIT", "dependencies": { "@turf/destination": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -4735,6 +4770,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/clean-coords/-/clean-coords-7.2.0.tgz", "integrity": "sha512-+5+J1+D7wW7O/RDXn46IfCHuX1gIV1pIAQNSA7lcDbr3HQITZj334C4mOGZLEcGbsiXtlHWZiBtm785Vg8i+QQ==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -4749,6 +4785,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-7.2.0.tgz", "integrity": "sha512-JlGUT+/5qoU5jqZmf6NMFIoLDY3O7jKd53Up+zbpJ2vzUp6QdwdNzwrsCeONhynWM13F0MVtPXH4AtdkrgFk4g==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@types/geojson": "^7946.0.10", @@ -4762,6 +4799,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/clusters/-/clusters-7.2.0.tgz", "integrity": "sha512-sKOrIKHHtXAuTKNm2USnEct+6/MrgyzMW42deZ2YG2RRKWGaaxHMFU2Yw71Yk4DqStOqTIBQpIOdrRuSOwbuQw==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/meta": "^7.2.0", @@ -4776,6 +4814,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/clusters-dbscan/-/clusters-dbscan-7.2.0.tgz", "integrity": "sha512-VWVUuDreev56g3/BMlnq/81yzczqaz+NVTypN5CigGgP67e+u/CnijphiuhKjtjDd/MzGjXgEWBJc26Y6LYKAw==", + "license": "MIT", "dependencies": { "@turf/clone": "^7.2.0", "@turf/distance": "^7.2.0", @@ -4793,6 +4832,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/clusters-kmeans/-/clusters-kmeans-7.2.0.tgz", "integrity": "sha512-BxQdK8jc8Mwm9yoClCYkktm4W004uiQGqb/i/6Y7a8xqgJITWDgTu/cy//wOxAWPk4xfe6MThjnqkszWW8JdyQ==", + "license": "MIT", "dependencies": { "@turf/clone": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -4810,6 +4850,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/collect/-/collect-7.2.0.tgz", "integrity": "sha512-zRVGDlYS8Bx/Zz4vnEUyRg4dmqHhkDbW/nIUIJh657YqaMj1SFi4Iv2i9NbcurlUBDJFkpuOhCvvEvAdskJ8UA==", + "license": "MIT", "dependencies": { "@turf/bbox": "^7.2.0", "@turf/boolean-point-in-polygon": "^7.2.0", @@ -4826,6 +4867,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/combine/-/combine-7.2.0.tgz", "integrity": "sha512-VEjm3IvnbMt3IgeRIhCDhhQDbLqCU1/5uN1+j1u6fyA095pCizPThGp4f/COSzC3t1s/iiV+fHuDsB6DihHffQ==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/meta": "^7.2.0", @@ -4840,6 +4882,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/concave/-/concave-7.2.0.tgz", "integrity": "sha512-cpaDDlumK762kdadexw5ZAB6g/h2pJdihZ+e65lbQVe3WukJHAANnIEeKsdFCuIyNKrwTz2gWu5ws+OpjP48Yw==", + "license": "MIT", "dependencies": { "@turf/clone": "^7.2.0", "@turf/distance": "^7.2.0", @@ -4860,6 +4903,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/convex/-/convex-7.2.0.tgz", "integrity": "sha512-HsgHm+zHRE8yPCE/jBUtWFyaaBmpXcSlyHd5/xsMhSZRImFzRzBibaONWQo7xbKZMISC3Nc6BtUjDi/jEVbqyA==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/meta": "^7.2.0", @@ -4875,6 +4919,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/destination/-/destination-7.2.0.tgz", "integrity": "sha512-8DUxtOO0Fvrh1xclIUj3d9C5WS20D21F5E+j+X9Q+ju6fcM4huOqTg5ckV1DN2Pg8caABEc5HEZJnGch/5YnYQ==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -4889,6 +4934,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/difference/-/difference-7.2.0.tgz", "integrity": "sha512-NHKD1v3s8RX+9lOpvHJg6xRuJOKiY3qxHhz5/FmE0VgGqnCkE7OObqWZ5SsXG+Ckh0aafs5qKhmDdDV/gGi6JA==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/meta": "^7.2.0", @@ -4904,6 +4950,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/dissolve/-/dissolve-7.2.0.tgz", "integrity": "sha512-gPG5TE3mAYuZqBut8tPYCKwi4hhx5Cq0ALoQMB9X0hrVtFIKrihrsj98XQM/5pL/UIpAxQfwisQvy6XaOFaoPA==", + "license": "MIT", "dependencies": { "@turf/flatten": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -4921,6 +4968,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/distance/-/distance-7.2.0.tgz", "integrity": "sha512-HBjjXIgEcD/wJYjv7/6OZj5yoky2oUvTtVeIAqO3lL80XRvoYmVg6vkOIu6NswkerwLDDNT9kl7+BFLJoHbh6Q==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -4935,6 +4983,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/distance-weight/-/distance-weight-7.2.0.tgz", "integrity": "sha512-NeoyV0fXDH+7nIoNtLjAoH9XL0AS1pmTIyDxEE6LryoDTsqjnuR0YQxIkLCCWDqECoqaOmmBqpeWONjX5BwWCg==", + "license": "MIT", "dependencies": { "@turf/centroid": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -4951,6 +5000,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/ellipse/-/ellipse-7.2.0.tgz", "integrity": "sha512-/Y75S5hE2+xjnTw4dXpQ5r/Y2HPM4xrwkPRCCQRpuuboKdEvm42azYmh7isPnMnBTVcmGb9UmGKj0HHAbiwt1g==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -4967,6 +5017,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/envelope/-/envelope-7.2.0.tgz", "integrity": "sha512-xOMtDeNKHwUuDfzQeoSNmdabsP0/IgVDeyzitDe/8j9wTeW+MrKzVbGz7627PT3h6gsO+2nUv5asfKtUbmTyHA==", + "license": "MIT", "dependencies": { "@turf/bbox": "^7.2.0", "@turf/bbox-polygon": "^7.2.0", @@ -4982,6 +5033,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/explode/-/explode-7.2.0.tgz", "integrity": "sha512-jyMXg93J1OI7/65SsLE1k9dfQD3JbcPNMi4/O3QR2Qb3BAs2039oFaSjtW+YqhMqVC4V3ZeKebMcJ8h9sK1n+A==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/meta": "^7.2.0", @@ -4996,6 +5048,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/flatten/-/flatten-7.2.0.tgz", "integrity": "sha512-q38Qsqr4l7mxp780zSdn0gp/WLBX+sa+gV6qIbDQ1HKCrrPK8QQJmNx7gk1xxEXVot6tq/WyAPysCQdX+kLmMA==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/meta": "^7.2.0", @@ -5010,6 +5063,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/flip/-/flip-7.2.0.tgz", "integrity": "sha512-X0TQ0U/UYh4tyXdLO5itP1sO2HOvfrZC0fYSWmTfLDM14jEPkEK8PblofznfBygL+pIFtOS2is8FuVcp5XxYpQ==", + "license": "MIT", "dependencies": { "@turf/clone": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -5025,6 +5079,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/geojson-rbush/-/geojson-rbush-7.2.0.tgz", "integrity": "sha512-ST8fLv+EwxVkDgsmhHggM0sPk2SfOHTZJkdgMXVFT7gB9o4lF8qk4y4lwvCCGIfFQAp2yv/PN5EaGMEKutk6xw==", + "license": "MIT", "dependencies": { "@turf/bbox": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -5040,6 +5095,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/great-circle/-/great-circle-7.2.0.tgz", "integrity": "sha512-n30OiADyOKHhor0aXNgYfXQYXO3UtsOKmhQsY1D89/Oh1nCIXG/1ZPlLL9ZoaRXXBTUBjh99a+K8029NQbGDhw==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -5053,6 +5109,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.2.0.tgz", "integrity": "sha512-cXo7bKNZoa7aC7ydLmUR02oB3IgDe7MxiPuRz3cCtYQHn+BJ6h1tihmamYDWWUlPHgSNF0i3ATc4WmDECZafKw==", + "license": "MIT", "dependencies": { "@types/geojson": "^7946.0.10", "tslib": "^2.8.1" @@ -5065,6 +5122,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/hex-grid/-/hex-grid-7.2.0.tgz", "integrity": "sha512-Yo2yUGxrTCQfmcVsSjDt0G3Veg8YD26WRd7etVPD9eirNNgXrIyZkbYA7zVV/qLeRWVmYIKRXg1USWl7ORQOGA==", + "license": "MIT", "dependencies": { "@turf/distance": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -5081,6 +5139,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/interpolate/-/interpolate-7.2.0.tgz", "integrity": "sha512-Ifgjm1SEo6XujuSAU6lpRMvoJ1SYTreil1Rf5WsaXj16BQJCedht/4FtWCTNhSWTwEz2motQ1WNrjTCuPG94xA==", + "license": "MIT", "dependencies": { "@turf/bbox": "^7.2.0", "@turf/centroid": "^7.2.0", @@ -5103,6 +5162,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/intersect/-/intersect-7.2.0.tgz", "integrity": "sha512-81GMzKS9pKqLPa61qSlFxLFeAC8XbwyCQ9Qv4z6o5skWk1qmMUbEHeMqaGUTEzk+q2XyhZ0sju1FV4iLevQ/aw==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/meta": "^7.2.0", @@ -5118,6 +5178,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.2.0.tgz", "integrity": "sha512-kV4u8e7Gkpq+kPbAKNC21CmyrXzlbBgFjO1PhrHPgEdNqXqDawoZ3i6ivE3ULJj2rSesCjduUaC/wyvH/sNr2Q==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@types/geojson": "^7946.0.10", @@ -5131,6 +5192,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/isobands/-/isobands-7.2.0.tgz", "integrity": "sha512-lYoHeRieFzpBp29Jh19QcDIb0E+dzo/K5uwZuNga4wxr6heNU0AfkD4ByAHYIXHtvmp4m/JpSKq/2N6h/zvBkg==", + "license": "MIT", "dependencies": { "@turf/area": "^7.2.0", "@turf/bbox": "^7.2.0", @@ -5151,6 +5213,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/isolines/-/isolines-7.2.0.tgz", "integrity": "sha512-4ZXKxvA/JKkxAXixXhN3UVza5FABsdYgOWXyYm3L5ryTPJVOYTVSSd9A+CAVlv9dZc3YdlsqMqLTXNOOre/kwg==", + "license": "MIT", "dependencies": { "@turf/bbox": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -5168,6 +5231,7 @@ "version": "2.7.2", "resolved": "https://registry.npmjs.org/@turf/jsts/-/jsts-2.7.2.tgz", "integrity": "sha512-zAezGlwWHPyU0zxwcX2wQY3RkRpwuoBmhhNE9HY9kWhFDkCxZ3aWK5URKwa/SWKJbj9aztO+8vtdiBA28KVJFg==", + "license": "(EDL-1.0 OR EPL-1.0)", "dependencies": { "jsts": "2.7.1" } @@ -5176,6 +5240,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/kinks/-/kinks-7.2.0.tgz", "integrity": "sha512-BtxDxGewJR0Q5WR9HKBSxZhirFX+GEH1rD7/EvgDsHS8e1Y5/vNQQUmXdURjdPa4StzaUBsWRU5T3A356gLbPA==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@types/geojson": "^7946.0.10", @@ -5189,6 +5254,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/length/-/length-7.2.0.tgz", "integrity": "sha512-LBmYN+iCgVtWNLsckVnpQIJENqIIPO63mogazMp23lrDGfWXu07zZQ9ZinJVO5xYurXNhc/QI2xxoqt2Xw90Ig==", + "license": "MIT", "dependencies": { "@turf/distance": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -5204,6 +5270,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/line-arc/-/line-arc-7.2.0.tgz", "integrity": "sha512-kfWzA5oYrTpslTg5fN50G04zSypiYQzjZv3FLjbZkk6kta5fo4JkERKjTeA8x4XNojb+pfmjMBB0yIh2w2dDRw==", + "license": "MIT", "dependencies": { "@turf/circle": "^7.2.0", "@turf/destination": "^7.2.0", @@ -5219,6 +5286,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/line-chunk/-/line-chunk-7.2.0.tgz", "integrity": "sha512-1ODyL5gETtWSL85MPI0lgp/78vl95M39gpeBxePXyDIqx8geDP9kXfAzctuKdxBoR4JmOVM3NT7Fz7h+IEkC+g==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/length": "^7.2.0", @@ -5234,6 +5302,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/line-intersect/-/line-intersect-7.2.0.tgz", "integrity": "sha512-GhCJVEkc8EmggNi85EuVLoXF5T5jNVxmhIetwppiVyJzMrwkYAkZSYB3IBFYGUUB9qiNFnTwungVSsBV/S8ZiA==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@types/geojson": "^7946.0.10", @@ -5248,6 +5317,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/line-offset/-/line-offset-7.2.0.tgz", "integrity": "sha512-1+OkYueDCbnEWzbfBh3taVr+3SyM2bal5jfnSEuDiLA6jnlScgr8tn3INo+zwrUkPFZPPAejL1swVyO5TjUahw==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -5262,6 +5332,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/line-overlap/-/line-overlap-7.2.0.tgz", "integrity": "sha512-NNn7/jg53+N10q2Kyt66bEDqN3101iW/1zA5FW7J6UbKApDFkByh+18YZq1of71kS6oUYplP86WkDp16LFpqqw==", + "license": "MIT", "dependencies": { "@turf/boolean-point-on-line": "^7.2.0", "@turf/geojson-rbush": "^7.2.0", @@ -5282,6 +5353,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/line-segment/-/line-segment-7.2.0.tgz", "integrity": "sha512-E162rmTF9XjVN4rINJCd15AdQGCBlNqeWN3V0YI1vOUpZFNT2ii4SqEMCcH2d+5EheHLL8BWVwZoOsvHZbvaWA==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -5297,6 +5369,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/line-slice/-/line-slice-7.2.0.tgz", "integrity": "sha512-bHotzZIaU1GPV3RMwttYpDrmcvb3X2i1g/WUttPZWtKrEo2VVAkoYdeZ2aFwtogERYS4quFdJ/TDzAtquBC8WQ==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -5311,6 +5384,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/line-slice-along/-/line-slice-along-7.2.0.tgz", "integrity": "sha512-4/gPgP0j5Rp+1prbhXqn7kIH/uZTmSgiubUnn67F8nb9zE+MhbRglhSlRYEZxAVkB7VrGwjyolCwvrROhjHp2A==", + "license": "MIT", "dependencies": { "@turf/bearing": "^7.2.0", "@turf/destination": "^7.2.0", @@ -5326,6 +5400,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/line-split/-/line-split-7.2.0.tgz", "integrity": "sha512-yJTZR+c8CwoKqdW/aIs+iLbuFwAa3Yan+EOADFQuXXIUGps3bJUXx/38rmowNoZbHyP1np1+OtrotyHu5uBsfQ==", + "license": "MIT", "dependencies": { "@turf/bbox": "^7.2.0", "@turf/geojson-rbush": "^7.2.0", @@ -5347,6 +5422,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/line-to-polygon/-/line-to-polygon-7.2.0.tgz", "integrity": "sha512-iKpJqc7EYc5NvlD4KaqrKKO6mXR7YWO/YwtW60E2FnsF/blnsy9OfAOcilYHgH3S/V/TT0VedC7DW7Kgjy2EIA==", + "license": "MIT", "dependencies": { "@turf/bbox": "^7.2.0", "@turf/clone": "^7.2.0", @@ -5363,6 +5439,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/mask/-/mask-7.2.0.tgz", "integrity": "sha512-ulJ6dQqXC0wrjIoqFViXuMUdIPX5Q6GPViZ3kGfeVijvlLM7kTFBsZiPQwALSr5nTQg4Ppf3FD0Jmg8IErPrgA==", + "license": "MIT", "dependencies": { "@turf/clone": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -5378,6 +5455,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.2.0.tgz", "integrity": "sha512-igzTdHsQc8TV1RhPuOLVo74Px/hyPrVgVOTgjWQZzt3J9BVseCdpfY/0cJBdlSRI4S/yTmmHl7gAqjhpYH5Yaw==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@types/geojson": "^7946.0.10" @@ -5390,6 +5468,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/midpoint/-/midpoint-7.2.0.tgz", "integrity": "sha512-AMn5S9aSrbXdE+Q4Rj+T5nLdpfpn+mfzqIaEKkYI021HC0vb22HyhQHsQbSeX+AWcS4CjD1hFsYVcgKI+5qCfw==", + "license": "MIT", "dependencies": { "@turf/bearing": "^7.2.0", "@turf/destination": "^7.2.0", @@ -5406,6 +5485,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/moran-index/-/moran-index-7.2.0.tgz", "integrity": "sha512-Aexh1EmXVPJhApr9grrd120vbalIthcIsQ3OAN2Tqwf+eExHXArJEJqGBo9IZiQbIpFJeftt/OvUvlI8BeO1bA==", + "license": "MIT", "dependencies": { "@turf/distance-weight": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -5421,6 +5501,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/nearest-neighbor-analysis/-/nearest-neighbor-analysis-7.2.0.tgz", "integrity": "sha512-LmP/crXb7gilgsL0wL9hsygqc537W/a1W5r9XBKJT4SKdqjoXX5APJatJfd3nwXbRIqwDH0cDA9/YyFjBPlKnA==", + "license": "MIT", "dependencies": { "@turf/area": "^7.2.0", "@turf/bbox": "^7.2.0", @@ -5441,6 +5522,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/nearest-point/-/nearest-point-7.2.0.tgz", "integrity": "sha512-0wmsqXZ8CGw4QKeZmS+NdjYTqCMC+HXZvM3XAQIU6k6laNLqjad2oS4nDrtcRs/nWDvcj1CR+Io7OiQ6sbpn5Q==", + "license": "MIT", "dependencies": { "@turf/clone": "^7.2.0", "@turf/distance": "^7.2.0", @@ -5457,6 +5539,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/nearest-point-on-line/-/nearest-point-on-line-7.2.0.tgz", "integrity": "sha512-UOhAeoDPVewBQV+PWg1YTMQcYpJsIqfW5+EuZ5vJl60XwUa0+kqB/eVfSLNXmHENjKKIlEt9Oy9HIDF4VeWmXA==", + "license": "MIT", "dependencies": { "@turf/distance": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -5473,6 +5556,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/nearest-point-to-line/-/nearest-point-to-line-7.2.0.tgz", "integrity": "sha512-EorU7Qj30A7nAjh++KF/eTPDlzwuuV4neBz7tmSTB21HKuXZAR0upJsx6M2X1CSyGEgNsbFB0ivNKIvymRTKBw==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -5489,6 +5573,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/planepoint/-/planepoint-7.2.0.tgz", "integrity": "sha512-8Vno01tvi5gThUEKBQ46CmlEKDAwVpkl7stOPFvJYlA1oywjAL4PsmgwjXgleZuFtXQUPBNgv5a42Pf438XP4g==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -5503,6 +5588,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/point-grid/-/point-grid-7.2.0.tgz", "integrity": "sha512-ai7lwBV2FREPW3XiUNohT4opC1hd6+F56qZe20xYhCTkTD9diWjXHiNudQPSmVAUjgMzQGasblQQqvOdL+bJ3Q==", + "license": "MIT", "dependencies": { "@turf/boolean-within": "^7.2.0", "@turf/distance": "^7.2.0", @@ -5519,6 +5605,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/point-on-feature/-/point-on-feature-7.2.0.tgz", "integrity": "sha512-ksoYoLO9WtJ/qI8VI9ltF+2ZjLWrAjZNsCsu8F7nyGeCh4I8opjf4qVLytFG44XA2qI5yc6iXDpyv0sshvP82Q==", + "license": "MIT", "dependencies": { "@turf/boolean-point-in-polygon": "^7.2.0", "@turf/center": "^7.2.0", @@ -5536,6 +5623,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/point-to-line-distance/-/point-to-line-distance-7.2.0.tgz", "integrity": "sha512-fB9Rdnb5w5+t76Gho2dYDkGe20eRrFk8CXi4v1+l1PC8YyLXO+x+l3TrtT8HzL/dVaZeepO6WUIsIw3ditTOPg==", + "license": "MIT", "dependencies": { "@turf/bearing": "^7.2.0", "@turf/distance": "^7.2.0", @@ -5557,6 +5645,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/point-to-polygon-distance/-/point-to-polygon-distance-7.2.0.tgz", "integrity": "sha512-w+WYuINgTiFjoZemQwOaQSje/8Kq+uqJOynvx7+gleQPHyWQ3VtTodtV4LwzVzXz8Sf7Mngx1Jcp2SNai5CJYA==", + "license": "MIT", "dependencies": { "@turf/boolean-point-in-polygon": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -5575,6 +5664,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/points-within-polygon/-/points-within-polygon-7.2.0.tgz", "integrity": "sha512-jRKp8/mWNMzA+hKlQhxci97H5nOio9tp14R2SzpvkOt+cswxl+NqTEi1hDd2XetA7tjU0TSoNjEgVY8FfA0S6w==", + "license": "MIT", "dependencies": { "@turf/boolean-point-in-polygon": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -5590,6 +5680,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/polygon-smooth/-/polygon-smooth-7.2.0.tgz", "integrity": "sha512-KCp9wF2IEynvGXVhySR8oQ2razKP0zwg99K+fuClP21pSKCFjAPaihPEYq6e8uI/1J7ibjL5++6EMl+LrUTrLg==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/meta": "^7.2.0", @@ -5604,6 +5695,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/polygon-tangents/-/polygon-tangents-7.2.0.tgz", "integrity": "sha512-AHUUPmOjiQDrtP/ODXukHBlUG0C/9I1je7zz50OTfl2ZDOdEqFJQC3RyNELwq07grTXZvg5TS5wYx/Y7nsm47g==", + "license": "MIT", "dependencies": { "@turf/bbox": "^7.2.0", "@turf/boolean-within": "^7.2.0", @@ -5622,6 +5714,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/polygon-to-line/-/polygon-to-line-7.2.0.tgz", "integrity": "sha512-9jeTN3LiJ933I5sd4K0kwkcivOYXXm1emk0dHorwXeSFSHF+nlYesEW3Hd889wb9lZd7/SVLMUeX/h39mX+vCA==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -5636,6 +5729,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/polygonize/-/polygonize-7.2.0.tgz", "integrity": "sha512-U9v+lBhUPDv+nsg/VcScdiqCB59afO6CHDGrwIl2+5i6Ve+/KQKjpTV/R+NqoC1iMXAEq3brY6HY8Ukp/pUWng==", + "license": "MIT", "dependencies": { "@turf/boolean-point-in-polygon": "^7.2.0", "@turf/envelope": "^7.2.0", @@ -5653,6 +5747,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/projection/-/projection-7.2.0.tgz", "integrity": "sha512-/qke5vJScv8Mu7a+fU3RSChBRijE6EVuFHU3RYihMuYm04Vw8dBMIs0enEpoq0ke/IjSbleIrGQNZIMRX9EwZQ==", + "license": "MIT", "dependencies": { "@turf/clone": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -5668,6 +5763,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/quadrat-analysis/-/quadrat-analysis-7.2.0.tgz", "integrity": "sha512-fDQh3+ldYNxUqS6QYlvJ7GZLlCeDZR6tD3ikdYtOsSemwW1n/4gm2xcgWJqy3Y0uszBwxc13IGGY7NGEjHA+0w==", + "license": "MIT", "dependencies": { "@turf/area": "^7.2.0", "@turf/bbox": "^7.2.0", @@ -5689,6 +5785,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/random/-/random-7.2.0.tgz", "integrity": "sha512-fNXs5mOeXsrirliw84S8UCNkpm4RMNbefPNsuCTfZEXhcr1MuHMzq4JWKb4FweMdN1Yx2l/xcytkO0s71cJ50w==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@types/geojson": "^7946.0.10", @@ -5702,6 +5799,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/rectangle-grid/-/rectangle-grid-7.2.0.tgz", "integrity": "sha512-f0o5ifvy0Ml/nHDJzMNcuSk4h11aa3BfvQNnYQhLpuTQu03j/ICZNlzKTLxwjcUqvxADUifty7Z9CX5W6zky4A==", + "license": "MIT", "dependencies": { "@turf/boolean-intersects": "^7.2.0", "@turf/distance": "^7.2.0", @@ -5717,6 +5815,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/rewind/-/rewind-7.2.0.tgz", "integrity": "sha512-SZpRAZiZsE22+HVz6pEID+ST25vOdpAMGk5NO1JeqzhpMALIkIGnkG+xnun2CfYHz7wv8/Z0ADiAvei9rkcQYA==", + "license": "MIT", "dependencies": { "@turf/boolean-clockwise": "^7.2.0", "@turf/clone": "^7.2.0", @@ -5734,6 +5833,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/rhumb-bearing/-/rhumb-bearing-7.2.0.tgz", "integrity": "sha512-jbdexlrR8X2ZauUciHx3tRwG+BXoMXke4B8p8/IgDlAfIrVdzAxSQN89FMzIKnjJ/kdLjo9bFGvb92bu31Etug==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -5748,6 +5848,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/rhumb-destination/-/rhumb-destination-7.2.0.tgz", "integrity": "sha512-U9OLgLAHlH4Wfx3fBZf3jvnkDjdTcfRan5eI7VPV1+fQWkOteATpzkiRjCvSYK575GljVwWBjkKca8LziGWitQ==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -5762,6 +5863,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/rhumb-distance/-/rhumb-distance-7.2.0.tgz", "integrity": "sha512-NsijTPON1yOc9tirRPEQQuJ5aQi7pREsqchQquaYKbHNWsexZjcDi4wnw2kM3Si4XjmgynT+2f7aXH7FHarHzw==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/invariant": "^7.2.0", @@ -5776,6 +5878,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/sample/-/sample-7.2.0.tgz", "integrity": "sha512-f+ZbcbQJ9glQ/F26re8LadxO0ORafy298EJZe6XtbctRTJrNus6UNAsl8+GYXFqMnXM22tbTAznnJX3ZiWNorA==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@types/geojson": "^7946.0.10", @@ -5789,6 +5892,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/sector/-/sector-7.2.0.tgz", "integrity": "sha512-zL06MjbbMG4DdpiNz+Q9Ax8jsCekt3R76uxeWShulAGkyDB5smdBOUDoRwxn05UX7l4kKv4Ucq2imQXhxKFd1w==", + "license": "MIT", "dependencies": { "@turf/circle": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -5806,6 +5910,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/shortest-path/-/shortest-path-7.2.0.tgz", "integrity": "sha512-6fpx8feZ2jMSaeRaFdqFShGWkNb+veUOeyLFSHA/aRD9n/e9F2pWZoRbQWKbKTpcKFJ2FnDEqCZnh/GrcAsqWA==", + "license": "MIT", "dependencies": { "@turf/bbox": "^7.2.0", "@turf/bbox-polygon": "^7.2.0", @@ -5827,6 +5932,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/simplify/-/simplify-7.2.0.tgz", "integrity": "sha512-9YHIfSc8BXQfi5IvEMbCeQYqNch0UawIGwbboJaoV8rodhtk6kKV2wrpXdGqk/6Thg6/RWvChJFKVVTjVrULyQ==", + "license": "MIT", "dependencies": { "@turf/clean-coords": "^7.2.0", "@turf/clone": "^7.2.0", @@ -5843,6 +5949,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/square/-/square-7.2.0.tgz", "integrity": "sha512-9pMoAGFvqzCDOlO9IRSSBCGXKbl8EwMx6xRRBMKdZgpS0mZgfm9xiptMmx/t1m4qqHIlb/N+3MUF7iMBx6upcA==", + "license": "MIT", "dependencies": { "@turf/distance": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -5857,6 +5964,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/square-grid/-/square-grid-7.2.0.tgz", "integrity": "sha512-EmzGXa90hz+tiCOs9wX+Lak6pH0Vghb7QuX6KZej+pmWi3Yz7vdvQLmy/wuN048+wSkD5c8WUo/kTeNDe7GnmA==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/rectangle-grid": "^7.2.0", @@ -5871,6 +5979,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/standard-deviational-ellipse/-/standard-deviational-ellipse-7.2.0.tgz", "integrity": "sha512-+uC0pR2nRjm90JvMXe/2xOCZsYV2II1ZZ2zmWcBWv6bcFXBspcxk2QfCC3k0bj6jDapELzoQgnn3cG5lbdQV2w==", + "license": "MIT", "dependencies": { "@turf/center-mean": "^7.2.0", "@turf/ellipse": "^7.2.0", @@ -5889,6 +5998,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/tag/-/tag-7.2.0.tgz", "integrity": "sha512-TAFvsbp5TCBqXue8ui+CtcLsPZ6NPC88L8Ad6Hb/R6VAi21qe0U42WJHQYXzWmtThoTNwxi+oKSeFbRDsr0FIA==", + "license": "MIT", "dependencies": { "@turf/boolean-point-in-polygon": "^7.2.0", "@turf/clone": "^7.2.0", @@ -5905,6 +6015,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/tesselate/-/tesselate-7.2.0.tgz", "integrity": "sha512-zHGcG85aOJJu1seCm+CYTJ3UempX4Xtyt669vFG6Hbr/Hc7ii6STQ2ysFr7lJwFtU9uyYhphVrrgwIqwglvI/Q==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@types/geojson": "^7946.0.10", @@ -5919,6 +6030,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/tin/-/tin-7.2.0.tgz", "integrity": "sha512-y24Vt3oeE6ZXvyLJamP0Ke02rPlDGE9gF7OFADnR0mT+2uectb0UTIBC3kKzON80TEAlA3GXpKFkCW5Fo/O/Kg==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@types/geojson": "^7946.0.10", @@ -5932,6 +6044,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/transform-rotate/-/transform-rotate-7.2.0.tgz", "integrity": "sha512-EMCj0Zqy3cF9d3mGRqDlYnX2ZBXe3LgT+piDR0EuF5c5sjuKErcFcaBIsn/lg1gp4xCNZFinkZ3dsFfgGHf6fw==", + "license": "MIT", "dependencies": { "@turf/centroid": "^7.2.0", "@turf/clone": "^7.2.0", @@ -5952,6 +6065,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/transform-scale/-/transform-scale-7.2.0.tgz", "integrity": "sha512-HYB+pw938eeI8s1/zSWFy6hq+t38fuUaBb0jJsZB1K9zQ1WjEYpPvKF/0//80zNPlyxLv3cOkeBucso3hzI07A==", + "license": "MIT", "dependencies": { "@turf/bbox": "^7.2.0", "@turf/center": "^7.2.0", @@ -5974,6 +6088,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/transform-translate/-/transform-translate-7.2.0.tgz", "integrity": "sha512-zAglR8MKCqkzDTjGMIQgbg/f+Q3XcKVzr9cELw5l9CrS1a0VTSDtBZLDm0kWx0ankwtam7ZmI2jXyuQWT8Gbug==", + "license": "MIT", "dependencies": { "@turf/clone": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -5991,6 +6106,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/triangle-grid/-/triangle-grid-7.2.0.tgz", "integrity": "sha512-4gcAqWKh9hg6PC5nNSb9VWyLgl821cwf9yR9yEzQhEFfwYL/pZONBWCO1cwVF23vSYMSMm+/TwqxH4emxaArfw==", + "license": "MIT", "dependencies": { "@turf/distance": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -6006,6 +6122,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/truncate/-/truncate-7.2.0.tgz", "integrity": "sha512-jyFzxYbPugK4XjV5V/k6Xr3taBjjvo210IbPHJXw0Zh7Y6sF+hGxeRVtSuZ9VP/6oRyqAOHKUrze+OOkPqBgUg==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/meta": "^7.2.0", @@ -6020,6 +6137,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/turf/-/turf-7.2.0.tgz", "integrity": "sha512-G1kKBu4hYgoNoRJgnpJohNuS7bLnoWHZ2G/4wUMym5xOSiYah6carzdTEsMoTsauyi7ilByWHx5UHwbjjCVcBw==", + "license": "MIT", "dependencies": { "@turf/along": "^7.2.0", "@turf/angle": "^7.2.0", @@ -6145,6 +6263,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/union/-/union-7.2.0.tgz", "integrity": "sha512-Xex/cfKSmH0RZRWSJl4RLlhSmEALVewywiEXcu0aIxNbuZGTcpNoI0h4oLFrE/fUd0iBGFg/EGLXRL3zTfpg6g==", + "license": "MIT", "dependencies": { "@turf/helpers": "^7.2.0", "@turf/meta": "^7.2.0", @@ -6160,6 +6279,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/unkink-polygon/-/unkink-polygon-7.2.0.tgz", "integrity": "sha512-dFPfzlIgkEr15z6oXVxTSWshWi51HeITGVFtl1GAKGMtiXJx1uMqnfRsvljqEjaQu/4AzG1QAp3b+EkSklQSiQ==", + "license": "MIT", "dependencies": { "@turf/area": "^7.2.0", "@turf/boolean-point-in-polygon": "^7.2.0", @@ -6177,6 +6297,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/voronoi/-/voronoi-7.2.0.tgz", "integrity": "sha512-3K6N0LtJsWTXxPb/5N2qD9e8f4q8+tjTbGV3lE3v8x06iCnNlnuJnqM5NZNPpvgvCatecBkhClO3/3RndE61Fw==", + "license": "MIT", "dependencies": { "@turf/clone": "^7.2.0", "@turf/helpers": "^7.2.0", @@ -6280,7 +6401,8 @@ "node_modules/@types/d3-voronoi": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/@types/d3-voronoi/-/d3-voronoi-1.1.12.tgz", - "integrity": "sha512-DauBl25PKZZ0WVJr42a6CNvI6efsdzofl9sajqZr2Gf5Gu733WkDdUGiPkUHXiUvYGzNNlFQde2wdZdfQPG+yw==" + "integrity": "sha512-DauBl25PKZZ0WVJr42a6CNvI6efsdzofl9sajqZr2Gf5Gu733WkDdUGiPkUHXiUvYGzNNlFQde2wdZdfQPG+yw==", + "license": "MIT" }, "node_modules/@types/debounce": { "version": "1.2.4", @@ -6349,9 +6471,9 @@ } }, "node_modules/@types/geojson": { - "version": "7946.0.16", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", - "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==" + "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==" }, "node_modules/@types/graceful-fs": { "version": "4.1.9", @@ -7992,6 +8114,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "license": "MIT", "engines": { "node": "*" } @@ -8770,6 +8893,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/concaveman/-/concaveman-1.2.1.tgz", "integrity": "sha512-PwZYKaM/ckQSa8peP5JpVr7IMJ4Nn/MHIaWUjP4be+KoZ7Botgs8seAZGpmaOM+UZXawcdYRao/px9ycrCihHw==", + "license": "ISC", "dependencies": { "point-in-polygon": "^1.1.0", "rbush": "^3.0.1", @@ -9378,12 +9502,14 @@ "node_modules/d3-array": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", - "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==", + "license": "BSD-3-Clause" }, "node_modules/d3-geo": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.7.1.tgz", "integrity": "sha512-O4AempWAr+P5qbk2bC2FuN/sDW4z+dN2wDf9QV3bxQt4M5HfOEeXLgJ/UKQW0+o1Dj8BE+L5kiDbdWUMjsmQpw==", + "license": "BSD-3-Clause", "dependencies": { "d3-array": "1" } @@ -9391,7 +9517,8 @@ "node_modules/d3-voronoi": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.2.tgz", - "integrity": "sha512-RhGS1u2vavcO7ay7ZNAPo4xeDh/VYeGof3x5ZLJBQgYhLegxr3s5IykvWmJ94FTU6mcbtp4sloqZ54mP6R4Utw==" + "integrity": "sha512-RhGS1u2vavcO7ay7ZNAPo4xeDh/VYeGof3x5ZLJBQgYhLegxr3s5IykvWmJ94FTU6mcbtp4sloqZ54mP6R4Utw==", + "license": "BSD-3-Clause" }, "node_modules/damerau-levenshtein": { "version": "1.0.8", @@ -9922,7 +10049,8 @@ "node_modules/earcut": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", - "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==" + "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==", + "license": "ISC" }, "node_modules/eastasianwidth": { "version": "0.2.0", @@ -11801,6 +11929,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/geojson-equality-ts/-/geojson-equality-ts-1.0.2.tgz", "integrity": "sha512-h3Ryq+0mCSN/7yLs0eDgrZhvc9af23o/QuC4aTiuuzP/MRCtd6mf5rLsLRY44jX0RPUfM8c4GqERQmlUxPGPoQ==", + "license": "MIT", "dependencies": { "@types/geojson": "^7946.0.14" } @@ -11809,6 +11938,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/geojson-polygon-self-intersections/-/geojson-polygon-self-intersections-1.2.1.tgz", "integrity": "sha512-/QM1b5u2d172qQVO//9CGRa49jEmclKEsYOQmWP9ooEjj63tBM51m2805xsbxkzlEELQ2REgTf700gUhhlegxA==", + "license": "MIT", "dependencies": { "rbush": "^2.0.1" } @@ -11816,12 +11946,14 @@ "node_modules/geojson-polygon-self-intersections/node_modules/quickselect": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-1.1.1.tgz", - "integrity": "sha512-qN0Gqdw4c4KGPsBOQafj6yj/PA6c/L63f6CaZ/DCF/xF4Esu3jVmKLUDYxghFx8Kb/O7y9tI7x2RjTSXwdK1iQ==" + "integrity": "sha512-qN0Gqdw4c4KGPsBOQafj6yj/PA6c/L63f6CaZ/DCF/xF4Esu3jVmKLUDYxghFx8Kb/O7y9tI7x2RjTSXwdK1iQ==", + "license": "ISC" }, "node_modules/geojson-polygon-self-intersections/node_modules/rbush": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/rbush/-/rbush-2.0.2.tgz", "integrity": "sha512-XBOuALcTm+O/H8G90b6pzu6nX6v2zCKiFG4BJho8a+bY6AER6t8uQUZdi5bomQc0AprCWhEGa7ncAbbRap0bRA==", + "license": "MIT", "dependencies": { "quickselect": "^1.0.1" } @@ -14672,6 +14804,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/jsts/-/jsts-2.7.1.tgz", "integrity": "sha512-x2wSZHEBK20CY+Wy+BPE7MrFQHW6sIsdaGUMEqmGAio+3gFzQaBYPwLRonUfQf9Ak8pBieqj9tUofX1+WtAEIg==", + "license": "(EDL-1.0 OR EPL-1.0)", "engines": { "node": ">= 12" } @@ -15105,7 +15238,8 @@ "node_modules/marchingsquares": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/marchingsquares/-/marchingsquares-1.3.3.tgz", - "integrity": "sha512-gz6nNQoVK7Lkh2pZulrT4qd4347S/toG9RXH2pyzhLgkL5mLkBoqgv4EvAGXcV0ikDW72n/OQb3Xe8bGagQZCg==" + "integrity": "sha512-gz6nNQoVK7Lkh2pZulrT4qd4347S/toG9RXH2pyzhLgkL5mLkBoqgv4EvAGXcV0ikDW72n/OQb3Xe8bGagQZCg==", + "license": "AGPL-3.0" }, "node_modules/mdn-data": { "version": "2.0.4", @@ -16121,12 +16255,14 @@ "node_modules/point-in-polygon": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/point-in-polygon/-/point-in-polygon-1.1.0.tgz", - "integrity": "sha512-3ojrFwjnnw8Q9242TzgXuTD+eKiutbzyslcq1ydfu82Db2y+Ogbmyrkpv0Hgj31qwT3lbS9+QAAO/pIQM35XRw==" + "integrity": "sha512-3ojrFwjnnw8Q9242TzgXuTD+eKiutbzyslcq1ydfu82Db2y+Ogbmyrkpv0Hgj31qwT3lbS9+QAAO/pIQM35XRw==", + "license": "MIT" }, "node_modules/point-in-polygon-hao": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/point-in-polygon-hao/-/point-in-polygon-hao-1.2.4.tgz", "integrity": "sha512-x2pcvXeqhRHlNRdhLs/tgFapAbSSe86wa/eqmj1G6pWftbEs5aVRJhRGM6FYSUERKu0PjekJzMq0gsI2XyiclQ==", + "license": "MIT", "dependencies": { "robust-predicates": "^3.0.2" } @@ -16134,12 +16270,14 @@ "node_modules/point-in-polygon-hao/node_modules/robust-predicates": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", - "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", + "license": "Unlicense" }, "node_modules/polyclip-ts": { "version": "0.16.8", "resolved": "https://registry.npmjs.org/polyclip-ts/-/polyclip-ts-0.16.8.tgz", "integrity": "sha512-JPtKbDRuPEuAjuTdhR62Gph7Is2BS1Szx69CFOO3g71lpJDFo78k4tFyi+qFOMVPePEzdSKkpGU3NBXPHHjvKQ==", + "license": "MIT", "dependencies": { "bignumber.js": "^9.1.0", "splaytree-ts": "^1.0.2" @@ -17634,7 +17772,8 @@ "node_modules/quickselect": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", - "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" + "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==", + "license": "ISC" }, "node_modules/raf": { "version": "3.4.1", @@ -17689,6 +17828,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/rbush/-/rbush-3.0.1.tgz", "integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==", + "license": "MIT", "dependencies": { "quickselect": "^2.0.0" } @@ -18521,7 +18661,8 @@ "node_modules/robust-predicates": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-2.0.4.tgz", - "integrity": "sha512-l4NwboJM74Ilm4VKfbAtFeGq7aEjWL+5kVFcmgFA2MrdnQWx9iE/tUGvxY5HyMI7o/WpSIUFLbC5fbeaHgSCYg==" + "integrity": "sha512-l4NwboJM74Ilm4VKfbAtFeGq7aEjWL+5kVFcmgFA2MrdnQWx9iE/tUGvxY5HyMI7o/WpSIUFLbC5fbeaHgSCYg==", + "license": "Unlicense" }, "node_modules/rollup": { "version": "2.79.2", @@ -19107,7 +19248,8 @@ "node_modules/skmeans": { "version": "0.9.7", "resolved": "https://registry.npmjs.org/skmeans/-/skmeans-0.9.7.tgz", - "integrity": "sha512-hNj1/oZ7ygsfmPZ7ZfN5MUBRoGg1gtpnImuJBgLO0ljQ67DtJuiQaiYdS4lUA6s0KCwnPhGivtC/WRwIZLkHyg==" + "integrity": "sha512-hNj1/oZ7ygsfmPZ7ZfN5MUBRoGg1gtpnImuJBgLO0ljQ67DtJuiQaiYdS4lUA6s0KCwnPhGivtC/WRwIZLkHyg==", + "license": "MIT" }, "node_modules/slash": { "version": "3.0.0", @@ -19270,7 +19412,8 @@ "node_modules/splaytree-ts": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/splaytree-ts/-/splaytree-ts-1.0.2.tgz", - "integrity": "sha512-0kGecIZNIReCSiznK3uheYB8sbstLjCZLiwcQwbmLhgHJj2gz6OnSPkVzJQCMnmEz1BQ4gPK59ylhBoEWOhGNA==" + "integrity": "sha512-0kGecIZNIReCSiznK3uheYB8sbstLjCZLiwcQwbmLhgHJj2gz6OnSPkVzJQCMnmEz1BQ4gPK59ylhBoEWOhGNA==", + "license": "BDS-3-Clause" }, "node_modules/split-string": { "version": "3.1.0", @@ -20051,6 +20194,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/sweepline-intersections/-/sweepline-intersections-1.5.0.tgz", "integrity": "sha512-AoVmx72QHpKtItPu72TzFL+kcYjd67BPLDoR0LarIk+xyaRg+pDTMFXndIEvZf9xEKnJv6JdhgRMnocoG0D3AQ==", + "license": "MIT", "dependencies": { "tinyqueue": "^2.0.0" } @@ -20375,7 +20519,8 @@ "node_modules/tinyqueue": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz", - "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==" + "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==", + "license": "ISC" }, "node_modules/tldts": { "version": "6.1.63", @@ -20432,6 +20577,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz", "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==", + "license": "ISC", "dependencies": { "commander": "2" }, @@ -20444,12 +20590,14 @@ "node_modules/topojson-client/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" }, "node_modules/topojson-server": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/topojson-server/-/topojson-server-3.0.1.tgz", "integrity": "sha512-/VS9j/ffKr2XAOjlZ9CgyyeLmgJ9dMwq6Y0YEON8O7p/tGGk+dCWnrE03zEdu7i4L7YsFZLEPZPzCvcB7lEEXw==", + "license": "ISC", "dependencies": { "commander": "2" }, @@ -20460,7 +20608,8 @@ "node_modules/topojson-server/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" }, "node_modules/tough-cookie": { "version": "5.0.0", diff --git a/app/package.json b/app/package.json index e7ca3e7..541d3a1 100644 --- a/app/package.json +++ b/app/package.json @@ -9,6 +9,7 @@ "@react-three/drei": "^9.113.0", "@react-three/fiber": "^8.17.7", "@react-three/postprocessing": "^2.16.3", + "@recast-navigation/core": "^0.39.0", "@recast-navigation/three": "^0.39.0", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", diff --git a/app/src/components/layout/sidebarLeft/visualization/widgets/Widgets2D.tsx b/app/src/components/layout/sidebarLeft/visualization/widgets/Widgets2D.tsx index 5833986..ab9fcc8 100644 --- a/app/src/components/layout/sidebarLeft/visualization/widgets/Widgets2D.tsx +++ b/app/src/components/layout/sidebarLeft/visualization/widgets/Widgets2D.tsx @@ -18,7 +18,7 @@ const sampleData = { { data: [65, 59, 80, 81, 56, 55, 40], backgroundColor: "#6f42c1", - borderColor: "#ffffff", + borderColor: "#b392f0", borderWidth: 1, }, ], diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/LineGrapInput.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/LineGrapInput.tsx index 17cbc3e..4d406d9 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/LineGrapInput.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/LineGrapInput.tsx @@ -1,115 +1,215 @@ -import React, { useEffect, useState } from 'react' -import MultiLevelDropdown from '../../../../ui/inputs/MultiLevelDropDown' -import { AddIcon } from '../../../../icons/ExportCommonIcons' -import RegularDropDown from '../../../../ui/inputs/RegularDropDown' -import useChartStore from '../../../../../store/useChartStore' -import axios from 'axios' +// import React, { useEffect, useState } from 'react' +// import MultiLevelDropdown from '../../../../ui/inputs/MultiLevelDropDown' +// import { AddIcon } from '../../../../icons/ExportCommonIcons' +// import RegularDropDown from '../../../../ui/inputs/RegularDropDown' +// import useChartStore from '../../../../../store/useChartStore' +// import axios from 'axios' -type Props = {} +// type Props = {} -const LineGrapInput = (props: Props) => { - const [dropDowndata, setDropDownData] = useState({}) - const [selections, setSelections] = useState>({}) - const [selectedOption, setSelectedOption] = useState('1h') - const { measurements, setMeasurements, updateDuration, duration } = useChartStore(); +// const LineGrapInput = (props: Props) => { +// const [dropDowndata, setDropDownData] = useState({}) +// const [selections, setSelections] = useState>({}) +// const [selectedOption, setSelectedOption] = useState('1h') +// const { measurements, setMeasurements, updateDuration, duration } = useChartStore(); +// const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; - const handleSelectDuration = (option: string) => { - updateDuration(option); // Normalize for key matching - }; +// const handleSelectDuration = (option: string) => { +// updateDuration(option); // Normalize for key matching +// }; - useEffect(() => { - const fetchZoneData = async () => { - try { - const response = await axios.get('http://192.168.0.192:5010/getinput'); - if (response.status === 200) { - console.log('dropdown data:', response.data); - setDropDownData(response.data) - } else { - console.log('Unexpected response:', response); - } - } catch (error) { - console.error('There was an error!', error); - } - }; - fetchZoneData(); - }, []); +// useEffect(() => { +// const fetchZoneData = async () => { +// try { +// const response = await axios.get(`http://${iotApiUrl}/getinput`); +// if (response.status === 200) { +// console.log('dropdown data:', response.data); +// setDropDownData(response.data) +// } else { +// console.log('Unexpected response:', response); +// } +// } catch (error) { +// console.error('There was an error!', error); +// } +// }; +// fetchZoneData(); +// }, []); - useEffect(() => { - console.log(selections); - }, [selections]) +// useEffect(() => { +// console.log(selections); +// }, [selections]) - const handleSelect = (inputKey: string, selectedData: { name: string, fields: string } | null) => { - setSelections(prev => { - if (selectedData === null) { - const newSelections = { ...prev }; - delete newSelections[inputKey]; - return newSelections; - } else { - return { - ...prev, - [inputKey]: selectedData - }; - } - }); - }; +// const handleSelect = (inputKey: string, selectedData: { name: string, fields: string } | null) => { +// setSelections(prev => { +// if (selectedData === null) { +// const newSelections = { ...prev }; +// delete newSelections[inputKey]; +// return newSelections; +// } else { +// return { +// ...prev, +// [inputKey]: selectedData +// }; +// } +// }); +// }; - interface Measurement { - name: string; - fields: string; - } +// interface Measurement { +// name: string; +// fields: string; +// } - interface InputData { - [key: string]: Measurement; - } +// interface InputData { +// [key: string]: Measurement; +// } - const extractMeasurements = (input: InputData): Measurement[] => { - return Object.values(input); - }; +// const extractMeasurements = (input: InputData): Measurement[] => { +// return Object.values(input); +// }; - useEffect(() => { - const measurementsData = extractMeasurements(selections); - setMeasurements(measurementsData); - }, [selections]); +// useEffect(() => { +// const measurementsData = extractMeasurements(selections); +// setMeasurements(measurementsData); +// }, [selections]); - return ( - <> -
- {[...Array(6)].map((_, index) => { - const inputKey = `input${index + 1}`; - return ( -
-
Input {index + 1}
-
- handleSelect(inputKey, selectedData)} - onUnselect={() => handleSelect(inputKey, null)} - selectedValue={selections[inputKey]} - /> -
- -
-
-
- ); - })} -
-
-
-
duration
-
- -
-
-
- - ) -} +// return ( +// <> +//
+// {[...Array(6)].map((_, index) => { +// const inputKey = `input${index + 1}`; +// return ( +//
+//
Input {index + 1}
+//
+// handleSelect(inputKey, selectedData)} +// onUnselect={() => handleSelect(inputKey, null)} +// selectedValue={selections[inputKey]} +// /> +//
+// +//
+//
+//
+// ); +// })} +//
+//
+//
+//
duration
+//
+// +//
+//
+//
+// +// ) +// } -export default LineGrapInput \ No newline at end of file +// export default LineGrapInput + + + +import React, { useEffect, useState } from "react"; +import MultiLevelDropdown from "../../../../ui/inputs/MultiLevelDropDown"; +import { AddIcon } from "../../../../icons/ExportCommonIcons"; +import RegularDropDown from "../../../../ui/inputs/RegularDropDown"; +import useChartStore from "../../../../../store/useChartStore"; +import axios from "axios"; + +type Props = {}; + +const LineGrapInput = (props: Props) => { + const { measurements, setMeasurements, updateDuration, duration } = useChartStore(); + + const [dropDowndata, setDropDownData] = useState({}); + const [selections, setSelections] = useState>(measurements); + const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; + + useEffect(() => { + const fetchZoneData = async () => { + try { + const response = await axios.get(`http://${iotApiUrl}/getinput`); + if (response.status === 200) { + console.log("dropdown data:", response.data); + setDropDownData(response.data); + } else { + console.log("Unexpected response:", response); + } + } catch (error) { + console.error("There was an error!", error); + } + }; + fetchZoneData(); + }, []); + + // Sync Zustand state when component mounts + useEffect(() => { + setSelections(measurements); + }, [measurements]); + + const handleSelect = (inputKey: string, selectedData: { name: string; fields: string } | null) => { + setSelections((prev) => { + const newSelections = { ...prev }; + if (selectedData === null) { + delete newSelections[inputKey]; + } else { + newSelections[inputKey] = selectedData; + } + setMeasurements(newSelections); // Update Zustand store + return newSelections; + }); + }; + + const handleSelectDuration = (option: string) => { + updateDuration(option); + }; + + return ( + <> +
+ {[...Array(6)].map((_, index) => { + const inputKey = `input${index + 1}`; + return ( +
+
Input {index + 1}
+
+ handleSelect(inputKey, selectedData)} + onUnselect={() => handleSelect(inputKey, null)} + selectedValue={selections[inputKey]} // Load from Zustand + /> +
+ +
+
+
+ ); + })} +
+
+
+
Duration
+
+ +
+
+
+ + ); +}; + +export default LineGrapInput; diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/PieChartInput.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/PieChartInput.tsx index 4561f7e..3087471 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/PieChartInput.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/PieChartInput.tsx @@ -8,11 +8,12 @@ type Props = {} const PieChartInput = (props: Props) => { const [dropDowndata, setDropDownData] = useState({}) const [selections, setSelections] = useState>({}) + const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; useEffect(() => { const fetchZoneData = async () => { try { - const response = await axios.get('http://192.168.0.192:5010/getinput'); + const response = await axios.get(`http://${iotApiUrl}/getinput`); if (response.status === 200) { console.log('dropdown data:', response.data); setDropDownData(response.data) diff --git a/app/src/components/ui/componets/DraggableWidget.tsx b/app/src/components/ui/componets/DraggableWidget.tsx index 339e7a6..86afe73 100644 --- a/app/src/components/ui/componets/DraggableWidget.tsx +++ b/app/src/components/ui/componets/DraggableWidget.tsx @@ -237,14 +237,14 @@ export const DraggableWidget = ({ title={widget.title} fontSize={widget.fontSize} fontWeight={widget.fontWeight} - data={{ - measurements: [ - { name: "testDevice", fields: "powerConsumption" }, - { name: "furnace", fields: "powerConsumption" }, - ], - interval: 1000, - duration: "1h", - }} + // data={{ + // measurements: [ + // { name: "testDevice", fields: "powerConsumption" }, + // { name: "furnace", fields: "powerConsumption" }, + // ], + // interval: 1000, + // duration: "1h", + // }} /> )} {widget.type === "bar" && ( @@ -253,14 +253,14 @@ export const DraggableWidget = ({ title={widget.title} fontSize={widget.fontSize} fontWeight={widget.fontWeight} - data={{ - measurements: [ - { name: "testDevice", fields: "powerConsumption" }, - { name: "furnace", fields: "powerConsumption" }, - ], - interval: 1000, - duration: "1h", - }} + // data={{ + // measurements: [ + // { name: "testDevice", fields: "powerConsumption" }, + // { name: "furnace", fields: "powerConsumption" }, + // ], + // interval: 1000, + // duration: "1h", + // }} /> )} {widget.type === "pie" && ( @@ -269,14 +269,14 @@ export const DraggableWidget = ({ title={widget.title} fontSize={widget.fontSize} fontWeight={widget.fontWeight} - data={{ - measurements: [ - { name: "testDevice", fields: "powerConsumption" }, - { name: "furnace", fields: "powerConsumption" }, - ], - interval: 1000, - duration: "1h", - }} + // data={{ + // measurements: [ + // { name: "testDevice", fields: "powerConsumption" }, + // { name: "furnace", fields: "powerConsumption" }, + // ], + // interval: 1000, + // duration: "1h", + // }} /> )} {widget.type === "doughnut" && ( diff --git a/app/src/components/ui/realTimeVis/charts/BarGraphComponent.tsx b/app/src/components/ui/realTimeVis/charts/BarGraphComponent.tsx index da656f2..3b644ac 100644 --- a/app/src/components/ui/realTimeVis/charts/BarGraphComponent.tsx +++ b/app/src/components/ui/realTimeVis/charts/BarGraphComponent.tsx @@ -1,6 +1,195 @@ -import { useMemo } from "react"; +// import React, { useEffect, useRef, useMemo, useState } from "react"; +// import { Chart } from "chart.js/auto"; +// import { useThemeStore } from "../../../../store/useThemeStore"; +// import io from "socket.io-client"; +// import { Bar } from 'react-chartjs-2'; +// import useChartStore from "../../../../store/useChartStore"; +// // WebSocket Connection +// // const socket = io("http://localhost:5000"); // Adjust to your backend URL + +// interface ChartComponentProps { +// type: any; +// title: string; +// fontFamily?: string; +// fontSize?: string; +// fontWeight?: "Light" | "Regular" | "Bold"; +// data: any; +// } + +// const LineGraphComponent = ({ +// type, +// title, +// fontFamily, +// fontSize, +// fontWeight = "Regular", +// data, +// }: ChartComponentProps) => { +// const canvasRef = useRef(null); +// const { themeColor } = useThemeStore(); +// const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({ +// labels: [], +// datasets: [], +// }); + +// const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; + +// const defaultData = { +// labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], +// datasets: [ +// { +// label: "Dataset", +// data: [12, 19, 3, 5, 2, 3], +// backgroundColor: ["#6f42c1"], +// borderColor: "#ffffff", +// borderWidth: 2, +// }, +// ], +// }; + +// // Memoize Theme Colors to Prevent Unnecessary Recalculations +// const buttonActionColor = useMemo( +// () => themeColor[0] || "#5c87df", +// [themeColor] +// ); +// const buttonAbortColor = useMemo( +// () => themeColor[1] || "#ffffff", +// [themeColor] +// ); + +// // Memoize Font Weight Mapping +// const chartFontWeightMap = useMemo( +// () => ({ +// Light: "lighter" as const, +// Regular: "normal" as const, +// Bold: "bold" as const, +// }), +// [] +// ); + +// // Parse and Memoize Font Size +// const fontSizeValue = useMemo( +// () => (fontSize ? parseInt(fontSize) : 12), +// [fontSize] +// ); + +// // Determine and Memoize Font Weight +// const fontWeightValue = useMemo( +// () => chartFontWeightMap[fontWeight], +// [fontWeight, chartFontWeightMap] +// ); + +// // Memoize Chart Font Style +// const chartFontStyle = useMemo( +// () => ({ +// family: fontFamily || "Arial", +// size: fontSizeValue, +// weight: fontWeightValue, +// }), +// [fontFamily, fontSizeValue, fontWeightValue] +// ); + +// // Memoize Chart Data +// // const data = useMemo(() => propsData, [propsData]); + +// // Memoize Chart Options +// const options = useMemo( +// () => ({ +// responsive: true, +// maintainAspectRatio: false, +// plugins: { +// title: { +// display: true, +// text: title, +// font: chartFontStyle, +// }, +// legend: { +// display: false, +// }, +// }, +// scales: { +// x: { +// ticks: { +// display: true, // This hides the x-axis labels +// }, +// }, +// }, +// }), +// [title, chartFontStyle] +// ); + +// const { measurements, setMeasurements, updateDuration, duration } = useChartStore(); + +// useEffect(() => { + +// const socket = io(`http://${iotApiUrl}`); + +// if ( measurements.length > 0 ) { +// var inputes = { +// measurements: measurements, +// duration: duration, +// interval: 1000, +// } + +// // Start stream +// const startStream = () => { +// socket.emit("lineInput", inputes); +// } + +// socket.on('connect', startStream); + +// socket.on("lineOutput", (response) => { +// const responceData = response.data; +// console.log("Received data:", responceData); + +// // Extract timestamps and values +// const labels = responceData.time; +// const datasets = measurements.map((measurement: any) => { +// const key = `${measurement.name}.${measurement.fields}`; +// return { +// label: key, +// data: responceData[key]?.values ?? [], // Ensure it exists +// backgroundColor: "#6f42c1", +// borderColor: "#ffffff", +// }; +// }); + +// setChartData({ labels, datasets }); +// }); +// } + +// return () => { +// socket.off("lineOutput"); +// socket.emit("stop_stream"); // Stop streaming when component unmounts +// }; +// }, [measurements, duration]); + +// // useEffect(() => { +// // if (!canvasRef.current) return; +// // const ctx = canvasRef.current.getContext("2d"); +// // if (!ctx) return; + +// // const chart = new Chart(ctx, { +// // type, +// // data: chartData, +// // options: options, +// // }); + +// // return () => chart.destroy(); +// // }, [chartData, type, title]); + +// return 0 ? chartData : defaultData} options={options} />; +// }; + +// export default LineGraphComponent; + + + +import React, { useEffect, useMemo, useState } from "react"; import { Bar } from "react-chartjs-2"; +import io from "socket.io-client"; +import { useThemeStore } from "../../../../store/useThemeStore"; +import useChartStore from "../../../../store/useChartStore"; interface ChartComponentProps { type: any; @@ -8,16 +197,42 @@ interface ChartComponentProps { fontFamily?: string; fontSize?: string; fontWeight?: "Light" | "Regular" | "Bold"; - data: any; } -const LineGraphComponent = ({ +const BarGraphComponent = ({ + type, title, fontFamily, fontSize, fontWeight = "Regular", }: ChartComponentProps) => { - // Memoize Font Weight Mapping + const { themeColor } = useThemeStore(); + const { measurements, duration } = useChartStore(); // Zustand Store + const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({ + labels: [], + datasets: [], + }); + + const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; + + const defaultData = { + labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], + datasets: [ + { + label: "Dataset", + data: [12, 19, 3, 5, 2, 3], + backgroundColor: ["#6f42c1"], + borderColor: "#b392f0", + borderWidth: 1, + }, + ], + }; + + // Memoize Theme Colors + const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]); + const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]); + + // Memoize Font Styling const chartFontWeightMap = useMemo( () => ({ Light: "lighter" as const, @@ -27,19 +242,9 @@ const LineGraphComponent = ({ [] ); - // Parse and Memoize Font Size - const fontSizeValue = useMemo( - () => (fontSize ? parseInt(fontSize) : 12), - [fontSize] - ); + const fontSizeValue = useMemo(() => (fontSize ? parseInt(fontSize) : 12), [fontSize]); + const fontWeightValue = useMemo(() => chartFontWeightMap[fontWeight], [fontWeight, chartFontWeightMap]); - // Determine and Memoize Font Weight - const fontWeightValue = useMemo( - () => chartFontWeightMap[fontWeight], - [fontWeight, chartFontWeightMap] - ); - - // Memoize Chart Font Style const chartFontStyle = useMemo( () => ({ family: fontFamily || "Arial", @@ -49,6 +254,7 @@ const LineGraphComponent = ({ [fontFamily, fontSizeValue, fontWeightValue] ); + // Memoized Chart Options const options = useMemo( () => ({ responsive: true, @@ -66,7 +272,7 @@ const LineGraphComponent = ({ scales: { x: { ticks: { - display: false, // This hides the x-axis labels + display: true, }, }, }, @@ -74,21 +280,53 @@ const LineGraphComponent = ({ [title, chartFontStyle] ); - const chartData = { - labels: ["January", "February", "March", "April", "May", "June", "July"], - datasets: [ - { - label: "My First Dataset", - data: [65, 59, 80, 81, 56, 55, 40], - backgroundColor: "#6f42c1", - borderColor: "#ffffff", - borderWidth: 2, - fill: false, - }, - ], - }; + useEffect(() => { + if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return; - return ; + const socket = io(`http://${iotApiUrl}`); + + const inputData = { + measurements, + duration, + interval: 1000, + }; + + const startStream = () => { + socket.emit("lineInput", inputData); + }; + + socket.on("connect", startStream); + + socket.on("lineOutput", (response) => { + const responseData = response.data; + console.log("Received data:", responseData); + + // Extract timestamps and values + const labels = responseData.time; + const datasets = Object.keys(measurements).map((key) => { + const measurement = measurements[key]; + const datasetKey = `${measurement.name}.${measurement.fields}`; + return { + label: datasetKey, + data: responseData[datasetKey]?.values ?? [], + backgroundColor: "#6f42c1", + borderColor: "#b392f0", + borderWidth: 1, + }; + }); + + setChartData({ labels, datasets }); + }); + + return () => { + socket.off("lineOutput"); + socket.emit("stop_stream"); // Stop streaming when component unmounts + socket.disconnect(); + }; + }, [measurements, duration, iotApiUrl]); + + return 0 ? chartData : defaultData} options={options} />; }; -export default LineGraphComponent; +export default BarGraphComponent; + diff --git a/app/src/components/ui/realTimeVis/charts/LineGraphComponent.tsx b/app/src/components/ui/realTimeVis/charts/LineGraphComponent.tsx index cc40187..fcc5aeb 100644 --- a/app/src/components/ui/realTimeVis/charts/LineGraphComponent.tsx +++ b/app/src/components/ui/realTimeVis/charts/LineGraphComponent.tsx @@ -1,115 +1,15 @@ -// import { useMemo } from "react"; -// import { Line } from "react-chartjs-2"; - -// interface ChartComponentProps { -// type: any; -// title: string; -// fontFamily?: string; -// fontSize?: string; -// fontWeight?: "Light" | "Regular" | "Bold"; -// data: any; -// } - -// const LineGraphComponent = ({ -// title, -// fontFamily, -// fontSize, -// fontWeight = "Regular", -// }: ChartComponentProps) => { -// // Memoize Font Weight Mapping -// const chartFontWeightMap = useMemo( -// () => ({ -// Light: "lighter" as const, -// Regular: "normal" as const, -// Bold: "bold" as const, -// }), -// [] -// ); - -// // Parse and Memoize Font Size -// const fontSizeValue = useMemo( -// () => (fontSize ? parseInt(fontSize) : 12), -// [fontSize] -// ); - -// // Determine and Memoize Font Weight -// const fontWeightValue = useMemo( -// () => chartFontWeightMap[fontWeight], -// [fontWeight, chartFontWeightMap] -// ); - -// // Memoize Chart Font Style -// const chartFontStyle = useMemo( -// () => ({ -// family: fontFamily || "Arial", -// size: fontSizeValue, -// weight: fontWeightValue, -// }), -// [fontFamily, fontSizeValue, fontWeightValue] -// ); - -// const options = useMemo( -// () => ({ -// responsive: true, -// maintainAspectRatio: false, -// plugins: { -// title: { -// display: true, -// text: title, -// font: chartFontStyle, -// }, -// legend: { -// display: false, -// }, -// }, -// scales: { -// x: { -// ticks: { -// display: true, // This hides the x-axis labels -// }, -// }, -// }, -// }), -// [title, chartFontStyle] -// ); - -// const chartData = { -// labels: ["January", "February", "March", "April", "May", "June", "July"], -// datasets: [ -// { -// label: "My First Dataset", -// data: [65, 59, 80, 81, 56, 55, 40], -// backgroundColor: "#6f42c1", // Updated to #6f42c1 (Purple) -// borderColor: "#ffffff", // Keeping border color white -// borderWidth: 2, -// fill: false, -// }, -// ], -// }; - -// return ; -// }; - -// export default LineGraphComponent; - - -import React, { useEffect, useRef, useMemo, useState } from "react"; -import { Chart } from "chart.js/auto"; -import { useThemeStore } from "../../../../store/useThemeStore"; +import React, { useEffect, useMemo, useState } from "react"; +import { Line } from "react-chartjs-2"; import io from "socket.io-client"; -import { Line } from 'react-chartjs-2'; +import { useThemeStore } from "../../../../store/useThemeStore"; import useChartStore from "../../../../store/useChartStore"; -// WebSocket Connection -// const socket = io("http://localhost:5000"); // Adjust to your backend URL - interface ChartComponentProps { type: any; title: string; fontFamily?: string; fontSize?: string; fontWeight?: "Light" | "Regular" | "Bold"; - data: any; } const LineGraphComponent = ({ @@ -118,60 +18,55 @@ const LineGraphComponent = ({ fontFamily, fontSize, fontWeight = "Regular", - data, }: ChartComponentProps) => { - const canvasRef = useRef(null); const { themeColor } = useThemeStore(); + const { measurements, duration } = useChartStore(); // Zustand Store const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({ labels: [], datasets: [], }); - // Memoize Theme Colors to Prevent Unnecessary Recalculations - const buttonActionColor = useMemo( - () => themeColor[0] || "#5c87df", - [themeColor] - ); - const buttonAbortColor = useMemo( - () => themeColor[1] || "#ffffff", - [themeColor] - ); - - // Memoize Font Weight Mapping - const chartFontWeightMap = useMemo( - () => ({ - Light: "lighter" as const, - Regular: "normal" as const, - Bold: "bold" as const, - }), - [] - ); - - // Parse and Memoize Font Size - const fontSizeValue = useMemo( - () => (fontSize ? parseInt(fontSize) : 12), - [fontSize] - ); - - // Determine and Memoize Font Weight - const fontWeightValue = useMemo( - () => chartFontWeightMap[fontWeight], - [fontWeight, chartFontWeightMap] - ); - - // Memoize Chart Font Style - const chartFontStyle = useMemo( - () => ({ - family: fontFamily || "Arial", - size: fontSizeValue, - weight: fontWeightValue, - }), - [fontFamily, fontSizeValue, fontWeightValue] - ); - - // Memoize Chart Data - // const data = useMemo(() => propsData, [propsData]); - + const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; + + const defaultData = { + labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], + datasets: [ + { + label: "Dataset", + data: [12, 19, 3, 5, 2, 3], + backgroundColor: ["#6f42c1"], + borderColor: "#b392f0", + borderWidth: 1, + }, + ], + }; + + // Memoize Theme Colors + const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]); + const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]); + + // Memoize Font Styling + const chartFontWeightMap = useMemo( + () => ({ + Light: "lighter" as const, + Regular: "normal" as const, + Bold: "bold" as const, + }), + [] + ); + + const fontSizeValue = useMemo(() => (fontSize ? parseInt(fontSize) : 12), [fontSize]); + const fontWeightValue = useMemo(() => chartFontWeightMap[fontWeight], [fontWeight, chartFontWeightMap]); + + const chartFontStyle = useMemo( + () => ({ + family: fontFamily || "Arial", + size: fontSizeValue, + weight: fontWeightValue, + }), + [fontFamily, fontSizeValue, fontWeightValue] + ); + // Memoize Chart Options const options = useMemo( () => ({ @@ -198,67 +93,54 @@ const LineGraphComponent = ({ [title, chartFontStyle] ); - const { measurements, setMeasurements, updateDuration, duration } = useChartStore(); + useEffect(() => {console.log(measurements); + },[measurements]) useEffect(() => { + if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return; - const socket = io("http://192.168.0.192:5010"); + const socket = io(`http://${iotApiUrl}`); - if ( measurements.length > 0 ) { - var inputes = { - measurements: measurements, - duration: duration, - interval: 1000, - } + const inputData = { + measurements, + duration, + interval: 1000, + }; - // Start stream const startStream = () => { - socket.emit("lineInput", inputes); - } + socket.emit("lineInput", inputData); + }; - socket.on('connect', startStream); + socket.on("connect", startStream); socket.on("lineOutput", (response) => { - const responceData = response.data; - console.log("Received data:", responceData); + const responseData = response.data; // Extract timestamps and values - const labels = responceData.time; - const datasets = measurements.map((measurement: any) => { - const key = `${measurement.name}.${measurement.fields}`; + const labels = responseData.time; + const datasets = Object.keys(measurements).map((key) => { + const measurement = measurements[key]; + const datasetKey = `${measurement.name}.${measurement.fields}`; return { - label: key, - data: responceData[key]?.values ?? [], // Ensure it exists - backgroundColor: themeColor[0] || "#5c87df", - borderColor: themeColor[1] || "#ffffff", + label: datasetKey, + data: responseData[datasetKey]?.values ?? [], + backgroundColor: "#6f42c1", + borderColor: "#b392f0", + borderWidth: 1, }; }); setChartData({ labels, datasets }); }); - } return () => { socket.off("lineOutput"); socket.emit("stop_stream"); // Stop streaming when component unmounts + socket.disconnect(); }; - }, [measurements, duration]); + }, [measurements, duration, iotApiUrl]); - // useEffect(() => { - // if (!canvasRef.current) return; - // const ctx = canvasRef.current.getContext("2d"); - // if (!ctx) return; - - // const chart = new Chart(ctx, { - // type, - // data: chartData, - // options: options, - // }); - - // return () => chart.destroy(); - // }, [chartData, type, title]); - - return ; + return 0 ? chartData : defaultData} options={options} />; }; -export default LineGraphComponent; \ No newline at end of file +export default LineGraphComponent; diff --git a/app/src/components/ui/realTimeVis/charts/PieGraphComponent.tsx b/app/src/components/ui/realTimeVis/charts/PieGraphComponent.tsx index 0066ec3..ca6b728 100644 --- a/app/src/components/ui/realTimeVis/charts/PieGraphComponent.tsx +++ b/app/src/components/ui/realTimeVis/charts/PieGraphComponent.tsx @@ -1,5 +1,195 @@ -import { useMemo } from "react"; +// import React, { useEffect, useRef, useMemo, useState } from "react"; +// import { Chart } from "chart.js/auto"; +// import { useThemeStore } from "../../../../store/useThemeStore"; +// import io from "socket.io-client"; +// import { Pie } from 'react-chartjs-2'; +// import useChartStore from "../../../../store/useChartStore"; + +// // WebSocket Connection +// // const socket = io("http://localhost:5000"); // Adjust to your backend URL + +// interface ChartComponentProps { +// type: any; +// title: string; +// fontFamily?: string; +// fontSize?: string; +// fontWeight?: "Light" | "Regular" | "Bold"; +// data: any; +// } + +// const PieChartComponent = ({ +// type, +// title, +// fontFamily, +// fontSize, +// fontWeight = "Regular", +// data, +// }: ChartComponentProps) => { +// const canvasRef = useRef(null); +// const { themeColor } = useThemeStore(); +// const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({ +// labels: [], +// datasets: [], +// }); + +// const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; + +// const defaultData = { +// labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], +// datasets: [ +// { +// label: "Dataset", +// data: [12, 19, 3, 5, 2, 3], +// backgroundColor: ["#6f42c1"], +// borderColor: "#ffffff", +// borderWidth: 2, +// }, +// ], +// }; + +// // Memoize Theme Colors to Prevent Unnecessary Recalculations +// const buttonActionColor = useMemo( +// () => themeColor[0] || "#6f42c1", +// [themeColor] +// ); +// const buttonAbortColor = useMemo( +// () => themeColor[1] || "#ffffff", +// [themeColor] +// ); + +// // Memoize Font Weight Mapping +// const chartFontWeightMap = useMemo( +// () => ({ +// Light: "lighter" as const, +// Regular: "normal" as const, +// Bold: "bold" as const, +// }), +// [] +// ); + +// // Parse and Memoize Font Size +// const fontSizeValue = useMemo( +// () => (fontSize ? parseInt(fontSize) : 12), +// [fontSize] +// ); + +// // Determine and Memoize Font Weight +// const fontWeightValue = useMemo( +// () => chartFontWeightMap[fontWeight], +// [fontWeight, chartFontWeightMap] +// ); + +// // Memoize Chart Font Style +// const chartFontStyle = useMemo( +// () => ({ +// family: fontFamily || "Arial", +// size: fontSizeValue, +// weight: fontWeightValue, +// }), +// [fontFamily, fontSizeValue, fontWeightValue] +// ); + +// // Memoize Chart Data +// // const data = useMemo(() => propsData, [propsData]); + +// // Memoize Chart Options +// const options = useMemo( +// () => ({ +// responsive: true, +// maintainAspectRatio: false, +// plugins: { +// title: { +// display: true, +// text: title, +// font: chartFontStyle, +// }, +// legend: { +// display: false, +// }, +// }, +// scales: { +// // x: { +// // ticks: { +// // display: true, // This hides the x-axis labels +// // }, +// // }, +// }, +// }), +// [title, chartFontStyle] +// ); + +// const { measurements, setMeasurements, updateDuration, duration } = useChartStore(); + +// useEffect(() => { + +// const socket = io(`http://${iotApiUrl}`); + +// if ( measurements.length > 0 ) { +// var inputes = { +// measurements: measurements, +// duration: duration, +// interval: 1000, +// } + +// // Start stream +// const startStream = () => { +// socket.emit("lineInput", inputes); +// } + +// socket.on('connect', startStream); + +// socket.on("lineOutput", (response) => { +// const responceData = response.data; +// console.log("Received data:", responceData); + +// // Extract timestamps and values +// const labels = responceData.time; +// const datasets = measurements.map((measurement: any) => { +// const key = `${measurement.name}.${measurement.fields}`; +// return { +// label: key, +// data: responceData[key]?.values ?? [], // Ensure it exists +// backgroundColor: "#6f42c1", +// borderColor: "#ffffff", +// }; +// }); + +// setChartData({ labels, datasets }); +// }); +// } + +// return () => { +// socket.off("lineOutput"); +// socket.emit("stop_stream"); // Stop streaming when component unmounts +// }; +// }, [measurements, duration]); + +// // useEffect(() => { +// // if (!canvasRef.current) return; +// // const ctx = canvasRef.current.getContext("2d"); +// // if (!ctx) return; + +// // const chart = new Chart(ctx, { +// // type, +// // data: chartData, +// // options: options, +// // }); + +// // return () => chart.destroy(); +// // }, [chartData, type, title]); + +// return 0 ? chartData : defaultData} options={options} />; +// }; + +// export default PieChartComponent; + + + +import React, { useEffect, useMemo, useState } from "react"; import { Pie } from "react-chartjs-2"; +import io from "socket.io-client"; +import { useThemeStore } from "../../../../store/useThemeStore"; +import useChartStore from "../../../../store/useChartStore"; interface ChartComponentProps { type: any; @@ -7,16 +197,42 @@ interface ChartComponentProps { fontFamily?: string; fontSize?: string; fontWeight?: "Light" | "Regular" | "Bold"; - data: any; } const PieChartComponent = ({ + type, title, fontFamily, fontSize, fontWeight = "Regular", }: ChartComponentProps) => { - // Memoize Font Weight Mapping + const { themeColor } = useThemeStore(); + const { measurements, duration } = useChartStore(); // Zustand Store + const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({ + labels: [], + datasets: [], + }); + + const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; + + const defaultData = { + labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], + datasets: [ + { + label: "Dataset", + data: [12, 19, 3, 5, 2, 3], + backgroundColor: ["#6f42c1"], + borderColor: "#b392f0", + borderWidth: 1, + }, + ], + }; + + // Memoize Theme Colors + const buttonActionColor = useMemo(() => themeColor[0] || "#5c87df", [themeColor]); + const buttonAbortColor = useMemo(() => themeColor[1] || "#ffffff", [themeColor]); + + // Memoize Font Styling const chartFontWeightMap = useMemo( () => ({ Light: "lighter" as const, @@ -26,19 +242,9 @@ const PieChartComponent = ({ [] ); - // Parse and Memoize Font Size - const fontSizeValue = useMemo( - () => (fontSize ? parseInt(fontSize) : 12), - [fontSize] - ); + const fontSizeValue = useMemo(() => (fontSize ? parseInt(fontSize) : 12), [fontSize]); + const fontWeightValue = useMemo(() => chartFontWeightMap[fontWeight], [fontWeight, chartFontWeightMap]); - // Determine and Memoize Font Weight - const fontWeightValue = useMemo( - () => chartFontWeightMap[fontWeight], - [fontWeight, chartFontWeightMap] - ); - - // Memoize Chart Font Style const chartFontStyle = useMemo( () => ({ family: fontFamily || "Arial", @@ -48,12 +254,7 @@ const PieChartComponent = ({ [fontFamily, fontSizeValue, fontWeightValue] ); - // Access the CSS variable for the primary accent color - const accentColor = getComputedStyle(document.documentElement) - .getPropertyValue("--accent-color") - .trim(); - - console.log("accentColor: ", accentColor); + // Memoized Chart Options const options = useMemo( () => ({ responsive: true, @@ -68,24 +269,64 @@ const PieChartComponent = ({ display: false, }, }, + scales: { + // x: { + // ticks: { + // display: true, + // }, + // }, + }, }), [title, chartFontStyle] ); - const chartData = { - labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], - datasets: [ - { - label: "Dataset", - data: [12, 19, 3, 5, 2, 3], - backgroundColor: ["#6f42c1"], - borderColor: "#ffffff", - borderWidth: 2, - }, - ], - }; + useEffect(() => { + if (!iotApiUrl || !measurements || Object.keys(measurements).length === 0) return; - return ; + const socket = io(`http://${iotApiUrl}`); + + const inputData = { + measurements, + duration, + interval: 1000, + }; + + const startStream = () => { + socket.emit("lineInput", inputData); + }; + + socket.on("connect", startStream); + + socket.on("lineOutput", (response) => { + const responseData = response.data; + console.log("Received data:", responseData); + + // Extract timestamps and values + const labels = responseData.time; + const datasets = Object.keys(measurements).map((key) => { + const measurement = measurements[key]; + const datasetKey = `${measurement.name}.${measurement.fields}`; + return { + label: datasetKey, + data: responseData[datasetKey]?.values ?? [], + backgroundColor: "#6f42c1", + borderColor: "#b392f0", + borderWidth: 1, + }; + }); + + setChartData({ labels, datasets }); + }); + + return () => { + socket.off("lineOutput"); + socket.emit("stop_stream"); // Stop streaming when component unmounts + socket.disconnect(); + }; + }, [measurements, duration, iotApiUrl]); + + return 0 ? chartData : defaultData} options={options} />; }; export default PieChartComponent; + diff --git a/app/src/services/factoryBuilder/mqtt/mqttEvents.ts b/app/src/services/factoryBuilder/mqtt/mqttEvents.ts index cd79484..0795c4d 100644 --- a/app/src/services/factoryBuilder/mqtt/mqttEvents.ts +++ b/app/src/services/factoryBuilder/mqtt/mqttEvents.ts @@ -6,7 +6,7 @@ const MqttEvents = () => { const { setTouch, setTemperature, setHumidity } = useDrieUIValue(); useEffect(() => { - const client = mqtt.connect("ws://192.168.0.192:1884", { + const client = mqtt.connect("ws://192.168.0.193:1884", { username: "gabby", password: "gabby" }); diff --git a/app/src/store/useChartStore.ts b/app/src/store/useChartStore.ts index 88d0c9c..4d61952 100644 --- a/app/src/store/useChartStore.ts +++ b/app/src/store/useChartStore.ts @@ -6,15 +6,15 @@ interface Measurement { } interface MeasurementStore { - measurements: Measurement[]; + measurements: Record; // Change array to Record interval: number; duration: string; - setMeasurements: (newMeasurements: Measurement[]) => void; + setMeasurements: (newMeasurements: Record) => void; updateDuration: (newDuration: string) => void; } const useChartStore = create((set) => ({ - measurements: [], + measurements: {}, // Initialize as an empty object interval: 1000, duration: "1h", @@ -26,3 +26,4 @@ const useChartStore = create((set) => ({ })); export default useChartStore; + From f46f29b88cf814ed166f32a8b285921b389eff71 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Fri, 28 Mar 2025 19:10:49 +0530 Subject: [PATCH 3/4] Add MQTT URL to environment variables and refactor simulation components --- app/.env | 3 + .../layout/sidebarRight/SideBarRight.tsx | 16 +- .../mechanics/ConveyorMechanics.tsx | 586 +++++++++++++++ .../mechanics/MachineMechanics.tsx | 533 ------------- .../mechanics/VehicleMechanics.tsx | 561 ++++++++++++++ .../modules/builder/agv/navMeshDetails.tsx | 12 +- app/src/modules/builder/agv/pathNavigator.tsx | 2 +- .../modules/builder/agv/polygonGenerator.tsx | 76 +- app/src/modules/collaboration/collabCams.tsx | 2 +- app/src/modules/scene/scene.tsx | 4 - .../simulation/behaviour/behaviour.tsx | 58 +- .../modules/simulation/path/pathConnector.tsx | 312 +++++--- .../modules/simulation/path/pathCreation.tsx | 203 +++-- app/src/modules/simulation/simulation.tsx | 2 +- app/src/modules/simulation/simulationUI.tsx | 698 +++++++++--------- app/src/pages/Project.tsx | 1 - .../factoryBuilder/mqtt/mqttEvents.ts | 5 +- app/src/store/store.ts | 29 +- app/src/types/world/worldTypes.d.ts | 32 + 19 files changed, 1971 insertions(+), 1164 deletions(-) create mode 100644 app/src/components/layout/sidebarRight/mechanics/ConveyorMechanics.tsx delete mode 100644 app/src/components/layout/sidebarRight/mechanics/MachineMechanics.tsx create mode 100644 app/src/components/layout/sidebarRight/mechanics/VehicleMechanics.tsx diff --git a/app/.env b/app/.env index db5ccb6..81bd26d 100644 --- a/app/.env +++ b/app/.env @@ -9,3 +9,6 @@ REACT_APP_SERVER_REST_API_BASE_URL=185.100.212.76:5000 # Base URL for the server marketplace API. REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011 + +# Base URL for the server mqtt. +REACT_APP_SERVER_MQTT_URL=185.100.212.76:23457 diff --git a/app/src/components/layout/sidebarRight/SideBarRight.tsx b/app/src/components/layout/sidebarRight/SideBarRight.tsx index 0efe99b..3ba5595 100644 --- a/app/src/components/layout/sidebarRight/SideBarRight.tsx +++ b/app/src/components/layout/sidebarRight/SideBarRight.tsx @@ -10,7 +10,7 @@ import { SimulationIcon, } from "../../icons/SimulationIcons"; import useToggleStore from "../../../store/useUIToggleStore"; -import MachineMechanics from "./mechanics/MachineMechanics"; +import ConveyorMechanics from "./mechanics/ConveyorMechanics"; import Visualization from "./visualization/Visualization"; import Analysis from "./analysis/Analysis"; import Simulations from "./simulation/Simulations"; @@ -18,6 +18,7 @@ import { useSelectedActionSphere } from "../../../store/store"; import GlobalProperties from "./properties/GlobalProperties"; import AsstePropertiies from "./properties/AssetProperties"; import ZoneProperties from "./properties/ZoneProperties"; +import VehicleMechanics from "./mechanics/VehicleMechanics"; const SideBarRight: React.FC = () => { const { activeModule } = useModuleStore(); @@ -98,17 +99,24 @@ const SideBarRight: React.FC = () => { {toggleUI && activeModule === "simulation" && ( <> - {subModule === "mechanics" && selectedActionSphere && ( + {subModule === "mechanics" && selectedActionSphere && selectedActionSphere.path.type === "Conveyor" && (
- + +
+
+ )} + {subModule === "mechanics" && selectedActionSphere && selectedActionSphere.path.type === "Vehicle" && ( +
+
+ {/* */}
)} {subModule === "mechanics" && !selectedActionSphere && (
- {/* */} +
)} diff --git a/app/src/components/layout/sidebarRight/mechanics/ConveyorMechanics.tsx b/app/src/components/layout/sidebarRight/mechanics/ConveyorMechanics.tsx new file mode 100644 index 0000000..a1f8bf3 --- /dev/null +++ b/app/src/components/layout/sidebarRight/mechanics/ConveyorMechanics.tsx @@ -0,0 +1,586 @@ +import React, { useRef, useState, useMemo, useEffect } from "react"; +import { + AddIcon, + InfoIcon, + RemoveIcon, + ResizeHeightIcon, +} from "../../../icons/ExportCommonIcons"; +import RenameInput from "../../../ui/inputs/RenameInput"; +import InputWithDropDown from "../../../ui/inputs/InputWithDropDown"; +import LabledDropdown from "../../../ui/inputs/LabledDropdown"; +import RegularDropDown from "../../../ui/inputs/RegularDropDown"; +import { handleResize } from "../../../../functions/handleResizePannel"; +import EyeDropInput from "../../../ui/inputs/EyeDropInput"; +import { useSelectedActionSphere, useSelectedPath, useSimulationPaths } from "../../../../store/store"; +import * as THREE from 'three'; +import * as Types from '../../../../types/world/worldTypes'; +import InputToggle from "../../../ui/inputs/InputToggle"; + +const ConveyorMechanics: React.FC = () => { + const { selectedActionSphere } = useSelectedActionSphere(); + const { selectedPath, setSelectedPath } = useSelectedPath(); + const { simulationPaths, setSimulationPaths } = useSimulationPaths(); + + const actionsContainerRef = useRef(null); + const triggersContainerRef = useRef(null); + + const selectedPoint = useMemo(() => { + if (!selectedActionSphere) return null; + return simulationPaths + .filter((path): path is Types.ConveyorEventsSchema => path.type === "Conveyor") + .flatMap((path) => path.points) + .find((point) => point.uuid === selectedActionSphere.point.uuid); + }, [selectedActionSphere, simulationPaths]); + + const handleAddAction = () => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => { + if (path.type === "Conveyor") { + return { + ...path, + points: path.points.map((point) => { + if (point.uuid === selectedActionSphere.point.uuid) { + const actionIndex = point.actions.length; + const newAction = { + uuid: THREE.MathUtils.generateUUID(), + name: `Action ${actionIndex + 1}`, + type: 'Inherit', + material: 'Inherit', + delay: 'Inherit', + spawnInterval: 'Inherit', + isUsed: false + }; + + return { ...point, actions: [...point.actions, newAction] }; + } + return point; + }), + }; + } + return path; + }); + + setSimulationPaths(updatedPaths); + }; + + const handleDeleteAction = (uuid: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleActionSelect = (uuid: string, actionType: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid + ? { + ...action, + type: actionType, + material: actionType === 'Spawn' || actionType === 'Swap' ? 'Inherit' : action.material, + delay: actionType === 'Delay' ? 'Inherit' : action.delay, + spawnInterval: actionType === 'Spawn' ? 'Inherit' : action.spawnInterval + } + : action + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + + // Update the selected item to reflect changes + if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { + const updatedAction = updatedPaths + .filter((path): path is Types.ConveyorEventsSchema => path.type === "Conveyor") + .flatMap(path => path.points) + .find(p => p.uuid === selectedActionSphere.point.uuid) + ?.actions.find(a => a.uuid === uuid); + + if (updatedAction) { + setSelectedItem({ + type: "action", + item: updatedAction + }); + } + } + }; + + // Modified handleMaterialSelect to ensure it only applies to relevant action types + const handleMaterialSelect = (uuid: string, material: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid && + (action.type === 'Spawn' || action.type === 'Swap') + ? { ...action, material } + : action + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + + // Update selected item if it's the current action + if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { + setSelectedItem({ + ...selectedItem, + item: { + ...selectedItem.item, + material + } + }); + } + }; + + const handleDelayChange = (uuid: string, delay: number | string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid ? { ...action, delay } : action + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleSpawnIntervalChange = (uuid: string, spawnInterval: number | string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid ? { ...action, spawnInterval } : action + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleSpeedChange = (speed: number) => { + if (!selectedPath) return; + + const updatedPaths = simulationPaths.map((path) => + path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path + ); + + setSimulationPaths(updatedPaths); + setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } }); + }; + + const handleAddTrigger = () => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => { + if (point.uuid === selectedActionSphere.point.uuid) { + const triggerIndex = point.triggers.length; + const newTrigger = { + uuid: THREE.MathUtils.generateUUID(), + name: `Trigger ${triggerIndex + 1}`, + type: '', + isUsed: false + }; + + return { ...point, triggers: [...point.triggers, newTrigger] }; + } + return point; + }), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleDeleteTrigger = (uuid: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleTriggerSelect = (uuid: string, triggerType: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + triggers: point.triggers.map((trigger) => + trigger.uuid === uuid ? { ...trigger, type: triggerType } : trigger + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + // Update the toggle handlers to immediately update the selected item + const handleActionToggle = (uuid: string) => { + if (!selectedActionSphere) return; + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => ({ + ...action, + isUsed: action.uuid === uuid ? !action.isUsed : false, + })), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + + // Immediately update the selected item if it's the one being toggled + if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { + setSelectedItem({ + ...selectedItem, + item: { + ...selectedItem.item, + isUsed: !selectedItem.item.isUsed + } + }); + } + }; + + // Do the same for trigger toggle + const handleTriggerToggle = (uuid: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + triggers: point.triggers.map((trigger) => ({ + ...trigger, + isUsed: trigger.uuid === uuid ? !trigger.isUsed : false, + })), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + + // Immediately update the selected item if it's the one being toggled + if (selectedItem?.type === "trigger" && selectedItem.item.uuid === uuid) { + setSelectedItem({ + ...selectedItem, + item: { + ...selectedItem.item, + isUsed: !selectedItem.item.isUsed + } + }); + } + }; + + const [selectedItem, setSelectedItem] = useState<{ type: "action" | "trigger"; item: any; } | null>(null); + + useEffect(() => { + setSelectedItem(null); // Reset selectedItem when selectedActionSphere changes + }, [selectedActionSphere]); + + return ( +
+
+ {selectedActionSphere?.path?.modelName || "point name not found"} +
+ +
+ {!selectedPath && + <> +
+
+
Actions
+
+ Add +
+
+
+
+ {selectedPoint?.actions.map((action) => ( +
+
setSelectedItem({ type: "action", item: action })} + > + +
+
handleDeleteAction(action.uuid)} + > + +
+
+ ))} +
+
handleResize(e, actionsContainerRef)} + > + +
+
+
+
+
+
Triggers
+
+ Add +
+
+
+
+ {selectedPoint?.triggers.map((trigger) => ( +
+
setSelectedItem({ type: "trigger", item: trigger })} + > + +
+
handleDeleteTrigger(trigger.uuid)} + > + +
+
+ ))} +
+
handleResize(e, triggersContainerRef)} + > + +
+
+
+ + } + +
+ {selectedItem && ( + <> +
{selectedItem.item.name}
+ + {selectedItem.type === "action" && ( + <> + handleActionToggle(selectedItem.item.uuid)} + /> + handleActionSelect(selectedItem.item.uuid, option)} + /> + + {/* Only show material dropdown for Spawn/Swap actions */} + {(selectedItem.item.type === 'Spawn' || selectedItem.item.type === 'Swap') && ( + handleMaterialSelect(selectedItem.item.uuid, option)} + /> + )} + + {/* Only show delay input for Delay actions */} + {selectedItem.item.type === 'Delay' && ( + { + const numValue = parseInt(value); + handleDelayChange( + selectedItem.item.uuid, + !value ? 'Inherit' : numValue + ); + }} + /> + )} + + {/* Only show spawn interval for Spawn actions */} + {selectedItem.item.type === 'Spawn' && ( + { + handleSpawnIntervalChange(selectedItem.item.uuid, (value === "") ? "Inherit" : parseInt(value)); + }} + /> + + )} + + )} + + {selectedItem.type === "trigger" && ( + <> + handleTriggerToggle(selectedItem.item.uuid)} + /> + + handleTriggerSelect(selectedItem.item.uuid, option)} + /> + + )} + + )} + + {selectedPath && !selectedItem && ( +
+ handleSpeedChange(parseFloat(value))} + /> +
+ )} +
+
+ + By selecting points, you can create events and triggers. +
+
+
+ ); +}; + +export default ConveyorMechanics; \ No newline at end of file diff --git a/app/src/components/layout/sidebarRight/mechanics/MachineMechanics.tsx b/app/src/components/layout/sidebarRight/mechanics/MachineMechanics.tsx deleted file mode 100644 index e1ecfb3..0000000 --- a/app/src/components/layout/sidebarRight/mechanics/MachineMechanics.tsx +++ /dev/null @@ -1,533 +0,0 @@ -import React, { useRef, useState, useMemo, useEffect } from "react"; -import { - AddIcon, - InfoIcon, - RemoveIcon, - ResizeHeightIcon, -} from "../../../icons/ExportCommonIcons"; -import RenameInput from "../../../ui/inputs/RenameInput"; -import InputWithDropDown from "../../../ui/inputs/InputWithDropDown"; -import LabledDropdown from "../../../ui/inputs/LabledDropdown"; -import RegularDropDown from "../../../ui/inputs/RegularDropDown"; -import { handleResize } from "../../../../functions/handleResizePannel"; -import EyeDropInput from "../../../ui/inputs/EyeDropInput"; -import { useSelectedActionSphere, useSelectedPath, useSimulationPaths } from "../../../../store/store"; -import * as THREE from 'three'; -import InputToggle from "../../../ui/inputs/InputToggle"; - -const MachineMechanics: React.FC = () => { - const { selectedActionSphere } = useSelectedActionSphere(); - const { selectedPath, setSelectedPath } = useSelectedPath(); - const { simulationPaths, setSimulationPaths } = useSimulationPaths(); - - const actionsContainerRef = useRef(null); - const triggersContainerRef = useRef(null); - - const selectedPoint = useMemo(() => { - if (!selectedActionSphere) return null; - return simulationPaths.flatMap((path) => path.points).find((point) => point.uuid === selectedActionSphere.point.uuid); - }, [selectedActionSphere, simulationPaths]); - - const handleAddAction = () => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => { - if (point.uuid === selectedActionSphere.point.uuid) { - const actionIndex = point.actions.length; - const newAction = { - uuid: THREE.MathUtils.generateUUID(), - name: `Action ${actionIndex + 1}`, - type: 'Inherit', - material: 'Inherit', - delay: 'Inherit', - spawnInterval: 'Inherit', - isUsed: false - }; - - return { ...point, actions: [...point.actions, newAction] }; - } - return point; - }), - })); - - setSimulationPaths(updatedPaths); - }; - - const handleDeleteAction = (uuid: string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) } - : point - ), - })); - - setSimulationPaths(updatedPaths); - }; - - const handleActionSelect = (uuid: string, actionType: string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => - action.uuid === uuid - ? { - ...action, - type: actionType, - // Reset dependent fields when type changes - material: actionType === 'Spawn' || actionType === 'Swap' ? 'Inherit' : action.material, - delay: actionType === 'Delay' ? 'Inherit' : action.delay, - spawnInterval: actionType === 'Spawn' ? 'Inherit' : action.spawnInterval - } - : action - ), - } - : point - ), - })); - - setSimulationPaths(updatedPaths); - - // Update the selected item to reflect changes - if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { - const updatedAction = updatedPaths - .flatMap(path => path.points) - .find(p => p.uuid === selectedActionSphere.point.uuid) - ?.actions.find(a => a.uuid === uuid); - - if (updatedAction) { - setSelectedItem({ - type: "action", - item: updatedAction - }); - } - } - }; - - // Modified handleMaterialSelect to ensure it only applies to relevant action types - const handleMaterialSelect = (uuid: string, material: string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => - action.uuid === uuid && - (action.type === 'Spawn' || action.type === 'Swap') - ? { ...action, material } - : action - ), - } - : point - ), - })); - - setSimulationPaths(updatedPaths); - - // Update selected item if it's the current action - if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { - setSelectedItem({ - ...selectedItem, - item: { - ...selectedItem.item, - material - } - }); - } - }; - - const handleDelayChange = (uuid: string, delay: number | string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => - action.uuid === uuid ? { ...action, delay } : action - ), - } - : point - ), - })); - - setSimulationPaths(updatedPaths); - }; - - const handleSpawnIntervalChange = (uuid: string, spawnInterval: number | string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => - action.uuid === uuid ? { ...action, spawnInterval } : action - ), - } - : point - ), - })); - - setSimulationPaths(updatedPaths); - }; - - const handleSpeedChange = (speed: number) => { - if (!selectedPath) return; - - const updatedPaths = simulationPaths.map((path) => - path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path - ); - - setSimulationPaths(updatedPaths); - setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } }); - }; - - const handleAddTrigger = () => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => { - if (point.uuid === selectedActionSphere.point.uuid) { - const triggerIndex = point.triggers.length; - const newTrigger = { - uuid: THREE.MathUtils.generateUUID(), - name: `Trigger ${triggerIndex + 1}`, - type: '', - isUsed: false - }; - - return { ...point, triggers: [...point.triggers, newTrigger] }; - } - return point; - }), - })); - - setSimulationPaths(updatedPaths); - }; - - const handleDeleteTrigger = (uuid: string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) } - : point - ), - })); - - setSimulationPaths(updatedPaths); - }; - - const handleTriggerSelect = (uuid: string, triggerType: string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - triggers: point.triggers.map((trigger) => - trigger.uuid === uuid ? { ...trigger, type: triggerType } : trigger - ), - } - : point - ), - })); - - setSimulationPaths(updatedPaths); - }; - - // Update the toggle handlers to immediately update the selected item - const handleActionToggle = (uuid: string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => ({ - ...action, - isUsed: action.uuid === uuid ? !action.isUsed : false, - })), - } - : point - ), - })); - - setSimulationPaths(updatedPaths); - - // Immediately update the selected item if it's the one being toggled - if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { - setSelectedItem({ - ...selectedItem, - item: { - ...selectedItem.item, - isUsed: !selectedItem.item.isUsed - } - }); - } - }; - - // Do the same for trigger toggle - const handleTriggerToggle = (uuid: string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - triggers: point.triggers.map((trigger) => ({ - ...trigger, - isUsed: trigger.uuid === uuid ? !trigger.isUsed : false, - })), - } - : point - ), - })); - - setSimulationPaths(updatedPaths); - - // Immediately update the selected item if it's the one being toggled - if (selectedItem?.type === "trigger" && selectedItem.item.uuid === uuid) { - setSelectedItem({ - ...selectedItem, - item: { - ...selectedItem.item, - isUsed: !selectedItem.item.isUsed - } - }); - } - }; - - const [selectedItem, setSelectedItem] = useState<{ type: "action" | "trigger"; item: any; } | null>(null); - - useEffect(() => { - setSelectedItem(null); // Reset selectedItem when selectedActionSphere changes - }, [selectedActionSphere]); - - return ( -
-
- {selectedActionSphere?.path?.modelName || "point name not found"} -
- -
-
-
-
Actions
-
- Add -
-
-
-
- {selectedPoint?.actions.map((action) => ( -
-
setSelectedItem({ type: "action", item: action })} - > - -
-
handleDeleteAction(action.uuid)} - > - -
-
- ))} -
-
handleResize(e, actionsContainerRef)} - > - -
-
-
-
-
-
Triggers
-
- Add -
-
-
-
- {selectedPoint?.triggers.map((trigger) => ( -
-
setSelectedItem({ type: "trigger", item: trigger })} - > - -
-
handleDeleteTrigger(trigger.uuid)} - > - -
-
- ))} -
-
handleResize(e, triggersContainerRef)} - > - -
-
-
-
- {selectedItem && ( - <> -
{selectedItem.item.name}
- - {selectedItem.type === "action" && ( - <> - handleActionToggle(selectedItem.item.uuid)} - /> - handleActionSelect(selectedItem.item.uuid, option)} - /> - - {/* Only show material dropdown for Spawn/Swap actions */} - {(selectedItem.item.type === 'Spawn' || selectedItem.item.type === 'Swap') && ( - handleMaterialSelect(selectedItem.item.uuid, option)} - /> - )} - - {/* Only show delay input for Delay actions */} - {selectedItem.item.type === 'Delay' && ( - { - const numValue = parseInt(value); - handleDelayChange( - selectedItem.item.uuid, - !value ? 'Inherit' : numValue - ); - }} - /> - )} - - {/* Only show spawn interval for Spawn actions */} - {selectedItem.item.type === 'Spawn' && ( - { - handleSpawnIntervalChange(selectedItem.item.uuid, (value === "") ? "Inherit" : parseInt(value)); - }} - /> - - )} - - )} - - {selectedItem.type === "trigger" && ( - <> - handleTriggerToggle(selectedItem.item.uuid)} - /> - - handleTriggerSelect(selectedItem.item.uuid, option)} - /> - - )} - - )} - - {selectedPath && !selectedItem && ( -
- handleSpeedChange(parseFloat(value))} - /> -
- )} -
-
- - By selecting points, you can create events and triggers. -
-
-
- ); -}; - -export default MachineMechanics; \ No newline at end of file diff --git a/app/src/components/layout/sidebarRight/mechanics/VehicleMechanics.tsx b/app/src/components/layout/sidebarRight/mechanics/VehicleMechanics.tsx new file mode 100644 index 0000000..7d3ffb0 --- /dev/null +++ b/app/src/components/layout/sidebarRight/mechanics/VehicleMechanics.tsx @@ -0,0 +1,561 @@ +import React, { useRef, useState, useMemo, useEffect } from "react"; +import { + AddIcon, + InfoIcon, + RemoveIcon, + ResizeHeightIcon, +} from "../../../icons/ExportCommonIcons"; +import RenameInput from "../../../ui/inputs/RenameInput"; +import InputWithDropDown from "../../../ui/inputs/InputWithDropDown"; +import LabledDropdown from "../../../ui/inputs/LabledDropdown"; +import RegularDropDown from "../../../ui/inputs/RegularDropDown"; +import { handleResize } from "../../../../functions/handleResizePannel"; +import EyeDropInput from "../../../ui/inputs/EyeDropInput"; +import { useSelectedActionSphere, useSelectedPath, useSimulationPaths } from "../../../../store/store"; +import * as THREE from 'three'; +import * as Types from '../../../../types/world/worldTypes'; +import InputToggle from "../../../ui/inputs/InputToggle"; + +const VehicleMechanics: React.FC = () => { + const { selectedActionSphere } = useSelectedActionSphere(); + const { selectedPath, setSelectedPath } = useSelectedPath(); + const { simulationPaths, setSimulationPaths } = useSimulationPaths(); + + const actionsContainerRef = useRef(null); + const triggersContainerRef = useRef(null); + + const selectedPoint = useMemo(() => { + if (!selectedActionSphere) return null; + return simulationPaths + .filter((path): path is Types.ConveyorEventsSchema => path.type === "Conveyor") + .flatMap((path) => path.points) + .find((point) => point.uuid === selectedActionSphere.point.uuid); + }, [selectedActionSphere, simulationPaths]); + + const handleAddAction = () => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => { + if (path.type === "Conveyor") { + return { + ...path, + points: path.points.map((point) => { + if (point.uuid === selectedActionSphere.point.uuid) { + const actionIndex = point.actions.length; + const newAction = { + uuid: THREE.MathUtils.generateUUID(), + name: `Action ${actionIndex + 1}`, + type: 'Inherit', + material: 'Inherit', + delay: 'Inherit', + spawnInterval: 'Inherit', + isUsed: false + }; + + return { ...point, actions: [...point.actions, newAction] }; + } + return point; + }), + }; + } + return path; + }); + + setSimulationPaths(updatedPaths); + }; + + const handleDeleteAction = (uuid: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleActionSelect = (uuid: string, actionType: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid + ? { + ...action, + type: actionType, + material: actionType === 'Spawn' || actionType === 'Swap' ? 'Inherit' : action.material, + delay: actionType === 'Delay' ? 'Inherit' : action.delay, + spawnInterval: actionType === 'Spawn' ? 'Inherit' : action.spawnInterval + } + : action + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + + // Update the selected item to reflect changes + if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { + const updatedAction = updatedPaths + .filter((path): path is Types.ConveyorEventsSchema => path.type === "Conveyor") + .flatMap(path => path.points) + .find(p => p.uuid === selectedActionSphere.point.uuid) + ?.actions.find(a => a.uuid === uuid); + + if (updatedAction) { + setSelectedItem({ + type: "action", + item: updatedAction + }); + } + } + }; + + // Modified handleMaterialSelect to ensure it only applies to relevant action types + const handleMaterialSelect = (uuid: string, material: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid && + (action.type === 'Spawn' || action.type === 'Swap') + ? { ...action, material } + : action + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + + // Update selected item if it's the current action + if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { + setSelectedItem({ + ...selectedItem, + item: { + ...selectedItem.item, + material + } + }); + } + }; + + const handleDelayChange = (uuid: string, delay: number | string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid ? { ...action, delay } : action + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleSpawnIntervalChange = (uuid: string, spawnInterval: number | string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid ? { ...action, spawnInterval } : action + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleSpeedChange = (speed: number) => { + if (!selectedPath) return; + + const updatedPaths = simulationPaths.map((path) => + path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path + ); + + setSimulationPaths(updatedPaths); + setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } }); + }; + + const handleAddTrigger = () => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => { + if (point.uuid === selectedActionSphere.point.uuid) { + const triggerIndex = point.triggers.length; + const newTrigger = { + uuid: THREE.MathUtils.generateUUID(), + name: `Trigger ${triggerIndex + 1}`, + type: '', + isUsed: false + }; + + return { ...point, triggers: [...point.triggers, newTrigger] }; + } + return point; + }), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleDeleteTrigger = (uuid: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleTriggerSelect = (uuid: string, triggerType: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + triggers: point.triggers.map((trigger) => + trigger.uuid === uuid ? { ...trigger, type: triggerType } : trigger + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + // Update the toggle handlers to immediately update the selected item + const handleActionToggle = (uuid: string) => { + if (!selectedActionSphere) return; + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => ({ + ...action, + isUsed: action.uuid === uuid ? !action.isUsed : false, + })), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + + // Immediately update the selected item if it's the one being toggled + if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { + setSelectedItem({ + ...selectedItem, + item: { + ...selectedItem.item, + isUsed: !selectedItem.item.isUsed + } + }); + } + }; + + // Do the same for trigger toggle + const handleTriggerToggle = (uuid: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + triggers: point.triggers.map((trigger) => ({ + ...trigger, + isUsed: trigger.uuid === uuid ? !trigger.isUsed : false, + })), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + + // Immediately update the selected item if it's the one being toggled + if (selectedItem?.type === "trigger" && selectedItem.item.uuid === uuid) { + setSelectedItem({ + ...selectedItem, + item: { + ...selectedItem.item, + isUsed: !selectedItem.item.isUsed + } + }); + } + }; + + const [selectedItem, setSelectedItem] = useState<{ type: "action" | "trigger"; item: any; } | null>(null); + + useEffect(() => { + setSelectedItem(null); // Reset selectedItem when selectedActionSphere changes + }, [selectedActionSphere]); + + return ( +
+
+ {selectedActionSphere?.path?.modelName || "point name not found"} +
+ +
+
+
+
Actions
+
+ Add +
+
+
+
+ <> + {console.log(selectedPoint)} + +
+
handleResize(e, actionsContainerRef)} + > + +
+
+
+
+
+
Triggers
+
+ Add +
+
+
+
+ {selectedPoint?.triggers.map((trigger) => ( +
+
setSelectedItem({ type: "trigger", item: trigger })} + > + +
+
handleDeleteTrigger(trigger.uuid)} + > + +
+
+ ))} +
+
handleResize(e, triggersContainerRef)} + > + +
+
+
+
+ {selectedItem && ( + <> +
{selectedItem.item.name}
+ + {selectedItem.type === "action" && ( + <> + handleActionToggle(selectedItem.item.uuid)} + /> + handleActionSelect(selectedItem.item.uuid, option)} + /> + + {/* Only show material dropdown for Spawn/Swap actions */} + {(selectedItem.item.type === 'Spawn' || selectedItem.item.type === 'Swap') && ( + handleMaterialSelect(selectedItem.item.uuid, option)} + /> + )} + + {/* Only show delay input for Delay actions */} + {selectedItem.item.type === 'Delay' && ( + { + const numValue = parseInt(value); + handleDelayChange( + selectedItem.item.uuid, + !value ? 'Inherit' : numValue + ); + }} + /> + )} + + {/* Only show spawn interval for Spawn actions */} + {selectedItem.item.type === 'Spawn' && ( + { + handleSpawnIntervalChange(selectedItem.item.uuid, (value === "") ? "Inherit" : parseInt(value)); + }} + /> + + )} + + )} + + {selectedItem.type === "trigger" && ( + <> + handleTriggerToggle(selectedItem.item.uuid)} + /> + + handleTriggerSelect(selectedItem.item.uuid, option)} + /> + + )} + + )} + + {selectedPath && !selectedItem && ( +
+ handleSpeedChange(parseFloat(value))} + /> +
+ )} +
+
+ + By selecting points, you can create events and triggers. +
+
+
+ ); +}; + +export default VehicleMechanics; \ No newline at end of file diff --git a/app/src/modules/builder/agv/navMeshDetails.tsx b/app/src/modules/builder/agv/navMeshDetails.tsx index c941011..571be5a 100644 --- a/app/src/modules/builder/agv/navMeshDetails.tsx +++ b/app/src/modules/builder/agv/navMeshDetails.tsx @@ -34,15 +34,11 @@ export default function NavMeshDetails({ const [positions, indices] = getPositionsAndIndices(meshes); - const cs = 0.5; + const cs = 0.25; const ch = 0.5; - const walkableRadius = 0.89; + const walkableRadius = 0.5; - const { success, navMesh } = generateSoloNavMesh(positions, indices, { - cs, - ch, - walkableRadius: Math.round(walkableRadius / ch), - }); + const { success, navMesh } = generateSoloNavMesh(positions, indices, { cs, ch, walkableRadius: Math.round(walkableRadius / ch), }); if (!success || !navMesh) { return; @@ -53,7 +49,7 @@ export default function NavMeshDetails({ const debugDrawer = new DebugDrawer(); debugDrawer.drawNavMesh(navMesh); // scene.add(debugDrawer); - } catch (error) {} + } catch (error) { } }; initializeNavigation(); diff --git a/app/src/modules/builder/agv/pathNavigator.tsx b/app/src/modules/builder/agv/pathNavigator.tsx index 4193fb7..25d3af0 100644 --- a/app/src/modules/builder/agv/pathNavigator.tsx +++ b/app/src/modules/builder/agv/pathNavigator.tsx @@ -86,7 +86,7 @@ export default function PathNavigator({ return ( <> - {path.length > 0 && } + {/* {path.length > 0 && } */} {path.length > 0 && ( 0 ? path[0] : [0, 0.1, 0]}> diff --git a/app/src/modules/builder/agv/polygonGenerator.tsx b/app/src/modules/builder/agv/polygonGenerator.tsx index 1eca588..8682371 100644 --- a/app/src/modules/builder/agv/polygonGenerator.tsx +++ b/app/src/modules/builder/agv/polygonGenerator.tsx @@ -43,66 +43,46 @@ export default function PolygonGenerator({ const lineFeatures = result?.map((line: any) => turf.lineString(line.map((p: any) => p?.position)) - ); + ); const polygons = turf.polygonize(turf.featureCollection(lineFeatures)); renderWallGeometry(wallPoints); - let union: any = []; + if (polygons.features.length > 1) { + polygons.features.forEach((feature) => { + if (feature.geometry.type === "Polygon") { - polygons.features.forEach((feature) => { - union.push(feature); - }); + const shape = new THREE.Shape(); + const coords = feature.geometry.coordinates[0]; - if (union.length > 1) { - const unionResult = turf.union(turf.featureCollection(union)); + shape.moveTo(coords[0][0], coords[0][1]); - if (unionResult?.geometry.type === "MultiPolygon") { - unionResult.geometry.coordinates.forEach((poly) => { - const coordinates = poly[0].map(([x, z]) => { - return new THREE.Vector3(x, 0, z); - }); - renderBoxGeometry(coordinates); - }); - } else if (unionResult?.geometry.type === "Polygon") { - const coordinates = unionResult.geometry.coordinates[0].map( - ([x, z]) => { - return new THREE.Vector3(x, 0, z); + for (let i = 1; i < coords.length; i++) { + shape.lineTo(coords[i][0], coords[i][1]); } - ); - renderBoxGeometry(coordinates); - } - } else if (union.length === 1) { - const coordinates = union[0].geometry.coordinates[0].map( - ([x, z]: [number, number]) => { - return new THREE.Vector3(x, 0, z); + 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); } - ); - // setRooms((prevRooms) => [...prevRooms, coordinates]); + }); + } }, [lines.current]); - const renderBoxGeometry = (coordinates: THREE.Vector3[]) => { - const minX = Math.min(...coordinates.map((p) => p.x)); - const maxX = Math.max(...coordinates.map((p) => p.x)); - const minZ = Math.min(...coordinates.map((p) => p.z)); - const maxZ = Math.max(...coordinates.map((p) => p.z)); - - const width = maxX - minX; - const depth = maxZ - minZ; - const height = 3; - - const geometry = new THREE.BoxGeometry(width, height, depth); - const material = new THREE.MeshBasicMaterial({ - color: "#ff66cc", - visible: false, - }); - - const mesh = new THREE.Mesh(geometry, material); - mesh.position.set((minX + maxX) / 2, height / 2, (minZ + maxZ) / 2); - groupRef.current?.add(mesh); - }; - const renderWallGeometry = (walls: THREE.Vector3[][]) => { walls.forEach((wall) => { if (wall.length < 2) return; diff --git a/app/src/modules/collaboration/collabCams.tsx b/app/src/modules/collaboration/collabCams.tsx index da20b34..9d5475e 100644 --- a/app/src/modules/collaboration/collabCams.tsx +++ b/app/src/modules/collaboration/collabCams.tsx @@ -78,7 +78,7 @@ const CamModelsGroup = () => { socket.off('userDisConnectRespones'); socket.off('cameraUpdateResponse'); }; - }, [socket]); + }, [socket, activeUsers]); useFrame(() => { if (!groupRef.current) return; diff --git a/app/src/modules/scene/scene.tsx b/app/src/modules/scene/scene.tsx index 8ceeb2e..9b13a54 100644 --- a/app/src/modules/scene/scene.tsx +++ b/app/src/modules/scene/scene.tsx @@ -49,7 +49,6 @@ export default function Scene() { - {/* */} @@ -58,9 +57,6 @@ export default function Scene() { - - - ); } diff --git a/app/src/modules/simulation/behaviour/behaviour.tsx b/app/src/modules/simulation/behaviour/behaviour.tsx index d7a08af..2854172 100644 --- a/app/src/modules/simulation/behaviour/behaviour.tsx +++ b/app/src/modules/simulation/behaviour/behaviour.tsx @@ -1,43 +1,29 @@ -import { useFloorItems } from '../../../store/store'; +import { useFloorItems, useSimulationPaths } from '../../../store/store'; import * as THREE from 'three'; import * as Types from '../../../types/world/worldTypes'; import { useEffect } from 'react'; -interface Path { - modeluuid: string; - modelName: string; - points: { - uuid: string; - position: [number, number, number]; - rotation: [number, number, number]; - actions: { uuid: string; name: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; - triggers: { uuid: string; name: string; type: string; isUsed: boolean }[] | []; - connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] }; - }[]; - pathPosition: [number, number, number]; - pathRotation: [number, number, number]; - speed: number; -} - -function Behaviour({ setSimulationPaths }: { setSimulationPaths: any }) { +function Behaviour() { + const { setSimulationPaths } = useSimulationPaths(); const { floorItems } = useFloorItems(); useEffect(() => { - const newPaths: Path[] = []; + const newPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[] = []; floorItems.forEach((item: Types.FloorItemType) => { - if (item.modelfileID === "6633215057b31fe671145959") { - const point1Position = new THREE.Vector3(0, 1.25, 3.3); - const middlePointPosition = new THREE.Vector3(0, 1.25, 0); - const point2Position = new THREE.Vector3(0, 1.25, -3.3); + if (item.modelfileID === "672a090f80d91ac979f4d0bd") { + const point1Position = new THREE.Vector3(0, 0.85, 2.2); + const middlePointPosition = new THREE.Vector3(0, 0.85, 0); + const point2Position = new THREE.Vector3(0, 0.85, -2.2); const point1UUID = THREE.MathUtils.generateUUID(); const middlePointUUID = THREE.MathUtils.generateUUID(); const point2UUID = THREE.MathUtils.generateUUID(); - const newPath: Path = { + const newPath: Types.ConveyorEventsSchema = { modeluuid: item.modeluuid, modelName: item.modelname, + type: 'Conveyor', points: [ { uuid: point1UUID, @@ -64,12 +50,32 @@ function Behaviour({ setSimulationPaths }: { setSimulationPaths: any }) { connections: { source: { pathUUID: item.modeluuid, pointUUID: point2UUID }, targets: [] }, }, ], - pathPosition: [...item.position], - pathRotation: [item.rotation.x, item.rotation.y, item.rotation.z], + assetPosition: [...item.position], + assetRotation: [item.rotation.x, item.rotation.y, item.rotation.z], speed: 1, }; newPaths.push(newPath); + } else if (item.modelfileID === "67e3da19c2e8f37134526e6a") { + const pointUUID = THREE.MathUtils.generateUUID(); + const pointPosition = new THREE.Vector3(0, 1.3, 0); + + const newVehiclePath: Types.VehicleEventsSchema = { + modeluuid: item.modeluuid, + modelName: item.modelname, + type: 'Vehicle', + point: { + uuid: pointUUID, + position: [pointPosition.x, pointPosition.y, pointPosition.z], + actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Start', start: THREE.MathUtils.generateUUID(), hitCount: 1, end: THREE.MathUtils.generateUUID(), buffer: 0, isUsed: false }], + triggers: [], + connections: { source: { pathUUID: item.modeluuid, pointUUID: pointUUID }, targets: [] }, + }, + assetPosition: [...item.position], + speed: 2, + }; + + newPaths.push(newVehiclePath); } }); diff --git a/app/src/modules/simulation/path/pathConnector.tsx b/app/src/modules/simulation/path/pathConnector.tsx index 93172b7..8df718c 100644 --- a/app/src/modules/simulation/path/pathConnector.tsx +++ b/app/src/modules/simulation/path/pathConnector.tsx @@ -1,6 +1,7 @@ import { useFrame, useThree } from '@react-three/fiber'; import React, { useEffect, useState } from 'react'; import * as THREE from 'three'; +import * as Types from '../../../types/world/worldTypes'; import { QuadraticBezierLine } from '@react-three/drei'; import { useIsConnecting, useSimulationPaths } from '../../../store/store'; import useModuleStore from '../../../store/useModuleStore'; @@ -27,61 +28,113 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec toPointUUID: string ) => { const updatedPaths = simulationPaths.map(path => { - if (path.modeluuid === fromPathUUID) { - return { - ...path, - points: path.points.map(point => { - if (point.uuid === fromPointUUID) { - const newTarget = { - pathUUID: toPathUUID, - pointUUID: toPointUUID - }; - const existingTargets = point.connections.targets || []; - - if (!existingTargets.some(target => - target.pathUUID === newTarget.pathUUID && - target.pointUUID === newTarget.pointUUID - )) { - return { - ...point, - connections: { - ...point.connections, - targets: [...existingTargets, newTarget] - } + if (path.type === 'Conveyor') { + if (path.modeluuid === fromPathUUID) { + return { + ...path, + points: path.points.map(point => { + if (point.uuid === fromPointUUID) { + const newTarget = { + pathUUID: toPathUUID, + pointUUID: toPointUUID }; + const existingTargets = point.connections.targets || []; + + if (!existingTargets.some(target => + target.pathUUID === newTarget.pathUUID && + target.pointUUID === newTarget.pointUUID + )) { + return { + ...point, + connections: { + ...point.connections, + targets: [...existingTargets, newTarget] + } + }; + } } - } - return point; - }) - }; + return point; + }) + }; + } + else if (path.modeluuid === toPathUUID) { + return { + ...path, + points: path.points.map(point => { + if (point.uuid === toPointUUID) { + const reverseTarget = { + pathUUID: fromPathUUID, + pointUUID: fromPointUUID + }; + const existingTargets = point.connections.targets || []; + + if (!existingTargets.some(target => + target.pathUUID === reverseTarget.pathUUID && + target.pointUUID === reverseTarget.pointUUID + )) { + return { + ...point, + connections: { + ...point.connections, + targets: [...existingTargets, reverseTarget] + } + }; + } + } + return point; + }) + }; + } } - else if (path.modeluuid === toPathUUID) { - return { - ...path, - points: path.points.map(point => { - if (point.uuid === toPointUUID) { - const reverseTarget = { - pathUUID: fromPathUUID, - pointUUID: fromPointUUID - }; - const existingTargets = point.connections.targets || []; + else if (path.type === 'Vehicle') { + // Handle outgoing connections from Vehicle + if (path.modeluuid === fromPathUUID && path.point.uuid === fromPointUUID) { + const newTarget = { + pathUUID: toPathUUID, + pointUUID: toPointUUID + }; + const existingTargets = path.point.connections.targets || []; - if (!existingTargets.some(target => - target.pathUUID === reverseTarget.pathUUID && - target.pointUUID === reverseTarget.pointUUID - )) { - return { - ...point, - connections: { - ...point.connections, - targets: [...existingTargets, reverseTarget] - } - }; + if (!existingTargets.some(target => + target.pathUUID === newTarget.pathUUID && + target.pointUUID === newTarget.pointUUID + )) { + return { + ...path, + point: { + ...path.point, + connections: { + ...path.point.connections, + targets: [...existingTargets, newTarget] + } } - } - return point; - }) - }; + }; + } + } + // Handle incoming connections to Vehicle + else if (path.modeluuid === toPathUUID && path.point.uuid === toPointUUID) { + const reverseTarget = { + pathUUID: fromPathUUID, + pointUUID: fromPointUUID + }; + const existingTargets = path.point.connections.targets || []; + + if (!existingTargets.some(target => + target.pathUUID === reverseTarget.pathUUID && + target.pointUUID === reverseTarget.pointUUID + )) { + return { + ...path, + point: { + ...path.point, + connections: { + ...path.point.connections, + targets: [...existingTargets, reverseTarget] + } + } + }; + } + } } return path; }); @@ -126,25 +179,43 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec if (intersects.length > 0) { const intersected = intersects[0].object; - if (intersected.name.includes("action-sphere")) { + if (intersected.name.includes("events-sphere")) { const pathUUID = intersected.userData.path.modeluuid; const sphereUUID = intersected.uuid; const worldPosition = new THREE.Vector3(); intersected.getWorldPosition(worldPosition); - const isStartOrEnd = intersected.userData.path.points.length > 0 && ( - sphereUUID === intersected.userData.path.points[0].uuid || - sphereUUID === intersected.userData.path.points[intersected.userData.path.points.length - 1].uuid - ); + let isStartOrEnd = false; + + if (intersected.userData.path.points) { + isStartOrEnd = intersected.userData.path.points.length > 0 && ( + sphereUUID === intersected.userData.path.points[0].uuid || + sphereUUID === intersected.userData.path.points[intersected.userData.path.points.length - 1].uuid + ); + } else if (intersected.userData.path.point) { + isStartOrEnd = sphereUUID === intersected.userData.path.point.uuid; + } if (pathUUID) { - // Check if sphere is already connected - const isAlreadyConnected = simulationPaths.some(path => - path.points.some(point => - point.uuid === sphereUUID && - point.connections.targets.length > 0 - ) - ); + const firstPath = simulationPaths.find(p => p.modeluuid === firstSelected?.pathUUID); + const secondPath = simulationPaths.find(p => p.modeluuid === pathUUID); + + if (firstPath && secondPath && firstPath.type === 'Vehicle' && secondPath.type === 'Vehicle') { + console.log("Cannot connect two vehicle paths together"); + return; + } + const isAlreadyConnected = simulationPaths.some(path => { + if (path.type === 'Conveyor') { + return path.points.some(point => + point.uuid === sphereUUID && + point.connections.targets.length > 0 + ); + } else if (path.type === 'Vehicle') { + return path.point.uuid === sphereUUID && + path.point.connections.targets.length > 0; + } + return false; + }); if (isAlreadyConnected) { console.log("Sphere is already connected. Ignoring."); @@ -211,6 +282,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec raycaster.setFromCamera(pointer, camera); const intersects = raycaster.intersectObjects(scene.children, true).filter((intersect) => !intersect.object.name.includes("Roof") && + !intersect.object.name.includes("agv-collider") && !intersect.object.name.includes("MeasurementReference") && !intersect.object.userData.isPathObject && !(intersect.object.type === "GridHelper") @@ -229,7 +301,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec } const sphereIntersects = raycaster.intersectObjects(pathsGroupRef.current.children, true).filter((obj) => - obj.object.name.includes("action-sphere") + obj.object.name.includes("events-sphere") ); if (sphereIntersects.length > 0) { @@ -237,27 +309,45 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec const sphereUUID = sphere.uuid; const spherePosition = new THREE.Vector3(); sphere.getWorldPosition(spherePosition); - const pathUUID = sphere.userData.path.modeluuid; + const pathData = sphere.userData.path; + const pathUUID = pathData.modeluuid; - const isStartOrEnd = sphere.userData.path.points.length > 0 && ( - sphereUUID === sphere.userData.path.points[0].uuid || - sphereUUID === sphere.userData.path.points[sphere.userData.path.points.length - 1].uuid - ); + const firstPath = simulationPaths.find(p => p.modeluuid === firstSelected.pathUUID); + const secondPath = simulationPaths.find(p => p.modeluuid === pathUUID); + const isVehicleToVehicle = firstPath?.type === 'Vehicle' && secondPath?.type === 'Vehicle'; - const isAlreadyConnected = simulationPaths.some(path => - path.points.some(point => - point.uuid === sphereUUID && - point.connections.targets.length > 0 - ) - ); + const isConnectable = (pathData.type === 'Vehicle' || + (pathData.points.length > 0 && ( + sphereUUID === pathData.points[0].uuid || + sphereUUID === pathData.points[pathData.points.length - 1].uuid + ))) && !isVehicleToVehicle; + + const isAlreadyConnected = simulationPaths.some(path => { + if (path.type === 'Conveyor') { + return path.points.some(point => + point.uuid === sphereUUID && + point.connections.targets.length > 0 + ); + } else if (path.type === 'Vehicle') { + return path.point.uuid === sphereUUID && + path.point.connections.targets.length > 0; + } + return false; + }); if ( !isAlreadyConnected && + !isVehicleToVehicle && firstSelected.sphereUUID !== sphereUUID && firstSelected.pathUUID !== pathUUID && - (firstSelected.isCorner || isStartOrEnd) + (firstSelected.isCorner || isConnectable) ) { - snappedSphere = { sphereUUID, position: spherePosition, pathUUID, isCorner: isStartOrEnd }; + snappedSphere = { + sphereUUID, + position: spherePosition, + pathUUID, + isCorner: isConnectable + }; } else { isInvalidConnection = true; } @@ -281,8 +371,13 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec end: point, mid: midPoint, }); + console.log({ + start: firstSelected.position, + end: point, + mid: midPoint, + }); - setIsConnecting(true); + // setIsConnecting(true); if (sphereIntersects.length > 0) { setHelperLineColor(isInvalidConnection ? 'red' : '#6cf542'); @@ -299,13 +394,53 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec } }); - // Render connections from simulationPaths return ( <> - {simulationPaths.flatMap(path => - path.points.flatMap(point => - point.connections.targets.map((target, index) => { - const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', point.uuid); + {simulationPaths.flatMap(path => { + if (path.type === 'Conveyor') { + return path.points.flatMap(point => + point.connections.targets.map((target, index) => { + const targetPath = simulationPaths.find(p => p.modeluuid === target.pathUUID); + if (targetPath?.type === 'Vehicle') return null; + + const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', point.uuid); + const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID); + + if (fromSphere && toSphere) { + const fromWorldPosition = new THREE.Vector3(); + const toWorldPosition = new THREE.Vector3(); + fromSphere.getWorldPosition(fromWorldPosition); + toSphere.getWorldPosition(toWorldPosition); + + const distance = fromWorldPosition.distanceTo(toWorldPosition); + const heightFactor = Math.max(0.5, distance * 0.2); + + const midPoint = new THREE.Vector3( + (fromWorldPosition.x + toWorldPosition.x) / 2, + Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor, + (fromWorldPosition.z + toWorldPosition.z) / 2 + ); + + return ( + + ); + } + return null; + }) + ); + } else if (path.type === 'Vehicle') { + return path.point.connections.targets.map((target, index) => { + const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', path.point.uuid); const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID); if (fromSphere && toSphere) { @@ -325,22 +460,23 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec return ( ); } return null; - }) - ) - )} + }); + } + return []; + })} {currentLine && ( { if (!selectedActionSphere) return; - const updatedPaths: Path[] = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - position: [ - selectedActionSphere.point.position.x, - selectedActionSphere.point.position.y, - selectedActionSphere.point.position.z, - ], - rotation: [ - selectedActionSphere.point.rotation.x, - selectedActionSphere.point.rotation.y, - selectedActionSphere.point.rotation.z, - ] - } - : point - ), - })); + const updatedPaths = simulationPaths.map((path) => { + if (path.type === "Conveyor") { + return { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + position: [ + selectedActionSphere.point.position.x, + selectedActionSphere.point.position.y, + selectedActionSphere.point.position.z, + ], + rotation: [ + selectedActionSphere.point.rotation.x, + selectedActionSphere.point.rotation.y, + selectedActionSphere.point.rotation.z, + ] + } + : point + ), + }; + } + return path; + }) as ConveyorEventsSchema[]; setSimulationPaths(updatedPaths); }; return ( - + {simulationPaths.map((path) => { - const points = path.points.map(point => new THREE.Vector3(...point.position)); + if (path.type === 'Conveyor') { + const points = path.points.map(point => new THREE.Vector3(...point.position)); - return ( - (groupRefs.current[path.modeluuid] = el!)} - position={path.pathPosition} - rotation={path.pathRotation} - onClick={(e) => { - if (isConnecting) return; - e.stopPropagation(); - setSelectedPath({ path, group: groupRefs.current[path.modeluuid] }); - setSelectedActionSphere(null); - setTransformMode(null); - setSubModule('mechanics'); - }} - onPointerMissed={() => { - setSelectedPath(null); - setSubModule('properties'); - }} - > - {path.points.map((point, index) => ( + return ( + (groupRefs.current[path.modeluuid] = el!)} + position={path.assetPosition} + rotation={path.assetRotation} + onClick={(e) => { + if (isConnecting) return; + e.stopPropagation(); + setSelectedPath({ path, group: groupRefs.current[path.modeluuid] }); + setSelectedActionSphere(null); + setTransformMode(null); + setSubModule('mechanics'); + }} + onPointerMissed={() => { + setSelectedPath(null); + setSubModule('properties'); + }} + > + {path.points.map((point, index) => ( + (sphereRefs.current[point.uuid] = el!)} + onClick={(e) => { + if (isConnecting) return; + e.stopPropagation(); + setSelectedActionSphere({ + path, + point: sphereRefs.current[point.uuid] + }); + setSubModule('mechanics'); + setSelectedPath(null); + }} + userData={{ point, path }} + onPointerMissed={() => { + setSubModule('properties'); + setSelectedActionSphere(null); + }} + > + + + ))} + + {points.slice(0, -1).map((point, index) => { + const nextPoint = points[index + 1]; + const segmentCurve = new THREE.CatmullRomCurve3([point, nextPoint]); + const tubeGeometry = new THREE.TubeGeometry(segmentCurve, 20, 0.1, 16, false); + + return ( + + + + ); + })} + + ); + } else if (path.type === 'Vehicle') { + return ( + (groupRefs.current[path.modeluuid] = el!)} + position={path.assetPosition} + onClick={(e) => { + if (isConnecting) return; + e.stopPropagation(); + setSelectedPath({ path, group: groupRefs.current[path.modeluuid] }); + setSelectedActionSphere(null); + setTransformMode(null); + setSubModule('mechanics'); + }} + onPointerMissed={() => { + setSelectedPath(null); + setSubModule('properties'); + }} + > (sphereRefs.current[point.uuid] = el!)} + name='events-sphere' + ref={el => (sphereRefs.current[path.point.uuid] = el!)} onClick={(e) => { if (isConnecting) return; e.stopPropagation(); setSelectedActionSphere({ path, - point: sphereRefs.current[point.uuid] + point: sphereRefs.current[path.point.uuid] }); setSubModule('mechanics'); setSelectedPath(null); }} - userData={{ point, path }} + userData={{ point: path.point, path }} onPointerMissed={() => { setSubModule('properties'); - setSelectedActionSphere(null) + setSelectedActionSphere(null); }} > - + - ))} - - {points.slice(0, -1).map((point, index) => { - const nextPoint = points[index + 1]; - const segmentCurve = new THREE.CatmullRomCurve3([point, nextPoint]); - const tubeGeometry = new THREE.TubeGeometry(segmentCurve, 20, 0.1, 16, false); - - return ( - - - - ); - })} - - ); + + ); + } + return null; })} {selectedActionSphere && transformMode && ( @@ -163,7 +220,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject ref={transformRef} object={selectedActionSphere.point} mode={transformMode} - onObjectChange={updateSimulationPaths} + onMouseUp={updateSimulationPaths} /> )} diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx index fab1042..10934fb 100644 --- a/app/src/modules/simulation/simulation.tsx +++ b/app/src/modules/simulation/simulation.tsx @@ -31,7 +31,7 @@ function Simulation() { return ( <> - + {activeModule === 'simulation' && ( <> diff --git a/app/src/modules/simulation/simulationUI.tsx b/app/src/modules/simulation/simulationUI.tsx index 3a84134..0ce9fc2 100644 --- a/app/src/modules/simulation/simulationUI.tsx +++ b/app/src/modules/simulation/simulationUI.tsx @@ -1,409 +1,409 @@ -import { useMemo, useState } from 'react'; -import { useSelectedActionSphere, useToggleView, useSimulationPaths, useSelectedPath, useStartSimulation, useDrawMaterialPath } from '../../store/store'; -import * as THREE from 'three'; -import useModuleStore from '../../store/useModuleStore'; +// import { useMemo, useState } from 'react'; +// import { useSelectedActionSphere, useToggleView, useSimulationPaths, useSelectedPath, useStartSimulation, useDrawMaterialPath } from '../../store/store'; +// import * as THREE from 'three'; +// import useModuleStore from '../../store/useModuleStore'; -function SimulationUI() { - const { ToggleView } = useToggleView(); - const { activeModule } = useModuleStore(); - const { startSimulation, setStartSimulation } = useStartSimulation(); - const { selectedActionSphere } = useSelectedActionSphere(); - const { selectedPath, setSelectedPath } = useSelectedPath(); - const { simulationPaths, setSimulationPaths } = useSimulationPaths(); - const { drawMaterialPath, setDrawMaterialPath } = useDrawMaterialPath(); - const [activeButton, setActiveButton] = useState(null); +// function SimulationUI() { +// const { ToggleView } = useToggleView(); +// const { activeModule } = useModuleStore(); +// const { startSimulation, setStartSimulation } = useStartSimulation(); +// const { selectedActionSphere } = useSelectedActionSphere(); +// const { selectedPath, setSelectedPath } = useSelectedPath(); +// const { simulationPaths, setSimulationPaths } = useSimulationPaths(); +// const { drawMaterialPath, setDrawMaterialPath } = useDrawMaterialPath(); +// const [activeButton, setActiveButton] = useState(null); - const handleAddAction = () => { - if (!selectedActionSphere) return; +// const handleAddAction = () => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => { - if (point.uuid === selectedActionSphere.point.uuid) { - const actionIndex = point.actions.length; - const newAction = { - uuid: THREE.MathUtils.generateUUID(), - name: `Action ${actionIndex + 1}`, // Assign action name based on index - type: 'Inherit', - material: 'Inherit', - delay: 'Inherit', - spawnInterval: 'Inherit', - isUsed: false - }; +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => { +// if (point.uuid === selectedActionSphere.point.uuid) { +// const actionIndex = point.actions.length; +// const newAction = { +// uuid: THREE.MathUtils.generateUUID(), +// name: `Action ${actionIndex + 1}`, // Assign action name based on index +// type: 'Inherit', +// material: 'Inherit', +// delay: 'Inherit', +// spawnInterval: 'Inherit', +// isUsed: false +// }; - return { ...point, actions: [...point.actions, newAction] }; - } - return point; - }), - })); +// return { ...point, actions: [...point.actions, newAction] }; +// } +// return point; +// }), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleDeleteAction = (uuid: string) => { - if (!selectedActionSphere) return; +// const handleDeleteAction = (uuid: string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleActionSelect = (uuid: string, actionType: string) => { - if (!selectedActionSphere) return; +// const handleActionSelect = (uuid: string, actionType: string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => - action.uuid === uuid ? { ...action, type: actionType } : action - ), - } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { +// ...point, +// actions: point.actions.map((action) => +// action.uuid === uuid ? { ...action, type: actionType } : action +// ), +// } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleMaterialSelect = (uuid: string, material: string) => { - if (!selectedActionSphere) return; +// const handleMaterialSelect = (uuid: string, material: string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => - action.uuid === uuid ? { ...action, material } : action - ), - } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { +// ...point, +// actions: point.actions.map((action) => +// action.uuid === uuid ? { ...action, material } : action +// ), +// } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleDelayChange = (uuid: string, delay: number | string) => { - if (!selectedActionSphere) return; +// const handleDelayChange = (uuid: string, delay: number | string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => - action.uuid === uuid ? { ...action, delay } : action - ), - } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { +// ...point, +// actions: point.actions.map((action) => +// action.uuid === uuid ? { ...action, delay } : action +// ), +// } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleSpawnIntervalChange = (uuid: string, spawnInterval: number | string) => { - if (!selectedActionSphere) return; +// const handleSpawnIntervalChange = (uuid: string, spawnInterval: number | string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => - action.uuid === uuid ? { ...action, spawnInterval } : action - ), - } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { +// ...point, +// actions: point.actions.map((action) => +// action.uuid === uuid ? { ...action, spawnInterval } : action +// ), +// } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleSpeedChange = (speed: number) => { - if (!selectedPath) return; +// const handleSpeedChange = (speed: number) => { +// if (!selectedPath) return; - const updatedPaths = simulationPaths.map((path) => - path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path - ); +// const updatedPaths = simulationPaths.map((path) => +// path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path +// ); - setSimulationPaths(updatedPaths); - setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } }); - }; +// setSimulationPaths(updatedPaths); +// setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } }); +// }; - const handleAddTrigger = () => { - if (!selectedActionSphere) return; +// const handleAddTrigger = () => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => { - if (point.uuid === selectedActionSphere.point.uuid) { - const triggerIndex = point.triggers.length; - const newTrigger = { - uuid: THREE.MathUtils.generateUUID(), - name: `Trigger ${triggerIndex + 1}`, // Assign name based on index - type: '', - isUsed: false - }; +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => { +// if (point.uuid === selectedActionSphere.point.uuid) { +// const triggerIndex = point.triggers.length; +// const newTrigger = { +// uuid: THREE.MathUtils.generateUUID(), +// name: `Trigger ${triggerIndex + 1}`, // Assign name based on index +// type: '', +// isUsed: false +// }; - return { ...point, triggers: [...point.triggers, newTrigger] }; - } - return point; - }), - })); +// return { ...point, triggers: [...point.triggers, newTrigger] }; +// } +// return point; +// }), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleDeleteTrigger = (uuid: string) => { - if (!selectedActionSphere) return; +// const handleDeleteTrigger = (uuid: string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleTriggerSelect = (uuid: string, triggerType: string) => { - if (!selectedActionSphere) return; +// const handleTriggerSelect = (uuid: string, triggerType: string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - triggers: point.triggers.map((trigger) => - trigger.uuid === uuid ? { ...trigger, type: triggerType } : trigger - ), - } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { +// ...point, +// triggers: point.triggers.map((trigger) => +// trigger.uuid === uuid ? { ...trigger, type: triggerType } : trigger +// ), +// } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleResetPath = () => { - if (!selectedPath) return; +// const handleResetPath = () => { +// if (!selectedPath) return; - }; +// }; - const handleActionToggle = (uuid: string) => { - if (!selectedActionSphere) return; +// const handleActionToggle = (uuid: string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => ({ - ...action, - isUsed: action.uuid === uuid ? !action.isUsed : false, - })), - } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { +// ...point, +// actions: point.actions.map((action) => ({ +// ...action, +// isUsed: action.uuid === uuid ? !action.isUsed : false, +// })), +// } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleTriggerToggle = (uuid: string) => { - if (!selectedActionSphere) return; +// const handleTriggerToggle = (uuid: string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - triggers: point.triggers.map((trigger) => ({ - ...trigger, - isUsed: trigger.uuid === uuid ? !trigger.isUsed : false, - })), - } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { +// ...point, +// triggers: point.triggers.map((trigger) => ({ +// ...trigger, +// isUsed: trigger.uuid === uuid ? !trigger.isUsed : false, +// })), +// } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const selectedPoint = useMemo(() => { - if (!selectedActionSphere) return null; - return simulationPaths.flatMap((path) => path.points).find((point) => point.uuid === selectedActionSphere.point.uuid); - }, [selectedActionSphere, simulationPaths]); +// const selectedPoint = useMemo(() => { +// if (!selectedActionSphere) return null; +// return simulationPaths.flatMap((path) => path.points).find((point) => point.uuid === selectedActionSphere.point.uuid); +// }, [selectedActionSphere, simulationPaths]); - const createPath = () => { - setActiveButton(activeButton !== 'addMaterialPath' ? 'addMaterialPath' : null); - setDrawMaterialPath(!drawMaterialPath); - } +// const createPath = () => { +// setActiveButton(activeButton !== 'addMaterialPath' ? 'addMaterialPath' : null); +// setDrawMaterialPath(!drawMaterialPath); +// } - return ( - <> - {activeModule === "simulation" && ( -
- {!ToggleView && ( - <> - +// return ( +// <> +// {activeModule === "simulation" && ( +//
+// {!ToggleView && ( +// <> +// -
- {!ToggleView && } -
+//
+// {!ToggleView && } +//
- {selectedPath && ( -
- - handleSpeedChange(parseFloat(e.target.value))} - /> -
- )} +// {selectedPath && ( +//
+// +// handleSpeedChange(parseFloat(e.target.value))} +// /> +//
+// )} - {selectedActionSphere && ( -
- - +// {selectedActionSphere && ( +//
+// +// - {selectedPoint?.actions.map((action) => ( -
- - - +// {selectedPoint?.actions.map((action) => ( +//
+// +// +// - {(action.type === 'Spawn' || action.type === 'Swap') && ( -
- -
- )} +// {(action.type === 'Spawn' || action.type === 'Swap') && ( +//
+// +//
+// )} - {action.type === 'Delay' && ( -
- - handleDelayChange(action.uuid, parseInt(e.target.value) || 'Inherit')} - /> +// {action.type === 'Delay' && ( +//
+// +// handleDelayChange(action.uuid, parseInt(e.target.value) || 'Inherit')} +// /> -
- )} +//
+// )} - {action.type === 'Spawn' && ( -
- - handleSpawnIntervalChange(action.uuid, parseInt(e.target.value) || 'Inherit')} - /> +// {action.type === 'Spawn' && ( +//
+// +// handleSpawnIntervalChange(action.uuid, parseInt(e.target.value) || 'Inherit')} +// /> -
- )} -
-
- ))} +//
+// )} +//
+//
+// ))} -
+//
- {selectedPoint?.triggers.map((trigger) => ( -
- - - -
-
- ))} +// {selectedPoint?.triggers.map((trigger) => ( +//
+// +// +// +//
+//
+// ))} -
- )} +//
+// )} - {selectedPath && ( -
- -
- )} - - )} -
- )} - - ); -} +// {selectedPath && ( +//
+// +//
+// )} +// +// )} +//
+// )} +// +// ); +// } -export default SimulationUI; \ No newline at end of file +// export default SimulationUI; \ No newline at end of file diff --git a/app/src/pages/Project.tsx b/app/src/pages/Project.tsx index 1046ea2..a7800e1 100644 --- a/app/src/pages/Project.tsx +++ b/app/src/pages/Project.tsx @@ -64,7 +64,6 @@ const Project: React.FC = () => { {activeModule === "market" && } {activeModule !== "market" && } - {/* */} {isPlaying && activeModule === "simulation" && }
); diff --git a/app/src/services/factoryBuilder/mqtt/mqttEvents.ts b/app/src/services/factoryBuilder/mqtt/mqttEvents.ts index cd79484..41175ca 100644 --- a/app/src/services/factoryBuilder/mqtt/mqttEvents.ts +++ b/app/src/services/factoryBuilder/mqtt/mqttEvents.ts @@ -6,10 +6,7 @@ const MqttEvents = () => { const { setTouch, setTemperature, setHumidity } = useDrieUIValue(); useEffect(() => { - const client = mqtt.connect("ws://192.168.0.192:1884", { - username: "gabby", - password: "gabby" - }); + const client = mqtt.connect(`ws://${process.env.REACT_APP_SERVER_MQTT_URL}`); client.subscribe("touch"); client.subscribe("temperature"); diff --git a/app/src/store/store.ts b/app/src/store/store.ts index 8b8e544..eb2fac4 100644 --- a/app/src/store/store.ts +++ b/app/src/store/store.ts @@ -2,7 +2,6 @@ import * as THREE from "three"; import * as Types from "../types/world/worldTypes"; import { create } from "zustand"; import { io } from "socket.io-client"; -import { ComponentType, SVGProps } from "react"; export const useSocketStore = create((set: any, get: any) => ({ socket: null, @@ -31,8 +30,8 @@ export const useSocketStore = create((set: any, get: any) => ({ })); export const useLoadingProgress = create<{ loadingProgress: number; setLoadingProgress: (x: number) => void }>((set) => ({ - loadingProgress: 1, - setLoadingProgress: (x: number) => set({ loadingProgress: x }), + loadingProgress: 1, + setLoadingProgress: (x: number) => set({ loadingProgress: x }), })); export const useOrganization = create((set: any) => ({ @@ -311,30 +310,14 @@ export const useSelectedPath = create((set: any) => ({ setSelectedPath: (x: any) => set({ selectedPath: x }), })); -interface Path { - modeluuid: string; - modelName: string; - points: { - uuid: string; - position: [number, number, number]; - rotation: [number, number, number]; - actions: { uuid: string; name: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; - triggers: { uuid: string; name: string; type: string; isUsed: boolean }[] | []; - connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] }; - }[]; - pathPosition: [number, number, number]; - pathRotation: [number, number, number]; - speed: number; -} - interface SimulationPathsStore { - simulationPaths: Path[]; - setSimulationPaths: (paths: Path[]) => void; + simulationPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]; + setSimulationPaths: (paths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => void; } export const useSimulationPaths = create((set) => ({ - simulationPaths: [], - setSimulationPaths: (paths: Path[]) => set({ simulationPaths: paths }), + simulationPaths: [], + setSimulationPaths: (paths) => set({ simulationPaths: paths }), })); export const useIsConnecting = create((set: any) => ({ diff --git a/app/src/types/world/worldTypes.d.ts b/app/src/types/world/worldTypes.d.ts index c1e7128..2fcbd4f 100644 --- a/app/src/types/world/worldTypes.d.ts +++ b/app/src/types/world/worldTypes.d.ts @@ -284,4 +284,36 @@ interface ConnectionStore { setConnections: (connections: PathConnection[]) => void; addConnection: (newConnection: PathConnection) => void; removeConnection: (fromUUID: string, toUUID: string) => void; +} + +interface ConveyorEventsSchema { + modeluuid: string; + modelName: string; + type: 'Conveyor'; + points: { + uuid: string; + position: [number, number, number]; + rotation: [number, number, number]; + actions: { uuid: string; name: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; + triggers: { uuid: string; name: string; type: string; isUsed: boolean }[] | []; + connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] }; + }[]; + assetPosition: [number, number, number]; + assetRotation: [number, number, number]; + speed: number; +} + +interface VehicleEventsSchema { + modeluuid: string; + modelName: string; + type: 'Vehicle'; + point: { + uuid: string; + position: [number, number, number]; + actions: { uuid: string; name: string; type: string; start: string, hitCount: number, end: string, buffer: number; isUsed: boolean }[] | []; + triggers: { uuid: string; name: string; type: string; isUsed: boolean }[] | []; + connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] }; + }; + assetPosition: [number, number, number]; + speed: number; } \ No newline at end of file From c842b81611ccba005e7104488220a02d5c7b6345 Mon Sep 17 00:00:00 2001 From: Gomathi9520 Date: Fri, 28 Mar 2025 19:13:20 +0530 Subject: [PATCH 4/4] 3dWidget dnd and 2d widgets backend api updated --- .../components/layout/3D-cards/CardsScene.tsx | 4 +- .../3D-cards/cards/ProductionCapacity.tsx | 10 ++- .../3D-cards/cards/ReturnOfInvestment.tsx | 11 ++- .../layout/3D-cards/cards/StateWorking.tsx | 14 +++- .../layout/3D-cards/cards/Throughput.tsx | 12 ++- .../visualization/widgets/Widgets2D.tsx | 4 +- .../visualization/widgets/Widgets3D.tsx | 28 ++++++- .../components/ui/componets/AddButtons.tsx | 59 ++++++++------ .../components/ui/componets/DisplayZone.tsx | 46 ++++++----- .../ui/componets/DraggableWidget.tsx | 18 +++-- .../ui/componets/Dropped3dWidget.tsx | 79 +++++++++++++++++++ .../ui/componets/DroppedFloatingWidgets.tsx | 1 - app/src/components/ui/componets/Panel.tsx | 38 +++++---- .../ui/componets/RealTimeVisulization.tsx | 79 +++++++++++++------ .../ui/realTimeVis/charts/ProgressCard.tsx | 2 +- .../builder/groups/floorItemsGroup.tsx | 5 +- .../modules/builder/groups/wallItemsGroup.tsx | 1 + app/src/modules/scene/scene.tsx | 3 + app/src/modules/simulation/simulation.tsx | 2 +- .../zoneData/addWidgets.ts | 30 +++++++ .../zoneData/getSelect2dZoneData.ts | 27 +++++++ .../zoneData/getZoneData.ts | 23 ++++++ .../realTimeVisulization/zoneData/panel.ts | 24 +----- app/src/store/store.ts | 59 +++++++++----- app/src/store/useZoneStore.ts | 1 + .../visualization/floating/common.scss | 5 +- 26 files changed, 435 insertions(+), 150 deletions(-) create mode 100644 app/src/components/ui/componets/Dropped3dWidget.tsx create mode 100644 app/src/services/realTimeVisulization/zoneData/addWidgets.ts create mode 100644 app/src/services/realTimeVisulization/zoneData/getSelect2dZoneData.ts create mode 100644 app/src/services/realTimeVisulization/zoneData/getZoneData.ts diff --git a/app/src/components/layout/3D-cards/CardsScene.tsx b/app/src/components/layout/3D-cards/CardsScene.tsx index 471034c..9318ce3 100644 --- a/app/src/components/layout/3D-cards/CardsScene.tsx +++ b/app/src/components/layout/3D-cards/CardsScene.tsx @@ -11,10 +11,10 @@ const CardsScene = () => { {/* 3d-cards */} - - {/* */} {/* */} + {/* */} {/* */} + {/* */} diff --git a/app/src/components/layout/3D-cards/cards/ProductionCapacity.tsx b/app/src/components/layout/3D-cards/cards/ProductionCapacity.tsx index 7402c8d..4da32bc 100644 --- a/app/src/components/layout/3D-cards/cards/ProductionCapacity.tsx +++ b/app/src/components/layout/3D-cards/cards/ProductionCapacity.tsx @@ -21,8 +21,11 @@ ChartJS.register( Tooltip, Legend ); +interface ProductionCapacityProps { + position: [number, number, number]; +} -const ProductionCapacity = () => { +const ProductionCapacity : React.FC = ({ position }) => { // Chart data for a week const chartData = { labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], // Days of the week @@ -76,7 +79,10 @@ const ProductionCapacity = () => { }; return ( - +
Production Capacity
diff --git a/app/src/components/layout/3D-cards/cards/ReturnOfInvestment.tsx b/app/src/components/layout/3D-cards/cards/ReturnOfInvestment.tsx index e4b60b4..8e8c444 100644 --- a/app/src/components/layout/3D-cards/cards/ReturnOfInvestment.tsx +++ b/app/src/components/layout/3D-cards/cards/ReturnOfInvestment.tsx @@ -35,8 +35,10 @@ const SmoothLineGraphComponent: React.FC = ({ }) => { return ; }; - -const ReturnOfInvestment = () => { +interface ReturnOfInvestmentProps { + position: [number, number, number]; +} +const ReturnOfInvestment: React.FC = ({ position }) => { // Improved sample data for the smooth curve graph (single day) const graphData: ChartData<"line"> = { labels: [ @@ -106,7 +108,10 @@ const ReturnOfInvestment = () => { }; return ( - +
Return of Investment
diff --git a/app/src/components/layout/3D-cards/cards/StateWorking.tsx b/app/src/components/layout/3D-cards/cards/StateWorking.tsx index 7e3de43..25ee39b 100644 --- a/app/src/components/layout/3D-cards/cards/StateWorking.tsx +++ b/app/src/components/layout/3D-cards/cards/StateWorking.tsx @@ -1,6 +1,9 @@ import { Html } from "@react-three/drei"; -import image from "../../../../assets/image/temp/image.png"; -const StateWorking = () => { +// import image from "../../../../assets/image/temp/image.png"; +interface StateWorkingProps { + position: [number, number, number]; +} +const StateWorking: React.FC = ({ position }) => { const datas = [ { key: "Oil Tank:", value: "24/341" }, { key: "Oil Refin:", value: 36.023 }, @@ -10,7 +13,10 @@ const StateWorking = () => { { key: "Time:", value: 13 - 9 - 2023 }, ]; return ( - +
@@ -20,7 +26,7 @@ const StateWorking = () => {
- + {/* */}
{/* Data */} diff --git a/app/src/components/layout/3D-cards/cards/Throughput.tsx b/app/src/components/layout/3D-cards/cards/Throughput.tsx index b12fc14..220c2a2 100644 --- a/app/src/components/layout/3D-cards/cards/Throughput.tsx +++ b/app/src/components/layout/3D-cards/cards/Throughput.tsx @@ -37,7 +37,12 @@ const LineGraphComponent: React.FC = ({ data, options }) => { return ; }; -const Throughput = () => { +interface ThroughputProps { + position: [number, number, number]; +} + +const Throughput: React.FC = ({ position }) => { + // Sample data for the line graph const graphData: ChartData<"line"> = { labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun"], @@ -86,7 +91,10 @@ const Throughput = () => { }; return ( - +
Throughput
diff --git a/app/src/components/layout/sidebarLeft/visualization/widgets/Widgets2D.tsx b/app/src/components/layout/sidebarLeft/visualization/widgets/Widgets2D.tsx index 5833986..d04c155 100644 --- a/app/src/components/layout/sidebarLeft/visualization/widgets/Widgets2D.tsx +++ b/app/src/components/layout/sidebarLeft/visualization/widgets/Widgets2D.tsx @@ -3,6 +3,7 @@ import { useWidgetStore } from "../../../../../store/useWidgetStore"; import { ChartType } from "chart.js/auto"; import ChartComponent from "./ChartComponent"; import { StockIncreseIcon } from "../../../../icons/RealTimeVisulationIcons"; +import { generateUniqueId } from "../../../../../functions/generateUniqueId"; const chartTypes: ChartType[] = [ "bar", @@ -40,7 +41,8 @@ const ChartWidget: React.FC = ({ type, index, title }) => { onDragStart={() => { setDraggedAsset({ type, - id: `widget-${index + 1}`, + id: generateUniqueId( + ), title, panel: "top", data: sampleData, diff --git a/app/src/components/layout/sidebarLeft/visualization/widgets/Widgets3D.tsx b/app/src/components/layout/sidebarLeft/visualization/widgets/Widgets3D.tsx index 2862cef..849c051 100644 --- a/app/src/components/layout/sidebarLeft/visualization/widgets/Widgets3D.tsx +++ b/app/src/components/layout/sidebarLeft/visualization/widgets/Widgets3D.tsx @@ -2,6 +2,7 @@ import widget1 from "../../../../../assets/image/3D/ProductionCapacity.png"; import widget2 from "../../../../../assets/image/3D/ReturnOfInvestment.png"; import widget3 from "../../../../../assets/image/3D/StateWorking.png"; import widget4 from "../../../../../assets/image/3D/Throughput.png"; +import { useAsset3dWidget } from "../../../../../store/store"; const Widgets3D = () => { const widgets = [ { name: "Widget 1", img: widget1 }, @@ -9,17 +10,38 @@ const Widgets3D = () => { { name: "Widget 3", img: widget3 }, { name: "Widget 4", img: widget4 }, ]; + const { widgetSelect, setWidgetSelect } = useAsset3dWidget(); + return (
{widgets?.map((widget, index) => ( -
-
{widget.name}
+
{ + let crt = e.target + if (crt instanceof HTMLElement) { + const widget = crt.cloneNode(true) as HTMLElement; + console.log('widget: ', widget); + e.dataTransfer.setDragImage(widget,0,0) + e.dataTransfer.effectAllowed="move" + } + }} + onPointerDown={() => { + setWidgetSelect("ui-" + widget.name); + }} + onPointerUp={() => { + setWidgetSelect(""); // Clearing selection correctly + }} + > + {/*
{widget.name}
*/} {widget.name}
))} diff --git a/app/src/components/ui/componets/AddButtons.tsx b/app/src/components/ui/componets/AddButtons.tsx index 7185fc6..11a1d80 100644 --- a/app/src/components/ui/componets/AddButtons.tsx +++ b/app/src/components/ui/componets/AddButtons.tsx @@ -16,6 +16,7 @@ interface ButtonsProps { zoneName: string; activeSides: Side[]; panelOrder: Side[]; + lockedPanels: Side[]; zoneId: string; zoneViewPortTarget: number[]; @@ -33,6 +34,7 @@ interface ButtonsProps { zoneName: string; activeSides: Side[]; panelOrder: Side[]; + lockedPanels: Side[]; zoneId: string; zoneViewPortTarget: number[]; @@ -120,23 +122,39 @@ const AddButtons: React.FC = ({ console.log("updatedZone: ", updatedZone); setSelectedZone(updatedZone); } else { - // If the panel is not active, activate it - const newActiveSides = [...selectedZone.activeSides, side]; + const updatePanelData = async () => { + try { + // Get email and organization safely + const email = localStorage.getItem("email") || ""; + const organization = email?.split("@")[1]?.split(".")[0] || "defaultOrg"; // Fallback value - const updatedZone = { - ...selectedZone, - activeSides: newActiveSides, - panelOrder: newActiveSides, + // Prevent duplicate side entries + const newActiveSides = selectedZone.activeSides.includes(side) + ? [...selectedZone.activeSides] + : [...selectedZone.activeSides, side]; + + const updatedZone = { + ...selectedZone, + activeSides: newActiveSides, + panelOrder: newActiveSides, + }; + + // API call + const response = await panelData(organization, selectedZone.zoneId, newActiveSides); + console.log("response: ", response); + + // Update state + console.log("updatedZone: ", updatedZone); + setSelectedZone(updatedZone); + } catch (error) { + console.error("Error updating panel data:", error); + } }; - const email = localStorage.getItem("email"); - const organization = email!.split("@")[1].split(".")[0]; - // let response = panelData(organization, selectedZone.zoneId, newActiveSides) - // console.log('response: ', response); - // Update the selectedZone state - console.log("updatedZone: ", updatedZone); - setSelectedZone(updatedZone); + updatePanelData(); // Call the async function } + + }; return ( @@ -146,9 +164,8 @@ const AddButtons: React.FC = ({
{/* "+" Button */}