From 739219c57b7c703a6ed7ed9549030c8c45b8c949 Mon Sep 17 00:00:00 2001 From: Timmeey86 Date: Tue, 27 Nov 2018 22:28:41 +0100 Subject: [PATCH] Finished first draft of ItemLiquidGenerator through TDD --- .../blocks/power/ItemLiquidGenerator.java | 14 ++- .../java/power/ItemLiquidGeneratorTests.java | 87 +++++++++++++++---- 2 files changed, 78 insertions(+), 23 deletions(-) diff --git a/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java index 83031719d2..83d433b8c6 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java @@ -45,8 +45,12 @@ public abstract class ItemLiquidGenerator extends ItemGenerator{ } } - //liquid takes priority over solids + entity.productionEfficiency = 0.0f; + // Note: Do not use this delta when calculating the amount of power or the power efficiency, but use it for resource consumption if necessary. + // Power amount is delta'd by PowerGraph class already. float calculationDelta = entity.delta(); + + //liquid takes priority over solids if(liquid != null && entity.liquids.get(liquid) >= 0.001f && entity.cons.valid()){ float baseLiquidEfficiency = getLiquidEfficiency(liquid) * this.liquidPowerMultiplier; float maximumPossible = maxLiquidGenerate * calculationDelta; @@ -62,22 +66,16 @@ public abstract class ItemLiquidGenerator extends ItemGenerator{ } }else if(entity.cons.valid()){ - // TODO: Adapt to new power system - //float maxPower = Math.min(powerCapacity - entity.power.amount, powerOutput * entity.delta()) * entity.efficiency; - if(entity.generateTime <= 0f && entity.items.total() > 0){ Effects.effect(generateEffect, tile.worldx() + Mathf.range(3f), tile.worldy() + Mathf.range(3f)); Item item = entity.items.take(); - // TODO: Adapt to new power system - //entity.efficiency = getItemEfficiency(item); + entity.productionEfficiency = getItemEfficiency(item); entity.explosiveness = item.explosiveness; entity.generateTime = 1f; } if(entity.generateTime > 0f){ entity.generateTime -= 1f / itemDuration * entity.delta(); - // TODO: Adapt to new power system - //entity.power.amount += maxPower; entity.generateTime = Mathf.clamp(entity.generateTime); if(Mathf.chance(entity.delta() * 0.06 * Mathf.clamp(entity.explosiveness - 0.25f))){ diff --git a/tests/src/test/java/power/ItemLiquidGeneratorTests.java b/tests/src/test/java/power/ItemLiquidGeneratorTests.java index cf54743faf..f8685709c7 100644 --- a/tests/src/test/java/power/ItemLiquidGeneratorTests.java +++ b/tests/src/test/java/power/ItemLiquidGeneratorTests.java @@ -1,5 +1,7 @@ package power; +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.content.Items; import io.anuke.mindustry.content.Liquids; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Liquid; @@ -8,22 +10,25 @@ import io.anuke.mindustry.world.blocks.power.BurnerGenerator; import io.anuke.mindustry.world.blocks.power.ItemGenerator; import io.anuke.mindustry.world.blocks.power.ItemLiquidGenerator; import io.anuke.mindustry.world.blocks.power.PowerGenerator; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.DynamicTest.dynamicTest; -/** This class tests the abstract ItemLiquidGenerator class and maybe some of its dependencies. */ +/** + * This class tests ItemLiquidGenerators. Currently, testing is only performed on the BurnerGenerator subclass, + * which means only power calculations based on flammability are tested. + */ public class ItemLiquidGeneratorTests extends PowerTestFixture{ private ItemLiquidGenerator generator; private Tile tile; private ItemGenerator.ItemGeneratorEntity entity; private final float fakeLiquidPowerMultiplier = 2.0f; - private final float fakeMaxLiquidGenerate = 0.5f; + private final float fakeItemDuration = 0.5f; + private final float maximumLiquidUsage = 0.5f; @BeforeEach public void createBurnerGenerator(){ @@ -32,26 +37,78 @@ public class ItemLiquidGeneratorTests extends PowerTestFixture{ powerProduction = 0.1f; itemDuration = 60f; liquidPowerMultiplier = fakeLiquidPowerMultiplier; - maxLiquidGenerate = fakeMaxLiquidGenerate; + itemDuration = fakeItemDuration; + maxLiquidGenerate = maximumLiquidUsage; }}; tile = createFakeTile(0, 0, generator); entity = tile.entity(); } - @Test - void testLiquidConsumption(){ - final float providedUsage = 0.1f; - final float expectedEfficiency = providedUsage / fakeMaxLiquidGenerate * fakeLiquidPowerMultiplier * Liquids.oil.flammability; + /** Tests the consumption and efficiency when being supplied with liquids. */ + @TestFactory + DynamicTest[] testLiquidConsumption(){ + return new DynamicTest[]{ + dynamicTest("01", () -> test_liquidConsumption(Liquids.oil, 0.0f, "No liquids provided")), + dynamicTest("02", () -> test_liquidConsumption(Liquids.oil, maximumLiquidUsage / 4.0f, "Low oil provided")), + dynamicTest("03", () -> test_liquidConsumption(Liquids.oil, maximumLiquidUsage * 1.0f, "Sufficient oil provided")), + dynamicTest("04", () -> test_liquidConsumption(Liquids.oil, maximumLiquidUsage * 2.0f, "Excess oil provided")) + // Note: The generator will decline any other liquid since it's not flammable + }; + } - entity.liquids.add(Liquids.oil, providedUsage); + void test_liquidConsumption(Liquid liquid, float availableLiquidAmount, String parameterDescription){ + final float expectedEfficiency = Math.min(1.0f, availableLiquidAmount / maximumLiquidUsage) * fakeLiquidPowerMultiplier * liquid.flammability; + final float expectedRemainingLiquidAmount = liquid.flammability > 0f ? Math.max(0.0f, availableLiquidAmount - maximumLiquidUsage) : availableLiquidAmount; + assertTrue(generator.acceptLiquid(tile, null, liquid, availableLiquidAmount), parameterDescription + ": Liquids which will be declined by the generator don't need to be tested - The code won't be called for those cases."); + + // Reset liquids since BeforeEach will not be called between dynamic tests + for(Liquid tmpLiquid : Vars.content.liquids()){ + entity.liquids.reset(tmpLiquid, 0.0f); + } + entity.liquids.add(liquid, availableLiquidAmount); entity.cons.update(tile.entity); - assumeTrue(entity.cons.valid()); + assertTrue(entity.cons.valid()); - // Perform an update on the generator once - This should use up all oil and produce a fraction of what's possible + // Perform an update on the generator once - This should use up any resource up to the maximum liquid usage generator.update(tile); - assertEquals(0.0f, entity.liquids.get(Liquids.oil)); - assertEquals(expectedEfficiency, entity.productionEfficiency); + assertEquals(expectedRemainingLiquidAmount, entity.liquids.get(liquid), parameterDescription + ": Remaining liquid amount mismatch."); + assertEquals(expectedEfficiency, entity.productionEfficiency, parameterDescription + ": Efficiency mismatch."); + } + + /** Tests the consumption and efficiency when being supplied with items. */ + @TestFactory + DynamicTest[] testItemConsumption(){ + return new DynamicTest[]{ + dynamicTest("01", () -> test_itemConsumption(Items.coal, 0, "No items provided")), + dynamicTest("02", () -> test_itemConsumption(Items.coal, 1, "Sufficient coal provided")), + dynamicTest("03", () -> test_itemConsumption(Items.coal, 10, "Excess coal provided")), + dynamicTest("04", () -> test_itemConsumption(Items.blastCompound, 1, "Blast compound provided")), + //dynamicTest("03", () -> test_itemConsumption(Items.plastanium, 1, "Plastanium provided")), // Not accepted by generator due to low flammability + dynamicTest("05", () -> test_itemConsumption(Items.biomatter, 1, "Biomatter provided")), + dynamicTest("06", () -> test_itemConsumption(Items.pyratite, 1, "Pyratite provided")) + }; + } + + void test_itemConsumption(Item item, int amount, String parameterDescription){ + final float expectedEfficiency = Math.min(1.0f, amount > 0 ? item.flammability : 0f); + final float expectedRemainingItemAmount = Math.max(0, amount - 1); + assertTrue(generator.acceptItem(item, tile, null), parameterDescription + ": Items which will be declined by the generator don't need to be tested - The code won't be called for those cases."); + + + // Reset items since BeforeEach will not be called between dynamic tests + entity.items.clear(); + if(amount > 0){ + entity.items.add(item, amount); + } + entity.cons.update(tile.entity); + assertTrue(entity.cons.valid()); + + // Perform an update on the generator once - This should use up one or zero items - dependent on if the item is accepted and available or not. + generator.update(tile); + + assertEquals(expectedRemainingItemAmount, entity.items.get(item), parameterDescription + ": Remaining item amount mismatch."); + assertEquals(expectedEfficiency, entity.productionEfficiency, parameterDescription + ": Efficiency mismatch."); } }