Start start in frontend! Simulation Query

This commit is contained in:
moxitech 2024-10-12 09:04:23 +07:00
parent 44e28d8e6b
commit e698c75309
6 changed files with 203 additions and 73 deletions

View File

@ -156,6 +156,16 @@ export const DeleteSignal = (name) => {
};
};
export const RunSimulatorSignal = (id) => {
const signal = 100;
return {
signal,
data: {
id,
},
};
};

View File

@ -7,7 +7,7 @@ import HeightPoint from './model/HeightPoint';
import { RandomHeightPoint } from './helpers/generateRandomHeightPoints'
import ModalWindow from './components/Modal/Modal';
import { getCustomCookie } from '../Services/Local';
import useWebsocketConnection, { DeleteSignal, spawnJsonSignal } from '../Services/WebsocketHook';
import useWebsocketConnection, { DeleteSignal, spawnJsonSignal, RunSimulatorSignal } from '../Services/WebsocketHook';
import './Dashboard.css';
@ -781,7 +781,10 @@ const containsObjectRecursively = (parent, target) => {
</div>
<div class="btn-group me-2" role="group" aria-label="Third group">
<button type="button" class="btn btn-info">
<i class="bi-play"/>
<i class="bi-play" onClick={() => {
sendMessage(RunSimulatorSignal(getCustomCookie("userToken")))
}}/>
</button>
</div>

View File

@ -3,7 +3,10 @@ package websocket
import (
"fmt"
"moxitech/dns/package/math/simulator"
sim_queue "moxitech/dns/package/simulation"
"moxitech/dns/package/utils/randomizer"
"strconv"
"strings"
"time"
)
@ -49,75 +52,112 @@ func (o *Modulation) MirrorPayloadToSimulationStruct() Modulation {
return shadow_sim_copy
}
func (o *Modulation) RunSimulator() {
// // Пример карты высот, замените на настоящие данные
// heightData := [][]float64{
// {0, 10, 15, 20},
// {5, 15, 25, 30},
// {10, 20, 35, 40},
// {15, 25, 40, 50},
// }
// StartNewSimulation - инициирует парсинг и добавление в очередь для обработки симуляции
func (o *Modulation) StartNewSimulation(timestep int, user_id string) {
mapObj := o.Map
drones := []*simulator.Drone{}
stations := []*simulator.BaseStation{}
// // Определяем карту высот
//
// mapObj := &simulator.Map{
// Name: "Example Map",
// MinBound: [3]float64{-1000, -1000, 0},
// MaxBound: [3]float64{1000, 1000, 500},
// HeightData: heightData,
// }
//
// ? mapObj := o.Map
for i, v := range o.Objects {
if v.Params == nil {
continue
}
// // Определяем дронов
//
// drones := []*simulator.Drone{
// {
// ID: 1,
// Name: "Drone 1",
// Coords: [3]float64{100, 100, 50},
// Params: simulator.DroneParams{
// AntennaRadius: 500,
// AntennaDirection: [3]float64{1, 0, 0},
// Waypoints: [][3]float64{{200, 200, 50}},
// Speed: 10,
// MeshName: "MeshA",
// },
// },
// }
//
// // Определяем базовые станции
//
// baseStations := []*simulator.BaseStation{
// {
// ID: 1,
// Name: "BaseStation1",
// Coords: [3]float64{0, 0, 0},
// Params: simulator.BaseStationParams{
// AntennaRadius: 2000,
// AntennaDirection: [3]float64{1, 0, 0},
// },
// },
// }
//
// // Создаем симуляцию
//
// sim := &simulator.NetworkSimulation{
// Map: mapObj,
// Drones: drones,
// BaseStations: baseStations,
// TimeStep: 2,
// }
//
// // Запуск симуляции на 300 секунд
// result_sim := sim.Simulate(300)
// result := u_sorting.SortMap(result_sim)
//
// for time, state := range result {
// for localstate, f := range state {
// fmt.Printf("%v| %v sec :: %v\n", time, localstate, f)
// }
// }
params := *v.Params
if v.Type == 1 {
// Парсинг параметров для дронов
antennaDirection := [3]float64{1, 0, 0} // значение по умолчанию
if dir, ok := params["antennaDirections"]; ok && dir != "" {
directionValues := strings.Split(dir, ",")
if len(directionValues) == 3 {
antennaDirection[0], _ = strconv.ParseFloat(directionValues[0], 64)
antennaDirection[1], _ = strconv.ParseFloat(directionValues[1], 64)
antennaDirection[2], _ = strconv.ParseFloat(directionValues[2], 64)
}
}
antennaRadius := 100.0 // значение по умолчанию
if radius, ok := params["antennaRadius"]; ok && radius != "" {
antennaRadius, _ = strconv.ParseFloat(radius, 64)
}
waypoints := [][3]float64{}
if wp, ok := params["wayPoints"]; ok && wp != "" {
// Парсинг waypoints, предполагаем, что это строка вида "x1,y1,z1;x2,y2,z2"
waypointStrings := strings.Split(wp, ";")
for _, waypointStr := range waypointStrings {
coords := strings.Split(waypointStr, ",")
if len(coords) == 3 {
x, _ := strconv.ParseFloat(coords[0], 64)
y, _ := strconv.ParseFloat(coords[1], 64)
z, _ := strconv.ParseFloat(coords[2], 64)
waypoints = append(waypoints, [3]float64{x, y, z})
}
}
}
speed := 0.0
if spd, ok := params["speed"]; ok && spd != "" {
speed, _ = strconv.ParseFloat(spd, 64)
}
meshName := ""
if mesh, ok := params["meshName"]; ok {
meshName = mesh
}
drone := simulator.Drone{
ID: i,
Name: v.Name,
Coords: [3]float64{float64(v.Coords[0]), float64(v.Coords[1]), float64(v.Coords[2])},
Params: simulator.DroneParams{
AntennaRadius: antennaRadius,
AntennaDirection: antennaDirection,
Waypoints: waypoints,
Speed: speed,
MeshName: meshName,
},
}
drones = append(drones, &drone)
}
if v.Type == 2 {
// Парсинг параметров для базовых станций
antennaDirection := [3]float64{1, 0, 0} // значение по умолчанию
if dir, ok := params["antennaDirections"]; ok && dir != "" {
directionValues := strings.Split(dir, ",")
if len(directionValues) == 3 {
antennaDirection[0], _ = strconv.ParseFloat(directionValues[0], 64)
antennaDirection[1], _ = strconv.ParseFloat(directionValues[1], 64)
antennaDirection[2], _ = strconv.ParseFloat(directionValues[2], 64)
}
}
antennaRadius := 200.0 // значение по умолчанию
if radius, ok := params["antennaRadius"]; ok && radius != "" {
antennaRadius, _ = strconv.ParseFloat(radius, 64)
}
baseStation := simulator.BaseStation{
ID: i,
Name: v.Name,
Coords: [3]float64{float64(v.Coords[0]), float64(v.Coords[1]), float64(v.Coords[2])},
Params: simulator.BaseStationParams{
AntennaRadius: antennaRadius,
AntennaDirection: antennaDirection,
},
}
stations = append(stations, &baseStation)
}
}
sim := &simulator.NetworkSimulation{
Map: &mapObj.Map,
Drones: drones,
BaseStations: stations,
TimeStep: timestep,
}
sim_queue.AddSimulationTask(*sim, user_id)
}
// SpawnExampleData создает случайные данные и перезаписывает карту

View File

@ -5,6 +5,7 @@ import (
"fmt"
"moxitech/dns/entity/dto"
"moxitech/dns/internal/server/handlers/authorization"
sim_queue "moxitech/dns/package/simulation"
"os"
"runtime"
"strconv"
@ -20,6 +21,8 @@ var (
)
func SpawnServer() error {
sim_queue.Start()
go sim_queue.InvokeComplete()
app := fiber.New()
app.Use(cors.New(cors.Config{
AllowHeaders: "*",

View File

@ -230,12 +230,22 @@ func (room *WebsocketRoom) InsertMapFromMongo(name string) {
}
// RunSimulation запускает симуляцию в горутине
func (room *WebsocketRoom) RunSimulation(name string) (int, error) {
// TODO +NormalizeDataForSimulation()
func (room *WebsocketRoom) RunSimulation(message websocket.SignalMessage) (int, error) {
var parsedData struct {
UserInvoked string `json:"id"`
}
// Парсим `data` в структуру
err := json.Unmarshal(message.Data, &parsedData)
if err != nil {
return -1, fmt.Errorf("[insert] error parsing data: %v", err)
}
if parsedData.UserInvoked == "" {
return -1, fmt.Errorf("[insert] Error parse userID: %v", err)
}
roomsMutex.Lock()
defer roomsMutex.Unlock()
room.Modulation.MirrorPayloadToSimulationStruct()
return -1, nil
room.Modulation.StartNewSimulation(100, parsedData.UserInvoked)
return 0, nil
}
// NormalizeDataForSimulation - Преобразование данных для отправки в симуляцию
@ -255,6 +265,7 @@ func (room *WebsocketRoom) WebsocketAction(message []byte) (error, bool) {
fmt.Printf("[WebsocketAction] %v", err)
return fmt.Errorf("error parsing occured: %v \n waiting for signal struct", err), false
}
fmt.Println("Run collector")
room.UpdateGroupUptime()
switch Signal.Signal {
case 0:
@ -264,6 +275,7 @@ func (room *WebsocketRoom) WebsocketAction(message []byte) (error, bool) {
room.InsertObject(Signal)
return nil, true
case 2:
fmt.Println("Начата вставка объекта")
room.InsertObject(Signal)
return nil, true
case 3:
@ -287,6 +299,8 @@ func (room *WebsocketRoom) WebsocketAction(message []byte) (error, bool) {
case 33:
// SYNC SIGNAL
case 100:
fmt.Println("Запуск симуляции : ", Signal)
room.RunSimulation(Signal)
case 101:
// room.StoreMongo(Signal)

View File

@ -0,0 +1,60 @@
package sim_queue
import (
"encoding/json"
"fmt"
"moxitech/dns/package/math/simulator"
"net/http"
)
var (
AddChannel = make(chan simulator.NetworkSimulation)
CompleteChannel = make(chan *simulationResult)
)
type simulationResult struct {
Sim *simulator.NetworkSimulation
UserID string
}
// AddSimulationTask adds a network simulation to the queue and runs it in a goroutine.
func AddSimulationTask(sim simulator.NetworkSimulation, userID string) {
AddChannel <- sim
CompleteChannel <- &simulationResult{Sim: &sim, UserID: userID}
}
// InvokeComplete listens for completed simulations, serializes them to JSON, and sends to a specified endpoint.
func InvokeComplete() {
for result := range CompleteChannel {
go func(result *simulationResult) {
jsonData, err := json.Marshal(result.Sim)
if err != nil {
fmt.Println("Error serializing simulation result:", err)
return
}
url := fmt.Sprintf("http://socket:9091/storeEvent?client_id=%s&message=%s", result.UserID, string(jsonData))
resp, err := http.Get(url)
if err != nil {
fmt.Println("Error sending simulation result:", err)
return
}
// database.Instance.InsertIntoSimulations(jsonData)
defer resp.Body.Close()
}(result)
}
}
// Start starts listening on the channels to manage simulations.
func Start() {
go func() {
for sim := range AddChannel {
go runSimulation(sim)
}
}()
}
// runSimulation runs a simulation and then sends it to the CompleteChannel.
func runSimulation(sim simulator.NetworkSimulation) {
sim.Simulate(sim.TimeStep) // Run the simulation for 300 iterations (as an example)
CompleteChannel <- &simulationResult{Sim: &sim}
}