using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using RobotNet.MapManager.Data; using RobotNet.MapManager.Services; using RobotNet.MapShares; using RobotNet.MapShares.Dtos; using RobotNet.MapShares.Models; using RobotNet.Shares; using System.Text.Json; namespace RobotNet.MapManager.Controllers; [Route("api/[controller]")] [ApiController] [Authorize] public class MapsDataController(MapEditorDbContext MapDb, LoggerController Logger) : ControllerBase { [HttpGet] [Route("{id}")] public async Task> GetMapData(Guid id) { var map = await MapDb.Maps.FindAsync(id); if (map is null) return new(false, $"Không tìm thấy bản đồ: {id}"); var result = new MessageResult(true) { Data = new() { Id = map.Id, Name = map.Name, OriginX = map.OriginX, OriginY = map.OriginY, Resolution = map.Resolution, ImageHeight = map.ImageHeight, ImageWidth = map.ImageWidth, Active = map.Active, Nodes = [.. MapDb.Nodes.Where(node => node.MapId == id).Select(node => new NodeDto() { Id = node.Id, MapId = node.MapId, Name = node.Name, Theta = node.Theta, X = node.X, Y = node.Y, AllowedDeviationXy = node.AllowedDeviationXy, AllowedDeviationTheta = node.AllowedDeviationTheta, Actions = node.Actions, })], Edges = [.. MapDb.Edges.Where(edge => edge.MapId == id).Select(edge => new EdgeDto() { Id = edge.Id, MapId = edge.MapId, StartNodeId = edge.StartNodeId, EndNodeId = edge.EndNodeId, MaxSpeed = edge.MaxSpeed, MaxHeight = edge.MaxHeight, MinHeight = edge.MinHeight, DirectionAllowed = edge.DirectionAllowed, RotationAllowed = edge.RotationAllowed, TrajectoryDegree = edge.TrajectoryDegree, ControlPoint1X = edge.ControlPoint1X, ControlPoint1Y = edge.ControlPoint1Y, ControlPoint2X = edge.ControlPoint2X, ControlPoint2Y = edge.ControlPoint2Y, MaxRotationSpeed = edge.MaxRotationSpeed, Actions = edge.Actions, AllowedDeviationXy = edge.AllowedDeviationXy, AllowedDeviationTheta = edge.AllowedDeviationTheta, })], Zones = [.. MapDb.Zones.Where(zone => zone.MapId == id).Select(zone => new ZoneDto() { Id = zone.Id, MapId = zone.MapId, Type = zone.Type, Name = zone.Name, X1 = zone.X1, X2 = zone.X2, Y1 = zone.Y1, Y2 = zone.Y2, X3 = zone.X3, Y3 = zone.Y3, X4 = zone.X4, Y4 = zone.Y4, }).OrderBy(z => z.Type)], Elements = [.. MapDb.Elements.Where(el => el.MapId == id).Select(element => new ElementDto() { Id = element.Id, MapId = element.MapId, ModelId = element.ModelId, Name = element.Name, NodeId = element.NodeId, OffsetX = element.OffsetX, OffsetY = element.OffsetY, IsOpen = element.IsOpen, Content = element.Content, })], Actions = [.. MapDb.Actions.Where(a => a.MapId == id).Select(action => new ActionDto() { Id = action.Id, MapId = action.MapId, Name = action.Name, Content = action.Content, })] } }; return result; } [HttpPut] [Route("{id}/updates")] public async Task>> Updates(Guid id, MapEditorBackupModel model) { if (model == null || model.Steps == null) return new(false, "Dữ liệu đầu vào không hợp lệ"); try { var map = await MapDb.Maps.FindAsync(id); if (map == null) return new(false, $"Không tồn tại map id = {id}"); List EdgeDtos = []; foreach (var step in model.Steps) { switch (step.Type) { case MapEditorBackupType.Node: PositionBackup? nodeUpdate = JsonSerializer.Deserialize(step.Obj.ToString() ?? "", JsonOptionExtends.Read); if (nodeUpdate is not null) { var nodeDb = await MapDb.Nodes.FindAsync(step.Id); if (nodeDb is not null) { nodeDb.X = nodeUpdate.X; nodeDb.Y = nodeUpdate.Y; } } break; case MapEditorBackupType.ControlPoint1Edge: PositionBackup? controlPoint1 = JsonSerializer.Deserialize(step.Obj.ToString() ?? "", JsonOptionExtends.Read); if (controlPoint1 is not null) { var edgeDb = await MapDb.Edges.FindAsync(step.Id); if (edgeDb is not null) { edgeDb.ControlPoint1X = controlPoint1.X; edgeDb.ControlPoint1Y = controlPoint1.Y; } } break; case MapEditorBackupType.ControlPoint2Edge: PositionBackup? controlPoint2 = JsonSerializer.Deserialize(step.Obj.ToString() ?? "", JsonOptionExtends.Read); if (controlPoint2 is not null) { var edgeDb = await MapDb.Edges.FindAsync(step.Id); if (edgeDb is not null) { edgeDb.ControlPoint2X = controlPoint2.X; edgeDb.ControlPoint2Y = controlPoint2.Y; } } break; case MapEditorBackupType.Zone: ZoneShapeBackup? zoneUpdate = JsonSerializer.Deserialize(step.Obj.ToString() ?? "", JsonOptionExtends.Read); if (zoneUpdate is not null) { var zoneDb = await MapDb.Zones.FindAsync(step.Id); if (zoneDb is not null) { zoneDb.X1 = zoneUpdate.X1; zoneDb.Y1 = zoneUpdate.Y1; zoneDb.X2 = zoneUpdate.X2; zoneDb.Y2 = zoneUpdate.Y2; zoneDb.X3 = zoneUpdate.X3; zoneDb.Y3 = zoneUpdate.Y3; zoneDb.X4 = zoneUpdate.X4; zoneDb.Y4 = zoneUpdate.Y4; } } break; case MapEditorBackupType.MoveEdge: List? edgesUpdate = JsonSerializer.Deserialize>(step.Obj.ToString() ?? "", JsonOptionExtends.Read); if (edgesUpdate is not null && edgesUpdate.Count > 0) { foreach (var edgeUpate in edgesUpdate) { var edgeDb = await MapDb.Edges.FindAsync(edgeUpate.Id); if (edgeDb is not null) { var startNode = await MapDb.Nodes.FindAsync(edgeDb.StartNodeId); var endNode = await MapDb.Nodes.FindAsync(edgeDb.EndNodeId); if (startNode is not null && endNode is not null) { startNode.X = edgeUpate.StartX; startNode.Y = edgeUpate.StartY; endNode.X = edgeUpate.EndX; endNode.Y = edgeUpate.EndY; } edgeDb.ControlPoint1X = edgeUpate.ControlPoint1X; edgeDb.ControlPoint1Y = edgeUpate.ControlPoint1Y; edgeDb.ControlPoint2X = edgeUpate.ControlPoint2X; edgeDb.ControlPoint2Y = edgeUpate.ControlPoint2Y; } } } break; case MapEditorBackupType.Copy: List? edgesCopy = JsonSerializer.Deserialize>(step.Obj.ToString() ?? "", JsonOptionExtends.Read); if (edgesCopy is not null && edgesCopy.Count > 0) { Dictionary CreateNewNode = []; foreach (var edgeCopy in edgesCopy) { if (!CreateNewNode.TryGetValue(edgeCopy.StartNodeId, out _)) { var startNode = await MapDb.Nodes.FindAsync(edgeCopy.StartNodeId); var newStartNode = await MapDb.Nodes.AddAsync(new Node() { MapId = edgeCopy.MapId, Name = map.NodeNameAutoGenerate ? $"{map.NodeNameTemplateDefault}{++map.NodeCount}" : string.Empty, X = edgeCopy.X1, Y = edgeCopy.Y1, Theta = startNode is not null ? startNode.Theta : 0, Actions = startNode is not null ? startNode.Actions : "", AllowedDeviationXy = startNode is not null ? startNode.AllowedDeviationXy : map.NodeAllowedDeviationXyDefault, AllowedDeviationTheta = startNode is not null ? startNode.AllowedDeviationTheta : map.NodeAllowedDeviationThetaDefault, }); CreateNewNode.Add(edgeCopy.StartNodeId, newStartNode.Entity); } if (!CreateNewNode.TryGetValue(edgeCopy.EndNodeId, out _)) { var endNode = await MapDb.Nodes.FindAsync(edgeCopy.EndNodeId); var newEndNode = await MapDb.Nodes.AddAsync(new Node() { MapId = edgeCopy.MapId, Name = map.NodeNameAutoGenerate ? $"{map.NodeNameTemplateDefault}{++map.NodeCount}" : string.Empty, X = edgeCopy.X2, Y = edgeCopy.Y2, Theta = endNode is not null ? endNode.Theta : 0, Actions = endNode is not null ? endNode.Actions : "", AllowedDeviationXy = endNode is not null ? endNode.AllowedDeviationXy : map.NodeAllowedDeviationXyDefault, AllowedDeviationTheta = endNode is not null ? endNode.AllowedDeviationTheta : map.NodeAllowedDeviationThetaDefault, }); CreateNewNode.Add(edgeCopy.EndNodeId, newEndNode.Entity); } var newEdge = await MapDb.Edges.AddAsync(new Edge() { MapId = edgeCopy.MapId, StartNodeId = CreateNewNode[edgeCopy.StartNodeId] is null ? Guid.Empty : CreateNewNode[edgeCopy.StartNodeId].Id, EndNodeId = CreateNewNode[edgeCopy.EndNodeId] is null ? Guid.Empty : CreateNewNode[edgeCopy.EndNodeId].Id, TrajectoryDegree = edgeCopy.TrajectoryDegree, ControlPoint1X = edgeCopy.ControlPoint1X, ControlPoint1Y = edgeCopy.ControlPoint1Y, ControlPoint2X = edgeCopy.ControlPoint2X, ControlPoint2Y = edgeCopy.ControlPoint2Y, DirectionAllowed = edgeCopy.DirectionAllowed, RotationAllowed = edgeCopy.RotationAllowed, MaxSpeed = edgeCopy.MaxSpeed, MaxRotationSpeed = edgeCopy.MaxRotationSpeed, MaxHeight = edgeCopy.MaxHeight, MinHeight = edgeCopy.MinHeight, Actions = edgeCopy.Actions, AllowedDeviationTheta = edgeCopy.AllowedDeviationTheta, AllowedDeviationXy = edgeCopy.AllowedDeviationXy, }); EdgeDtos.Add(new() { Id = newEdge.Entity.Id, MapId = newEdge.Entity.MapId, StartNodeId = newEdge.Entity.StartNodeId, EndNodeId = newEdge.Entity.EndNodeId, TrajectoryDegree = newEdge.Entity.TrajectoryDegree, ControlPoint1X = newEdge.Entity.ControlPoint1X, ControlPoint1Y = newEdge.Entity.ControlPoint1Y, ControlPoint2X = newEdge.Entity.ControlPoint2X, ControlPoint2Y = newEdge.Entity.ControlPoint2Y, DirectionAllowed = newEdge.Entity.DirectionAllowed, RotationAllowed = newEdge.Entity.RotationAllowed, MaxSpeed = newEdge.Entity.MaxSpeed, MaxRotationSpeed = newEdge.Entity.MaxRotationSpeed, MaxHeight = newEdge.Entity.MaxHeight, MinHeight = newEdge.Entity.MinHeight, Actions = newEdge.Entity.Actions, AllowedDeviationXy = newEdge.Entity.AllowedDeviationXy, AllowedDeviationTheta = newEdge.Entity.AllowedDeviationTheta, StartNode = new NodeDto() { Id = CreateNewNode[edgeCopy.StartNodeId].Id, Name = CreateNewNode[edgeCopy.StartNodeId].Name, MapId = CreateNewNode[edgeCopy.StartNodeId].MapId, Theta = CreateNewNode[edgeCopy.StartNodeId].Theta, X = CreateNewNode[edgeCopy.StartNodeId].X, Y = CreateNewNode[edgeCopy.StartNodeId].Y, AllowedDeviationXy = CreateNewNode[edgeCopy.StartNodeId].AllowedDeviationXy, AllowedDeviationTheta = CreateNewNode[edgeCopy.StartNodeId].AllowedDeviationTheta, Actions = CreateNewNode[edgeCopy.StartNodeId].Actions, }, EndNode = new NodeDto() { Id = CreateNewNode[edgeCopy.EndNodeId].Id, Name = CreateNewNode[edgeCopy.EndNodeId].Name, MapId = CreateNewNode[edgeCopy.EndNodeId].MapId, Theta = CreateNewNode[edgeCopy.EndNodeId].Theta, X = CreateNewNode[edgeCopy.EndNodeId].X, Y = CreateNewNode[edgeCopy.EndNodeId].Y, AllowedDeviationXy = CreateNewNode[edgeCopy.EndNodeId].AllowedDeviationXy, AllowedDeviationTheta = CreateNewNode[edgeCopy.EndNodeId].AllowedDeviationTheta, Actions = CreateNewNode[edgeCopy.EndNodeId].Actions, }, }); } } break; case MapEditorBackupType.SplitNode: var nodeSplit = await MapDb.Nodes.FindAsync(step.Id); if (nodeSplit is not null) { SplitNodeBackup? SplitNodeUpdate = JsonSerializer.Deserialize(step.Obj.ToString() ?? "", JsonOptionExtends.Read); if (SplitNodeUpdate is not null) { foreach (var data in SplitNodeUpdate.EdgeSplit) { var edge = await MapDb.Edges.FindAsync(data.Key); if (edge is not null) { var newNode = new Node() { Id = data.Value.Id, Name = data.Value.Name, X = data.Value.X, Y = data.Value.Y, Theta = data.Value.Theta, MapId = data.Value.MapId, AllowedDeviationXy = data.Value.AllowedDeviationXy, AllowedDeviationTheta = data.Value.AllowedDeviationTheta, Actions = data.Value.Actions, }; if (edge.StartNodeId == nodeSplit.Id) edge.StartNodeId = newNode.Id; else if (edge.EndNodeId == nodeSplit.Id) edge.EndNodeId = newNode.Id; else continue; await MapDb.Nodes.AddAsync(newNode); } } } } break; case MapEditorBackupType.MergeNode: var nodemerge = await MapDb.Nodes.FindAsync(step.Id); if (nodemerge is not null) { MergeNodeUpdate? MergeNodeUpdate = JsonSerializer.Deserialize(step.Obj.ToString() ?? "", JsonOptionExtends.Read); if (MergeNodeUpdate is not null) { foreach (var data in MergeNodeUpdate.EdgesMerge) { var edge = await MapDb.Edges.FindAsync(data.Key); if (edge is not null) { var rmNode = await MapDb.Nodes.FindAsync(data.Value); if (edge.StartNodeId == data.Value) edge.StartNodeId = nodemerge.Id; else if (edge.EndNodeId == data.Value) edge.EndNodeId = nodemerge.Id; if (rmNode is not null) MapDb.Nodes.Remove(rmNode); } } } } break; } } await MapDb.SaveChangesAsync(); Logger.Info($"User {HttpContext.User.Identity?.Name} đã cập nhật dữ liệu cho bản đồ: {map.Name} - {map.Id}"); return new(true) { Data = EdgeDtos }; } catch (Exception ex) { Logger.Warning($"Updates: Hệ thống có lỗi xảy ra - {ex.Message}"); return new(false, "Hệ thống có lỗi xảy ra"); } } }