Insert, update, exampling, delete over websocket
This commit is contained in:
parent
fa4be8d5ff
commit
f2e9c6f38f
1
.env
1
.env
@ -6,6 +6,7 @@ MONGO_INITDB_ROOT_PASSWORD=moxitech
|
||||
MONGO_INITDB_DATABASE=drone-network-simulator
|
||||
MONGO_INITDB_SIM_COLLECTION=simulations
|
||||
MONGO_INITDB_SIM_HIST_COLLECTION=simulations_history
|
||||
MONGO_INITDB_MAP_COLLECTION=map_templates
|
||||
|
||||
POSTGRES_DB=moxitech
|
||||
POSTGRES_USER=moxitech
|
||||
|
@ -1,6 +1,10 @@
|
||||
package websocket
|
||||
|
||||
import "moxitech/dns/package/math/simulator"
|
||||
import (
|
||||
"moxitech/dns/package/math/simulator"
|
||||
"moxitech/dns/package/utils/randomizer"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Modulation struct {
|
||||
Map *MapPartial `json:"map"`
|
||||
@ -21,6 +25,91 @@ type SystemObject struct {
|
||||
Params *map[string]string `json:"params"`
|
||||
}
|
||||
|
||||
func (o *SystemObject) Delete() {
|
||||
|
||||
// DeleteObjectIfExists удаляет объект если он найден
|
||||
func (o *Modulation) DeleteObjectIfExists(name string) {
|
||||
if o.Objects == nil {
|
||||
return
|
||||
}
|
||||
for i, obj := range o.Objects {
|
||||
if obj.Name == name {
|
||||
o.Objects = append(o.Objects[:i], o.Objects[i+1:]...)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SpawnExampleData создает случайные данные и перезаписывает карту
|
||||
func (o *Modulation) SpawnExampleData() bool {
|
||||
o.Map = &MapPartial{
|
||||
Map: simulator.MakeRandomMap(),
|
||||
Name: "example starter map",
|
||||
Changed: false,
|
||||
}
|
||||
o.Objects = make([]*SystemObject, 0)
|
||||
o.Ts_update = time.Now().Unix()
|
||||
return true
|
||||
}
|
||||
|
||||
// AddObject добавляет объект станции или дрона
|
||||
func (o *Modulation) AddObject(name string, obj_type int, coords [3]int, params map[string]string) {
|
||||
if obj_type != 1 && obj_type != 2 {
|
||||
// Значит объект не станция или не дрон
|
||||
return
|
||||
}
|
||||
if o.Objects == nil {
|
||||
o.Objects = make([]*SystemObject, 0)
|
||||
}
|
||||
if o.ObjectExists(name) {
|
||||
name = name + " " + randomizer.GenerateRandomString()
|
||||
}
|
||||
obj := &SystemObject{
|
||||
Name: name,
|
||||
Type: obj_type,
|
||||
Coords: coords,
|
||||
Params: ¶ms,
|
||||
}
|
||||
o.Objects = append(o.Objects, obj)
|
||||
}
|
||||
|
||||
// UpdateObject обновляет объект станции или дрона по имени
|
||||
func (o *Modulation) UpdateObject(name string, obj_type int, coords [3]int, params map[string]string) {
|
||||
if obj_type != 1 && obj_type != 2 {
|
||||
// Значит объект не станция или не дрон
|
||||
return
|
||||
}
|
||||
if o.Objects == nil {
|
||||
o.Objects = make([]*SystemObject, 0)
|
||||
}
|
||||
ok := o.ObjectExists(name)
|
||||
if !ok {
|
||||
o.AddObject(name, obj_type, coords, params)
|
||||
return
|
||||
}
|
||||
obj := &SystemObject{
|
||||
Name: name,
|
||||
Type: obj_type,
|
||||
Coords: coords,
|
||||
Params: ¶ms,
|
||||
}
|
||||
o.DeleteObjectIfExists(name)
|
||||
o.Objects = append(o.Objects, obj)
|
||||
}
|
||||
|
||||
// GetObjects вернет все объекты карты
|
||||
func (o *Modulation) GetObjects() []*SystemObject {
|
||||
return o.Objects
|
||||
}
|
||||
|
||||
// ObjectExists проверит есть ли объект с заданным (именем | id) на карте
|
||||
func (o *Modulation) ObjectExists(name string) bool {
|
||||
if o.Objects == nil {
|
||||
o.Objects = make([]*SystemObject, 0)
|
||||
return false
|
||||
}
|
||||
for _, obj := range o.Objects {
|
||||
if obj.Name == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -91,18 +91,24 @@ func CreateOrConnectSocket(c *websocket.Conn) {
|
||||
}
|
||||
// LOGGING :
|
||||
fmt.Printf("Received message from user %s: %s\n", userToken, msg)
|
||||
room.UpdateGroupUptime()
|
||||
// Обрабатываем сообщение
|
||||
|
||||
data, err := json.Marshal(Rooms)
|
||||
err, ok = room.WebsocketAction(msg)
|
||||
if err != nil {
|
||||
fmt.Printf("Error marshal json: %v\n", err)
|
||||
err = c.WriteMessage(websocket.TextMessage, []byte(fmt.Sprintf("%v", err)))
|
||||
if err != nil {
|
||||
fmt.Printf("Error writing message: %v\n", err)
|
||||
}
|
||||
}
|
||||
err = c.WriteMessage(websocket.TextMessage, []byte(fmt.Sprintf("%v", string(data))))
|
||||
if err != nil {
|
||||
fmt.Printf("Error writing message: %v\n", err)
|
||||
if ok {
|
||||
// Обрабатываем сообщение
|
||||
data, err := json.Marshal(Rooms[groupHash])
|
||||
if err != nil {
|
||||
fmt.Printf("Error marshal json: %v\n", err)
|
||||
}
|
||||
err = c.WriteMessage(websocket.TextMessage, []byte(fmt.Sprintf("%v", string(data))))
|
||||
if err != nil {
|
||||
fmt.Printf("Error writing message: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Закрываем соединение при выходе
|
||||
|
@ -5,7 +5,8 @@ import (
|
||||
"fmt"
|
||||
"moxitech/dns/entity/websocket"
|
||||
"moxitech/dns/package/math/simulator"
|
||||
u_sorting "moxitech/dns/package/utils/sorting"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
@ -79,102 +80,193 @@ func (room *WebsocketRoom) FlushGroupRequest() {
|
||||
// ... ДОБАВИТЬ ЛОГИКУ ИЗ WEBSOCKET ACTION ...
|
||||
//
|
||||
|
||||
// FlushGroupRequest сохраняет результат вычислений группы
|
||||
// @GroupEntity : WS entity -> сущность группы с данными и вычислениями
|
||||
// func (room *WebsocketRoom) DeleteMapObjectRequest(name string) {
|
||||
// roomsMutex.Lock()
|
||||
// defer roomsMutex.Unlock()
|
||||
// room.Modulation.Objects.DeleteObject(name)
|
||||
// DeleteMapObjectRequest удаляет определенный объект
|
||||
func (room *WebsocketRoom) DeleteMapObjectRequest(message websocket.SignalMessage) {
|
||||
var parsedData struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
err := json.Unmarshal(message.Data, &parsedData)
|
||||
if err != nil {
|
||||
fmt.Printf("[delete] error parsing data: %v", err)
|
||||
}
|
||||
|
||||
// }
|
||||
roomsMutex.Lock()
|
||||
defer roomsMutex.Unlock()
|
||||
room.Modulation.DeleteObjectIfExists(parsedData.Name)
|
||||
}
|
||||
|
||||
// InsertObject вставляет базовые случайные данные в симуляцию
|
||||
func (room *WebsocketRoom) InsertObject(message websocket.SignalMessage) error {
|
||||
// Тип объекта (тип сигнала)
|
||||
type_obj := message.Signal
|
||||
// Определяем структуру для данных в поле `data`
|
||||
var parsedData struct {
|
||||
Name string `json:"name"`
|
||||
Params map[string]string `json:"params"`
|
||||
}
|
||||
|
||||
// Парсим `data` в структуру
|
||||
err := json.Unmarshal(message.Data, &parsedData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("[insert] error parsing data: %v", err)
|
||||
}
|
||||
|
||||
// Получаем значения name и params
|
||||
name := parsedData.Name
|
||||
params := parsedData.Params
|
||||
|
||||
// Проверяем наличие координат в параметрах
|
||||
if params["coords"] == "" {
|
||||
return fmt.Errorf("[insert] coords is empty")
|
||||
}
|
||||
|
||||
// Разделяем строку координат на отдельные элементы
|
||||
coordinateStrings := strings.Split(params["coords"], ",")
|
||||
|
||||
// Инициализируем массив для хранения координат
|
||||
coordinates := make([]int, len(coordinateStrings))
|
||||
|
||||
// Преобразуем каждую координату в целое число
|
||||
for i, coord := range coordinateStrings {
|
||||
parsedCoord, err := strconv.Atoi(strings.TrimSpace(coord))
|
||||
if err != nil {
|
||||
return fmt.Errorf("[insert] invalid coordinate: %s", coord)
|
||||
}
|
||||
coordinates[i] = parsedCoord
|
||||
}
|
||||
params["coords"] = ""
|
||||
// Добавляем объект в комнату
|
||||
roomsMutex.Lock()
|
||||
defer roomsMutex.Unlock()
|
||||
room.Modulation.AddObject(name, type_obj, [3]int{coordinates[0], coordinates[1], coordinates[2]}, params)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateObjectRequest вставляет базовые случайные данные в симуляцию
|
||||
func (room *WebsocketRoom) UpdateObjectRequest(message websocket.SignalMessage) error {
|
||||
// Тип объекта (тип сигнала)
|
||||
type_obj := message.Signal - 20
|
||||
// Определяем структуру для данных в поле `data`
|
||||
var parsedData struct {
|
||||
Name string `json:"name"`
|
||||
Params map[string]string `json:"params"`
|
||||
}
|
||||
|
||||
// Парсим `data` в структуру
|
||||
err := json.Unmarshal(message.Data, &parsedData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("[insert] error parsing data: %v", err)
|
||||
}
|
||||
|
||||
// Получаем значения name и params
|
||||
name := parsedData.Name
|
||||
params := parsedData.Params
|
||||
|
||||
// Проверяем наличие координат в параметрах
|
||||
if params["coords"] == "" {
|
||||
return fmt.Errorf("[insert] coords is empty")
|
||||
}
|
||||
|
||||
// Разделяем строку координат на отдельные элементы
|
||||
coordinateStrings := strings.Split(params["coords"], ",")
|
||||
|
||||
// Инициализируем массив для хранения координат
|
||||
coordinates := make([]int, len(coordinateStrings))
|
||||
|
||||
// Преобразуем каждую координату в целое число
|
||||
for i, coord := range coordinateStrings {
|
||||
parsedCoord, err := strconv.Atoi(strings.TrimSpace(coord))
|
||||
if err != nil {
|
||||
return fmt.Errorf("[insert] invalid coordinate: %s", coord)
|
||||
}
|
||||
coordinates[i] = parsedCoord
|
||||
}
|
||||
params["coords"] = ""
|
||||
// Добавляем объект в комнату
|
||||
roomsMutex.Lock()
|
||||
defer roomsMutex.Unlock()
|
||||
|
||||
room.Modulation.AddObject(name, type_obj, [3]int{coordinates[0], coordinates[1], coordinates[2]}, params)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// InsertBasicData вставляет базовые случайные данные в симуляцию
|
||||
func (room *WebsocketRoom) InsertExampleData() {
|
||||
roomsMutex.Lock()
|
||||
defer roomsMutex.Unlock()
|
||||
room.Modulation.SpawnExampleData()
|
||||
}
|
||||
|
||||
// InsertMapFromJson вставляет высоты и прочие данные карты в симуляцию, по шаблону
|
||||
func (room *WebsocketRoom) InsertMapFromJson(template string) {
|
||||
// TODO
|
||||
roomsMutex.Lock()
|
||||
defer roomsMutex.Unlock()
|
||||
room.Modulation.DeleteObjectIfExists(template)
|
||||
}
|
||||
|
||||
// InsertMapFromMongo вставляет высоты и прочие данные карты в симуляцию, из mongo по названию
|
||||
func (room *WebsocketRoom) InsertMapFromMongo(name string) {
|
||||
// TODO
|
||||
roomsMutex.Lock()
|
||||
defer roomsMutex.Unlock()
|
||||
room.Modulation.DeleteObjectIfExists(name)
|
||||
}
|
||||
|
||||
// RunSimulation запускает симуляцию в горутине
|
||||
func (room *WebsocketRoom) RunSimulation(name string) {
|
||||
// TODO +NormalizeDataForSimulation()
|
||||
roomsMutex.Lock()
|
||||
defer roomsMutex.Unlock()
|
||||
room.Modulation.DeleteObjectIfExists(name)
|
||||
}
|
||||
|
||||
// NormalizeDataForSimulation - Преобразование данных для отправки в симуляцию
|
||||
func (room *WebsocketRoom) NormalizeDataForSimulation() {
|
||||
// func (room *WebsocketRoom) NormalizeDataForSimulation() {
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
// InitBroadCast - Инициализация раздачи контента участникам комнаты
|
||||
func (room *WebsocketRoom) InitBroadCast() {
|
||||
|
||||
}
|
||||
|
||||
func SpawnSimulation(heightData [][]float64) {
|
||||
// Пример карты высот, замените на настоящие данные
|
||||
// heightData := [][]float64{
|
||||
// {0, 10, 15, 20},
|
||||
// {5, 15, 25, 30},
|
||||
// {10, 20, 35, 40},
|
||||
// {15, 25, 40, 50},
|
||||
// }
|
||||
|
||||
// Определяем карту высот
|
||||
mapObj := &simulator.Map{
|
||||
Name: "Example Map",
|
||||
MinBound: [3]float64{-1000, -1000, 0},
|
||||
MaxBound: [3]float64{1000, 1000, 500},
|
||||
HeightData: heightData,
|
||||
}
|
||||
// Определяем дронов
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (room *WebsocketRoom) WebsocketAction(message []byte) {
|
||||
func (room *WebsocketRoom) WebsocketAction(message []byte) (error, bool) {
|
||||
var Signal websocket.SignalMessage
|
||||
err := json.Unmarshal(message, &Signal)
|
||||
if err != nil {
|
||||
fmt.Printf("[WebsocketAction] %v", err)
|
||||
return fmt.Errorf("error parsing occured: %v \n waiting for signal struct", err), false
|
||||
}
|
||||
room.UpdateGroupUptime()
|
||||
switch Signal.Signal {
|
||||
case 0:
|
||||
room.UpdateGroupUptime()
|
||||
return nil, false
|
||||
case 1:
|
||||
room.InsertObject(Signal)
|
||||
return nil, true
|
||||
case 2:
|
||||
room.InsertObject(Signal)
|
||||
return nil, true
|
||||
case 3:
|
||||
|
||||
room.DeleteMapObjectRequest(Signal)
|
||||
return nil, true
|
||||
case 21:
|
||||
// Update Base Station
|
||||
room.UpdateObjectRequest(Signal)
|
||||
return nil, true
|
||||
|
||||
case 22:
|
||||
// Update Drone
|
||||
room.UpdateObjectRequest(Signal)
|
||||
return nil, true
|
||||
|
||||
case 30:
|
||||
// Init example data
|
||||
room.InsertExampleData()
|
||||
case 31:
|
||||
case 32:
|
||||
|
||||
@ -197,4 +289,5 @@ func (room *WebsocketRoom) WebsocketAction(message []byte) {
|
||||
// Запуск симуляции :: 100
|
||||
|
||||
// Пользователь исключен :: 301
|
||||
return nil, false
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package simulator
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"moxitech/dns/package/math/distance"
|
||||
"sync"
|
||||
)
|
||||
@ -259,3 +260,29 @@ func MakeExampleMap() Map {
|
||||
}
|
||||
return mapObj
|
||||
}
|
||||
|
||||
// Создает полностью случаную карту
|
||||
func MakeRandomMap() Map {
|
||||
// Задаём случайное количество высот
|
||||
numRows := rand.Intn(50) + 1 // Случайное количество строк (от 1 до 50)
|
||||
numCols := rand.Intn(50) + 1 // Случайное количество столбцов (от 1 до 50)
|
||||
|
||||
// Инициализируем данные высот
|
||||
heightData := make([][]float64, numRows)
|
||||
for i := range heightData {
|
||||
heightData[i] = make([]float64, numCols)
|
||||
for j := range heightData[i] {
|
||||
// Случайные значения высот
|
||||
heightData[i][j] = rand.Float64() * 100 // высоты от 0 до 100
|
||||
}
|
||||
}
|
||||
|
||||
// Определяем карту высот
|
||||
mapObj := Map{
|
||||
Name: "RandomGeneratedMap",
|
||||
MinBound: [3]float64{-2000, -2000, 0}, // Минимальные координаты
|
||||
MaxBound: [3]float64{2000, 2000, 500}, // Максимальные координаты
|
||||
HeightData: heightData, // Случайные высоты
|
||||
}
|
||||
return mapObj
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user