fix algorithm: correct handling of not yet expanded usages of items
parent
c42915ecb4
commit
d872dd2b54
|
|
@ -793,7 +793,7 @@ public class Database {
|
|||
}
|
||||
|
||||
public static Item add(Item i) {
|
||||
items.add(i);
|
||||
//items.add(i);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -145,6 +145,8 @@ public class Test {
|
|||
planFor("p3_me", new Production(Database.ModularEngine, 1));
|
||||
planFor("p3_vf", new Production(Database.VersatileFrameWork, 1));
|
||||
planFor("screw", new Production(Database.ReinforcedIronPlate, 1));
|
||||
planFor("rotor", new Production(Database.Rotor, 1));
|
||||
planFor("mf", new Production(Database.ModularFrame, 1));
|
||||
}
|
||||
|
||||
private static void planFor(Item item, int amount, String name) {
|
||||
|
|
|
|||
|
|
@ -178,18 +178,15 @@ public class Recipe {
|
|||
Graph<Item, DefaultWeightedEdge> buildGraph = buildGraph(target);
|
||||
Graph<Item, ProductionEdge> production = new DefaultDirectedWeightedGraph<>(ProductionEdge.class);
|
||||
Map<Item, Double> map = new HashMap<>();
|
||||
Queue<Item> queue = new LinkedList<>();
|
||||
Queue<Item> queue = new LinkedList<>(); // items left to expand / update
|
||||
queue.add(target);
|
||||
map.put(target, prodPerMinute);
|
||||
production.addVertex(target);
|
||||
production.addEdge(target, target, new ProductionEdge(target, target, prodPerMinute, processesNeeded(target, prodPerMinute)));
|
||||
Set<Item> visited = new HashSet<>();
|
||||
Set<Item> visited = 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)) {
|
||||
System.out.println("hint: already processed " + item.getName() + "! Skip!");
|
||||
//continue;
|
||||
} else {
|
||||
if (!visited.contains(item)) {
|
||||
// next items
|
||||
buildGraph.incomingEdgesOf(item)
|
||||
.stream()
|
||||
|
|
@ -202,15 +199,17 @@ public class Recipe {
|
|||
for (DefaultWeightedEdge edge : buildGraph.outgoingEdgesOf(item)) {
|
||||
Item product = buildGraph.getEdgeTarget(edge);
|
||||
Double productWantedPerMinute = map.get(product);
|
||||
System.out.println(item.getName());
|
||||
if (item.getRecipe().outputs.containsKey(product)) { // TODO: method isByProduct
|
||||
// product is by-product, no forward dependency
|
||||
System.out.println("BY-PRODUCT " + item.getName() + " -> " + product.getName() + "... " + queue);
|
||||
byProducts.add(product);
|
||||
continue;
|
||||
}
|
||||
if (productWantedPerMinute == null) {
|
||||
if (queue.contains(product) || productWantedPerMinute == null) {
|
||||
// defer update, no all usages are expanded yet
|
||||
System.err.println("product still queued or productWantedPerMinute null for '" + product.getName() + "' from '" + item.getName() + "'");
|
||||
sum = 0;
|
||||
queue.add(item);
|
||||
break;
|
||||
}
|
||||
double amountNeeded = buildGraph.getEdgeWeight(edge);
|
||||
|
|
@ -221,7 +220,7 @@ public class Recipe {
|
|||
production.addVertex(item);
|
||||
production.addEdge(item, product, new ProductionEdge(item, product, requiredInput, processesNeeded(item, requiredInput)));
|
||||
}
|
||||
if (!map.containsKey(item) && sum > 0) {
|
||||
if (sum > 0) {
|
||||
map.put(item, sum);
|
||||
}
|
||||
if (!byProducts.isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
package satisfactory;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class PlanTest {
|
||||
|
||||
@Test
|
||||
void twoItems() {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,8 @@ package satisfactory.items;
|
|||
import org.junit.jupiter.api.Test;
|
||||
import satisfactory.Database;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class DatabaseTest {
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -1,15 +1,9 @@
|
|||
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.*;
|
||||
import static satisfactory.items.TestHelper.assertMap;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static satisfactory.items.TestHelper.test;
|
||||
|
||||
class ItemTest {
|
||||
|
|
@ -20,20 +14,28 @@ class ItemTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void productionScrews2() {
|
||||
/*Map<Item, Double> production = Database.Screw.getRecipe().sum(Database.Screw, 100);
|
||||
assertEquals(100, production.get(Database.Screw), "Screws (output)");
|
||||
assertEquals(25, production.get(Database.IronRod), "IronRod");
|
||||
assertEquals(25, production.get(Database.IronIngot), "IronIngot");
|
||||
assertEquals(25, production.get(Database.IronOre), "IronOre");
|
||||
|
||||
*/
|
||||
fail("TODO: migrate");
|
||||
void productionReinforcedIronPlates() {
|
||||
test(Database.ReinforcedIronPlate);
|
||||
}
|
||||
|
||||
@Test
|
||||
void productionReinforcedIronPlates() {
|
||||
test(Database.ReinforcedIronPlate);
|
||||
void productionModularFrame() {
|
||||
test(Database.ModularFrame);
|
||||
}
|
||||
|
||||
@Test
|
||||
void productionSteelPipe() {
|
||||
test(Database.SteelPipe);
|
||||
}
|
||||
|
||||
@Test
|
||||
void productionRotor() {
|
||||
test(Database.Rotor);
|
||||
}
|
||||
|
||||
@Test
|
||||
void productionEncasedIndustrialBeam() {
|
||||
test(Database.EncasedIndustrialBeam);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -3,12 +3,9 @@ package satisfactory.items;
|
|||
import org.junit.jupiter.api.Test;
|
||||
import satisfactory.Database;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static satisfactory.items.TestHelper.assertMap;
|
||||
import static satisfactory.items.TestHelper.test;
|
||||
import static satisfactory.items.ValidatedValues.*;
|
||||
import static satisfactory.items.TestHelper.*;
|
||||
|
||||
class Phase3Test {
|
||||
|
||||
|
|
@ -32,14 +29,6 @@ class Phase3Test {
|
|||
test(item);
|
||||
}
|
||||
|
||||
private Double check(
|
||||
Double test) {
|
||||
if (test == null) {
|
||||
return 0.0;
|
||||
}
|
||||
return test;
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPhase3_ME_ACU_VF() {
|
||||
// references
|
||||
|
|
@ -60,170 +49,52 @@ class Phase3Test {
|
|||
assertMap(ref, calculations);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMerge() {
|
||||
Map<String, Double> a = new HashMap<>();
|
||||
Map<String, Double> b = new HashMap<>();
|
||||
Map<String, Double> c = new HashMap<>();
|
||||
Map<String, Double> e = new HashMap<>();
|
||||
{
|
||||
a.put("a", 1.0);
|
||||
b.put("a", 2.0);
|
||||
c.put("a", 4.0);
|
||||
e.put("a", 7.);
|
||||
}
|
||||
{
|
||||
a.put("b", 1.0);
|
||||
b.put("b", 2.0);
|
||||
//c.put("b", 4.0);
|
||||
e.put("b", 3.);
|
||||
}
|
||||
Map<String, Double> m = merge(a,b,c);
|
||||
e.forEach((s, aDouble) -> {
|
||||
assertEquals(aDouble, m.get(s));
|
||||
});
|
||||
}
|
||||
|
||||
private <K> Map<K, Double> merge(Map<K, Double>... single_refs) {
|
||||
Map<K, Double> ref = new HashMap<>();
|
||||
for (Map<K, Double> singleRef : single_refs) {
|
||||
singleRef.forEach((singleItem, singleValue) -> ref.compute(singleItem, (refItem, refValue) -> singleValue + check(refValue)));
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
@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);
|
||||
Map<Item, Double> ref1 = merge(
|
||||
ValidatedValues.get(Database.ModularEngine),
|
||||
ValidatedValues.get(Database.AdaptiveControlUnit)
|
||||
);
|
||||
|
||||
// calculate
|
||||
Map<Item, Double> calculations = SumResult.sum(new Production(Database.ModularEngine, 1), new Production(Database.AdaptiveControlUnit, 1)).getMap();
|
||||
Map<Item, Double> calculations1 = SumResult.sum(
|
||||
new Production(Database.ModularEngine, 1),
|
||||
new Production(Database.AdaptiveControlUnit, 1)
|
||||
).getMap();
|
||||
|
||||
// assert
|
||||
assertMap(ref, calculations);
|
||||
assertMap(ref1, calculations1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPhase3_ACU_VF() {
|
||||
// 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);
|
||||
Map<Item, Double> ref1 = merge(
|
||||
ValidatedValues.get(Database.AdaptiveControlUnit),
|
||||
ValidatedValues.get(Database.VersatileFrameWork));
|
||||
|
||||
// calculate
|
||||
Map<Item, Double> calculations = SumResult.sum(new Production(Database.AdaptiveControlUnit, 1), new Production(Database.VersatileFrameWork, 1)).getMap();
|
||||
Map<Item, Double> calculations1 = SumResult.sum(
|
||||
new Production(Database.AdaptiveControlUnit, 1),
|
||||
new Production(Database.VersatileFrameWork, 1)
|
||||
).getMap();
|
||||
|
||||
// assert
|
||||
assertMap(ref, calculations);
|
||||
assertMap(ref1, calculations1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPhase3_ME_VF() {
|
||||
// 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);
|
||||
Map<Item, Double> ref1 = merge(
|
||||
ValidatedValues.get(Database.ModularEngine),
|
||||
ValidatedValues.get(Database.VersatileFrameWork));
|
||||
|
||||
// calculate
|
||||
Map<Item, Double> calculations = SumResult.sum(new Production(Database.ModularEngine, 1), new Production(Database.VersatileFrameWork, 1)).getMap();
|
||||
|
||||
// assert
|
||||
assertMap(ref, calculations);
|
||||
Map<Item, Double> calculations1 = SumResult.sum(
|
||||
new Production(Database.ModularEngine, 1),
|
||||
new Production(Database.VersatileFrameWork, 1)
|
||||
).getMap();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
package satisfactory.items;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
|
@ -21,7 +24,46 @@ public class TestHelper {
|
|||
|
||||
// calculate
|
||||
Map<Item, Double> calculations = SumResult.sum(new Production(item, 1)).getMap();
|
||||
|
||||
assertMap(ref, calculations);
|
||||
}
|
||||
|
||||
public static <K> Map<K, Double> merge(Map<K, Double>... single_refs) {
|
||||
Map<K, Double> ref = new HashMap<>();
|
||||
for (Map<K, Double> singleRef : single_refs) {
|
||||
singleRef.forEach((singleItem, singleValue) -> ref.compute(singleItem, (refItem, refValue) -> singleValue + check(refValue)));
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
private static Double check(
|
||||
Double test) {
|
||||
if (test == null) {
|
||||
return 0.0;
|
||||
}
|
||||
return test;
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMerge() {
|
||||
Map<String, Double> a = new HashMap<>();
|
||||
Map<String, Double> b = new HashMap<>();
|
||||
Map<String, Double> c = new HashMap<>();
|
||||
Map<String, Double> e = new HashMap<>();
|
||||
{
|
||||
a.put("a", 1.0);
|
||||
b.put("a", 2.0);
|
||||
c.put("a", 4.0);
|
||||
e.put("a", 7.);
|
||||
}
|
||||
{
|
||||
a.put("b", 1.0);
|
||||
b.put("b", 2.0);
|
||||
//c.put("b", 4.0);
|
||||
e.put("b", 3.);
|
||||
}
|
||||
Map<String, Double> m = merge(a, b, c);
|
||||
e.forEach((s, aDouble) -> {
|
||||
assertEquals(aDouble, m.get(s));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import java.util.Map;
|
|||
|
||||
public class ValidatedValues {
|
||||
|
||||
private static Map<Item, Map<Item, Double>> values = new HashMap<>();
|
||||
private static final Map<Item, Map<Item, Double>> values = new HashMap<>();
|
||||
|
||||
static {
|
||||
values.put(Database.AdaptiveControlUnit, ACU());
|
||||
|
|
@ -34,6 +34,49 @@ public class ValidatedValues {
|
|||
ref.put(item, 1.);
|
||||
values.put(item, ref);
|
||||
}
|
||||
{
|
||||
Item item = Database.ModularFrame;
|
||||
Map<Item, Double> ref = new HashMap<>();
|
||||
ref.put(Database.IronOre, 24.);
|
||||
ref.put(Database.IronIngot, 24.);
|
||||
ref.put(Database.IronRod, 10.5);
|
||||
ref.put(Database.IronPlate, 9.);
|
||||
ref.put(Database.Screw, 18.);
|
||||
ref.put(Database.ReinforcedIronPlate, 1.5);
|
||||
ref.put(item, 1.);
|
||||
values.put(item, ref);
|
||||
}
|
||||
{
|
||||
Item item = Database.SteelPipe;
|
||||
Map<Item, Double> ref = new HashMap<>();
|
||||
ref.put(Database.IronOre, 1.5);
|
||||
ref.put(Database.Coal, 1.5);
|
||||
ref.put(Database.SteelIngot, 1.5);
|
||||
ref.put(item, 1.);
|
||||
values.put(item, ref);
|
||||
}
|
||||
{
|
||||
Item item = Database.Rotor;
|
||||
Map<Item, Double> ref = new HashMap<>();
|
||||
ref.put(Database.IronOre, 11.25);
|
||||
ref.put(Database.IronIngot, 11.25);
|
||||
ref.put(Database.IronRod, 11.25);
|
||||
ref.put(Database.Screw, 25.);
|
||||
ref.put(item, 1.);
|
||||
values.put(item, ref);
|
||||
}
|
||||
{
|
||||
Item item = Database.EncasedIndustrialBeam;
|
||||
Map<Item, Double> ref = new HashMap<>();
|
||||
ref.put(Database.IronOre, 16.);
|
||||
ref.put(Database.Coal, 16.);
|
||||
ref.put(Database.SteelIngot, 16.);
|
||||
ref.put(Database.Limestone, 15.);
|
||||
ref.put(Database.Concrete, 5.);
|
||||
ref.put(Database.SteelBeam, 4.);
|
||||
ref.put(item, 1.);
|
||||
values.put(item, ref);
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<Item, Double> get(Item item) {
|
||||
|
|
@ -69,7 +112,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);
|
||||
//ref.put(Database.HeavyOilResidue, 39.0); // FIXME byproduct
|
||||
ref.put(Database.CopperSheet, 30.0);
|
||||
return ref;
|
||||
}
|
||||
|
|
@ -96,7 +139,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);
|
||||
//ref.put(Database.HeavyOilResidue, 15.0); // FIXME byproduct
|
||||
return ref;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue