diff --git a/src/Test.java b/src/Test.java index c52fe2c..048367d 100644 --- a/src/Test.java +++ b/src/Test.java @@ -1,15 +1,17 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; +import items.Database; import items.Item; import items.Recipe; +import items.Utils; import java.util.Map; public class Test { public static void main(String[] args) throws JsonProcessingException { - //System.out.println(Database.AdaptiveControlUnit); - Map totalRequirements = Database.HeavyModularFrame.getRecipes().stream().findFirst().get().getTotalRequirements(); + //System.out.println(items.Database.AdaptiveControlUnit); + Map totalRequirements = Database.HeavyModularFrame.getRecipe().getTotalRequirements(); System.out.println(totalRequirements); ObjectMapper om = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT); @@ -17,12 +19,22 @@ public class Test { String json = om.writeValueAsString(totalRequirements); System.out.println(json); - Map rawOnly = Database.HeavyModularFrame.getRecipes().iterator().next().getRawOnly(); + Map rawOnly = Utils.getRawOnly(Database.HeavyModularFrame.getRecipe().getTotalRequirements()); String json2 = om.writeValueAsString(rawOnly); String json3 = om.writeValueAsString(Recipe.getInputs(rawOnly)); System.out.println(json2); System.out.println(json3); - System.out.println(om.writeValueAsString(Database.AdaptiveControlUnit.getRecipes().iterator().next().getRawOnly())); + System.out.println(om.writeValueAsString(Utils.getRawOnly(Database.AdaptiveControlUnit.getRecipe().getTotalRequirements()))); + System.out.println(om.writeValueAsString(Database.AdaptiveControlUnit.getRecipe().getTotalRequirements())); + + System.out.println(); + System.out.println(om.writeValueAsString(Database.AdaptiveControlUnit)); + System.out.println(Database.AdaptiveControlUnit.getProductionRate()); + System.out.println("total requirements for ACU"); + System.out.println(om.writeValueAsString(Utils.shorten(Database.AdaptiveControlUnit.getRecipe().getTotalRequirements()))); + //System.out.println(Database.AdaptiveControlUnit.getRecipe().getRequirementRates(Database.AdaptiveControlUnit)); + System.out.println("requirement rate for ACU"); + System.out.println(om.writeValueAsString(Utils.shorten(Database.AdaptiveControlUnit.getRecipe().getRequirementRates(Database.AdaptiveControlUnit)))); } } diff --git a/src/Database.java b/src/items/Database.java similarity index 84% rename from src/Database.java rename to src/items/Database.java index b1c92ba..bfe8344 100644 --- a/src/Database.java +++ b/src/items/Database.java @@ -1,8 +1,15 @@ -import items.Item; -import items.Recipe; +package items; + import items.type.*; +import java.util.*; + public class Database { + // dirty! + private static final Collection items = new HashSet<>(); + public static final Map preferences = new HashMap<>(); + + // Items & recipes public static final Item IronOre = new Ore("Iron Ore"); public static final Item IronIngot = new Ingot("Iron Ingot", new Recipe(2, IronOre, 1)); public static final Item CopperOre = new Ore("Copper Ore"); @@ -73,19 +80,37 @@ public class Database { static { { + Set ores = new HashSet<>(Arrays.asList(IronOre, Coal, Limestone, CopperOre, CateriumOre, Sulfur)); + for (Item ore : ores) { + Recipe mk1 = new Recipe(1, "Miner MK 1", false); + ore.add(mk1, 1); + Recipe mk2 = new Recipe(1, "Miner MK2", false); + ore.add(mk2, 2); + } + + Set rawFluids = new HashSet<>(Arrays.asList(CrudeOil, Water)); + // no common well yet + CrudeOil.add(new Recipe(1, "Oil extracting thingy", false), 2); + Water.add(new Recipe(1, "water pump thingy", false), 2); + } + { + // Steel Ingot Recipe recipe = new Recipe(4); recipe.addInput(IronOre, 3); recipe.addInput(Coal, 3); SteelIngot.add(recipe, 3); } { + // Iron Plate Recipe recipe = new Recipe(6, IronIngot, 3); IronPlate.add(recipe, 2); } { + // Screw Screw.add(new Recipe(6, IronRod, 1), 4); } { + // Reinforced Iron Plate Recipe recipe = new Recipe(12); recipe.addInput(IronPlate, 6); recipe.addInput(Screw, 12); @@ -94,25 +119,31 @@ public class Database { bolted.addInput(IronPlate, 18); bolted.addInput(Screw, 50); ReinforcedIronPlate.add(bolted, 3); + + ReinforcedIronPlate.setPreference(recipe); } { + // Modular Frame Recipe recipe = new Recipe(60); recipe.addInput(ReinforcedIronPlate, 3); recipe.addInput(IronRod, 12); ModularFrame.add(recipe, 2); } { + // Steel Pipe Recipe recipe = new Recipe(6); recipe.addInput(SteelIngot, 3); SteelPipe.add(recipe, 2); } { + // Encased Industrial Beam Recipe recipe = new Recipe(10); recipe.addInput(SteelBeam, 4); recipe.addInput(Concrete, 5); EncasedIndustrialBeam.add(recipe); } { + // Heavy Modular Frame Recipe recipe = new Recipe(30); recipe.addInput(ModularFrame, 5); recipe.addInput(SteelPipe, 15); @@ -121,24 +152,29 @@ public class Database { HeavyModularFrame.add(recipe); } { + // Wire Wire.add(new Recipe(4, CopperIngot, 1), 2); } { + // Quickwire Quickwire.add(new Recipe(5, CateriumIngot, 1), 5); } { + // Circuit Board Recipe recipe = new Recipe(8); recipe.addInput(CopperSheet, 2); recipe.addInput(Plastic, 4); CircuitBoard.add(recipe); } { + // A.I. Limiter Recipe recipe = new Recipe(12); recipe.addInput(CopperSheet, 5); recipe.addInput(Quickwire, 20); AILimiter.add(recipe); } { + // High Speed Connector Recipe recipe = new Recipe(16); recipe.addInput(Quickwire, 56); recipe.addInput(Cable, 10); @@ -146,6 +182,7 @@ public class Database { HighSpeedConnector.add(recipe); } { + // Biomass Biomass.add(new Recipe(5, Leaves, 10), 5); Biomass.add(new Recipe(4, Wood, 4), 20); Biomass.add(new Recipe(4, Mycelia, 10), 10); @@ -153,47 +190,56 @@ public class Database { Biomass.add(new Recipe(8, AlienOrgans, 1), 200); } { + // Fabric Recipe recipe = new Recipe(4); recipe.addInput(Mycelia); recipe.addInput(Biomass, 5); Fabric.add(recipe); } { + // Solid Biofuel SolidBiofuel.add(new Recipe(4, Biomass, 8), 4); } { + // Rotator Recipe recipe = new Recipe(15); recipe.addInput(IronRod, 5); recipe.addInput(Screw, 25); Rotor.add(recipe); } { + // Stator Recipe recipe = new Recipe(12); recipe.addInput(SteelPipe, 3); recipe.addInput(Wire, 8); Stator.add(recipe); } { + // Motor Recipe recipe = new Recipe(12); recipe.addInput(Rotor, 2); recipe.addInput(Stator, 2); Motor.add(recipe); } { + // Power Shard PowerShard.add(new Recipe(8, GreenPowerSlug, 1)); PowerShard.add(new Recipe(12, YellowPowerSlug, 1), 2); PowerShard.add(new Recipe(24, PurplePowerSlug, 1), 5); } { + // Black Powder Recipe recipe = new Recipe(8); recipe.addInput(Coal); recipe.addInput(Sulfur, 2); BlackPowder.add(recipe); } { + // Color Catridge ColorCatridge.add(new Recipe(8, FlowerPetals, 5), 10); } { + // Rifle Catridge Recipe recipe = new Recipe(20); recipe.addInput(Beacon, 1); recipe.addInput(SteelPipe, 10); @@ -202,6 +248,7 @@ public class Database { RifleCatridge.add(recipe, 5); } { + // Gas Filter Recipe recipe = new Recipe(8); recipe.addInput(Coal, 5); recipe.addInput(Rubber, 2); @@ -209,6 +256,7 @@ public class Database { GasFilter.add(recipe); } { + // Computer Recipe recipe = new Recipe(24); recipe.addInput(CircuitBoard, 10); recipe.addInput(Cable, 9); @@ -220,8 +268,11 @@ public class Database { alternative.addInput(Quickwire, 28); alternative.addInput(Rubber, 12); Computer.add(alternative); + + Computer.setPreference(recipe); } { + // Super Computer Recipe recipe = new Recipe(32); recipe.addInput(Computer, 2); recipe.addInput(AILimiter, 2); @@ -230,9 +281,11 @@ public class Database { SuperComputer.add(recipe); } { + // Empty Canister EmptyCanister.add(new Recipe(4, Plastic, 2), 4); } { + // Beacon Recipe recipe = new Recipe(8); recipe.addInput(IronPlate, 3); recipe.addInput(IronRod); @@ -241,6 +294,7 @@ public class Database { Beacon.add(recipe); } { + // Modular Engine Recipe recipe = new Recipe(60, false); recipe.addInput(Motor, 2); recipe.addInput(Rubber, 15); @@ -248,6 +302,7 @@ public class Database { ModularEngine.add(recipe); } { + // Adaptive Control Unit Recipe recipe = new Recipe(120, false); recipe.addInput(AutomatedWiring, 15); recipe.addInput(CircuitBoard, 10); @@ -256,30 +311,35 @@ public class Database { AdaptiveControlUnit.add(recipe); } { + // Nobelisk Recipe recipe = new Recipe(20, false); recipe.addInput(BlackPowder, 5); recipe.addInput(SteelPipe, 10); Nobelisk.add(recipe); } { + // Smart Plating Recipe recipe = new Recipe(30, false); recipe.addInput(ReinforcedIronPlate); recipe.addInput(Rotor); SmartPlating.add(recipe); } { + // Automated Wiring Recipe recipe = new Recipe(24, false); recipe.addInput(Stator); recipe.addInput(Cable, 20); AutomatedWiring.add(recipe); } { + // Versatile Framework Recipe recipe = new Recipe(24, false); recipe.addInput(ModularFrame); recipe.addInput(SteelBeam, 12); VersatileFrameWork.add(recipe, 2); } { + // Fuel Recipe residualFuel = new Recipe(6, "Residual Fuel", false); residualFuel.addInput(HeavyOilResidue, 6); Fuel.add(residualFuel, 4); @@ -287,14 +347,18 @@ public class Database { recipe.addInput(CrudeOil, 6); recipe.addOutput(PolymerResin, 3); Fuel.add(recipe, 4); + + Fuel.setPreference(recipe); } { + // Liquid Biofuel Recipe recipe = new Recipe(4, false); recipe.addInput(SolidBiofuel, 6); recipe.addInput(Water, 3); LiquidBiofuel.add(recipe, 4); } { + // Plastic Recipe recipe = new Recipe(6, false); recipe.addInput(CrudeOil, 3); recipe.addOutput(HeavyOilResidue, 1); @@ -303,8 +367,11 @@ public class Database { residualPlastic.addInput(PolymerResin, 6); residualPlastic.addInput(Water, 2); Plastic.add(residualPlastic, 2); + + Plastic.setPreference(recipe); } { + // Rubber Recipe recipe = new Recipe(6, false); recipe.addInput(CrudeOil, 3); recipe.addOutput(HeavyOilResidue, 2); @@ -312,12 +379,23 @@ public class Database { Recipe residualRubber = new Recipe(6, "Residual Rubber", false); residualRubber.addInput(PolymerResin, 6); residualRubber.addInput(Water, 4); - Plastic.add(residualRubber, 2); + Rubber.add(residualRubber, 2); + + Rubber.setPreference(recipe); } { + // Petroleum Coke Recipe recipe = new Recipe(6, false); recipe.addInput(HeavyOilResidue, 4); PetroleumCoke.add(recipe, 12); } } + + public static void add(Item i) { + items.add(i); + } + + public static Collection getItems() { + return new HashSet<>(items); + } } diff --git a/src/items/Item.java b/src/items/Item.java index 517bd8a..7a14ab2 100644 --- a/src/items/Item.java +++ b/src/items/Item.java @@ -4,24 +4,28 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Set; + public class Item { protected boolean isRaw = false; private String name; private Set recipes; + private Recipe preference = null; - public Item(String name, Set recipes) { + protected Item(String name, Set recipes) { this.name = name; this.recipes = recipes; + Database.add(this); + for (Recipe recipe : recipes) { + add(recipe); + } } public Item(String name, Recipe... recipes) { - this(name); - Arrays.asList(recipes).forEach(this::add); + this(name, new HashSet<>(Arrays.asList(recipes))); } public Item(String name) { - this.name = name; - this.recipes = new HashSet<>(); + this(name, new HashSet<>()); } public void add(Recipe recipe) { @@ -45,6 +49,27 @@ public class Item { return isRaw; } + public float getProductionRate() { + Recipe recipe = getRecipe(); + if (recipe == null) { + return 0; + } + return recipe.getProductionRate(this); + } + + public Recipe getRecipe() { + Recipe recipe = preference; + if (recipe == null) { + recipe = recipes.stream().findFirst().orElse(null); + if (recipe == null) { + if (Database.preferences.containsKey(this)) { + recipe = Database.preferences.get(this); + } + } + } + return recipe; + } + @Override public String toString() { return "Item{" + @@ -52,4 +77,9 @@ public class Item { ", recipes=" + recipes + '}'; } + + public void setPreference(Recipe preference) { + this.preference = preference; + } + } diff --git a/src/items/Recipe.java b/src/items/Recipe.java index 6641478..e00719a 100644 --- a/src/items/Recipe.java +++ b/src/items/Recipe.java @@ -1,5 +1,8 @@ package items; +import items.requirements.RateAccumulator; +import items.requirements.TotalAccumulator; + import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; @@ -28,6 +31,7 @@ public class Recipe { } public Recipe(int duration, Map inputs, Map outputs) { + this.duration = duration; this.inputs = inputs; this.outputs = outputs; } @@ -82,34 +86,21 @@ public class Recipe { } public Map getTotalRequirements() { - Map total = new HashMap<>(); - Map queue = new HashMap<>(); - for (Item i : inputs.keySet()) { - queue.put(i, inputs.get(i)); - } - while (!queue.isEmpty()) { - Item i = queue.keySet().iterator().next(); - int amount = queue.remove(i); - total.put(i, total.getOrDefault(i, 0) + amount); - if (i.getRecipes().isEmpty()) { - continue; - } - Recipe r = i.getRecipes().iterator().next(); - Map subRequirements = r.getTotalRequirements(); - for (Item subItem : subRequirements.keySet()) { - int subAmount = subRequirements.get(subItem); - total.put(subItem, total.getOrDefault(subItem, 0) + subAmount * amount); - } - } - return total; + return new TotalAccumulator(inputs).accumulate(); } - public Map getRawOnly() { - Map totals = getTotalRequirements(); - Map raws = new HashMap<>(); - for (Item item : totals.keySet().stream().filter(Item::isRaw).collect(Collectors.toList())) { - raws.put(item, totals.get(item)); - } - return raws; + public float getProductionRate(Item item) { + Integer integer = outputs.get(item); + float production = integer; + return production / duration; + } + + public Map getRequirementRates(Item item){ + float rate = getProductionRate(item); + return new RateAccumulator(this, item).accumulate(); + } + + public Map getInputs() { + return inputs; } } diff --git a/src/items/Utils.java b/src/items/Utils.java new file mode 100644 index 0000000..f5fab1d --- /dev/null +++ b/src/items/Utils.java @@ -0,0 +1,21 @@ +package items; + +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; + +public class Utils { + public static Map getRawOnly(Map totals) { + Map raws = new HashMap<>(); + for (Item item : totals.keySet().stream().filter(Item::isRaw).collect(Collectors.toList())) { + raws.put(item, totals.get(item)); + } + return raws; + } + + public static Map shorten(Map totals){ + Map shortend = new HashMap<>(); + totals.forEach((item, e) -> shortend.put(item.getName(), e)); + return shortend; + } +} diff --git a/src/items/requirements/Accumulator.java b/src/items/requirements/Accumulator.java new file mode 100644 index 0000000..d3b29ef --- /dev/null +++ b/src/items/requirements/Accumulator.java @@ -0,0 +1,48 @@ +package items.requirements; + +import items.Item; +import items.Recipe; + +import java.util.HashMap; +import java.util.Map; + +public abstract class Accumulator implements RequirementAccumulator{ + protected Map inputs; + + public Accumulator(Map inputs) { + this.inputs = inputs; + } + + protected abstract E calculate(Item i, E subAmount, E amount, Map total); + + protected abstract E dequeue(Item item, E amount, Map totals); + + @Override + public Map accumulate() { + Map total = new HashMap<>(); + Map queue = new HashMap<>(); + for (Item i : inputs.keySet()) { + queue.put(i, inputs.get(i)); + } + while (!queue.isEmpty()) { + Item i = queue.keySet().iterator().next(); + E amount = queue.remove(i); + E newTotal = dequeue(i, amount, total); + total.put(i,newTotal); + if (i.getRecipes().isEmpty()) { + continue; + } + Recipe r = i.getRecipes().iterator().next(); + Map subRequirements = getRequirements(r, i); + for (Item subItem : subRequirements.keySet()) { + E subAmount = subRequirements.get(subItem); + E newSubTotal = calculate(subItem, subAmount, amount, total); + total.put(subItem, newSubTotal); + } + } + return total; + } + + protected abstract Map getRequirements(Recipe r, Item i);// r.getTotalRequirements() + +} diff --git a/src/items/requirements/RateAccumulator.java b/src/items/requirements/RateAccumulator.java new file mode 100644 index 0000000..2e6770d --- /dev/null +++ b/src/items/requirements/RateAccumulator.java @@ -0,0 +1,34 @@ +package items.requirements; + +import items.Item; +import items.Recipe; + +import java.util.HashMap; +import java.util.Map; + +public class RateAccumulator extends Accumulator { + private Item item; + + public RateAccumulator(Recipe recipe, Item item) { + super(new HashMap<>()); + recipe.getInputs().forEach((item1, integer) -> inputs.put(item1, Float.valueOf(integer))); + this.item = item; + } + + @Override + protected Float calculate(Item i, Float subAmount, Float amount, Map total) { + Float base = total.getOrDefault(i, 0f); + float additional = subAmount * amount * i.getProductionRate(); + return base + additional; + } + + @Override + protected Float dequeue(Item item, Float amount, Map totals) { + return totals.getOrDefault(item, 0f) + amount; + } + + @Override + protected Map getRequirements(Recipe r, Item i) { + return r.getRequirementRates(i); + } +} diff --git a/src/items/requirements/RequirementAccumulator.java b/src/items/requirements/RequirementAccumulator.java new file mode 100644 index 0000000..cb971c2 --- /dev/null +++ b/src/items/requirements/RequirementAccumulator.java @@ -0,0 +1,9 @@ +package items.requirements; + +import items.Item; + +import java.util.Map; + +public interface RequirementAccumulator { + Map accumulate(); +} diff --git a/src/items/requirements/TotalAccumulator.java b/src/items/requirements/TotalAccumulator.java new file mode 100644 index 0000000..26a7362 --- /dev/null +++ b/src/items/requirements/TotalAccumulator.java @@ -0,0 +1,29 @@ +package items.requirements; + +import items.Item; +import items.Recipe; + +import java.util.Map; + +public class TotalAccumulator extends Accumulator{ + + public TotalAccumulator(Map inputs) { + super(inputs); + } + + @Override + protected Integer calculate(Item i, Integer subAmount, Integer amount, Map total) { + return total.getOrDefault(i, 0) + subAmount * amount; + } + + + @Override + protected Integer dequeue(Item item, Integer amount, Map totals) { + return totals.getOrDefault(item, 0) + amount; + } + + @Override + protected Map getRequirements(Recipe r, Item i) { + return r.getTotalRequirements(); + } +} diff --git a/src/items/type/Fluid.java b/src/items/type/Fluid.java index 07afb80..a8ab3c4 100644 --- a/src/items/type/Fluid.java +++ b/src/items/type/Fluid.java @@ -6,9 +6,6 @@ import items.Recipe; import java.util.Set; public abstract class Fluid extends Item { - public Fluid(String name, Set recipes) { - super(name, recipes); - } public Fluid(String name, Recipe... recipes) { super(name, recipes); diff --git a/src/items/type/Ingot.java b/src/items/type/Ingot.java index f5e7017..113d2b9 100644 --- a/src/items/type/Ingot.java +++ b/src/items/type/Ingot.java @@ -6,9 +6,6 @@ import items.Recipe; import java.util.Set; public class Ingot extends Item { - public Ingot(String name, Set recipes) { - super(name, recipes); - } public Ingot(String name, Recipe... recipes) { super(name, recipes); diff --git a/src/items/type/Ore.java b/src/items/type/Ore.java index af6e5c5..55790b2 100644 --- a/src/items/type/Ore.java +++ b/src/items/type/Ore.java @@ -6,10 +6,6 @@ import items.Recipe; import java.util.Set; public class Ore extends Item { - public Ore(String name, Set recipes) { - super(name, recipes); - setIsRaw(); - } public Ore(String name, Recipe... recipes) { super(name, recipes); diff --git a/src/items/type/Part.java b/src/items/type/Part.java index afe361d..087b91c 100644 --- a/src/items/type/Part.java +++ b/src/items/type/Part.java @@ -6,9 +6,6 @@ import items.Recipe; import java.util.Set; public class Part extends Item { - public Part(String name, Set recipes) { - super(name, recipes); - } public Part(String name, Recipe... recipes) { super(name, recipes); diff --git a/src/items/type/Pickup.java b/src/items/type/Pickup.java index 16d9543..0c15c97 100644 --- a/src/items/type/Pickup.java +++ b/src/items/type/Pickup.java @@ -6,9 +6,6 @@ import items.Recipe; import java.util.Set; public class Pickup extends Item { - public Pickup(String name, Set recipes) { - super(name, recipes); - } public Pickup(String name, Recipe... recipes) { super(name, recipes); diff --git a/src/items/type/ProcessedFluid.java b/src/items/type/ProcessedFluid.java index 8cec3d8..7a77a92 100644 --- a/src/items/type/ProcessedFluid.java +++ b/src/items/type/ProcessedFluid.java @@ -5,9 +5,6 @@ import items.Recipe; import java.util.Set; public class ProcessedFluid extends Fluid { - public ProcessedFluid(String name, Set recipes) { - super(name, recipes); - } public ProcessedFluid(String name, Recipe... recipes) { super(name, recipes); diff --git a/src/items/type/RawFluid.java b/src/items/type/RawFluid.java index 25d2a39..7c4c3b1 100644 --- a/src/items/type/RawFluid.java +++ b/src/items/type/RawFluid.java @@ -5,10 +5,6 @@ import items.Recipe; import java.util.Set; public class RawFluid extends Fluid { - public RawFluid(String name, Set recipes) { - super(name, recipes); - setIsRaw(); - } public RawFluid(String name, Recipe... recipes) { super(name, recipes); diff --git a/src/items/type/Tool.java b/src/items/type/Tool.java index 8bcd233..ba19f17 100644 --- a/src/items/type/Tool.java +++ b/src/items/type/Tool.java @@ -6,9 +6,6 @@ import items.Recipe; import java.util.Set; public class Tool extends Item { - public Tool(String name, Set recipes) { - super(name, recipes); - } public Tool(String name, Recipe... recipes) { super(name, recipes);