Deepen faction economy and station planning
This commit is contained in:
105
apps/backend/Industry/Planning/ProductionGraphBuilder.cs
Normal file
105
apps/backend/Industry/Planning/ProductionGraphBuilder.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
namespace SpaceGame.Api.Industry.Planning;
|
||||
|
||||
internal static class ProductionGraphBuilder
|
||||
{
|
||||
internal static ProductionGraph Build(
|
||||
IReadOnlyCollection<ItemDefinition> items,
|
||||
IReadOnlyCollection<RecipeDefinition> recipes,
|
||||
IReadOnlyCollection<ModuleDefinition> modules)
|
||||
{
|
||||
var commodities = items.ToDictionary(
|
||||
item => item.Id,
|
||||
item => new ProductionCommodityNode
|
||||
{
|
||||
ItemId = item.Id,
|
||||
Name = item.Name,
|
||||
Group = item.Group,
|
||||
CargoKind = item.CargoKind,
|
||||
},
|
||||
StringComparer.Ordinal);
|
||||
|
||||
var processes = new Dictionary<string, ProductionProcessNode>(StringComparer.Ordinal);
|
||||
var processesByOutputId = new Dictionary<string, List<ProductionProcessNode>>(StringComparer.Ordinal);
|
||||
var processesByInputId = new Dictionary<string, List<ProductionProcessNode>>(StringComparer.Ordinal);
|
||||
var outputsByModuleId = new Dictionary<string, HashSet<string>>(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<string>(StringComparer.Ordinal);
|
||||
outputsByModuleId[module.Id] = outputs;
|
||||
}
|
||||
|
||||
foreach (var product in module.Products)
|
||||
{
|
||||
outputs.Add(product);
|
||||
}
|
||||
}
|
||||
|
||||
return new ProductionGraph
|
||||
{
|
||||
Commodities = commodities,
|
||||
Processes = processes,
|
||||
ProcessesByOutputId = processesByOutputId.ToDictionary(entry => entry.Key, entry => (IReadOnlyList<ProductionProcessNode>)entry.Value, StringComparer.Ordinal),
|
||||
ProcessesByInputId = processesByInputId.ToDictionary(entry => entry.Key, entry => (IReadOnlyList<ProductionProcessNode>)entry.Value, StringComparer.Ordinal),
|
||||
OutputsByModuleId = outputsByModuleId.ToDictionary(entry => entry.Key, entry => (IReadOnlyList<string>)entry.Value.OrderBy(value => value, StringComparer.Ordinal).ToList(), StringComparer.Ordinal),
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user