84 lines
2.7 KiB
C#
84 lines
2.7 KiB
C#
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 =>
|
|
{
|
|
var name = Path.GetFileName(p);
|
|
return !string.Equals(name, "schema.json", StringComparison.OrdinalIgnoreCase)
|
|
&& !string.Equals(name, "sessions.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();
|
|
}
|
|
}
|
|
}
|