fix graph merge loss of rates
parent
e1f442308e
commit
b0f49eb814
|
|
@ -7,7 +7,6 @@ import satisfactory.items.type.*;
|
|||
import java.util.*;
|
||||
|
||||
public class Database {
|
||||
// dirty!
|
||||
private static final Collection<Item> items = new HashSet<>();
|
||||
public static final Map<Item, Recipe> preferences = new HashMap<>();
|
||||
|
||||
|
|
@ -88,6 +87,7 @@ public class Database {
|
|||
ore.add(mk1, 1);
|
||||
Recipe mk2 = new Recipe(1, "Miner MK2", false);
|
||||
ore.add(mk2, 2);
|
||||
ore.setPreference(mk2);
|
||||
}
|
||||
|
||||
Set<Item> rawFluids = new HashSet<>(Arrays.asList(CrudeOil, Water));
|
||||
|
|
@ -167,6 +167,7 @@ public class Database {
|
|||
recipe.addInput(CopperSheet, 2);
|
||||
recipe.addInput(Plastic, 4);
|
||||
CircuitBoard.add(recipe);
|
||||
// TODO: alternative
|
||||
}
|
||||
{
|
||||
// A.I. Limiter
|
||||
|
|
|
|||
|
|
@ -67,28 +67,30 @@ public class Test {
|
|||
System.out.println("\nSUM_reif");
|
||||
Database.ReinforcedIronPlate.getRecipe().sum(Database.ReinforcedIronPlate, 100);
|
||||
System.out.println("\nSUM_screw");
|
||||
Graph<Item, ProductionEdge> screws100 = Database.Screw.getRecipe().sum(Database.Screw, 100);
|
||||
Graph<Item, ProductionEdge> computers100 = Database.Computer.getRecipe().sum(Database.Computer, 100);
|
||||
Graph<Item, ProductionEdge> screws100 = Database.Screw.getRecipe().sum(Database.Screw, 100).getProduction();
|
||||
Graph<Item, ProductionEdge> computers100 = Database.Computer.getRecipe().sum(Database.Computer, 100).getProduction();
|
||||
|
||||
plot2(screws100, "screw_sum");
|
||||
System.out.println("\nSUM_ACU");
|
||||
plot2(Database.AdaptiveControlUnit.getRecipe().sum(Database.AdaptiveControlUnit, 1), "acu4");
|
||||
plot2(Database.AdaptiveControlUnit.getRecipe().sum(Database.AdaptiveControlUnit, 1).getProduction(), "acu4");
|
||||
|
||||
|
||||
plot2(Utils.merge(screws100, computers100), "merged");
|
||||
//plot2(SumResult.merge(screws100, computers100), "merged");
|
||||
|
||||
System.out.println("\n\nPHASE 3");
|
||||
Graph<Item, ProductionEdge> phase3;
|
||||
//phase3 = Utils.sum(Database.VersatileFrameWork, 2500);
|
||||
//phase3 = Utils.merge(phase3, Utils.sum(Database.ModularEngine,500));
|
||||
phase3 = Utils.sum(Database.ModularEngine,5);
|
||||
phase3 = Utils.merge(phase3, Utils.sum(Database.AdaptiveControlUnit, 1));
|
||||
//phase3 = SumResult.sum(Database.ModularEngine,5);
|
||||
//phase3 = SumResult.merge(phase3, SumResult.sum(Database.AdaptiveControlUnit, 1));
|
||||
|
||||
phase3 = SumResult.sum(new Production(Database.ModularEngine,5), new Production(Database.AdaptiveControlUnit,1)).getProduction();
|
||||
|
||||
plot2(phase3, "phase3");
|
||||
System.out.println("\nrubber");
|
||||
plot2(Utils.sum(Database.Rubber, 75),"rubber");
|
||||
plot2(SumResult.sum(Database.Rubber, 75),"rubber");
|
||||
System.out.println("\ntest");
|
||||
Utils.sum(Database.Plastic, 4);
|
||||
SumResult.sum(Database.Plastic, 4);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import org.jgrapht.traverse.DepthFirstIterator;
|
|||
import org.jgrapht.traverse.GraphIterator;
|
||||
import satisfactory.items.Item;
|
||||
import satisfactory.items.ProductionEdge;
|
||||
import satisfactory.items.SumResult;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
|
|
@ -84,37 +85,6 @@ public class Utils {
|
|||
}
|
||||
}
|
||||
|
||||
public static Graph<Item, ProductionEdge> merge(Graph<Item, ProductionEdge> graph0, Graph<Item, ProductionEdge> graph1) {
|
||||
Graph<Item, ProductionEdge> result = new DefaultDirectedWeightedGraph<>(ProductionEdge.class);
|
||||
|
||||
graph0.vertexSet().forEach(result::addVertex);
|
||||
graph0.edgeSet().forEach(productionEdge -> result.addEdge(graph0.getEdgeSource(productionEdge), graph0.getEdgeTarget(productionEdge), productionEdge));
|
||||
|
||||
graph1.vertexSet().forEach(result::addVertex);
|
||||
graph1.edgeSet().forEach(productionEdge -> {
|
||||
List<ProductionEdge> collect = result.edgeSet().stream().filter(productionEdge1 -> productionEdge1.hasTarget(productionEdge.getTarget())).collect(Collectors.toList());
|
||||
collect.forEach(edge -> {
|
||||
Item src = result.getEdgeSource(edge);
|
||||
Item target = result.getEdgeTarget(edge);
|
||||
Item target2 = graph1.getEdgeTarget(productionEdge);
|
||||
if (target != target2) {
|
||||
result.addEdge(src, target2, productionEdge);
|
||||
} else {
|
||||
result.removeEdge(edge);
|
||||
result.addEdge(src, target, edge);
|
||||
}
|
||||
});
|
||||
if (collect.isEmpty()) {
|
||||
result.addEdge(graph1.getEdgeSource(productionEdge), graph1.getEdgeTarget(productionEdge), productionEdge);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Graph<Item, ProductionEdge> sum(Item item, int amount) {
|
||||
return item.getRecipe().sum(item,amount);
|
||||
}
|
||||
|
||||
public static void plot2(Graph<Item, ProductionEdge> sum, String filename) {
|
||||
DOTExporter<Item, ProductionEdge> de = new DOTExporter<>(Item::ID);
|
||||
de.setEdgeAttributeProvider(productionEdge -> {
|
||||
|
|
@ -127,8 +97,10 @@ public class Utils {
|
|||
if (item.isRaw()) {
|
||||
m.put("peripheries", DefaultAttribute.createAttribute(2));
|
||||
}
|
||||
m.put("label", DefaultAttribute.createAttribute(item.getName()));
|
||||
return m;
|
||||
});
|
||||
de.exportGraph(sum, new File(filename + ".dot"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
package satisfactory.items;
|
||||
|
||||
public class Production {
|
||||
private final Item item;
|
||||
private final int amount;
|
||||
|
||||
public Production(Item item, int amount) {
|
||||
this.item = item;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public Item getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,20 +3,30 @@ package satisfactory.items;
|
|||
import java.util.Objects;
|
||||
|
||||
public class ProductionEdge {
|
||||
private Item source;
|
||||
private final Item source;
|
||||
private final Item target;
|
||||
private double totalRequired;
|
||||
private double instances;
|
||||
|
||||
public ProductionEdge(Item source,double totalRequired, double productionRate) {
|
||||
public ProductionEdge(Item source, Item target, double totalRequired, double productionRate) {
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
this.totalRequired = totalRequired;
|
||||
this.instances = productionRate;
|
||||
}
|
||||
|
||||
public String label() {
|
||||
//return "(" + totalRequired + "||" + instances + ")";
|
||||
return "(%.2f||%.2f)".formatted(totalRequired, instances);
|
||||
}
|
||||
|
||||
public void merge(ProductionEdge other) {
|
||||
if (source.equals(other.getSource())) {
|
||||
totalRequired += other.getTotalRequired();
|
||||
instances += other.getInstances();
|
||||
}
|
||||
}
|
||||
|
||||
public double getTotalRequired() {
|
||||
return totalRequired;
|
||||
}
|
||||
|
|
@ -33,7 +43,7 @@ public class ProductionEdge {
|
|||
this.instances = instances;
|
||||
}
|
||||
|
||||
public boolean hasTarget(Item t){
|
||||
public boolean hasSource(Item t) {
|
||||
return source.equals(t);
|
||||
}
|
||||
|
||||
|
|
@ -42,23 +52,28 @@ public class ProductionEdge {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ProductionEdge that = (ProductionEdge) o;
|
||||
return Double.compare(that.totalRequired, totalRequired) == 0 && instances == that.instances && Objects.equals(source, that.source);
|
||||
return Objects.equals(source, that.source) && Objects.equals(target, that.target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source, totalRequired, instances);
|
||||
return Objects.hash(source, target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ProductionEdge{" +
|
||||
"totalRequired=" + totalRequired +
|
||||
"source=" + source.getName() +
|
||||
", totalRequired=" + totalRequired +
|
||||
", instances=" + instances +
|
||||
'}';
|
||||
}
|
||||
|
||||
public Item getTarget() {
|
||||
public Item getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public Item getTarget() {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
package satisfactory.items;
|
||||
|
||||
import satisfactory.items.requirements.RateAccumulator;
|
||||
import satisfactory.items.requirements.TotalAccumulator;
|
||||
import org.jgrapht.Graph;
|
||||
import org.jgrapht.Graphs;
|
||||
import org.jgrapht.graph.DefaultDirectedWeightedGraph;
|
||||
import org.jgrapht.graph.DefaultWeightedEdge;
|
||||
import satisfactory.items.requirements.RateAccumulator;
|
||||
import satisfactory.items.requirements.TotalAccumulator;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
|
@ -180,7 +180,7 @@ public class Recipe {
|
|||
return n / r.getProductionRate(target);
|
||||
}
|
||||
|
||||
public Graph<Item, ProductionEdge> sum(Item target, int prodPerMinute) {
|
||||
public SumResult sum(Item target, int prodPerMinute) {
|
||||
Graph<Item, DefaultWeightedEdge> buildGraph = buildGraph(target);
|
||||
Graph<Item, ProductionEdge> production = new DefaultDirectedWeightedGraph<>(ProductionEdge.class);
|
||||
Map<Item, Double> map = new HashMap<>();
|
||||
|
|
@ -188,10 +188,10 @@ public class Recipe {
|
|||
queue.add(target);
|
||||
map.put(target, (double) prodPerMinute);
|
||||
production.addVertex(target);
|
||||
production.addEdge(target, target, new ProductionEdge(target, prodPerMinute, processesNeeded(target, prodPerMinute)));
|
||||
production.addEdge(target, target, new ProductionEdge(target, target, prodPerMinute, processesNeeded(target, prodPerMinute)));
|
||||
while (!queue.isEmpty()) {
|
||||
Item item = queue.remove();
|
||||
// next satisfactory.items
|
||||
// next items
|
||||
buildGraph.incomingEdgesOf(item)
|
||||
.stream()
|
||||
.map(buildGraph::getEdgeSource)
|
||||
|
|
@ -218,7 +218,7 @@ public class Recipe {
|
|||
sum += requiredInput;
|
||||
|
||||
production.addVertex(item);
|
||||
production.addEdge(item, product, new ProductionEdge(item, requiredInput, processesNeeded(item, requiredInput)));
|
||||
production.addEdge(item, product, new ProductionEdge(item, product, requiredInput, processesNeeded(item, requiredInput)));
|
||||
}
|
||||
if (!map.containsKey(item) && sum > 0) {
|
||||
map.put(item, sum);
|
||||
|
|
@ -227,13 +227,14 @@ public class Recipe {
|
|||
byProducts.forEach(item1 -> {
|
||||
production.addVertex(item1);
|
||||
// TODO: calculate produced amount
|
||||
production.addEdge(item, item1, new ProductionEdge(item, 0,0));
|
||||
production.addEdge(item, item1, new ProductionEdge(item, item1, 0, 0));
|
||||
});
|
||||
}
|
||||
}
|
||||
map.forEach((item, aDouble) -> {
|
||||
System.out.println(item.getName() + ": " + aDouble);
|
||||
});
|
||||
return production;
|
||||
return new SumResult(production, map);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
package satisfactory.items;
|
||||
|
||||
import org.jgrapht.Graph;
|
||||
import org.jgrapht.graph.DefaultDirectedWeightedGraph;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SumResult {
|
||||
private final Graph<Item, ProductionEdge> production;
|
||||
private final Map<Item, Double> map;
|
||||
|
||||
public SumResult(Graph<Item, ProductionEdge> production, Map<Item, Double> map) {
|
||||
this.production = production;
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public SumResult() {
|
||||
production = new DefaultDirectedWeightedGraph<>(ProductionEdge.class);
|
||||
map = new HashMap<>();
|
||||
}
|
||||
|
||||
public Graph<Item, ProductionEdge> getProduction() {
|
||||
return production;
|
||||
}
|
||||
|
||||
public Map<Item, Double> getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
public SumResult merge(SumResult other){
|
||||
HashMap<Item, Double> map = new HashMap<>();
|
||||
this.map.forEach(map::put);
|
||||
other.map.forEach((item, aDouble) -> map.merge(item,aDouble,Double::sum));
|
||||
return new SumResult(merge(production, other.getProduction()), map);
|
||||
}
|
||||
|
||||
public static Graph<Item, ProductionEdge> sum(Item item, int amount) {
|
||||
return item.getRecipe().sum(item, amount).getProduction();
|
||||
}
|
||||
|
||||
public static SumResult sum(Production... productions) {
|
||||
return Arrays.stream(productions)
|
||||
.map(prod -> prod.getItem().getRecipe().sum(prod.getItem(), prod.getAmount()))
|
||||
.reduce(SumResult::merge).orElse(new SumResult());
|
||||
}
|
||||
|
||||
public static Graph<Item, ProductionEdge> merge(Graph<Item, ProductionEdge> graph0, Graph<Item, ProductionEdge> graph1) {
|
||||
// ToDo: test!
|
||||
Graph<Item, ProductionEdge> result = new DefaultDirectedWeightedGraph<>(ProductionEdge.class);
|
||||
|
||||
graph0.vertexSet().forEach(result::addVertex);
|
||||
graph0.edgeSet().forEach(productionEdge -> result.addEdge(graph0.getEdgeSource(productionEdge), graph0.getEdgeTarget(productionEdge), productionEdge));
|
||||
|
||||
graph1.vertexSet().forEach(result::addVertex);
|
||||
graph1.edgeSet().forEach(productionEdge -> {
|
||||
List<ProductionEdge> collect = result.edgeSet().stream()
|
||||
.filter(productionEdge1 -> productionEdge1.hasSource(productionEdge.getSource()))
|
||||
.collect(Collectors.toList());
|
||||
collect.forEach(edge -> {
|
||||
Item src = result.getEdgeSource(edge);
|
||||
Item target = result.getEdgeTarget(edge);
|
||||
Item target2 = graph1.getEdgeTarget(productionEdge);
|
||||
if (target != target2) {
|
||||
result.addEdge(src, target2, productionEdge);
|
||||
} else {
|
||||
/*result.removeEdge(edge);
|
||||
result.addEdge(src, target, edge);*/
|
||||
edge.merge(productionEdge);
|
||||
}
|
||||
});
|
||||
if (collect.isEmpty()) {
|
||||
result.addEdge(graph1.getEdgeSource(productionEdge), graph1.getEdgeTarget(productionEdge), productionEdge);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,14 @@
|
|||
package satisfactory.items;
|
||||
|
||||
import org.jgrapht.Graph;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import satisfactory.Database;
|
||||
import satisfactory.Utils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import satisfactory.Database;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class ItemTest {
|
||||
|
||||
|
|
@ -48,4 +49,52 @@ class ItemTest {
|
|||
float productionRate = Database.Screw.getRecipe().getProductionRate(Database.Screw);
|
||||
assertEquals(40, productionRate);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPhase3_ME_ACU() {
|
||||
// references
|
||||
Map<Item, Double> ref = new HashMap<>();
|
||||
ref.put(Database.CircuitBoard, 15.0);
|
||||
ref.put(Database.Computer, 1.0);
|
||||
ref.put(Database.Limestone,75.0);
|
||||
ref.put(Database.Concrete,25.0);
|
||||
ref.put(Database.SteelBeam,20.0);
|
||||
ref.put(Database.EncasedIndustrialBeam, 5.0);
|
||||
ref.put(Database.ModularFrame,5.0);
|
||||
ref.put(Database.HeavyModularFrame,1.0);
|
||||
ref.put(Database.Plastic, 78.0);
|
||||
ref.put(Database.CopperSheet, 30.0);
|
||||
ref.put(Database.Coal,226.25);
|
||||
ref.put(Database.Cable,159.0);
|
||||
ref.put(Database.CopperOre,329.0);
|
||||
ref.put(Database.AutomatedWiring, 7.5);
|
||||
ref.put(Database.AdaptiveControlUnit, 1.0);
|
||||
ref.put(Database.CrudeOil, 229.5);
|
||||
ref.put(Database.ReinforcedIronPlate, 17.5);
|
||||
ref.put(Database.CopperIngot, 329.0);
|
||||
ref.put(Database.SteelIngot, 226.25);
|
||||
ref.put(Database.IronPlate, 105.0);
|
||||
ref.put(Database.SmartPlating, 10.0);
|
||||
//ref.put(Database.HeavyOilResidue, 114.0); // TODO: implement calculation
|
||||
ref.put(Database.Rubber, 75.0);
|
||||
ref.put(Database.Wire, 538.0);
|
||||
ref.put(Database.SteelPipe, 97.5);
|
||||
ref.put(Database.Stator, 27.5);
|
||||
ref.put(Database.Screw, 1112.0);
|
||||
ref.put(Database.IronOre, 841.75);
|
||||
ref.put(Database.IronIngot, 615.5);
|
||||
ref.put(Database.IronRod, 458.0);
|
||||
ref.put(Database.Rotor, 30.0);
|
||||
ref.put(Database.Motor, 10.0);
|
||||
ref.put(Database.ModularEngine, 5.0);
|
||||
|
||||
// calculate
|
||||
Map<Item, Double> calculations = SumResult.sum(new Production(Database.ModularEngine, 5), new Production(Database.AdaptiveControlUnit, 1)).getMap();
|
||||
|
||||
// assert
|
||||
ref.forEach((item, amount) -> {
|
||||
assertTrue(calculations.containsKey(item), "exists? " + item.getName());
|
||||
assertEquals(amount, calculations.get(item), 0.01, item.getName());
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue