181 lines
6.1 KiB
C#
181 lines
6.1 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using RobotNet10.MapEditor.Shared.DTOs.Requests;
|
|
using RobotNet10.MapManager.Data;
|
|
|
|
namespace RobotNet10.MapManager.Services;
|
|
|
|
/// <summary>
|
|
/// Service implementation for managing stations
|
|
/// </summary>
|
|
public class StationService(MapDbContext context) : IStationService
|
|
{
|
|
private readonly MapDbContext _context = context;
|
|
|
|
public async Task<Station> CreateAsync(CreateStationRequest request)
|
|
{
|
|
// Check if station ID already exists in this level
|
|
var exists = await _context.Stations
|
|
.AnyAsync(s => s.LevelId == request.LayoutLevelId && s.StationId == request.StationId);
|
|
|
|
if (exists)
|
|
{
|
|
throw new InvalidOperationException(
|
|
$"Station with ID '{request.StationId}' already exists in this layout level");
|
|
}
|
|
|
|
using var transaction = await _context.Database.BeginTransactionAsync();
|
|
try
|
|
{
|
|
var station = new Station
|
|
{
|
|
LevelId = request.LayoutLevelId,
|
|
StationId = request.StationId,
|
|
StationName = request.StationName,
|
|
StationDescription = request.StationDescription,
|
|
StationHeight = request.StationHeight,
|
|
X = request.X,
|
|
Y = request.Y,
|
|
Theta = request.Theta
|
|
};
|
|
|
|
_context.Stations.Add(station);
|
|
await _context.SaveChangesAsync();
|
|
|
|
// Add interaction nodes if provided
|
|
if (request.InteractionNodeIds != null && request.InteractionNodeIds.Count != 0)
|
|
{
|
|
foreach (var nodeId in request.InteractionNodeIds)
|
|
{
|
|
var interactionNode = new StationInteractionNode
|
|
{
|
|
StationId = station.Id,
|
|
NodeId = nodeId
|
|
};
|
|
_context.StationInteractionNodes.Add(interactionNode);
|
|
}
|
|
await _context.SaveChangesAsync();
|
|
}
|
|
|
|
await transaction.CommitAsync();
|
|
|
|
// Reload with interaction nodes
|
|
return (await GetByIdAsync(station.Id, includeInteractionNodes: true))!;
|
|
}
|
|
catch
|
|
{
|
|
await transaction.RollbackAsync();
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task<List<Station>> GetStationsByLevelAsync(Guid layoutLevelId, bool includeInteractionNodes = true)
|
|
{
|
|
var query = _context.Stations.Where(s => s.LevelId == layoutLevelId);
|
|
|
|
if (includeInteractionNodes)
|
|
{
|
|
query = query
|
|
.Include(s => s.InteractionNodes)
|
|
.ThenInclude(sin => sin.Node);
|
|
}
|
|
|
|
return await query.OrderBy(s => s.StationId).ToListAsync();
|
|
}
|
|
|
|
public async Task<Station?> GetByIdAsync(Guid stationId, bool includeInteractionNodes = true)
|
|
{
|
|
var query = _context.Stations.Where(s => s.Id == stationId);
|
|
|
|
if (includeInteractionNodes)
|
|
{
|
|
query = query
|
|
.Include(s => s.InteractionNodes)
|
|
.ThenInclude(sin => sin.Node)
|
|
.ThenInclude(n => n.VehicleProperties);
|
|
}
|
|
|
|
return await query.FirstOrDefaultAsync();
|
|
}
|
|
|
|
public async Task<Station> UpdateAsync(Guid stationId, UpdateStationRequest request)
|
|
{
|
|
var station = await GetByIdAsync(stationId, includeInteractionNodes: true) ??
|
|
throw new InvalidOperationException($"Station with ID '{stationId}' not found");
|
|
|
|
// Update properties
|
|
if (request.StationName != null)
|
|
station.StationName = request.StationName;
|
|
|
|
if (request.StationDescription != null)
|
|
station.StationDescription = request.StationDescription;
|
|
|
|
if (request.StationHeight.HasValue)
|
|
station.StationHeight = request.StationHeight.Value;
|
|
|
|
if (request.X.HasValue)
|
|
station.X = request.X.Value;
|
|
|
|
if (request.Y.HasValue)
|
|
station.Y = request.Y.Value;
|
|
|
|
if (request.Theta.HasValue)
|
|
station.Theta = request.Theta.Value;
|
|
|
|
// Update interaction nodes if provided
|
|
if (request.InteractionNodeIds != null)
|
|
{
|
|
// Remove existing interaction nodes
|
|
var existingInteractionNodes = await _context.StationInteractionNodes
|
|
.Where(sin => sin.StationId == stationId)
|
|
.ToListAsync();
|
|
_context.StationInteractionNodes.RemoveRange(existingInteractionNodes);
|
|
|
|
// Add new interaction nodes
|
|
foreach (var nodeId in request.InteractionNodeIds)
|
|
{
|
|
// Verify node exists
|
|
var nodeExists = await _context.Nodes.AnyAsync(n => n.Id == nodeId);
|
|
if (!nodeExists)
|
|
{
|
|
throw new InvalidOperationException($"Node with ID '{nodeId}' not found");
|
|
}
|
|
|
|
var interactionNode = new StationInteractionNode
|
|
{
|
|
StationId = stationId,
|
|
NodeId = nodeId
|
|
};
|
|
_context.StationInteractionNodes.Add(interactionNode);
|
|
}
|
|
}
|
|
|
|
await _context.SaveChangesAsync();
|
|
|
|
// Reload with interaction nodes
|
|
return (await GetByIdAsync(stationId, includeInteractionNodes: true))!;
|
|
}
|
|
|
|
public async Task<bool> DeleteAsync(Guid stationId)
|
|
{
|
|
var station = await GetByIdAsync(stationId, includeInteractionNodes: false);
|
|
if (station == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Delete interaction nodes (cascade will handle this, but explicit for clarity)
|
|
var interactionNodes = await _context.StationInteractionNodes
|
|
.Where(sin => sin.StationId == stationId)
|
|
.ToListAsync();
|
|
_context.StationInteractionNodes.RemoveRange(interactionNodes);
|
|
|
|
// Delete station
|
|
_context.Stations.Remove(station);
|
|
|
|
await _context.SaveChangesAsync();
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|