using System; using System.Collections.Generic; using CtrEditor.ObjetosSim; namespace CtrEditor.HydraulicSimulator.TSNet.Components { /// /// Adaptador simplificado para osHydPump - 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 /// public class TSNetPumpAdapter { private readonly osHydPump pump; private string nodeId; // Configuración capturada al inicio de simulación (INMUTABLE durante simulación) public PumpConfiguration Configuration { get; private set; } // Resultados calculados por TSNet (SOLO escritura desde TSNet) public TSNetPumpResults Results { get; private set; } public TSNetPumpAdapter(osHydPump pump) { this.pump = pump ?? throw new ArgumentNullException(nameof(pump)); // Validación defensiva para Id if (pump.Id == null) { throw new InvalidOperationException($"La bomba '{pump.Nombre ?? "sin nombre"}' no tiene un Id válido"); } this.nodeId = $"PUMP_{pump.Id.Value}"; this.Results = new TSNetPumpResults { PumpId = nodeId }; } /// /// ID único del nodo de bomba para TSNet /// public string NodeId => nodeId; /// /// Captura la configuración actual de la bomba al INICIO de la simulación /// Esta configuración queda CONGELADA hasta que se detenga y reinicie la simulación /// public void CaptureConfigurationForSimulation() { Configuration = new PumpConfiguration { PumpId = nodeId, PumpHead = pump.PumpHead, MaxFlow = pump.MaxFlow, SpeedRatio = pump.SpeedRatio, IsRunning = pump.IsRunning, PumpDirection = pump.PumpDirection.ToString(), // Convertir int a string Position = new PumpPosition { X = pump.Left, Y = pump.Top }, CapturedAt = DateTime.Now }; } /// /// Resetea los resultados (para nueva simulación) /// public void ResetCalculatedValues() { Results = new TSNetPumpResults { PumpId = nodeId }; } /// /// Validación de configuración capturada /// public List ValidateConfiguration() { var errors = new List(); if (Configuration == null) { errors.Add($"Bomba {NodeId}: Configuración no capturada"); return errors; } if (Configuration.PumpHead <= 0) errors.Add($"Bomba {NodeId}: PumpHead debe ser mayor que 0"); if (Configuration.MaxFlow <= 0) errors.Add($"Bomba {NodeId}: MaxFlow debe ser mayor que 0"); if (Configuration.SpeedRatio < 0 || Configuration.SpeedRatio > 1) errors.Add($"Bomba {NodeId}: SpeedRatio debe estar entre 0 y 1"); return errors; } public override string ToString() { var configStatus = Configuration != null ? "Configured" : "Not Configured"; var resultStatus = Results?.OperationalStatus ?? "No Results"; return $"TSNetPumpAdapter[{NodeId}] - Config: {configStatus}, Results: {resultStatus}"; } /// /// Aplica los resultados de TSNet a la bomba /// public void ApplyTSNetResults(Dictionary flows, Dictionary pressures) { if (Results == null) return; try { // Actualizar resultados desde los diccionarios de TSNet if (flows.ContainsKey(NodeId)) { Results.CalculatedFlowM3s = flows[NodeId]; Results.CalculatedFlowLMin = flows[NodeId] * 60000; // m³/s a L/min } if (pressures.ContainsKey(NodeId)) { Results.OutletPressureBar = pressures[NodeId] / 100000.0; // Pa a bar } Results.Timestamp = DateTime.Now; Results.OperationalStatus = "Updated from TSNet"; } catch (Exception ex) { Results.OperationalStatus = $"Error: {ex.Message}"; } } } /// /// Configuración inmutable de la bomba capturada al inicio de simulación /// public class PumpConfiguration { public string PumpId { get; set; } public DateTime CapturedAt { get; set; } // Propiedades de la bomba public double PumpHead { get; set; } public double MaxFlow { get; set; } public double SpeedRatio { get; set; } public bool IsRunning { get; set; } public string PumpDirection { get; set; } public PumpPosition Position { get; set; } } /// /// Posición de la bomba en el canvas /// public class PumpPosition { public double X { get; set; } public double Y { get; set; } } }