From af1cefc71c195eb059018aba7e8a1b6022d2956e Mon Sep 17 00:00:00 2001 From: moxitech Date: Mon, 18 Nov 2024 16:11:36 +0700 Subject: [PATCH] Worker version --- nginx.conf | 24 +- .../src/app/components/Player/Model.tsx | 22 ++ .../src/app/components/Player/Player.tsx | 237 ++++++++---------- .../src/app/pages/simulations/page.tsx | 46 ++-- 4 files changed, 164 insertions(+), 165 deletions(-) create mode 100644 src/usn-frontend/src/app/components/Player/Model.tsx diff --git a/nginx.conf b/nginx.conf index 55625bc..d5b5aca 100644 --- a/nginx.conf +++ b/nginx.conf @@ -29,17 +29,17 @@ http { proxy_set_header X-Forwarded-Proto $scheme; } } - # server { - # listen 80; - # server_name ws.localhost; - # # add_header 'Access-Control-Allow-Origin' 'http://socket' always; + server { + listen 80; + server_name math.localhost; + # add_header 'Access-Control-Allow-Origin' 'http://math' always; - # location / { - # proxy_pass http://socket:9091; - # proxy_set_header Host $host; - # proxy_set_header X-Real-IP $remote_addr; - # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - # proxy_set_header X-Forwarded-Proto $scheme; - # } - # } + location / { + proxy_pass http://math:10000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + } } diff --git a/src/usn-frontend/src/app/components/Player/Model.tsx b/src/usn-frontend/src/app/components/Player/Model.tsx new file mode 100644 index 0000000..22a9444 --- /dev/null +++ b/src/usn-frontend/src/app/components/Player/Model.tsx @@ -0,0 +1,22 @@ +import { SimDrone } from "../Threejs/Models" + +// IPlayerSimulationPart - часть симуляции +// export interface IPlayerSimulationPart { +// Timestamp?: number // Временная метка +// CGS?: [] // базовые станции - DTO +// UAV?: SimDrone[] // беспилотные аппараты - DTO +// } + +export interface Drone { + connected_to: string | null; + frequency: number; + name: string; + position: [number, number, number]; + rssi: number | null; +} + +export interface IPlayerSimulationPart { + [key: string]: { + [droneName: string]: Drone; + }; +} diff --git a/src/usn-frontend/src/app/components/Player/Player.tsx b/src/usn-frontend/src/app/components/Player/Player.tsx index 6eb2569..757257c 100644 --- a/src/usn-frontend/src/app/components/Player/Player.tsx +++ b/src/usn-frontend/src/app/components/Player/Player.tsx @@ -3,6 +3,7 @@ import { Canvas } from '@react-three/fiber'; import { OrbitControls, useGLTF, Line, Text } from '@react-three/drei'; import React, { useState, useEffect, useRef } from 'react'; import { Drone, BaseStation, SimDrone } from '../Threejs/Models'; +import { IPlayerSimulationPart } from './Model'; interface Player { @@ -10,7 +11,7 @@ interface Player { TimeEnd: number; // Время окончания TimeStep: number; // временной шаг onTimeUpdate?: (currentTime: number) => void; // callback для возврата текущего времени - simulationEndedValues?: object + simulationEndedValues?: IPlayerSimulationPart } const InitPlayer: React.FC = ({ Click, TimeStep, TimeEnd, onTimeUpdate, simulationEndedValues }) => { @@ -20,36 +21,20 @@ const InitPlayer: React.FC = ({ Click, TimeStep, TimeEnd, onTimeUpdate, const [isDropdownOpen, setIsDropdownOpen] = useState(false); // состояние выпадающей панели const [TimestampEnd, setTimestampEnd] = useState(); const [TimestampStep, setTimestampStep] = useState(); - const [Simulations, setSimulations] = useState(); + const [Simulations, setSimulations] = useState(); - const ParseSimulationResponse = (simulationResponse: any): IPlayerSimulationPart[] => { - const parsedParts: IPlayerSimulationPart[] = Object.keys(simulationResponse).map((timestamp) => { - const drones = Object.values(simulationResponse[timestamp]).map((drone: any) => ({ - connected_to: drone.connected_to, - position: drone.position as [number, number, number], - rssi: drone.rssi, - name: drone.name, - frequency: drone.frequency, - })); - - return { - Timestamp: parseInt(timestamp, 10), - UAV: drones, - }; - }); - - return parsedParts; - }; useEffect(() => { let interval: NodeJS.Timeout | null = null; if (simulationEndedValues) { - console.log("TODO: parse this pls") + setSimulations(simulationEndedValues); + // console.log(simulationEndedValues); + console.log(simulationEndedValues) + setTimestampStep(1) + setTimestampEnd(299) } else { fetch("/tests/test_results.json") .then(simulationResponse => simulationResponse.json().then(val => { - let parts = ParseSimulationResponse(val) - setSimulations(parts) setTimestampStep(1) setTimestampEnd(100) })) @@ -79,7 +64,7 @@ const InitPlayer: React.FC = ({ Click, TimeStep, TimeEnd, onTimeUpdate, clearInterval(interval); } }; - }, [isPlaying, TimeStep, TimeEnd, playbackSpeed, onTimeUpdate]); + }, [isPlaying, TimeStep, TimeEnd, playbackSpeed, onTimeUpdate, simulationEndedValues]); const handlePlayPause = () => { setIsPlaying(!isPlaying); @@ -99,7 +84,7 @@ const InitPlayer: React.FC = ({ Click, TimeStep, TimeEnd, onTimeUpdate, return (
- +
@@ -159,159 +144,131 @@ const InitPlayer: React.FC = ({ Click, TimeStep, TimeEnd, onTimeUpdate, ); }; -// IPlayerSimulationPart - часть симуляции -interface IPlayerSimulationPart { - Timestamp?: number // Временная метка - CGS?: [] // базовые станции - DTO - UAV?: SimDrone[] // беспилотные аппараты - DTO -} + // IPlayerTsInstance - объект плеера interface IPlayerTsInstance { TimestampEnd?: number TimestampStep?: number - Simulations?: IPlayerSimulationPart[] + Simulations?: IPlayerSimulationPart + //// IPlayerSimulationPart - часть симуляции + // interface Drone { + // connected_to: string | null; + // frequency: number; + // name: string; + // position: [number, number, number]; + // rssi: number | null; + // } + + // interface IPlayerSimulationPart { + // [key: string]: { + // [droneName: string]: Drone; + // }; + // } } -const PlayerTsInstance : React.FC = ({ - TimestampEnd, - TimestampStep, - Simulations +const PlayerTsInstance: React.FC = ({ + TimestampEnd = 299, // Конечная временная метка + TimestampStep = 1, // Шаг временной метки + Simulations, }) => { + const [currentTimestamp, setCurrentTimestamp] = useState(0); const [drones, setDrones] = useState([]); const [baseStations, setBaseStations] = useState([]); - const [selectedObject, setSelectedObject] = useState<{ type: 'drone' | 'baseStation'; id: number } | null>(null); - const orbitControlsRef = useRef(null); // Reference to OrbitControls - - const addDrone = (drone?: Drone) => { - setDrones((prev) => [ - ...prev, - drone || { - id: prev.length, - name: `Drone ${prev.length + 1}`, - position: [Math.random() * 10, 5, Math.random() * 10], - frequency: Math.random() * 100 + 400, // Example frequency range between 400-500 - signalRadius: Math.random() * 5 + 5, // Example signal radius between 5-10 - }, - ]); - }; + const [isPlaying, setIsPlaying] = useState(false); // Флаг для управления анимацией - const addBaseStation = (baseStation?: BaseStation) => { - setBaseStations((prev) => [ - ...prev, - baseStation || { - id: prev.length, - name: `Base Station ${prev.length + 1}`, - position: [Math.random() * 10, -1, Math.random() * 10], - frequency: Math.random() * 100 + 400, // Example frequency range between 400-500 - signalRadius: Math.random() * 5 + 5, // Example signal radius between 5-10 - antennaDirection: [0, 1, 0], - }, - ]); - }; + const intervalRef = useRef(null); - - - const handleObjectClick = (type: 'drone' | 'baseStation', id: number) => { - setSelectedObject({ type, id }); - focusOnObject(type, id); - }; + useEffect(() => { + // Инициализация объектов на начальной метке времени + if (Simulations) { + updateObjects(currentTimestamp); + } + }, [Simulations, currentTimestamp]); - const focusOnObject = (type: 'drone' | 'baseStation', id: number) => { - const object = type === 'drone' ? drones.find((d) => d.id === id) : baseStations.find((b) => b.id === id); - if (object && orbitControlsRef.current) { - orbitControlsRef.current.target.set(...object.position); + const updateObjects = (timestamp: number) => { + if (!Simulations) return; + + const simulationStep = Simulations[timestamp]; + if (simulationStep) { + const updatedDrones = Object.values(simulationStep).map((drone) => ({ + ...drone, + })); + // @ts-ignore + setDrones(updatedDrones); } }; - const selectNextObject = (direction: 'next' | 'prev') => { - if (!selectedObject) return; + const startSimulation = () => { + if (!Simulations || isPlaying) return; - const currentList = selectedObject.type === 'drone' ? drones : baseStations; - const currentIndex = currentList.findIndex((obj) => obj.id === selectedObject.id); - const newIndex = direction === 'next' - ? (currentIndex + 1) % currentList.length - : (currentIndex - 1 + currentList.length) % currentList.length; - setSelectedObject({ type: selectedObject.type, id: currentList[newIndex].id }); - focusOnObject(selectedObject.type, currentList[newIndex].id); + setIsPlaying(true); + intervalRef.current = setInterval(() => { + setCurrentTimestamp((prev) => { + const nextTimestamp = prev + TimestampStep; + if (nextTimestamp >= TimestampEnd) { + clearInterval(intervalRef.current!); + setIsPlaying(false); + return prev; // Остановим на последней метке + } + return nextTimestamp; + }); + }, 100); // Интервал обновления в миллисекундах + }; + + const stopSimulation = () => { + if (intervalRef.current) { + clearInterval(intervalRef.current); + } + setIsPlaying(false); + }; + + const resetSimulation = () => { + stopSimulation(); + setCurrentTimestamp(0); + if (Simulations) updateObjects(0); // Сброс объектов к начальной метке }; return ( -
+
-
- +
+ - + {baseStations.map((baseStation) => ( handleObjectClick('baseStation', baseStation.id)} - isSelected={selectedObject?.type === 'baseStation' && selectedObject.id === baseStation.id} position={baseStation.position} + // @ts-ignore + baseStationName={baseStation.name} /> ))} {drones.map((drone) => ( + // @ts-ignore handleObjectClick('drone', drone.id)} - isSelected={selectedObject?.type === 'drone' && selectedObject.id === drone.id} /> ))} - {drones.flatMap((drone) => ( - baseStations.map((baseStation) => { - const distance = Math.sqrt( - Math.pow(drone.position[0] - baseStation.position[0], 2) + - Math.pow(drone.position[1] - baseStation.position[1], 2) + - Math.pow(drone.position[2] - baseStation.position[2], 2) - ); - - if (distance <= drone.signalRadius && distance <= baseStation.signalRadius) { - return ( - - ); - } - return null; - }) - ))} - {baseStations.map((baseStation) => ( - baseStation.signalRadius > 0 && ( - - - - - ) - ))} - {drones.map((drone) => ( - drone.signalRadius > 0 && ( - - - - - ) - ))}
-
- - +
+ + +
-
); }; @@ -344,6 +301,10 @@ const DroneModel = ({ position, droneName, onClick, isSelected }: { position: [n )} + + + + ); }; diff --git a/src/usn-frontend/src/app/pages/simulations/page.tsx b/src/usn-frontend/src/app/pages/simulations/page.tsx index 8aca197..1485f90 100644 --- a/src/usn-frontend/src/app/pages/simulations/page.tsx +++ b/src/usn-frontend/src/app/pages/simulations/page.tsx @@ -1,4 +1,5 @@ "use client"; +import { IPlayerSimulationPart } from '@/app/components/Player/Model'; import InitPlayer from '@/app/components/Player/Player'; import { BaseStation, Drone } from '@/app/components/Threejs/Models'; import ThreeJsInstance from '@/app/components/Threejs/ThreeJsInstance'; @@ -8,7 +9,7 @@ import React, { useEffect, useState } from 'react'; const Simulations: React.FC = () => { const [activeSimulationWindow, setActiveSimulationWindow] = useState(false); const [mathServer, setMathServer] = useState(""); - const [simulationDto, setSimulationDto] = useState({}); + const [simulationDto, setSimulationDto] = useState(); const ActiveSimulation = (value: boolean, Drones : Drone[], CGS: BaseStation[]) => { // Используя mathServer - отправляем массив данных @@ -20,7 +21,7 @@ const Simulations: React.FC = () => { position: drone.position, freq: drone.frequency, radius: drone.signalRadius, - endpoints: [[0, 0, 1], [10, 0, 1]], // TODO: статические значения + endpoints: [[0, 5, 1], [10, 5, 1]], // TODO: статические значения speed: 1 // TODO: можно изменить при необходимости })); @@ -43,25 +44,40 @@ const Simulations: React.FC = () => { sendToMathServer(simulationData); // Устанавливает окно симуляции setActiveSimulationWindow(value); - }; + }; // Пример функции для отправки данных const sendToMathServer = (data: object) => { console.log("Sending simulation data:", JSON.stringify(data, null, 2)); - // Реализовать отправку данных, например, через fetch - fetch(mathServer, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(data) - }).then( - out => console.log(out) - // TODO: setup to end + + + const myHeaders = new Headers(); + myHeaders.append("Content-Type", "application/json"); + + const requestOptions : RequestInit = { + method: "POST", + headers: myHeaders, + body: JSON.stringify(data), + redirect: "follow" + }; + fetch(mathServer, requestOptions).then( + // TODO: setup to end + out => { + if (out.status == 200){ + // console.log(out.json()) + const val = out.json() as Promise + val.then(v => { + setSimulationDto(v) + console.log(v) + }); + } else { + console.log(out) + } + } ); }; useEffect(() => { - setMathServer("http://localhost:10000/simulation/forceRunCalc/") + setMathServer("http://localhost:10000/simulation/forceRunCalc") }, []) return ( @@ -74,7 +90,7 @@ const Simulations: React.FC = () => { Click={() => {}} TimeEnd={100} TimeStep={1} - // simulationEndedValues={null} // TODO: SET AFTER SIMULATION REALY COMPLETE + simulationEndedValues={simulationDto} // TODO: SET AFTER SIMULATION REALY COMPLETE />
: