// MyBWRSimulator.Core/Data/ConfigurationLoader.cs namespace MyBWRSimulator.Core.Data { using MyBWRSimulator.Core.Components.Abstract; using MyBWRSimulator.Core.Components.Concrete; using MyBWRSimulator.Core.Ports; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.Json; using System.Text.Json.Serialization; /// /// Helper class for deserializing component and connection configurations. /// public class ComponentConfig { public string Type { get; set; } public string ID { get; set; } public string Name { get; set; } public int UpdatePriority { get; set; } public JsonElement InitialState { get; set; } // Use JsonElement to handle dynamic properties } /// /// Helper class for deserializing connection configurations. /// public class PortReference { public string ComponentID { get; set; } public string PortID { get; set; } } /// /// Overall configuration structure. /// public class PlantConfiguration { public List Components { get; set; } public List Connections { get; set; } } /// /// Helper class for deserializing connection configurations. /// public class ConnectionConfig { public PortReference PortA { get; set; } public PortReference PortB { get; set; } } /// /// Handles loading simulation configuration from a JSON file. /// public class ConfigurationLoader { /// /// Loads components and establishes connections from a JSON configuration file. /// /// The path to the JSON configuration file. /// An output list to populate with instantiated components. public static void LoadConfiguration(string filePath, out List components) { components = new List(); if (!File.Exists(filePath)) { Console.WriteLine($"Error: Configuration file not found at {filePath}"); return; } try { string jsonString = File.ReadAllText(filePath); var config = JsonSerializer.Deserialize(jsonString, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); if (config?.Components == null) { Console.WriteLine("Error: No components found in configuration."); return; } // 1. Instantiate Components foreach (var compConfig in config.Components) { Component newComponent = null; switch (compConfig.Type) { case "Pump": // Example: Deserialize specific properties for Pump var pumpProps = compConfig.InitialState.Deserialize>(); newComponent = new Pump(compConfig.ID, compConfig.Name, pumpProps["MaxFlowRate"], pumpProps["MaxHeadPressure"]); if (pumpProps.TryGetValue("PumpSpeed", out double pumpSpeed)) { ((Pump)newComponent).SetPumpSpeed(pumpSpeed); } break; case "FluidTank": // Example: Deserialize specific properties for FluidTank var tankProps = compConfig.InitialState.Deserialize>(); newComponent = new FluidTank(compConfig.ID, compConfig.Name, tankProps["MaxVolume"], (int)tankProps["NumInlets"], (int)tankProps["NumOutlets"], tankProps["InitialVolume"]); break; case "Pipe": var pipeProps = compConfig.InitialState.Deserialize>(); newComponent = new Pipe(compConfig.ID, compConfig.Name, pipeProps["Length"], pipeProps["Diameter"]); break; case "ReactorCore": newComponent = new ReactorCore(compConfig.ID, compConfig.Name, compConfig.UpdatePriority); // ReactorCore might have no specific initial state beyond base properties break; // Add more component types here default: Console.WriteLine($"Warning: Unknown component type '{compConfig.Type}' for ID '{compConfig.ID}'. Skipping."); break; } if (newComponent != null) { components.Add(newComponent); newComponent.Initialize(); // Initialize after creation } } // 2. Establish Connections if (config.Connections != null) { foreach (var connConfig in config.Connections) { var compA = components.FirstOrDefault(c => c.ID == connConfig.PortA.ComponentID); var compB = components.FirstOrDefault(c => c.ID == connConfig.PortB.ComponentID); if (compA == null || compB == null) { Console.WriteLine($"Warning: Could not find one or both components for connection: {connConfig.PortA.ComponentID}.{connConfig.PortA.PortID} <-> {connConfig.PortB.ComponentID}.{connConfig.PortB.PortID}"); continue; } // Use the new GetPortById methods for more robust lookup Port portA = compA.GetFluidPortById(connConfig.PortA.PortID) as Port ?? compA.GetThermalPortById(connConfig.PortA.PortID) as Port; Port portB = compB.GetFluidPortById(connConfig.PortB.PortID) as Port ?? compB.GetThermalPortById(connConfig.PortB.PortID) as Port; if (portA != null && portB != null) { portA.Connect(portB); } else { Console.WriteLine($"Warning: Could not find one or both ports for connection: {connConfig.PortA.ComponentID}.{connConfig.PortA.PortID} <-> {connConfig.PortB.ComponentID}.{connConfig.PortB.PortID}"); } } } } catch (JsonException ex) { Console.WriteLine($"Error parsing JSON configuration: {ex.Message}"); } catch (Exception ex) { Console.WriteLine($"An unexpected error occurred during configuration loading: {ex.Message}"); } } } }