using SpaceGame.Api.Universe.Bootstrap; namespace SpaceGame.Api.Universe.Scenario; public sealed class ScenarioValidationService(IStaticDataProvider staticData) { public ScenarioDefinition CreateEmptyScenario( WorldGenerationOptions worldGenerationOptions, IReadOnlyList systems) { if (systems.Count == 0) { throw new InvalidOperationException("World generation produced no systems."); } return new ScenarioDefinition { WorldGeneration = worldGenerationOptions, InitialStations = [], ShipFormations = [], PatrolRoutes = [], }; } public void Validate( ScenarioDefinition scenario, IReadOnlySet availableSystemIds) { foreach (var station in scenario.InitialStations) { ValidateSystemExists(station.SystemId, $"station '{station.Label}' system", availableSystemIds); ValidateFactionId(station.FactionId, $"station '{station.Label}'"); foreach (var moduleId in station.StartingModules) { ValidateModuleId(moduleId, $"station '{station.Label}' starting module"); } } foreach (var formation in scenario.ShipFormations) { ValidateSystemExists(formation.SystemId, $"ship formation '{formation.ShipId}' system", availableSystemIds); ValidateFactionId(formation.FactionId, $"ship formation '{formation.ShipId}' in system '{formation.SystemId}'"); ValidateShipId(formation.ShipId, $"ship formation in system '{formation.SystemId}'"); foreach (var itemId in formation.StartingInventory.Keys) { ValidateItemId(itemId, $"ship formation '{formation.ShipId}' starting inventory"); } } foreach (var route in scenario.PatrolRoutes) { ValidateSystemExists(route.SystemId, "patrol route system", availableSystemIds); } } private static string GetRequiredFactionId(string? factionId, string context) { if (!string.IsNullOrWhiteSpace(factionId)) { return factionId; } throw new InvalidOperationException($"Scenario {context} is missing a factionId."); } private static void ValidateSystemExists( string systemId, string context, IReadOnlySet availableSystemIds) { if (!availableSystemIds.Contains(systemId)) { throw new InvalidOperationException($"Scenario {context} references unknown generated system '{systemId}'."); } } private void ValidateFactionId(string? factionId, string context) { var requiredFactionId = GetRequiredFactionId(factionId, context); if (!staticData.FactionDefinitions.ContainsKey(requiredFactionId)) { throw new InvalidOperationException($"Scenario {context} references unknown faction '{requiredFactionId}'."); } } private void ValidateModuleId(string moduleId, string context) { if (!staticData.ModuleDefinitions.ContainsKey(moduleId)) { throw new InvalidOperationException($"Scenario {context} references unknown module '{moduleId}'."); } } private void ValidateShipId(string shipId, string context) { if (!staticData.ShipDefinitions.ContainsKey(shipId)) { throw new InvalidOperationException($"Scenario {context} references unknown ship '{shipId}'."); } } private void ValidateItemId(string itemId, string context) { if (!staticData.ItemDefinitions.ContainsKey(itemId)) { throw new InvalidOperationException($"Scenario {context} references unknown item '{itemId}'."); } } }