namespace SpaceGame.Api.Industry.Planning; public sealed class ProductionGraph { public required IReadOnlyDictionary Commodities { get; init; } public required IReadOnlyDictionary Processes { get; init; } public required IReadOnlyDictionary> ProcessesByOutputId { get; init; } public required IReadOnlyDictionary> ProcessesByInputId { get; init; } public required IReadOnlyDictionary> OutputsByModuleId { get; init; } public IReadOnlyList GetProcessesForOutput(string itemId) => ProcessesByOutputId.TryGetValue(itemId, out var processes) ? processes : []; public IReadOnlyList GetProcessesForInput(string itemId) => ProcessesByInputId.TryGetValue(itemId, out var processes) ? processes : []; public string? GetPrimaryProducerModule(string itemId) => GetProcessesForOutput(itemId) .SelectMany(process => process.RequiredModuleIds) .FirstOrDefault(); public string? GetPrimaryOutputForModule(string moduleId) => OutputsByModuleId.TryGetValue(moduleId, out var outputs) ? outputs.FirstOrDefault() : null; public IReadOnlyList GetImmediateInputs(string itemId) => GetProcessesForOutput(itemId) .SelectMany(process => process.Inputs.Keys) .Distinct(StringComparer.Ordinal) .ToList(); } public sealed class ProductionCommodityNode { public required string ItemId { get; init; } public required string Name { get; init; } public required string Group { get; init; } public required string CargoKind { get; init; } public List ProducerProcessIds { get; } = []; public List ConsumerProcessIds { get; } = []; } public sealed class ProductionProcessNode { public required string Id { get; init; } public required string Label { get; init; } public required string FacilityCategory { get; init; } public required IReadOnlyList RequiredModuleIds { get; init; } public required IReadOnlyDictionary Inputs { get; init; } public required IReadOnlyDictionary Outputs { get; init; } public required bool ProducesShip { get; init; } }