diff options
Diffstat (limited to 'src')
5 files changed, 370 insertions, 307 deletions
diff --git a/src/main/java/gregtech/api/util/GT_OverclockCalculator.java b/src/main/java/gregtech/api/util/GT_OverclockCalculator.java index 91cdf865ad..5dda0b5c01 100644 --- a/src/main/java/gregtech/api/util/GT_OverclockCalculator.java +++ b/src/main/java/gregtech/api/util/GT_OverclockCalculator.java @@ -1,23 +1,18 @@ package gregtech.api.util; +import java.util.function.Function; import java.util.function.Supplier; import javax.annotation.Nonnull; -import gregtech.api.enums.GT_Values; - public class GT_OverclockCalculator { - private static final double LOG2 = Math.log(2); - + // region variables + // region basic properties /** - * Voltage the recipe will run at + * EUt the recipe originally runs at */ - private long recipeVoltage = 0; - /* - * The amount of amps the recipe needs - */ - private long recipeAmperage = 1; + private long recipeEUt = 0; /** * Voltage of the machine */ @@ -31,35 +26,15 @@ public class GT_OverclockCalculator { */ private int duration = 0; /** - * The parallel the machine has when trying to overclock - */ - private int parallel = 1; - - /** - * The min heat required for the recipe - */ - private int recipeHeat = 0; - /** - * The heat the machine has when starting the recipe - */ - private int machineHeat = 0; - /** - * How much the duration should be divided by for each 1800K above recipe heat - */ - private double durationDecreasePerHeatOC = 4; - /** - * Whether to enable overclocking with heat like the EBF every 1800 heat difference + * A supplier used for machines which have a custom way of calculating base duration, like Neutron Activator */ - private boolean heatOC; - /** - * Whether to enable heat discounts every 900 heat difference - */ - private boolean heatDiscount; + private Supplier<Double> durationUnderOneTickSupplier; /** - * The value used for discount final eut per 900 heat + * The parallel the machine has when trying to overclock */ - private double heatDiscountExponent = 0.95; - + private int parallel = 1; + // endregion + // region extra factors /** * Discount for EUt at the beginning of calculating overclocks, like GT++ machines */ @@ -68,29 +43,36 @@ public class GT_OverclockCalculator { * Speeding/Slowing up/down the duration of a recipe at the beginning of calculating overclocks, like GT++ machines */ private double speedBoost = 1; - + // endregion + // region overclock parameters /** * How much the energy would be multiplied by per overclock available */ private double eutIncreasePerOC = 4; /** + * A supplier used for machines which have a custom way of calculating energy increase multipliers for every + * overclock, like Advanced Assembling Line + */ + private Function<Integer, Double> eutIncreasePerOCSupplier = getDefaultEutIncreasePerOCSupplier(); + /** * How much the duration would be divided by per overclock made that isn't an overclock from HEAT */ private double durationDecreasePerOC = 2; /** - * Whether to give EUt Discount when the duration goes below one tick + * A supplier used for machines which have a custom way of calculating duration decrease multipliers for every + * overclock */ - private boolean oneTickDiscount; + private Function<Integer, Double> durationDecreasePerOCSupplier = getDefaultDurationDecreasePerOCSupplier(); /** - * Whether the multi should use amperage to overclock with an exponent. Incompatible with amperageOC + * Whether at least one of {@link #eutIncreasePerOCSupplier} and {@link #durationDecreasePerOCSupplier} has been set */ - private boolean laserOC; + private boolean hasAtLeastOneSupplierBeenSet; /** - * Laser OC's penalty for using high amp lasers for overclocking. Like what the Adv. Assline is doing + * Whether to give EUt Discount when the duration goes below one tick */ - private double laserOCPenalty = 0.3; + private boolean oneTickDiscount; /** - * Whether the multi should use amperage to overclock normally. Incompatible with laserOC + * Whether the multi should use amperage to overclock normally. */ private boolean amperageOC; /** @@ -106,24 +88,60 @@ public class GT_OverclockCalculator { */ private int overclockCount; /** - * How many overclocks were performed with heat out of the overclocks we had + * Should we actually try to calculate overclocking */ - private int heatOverclockCount; + private boolean noOverclock; /** - * A supplier, which is used for machines which have a custom way of calculating duration, like Neutron Activator + * The parallel the machine actually used. */ - private Supplier<Double> durationUnderOneTickSupplier; + private int currentParallel; + // endregion + // region heat overclock /** - * Should we actually try to calculate overclocking + * The min heat required for the recipe */ - private boolean noOverclock; + private int recipeHeat = 0; + /** + * The heat the machine has when starting the recipe + */ + private int machineHeat = 0; + /** + * How much the duration should be divided by for each 1800K above recipe heat + */ + private double durationDecreasePerHeatOC = 4; + /** + * Whether to enable overclocking with heat like the EBF every 1800 heat difference + */ + private boolean heatOC; + /** + * Whether to enable heat discounts every 900 heat difference + */ + private boolean heatDiscount; + /** + * The value used for discount final eut per 900 heat + */ + private double heatDiscountExponent = 0.95; + // endregion + // region result /** * variable to check whether the overclocks have been calculated */ private boolean calculated; - + /** + * The calculated duration result. + */ + private int calculatedDuration; + /** + * The calculated energy consumption result. + */ + private long calculatedConsumption; + // endregion + // region constants private static final int HEAT_DISCOUNT_THRESHOLD = 900; private static final int HEAT_PERFECT_OVERCLOCK_THRESHOLD = 1800; + private static final double LOG2 = Math.log(2); + // endregion + // endregion /** * Creates calculator that doesn't do OC at all. Will use recipe duration. @@ -147,12 +165,13 @@ public class GT_OverclockCalculator { */ public GT_OverclockCalculator() {} + // region setters /** * @param recipeEUt Sets the Recipe's starting voltage */ @Nonnull public GT_OverclockCalculator setRecipeEUt(long recipeEUt) { - this.recipeVoltage = recipeEUt; + this.recipeEUt = recipeEUt; return this; } @@ -184,15 +203,6 @@ public class GT_OverclockCalculator { } /** - * @param recipeAmperage Sets the Amperage of the recipe - */ - @Nonnull - public GT_OverclockCalculator setRecipeAmperage(long recipeAmperage) { - this.recipeAmperage = recipeAmperage; - return this; - } - - /** * Enables Perfect OC in calculation */ @Nonnull @@ -275,16 +285,6 @@ public class GT_OverclockCalculator { } /** - * @deprecated Deprecated in favor of {@link #setHeatPerfectOC(double)}. Calls {@link #setHeatPerfectOC(double)} - * where the given value is 2^heatPerfectOC - */ - @Deprecated - @Nonnull - public GT_OverclockCalculator setHeatPerfectOC(int heatPerfectOC) { - return setHeatPerfectOC(Math.pow(2, heatPerfectOC)); - } - - /** * Sets the Overclock that should be calculated when a heat OC is applied. */ @Nonnull @@ -339,23 +339,11 @@ public class GT_OverclockCalculator { } @Nonnull - public GT_OverclockCalculator setLaserOC(boolean laserOC) { - this.laserOC = laserOC; - return this; - } - - @Nonnull public GT_OverclockCalculator setAmperageOC(boolean amperageOC) { this.amperageOC = amperageOC; return this; } - @Nonnull - public GT_OverclockCalculator setLaserOCPenalty(double laserOCPenalty) { - this.laserOCPenalty = laserOCPenalty; - return this; - } - /** * Set a supplier for calculating custom duration for when its needed under one tick */ @@ -375,6 +363,37 @@ public class GT_OverclockCalculator { } /** + * Set a supplier for calculating custom EUt increase multipliers for every overclock + */ + public GT_OverclockCalculator setEutIncreasePerOCSupplier(Function<Integer, Double> eutIncreasePerOCSupplier) { + this.eutIncreasePerOCSupplier = eutIncreasePerOCSupplier; + this.hasAtLeastOneSupplierBeenSet = true; + return this; + } + + /** + * Set a supplier for calculating custom duration decrease multipliers for every overclock + */ + public GT_OverclockCalculator setDurationDecreasePerOCSupplier( + Function<Integer, Double> durationDecreasePerOCSupplier) { + this.durationDecreasePerOCSupplier = durationDecreasePerOCSupplier; + this.hasAtLeastOneSupplierBeenSet = true; + return this; + } + + /** + * Set actually performed parallel + */ + public GT_OverclockCalculator setCurrentParallel(int currentParallel) { + this.currentParallel = currentParallel; + // Sets parallel to the actually performed one if machine's parallel is underused. + this.parallel = Math.min(parallel, currentParallel); + return this; + } + + // endregion + // region calculate + /** * Call this when all values have been put it. */ @Nonnull @@ -388,68 +407,93 @@ public class GT_OverclockCalculator { } private void calculateOverclock() { - duration = (int) Math.ceil(duration * speedBoost); - if (noOverclock) { - recipeVoltage = calculateFinalRecipeEUt(calculateHeatDiscountMultiplier()); - return; - } - if (laserOC && amperageOC) { - throw new IllegalStateException("Tried to calculate overclock with both laser and amperage overclocking"); - } + double durationInDouble = durationUnderOneTickSupplier != null ? durationUnderOneTickSupplier.get() + : duration * speedBoost; + calculatedConsumption = recipeEUt; double heatDiscountMultiplier = calculateHeatDiscountMultiplier(); - if (heatOC) { - heatOverclockCount = calculateAmountOfHeatOverclocks(); - } - - double recipePowerTier = calculateRecipePowerTier(heatDiscountMultiplier); - double machinePowerTier = calculateMachinePowerTier(); + // Usually a safeguard when currentParallel is not set: We assume parallel is fully used. + currentParallel = Math.max(currentParallel, parallel); - overclockCount = calculateAmountOfNeededOverclocks(machinePowerTier, recipePowerTier); - if (!amperageOC) { - overclockCount = Math.min(overclockCount, calculateRecipeToMachineVoltageDifference()); + if (noOverclock) { + calculatedConsumption = calculateFinalRecipeEUt(heatDiscountMultiplier); + calculatedDuration = (int) Math.ceil(durationInDouble); + return; } - // Not just a safeguard. This also means that you can run a 1.2A recipe on a single hatch for a regular gt - // multi. - // This is intended, including the fact that you don't get an OC with a one tier upgrade in that case. - overclockCount = Math.max(overclockCount, 0); - - overclockCount = limitOverclocks ? Math.min(maxOverclocks, overclockCount) : overclockCount; - heatOverclockCount = Math.min(heatOverclockCount, overclockCount); - recipeVoltage = (long) Math.floor(recipeVoltage * Math.pow(eutIncreasePerOC, overclockCount)); - duration = (int) Math.floor(duration / Math.pow(durationDecreasePerOC, overclockCount - heatOverclockCount)); - duration = (int) Math.floor(duration / Math.pow(durationDecreasePerHeatOC, heatOverclockCount)); - if (oneTickDiscount) { - recipeVoltage = (long) Math.floor( - recipeVoltage - / Math.pow(durationDecreasePerOC, ((int) (machinePowerTier - recipePowerTier - overclockCount)))); - if (recipeVoltage < 1) { - recipeVoltage = 1; + // First we need to overclock to reach 1 tick. + // Then we need to overclock under one tick to get more extra parallels. + // We stop overclocking if we've already reached 1 tick and got enough parallels to actually perform. + double requiredUnderOneTickMultiplier = durationInDouble * currentParallel / parallel; + if (hasAtLeastOneSupplierBeenSet) { // custom overclock + double currentEutIncrease = eutIncreasePerOCSupplier.apply(overclockCount + 1); + double currentDurationDecrease = durationDecreasePerOCSupplier.apply(overclockCount + 1); + double machinePower = calculateMachinePower(); + double currentConsumption = calculateRecipePower(heatDiscountMultiplier); + double currentUnderOneTickMultiplier = 1; + // Whether we have enough power for the next overclock; + // whether we need more overclock to reach 1 tick and get enough extra parallel; + // whether we have reached the overclock limit + while (machinePower > currentConsumption * currentEutIncrease + && requiredUnderOneTickMultiplier > currentUnderOneTickMultiplier + && (!limitOverclocks || overclockCount < maxOverclocks)) { + currentConsumption *= currentEutIncrease; + durationInDouble /= currentDurationDecrease; + overclockCount++; + currentEutIncrease = eutIncreasePerOCSupplier.apply(overclockCount + 1); + currentDurationDecrease = durationDecreasePerOCSupplier.apply(overclockCount + 1); } + calculatedConsumption = (long) Math.max(currentConsumption, 1); + calculatedDuration = (int) Math.max(durationInDouble, 1); + } else { // general overclock + double recipePowerTier = calculateRecipePowerTier(heatDiscountMultiplier); + double machinePowerTier = calculateMachinePowerTier(); + + int maxOverclockCount = calculateAmountOfOverclocks(machinePowerTier, recipePowerTier); + if (limitOverclocks) maxOverclockCount = Math.min(maxOverclocks, maxOverclockCount); + if (!amperageOC) { + // Limit overclocks by voltage tier. + maxOverclockCount = Math.min(maxOverclockCount, calculateRecipeToMachineVoltageDifference()); + } + overclockCount = calculateAmountOfNeededOverclocks(maxOverclockCount, requiredUnderOneTickMultiplier); + + // If triggered, it indicates that recipe power > machine power. + // Not just a safeguard. This also means that you can run a 1.2A recipe on a single hatch for a regular gt + // multi. + // This is intended, including the fact that you don't get an OC with a one tier upgrade in that case. + overclockCount = Math.max(overclockCount, 0); + + int heatOverclockCount = Math.min(calculateMaxAmountOfHeatOverclocks(), overclockCount); + calculatedConsumption = (long) Math.floor(recipeEUt * Math.pow(eutIncreasePerOC, overclockCount)); + durationInDouble /= Math.pow(durationDecreasePerHeatOC, heatOverclockCount) + * Math.pow(durationDecreasePerOC, overclockCount - heatOverclockCount); + if (oneTickDiscount) { + calculatedConsumption = (long) Math + .floor(calculatedConsumption / Math.pow(durationDecreasePerOC, maxOverclockCount - overclockCount)); + calculatedConsumption = Math.max(calculatedConsumption, 1); + } + calculatedConsumption = calculateFinalRecipeEUt(heatDiscountMultiplier); + calculatedDuration = (int) Math.max(durationInDouble, 1); } + } - if (laserOC) { - calculateLaserOC(); - } - - if (duration < 1) { - duration = 1; - } - - recipeVoltage = calculateFinalRecipeEUt(heatDiscountMultiplier); + private double calculateRecipePower(double heatDiscountMultiplier) { + return recipeEUt * parallel * eutDiscount * heatDiscountMultiplier; } private double calculateRecipePowerTier(double heatDiscountMultiplier) { - return calculatePowerTier(recipeVoltage * parallel * eutDiscount * heatDiscountMultiplier * recipeAmperage); + return calculatePowerTier(calculateRecipePower(heatDiscountMultiplier)); + } + + private double calculateMachinePower() { + return machineVoltage * (amperageOC ? machineAmperage : Math.min(machineAmperage, parallel)); } private double calculateMachinePowerTier() { - return calculatePowerTier( - machineVoltage * (amperageOC ? machineAmperage : Math.min(machineAmperage, parallel))); + return calculatePowerTier(calculateMachinePower()); } private int calculateRecipeToMachineVoltageDifference() { - return (int) (Math.ceil(calculatePowerTier(machineVoltage)) - Math.ceil(calculatePowerTier(recipeVoltage))); + return (int) (Math.ceil(calculatePowerTier(machineVoltage)) - Math.ceil(calculatePowerTier(recipeEUt))); } private double calculatePowerTier(double voltage) { @@ -457,15 +501,11 @@ public class GT_OverclockCalculator { } private long calculateFinalRecipeEUt(double heatDiscountMultiplier) { - return (long) Math.ceil(recipeVoltage * eutDiscount * heatDiscountMultiplier * parallel * recipeAmperage); + return (long) Math.ceil(calculatedConsumption * eutDiscount * heatDiscountMultiplier * parallel); } - private int calculateAmountOfHeatOverclocks() { - return Math.min( - (machineHeat - recipeHeat) / HEAT_PERFECT_OVERCLOCK_THRESHOLD, - calculateAmountOfOverclocks( - calculateMachinePowerTier(), - calculateRecipePowerTier(calculateHeatDiscountMultiplier()))); + private int calculateMaxAmountOfHeatOverclocks() { + return heatOC ? (machineHeat - recipeHeat) / HEAT_PERFECT_OVERCLOCK_THRESHOLD : 0; } /** @@ -475,28 +515,16 @@ public class GT_OverclockCalculator { return (int) (machinePowerTier - recipePowerTier); } - /** - * Calculates the amount of overclocks needed to reach 1 ticking - * - * Here we limit "the tier difference overclock" amount to a number of overclocks needed to reach 1 tick duration, - * for example: - * - * recipe initial duration = 250 ticks (12,5 seconds LV(1)) - * we have LCR with IV(5) energy hatch, which overclocks at 4/4 rate - * - * log_4 (250) ~ 3,98 is the number of overclocks needed to reach 1 tick - * - * to calculate log_a(b) we can use the log property: - * log_a(b) = log_c(b) / log_c(a) - * in our case we use natural log base as 'c' - * - * as a final step we apply Math.ceil(), - * otherwise for fractional nums like 3,98 we will never reach 1 tick - */ - private int calculateAmountOfNeededOverclocks(double machinePowerTier, double recipePowerTier) { - return (int) Math.min( - calculateAmountOfOverclocks(machinePowerTier, recipePowerTier), - Math.ceil(Math.log(duration) / Math.log(durationDecreasePerOC))); + private int calculateAmountOfNeededOverclocks(int maxOverclockCount, double requiredUnderOneTickMultiplier) { + int neededHeatOC = (int) Math.min( + calculateMaxAmountOfHeatOverclocks(), + Math.ceil(Math.log(requiredUnderOneTickMultiplier) / Math.log(durationDecreasePerHeatOC))); + neededHeatOC = Math.max(neededHeatOC, 0); + int neededNormalOC = (int) Math.ceil( + (Math.log(requiredUnderOneTickMultiplier) - Math.log(durationDecreasePerHeatOC) * neededHeatOC) + / Math.log(durationDecreasePerOC)); + neededNormalOC = Math.max(neededNormalOC, 0); + return Math.min(maxOverclockCount, neededHeatOC + neededNormalOC); } private double calculateHeatDiscountMultiplier() { @@ -504,16 +532,8 @@ public class GT_OverclockCalculator { return Math.pow(heatDiscountExponent, heatDiscounts); } - private void calculateLaserOC() { - long inputEut = machineVoltage * machineAmperage; - double currentPenalty = eutIncreasePerOC + laserOCPenalty; - while (inputEut > recipeVoltage * currentPenalty && recipeVoltage * currentPenalty > 0 && duration > 1) { - duration /= durationDecreasePerOC; - recipeVoltage *= currentPenalty; - currentPenalty += laserOCPenalty; - } - } - + // endregion + // region result getters /** * @return The consumption after overclock has been calculated */ @@ -521,7 +541,7 @@ public class GT_OverclockCalculator { if (!calculated) { throw new IllegalStateException("Tried to get consumption before calculating"); } - return recipeVoltage; + return calculatedConsumption; } /** @@ -531,7 +551,7 @@ public class GT_OverclockCalculator { if (!calculated) { throw new IllegalStateException("Tried to get duration before calculating"); } - return duration; + return calculatedDuration; } /** @@ -551,68 +571,51 @@ public class GT_OverclockCalculator { return calculated; } + // endregion + // region misc /** * Returns duration as a double to show how much it is overclocking too much to determine extra parallel. This * doesn't count as calculating */ public double calculateDurationUnderOneTick() { - if (durationUnderOneTickSupplier != null) return durationUnderOneTickSupplier.get(); - if (noOverclock) return duration; - int normalOverclocks = calculateAmountOfOverclocks( - calculateMachinePowerTier(), - calculateRecipePowerTier(calculateHeatDiscountMultiplier())); - normalOverclocks = limitOverclocks ? Math.min(normalOverclocks, maxOverclocks) : normalOverclocks; - int heatOverclocks = Math.min(calculateAmountOfHeatOverclocks(), normalOverclocks); - return (duration * speedBoost) / (Math.pow(durationDecreasePerOC, normalOverclocks - heatOverclocks) - * Math.pow(durationDecreasePerHeatOC, heatOverclocks)); - } - - /** - * Returns the EUt consumption one would get from overclocking under 1 tick - * This Doesn't count as calculating - * - * @param originalMaxParallel Parallels which are of the actual machine before the overclocking extra ones - */ - public long calculateEUtConsumptionUnderOneTick(int originalMaxParallel, int currentParallel) { - if (noOverclock) return recipeVoltage; + double durationInDouble = durationUnderOneTickSupplier != null ? durationUnderOneTickSupplier.get() + : duration * speedBoost; + if (noOverclock) return durationInDouble; 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(durationDecreasePerHeatOC), - calculateAmountOfHeatOverclocks()); - double amountOfParallelOverclocks = Math.log(parallelMultiplierFromOverclocks) / Math.log(durationDecreasePerOC) - - amountOfParallelHeatOverclocks * (durationDecreasePerHeatOC - durationDecreasePerOC); - double machineTier = calculateMachinePowerTier(); - double recipeTier = calculateRecipePowerTier(heatDiscountMultiplier); - double amountOfTotalOverclocks = calculateAmountOfOverclocks(machineTier, recipeTier); - if (recipeVoltage <= GT_Values.V[0]) { - amountOfTotalOverclocks = Math.min(amountOfTotalOverclocks, calculateRecipeToMachineVoltageDifference()); + if (hasAtLeastOneSupplierBeenSet) { + int overclockCount = 0; + double currentEutIncrease = eutIncreasePerOCSupplier.apply(overclockCount + 1); + double currentDurationDecrease = durationDecreasePerOCSupplier.apply(overclockCount + 1); + double machinePower = calculateMachinePower(); + double recipePower = calculateRecipePower(heatDiscountMultiplier); + while (machinePower > recipePower * currentEutIncrease + && (!limitOverclocks || overclockCount < maxOverclocks)) { + recipePower *= currentEutIncrease; + durationInDouble /= currentDurationDecrease; + overclockCount++; + currentEutIncrease = eutIncreasePerOCSupplier.apply(overclockCount + 1); + currentDurationDecrease = durationDecreasePerOCSupplier.apply(overclockCount + 1); + } + } else { + int maxOverclockCount = calculateAmountOfOverclocks( + calculateMachinePowerTier(), + calculateRecipePowerTier(heatDiscountMultiplier)); + if (limitOverclocks) maxOverclockCount = Math.min(maxOverclocks, maxOverclockCount); + int heatOverclocks = Math.min(calculateMaxAmountOfHeatOverclocks(), maxOverclockCount); + durationInDouble /= Math.pow(durationDecreasePerOC, maxOverclockCount - heatOverclocks) + * Math.pow(durationDecreasePerHeatOC, heatOverclocks); } - amountOfTotalOverclocks = limitOverclocks ? Math.min(amountOfTotalOverclocks, maxOverclocks) - : amountOfTotalOverclocks; - return (long) Math.ceil( - recipeVoltage * Math.pow(eutIncreasePerOC, amountOfParallelOverclocks + amountOfParallelHeatOverclocks) - * Math.pow( - eutIncreasePerOC, - amountOfTotalOverclocks - (amountOfParallelOverclocks + amountOfParallelHeatOverclocks)) - * originalMaxParallel - * eutDiscount - * recipeAmperage - * heatDiscountMultiplier); + return durationInDouble; + } + + private Function<Integer, Double> getDefaultEutIncreasePerOCSupplier() { + return overclockCount -> eutIncreasePerOC; + } + + private Function<Integer, Double> getDefaultDurationDecreasePerOCSupplier() { + return overclockCount -> overclockCount <= calculateMaxAmountOfHeatOverclocks() ? durationDecreasePerHeatOC + : durationDecreasePerOC; } + + // endregion } diff --git a/src/main/java/gregtech/api/util/GT_ParallelHelper.java b/src/main/java/gregtech/api/util/GT_ParallelHelper.java index 141ea35e9e..157488a8ca 100644 --- a/src/main/java/gregtech/api/util/GT_ParallelHelper.java +++ b/src/main/java/gregtech/api/util/GT_ParallelHelper.java @@ -469,8 +469,8 @@ public class GT_ParallelHelper { // Save the original max parallel before calculating our overclocking under 1 tick int originalMaxParallel = maxParallel; - double tickTimeAfterOC = calculator.setParallel(originalMaxParallel) - .calculateDurationUnderOneTick(); + calculator.setParallel(originalMaxParallel); + double tickTimeAfterOC = calculator.calculateDurationUnderOneTick(); if (tickTimeAfterOC < 1) { maxParallel = GT_Utility.safeInt((long) (maxParallel / tickTimeAfterOC), 0); } @@ -559,12 +559,8 @@ public class GT_ParallelHelper { return; } - long eutUseAfterOC = calculator.calculateEUtConsumptionUnderOneTick(originalMaxParallel, currentParallel); - calculator.setParallel(Math.min(currentParallel, originalMaxParallel)) + calculator.setCurrentParallel(currentParallel) .calculate(); - if (currentParallel > originalMaxParallel) { - calculator.setRecipeEUt(eutUseAfterOC); - } // If Batch Mode is enabled determine how many extra parallels we can get if (batchMode && currentParallel > 0 && calculator.getDuration() < MAX_BATCH_MODE_TICK_TIME) { int tExtraParallels; diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_IntegratedOreFactory.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_IntegratedOreFactory.java index 48ab5a10f5..af55829f6c 100644 --- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_IntegratedOreFactory.java +++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_IntegratedOreFactory.java @@ -273,10 +273,10 @@ public class GT_MetaTileEntity_IntegratedOreFactory GT_OverclockCalculator calculator = new GT_OverclockCalculator().setEUt(availableEUt) .setRecipeEUt(RECIPE_EUT) - .setDuration(getTime(sMode)); + .setDuration(getTime(sMode)) + .setParallel(originalMaxParallel); - double tickTimeAfterOC = calculator.setParallel(originalMaxParallel) - .calculateDurationUnderOneTick(); + double tickTimeAfterOC = calculator.calculateDurationUnderOneTick(); if (tickTimeAfterOC < 1) { maxParallel = GT_Utility.safeInt((long) (maxParallel / tickTimeAfterOC), 0); @@ -325,9 +325,7 @@ public class GT_MetaTileEntity_IntegratedOreFactory currentParallel = itemParallel; int currentParallelBeforeBatchMode = Math.min(currentParallel, maxParallelBeforeBatchMode); - long eutUseAfterOC = calculator - .calculateEUtConsumptionUnderOneTick(originalMaxParallel, currentParallelBeforeBatchMode); - calculator.setParallel(Math.min(currentParallelBeforeBatchMode, originalMaxParallel)) + calculator.setCurrentParallel(currentParallelBeforeBatchMode) .calculate(); double batchMultiplierMax = 1; @@ -407,7 +405,7 @@ public class GT_MetaTileEntity_IntegratedOreFactory this.mEfficiencyIncrease = 10000; this.mOutputItems = sMidProduct; this.mMaxProgresstime = (int) (calculator.getDuration() * batchMultiplierMax); - this.lEUt = eutUseAfterOC; + this.lEUt = calculator.getConsumption(); if (this.lEUt > 0) { this.lEUt = -this.lEUt; } diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_MultiFurnace.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_MultiFurnace.java index b7b34add0b..5d611b270d 100644 --- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_MultiFurnace.java +++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_MultiFurnace.java @@ -156,11 +156,14 @@ public class GT_MetaTileEntity_MultiFurnace ArrayList<ItemStack> tInputList = getAllStoredInputs(); if (tInputList.isEmpty()) return CheckRecipeResultRegistry.NO_RECIPE; - int mVoltage = GT_Utility.safeInt(getMaxInputVoltage()); + long inputVoltage = getMaxInputVoltage(); - GT_OverclockCalculator calculator = new GT_OverclockCalculator().setEUt(mVoltage) + int fakeOriginalMaxParallel = 1; + GT_OverclockCalculator calculator = new GT_OverclockCalculator().setEUt(inputVoltage) .setRecipeEUt(RECIPE_EUT) - .setDuration(RECIPE_DURATION); + .setDuration(RECIPE_DURATION) + .setParallel(fakeOriginalMaxParallel); + int maxParallel = this.mLevel; int originalMaxParallel = maxParallel; double tickTimeAfterOC = calculator.calculateDurationUnderOneTick(); @@ -174,35 +177,32 @@ public class GT_MetaTileEntity_MultiFurnace } // Calculate parallel - int tCurrentParallel = 0; + int currentParallel = 0; for (ItemStack item : tInputList) { ItemStack smeltedOutput = GT_ModHandler.getSmeltingOutput(item, false, null); if (smeltedOutput != null) { - if (item.stackSize <= (maxParallel - tCurrentParallel)) { - tCurrentParallel += item.stackSize; + if (item.stackSize <= (maxParallel - currentParallel)) { + currentParallel += item.stackSize; } else { - tCurrentParallel = maxParallel; + currentParallel = maxParallel; break; } } } - if (tCurrentParallel <= 0) { + if (currentParallel <= 0) { return CheckRecipeResultRegistry.NO_RECIPE; } - int currentParallelBeforeBatchMode = Math.min(tCurrentParallel, maxParallelBeforeBatchMode); + int currentParallelBeforeBatchMode = Math.min(currentParallel, maxParallelBeforeBatchMode); + int fakeCurrentParallel = (int) Math.ceil((double) currentParallelBeforeBatchMode / originalMaxParallel); - long eutUseAfterOC = calculator.calculateEUtConsumptionUnderOneTick( - 1, - (int) Math.ceil((double) currentParallelBeforeBatchMode / originalMaxParallel)); - calculator - .setParallel(Math.min((int) Math.ceil((double) currentParallelBeforeBatchMode / originalMaxParallel), 1)) + calculator.setCurrentParallel(fakeCurrentParallel) .calculate(); double batchMultiplierMax = 1; // In case batch mode enabled - if (tCurrentParallel > maxParallelBeforeBatchMode && calculator.getDuration() < getMaxBatchSize()) { + if (currentParallel > maxParallelBeforeBatchMode && calculator.getDuration() < getMaxBatchSize()) { batchMultiplierMax = (double) getMaxBatchSize() / calculator.getDuration(); - batchMultiplierMax = Math.min(batchMultiplierMax, (double) tCurrentParallel / maxParallelBeforeBatchMode); + batchMultiplierMax = Math.min(batchMultiplierMax, (double) currentParallel / maxParallelBeforeBatchMode); } int finalParallel = (int) (batchMultiplierMax * maxParallelBeforeBatchMode); @@ -230,7 +230,7 @@ public class GT_MetaTileEntity_MultiFurnace this.mEfficiency = 10000 - (getIdealStatus() - getRepairStatus()) * 1000; this.mEfficiencyIncrease = 10000; this.mMaxProgresstime = (int) (calculator.getDuration() * batchMultiplierMax); - this.lEUt = eutUseAfterOC; + this.lEUt = calculator.getConsumption(); if (this.lEUt > 0) this.lEUt = -this.lEUt; diff --git a/src/test/java/gregtech/overclock/GT_OverclockCalculator_UnitTest.java b/src/test/java/gregtech/overclock/GT_OverclockCalculator_UnitTest.java index e1560b27cb..6056b00c73 100644 --- a/src/test/java/gregtech/overclock/GT_OverclockCalculator_UnitTest.java +++ b/src/test/java/gregtech/overclock/GT_OverclockCalculator_UnitTest.java @@ -4,6 +4,8 @@ import static gregtech.api.enums.GT_Values.V; import static gregtech.api.enums.GT_Values.VP; import static org.junit.jupiter.api.Assertions.assertEquals; +import java.util.function.Function; + import org.junit.jupiter.api.Test; import gregtech.api.enums.TierEU; @@ -26,7 +28,7 @@ class GT_OverclockCalculator_UnitTest { .setRecipeHeat(1800) .setMachineHeat(1800 * 5) .calculate(); - assertEquals(1024 >> 8, calculator.getDuration(), messageDuration); + assertEquals(1024 / Math.pow(4, 4), calculator.getDuration(), messageDuration); assertEquals(correctConsumption, calculator.getConsumption(), messageEUt); } @@ -42,7 +44,7 @@ class GT_OverclockCalculator_UnitTest { .setRecipeHeat(1800) .setMachineHeat(2700) .calculate(); - assertEquals(1024 >> 4, calculator.getDuration(), messageDuration); + assertEquals(1024 / Math.pow(2, 4), calculator.getDuration(), messageDuration); assertEquals(correctConsumption, calculator.getConsumption(), messageEUt); } @@ -56,7 +58,7 @@ class GT_OverclockCalculator_UnitTest { .setRecipeHeat(1800) .setMachineHeat(1800) .calculate(); - assertEquals(1024 >> 4, calculator.getDuration(), messageDuration); + assertEquals(1024 / Math.pow(2, 4), calculator.getDuration(), messageDuration); assertEquals(VP[5], calculator.getConsumption(), messageEUt); } @@ -72,7 +74,7 @@ class GT_OverclockCalculator_UnitTest { .setRecipeHeat(1800) .setMachineHeat(3600) .calculate(); - assertEquals(1024 >> 5, calculator.getDuration(), messageDuration); + assertEquals(1024 / (Math.pow(4, 1) * Math.pow(2, 3)), calculator.getDuration(), messageDuration); assertEquals(correctConsumption, calculator.getConsumption(), messageEUt); } @@ -82,7 +84,7 @@ class GT_OverclockCalculator_UnitTest { .setEUt(V[6]) .setDuration(1024) .calculate(); - assertEquals(1024 >> 5, calculator.getDuration(), messageDuration); + assertEquals(1024 / Math.pow(2, 5), calculator.getDuration(), messageDuration); assertEquals(VP[6], calculator.getConsumption(), messageEUt); } @@ -93,7 +95,7 @@ class GT_OverclockCalculator_UnitTest { .setDuration(2048) .enablePerfectOC() .calculate(); - assertEquals(2048 >> 10, calculator.getDuration(), messageDuration); + assertEquals(2048 / Math.pow(4, 5), calculator.getDuration(), messageDuration); assertEquals(VP[6], calculator.getConsumption(), messageEUt); } @@ -109,7 +111,7 @@ class GT_OverclockCalculator_UnitTest { .setRecipeHeat(486) .setMachineHeat(3900) .calculate(); - assertEquals(2048 >> 6, calculator.getDuration(), messageDuration); + assertEquals(2048 / (Math.pow(4, 1) * Math.pow(2, 4)), calculator.getDuration(), messageDuration); assertEquals(correctConsumption, calculator.getConsumption(), messageEUt); } @@ -121,7 +123,7 @@ class GT_OverclockCalculator_UnitTest { .setDuration(1024) .setAmperageOC(true) .calculate(); - assertEquals(1024 >> 6, calculator.getDuration(), messageDuration); + assertEquals(1024 / Math.pow(2, 6), calculator.getDuration(), messageDuration); assertEquals(VP[7], calculator.getConsumption(), messageEUt); } @@ -133,8 +135,8 @@ class GT_OverclockCalculator_UnitTest { .setDuration(1024) .setAmperageOC(true) .calculate(); - assertEquals(1024 >> 6, calculator.getDuration(), messageDuration); - assertEquals(VP[0] << 12, calculator.getConsumption(), messageEUt); + assertEquals(1024 / Math.pow(2, 6), calculator.getDuration(), messageDuration); + assertEquals(VP[0] * Math.pow(4, 6), calculator.getConsumption(), messageEUt); } @Test @@ -145,7 +147,7 @@ class GT_OverclockCalculator_UnitTest { .setDuration(1024) .setAmperageOC(true) .calculate(); - assertEquals(1024 >> 9, calculator.getDuration(), messageDuration); + assertEquals(1024 / Math.pow(2, 9), calculator.getDuration(), messageDuration); assertEquals(VP[10], calculator.getConsumption(), messageEUt); } @@ -157,7 +159,7 @@ class GT_OverclockCalculator_UnitTest { .setDuration(1024) .setAmperageOC(true) .calculate(); - assertEquals(1024 >> 9, calculator.getDuration(), messageDuration); + assertEquals(1024 / Math.pow(2, 9), calculator.getDuration(), messageDuration); assertEquals(VP[10], calculator.getConsumption(), messageEUt); } @@ -170,7 +172,7 @@ class GT_OverclockCalculator_UnitTest { .setParallel(16) .setAmperageOC(true) .calculate(); - assertEquals(1024 >> 6, calculator.getDuration(), messageDuration); + assertEquals(1024 / Math.pow(2, 6), calculator.getDuration(), messageDuration); assertEquals(VP[9], calculator.getConsumption(), messageEUt); } @@ -184,7 +186,7 @@ class GT_OverclockCalculator_UnitTest { .setAmperageOC(true) .enablePerfectOC() .calculate(); - assertEquals(4096 >> 12, calculator.getDuration(), messageDuration); + assertEquals(4096 / Math.pow(4, 6), calculator.getDuration(), messageDuration); assertEquals(VP[9], calculator.getConsumption(), messageEUt); } @@ -197,7 +199,7 @@ class GT_OverclockCalculator_UnitTest { .setParallel(16) .setAmperageOC(true) .calculate(); - assertEquals(1024 >> 7, calculator.getDuration(), messageDuration); + assertEquals(1024 / Math.pow(2, 7), calculator.getDuration(), messageDuration); assertEquals(VP[10], calculator.getConsumption(), messageEUt); } @@ -208,7 +210,7 @@ class GT_OverclockCalculator_UnitTest { .setDuration(1024) .setParallel(8) .calculate(); - assertEquals(1024 >> 5, calculator.getDuration(), messageDuration); + assertEquals(1024 / Math.pow(2, 5), calculator.getDuration(), messageDuration); assertEquals(VP[6] * 8, calculator.getConsumption(), messageEUt); } @@ -221,7 +223,7 @@ class GT_OverclockCalculator_UnitTest { .setParallel(8) .setAmperageOC(true) .calculate(); - assertEquals(1024 >> 9, calculator.getDuration(), messageDuration); + assertEquals(1024 / Math.pow(2, 9), calculator.getDuration(), messageDuration); assertEquals(VP[6] * 8 * 256, calculator.getConsumption(), messageEUt); } @@ -231,7 +233,7 @@ class GT_OverclockCalculator_UnitTest { .setEUt(V[6]) .setDuration(77) .calculate(); - assertEquals(77 >> 5, calculator.getDuration(), messageDuration); + assertEquals((int) (77 / Math.pow(2, 5)), calculator.getDuration(), messageDuration); assertEquals(VP[6], calculator.getConsumption(), messageEUt); } @@ -253,7 +255,7 @@ class GT_OverclockCalculator_UnitTest { .setEUtDiscount(0.9f) .setDuration(1024) .calculate(); - assertEquals(1024 >> 5, calculator.getDuration(), messageDuration); + assertEquals(1024 / Math.pow(2, 5), calculator.getDuration(), messageDuration); assertEquals(correctConsumption, calculator.getConsumption(), messageEUt); } @@ -266,7 +268,7 @@ class GT_OverclockCalculator_UnitTest { .setDuration(1024) .enablePerfectOC() .calculate(); - assertEquals(1024 >> 10, calculator.getDuration(), messageDuration); + assertEquals(1024 / Math.pow(4, 5), calculator.getDuration(), messageDuration); assertEquals(correctConsumption, calculator.getConsumption(), messageEUt); } @@ -277,7 +279,7 @@ class GT_OverclockCalculator_UnitTest { .setSpeedBoost(0.9f) .setDuration(1024) .calculate(); - assertEquals((int) (1024 * 0.9f) >> 5, calculator.getDuration(), messageDuration); + assertEquals((int) (1024 * 0.9f / Math.pow(2, 5)), calculator.getDuration(), messageDuration); assertEquals(VP[6], calculator.getConsumption(), messageEUt); } @@ -289,7 +291,7 @@ class GT_OverclockCalculator_UnitTest { .setDuration(2048) .enablePerfectOC() .calculate(); - assertEquals((int) (2048 * 0.9f) >> 10, calculator.getDuration(), messageDuration); + assertEquals((int) ((2048 * 0.9f) / Math.pow(4, 5)), calculator.getDuration(), messageDuration); assertEquals(VP[6], calculator.getConsumption(), messageEUt); } @@ -326,17 +328,17 @@ class GT_OverclockCalculator_UnitTest { assertEquals(1, calculator.getDuration(), messageDuration); /* - * duration with speedboost = 5 - * log_2(5) ~ 2.3; + * duration with speedboost = 4.4 + * log_2(5) ~ 2.14; * round up to 3 to reach one tick duration */ int overclocksTillOneTick = 3; int overclocksBeyondOneTick = 2; // 3 overclocks, each gives 4x consumption growth per tick (1920) - long targetEUt = VP[1] << 2 * overclocksTillOneTick; + long targetEUt = (long) (VP[1] * Math.pow(4, overclocksTillOneTick)); // 2 remaining overclocks are beyond 1 tick, each provides 2x comsumption discount (480) - targetEUt >>= overclocksBeyondOneTick; + targetEUt /= Math.pow(2, overclocksBeyondOneTick); assertEquals(targetEUt, calculator.getConsumption(), messageEUt); } @@ -352,17 +354,17 @@ class GT_OverclockCalculator_UnitTest { .calculate(); /* - * duration with speedboost = 18 - * log_4(18) ~ 2.08; + * duration with speedboost = 17.6 + * log_4(18) ~ 2.06; * round up to 3 to reach one tick duration */ int overclocksTillOneTick = 3; int overclocksBeyondOneTick = 2; // 3 overclocks, each gives 4x consumption growth per tick (1920) - long targetEUt = VP[1] << 2 * overclocksTillOneTick; + long targetEUt = (long) (VP[1] * Math.pow(4, overclocksTillOneTick)); // 2 remaining overclocks are beyond 1 tick, each provides 4x comsumption discount (120) - targetEUt >>= 2 * overclocksBeyondOneTick; + targetEUt /= Math.pow(4, overclocksBeyondOneTick); assertEquals(targetEUt, calculator.getConsumption(), messageEUt); assertEquals(1, calculator.getDuration(), messageDuration); @@ -376,7 +378,7 @@ class GT_OverclockCalculator_UnitTest { .setEUtDiscount(0.9f) .setDuration(1024) .calculate(); - assertEquals(1024 >> 5, calculator.getDuration(), messageDuration); + assertEquals(1024 / Math.pow(2, 5), calculator.getDuration(), messageDuration); assertEquals(correctConsumption, calculator.getConsumption(), messageEUt); } @@ -389,7 +391,7 @@ class GT_OverclockCalculator_UnitTest { .setParallel(14) .setDuration(1024) .calculate(); - assertEquals(1024 >> 3, calculator.getDuration(), messageDuration); + assertEquals(1024 / Math.pow(2, 3), calculator.getDuration(), messageDuration); assertEquals(correctConsumption, calculator.getConsumption(), messageEUt); } @@ -413,7 +415,7 @@ class GT_OverclockCalculator_UnitTest { .setDuration(30) .calculate(); assertEquals(1, calculator.getDuration(), messageDuration); - assertEquals(16 << 14, calculator.getConsumption(), messageEUt); + assertEquals(16 * Math.pow(4, 7), calculator.getConsumption(), messageEUt); } @Test @@ -422,10 +424,12 @@ class GT_OverclockCalculator_UnitTest { .setParallel(56) .setAmperage(1) .setAmperageOC(true) - .setSpeedBoost(1f / 6f) - .setEUt(V[14]) - .setDuration(56); - assertEquals((24 * 56) << 20, calculator.calculateEUtConsumptionUnderOneTick(56, 6144)); + .setSpeedBoost(1f / 6.01f) // If we set this to 1/6 we will get 11 overclocks because of float imprecision. + .setEUt(V[14] * 1_048_576) + .setDuration(56) + .setCurrentParallel(6144) + .calculate(); + assertEquals((24 * 56) * Math.pow(4, 10), calculator.getConsumption()); } @Test @@ -441,10 +445,36 @@ class GT_OverclockCalculator_UnitTest { .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()))); + calculator.setCurrentParallel((int) (256 / calculator.calculateDurationUnderOneTick())) + .calculate(); + assertEquals(Math.ceil((((long) 1920 * 256) * Math.pow(4, 14)) * heatDiscount), calculator.getConsumption()); + } + + @Test + void testCorrectOverclockWhenCurrentParallelLessThanOriginalParallel() { + GT_OverclockCalculator calculator = new GT_OverclockCalculator().setRecipeEUt(24) + .setParallel(64) + .setAmperage(1) + .setAmperageOC(true) + .setEUt(V[6]) + .setDuration(56) + .setCurrentParallel(16) + .calculate(); + assertEquals(56 / Math.pow(2, 3), calculator.getDuration()); + assertEquals((24 * 16) * Math.pow(4, 3), calculator.getConsumption()); + } + + @Test + void stopsCorrectlyWhenOverclockingUnderOneTick() { + GT_OverclockCalculator calculator = new GT_OverclockCalculator().setRecipeEUt(VP[2]) + .setEUt(V[9]) + .setParallel(4) + .setDuration(10) + .setAmperageOC(false) + .setAmperage(16) + .setCurrentParallel(16) + .calculate(); + assertEquals((VP[2] * 4) * Math.pow(4, 6), calculator.getConsumption()); } @Test @@ -475,7 +505,7 @@ class GT_OverclockCalculator_UnitTest { .setAmperageOC(false) .setAmperage(16) .calculate(); - assertEquals((32 * 64), calculator.getConsumption(), messageEUt); + assertEquals(32 * 64, calculator.getConsumption(), messageEUt); } @Test @@ -499,7 +529,7 @@ class GT_OverclockCalculator_UnitTest { .setAmperageOC(false) .setAmperage(16) .calculate(); - assertEquals((8 << 4) * 16, calculator.getConsumption(), messageEUt); + assertEquals((8 * 16) * Math.pow(4, 2), calculator.getConsumption(), messageEUt); } @Test @@ -510,7 +540,7 @@ class GT_OverclockCalculator_UnitTest { .setDuration(20) .setAmperageOC(false) .calculate(); - assertEquals((8 << 2) * 16, calculator.getConsumption(), messageEUt); + assertEquals((8 * 16) * Math.pow(4, 1), calculator.getConsumption(), messageEUt); } @Test @@ -522,7 +552,7 @@ class GT_OverclockCalculator_UnitTest { .setAmperage(64) .setAmperageOC(false) .calculate(); - assertEquals((7 << 4) * 64, calculator.getConsumption(), messageEUt); + assertEquals((7 * 64) * Math.pow(4, 2), calculator.getConsumption(), messageEUt); } @Test @@ -534,7 +564,7 @@ class GT_OverclockCalculator_UnitTest { .setAmperage(19) .setAmperageOC(false) .calculate(); - assertEquals((7 << 4) * 19, calculator.getConsumption(), messageEUt); + assertEquals((7 * 19) * Math.pow(4, 2), calculator.getConsumption(), messageEUt); } @Test @@ -546,7 +576,7 @@ class GT_OverclockCalculator_UnitTest { .setAmperage(25) .setAmperageOC(false) .calculate(); - assertEquals((7 << 4) * 29, calculator.getConsumption(), messageEUt); + assertEquals((7 * 29) * Math.pow(4, 2), calculator.getConsumption(), messageEUt); } @Test @@ -556,8 +586,9 @@ class GT_OverclockCalculator_UnitTest { .setParallel(64) .setDuration(300) .setAmperage(64) - .setAmperageOC(false); - assertEquals(TierEU.LuV * 64, calculator.calculateEUtConsumptionUnderOneTick(64, 64), messageEUt); + .setAmperageOC(false) + .calculate(); + assertEquals(TierEU.LuV * 64, calculator.getConsumption(), messageEUt); } @Test @@ -568,7 +599,7 @@ class GT_OverclockCalculator_UnitTest { .setDuration(1024) .setEUtIncreasePerOC(4.1) .calculate(); - assertEquals(1024 >> 5, calculator.getDuration(), messageDuration); + assertEquals(1024 / Math.pow(2, 5), calculator.getDuration(), messageDuration); assertEquals(expectedEUt, calculator.getConsumption(), messageEUt); } @@ -585,6 +616,41 @@ class GT_OverclockCalculator_UnitTest { } @Test + void overclockWithCustomEutIncreasePerOCSupplier() { + Function<Integer, Double> laserOC = overclockCount -> overclockCount <= 5 ? 4 + : (4 + 0.3 * (overclockCount - 5)); + GT_OverclockCalculator calculator = new GT_OverclockCalculator().setRecipeEUt(VP[1]) + .setEUt(V[6]) + .setAmperageOC(true) + .setAmperage(1024) + .setDuration(1024) + .setEutIncreasePerOCSupplier(laserOC) + .calculate(); + assertEquals(5 + 4, calculator.getPerformedOverclocks()); + assertEquals(1024 / Math.pow(2, 9), calculator.getDuration()); + assertEquals((int) (VP[1] * Math.pow(4, 5) * 4.3 * 4.6 * 4.9 * 5.2), calculator.getConsumption()); + } + + @Test + void overclockUnderOneTickWithCustomEutIncreasePerOCSupplier() { + Function<Integer, Double> laserOC = overclockCount -> overclockCount <= 5 ? 4 + : (4 + 0.3 * (overclockCount - 5)); + GT_OverclockCalculator calculator = new GT_OverclockCalculator().setRecipeEUt(VP[1]) + .setEUt(V[6]) + .setAmperageOC(true) + .setAmperage(4000) + .setDuration(64) + .setEutIncreasePerOCSupplier(laserOC); + + assertEquals(Math.pow(2, 10) / 64, (int) (1 / calculator.calculateDurationUnderOneTick())); + + calculator.calculate(); + + assertEquals(5 + 5, calculator.getPerformedOverclocks()); + assertEquals((int) (VP[1] * Math.pow(4, 5) * 4.3 * 4.6 * 4.9 * 5.2 * 5.5), calculator.getConsumption()); + } + + @Test void slightlyOverOneAmpRecipeWorksWithSingleEnergyHatch() { GT_OverclockCalculator calculator = new GT_OverclockCalculator().setRecipeEUt(614400) .setEUt(TierEU.UV) |