167 lines
7.3 KiB
C#
167 lines
7.3 KiB
C#
// 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;
|
|
|
|
/// <summary>
|
|
/// Helper class for deserializing component and connection configurations.
|
|
/// </summary>
|
|
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
|
|
}
|
|
|
|
/// <summary>
|
|
/// Helper class for deserializing connection configurations.
|
|
/// </summary>
|
|
public class PortReference
|
|
{
|
|
public string ComponentID { get; set; }
|
|
public string PortID { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Overall configuration structure.
|
|
/// </summary>
|
|
public class PlantConfiguration
|
|
{
|
|
public List<ComponentConfig> Components { get; set; }
|
|
public List<ConnectionConfig> Connections { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Helper class for deserializing connection configurations.
|
|
/// </summary>
|
|
public class ConnectionConfig
|
|
{
|
|
public PortReference PortA { get; set; }
|
|
public PortReference PortB { get; set; }
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Handles loading simulation configuration from a JSON file.
|
|
/// </summary>
|
|
public class ConfigurationLoader
|
|
{
|
|
/// <summary>
|
|
/// Loads components and establishes connections from a JSON configuration file.
|
|
/// </summary>
|
|
/// <param name="filePath">The path to the JSON configuration file.</param>
|
|
/// <param name="components">An output list to populate with instantiated components.</param>
|
|
public static void LoadConfiguration(string filePath, out List<Component> components)
|
|
{
|
|
components = new List<Component>();
|
|
if (!File.Exists(filePath))
|
|
{
|
|
Console.WriteLine($"Error: Configuration file not found at {filePath}");
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
string jsonString = File.ReadAllText(filePath);
|
|
var config = JsonSerializer.Deserialize<PlantConfiguration>(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<Dictionary<string, double>>();
|
|
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<Dictionary<string, double>>();
|
|
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<Dictionary<string, double>>();
|
|
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}");
|
|
}
|
|
}
|
|
}
|
|
} |