CtrEditor/HydraulicSimulator/TSNet/Components/TSNetTankAdapter.cs

185 lines
7.3 KiB
C#

using System;
using System.Collections.Generic;
using CtrEditor.ObjetosSim;
namespace CtrEditor.HydraulicSimulator.TSNet.Components
{
/// <summary>
/// Adaptador simplificado para osHydTank - SOLO lectura de configuración y almacenamiento de resultados
/// Los valores se capturan al INICIAR la simulación y no se modifican durante la ejecución
/// </summary>
public class TSNetTankAdapter
{
private readonly osHydTank tank;
private string tankId;
// Configuración capturada al inicio de simulación (INMUTABLE durante simulación)
public TankConfiguration Configuration { get; private set; }
// Resultados calculados por TSNet (SOLO escritura desde TSNet)
public TSNetTankResults Results { get; private set; }
/// <summary>
/// Acceso al objeto tanque hidráulico subyacente
/// </summary>
public osHydTank Tank => tank;
public TSNetTankAdapter(osHydTank tank)
{
this.tank = tank ?? throw new ArgumentNullException(nameof(tank));
// Validación defensiva para Id
if (tank.Id == null)
{
throw new InvalidOperationException($"El tanque '{tank.Nombre ?? "sin nombre"}' no tiene un Id válido");
}
this.tankId = $"TANK_{tank.Id.Value}";
this.Results = new TSNetTankResults { TankId = tankId };
}
/// <summary>
/// ID único del tanque para TSNet
/// </summary>
public string TankId => tankId;
/// <summary>
/// Captura la configuración actual del tanque al INICIO de la simulación
/// Esta configuración queda CONGELADA hasta que se detenga y reinicie la simulación
/// </summary>
public void CaptureConfigurationForSimulation()
{
// Debug: Log valores antes de capturar
System.Diagnostics.Debug.WriteLine($"TSNetTankAdapter: Capturando configuración para {tank.Nombre}");
System.Diagnostics.Debug.WriteLine($" tank.CurrentLevel: {tank.CurrentLevel}");
System.Diagnostics.Debug.WriteLine($" tank.MaxLevel: {tank.MaxLevel}");
System.Diagnostics.Debug.WriteLine($" tank.Diameter: {tank.Diameter}");
Configuration = new TankConfiguration
{
TankId = tankId,
MinLevelM = 0, // Simplificado - no necesitamos nivel mínimo
MaxLevelM = tank.MaxLevel,
InitialLevelM = tank.CurrentLevel, // Solo usar CurrentLevel - es lo único que importa
DiameterM = tank.Diameter,
TankPressure = tank.TankPressure,
IsFixedPressure = tank.IsFixedPressure,
Position = new TankPosition { X = tank.Left, Y = tank.Top },
CapturedAt = DateTime.Now
};
// Debug: Log configuración capturada
System.Diagnostics.Debug.WriteLine($" Configuration.InitialLevelM: {Configuration.InitialLevelM}");
System.Diagnostics.Debug.WriteLine($" Configuration.MaxLevelM: {Configuration.MaxLevelM}");
}
/// <summary>
/// Resetea los resultados (para nueva simulación)
/// </summary>
public void ResetCalculatedValues()
{
Results = new TSNetTankResults { TankId = tankId };
}
/// <summary>
/// Validación de configuración capturada
/// </summary>
public List<string> ValidateConfiguration()
{
var errors = new List<string>();
if (Configuration == null)
{
errors.Add($"Tanque {TankId}: Configuración no capturada");
return errors;
}
if (Configuration.MinLevelM < 0)
errors.Add($"Tanque {TankId}: MinLevelM no puede ser negativo");
if (Configuration.MaxLevelM <= Configuration.MinLevelM)
errors.Add($"Tanque {TankId}: MaxLevelM debe ser mayor que MinLevelM");
if (Configuration.InitialLevelM < Configuration.MinLevelM || Configuration.InitialLevelM > Configuration.MaxLevelM)
{
// Log de depuración detallado
System.Diagnostics.Debug.WriteLine($"VALIDACION ERROR - Tanque {TankId}:");
System.Diagnostics.Debug.WriteLine($" InitialLevelM: {Configuration.InitialLevelM}");
System.Diagnostics.Debug.WriteLine($" MinLevelM: {Configuration.MinLevelM}");
System.Diagnostics.Debug.WriteLine($" MaxLevelM: {Configuration.MaxLevelM}");
System.Diagnostics.Debug.WriteLine($" InitialLevelM < MinLevelM: {Configuration.InitialLevelM < Configuration.MinLevelM}");
System.Diagnostics.Debug.WriteLine($" InitialLevelM > MaxLevelM: {Configuration.InitialLevelM > Configuration.MaxLevelM}");
errors.Add($"Tanque {TankId}: InitialLevelM ({Configuration.InitialLevelM}) debe estar entre MinLevelM ({Configuration.MinLevelM}) y MaxLevelM ({Configuration.MaxLevelM})");
}
if (Configuration.DiameterM <= 0)
errors.Add($"Tanque {TankId}: DiameterM debe ser mayor que 0");
return errors;
}
public override string ToString()
{
var configStatus = Configuration != null ? "Configured" : "Not Configured";
var resultStatus = Results?.Status ?? "No Results";
return $"TSNetTankAdapter[{TankId}] - Config: {configStatus}, Results: {resultStatus}";
}
/// <summary>
/// Aplica los resultados de TSNet al tanque
/// </summary>
public void ApplyTSNetResults(Dictionary<string, double> flows, Dictionary<string, double> pressures)
{
if (Results == null) return;
try
{
// Actualizar resultados desde los diccionarios de TSNet
if (flows.ContainsKey(TankId))
{
Results.NetFlowM3s = flows[TankId];
}
if (pressures.ContainsKey(TankId))
{
Results.CalculatedPressureBar = pressures[TankId] / 100000.0; // Pa a bar
}
Results.Timestamp = DateTime.Now;
Results.Status = "Updated from TSNet";
}
catch (Exception ex)
{
Results.Status = $"Error: {ex.Message}";
}
}
}
/// <summary>
/// Configuración inmutable del tanque capturada al inicio de simulación
/// </summary>
public class TankConfiguration
{
public string TankId { get; set; }
public DateTime CapturedAt { get; set; }
// Propiedades físicas del tanque
public double MinLevelM { get; set; }
public double MaxLevelM { get; set; }
public double InitialLevelM { get; set; }
public double DiameterM { get; set; }
public double TankPressure { get; set; }
public bool IsFixedPressure { get; set; }
public TankPosition Position { get; set; }
}
/// <summary>
/// Posición del tanque en el canvas
/// </summary>
public class TankPosition
{
public double X { get; set; }
public double Y { get; set; }
}
}