From 78b436b8f4b55b8f892c43aa4d34b6856547e20a Mon Sep 17 00:00:00 2001 From: BlueWeabo Date: Sun, 30 Jul 2023 11:11:19 +0300 Subject: Fix Overclock Calculator Making Too many parallels and wrong eut consumption (#2190) * fix overclock calculator making too many parallels and wrong eut consumptions * fix duration increase when trying to do a noOverclock calculator * spotless * add correct api for no overclock * address review --- .../gregtech/api/util/GT_OverclockCalculator.java | 92 +++++++++++++--------- .../java/gregtech/api/util/GT_ParallelHelper.java | 5 +- .../overclock/GT_OverclockCalculator_UnitTest.java | 38 +++++++++ 3 files changed, 94 insertions(+), 41 deletions(-) diff --git a/src/main/java/gregtech/api/util/GT_OverclockCalculator.java b/src/main/java/gregtech/api/util/GT_OverclockCalculator.java index 5b4380028f..0ca9bf3f46 100644 --- a/src/main/java/gregtech/api/util/GT_OverclockCalculator.java +++ b/src/main/java/gregtech/api/util/GT_OverclockCalculator.java @@ -70,7 +70,7 @@ public class GT_OverclockCalculator { /** * How much the bits should be moved to the left when it is overclocking (Going up, 2 meaning it is multiplied with - * 4x)- + * 4x) */ private int eutIncreasePerOC = 2; /** @@ -113,7 +113,10 @@ public class GT_OverclockCalculator { * A supplier, which is used for machines which have a custom way of calculating duration, like Neutron Activator */ private Supplier durationUnderOneTickSupplier; - + /** + * Should we actually try to calculate overclocking + */ + private boolean noOverclock; /** * variable to check whether the overclocks have been calculated */ @@ -135,7 +138,8 @@ public class GT_OverclockCalculator { public static GT_OverclockCalculator ofNoOverclock(long eut, int duration) { return new GT_OverclockCalculator().setRecipeEUt(eut) .setDuration(duration) - .setEUt(eut); + .setEUt(eut) + .setNoOverclock(true); } /** @@ -143,37 +147,6 @@ public class GT_OverclockCalculator { */ public GT_OverclockCalculator() {} - /** - * Constructor for creating a new calculator with the save values - * - * @param calculator Calculator to copy over - */ - public GT_OverclockCalculator(@Nonnull GT_OverclockCalculator calculator) { - this(); - setRecipeEUt(calculator.recipeVoltage); - setRecipeAmperage(calculator.recipeAmperage); - setEUt(calculator.machineVoltage); - setAmperage(calculator.machineAmperage); - setDuration(calculator.duration); - setParallel(calculator.parallel); - setRecipeHeat(calculator.recipeHeat); - setMachineHeat(calculator.machineHeat); - setHeatPerfectOC(calculator.durationDecreasePerHeatOC); - setHeatOC(calculator.heatOC); - setHeatDiscount(calculator.heatDiscount); - setHeatDiscountMultiplier((float) calculator.heatDiscountExponent); - setEUtDiscount((float) calculator.eutDiscount); - setSpeedBoost((float) calculator.speedBoost); - setEUtIncreasePerOC(calculator.eutIncreasePerOC); - setDurationDecreasePerOC(calculator.durationDecreasePerOC); - setOneTickDiscount(calculator.oneTickDiscount); - setLaserOC(calculator.laserOC); - setLaserOCPenalty(calculator.laserOCPenalty); - setAmperageOC(calculator.amperageOC); - maxOverclocks = calculator.maxOverclocks; - limitOverclocks = calculator.limitOverclocks; - } - /** * @param recipeEUt Sets the Recipe's starting voltage */ @@ -387,6 +360,14 @@ public class GT_OverclockCalculator { return this; } + /** + * Sets if we should do overclocking or not + */ + public GT_OverclockCalculator setNoOverclock(boolean noOverclock) { + this.noOverclock = noOverclock; + return this; + } + /** * Call this when all values have been put it. */ @@ -400,6 +381,10 @@ public class GT_OverclockCalculator { } private void calculateOverclock() { + if (noOverclock) { + calculateFinalRecipeEUt(calculateHeatDiscountMultiplier()); + return; + } if (laserOC && amperageOC) { throw new IllegalStateException("Tried to calculate overclock with both laser and amperage overclocking"); } @@ -533,6 +518,7 @@ public class GT_OverclockCalculator { */ public double calculateDurationUnderOneTick() { if (durationUnderOneTickSupplier != null) return durationUnderOneTickSupplier.get(); + if (noOverclock) return duration; int normalOverclocks = calculateAmountOfOverclocks( calculateMachinePowerTier(), calculateRecipePowerTier(calculateHeatDiscountMultiplier())); @@ -549,13 +535,41 @@ public class GT_OverclockCalculator { * @param originalMaxParallel Parallels which are of the actual machine before the overclocking extra ones */ public long calculateEUtConsumptionUnderOneTick(int originalMaxParallel, int currentParallel) { - double parallelOverclocks = Math.log((double) currentParallel / originalMaxParallel) - / Math.log(1 << durationDecreasePerOC); - return (long) Math.floor( - recipeVoltage * Math.pow(1 << eutIncreasePerOC, parallelOverclocks) + if (noOverclock) return recipeVoltage; + double heatDiscountMultiplier = calculateHeatDiscountMultiplier(); + // So what we need to do here is as follows: + // - First we need to figure out what out parallel multiplier for getting to that OC was + // - Second we need to find how many of those were from heat overclocks + // - Third we need to find how many were from normal overclocking. + // = For that we need to find how much better heat overclocks are compared to normal ones + // = Then remove that many from our normal overclocks + // - Fourth we find how many total overclocks we have + // - Fifth we find how many of those are needed to one tick + // - Finally we calculate the formula + // = The energy increase from our overclocks for parallel + // = The energy increase from our overclock to reach maximum under one tick potential + // =- NOTE: This will always cause machine to use full power no matter what. Otherwise it creates many + // anomalies. + // = Everything else for recipe voltage is also calculated here. + + double parallelMultiplierFromOverclocks = (double) currentParallel / originalMaxParallel; + double amountOfParallelHeatOverclocks = Math.min( + Math.log(parallelMultiplierFromOverclocks) / Math.log(1 << durationDecreasePerHeatOC), + calculateAmountOfHeatOverclocks()); + double amountOfParallelOverclocks = Math.log(parallelMultiplierFromOverclocks) + / Math.log(1 << durationDecreasePerOC) + - amountOfParallelHeatOverclocks * (1 << durationDecreasePerHeatOC - durationDecreasePerOC); + double machineTier = calculateMachinePowerTier(); + double recipeTier = calculateRecipePowerTier(heatDiscountMultiplier); + double amountOfTotalOverclocks = calculateAmountOfOverclocks(machineTier, recipeTier); + return (long) Math.ceil( + recipeVoltage * Math.pow(1 << eutIncreasePerOC, amountOfParallelOverclocks + amountOfParallelHeatOverclocks) + * Math.pow( + 1 << eutIncreasePerOC, + amountOfTotalOverclocks - (amountOfParallelOverclocks + amountOfParallelHeatOverclocks)) * originalMaxParallel * eutDiscount * recipeAmperage - * calculateHeatDiscountMultiplier()); + * heatDiscountMultiplier); } } diff --git a/src/main/java/gregtech/api/util/GT_ParallelHelper.java b/src/main/java/gregtech/api/util/GT_ParallelHelper.java index 6d28dab036..7849efd277 100644 --- a/src/main/java/gregtech/api/util/GT_ParallelHelper.java +++ b/src/main/java/gregtech/api/util/GT_ParallelHelper.java @@ -404,9 +404,10 @@ public class GT_ParallelHelper { // Save the original max parallel before calculating our overclocking under 1 tick int originalMaxParallel = maxParallel; - double tickTimeAfterOC = calculator.calculateDurationUnderOneTick(); + double tickTimeAfterOC = calculator.setParallel(originalMaxParallel) + .calculateDurationUnderOneTick(); if (tickTimeAfterOC < 1) { - maxParallel = (int) Math.floor(maxParallel / tickTimeAfterOC); + maxParallel = (int) (maxParallel / tickTimeAfterOC); } int maxParallelBeforeBatchMode = maxParallel; diff --git a/src/test/java/gregtech/overclock/GT_OverclockCalculator_UnitTest.java b/src/test/java/gregtech/overclock/GT_OverclockCalculator_UnitTest.java index cd33b4280a..58ce077537 100644 --- a/src/test/java/gregtech/overclock/GT_OverclockCalculator_UnitTest.java +++ b/src/test/java/gregtech/overclock/GT_OverclockCalculator_UnitTest.java @@ -363,4 +363,42 @@ class GT_OverclockCalculator_UnitTest { assertEquals(1, calculator.getDuration(), messageDuration); assertEquals(16 << 14, calculator.getConsumption(), messageEUt); } + + @Test + void testCorrectEUtWhenOverclockingUnderOneTick_Test() { + GT_OverclockCalculator calculator = new GT_OverclockCalculator().setRecipeEUt(24) + .setParallel(56) + .setAmperage(1) + .setAmperageOC(true) + .setSpeedBoost(1f / 6f) + .setEUt(V[14]) + .setDuration(56); + assertEquals((24 * 56) << 20, calculator.calculateEUtConsumptionUnderOneTick(56, 6144)); + } + + @Test + void testCorrectEUtWhenOverclockingUnderOneTickWithHeat_Test() { + double heatDiscount = Math.pow(0.95, (15500 - 2000) / 900); + GT_OverclockCalculator calculator = new GT_OverclockCalculator().setRecipeEUt(1920) + .setParallel(256) + .setAmperage(1) + .setAmperageOC(true) + .setHeatDiscount(true) + .setHeatOC(true) + .setRecipeHeat(2000) + .setMachineHeat(15500) + .setEUt(V[12] * 1_048_576) + .setDuration(250); + assertEquals( + Math.ceil((((long) 1920 * 256) << 28) * heatDiscount), + calculator + .calculateEUtConsumptionUnderOneTick(256, (int) (256 / calculator.calculateDurationUnderOneTick()))); + } + + @Test + void testNoOverclockCorrectWithUnderOneTickLogic_Test() { + GT_OverclockCalculator calculator = GT_OverclockCalculator.ofNoOverclock(2_693_264_510L, 100) + .setParallel(24 * 64); + assertEquals(100, calculator.calculateDurationUnderOneTick()); + } } -- cgit