namespace SpaceGame.Api.Industry.Planning; internal static class ProductionGraphBuilder { internal static ProductionGraph Build( IReadOnlyCollection items, IReadOnlyCollection recipes, IReadOnlyCollection modules) { var commodities = items.ToDictionary( item => item.Id, item => new ProductionCommodityNode { ItemId = item.Id, Name = item.Name, Group = item.Group, CargoKind = item.CargoKind?.ToDataValue() ?? string.Empty, }, StringComparer.Ordinal); var processes = new Dictionary(StringComparer.Ordinal); var processesByOutputId = new Dictionary>(StringComparer.Ordinal); var processesByInputId = new Dictionary>(StringComparer.Ordinal); var outputsByModuleId = new Dictionary>(StringComparer.Ordinal); foreach (var recipe in recipes) { var outputs = recipe.Outputs .GroupBy(output => output.ItemId, StringComparer.Ordinal) .ToDictionary(group => group.Key, group => group.Sum(output => output.Amount), StringComparer.Ordinal); var inputs = recipe.Inputs .GroupBy(input => input.ItemId, StringComparer.Ordinal) .ToDictionary(group => group.Key, group => group.Sum(input => input.Amount), StringComparer.Ordinal); var process = new ProductionProcessNode { Id = recipe.Id, Label = recipe.Label, FacilityCategory = recipe.FacilityCategory, RequiredModuleIds = recipe.RequiredModules.ToList(), Inputs = inputs, Outputs = outputs, ProducesShip = recipe.ShipOutputId is not null, }; processes[process.Id] = process; foreach (var output in outputs.Keys) { if (!commodities.ContainsKey(output)) { continue; } commodities[output].ProducerProcessIds.Add(process.Id); if (!processesByOutputId.TryGetValue(output, out var outputProcesses)) { outputProcesses = []; processesByOutputId[output] = outputProcesses; } outputProcesses.Add(process); } foreach (var input in inputs.Keys) { if (!commodities.ContainsKey(input)) { continue; } commodities[input].ConsumerProcessIds.Add(process.Id); if (!processesByInputId.TryGetValue(input, out var inputProcesses)) { inputProcesses = []; processesByInputId[input] = inputProcesses; } inputProcesses.Add(process); } } foreach (var module in modules) { if (!outputsByModuleId.TryGetValue(module.Id, out var outputs)) { outputs = new HashSet(StringComparer.Ordinal); outputsByModuleId[module.Id] = outputs; } foreach (var product in module.ProductItemIds) { outputs.Add(product); } } return new ProductionGraph { Commodities = commodities, Processes = processes, ProcessesByOutputId = processesByOutputId.ToDictionary(entry => entry.Key, entry => (IReadOnlyList)entry.Value, StringComparer.Ordinal), ProcessesByInputId = processesByInputId.ToDictionary(entry => entry.Key, entry => (IReadOnlyList)entry.Value, StringComparer.Ordinal), OutputsByModuleId = outputsByModuleId.ToDictionary(entry => entry.Key, entry => (IReadOnlyList)entry.Value.OrderBy(value => value, StringComparer.Ordinal).ToList(), StringComparer.Ordinal), }; } }