feature: In-App Simulation Runner (Backend)
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
using VigilCare.Simulation;
|
||||
|
||||
public interface IScenarioCatalog
|
||||
{
|
||||
IReadOnlyList<ScenarioFile> ListScenarios();
|
||||
ScenarioFile? GetById(string scenarioId);
|
||||
}
|
||||
|
||||
public sealed class ScenarioCatalog : IScenarioCatalog
|
||||
{
|
||||
private readonly string _directory;
|
||||
private readonly object _gate = new();
|
||||
private IReadOnlyList<(ScenarioFile Scenario, string Path, DateTime LastWriteUtc)> _entries =
|
||||
Array.Empty<(ScenarioFile, string, DateTime)>();
|
||||
|
||||
public ScenarioCatalog(Microsoft.Extensions.Options.IOptions<SimulationOptions> options)
|
||||
{
|
||||
_directory = options.Value.ScenarioDirectory;
|
||||
}
|
||||
|
||||
public IReadOnlyList<ScenarioFile> ListScenarios()
|
||||
{
|
||||
RefreshIfNeeded();
|
||||
return _entries.Select(e => e.Scenario).ToList();
|
||||
}
|
||||
|
||||
public ScenarioFile? GetById(string scenarioId)
|
||||
{
|
||||
RefreshIfNeeded();
|
||||
return _entries
|
||||
.Select(e => e.Scenario)
|
||||
.FirstOrDefault(s => string.Equals(
|
||||
s.Scenario.Id, scenarioId, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private void RefreshIfNeeded()
|
||||
{
|
||||
lock (_gate)
|
||||
{
|
||||
if (!Directory.Exists(_directory))
|
||||
{
|
||||
_entries = Array.Empty<(ScenarioFile, string, DateTime)>();
|
||||
return;
|
||||
}
|
||||
|
||||
var disk = Directory.EnumerateFiles(_directory, "*.json")
|
||||
.Where(p => !string.Equals(
|
||||
Path.GetFileName(p), "schema.json", StringComparison.OrdinalIgnoreCase))
|
||||
.Select(p => (Path: p, LastWriteUtc: File.GetLastWriteTimeUtc(p)))
|
||||
.OrderBy(x => x.Path, StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
|
||||
var unchanged = _entries.Count == disk.Count
|
||||
&& _entries.Zip(disk, (cached, onDisk) =>
|
||||
cached.Path == onDisk.Path && cached.LastWriteUtc == onDisk.LastWriteUtc)
|
||||
.All(eq => eq);
|
||||
|
||||
if (unchanged)
|
||||
return;
|
||||
|
||||
var loaded = new List<(ScenarioFile Scenario, string Path, DateTime LastWriteUtc)>();
|
||||
foreach (var file in disk)
|
||||
{
|
||||
try
|
||||
{
|
||||
loaded.Add((ScenarioLoader.Load(file.Path), file.Path, file.LastWriteUtc));
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Skip corrupt files — catalogue must stay resilient.
|
||||
}
|
||||
}
|
||||
|
||||
_entries = loaded
|
||||
.OrderBy(e => e.Scenario.Scenario.Id, StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user