diff --git a/src/main/java/satisfactory/Utils.java b/src/main/java/satisfactory/Utils.java index 582f741..72a7c66 100644 --- a/src/main/java/satisfactory/Utils.java +++ b/src/main/java/satisfactory/Utils.java @@ -110,7 +110,7 @@ public class Utils { double instances = sum.outgoingEdgesOf(item).stream().map(ProductionEdge::getInstances).reduce(Double::sum).orElseGet(() -> Double.NaN); String buildingName = item.getRecipe().getBuilding().getName(); if (Double.isNaN(required) || Double.isNaN(instances)) { - required = -sum.incomingEdgesOf(item).stream().map(ProductionEdge::getTotalRequired).reduce(Double::sum).orElseGet(() -> Double.NaN); + required = -sum.incomingEdgesOf(item).stream().map(ProductionEdge::getTotalProduced).reduce(Double::sum).orElseGet(() -> Double.NaN); instances = 0; buildingName = ""; } diff --git a/src/main/java/satisfactory/items/ProductionEdge.java b/src/main/java/satisfactory/items/ProductionEdge.java index 317932c..bf478d8 100644 --- a/src/main/java/satisfactory/items/ProductionEdge.java +++ b/src/main/java/satisfactory/items/ProductionEdge.java @@ -7,6 +7,12 @@ public class ProductionEdge { private final Item target; private double totalRequired; private double instances; + private boolean ignoreUpstream; + + public ProductionEdge(Item source, Item target, double totalRequired, double productionRate, boolean ignoreUpstream) { + this(source, target, totalRequired, productionRate); + this.ignoreUpstream = ignoreUpstream; + } public ProductionEdge(Item source, Item target, double totalRequired, double productionRate) { this.source = source; @@ -28,6 +34,13 @@ public class ProductionEdge { } public double getTotalRequired() { + if (ignoreUpstream){ + return 0.0; + } + return totalRequired; + } + public double getTotalProduced(){ + // for byproducts return totalRequired; } @@ -36,6 +49,9 @@ public class ProductionEdge { } public double getInstances() { + if (ignoreUpstream){ + return 0.0; + } return instances; } diff --git a/src/main/java/satisfactory/items/Recipe.java b/src/main/java/satisfactory/items/Recipe.java index ebb76c0..28ab6ed 100644 --- a/src/main/java/satisfactory/items/Recipe.java +++ b/src/main/java/satisfactory/items/Recipe.java @@ -179,7 +179,11 @@ public class Recipe { private double getByproductRate(Item main, Item product, double production) { double runs = getRequiredProcessRuns(main, production); - return product.getRecipe().outputs.get(product) * runs; + System.out.printf("BY-RATE: %s -> %s%n", main.getName(), product.getName()); + if (!main.getRecipe().outputs.containsKey(product)){ + return Double.NaN; + } + return main.getRecipe().outputs.get(product) * runs; } public SumResult sum(Item target, double prodPerMinute) { @@ -192,6 +196,7 @@ public class Recipe { production.addVertex(target); production.addEdge(target, target, new ProductionEdge(target, target, prodPerMinute, processesNeeded(target, prodPerMinute))); Set visited = new HashSet<>(); // keep track of which items are already expanded fully into the graph + Set by = new HashSet<>(); // keep track of which items are already expanded fully into the graph while (!queue.isEmpty()) { Item item = queue.remove(); if (!visited.contains(item)) { @@ -236,15 +241,22 @@ public class Recipe { } if (!byProducts.isEmpty()) { double finalSum = sum; - byProducts.forEach(item1 -> { - production.addVertex(item1); + byProducts.forEach(byproduct -> { + production.addVertex(byproduct); // TODO: calculate produced amount - double byproductRate = getByproductRate(item, item1, finalSum); - production.addEdge(item, item1, new ProductionEdge(item, item1, byproductRate, processesNeeded(item, finalSum))); + double byproductRate = getByproductRate(item, byproduct, finalSum); + production.addEdge(item, byproduct, new ProductionEdge(item, byproduct, byproductRate, processesNeeded(item, finalSum), true)); }); + by.addAll(byProducts); } visited.add(item); } + by.forEach(item -> {production.incomingEdgesOf(item).forEach(productionEdge -> { + Item source = productionEdge.getSource(); + double sourceRate = map.get(source); + double byProductRate = getByproductRate(source, item, sourceRate); + map.put(item, byProductRate + map.getOrDefault(item,0.0)); + });}); map.forEach((item, aDouble) -> System.out.println(item.getName() + ": " + aDouble)); return new SumResult(production, map); } diff --git a/src/main/java/satisfactory/items/SumResult.java b/src/main/java/satisfactory/items/SumResult.java index 1fc5a95..89bebd7 100644 --- a/src/main/java/satisfactory/items/SumResult.java +++ b/src/main/java/satisfactory/items/SumResult.java @@ -29,6 +29,11 @@ public class SumResult { .map(prod -> prod.getItem().getRecipe().sum(prod.getItem(), prod.getAmount())) .reduce(SumResult::merge).orElse(new SumResult()); } + public static SumResult sum(List productions) { + return productions.stream() + .map(prod -> prod.getItem().getRecipe().sum(prod.getItem(), prod.getAmount())) + .reduce(SumResult::merge).orElse(new SumResult()); + } public static Graph merge(Graph graph0, Graph graph1) { // ToDo: test! @@ -69,8 +74,7 @@ public class SumResult { } public SumResult merge(SumResult other) { - HashMap map = new HashMap<>(); - map.putAll(this.map); + HashMap map = new HashMap<>(this.map); other.map.forEach((item, aDouble) -> map.merge(item, aDouble, Double::sum)); return new SumResult(merge(production, other.getProduction()), map); } diff --git a/src/test/java/satisfactory/items/ItemTest.java b/src/test/java/satisfactory/items/ItemTest.java index 6e65898..cebcb39 100644 --- a/src/test/java/satisfactory/items/ItemTest.java +++ b/src/test/java/satisfactory/items/ItemTest.java @@ -51,4 +51,17 @@ class ItemTest { fail(); } + @Test + void productionPlastic(){ + test(Database.Plastic,"plastic"); + } + @Test + void productionRubber(){ + test(Database.Rubber,"rubber"); + } + @Test + void productionRubberAndPlastic(){ + test("rubberAndPlastic",Database.Rubber, Database.Plastic); + } + } \ No newline at end of file diff --git a/src/test/java/satisfactory/items/Phase3Test.java b/src/test/java/satisfactory/items/Phase3Test.java index c2a6943..22f6455 100644 --- a/src/test/java/satisfactory/items/Phase3Test.java +++ b/src/test/java/satisfactory/items/Phase3Test.java @@ -3,23 +3,21 @@ package satisfactory.items; import org.junit.jupiter.api.Test; import satisfactory.Database; -import java.util.Map; - -import static satisfactory.items.TestHelper.*; +import static satisfactory.items.TestHelper.test; class Phase3Test { @Test void testPhase3_ACU() { Item item = Database.AdaptiveControlUnit; - test(item); + test(item, "p3_acu"); } @Test void testPhase3_ME() { Item item = Database.ModularEngine; - test(item); + test(item, "p3_me"); } @@ -31,70 +29,21 @@ class Phase3Test { @Test void testPhase3_ME_ACU_VF() { - // references - Map ref = merge( - ValidatedValues.get(Database.ModularEngine), - ValidatedValues.get(Database.AdaptiveControlUnit), - ValidatedValues.get(Database.VersatileFrameWork)); - ref.forEach((item, aDouble) -> System.out.println(aDouble + "\t" + item.getName())); - - // calculate - Map calculations = SumResult.sum( - new Production(Database.ModularEngine, 1), - new Production(Database.AdaptiveControlUnit, 1), - new Production(Database.VersatileFrameWork, 1) - ).getMap(); - - // assert - assertMap(ref, calculations); + test(Database.ModularEngine, Database.AdaptiveControlUnit, Database.VersatileFrameWork); } @Test void testPhase3_ME_ACU() { - // references - Map ref1 = merge( - ValidatedValues.get(Database.ModularEngine), - ValidatedValues.get(Database.AdaptiveControlUnit) - ); - - // calculate - Map calculations1 = SumResult.sum( - new Production(Database.ModularEngine, 1), - new Production(Database.AdaptiveControlUnit, 1) - ).getMap(); - - // assert - assertMap(ref1, calculations1); + test(Database.ModularEngine, Database.AdaptiveControlUnit); } @Test void testPhase3_ACU_VF() { - // references - Map ref1 = merge( - ValidatedValues.get(Database.AdaptiveControlUnit), - ValidatedValues.get(Database.VersatileFrameWork)); - - // calculate - Map calculations1 = SumResult.sum( - new Production(Database.AdaptiveControlUnit, 1), - new Production(Database.VersatileFrameWork, 1) - ).getMap(); - - // assert - assertMap(ref1, calculations1); + test(Database.AdaptiveControlUnit, Database.VersatileFrameWork); } @Test void testPhase3_ME_VF() { - // references - Map ref1 = merge( - ValidatedValues.get(Database.ModularEngine), - ValidatedValues.get(Database.VersatileFrameWork)); - - // calculate - Map calculations1 = SumResult.sum( - new Production(Database.ModularEngine, 1), - new Production(Database.VersatileFrameWork, 1) - ).getMap(); + test(Database.ModularEngine, Database.VersatileFrameWork); } } \ No newline at end of file diff --git a/src/test/java/satisfactory/items/TestHelper.java b/src/test/java/satisfactory/items/TestHelper.java index c1acdfc..f75ab4f 100644 --- a/src/test/java/satisfactory/items/TestHelper.java +++ b/src/test/java/satisfactory/items/TestHelper.java @@ -2,7 +2,9 @@ package satisfactory.items; import org.junit.jupiter.api.Test; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -38,12 +40,37 @@ public class TestHelper { assertMap(ref, calculations.getMap()); } + public static void test(String name, Item... items) { + + // references + Map ref1 = merge(Arrays.stream(items).map(ValidatedValues::get).toList()); + + // calculate + SumResult sumResult = SumResult.sum(Arrays.stream(items).map(item -> new Production(item, 1.0)).toList()); + Map calculations = sumResult.getMap(); + + // plot + if (name != null) { + name = "test_" + name; + plot2(sumResult.getProduction(), name); + javaPlot(name); + list(sumResult, name); + } + + // assert + assertMap(ref1, calculations); + } + + public static void test(Item... items) { + test(null, items); + } + private static SumResult calculate(Item item) { // calculate return SumResult.sum(new Production(item, 1)); } - public static Map merge(Map... single_refs) { + public static Map merge(List> single_refs) { Map ref = new HashMap<>(); for (Map singleRef : single_refs) { singleRef.forEach((singleItem, singleValue) -> ref.compute(singleItem, (refItem, refValue) -> singleValue + check(refValue))); @@ -77,7 +104,7 @@ public class TestHelper { //c.put("b", 4.0); e.put("b", 3.); } - Map m = merge(a, b, c); + Map m = merge(Arrays.asList(a, b, c)); e.forEach((s, aDouble) -> { assertEquals(aDouble, m.get(s)); }); diff --git a/src/test/java/satisfactory/items/ValidatedValues.java b/src/test/java/satisfactory/items/ValidatedValues.java index 6f979c6..85d59f8 100644 --- a/src/test/java/satisfactory/items/ValidatedValues.java +++ b/src/test/java/satisfactory/items/ValidatedValues.java @@ -78,6 +78,22 @@ public class ValidatedValues { ref.put(item, 1.); values.put(item, ref); } + { + Item item = Database.Plastic; + Map ref = new HashMap<>(); + ref.put(Database.CrudeOil, 1.5); + ref.put(Database.Plastic, 1.); + ref.put(Database.HeavyOilResidue, 0.5); + values.put(item, ref); + } + { + Item item = Database.Rubber; + Map ref = new HashMap<>(); + ref.put(Database.CrudeOil, 1.5); + ref.put(Database.HeavyOilResidue, 1.); + ref.put(item, 1.); + values.put(item, ref); + } } public static Map get(Item item) { @@ -113,7 +129,7 @@ public class ValidatedValues { ref.put(Database.CopperIngot, 249.0); ref.put(Database.IronRod, 90.5); ref.put(Database.IronIngot, 158.0); - //ref.put(Database.HeavyOilResidue, 39.0); // FIXME byproduct + ref.put(Database.HeavyOilResidue, 39.0); // FIXME byproduct ref.put(Database.CopperSheet, 30.0); return ref; } @@ -140,7 +156,7 @@ public class ValidatedValues { ref.put(Database.SmartPlating, 2.0); ref.put(Database.ReinforcedIronPlate, 2.0); ref.put(Database.Rubber, 15.0); - //ref.put(Database.HeavyOilResidue, 15.0); // FIXME byproduct + ref.put(Database.HeavyOilResidue, 15.0); // FIXME byproduct return ref; }