// MyBWRSimulator.Core/Simulation/Simulator.cs namespace MyBWRSimulator.Core.Simulation { using MyBWRSimulator.Core.Components.Abstract; using MyBWRSimulator.Core.Data; using System; using System.Collections.Generic; using System.Linq; /// /// The orchestrator of the simulation. Manages components, runs the simulation loop, and provides data. /// public class Simulator { private List _components; private double _simulationTime; private bool _isPaused; public Simulator() { _components = new List(); _simulationTime = 0.0; _isPaused = false; } /// /// Adds a component to the simulation. /// /// The component to add. public void AddComponent(Component component) { if (component != null && !_components.Contains(component)) { _components.Add(component); _components = _components.OrderBy(c => c.UpdatePriority).ToList(); // Re-sort after adding component.Initialize(); Console.WriteLine($"Component '{component.Name}' ({component.ID}) added."); } } /// /// Removes a component from the simulation. /// /// The component to remove. public void RemoveComponent(Component component) { if (component != null && _components.Remove(component)) { _components = _components.OrderBy(c => c.UpdatePriority).ToList(); // Re-sort after removing component.Shutdown(); Console.WriteLine($"Component '{component.Name}' ({component.ID}) removed."); } } /// /// Loads components and connections from a configuration file. /// /// The path to the configuration JSON file. public void LoadPlantConfiguration(string filePath) { ConfigurationLoader.LoadConfiguration(filePath, out _components); _components = _components.OrderBy(c => c.UpdatePriority).ToList(); // Ensure sorted after load Console.WriteLine($"Loaded { _components.Count} components from configuration."); } /// /// Runs the simulation for a specified duration with a given time step. /// /// Total simulation duration (e.g., in seconds). /// Time step for each update iteration (e.g., in seconds). public void RunSimulation(double duration, double timeStep) { Console.WriteLine($"Starting simulation for {duration} seconds with a time step of {timeStep} seconds..."); _isPaused = false; while (_simulationTime < duration && !_isPaused) { Console.WriteLine($"\n--- Simulation Time: {_simulationTime:F2} s ---"); foreach (var component in _components) { component.Update(timeStep); } _simulationTime += timeStep; // For console output, add a small delay to see updates System.Threading.Thread.Sleep(100); } if (_simulationTime >= duration) { Console.WriteLine("\nSimulation finished."); } else if (_isPaused) { Console.WriteLine("\nSimulation paused."); } // Call shutdown for all components at the end of the simulation foreach (var component in _components) { component.Shutdown(); } } /// /// Pauses the simulation. /// public void PauseSimulation() { _isPaused = true; } /// /// Resumes the simulation. /// public void ResumeSimulation() { _isPaused = false; } /// /// Gets current simulation data from all components. /// (Placeholder - you'll define the structure of this data more concretely later) /// /// A dictionary containing simulation data. public Dictionary GetSimulationData() { var data = new Dictionary(); data["SimulationTime"] = _simulationTime; data["ComponentStates"] = _components.Select(c => new { c.ID, c.Name // Add specific properties for each component type here // Example for Pump: (c as Pump)?.PumpSpeed // Example for FluidTank: (c as FluidTank)?.CurrentVolume }).ToList(); return data; } } }