From 3e519e890249825dc8face0087cc631684d36e8c Mon Sep 17 00:00:00 2001 From: Alkalus <3060479+draknyte1@users.noreply.github.com> Date: Thu, 13 Jan 2022 00:28:02 +0000 Subject: Basically finished work on Reactor Simulator. --- .../Ic2ExpReactorPlanner/AutomationSimulator.java | 759 +++++++ .../java/Ic2ExpReactorPlanner/BigintStorage.java | 60 + .../java/Ic2ExpReactorPlanner/Bundle.properties | 411 ++++ .../java/Ic2ExpReactorPlanner/BundleHelper.java | 43 + .../Ic2ExpReactorPlanner/Bundle_zh_CN.properties | 373 ++++ .../Ic2ExpReactorPlanner/ComponentFactory.java | 224 ++ .../java/Ic2ExpReactorPlanner/MaterialsList.java | 302 +++ src/main/java/Ic2ExpReactorPlanner/Reactor.java | 763 +++++++ .../Ic2ExpReactorPlanner/ReactorPlannerFrame.form | 2260 ++++++++++++++++++++ .../java/Ic2ExpReactorPlanner/SimulationData.java | 81 + .../java/Ic2ExpReactorPlanner/TaloniusDecoder.java | 26 + .../components/Condensator.java | 48 + .../components/CoolantCell.java | 31 + .../Ic2ExpReactorPlanner/components/Exchanger.java | 130 ++ .../Ic2ExpReactorPlanner/components/FuelRod.java | 166 ++ .../Ic2ExpReactorPlanner/components/Plating.java | 49 + .../components/ReactorItem.java | 533 +++++ .../Ic2ExpReactorPlanner/components/Reflector.java | 66 + .../java/Ic2ExpReactorPlanner/components/Vent.java | 110 + 19 files changed, 6435 insertions(+) create mode 100644 src/main/java/Ic2ExpReactorPlanner/AutomationSimulator.java create mode 100644 src/main/java/Ic2ExpReactorPlanner/BigintStorage.java create mode 100644 src/main/java/Ic2ExpReactorPlanner/Bundle.properties create mode 100644 src/main/java/Ic2ExpReactorPlanner/BundleHelper.java create mode 100644 src/main/java/Ic2ExpReactorPlanner/Bundle_zh_CN.properties create mode 100644 src/main/java/Ic2ExpReactorPlanner/ComponentFactory.java create mode 100644 src/main/java/Ic2ExpReactorPlanner/MaterialsList.java create mode 100644 src/main/java/Ic2ExpReactorPlanner/Reactor.java create mode 100644 src/main/java/Ic2ExpReactorPlanner/ReactorPlannerFrame.form create mode 100644 src/main/java/Ic2ExpReactorPlanner/SimulationData.java create mode 100644 src/main/java/Ic2ExpReactorPlanner/TaloniusDecoder.java create mode 100644 src/main/java/Ic2ExpReactorPlanner/components/Condensator.java create mode 100644 src/main/java/Ic2ExpReactorPlanner/components/CoolantCell.java create mode 100644 src/main/java/Ic2ExpReactorPlanner/components/Exchanger.java create mode 100644 src/main/java/Ic2ExpReactorPlanner/components/FuelRod.java create mode 100644 src/main/java/Ic2ExpReactorPlanner/components/Plating.java create mode 100644 src/main/java/Ic2ExpReactorPlanner/components/ReactorItem.java create mode 100644 src/main/java/Ic2ExpReactorPlanner/components/Reflector.java create mode 100644 src/main/java/Ic2ExpReactorPlanner/components/Vent.java (limited to 'src/main/java/Ic2ExpReactorPlanner') diff --git a/src/main/java/Ic2ExpReactorPlanner/AutomationSimulator.java b/src/main/java/Ic2ExpReactorPlanner/AutomationSimulator.java new file mode 100644 index 0000000000..488de59a8d --- /dev/null +++ b/src/main/java/Ic2ExpReactorPlanner/AutomationSimulator.java @@ -0,0 +1,759 @@ +package Ic2ExpReactorPlanner; + +import static Ic2ExpReactorPlanner.BundleHelper.formatI18n; +import static Ic2ExpReactorPlanner.BundleHelper.getI18n; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +import Ic2ExpReactorPlanner.components.ReactorItem; +import gtPlusPlus.api.objects.Logger; +import gtPlusPlus.core.util.math.MathUtils; +import gtPlusPlus.xmod.gregtech.common.tileentities.misc.GT_TileEntity_ComputerCube; + +/** + * + * @author Brian McCloud + */ +public class AutomationSimulator { + + private final Reactor reactor; + + private final ArrayList output; + + private final GT_TileEntity_ComputerCube mReactor; + + private final boolean[][] alreadyBroken = new boolean[6][9]; + + private final boolean[][] needsCooldown = new boolean[6][9]; + + private final int initialHeat; + + private double minEUoutput = Double.MAX_VALUE; + private double maxEUoutput = 0.0; + private double minHeatOutput = Double.MAX_VALUE; + private double maxHeatOutput = 0.0; + + private final int onPulseDuration; + private final int offPulseDuration; + private final int clockPeriod; + private final int suspendTemp; + private final int resumeTemp; + private final int maxSimulationTicks; + + private boolean reachedBelow50; + private boolean reachedBurn; + private boolean reachedEvaporate; + private boolean reachedHurt; + private boolean reachedLava; + private boolean reachedExplode; + + private boolean allFuelRodsDepleted = false; + private boolean componentsIntact = true; + private boolean anyRodsDepleted = false; + + private int activeTime = 0; + private int inactiveTime = 0; + private int currentActiveTime = 0; + private int minActiveTime = Integer.MAX_VALUE; + private int maxActiveTime = 0; + private int currentInactiveTime = 0; + private int minInactiveTime = Integer.MAX_VALUE; + private int maxInactiveTime = 0; + + private double totalHullHeating = 0; + private double totalComponentHeating = 0; + private double totalHullCooling = 0; + private double totalVentCooling = 0; + + private boolean showHeatingCoolingCalled = false; + + private boolean active = true; + + private int pauseTimer = 0; + + private int redstoneUsed = 0; + + private int lapisUsed = 0; + + private final MaterialsList replacedItems = new MaterialsList(); + + private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat(getI18n("Simulation.DecimalFormat")); + + private boolean completed = false; + + private boolean mRunning = false; + + private final SimulationData data = new SimulationData(); + public SimulationData getData() { + if (completed) { + return data; + } + return null; + } + + public AutomationSimulator(final Reactor reactor, final ArrayList output2, final GT_TileEntity_ComputerCube aTile) { + this.reactor = reactor; + this.output = output2; + this.mReactor = aTile; + this.initialHeat = (int) reactor.getCurrentHeat(); + this.onPulseDuration = reactor.getOnPulse(); + this.offPulseDuration = reactor.getOffPulse(); + this.clockPeriod = onPulseDuration + offPulseDuration; + this.suspendTemp = reactor.getSuspendTemp(); + this.resumeTemp = reactor.getResumeTemp(); + this.maxSimulationTicks = reactor.getMaxSimulationTicks(); + } + + public void process() { + + mRunning = true; + completed = false; + long startTime = System.nanoTime(); + int reactorTicks = 0; + int cooldownTicks = 0; + int totalRodCount = 0; + + publish(""); // NOI18N + publish(getI18n("Simulation.Started")); + reactor.setCurrentHeat(initialHeat); + reactor.clearVentedHeat(); + double minReactorHeat = initialHeat; + double maxReactorHeat = initialHeat; + reachedBelow50 = false; + reachedBurn = initialHeat >= 0.4 * reactor.getMaxHeat(); + reachedEvaporate = initialHeat >= 0.5 * reactor.getMaxHeat(); + reachedHurt = initialHeat >= 0.7 * reactor.getMaxHeat(); + reachedLava = initialHeat >= 0.85 * reactor.getMaxHeat(); + reachedExplode = false; + for (int row = 0; row < 6; row++) { + for (int col = 0; col < 9; col++) { + ReactorItem component = reactor.getComponentAt(row, col); + if (component != null) { + component.clearCurrentHeat(); + component.clearDamage(); + totalRodCount += component.getRodCount(); + } + publish(String.format("R%dC%d:0xC0C0C0", row, col)); // NOI18N + } + } + data.totalRodCount = totalRodCount; + double lastEUoutput = 0.0; + double totalEUoutput = 0.0; + double lastHeatOutput = 0.0; + double totalHeatOutput = 0.0; + double maxGeneratedHeat = 0.0; + double explosionPower = 10.0; + allFuelRodsDepleted = false; + componentsIntact = true; + anyRodsDepleted = false; + Logger.INFO("Reactor Current Heat: "+reactor.getCurrentHeat()); + Logger.INFO("Reactor Max Heat: "+reactor.getMaxHeat()); + Logger.INFO("Least EU Output: "+lastEUoutput); + Logger.INFO("Least Heat Output: "+lastHeatOutput); + Logger.INFO("Reactor Max Ticks: "+maxSimulationTicks); + Logger.INFO("All Fuel Depleted: "+allFuelRodsDepleted); + Logger.INFO("Running: "+isRunning()); + Logger.INFO("Stopped: "+hasStopped()); + while (reactor.getCurrentHeat() < reactor.getMaxHeat() && (!allFuelRodsDepleted || lastEUoutput > 0 || lastHeatOutput > 0) && reactorTicks < maxSimulationTicks && isRunning()) { + //Logger.INFO("Reactor Tick: "+reactorTicks); + reactorTicks++; + reactor.clearEUOutput(); + reactor.clearVentedHeat(); + for (int row = 0; row < 6; row++) { + for (int col = 0; col < 9; col++) { + ReactorItem component = reactor.getComponentAt(row, col); + if (component != null) { + component.preReactorTick(); + } + } + } + if (active) { + allFuelRodsDepleted = true; // assume rods depleted until one is + // found that isn't. + } + double generatedHeat = 0.0; + for (int row = 0; row < 6; row++) { + for (int col = 0; col < 9; col++) { + ReactorItem component = reactor.getComponentAt(row, col); + if (component != null && !component.isBroken()) { + if (allFuelRodsDepleted && component.getRodCount() > 0) { + allFuelRodsDepleted = false; + } + if (active) { + generatedHeat += component.generateHeat(); + } + component.dissipate(); + component.transfer(); + } + } + } + maxReactorHeat = Math.max(reactor.getCurrentHeat(), maxReactorHeat); + minReactorHeat = Math.min(reactor.getCurrentHeat(), minReactorHeat); + checkReactorTemperature(reactorTicks); + maxGeneratedHeat = Math.max(generatedHeat, maxGeneratedHeat); + if (active) { + for (int row = 0; row < 6; row++) { + for (int col = 0; col < 9; col++) { + ReactorItem component = reactor.getComponentAt(row, col); + if (component != null && !component.isBroken()) { + component.generateEnergy(); + } + } + } + } + lastEUoutput = reactor.getCurrentEUoutput(); + totalEUoutput += lastEUoutput; + lastHeatOutput = reactor.getVentedHeat(); + totalHeatOutput += lastHeatOutput; + if (reactor.getCurrentHeat() <= reactor.getMaxHeat()) { + if (reactor.isPulsed() || reactor.isAutomated()) { + if (active) { + activeTime++; + currentActiveTime++; + if (reactor.isPulsed() && (reactor.getCurrentHeat() >= suspendTemp || (reactorTicks % clockPeriod) >= onPulseDuration)) { + active = false; + minActiveTime = Math.min(currentActiveTime, minActiveTime); + maxActiveTime = Math.max(currentActiveTime, maxActiveTime); + currentActiveTime = 0; + } + } + else { + inactiveTime++; + currentInactiveTime++; + if (reactor.isAutomated() && pauseTimer > 0) { + pauseTimer--; + } + else if ((reactor.isPulsed() && reactor.getCurrentHeat() <= resumeTemp && (reactorTicks % clockPeriod) < onPulseDuration)) { + active = true; + minInactiveTime = Math.min(currentInactiveTime, minInactiveTime); + maxInactiveTime = Math.max(currentInactiveTime, maxInactiveTime); + currentInactiveTime = 0; + } + } + } + minEUoutput = Math.min(lastEUoutput, minEUoutput); + maxEUoutput = Math.max(lastEUoutput, maxEUoutput); + minHeatOutput = Math.min(lastHeatOutput, minHeatOutput); + maxHeatOutput = Math.max(lastHeatOutput, maxHeatOutput); + } + calculateHeatingCooling(reactorTicks); + handleAutomation(reactorTicks); + + handleBrokenComponents(reactorTicks, totalHeatOutput, totalRodCount, totalEUoutput, minReactorHeat, maxReactorHeat); + } + + if (hasStopped()) { + publish(formatI18n("Simulation.CancelledAtTick", reactorTicks)); + } + data.minTemp = (int) minReactorHeat; + data.maxTemp = (int) maxReactorHeat; + publish(formatI18n("Simulation.ReactorMinTemp", minReactorHeat)); + publish(formatI18n("Simulation.ReactorMaxTemp", maxReactorHeat)); + if (reactor.getCurrentHeat() < reactor.getMaxHeat()) { + publish(formatI18n("Simulation.TimeWithoutExploding", reactorTicks)); + if (reactor.isPulsed()) { + String rangeString = ""; + if (maxActiveTime > minActiveTime) { + rangeString = formatI18n("Simulation.ActiveTimeRange", minActiveTime, maxActiveTime); + } + else if (minActiveTime < activeTime) { + rangeString = formatI18n("Simulation.ActiveTimeSingle", minActiveTime); + } + publish(formatI18n("Simulation.ActiveTime", activeTime, rangeString)); + rangeString = ""; + if (maxInactiveTime > minInactiveTime) { + rangeString = formatI18n("Simulation.InactiveTimeRange", minInactiveTime, maxInactiveTime); + } + else if (minInactiveTime < inactiveTime) { + rangeString = formatI18n("Simulation.InactiveTimeSingle", minInactiveTime); + } + publish(formatI18n("Simulation.InactiveTime", inactiveTime, rangeString)); + } + final String replacedItemsString = replacedItems.toString(); + if (!replacedItemsString.isEmpty()) { + data.replacedItems = new MaterialsList(replacedItems); + publish(formatI18n("Simulation.ComponentsReplaced", replacedItemsString)); + } + + if (reactorTicks > 0) { + data.totalReactorTicks = reactorTicks; + if (reactor.isFluid()) { + data.totalHUoutput = (int) (40 * totalHeatOutput); + data.avgHUoutput = (int) (2 * totalHeatOutput / reactorTicks); + data.minHUoutput = 2 * minHeatOutput; + data.maxHUoutput = (int) (2 * maxHeatOutput); + if (totalHeatOutput > 0) { + publish(formatI18n("Simulation.HeatOutputs", DECIMAL_FORMAT.format(40 * totalHeatOutput), DECIMAL_FORMAT.format(2 * totalHeatOutput / reactorTicks), DECIMAL_FORMAT.format(2 + * minHeatOutput), DECIMAL_FORMAT.format(2 * maxHeatOutput))); + if (totalRodCount > 0) { + publish(formatI18n("Simulation.Efficiency", totalHeatOutput / reactorTicks / 4 / totalRodCount, minHeatOutput / 4 / totalRodCount, maxHeatOutput / 4 / totalRodCount)); + } + } + } + else { + data.totalEUoutput = (int) totalEUoutput; + data.avgEUoutput = MathUtils.roundToClosestInt(Math.ceil(totalEUoutput / (reactorTicks * 20))); + data.minEUoutput = minEUoutput / 20.0; + data.maxEUoutput = (int) (maxEUoutput / 20.0); + if (totalEUoutput > 0) { + publish(formatI18n("Simulation.EUOutputs", DECIMAL_FORMAT.format(totalEUoutput), DECIMAL_FORMAT.format(totalEUoutput / (reactorTicks * 20)), DECIMAL_FORMAT.format(minEUoutput + / 20.0), DECIMAL_FORMAT.format(maxEUoutput / 20.0))); + if (totalRodCount > 0) { + publish(formatI18n("Simulation.Efficiency", totalEUoutput / reactorTicks / 100 / totalRodCount, minEUoutput / 100 / totalRodCount, maxEUoutput / 100 / totalRodCount)); + } + } + } + } + + if (reactor.getCurrentHeat() > 0.0) { + publish(formatI18n("Simulation.ReactorRemainingHeat", reactor.getCurrentHeat())); + } + double prevReactorHeat = reactor.getCurrentHeat(); + double prevTotalComponentHeat = 0.0; + for (int row = 0; row < 6; row++) { + for (int col = 0; col < 9; col++) { + ReactorItem component = reactor.getComponentAt(row, col); + if (component != null && !component.isBroken()) { + if (component.getCurrentHeat() > 0.0) { + prevTotalComponentHeat += component.getCurrentHeat(); + publish(String.format("R%dC%d:0xFFA500", row, col)); // NOI18N + component.info.append(formatI18n("ComponentInfo.RemainingHeat", component.getCurrentHeat())); + } + } + } + } + if (prevReactorHeat == 0.0 && prevTotalComponentHeat == 0.0) { + publish(getI18n("Simulation.NoCooldown")); + } + else if (reactor.getCurrentHeat() < reactor.getMaxHeat()) { + double currentTotalComponentHeat = prevTotalComponentHeat; + int reactorCooldownTime = 0; + do { + reactor.clearVentedHeat(); + prevReactorHeat = reactor.getCurrentHeat(); + if (prevReactorHeat == 0.0) { + reactorCooldownTime = cooldownTicks; + } + prevTotalComponentHeat = currentTotalComponentHeat; + for (int row = 0; row < 6; row++) { + for (int col = 0; col < 9; col++) { + ReactorItem component = reactor.getComponentAt(row, col); + if (component != null && !component.isBroken()) { + component.dissipate(); + component.transfer(); + } + } + } + lastHeatOutput = reactor.getVentedHeat(); + totalHeatOutput += lastHeatOutput; + minEUoutput = Math.min(lastEUoutput, minEUoutput); + maxEUoutput = Math.max(lastEUoutput, maxEUoutput); + minHeatOutput = Math.min(lastHeatOutput, minHeatOutput); + maxHeatOutput = Math.max(lastHeatOutput, maxHeatOutput); + cooldownTicks++; + currentTotalComponentHeat = 0.0; + for (int row = 0; row < 6; row++) { + for (int col = 0; col < 9; col++) { + ReactorItem component = reactor.getComponentAt(row, col); + if (component != null && !component.isBroken()) { + currentTotalComponentHeat += component.getCurrentHeat(); + if (component.getCurrentHeat() == 0.0 && needsCooldown[row][col]) { + component.info.append(formatI18n("ComponentInfo.CooldownTime", cooldownTicks)); + needsCooldown[row][col] = false; + } + } + } + } + } + while (lastHeatOutput > 0 && cooldownTicks < 50000); + if (reactor.getCurrentHeat() < reactor.getMaxHeat()) { + if (reactor.getCurrentHeat() == 0.0) { + publish(formatI18n("Simulation.ReactorCooldownTime", reactorCooldownTime)); + } + else if (reactorCooldownTime > 0) { + publish(formatI18n("Simulation.ReactorResidualHeat", reactor.getCurrentHeat(), reactorCooldownTime)); + } + publish(formatI18n("Simulation.TotalCooldownTime", cooldownTicks)); + } + } + } + else { + publish(formatI18n("Simulation.ReactorOverheatedTime", reactorTicks)); + explosionPower = 10.0; + double explosionPowerMult = 1.0; + for (int row = 0; row < 6; row++) { + for (int col = 0; col < 9; col++) { + ReactorItem component = reactor.getComponentAt(row, col); + if (component != null) { + explosionPower += component.getExplosionPowerOffset(); + explosionPowerMult *= component.getExplosionPowerMultiplier(); + } + } + } + explosionPower *= explosionPowerMult; + publish(formatI18n("Simulation.ExplosionPower", explosionPower)); + } + double totalEffectiveVentCooling = 0.0; + double totalVentCoolingCapacity = 0.0; + double totalCellCooling = 0.0; + double totalCondensatorCooling = 0.0; + + for (int row = 0; row < 6; row++) { + for (int col = 0; col < 9; col++) { + ReactorItem component = reactor.getComponentAt(row, col); + if (component != null) { + if (component.getVentCoolingCapacity() > 0) { + component.info.append(formatI18n("ComponentInfo.UsedCooling", component.getBestVentCooling(), component.getVentCoolingCapacity())); + totalEffectiveVentCooling += component.getBestVentCooling(); + totalVentCoolingCapacity += component.getVentCoolingCapacity(); + } + else if (component.getBestCellCooling() > 0) { + component.info.append(formatI18n("ComponentInfo.ReceivedHeat", component.getBestCellCooling())); + totalCellCooling += component.getBestCellCooling(); + } + else if (component.getBestCondensatorCooling() > 0) { + component.info.append(formatI18n("ComponentInfo.ReceivedHeat", component.getBestCondensatorCooling())); + totalCondensatorCooling += component.getBestCondensatorCooling(); + } + else if (component.getMaxHeatGenerated() > 0) { + if (!reactor.isFluid() && component.getMaxEUGenerated() > 0) { + component.info.append(formatI18n("ComponentInfo.GeneratedEU", component.getMinEUGenerated(), component.getMaxEUGenerated())); + } + component.info.append(formatI18n("ComponentInfo.GeneratedHeat", component.getMinHeatGenerated(), component.getMaxHeatGenerated())); + } + if (component.getMaxReachedHeat() > 0) { + component.info.append(formatI18n("ComponentInfo.ReachedHeat", component.getMaxReachedHeat(), component.getMaxHeat())); + } + } + } + } + + // if (totalVentCoolingCapacity > 0) { + // publish(formatI18n("Simulation.TotalVentCooling", + // totalEffectiveVentCooling, totalVentCoolingCapacity)); + // } + showHeatingCooling(reactorTicks); // Call to show this info in case it + // hasn't already been shown, such + // as for an automated reactor. + if (totalCellCooling > 0) { + publish(formatI18n("Simulation.TotalCellCooling", totalCellCooling)); + } + if (totalCondensatorCooling > 0) { + publish(formatI18n("Simulation.TotalCondensatorCooling", totalCondensatorCooling)); + } + if (maxGeneratedHeat > 0) { + publish(formatI18n("Simulation.MaxHeatGenerated", maxGeneratedHeat)); + } + if (redstoneUsed > 0) { + publish(formatI18n("Simulation.RedstoneUsed", redstoneUsed)); + } + if (lapisUsed > 0) { + publish(formatI18n("Simulation.LapisUsed", lapisUsed)); + } + // double totalCooling = totalEffectiveVentCooling + totalCellCooling + + // totalCondensatorCooling; + // if (totalCooling >= maxGeneratedHeat) { + // publish(formatI18n("Simulation.ExcessCooling", totalCooling - + // maxGeneratedHeat)); + // } else { + // publish(formatI18n("Simulation.ExcessHeating", maxGeneratedHeat - + // totalCooling)); + // } + // return null; + + /* catch (Throwable e) { + if (cooldownTicks == 0) { + publish(formatI18n("Simulation.ErrorReactor", reactorTicks)); + } else { + publish(formatI18n("Simulation.ErrorCooldown", cooldownTicks)); + } + publish(e.toString(), " ", Arrays.toString(e.getStackTrace())); // NO18N + + }*/ + data.explosionPower = (int) explosionPower; + data.totalReactorTicks = reactorTicks; + long endTime = System.nanoTime(); + publish(formatI18n("Simulation.ElapsedTime", (endTime - startTime) / 1e9)); + mRunning = false; + completed = true; + } + + public boolean hasStopped() { + return !mRunning; + } + + public boolean isRunning() { + return mRunning; + } + + private void handleBrokenComponents(final int reactorTicks, final double totalHeatOutput, final int totalRodCount, final double totalEUoutput, final double minReactorHeat, final double maxReactorHeat) { + for (int row = 0; row < 6; row++) { + for (int col = 0; col < 9; col++) { + ReactorItem component = reactor.getComponentAt(row, col); + if (component != null && component.isBroken() && !alreadyBroken[row][col]) { + alreadyBroken[row][col] = true; + if (component.getRodCount() == 0) { + publish(String.format("R%dC%d:0xFF0000", row, col)); // NOI18N + component.info.append(formatI18n("ComponentInfo.BrokeTime", reactorTicks)); + if (componentsIntact) { + componentsIntact = false; + data.firstComponentBrokenTime = reactorTicks; + data.firstComponentBrokenRow = row; + data.firstComponentBrokenCol = col; + data.firstComponentBrokenDescription = component.toString(); + publish(formatI18n("Simulation.FirstComponentBrokenDetails", component.toString(), row, col, reactorTicks)); + if (reactor.isFluid()) { + data.prebreakTotalHUoutput = 40 * totalHeatOutput; + data.prebreakAvgHUoutput = 2 * totalHeatOutput / reactorTicks; + data.prebreakMinHUoutput = 2 * minHeatOutput; + data.prebreakMaxHUoutput = 2 * maxHeatOutput; + publish(formatI18n("Simulation.HeatOutputsBeforeBreak", DECIMAL_FORMAT.format(40 * totalHeatOutput), DECIMAL_FORMAT.format(2 * totalHeatOutput + / reactorTicks), DECIMAL_FORMAT.format(2 * minHeatOutput), DECIMAL_FORMAT.format(2 * maxHeatOutput))); + if (totalRodCount > 0) { + publish(formatI18n("Simulation.Efficiency", totalHeatOutput / reactorTicks / 4 / totalRodCount, minHeatOutput / 4 / totalRodCount, maxHeatOutput / 4 + / totalRodCount)); + } + } + else { + data.prebreakTotalEUoutput = totalEUoutput; + data.prebreakAvgEUoutput = totalEUoutput / (reactorTicks * 20); + data.prebreakMinEUoutput = minEUoutput / 20.0; + data.prebreakMaxEUoutput = maxEUoutput / 20.0; + publish(formatI18n("Simulation.EUOutputsBeforeBreak", DECIMAL_FORMAT.format(totalEUoutput), DECIMAL_FORMAT.format(totalEUoutput + / (reactorTicks * 20)), DECIMAL_FORMAT.format(minEUoutput / 20.0), DECIMAL_FORMAT.format(maxEUoutput / 20.0))); + if (totalRodCount > 0) { + publish(formatI18n("Simulation.Efficiency", totalEUoutput / reactorTicks / 100 / totalRodCount, minEUoutput / 100 / totalRodCount, maxEUoutput / 100 + / totalRodCount)); + } + } + } + } + else if (!anyRodsDepleted) { + anyRodsDepleted = true; + data.firstRodDepletedTime = reactorTicks; + data.firstRodDepletedRow = row; + data.firstRodDepletedCol = col; + data.firstRodDepletedDescription = component.toString(); + publish(formatI18n("Simulation.FirstRodDepletedDetails", component.toString(), row, col, reactorTicks)); + if (reactor.isFluid()) { + data.predepleteTotalHUoutput = 40 * totalHeatOutput; + data.predepleteAvgHUoutput = 2 * totalHeatOutput / reactorTicks; + data.predepleteMinHUoutput = 2 * minHeatOutput; + data.predepleteMaxHUoutput = 2 * maxHeatOutput; + publish(formatI18n("Simulation.HeatOutputsBeforeDepleted", DECIMAL_FORMAT.format(40 * totalHeatOutput), DECIMAL_FORMAT.format(2 * totalHeatOutput + / reactorTicks), DECIMAL_FORMAT.format(2 * minHeatOutput), DECIMAL_FORMAT.format(2 * maxHeatOutput))); + if (totalRodCount > 0) { + publish(formatI18n("Simulation.Efficiency", totalHeatOutput / reactorTicks / 4 / totalRodCount, minHeatOutput / 4 / totalRodCount, maxHeatOutput / 4 / totalRodCount)); + } + } + else { + data.predepleteTotalEUoutput = totalEUoutput; + data.predepleteAvgEUoutput = totalEUoutput / (reactorTicks * 20); + data.predepleteMinEUoutput = minEUoutput / 20.0; + data.predepleteMaxEUoutput = maxEUoutput / 20.0; + publish(formatI18n("Simulation.EUOutputsBeforeDepleted", DECIMAL_FORMAT.format(totalEUoutput), DECIMAL_FORMAT.format(totalEUoutput + / (reactorTicks * 20)), DECIMAL_FORMAT.format(minEUoutput / 20.0), DECIMAL_FORMAT.format(maxEUoutput / 20.0))); + if (totalRodCount > 0) { + publish(formatI18n("Simulation.Efficiency", totalEUoutput / reactorTicks / 100 / totalRodCount, minEUoutput / 100 / totalRodCount, maxEUoutput / 100 / totalRodCount)); + } + } + data.predepleteMinTemp = minReactorHeat; + data.predepleteMaxTemp = maxReactorHeat; + publish(formatI18n("Simulation.ReactorMinTempBeforeDepleted", minReactorHeat)); + publish(formatI18n("Simulation.ReactorMaxTempBeforeDepleted", maxReactorHeat)); + } + showHeatingCooling(reactorTicks); + } + } + } + } + + private void handleAutomation(final int reactorTicks) { + for (int row = 0; row < 6; row++) { + for (int col = 0; col < 9; col++) { + ReactorItem component = reactor.getComponentAt(row, col); + if (component != null && reactor.isAutomated()) { + if (component.getMaxHeat() > 1) { + if (component.getAutomationThreshold() > component.getInitialHeat() && component.getCurrentHeat() >= component.getAutomationThreshold()) { + component.clearCurrentHeat(); + replacedItems.add(component.name); + component.info.append(formatI18n("ComponentInfo.ReplacedTime", reactorTicks)); + if (component.getReactorPause() > 0) { + active = false; + pauseTimer = Math.max(pauseTimer, component.getReactorPause()); + minActiveTime = Math.min(currentActiveTime, minActiveTime); + maxActiveTime = Math.max(currentActiveTime, maxActiveTime); + currentActiveTime = 0; + } + } + else if (component.getAutomationThreshold() < component.getInitialHeat() && component.getCurrentHeat() <= component.getAutomationThreshold()) { + component.clearCurrentHeat(); + replacedItems.add(component.name); + component.info.append(formatI18n("ComponentInfo.ReplacedTime", reactorTicks)); + if (component.getReactorPause() > 0) { + active = false; + pauseTimer = Math.max(pauseTimer, component.getReactorPause()); + minActiveTime = Math.min(currentActiveTime, minActiveTime); + maxActiveTime = Math.max(currentActiveTime, maxActiveTime); + currentActiveTime = 0; + } + } + } + else if (component.isBroken() || (component.getMaxDamage() > 1 && component.getCurrentDamage() >= component.getAutomationThreshold())) { + component.clearDamage(); + replacedItems.add(component.name); + component.info.append(formatI18n("ComponentInfo.ReplacedTime", reactorTicks)); + if (component.getReactorPause() > 0) { + active = false; + pauseTimer = Math.max(pauseTimer, component.getReactorPause()); + minActiveTime = Math.min(currentActiveTime, minActiveTime); + maxActiveTime = Math.max(currentActiveTime, maxActiveTime); + currentActiveTime = 0; + } + } + } + if (reactor.isUsingReactorCoolantInjectors() && component != null && component.needsCoolantInjected()) { + component.injectCoolant(); + if ("rshCondensator".equals(component.baseName)) { + redstoneUsed++; + } + else if ("lzhCondensator".equals(component.baseName)) { + lapisUsed++; + } + } + } + } + } + + private void checkReactorTemperature(final int reactorTicks) { + if (reactor.getCurrentHeat() < 0.5 * reactor.getMaxHeat() && !reachedBelow50 && reachedEvaporate) { + publish(formatI18n("Simulation.TimeToBelow50", reactorTicks)); + reachedBelow50 = true; + data.timeToBelow50 = reactorTicks; + } + if (reactor.getCurrentHeat() >= 0.4 * reactor.getMaxHeat() && !reachedBurn) { + publish(formatI18n("Simulation.TimeToBurn", reactorTicks)); + reachedBurn = true; + data.timeToBurn = reactorTicks; + } + if (reactor.getCurrentHeat() >= 0.5 * reactor.getMaxHeat() && !reachedEvaporate) { + publish(formatI18n("Simulation.TimeToEvaporate", reactorTicks)); + reachedEvaporate = true; + data.timeToEvaporate = reactorTicks; + } + if (reactor.getCurrentHeat() >= 0.7 * reactor.getMaxHeat() && !reachedHurt) { + publish(formatI18n("Simulation.TimeToHurt", reactorTicks)); + reachedHurt = true; + data.timeToHurt = reactorTicks; + } + if (reactor.getCurrentHeat() >= 0.85 * reactor.getMaxHeat() && !reachedLava) { + publish(formatI18n("Simulation.TimeToLava", reactorTicks)); + reachedLava = true; + data.timeToLava = reactorTicks; + } + if (reactor.getCurrentHeat() >= reactor.getMaxHeat() && !reachedExplode) { + publish(formatI18n("Simulation.TimeToXplode", reactorTicks)); + reachedExplode = true; + data.timeToXplode = reactorTicks; + } + } + + private void calculateHeatingCooling(final int reactorTicks) { + if (reactorTicks > 20) { + for (int row = 0; row < 6; row++) { + for (int col = 0; col < 9; col++) { + ReactorItem component = reactor.getComponentAt(row, col); + if (component != null) { + totalHullHeating += component.getCurrentHullHeating(); + totalComponentHeating += component.getCurrentComponentHeating(); + totalHullCooling += component.getCurrentHullCooling(); + totalVentCooling += component.getCurrentVentCooling(); + } + } + } + } + } + + private void showHeatingCooling(final int reactorTicks) { + if (!showHeatingCoolingCalled) { + showHeatingCoolingCalled = true; + if (reactorTicks >= 40) { + double totalHullCoolingCapacity = 0; + double totalVentCoolingCapacity = 0; + for (int row = 0; row < 6; row++) { + for (int col = 0; col < 9; col++) { + ReactorItem component = reactor.getComponentAt(row, col); + if (component != null) { + totalHullCoolingCapacity += component.getHullCoolingCapacity(); + totalVentCoolingCapacity += component.getVentCoolingCapacity(); + } + } + } + data.hullHeating = totalHullHeating / (reactorTicks - 20); + data.componentHeating = totalComponentHeating / (reactorTicks - 20); + data.hullCooling = totalHullCooling / (reactorTicks - 20); + data.hullCoolingCapacity = totalHullCoolingCapacity; + data.ventCooling = totalVentCooling / (reactorTicks - 20); + data.ventCoolingCapacity = totalVentCoolingCapacity; + if (totalHullHeating > 0) { + publish(formatI18n("Simulation.HullHeating", totalHullHeating / (reactorTicks - 20))); + } + if (totalComponentHeating > 0) { + publish(formatI18n("Simulation.ComponentHeating", totalComponentHeating / (reactorTicks - 20))); + } + if (totalHullCoolingCapacity > 0) { + publish(formatI18n("Simulation.HullCooling", totalHullCooling / (reactorTicks - 20), totalHullCoolingCapacity)); + } + if (totalVentCoolingCapacity > 0) { + publish(formatI18n("Simulation.VentCooling", totalVentCooling / (reactorTicks - 20), totalVentCoolingCapacity)); + } + } + } + } + + private void publish(String aString) { + output.add(aString); + } + + protected void process(List chunks) { + /* + for (String chunk : chunks) { + if (chunk.isEmpty()) { + output.add(""); // NO18N + } + else { + if (chunk.matches("R\\dC\\d:.*")) { // NO18N + String temp = chunk.substring(5); + int row = chunk.charAt(1) - '0'; + int col = chunk.charAt(3) - '0'; + if (temp.startsWith("0x")) { // NO18N + mReactorComponents[row][col].setBackground(Color.decode(temp)); + if ("0xC0C0C0".equals(temp)) { + mReactorComponents[row][col].setToolTipText(null); + } + else if ("0xFF0000".equals(temp)) { + mReactorComponents[row][col].setToolTipText(getI18n("ComponentTooltip.Broken")); + } + else if ("0xFFA500".equals(temp)) { + mReactorComponents[row][col].setToolTipText(getI18n("ComponentTooltip.ResidualHeat")); + } + } + } + else { + output.add(chunk); + } + } + } + */ + } + + public void cancel() { + Logger.INFO("Stopping Simulation."); + mRunning = false; + completed = true; + } + + +} diff --git a/src/main/java/Ic2ExpReactorPlanner/BigintStorage.java b/src/main/java/Ic2ExpReactorPlanner/BigintStorage.java new file mode 100644 index 0000000000..03960cd7b1 --- /dev/null +++ b/src/main/java/Ic2ExpReactorPlanner/BigintStorage.java @@ -0,0 +1,60 @@ +package Ic2ExpReactorPlanner; + +import java.math.BigInteger; +import java.util.Base64; + +/** + * Stores numbers of varying size inside a BigInteger, expecting each to have + * a defined limit (which need not be an exact power of 2). Numbers are to be + * extracted in reverse order they were stored, and special values can be used + * to make certain values optional for inclusion (the calling class is + * responsible for handling this logic, though). + * @author Brian McCloud + */ +public class BigintStorage { + private BigInteger storedValue = BigInteger.ZERO; + + /** + * Stores the specified value. Requires that 0 <= value <= max. + * @param value the value to store. + * @param max the expected maximum for the value. + */ + public void store(int value, int max) { + if (value < 0 || value > max) { + throw new IllegalArgumentException(); + } + storedValue = storedValue.multiply(BigInteger.valueOf(max + 1)).add(BigInteger.valueOf(value)); + } + + /** + * Extracts a value based on the specified maximum. + * @param max the expected maximum for the value. + * @return the extracted value. + */ + public int extract(int max) { + BigInteger[] values = storedValue.divideAndRemainder(BigInteger.valueOf(max + 1)); + storedValue = values[0]; + return values[1].intValue(); + } + + /** + * Takes input of a Base64 string, and converts it to a BigintStorage. + * @param code the Base64-encoded string (presumed to be from @outputBase64) + * @return the converted storage object. + */ + public static BigintStorage inputBase64(String code) { + BigintStorage result = new BigintStorage(); + byte[] temp = Base64.getDecoder().decode(code); + result.storedValue = new BigInteger(temp); + return result; + } + + /** + * Outputs the current value of this BigintStorage as a Base64-encoded string. + * @return the Base64-encoded string. + */ + public String outputBase64() { + byte[] temp = storedValue.toByteArray(); + return Base64.getEncoder().encodeToString(temp); + } +} diff --git a/src/main/java/Ic2ExpReactorPlanner/Bundle.properties b/src/main/java/Ic2ExpReactorPlanner/Bundle.properties new file mode 100644 index 0000000000..b20587693f --- /dev/null +++ b/src/main/java/Ic2ExpReactorPlanner/Bundle.properties @@ -0,0 +1,411 @@ + +# Comparison keys are for comparing two simulated reactors. Instead of being in +# in a TextArea like the main simulation, the comparison will be in a JLabel, wrapped +# in html tags, to allow color coding of the text more easily. + +Comparison.CompareDecimalFormat=+#,##0.##;-# +Comparison.ComponentHeating=Component heating: %s (%s/%s)
+Comparison.ComponentsHeading=Components:
+Comparison.ComponentsReplacedHeading=Components replaced:
+Comparison.Default=Please run at least two simulations (preferably with different reactor designs) to get a comparison. +Comparison.EUEUoutput=total output: %s (%s/%s) EU (%s EU/t average (%s/%s), %s EU/t min (%s/%s), %s EU/t max (%s/%s))
+Comparison.EUHUoutput=total output: %s EU / %s HU (%s EU/t / %s HU/t average, %s EU/t / %s HU/t min, %s EU/t / %s HU/t max)
+Comparison.Header=Most recent simulated reactor (left, in-grid) compared to previous simulated reactor (right, in-tab): +Comparison.HUEUoutput=total output: %s HU / %s EU (%s HU/t / %s EU/t average, %s HU/t / %s EU/t min, %s HU/t / %s EU/t max)
+Comparison.HUHUoutput=total output: %s (%s/%s) HU (%s HU/t average (%s/%s), %s HU/t min (%s/%s), %s HU/t max (%s/%s))
+Comparison.HullCooling=Hull cooling: %s (%s/%s)
+Comparison.HullCoolingPossible=Possible hull cooling: %s (%s/%s)
+Comparison.HullHeating=Hull heating: %s (%s/%s)
+Comparison.MaterialsEntry=%s %s (%s/%s)
+Comparison.MaterialsHeading=Materials:
+Comparison.NoDifferences=No significant differences detected. +Comparison.PostsimMaxTemp=Reactor maximum temperature: %s (%s/%s)
+Comparison.PostsimMinTemp=Reactor minimum temperature: %s (%s/%s)
+Comparison.PredepleteMaxTemp=Reactor maximum temperature (before first fuel rod depleted): %s (%s/%s)
+Comparison.PredepleteMinTemp=Reactor minimum temperature (before first fuel rod depleted): %s (%s/%s)
+Comparison.Prefix.PostSimulation=After simulation,\u0020 +Comparison.Prefix.PostSimulationTime=Time simulated:\u0020 +Comparison.Prefix.Prebreak=Before first component broken,\u0020 +Comparison.Prefix.PrebreakTime=Time to first component break:\u0020 +Comparison.Prefix.Predeplete=Before first rod depleted,\u0020 +Comparison.Prefix.PredepleteTime=Time to first rod depletion:\u0020 +Comparison.Prefix.TimeToBelow50=Time to below 50%% heat (after being above it):\u0020 +Comparison.Prefix.TimeToBurn=Time to "Burn" temperature:\u0020 +Comparison.Prefix.TimeToEvaporate=Time to "Evaporate" temperature:\u0020 +Comparison.Prefix.TimeToHurt=Time to "Hurt" temperature:\u0020 +Comparison.Prefix.TimeToLava=Time to "Lava" temperature:\u0020 +Comparison.Prefix.TimeToXplode=Time to explode:\u0020 +Comparison.SimpleDecimalFormat=#,##0.## +Comparison.Time.Both=%+,d seconds (%d/%d)
+Comparison.Time.BothColored=%+,d seconds (%d/%d)
+Comparison.Time.LeftOnly=%d/\u221e
+Comparison.Time.RightOnly=\u221e/%d
+Comparison.VentCooling=Vent cooling: %s (%s/%s)
+Comparison.VentCoolingPossible=Possible vent cooling: %s (%s/%s)
+ +# ComponentData keys are for providing extra details in the tooltips for the component palette. +# Suggested by kekzdealer in Pull Request: https://github.com/MauveCloud/Ic2ExpReactorPlanner/pull/67 +# but heavily modified since. + +ComponentData.AdvancedHeatExchanger=Heat Capacity: 10,000
Hull Exchange Rate: 8 heat/s
Component Exchange Rate: 24 heat/s +ComponentData.AdvancedHeatVent=Heat Capacity: 1,000
Self Venting Rate: 12 heat/s +ComponentData.ComponentHeatExchanger=Heat Capacity: 5,000
Component Exchange Rate: 36 heat/s +ComponentData.ComponentHeatVent=Component Venting Rate: 4 heat/s +ComponentData.ContainmentReactorPlating=Dampens explosions +ComponentData.CoolantCell10k=Heat Capacity: 10,000 +ComponentData.CoolantCell180kHelium=Heat Capacity: 180,000 +ComponentData.CoolantCell180kNak=Heat Capacity: 180,000 +ComponentData.CoolantCell30k=Heat Capacity: 30,000 +ComponentData.CoolantCell360kHelium=Heat Capacity: 360,000 +ComponentData.CoolantCell360kNak=Heat Capacity: 360,000 +ComponentData.CoolantCell60k=Heat Capacity: 60,000 +ComponentData.CoolantCell60kHelium=Heat Capacity: 60,000 +ComponentData.CoolantCell60kNak=Heat Capacity: 60,000 +ComponentData.CoolantCell180kSpace=Heat Capacity: 180,000 +ComponentData.CoolantCell360kSpace=Heat Capacity: 360,000 +ComponentData.CoolantCell540kSpace=Heat Capacity: 540,000 +ComponentData.CoolantCell1080kSpace=Heat Capacity: 1080,000 +ComponentData.DualFuelRodCesium=Generation Time: 10,861 seconds
EU Generation: 40/60/80/100/120 /t
Heat Generation: 6/12/20/30/42 /s +ComponentData.DualFuelRodCoaxium=Generation Time: 20,000 seconds
EU Generation: 20/30/40/50/60 /t
Heat Generation: 0 /s +ComponentData.DualFuelRodMox=Generation Time: 10,000 seconds
EU Generation: [20,100)/[30,150)/[40,200)/[50,250)/[60,300) /t - scales linearly with hull temperature.
Heat Generation in EU reactor or when hull temperature<=50%: 24/48/80/120/168 /s
Heat Generation in fluid reactor when hull temperature>50%: 48/96/160/240/336 /s +ComponentData.DualFuelRodNaquadah=Generation Time: 100,000 seconds
EU Generation: [40,100)/[60,150)/[80,200)/[100,250)/[120,300) /t - scales linearly with hull temperature.
Heat Generation in EU reactor or when hull temperature<=50%: 24/48/80/120/168 /s
Heat Generation in fluid reactor when hull temperature>50%: 48/96/160/240/336 /s +ComponentData.DualFuelRodNaquadahGTNH=Generation Time: 100,000 seconds
EU Generation: 20/30/40/50/60 /t
Heat Generation: 24/48/80/120/168 /s +ComponentData.DualFuelRodNaquadria=Generation Time: 100,000 seconds
EU Generation: [40,100)/[60,150)/[80,200)/[100,250)/[120,300) /t - scales linearly with hull temperature.
Heat Generation in EU reactor or when hull temperature<=50%: 24/48/80/120/168 /s
Heat Generation in fluid reactor when hull temperature>50%: 48/96/160/240/336 /s +ComponentData.DualFuelRodThorium=Generation Time: 50,000 seconds
EU Generation: 4/6/8/10/12 /t
Heat Generation: 6/12/20/30/42 /s +ComponentData.DualFuelRodTiberium=Generation Time: 50,000 seconds
EU Generation: 10/20/30/40/50 /t
Heat Generation: 12/24/40/60/84 /s +ComponentData.DualFuelRodUranium=Generation Time: 20,000 seconds
EU Generation: 20/30/40/50/60 /t
Heat Generation: 24/48/80/120/168 /s +ComponentData.FuelRodCesium=Generation Time: 10,861 seconds
EU Generation: 10/20/30/40/50 /t
Heat Generation: 1/3/8/10/15 /s +ComponentData.FuelRodCoaxium=Generation Time: 20,000 seconds
EU Generation: 5/10/15/20/25 /t
Heat Generation: 0 /s +ComponentData.FuelRodMox=Generation Time: 10,000 seconds
EU Generation: [5,25)/[10,50)/[15,75)/[20,100)/[25,125) /t - scales linearly with hull temperature.
Heat Generation in EU reactor or when hull temperature<=50%: 4/12/24/40/60 /s
Heat Generation in fluid reactor when hull temperature>50%: 8/24/48/80/120 /s +ComponentData.FuelRodNaquadah=Generation Time: 100,000 seconds
EU Generation: [10,25)/[20,50)/[30,75)/[40,100)/[50,125) /t - scales linearly with hull temperature.
Heat Generation in EU reactor or when hull temperature<=50%: 4/12/24/40/60 /s
Heat Generation in fluid reactor when hull temperature>50%: 8/24/48/80/120 /s +ComponentData.FuelRodNaquadahGTNH=Generation Time: 100,000 seconds
EU Generation: 5/10/15/20/25 /t
Heat Generation: 4/12/24/40/60 /s +ComponentData.FuelRodNaquadria=Generation Time: 100,000 seconds
EU Generation: [10,25)/[20,50)/[30,75)/[40,100)/[50,125) /t - scales linearly with hull temperature.
Heat Generation in EU reactor or when hull temperature<=50%: 4/12/24/40/60 /s
Heat Generation in fluid reactor when hull temperature>50%: 8/24/48/80/120 /s +ComponentData.FuelRodTheCore=Generation Time: 100,000 seconds
EU Generation: 10880 /t
Heat Generation: 19584 /s +ComponentData.FuelRodThorium=Generation Time: 50,000 seconds
EU Generation: 1/2/3/4/5 /t
Heat Generation: 1/3/6/10/15 /s +ComponentData.FuelRodTiberium=Generation Time: 50,000 seconds
EU Generation: 5/10/15/20/25 /t
Heat Generation: 2/6/12/20/30 /s +ComponentData.FuelRodUranium=Generation Time: 20,000 seconds
EU Generation: 5/10/15/20/25 /t
Heat Generation: 4/12/24/40/60 /s +ComponentData.HeatCapacityReactorPlating=Increases maximum heat capacity +ComponentData.HeatExchanger=Heat Capacity: 2,500
Hull Exchange Rate: 4 heat/s
Component Exchange Rate: 12 heat/s +ComponentData.HeatVent=Heat Capacity: 1,000
Self Venting Rate: 6 heat/s +ComponentData.IridiumNeutronReflector=Durability: Infinite +ComponentData.LzhCondensator=Heat Capacity: 100,000
Cannot be vented from. +ComponentData.NeutronReflector=Durability: 30,000 (10,000 in MC 1.7.10) +ComponentData.OverclockedHeatVent=Heat Capacity: 1,000
Self Venting Rate: 20 heat/s
Hull Cooling Rate: 36 heat/s +ComponentData.QuadFuelRodCesium=Generation Time: 10,861 seconds
EU Generation: 120/160/200/240/280 /t
Heat Generation: 24/40/60/84/112 /s +ComponentData.QuadFuelRodCoaxium=Generation Time: 20,000 seconds
EU Generation: 60/80/100/120/140 /t
Heat Generation: 0 /s +ComponentData.QuadFuelRodMox=Generation Time: 10,000 seconds
EU Generation: [60,300)/[80,400)/[100,500)/[120,600)/[140,700) /t - scales linearly with hull temperature.
Heat Generation in EU reactor or when hull temperature<=50%: 96/160/240/336/448 /s
Heat Generation in fluid reactor when hull temperature>50%: 192/320/480/672/896 /s +ComponentData.QuadFuelRodNaquadah=Generation Time: 100,000 seconds
EU Generation: [120,300)/[160,400)/[200,500)/[240,600)/[280,700) /t - scales linearly with hull temperature.
Heat Generation in EU reactor or when hull temperature<=50%: 96/160/240/336/448 /s
Heat Generation in fluid reactor when hull temperature>50%: 192/320/480/672/896 /s +ComponentData.QuadFuelRodNaquadahGTNH=Generation Time: 100,000 seconds
EU Generation: 60/80/100/120/140 /t
Heat Generation: 96/160/240/336/448 /s +ComponentData.QuadFuelRodNaquadria=Generation Time: 100,000 seconds
EU Generation: [120,300)/[160,400)/[200,500)/[240,600)/[280,700) /t - scales linearly with hull temperature.
Heat Generation in EU reactor or when hull temperature<=50%: 96/160/240/336/448 /s
Heat Generation in fluid reactor when hull temperature>50%: 192/320/480/672/896 /s +ComponentData.QuadFuelRodThorium=Generation Time: 50,000 seconds
EU Generation: 12/16/20/24/28 /t
Heat Generation: 24/40/60/84/112 /s +ComponentData.QuadFuelRodTiberium=Generation Time: 50,000 seconds
EU Generation: 60/80/100/120/140 /t
Heat Generation: 48/80/120/168/224 /s +ComponentData.QuadFuelRodUranium=Generation Time: 20,000 seconds
EU Generation: 60/80/100/120/140 /t
Heat Generation: 96/160/240/336/448 /s +ComponentData.ReactorHeatExchanger=Heat Capacity: 5,000
Hull Exchange Rate: 72 heat/s +ComponentData.ReactorHeatVent=Heat Capacity: 1,000
Self Venting Rate: 5 heat/s
Hull Cooling Rate: 5 heat/s +ComponentData.ReactorPlating=Crafting component for Containment and Heat-Capacity Reactor Plating +ComponentData.RshCondensator=Heat Capacity: 20,000
Cannot be vented from. +ComponentData.ThickNeutronReflector=Durability: 120,000 (40,000 in MC 1.7.10) + +# ComponentInfo keys are for updating information about a component during a simulation. + +ComponentInfo.BrokeTime=\nBroke after %,d seconds. +ComponentInfo.CooldownTime=\nTook %,d seconds to cool down. +ComponentInfo.GeneratedEU=\nGenerated %,.2f to %,.2f EU per second. +ComponentInfo.GeneratedHeat=\nGenerated %,.0f to %,.0f heat per second. +ComponentInfo.ReachedHeat=\nReached up to %,.0f of %,.0f heat. +ComponentInfo.ReceivedHeat=\nReceived at most %,.0f heat per second. +ComponentInfo.RemainingHeat=\nHad %,.0f heat left after main simulation stopped. +ComponentInfo.ReplacedTime=\nReplaced at %,d seconds. +ComponentInfo.ResidualHeat=\nHad %,.0f heat left after cooldown period. +ComponentInfo.UsedCooling=\nUsed %,.0f of %,.0f cooling. + + +# Keys for component names were originally matched to class names, to allow using reflection to look them up. +# However, refactoring eliminated the "one class for each component type" idea. +# These keys will be used both in the reactor area and the component selection area. + +ComponentName.AdvancedHeatExchanger=Advanced Heat Exchanger +ComponentName.AdvancedHeatVent=Advanced Heat Vent +ComponentName.ComponentHeatExchanger=Component Heat Exchanger +ComponentName.ComponentHeatVent=Component Heat Vent +ComponentName.ContainmentReactorPlating=Containment Reactor Plating +ComponentName.CoolantCell10k=10k Coolant Cell +ComponentName.CoolantCell1080kSpace=1080k Space Coolant Cell +ComponentName.CoolantCell180kHelium=180k He Coolant Cell +ComponentName.CoolantCell180kNak=180k NaK Coolant Cell +ComponentName.CoolantCell180kSpace=180k Space Coolant Cell +ComponentName.CoolantCell30k=30k Coolant Cell +ComponentName.CoolantCell360kHelium=360k He Coolant Cell +ComponentName.CoolantCell360kNak=360k NaK Coolant Cell +ComponentName.CoolantCell360kSpace=360k Space Coolant Cell +ComponentName.CoolantCell540kSpace=540k Space Coolant Cell +ComponentName.CoolantCell60k=60k Coolant Cell +ComponentName.CoolantCell60kHelium=60k He Coolant Cell +ComponentName.CoolantCell60kNak=60k NaK Coolant Cell +ComponentName.DualFuelRodCesium=Dual Fuel Rod (Cesium) +ComponentName.DualFuelRodCoaxium=Dual Fuel Rod (Coaxium) +ComponentName.DualFuelRodMox=Dual Fuel Rod (MOX) +ComponentName.DualFuelRodNaquadah=Dual Fuel Rod (Naquadah) +ComponentName.DualFuelRodNaquadahGTNH=Dual Fuel Rod (Naquadah) +ComponentName.DualFuelRodNaquadria=Dual Fuel Rod (Naquadria) +ComponentName.DualFuelRodThorium=Dual Fuel Rod (Thorium) +ComponentName.DualFuelRodTiberium=Dual Fuel Rod (Tiberium) +ComponentName.DualFuelRodUranium=Dual Fuel Rod (Uranium) +ComponentName.FuelRodCesium=Fuel Rod (Cesium) +ComponentName.FuelRodCoaxium=Fuel Rod (Coaxium) +ComponentName.FuelRodMox=Fuel Rod (MOX) +ComponentName.FuelRodNaquadah=Fuel Rod (Naquadah) +ComponentName.FuelRodNaquadahGTNH=Fuel Rod (Naquadah) +ComponentName.FuelRodNaquadria=Fuel Rod (Naquadria) +ComponentName.FuelRodTheCore=Fuel Rod (The Core) +ComponentName.FuelRodThorium=Fuel Rod (Thorium) +ComponentName.FuelRodTiberium=Fuel Rod (Tiberium) +ComponentName.FuelRodUranium=Fuel Rod (Uranium) +ComponentName.HeatCapacityReactorPlating=Heat-Capacity Reactor Plating +ComponentName.HeatExchanger=Heat Exchanger +ComponentName.HeatVent=Heat Vent +ComponentName.IridiumNeutronReflector=Iridium Neutron Reflector +ComponentName.LzhCondensator=LZH-Condensator +ComponentName.NeutronReflector=Neutron Reflector +ComponentName.OverclockedHeatVent=Overclocked Heat Vent +ComponentName.QuadFuelRodCesium=Quad Fuel Rod (Cesium) +ComponentName.QuadFuelRodCoaxium=Quad Fuel Rod (Coaxium) +ComponentName.QuadFuelRodMox=Quad Fuel Rod (MOX) +ComponentName.QuadFuelRodNaquadah=Quad Fuel Rod (Naquadah) +ComponentName.QuadFuelRodNaquadahGTNH=Quad Fuel Rod (Naquadah) +ComponentName.QuadFuelRodNaquadria=Quad Fuel Rod (Naquadria) +ComponentName.QuadFuelRodThorium=Quad Fuel Rod (Thorium) +ComponentName.QuadFuelRodTiberium=Quad Fuel Rod (Tiberium) +ComponentName.QuadFuelRodUranium=Quad Fuel Rod (Uranium) +ComponentName.ReactorHeatExchanger=Reactor Heat Exchanger +ComponentName.ReactorHeatVent=Reactor Heat Vent +ComponentName.ReactorPlating=Reactor Plating +ComponentName.RshCondensator=RSH-Condensator +ComponentName.ThickNeutronReflector=Thick Neutron Reflector + +ComponentTooltip.Broken=Broke during last simulation +ComponentTooltip.ResidualHeat=Had residual heat after last simulation + +Config.CSVCheckbox=Output CSV Data +Config.CSVLimit=For how many simulated seconds: +Config.EUReactor=EU Reactor +Config.FluidReactor=Fluid Reactor +Config.InitialComponentHeat=Initial Heat: +Config.NoComponentSelected=No component selected +Config.OffPulse=Off-pulse duration: +Config.OnPulse=On-pulse duration: +Config.PlacingReactorPause=Reactor Pause: +Config.PlacingReplacementThreshold=Threshold: +Config.PulseHelp=(on-pulse can be set to 5 million to mimic having no redstone timing) +Config.ReactorCoolantInjectors=Use Reactor Coolant Injectors (MC 1.8+ only) +Config.ReactorPause=Reactor Pause (seconds): +Config.ReactorPauseHelp=(This is how long the reactor will pause while replacing this component) +Config.ReplacementThreshold=Replacement Threshold: +Config.ReplacementThresholdHelp=(Set higher than component's initial heat/damage to replace the component when it gets this hot/damaged, or lower to replace a component that has cooled; broken components will be replaced during automation runs regardless of this setting) +Config.ResumeTemp=Resume when reactor temp <= +# Same language string should be usable anywhere "seconds" appears. +Config.Seconds=seconds +Config.SimulationStyle=Simulation Style: +Config.SuspendTemp=Suspend when reactor temp >= +Config.SuspendTempHelp=(both temps can be set to match explode temp to mimic having no temperature control) + +CSVData.EntryComponentValue=,"%.2f" +CSVData.EntryComponentOutput=,%.0f +CSVData.EntryCoreHeat=,%.0f +CSVData.EntryEUOutput=,"%.2f" +CSVData.EntryHUOutput=,%.0f +CSVData.EntryReactorTick=%d +CSVData.HeaderComponentName=,%s (R%dC%d) +CSVData.HeaderComponentOutput=,%s (R%dC%d) Output +CSVData.HeaderCoreHeat=,Core Heat +CSVData.HeaderEUOutput=,EU Output +CSVData.HeaderHUOutput=,HU Output +CSVData.HeaderReactorTick=Reactor Time + +MaterialName.AdvancedAlloy=Advanced Alloy +MaterialName.AdvancedCircuit=Advanced Circuit +MaterialName.Aluminium=Aluminium +MaterialName.BasicCircuit=Basic Circuit +MaterialName.Beryllium=Beryllium +MaterialName.Bronze=Bronze +MaterialName.CallistoIceDust=Callisto Ice Dust +MaterialName.CesiumFuel=Cesium-Enriched Nuclear Fuel +MaterialName.Coal=Coal +MaterialName.CoaxiumFuel=Coaxium-Enriched Nuclear Fuel +MaterialName.Copper=Copper +MaterialName.Diamond=Diamond +MaterialName.DistilledWater=Distilled Water +MaterialName.EmptyCell=Empty Cell +MaterialName.EnrichedNaquadah=Enriched Naquadah +MaterialName.FluxedElectrum=Fluxed Electrum +MaterialName.Glass=Glass +MaterialName.GlowstoneDust=Glowstone Dust +MaterialName.Gold=Gold +MaterialName.Graphite=Graphite +MaterialName.Helium==Helium +MaterialName.Iridium=Iridium +MaterialName.IridiumReinforcedPlate=Iridium Reinforced Plate +MaterialName.Iron=Iron +MaterialName.LapisLazuli=Lapis Lazuli +MaterialName.Lead=Lead +MaterialName.LedoxDust=Ledox Dust +MaterialName.MoxFuel=MOX Fuel +MaterialName.Naquadria=Naquadria +MaterialName.Platinum=Platinum +MaterialName.Potassium=Potassium +MaterialName.Redstone=Redstone +MaterialName.ReinforcedGlass=Reinforced Glass +MaterialName.Rubber=Rubber +MaterialName.Sodium=Sodium +MaterialName.Thorium=Thorium +MaterialName.Tiberium=Tiberium +MaterialName.Tungsten=Tungsten +MaterialName.Tin=Tin +MaterialName.UraniumFuel=Uranium Fuel + +# %s at the end of this string is for optionally showing the range of active time. +Simulation.ActiveTime=Reactor was active for a total of %,d seconds%s.\n +Simulation.ActiveTimeRange=\u0020(%,d to %,d seconds at a time) +Simulation.ActiveTimeSingle=\u0020(%,d seconds at a time) +Simulation.CancelledAtTick=Simulation cancelled after simulating %,d seconds.\n +Simulation.ComponentHeating=Component heating: %.2f average.\n +Simulation.ComponentsReplaced=Components replaced:\n%s +Simulation.CSVOpenFailure=Failed to open CSV file for output.\n +Simulation.CycleCompleteTime=Cycle complete after %,d seconds.\n +# This will be used to optionally show extra precision, in format strings where %s is used when %.2f might otherwise be expected. +Simulation.DecimalFormat=#,##0.## +Simulation.Efficiency=Efficiency: %.2f average, %.2f minimum, %.2f maximum\n +Simulation.ElapsedTime=Simulation took %.2f seconds.\n +Simulation.ErrorCooldown=Error %,d simulated seconds into cooldown.\n +Simulation.ErrorReactor=Error after simulating %d seconds of reactor activity\n +Simulation.EUOutputs=Total output after full simulation: %s EU (%s EU/t average, %s EU/t min, %s EU/t max)\n +Simulation.EUOutputsBeforeDepleted=Total output before first fuel rod depleted: %s EU (%s EU/t average, %s EU/t min, %s EU/t max)\n +Simulation.EUOutputsBeforeBreak=Total output before first component broken: %s EU (%s EU/t average, %s EU/t min, %s EU/t max)\n +Simulation.ExcessCooling=Excess cooling: %.2f\n +Simulation.ExcessHeating=Excess heating: %.2f\n +Simulation.ExplosionPower=Raw explosion power: %,.2f\n +Simulation.FirstComponentBrokenDetails=First Component Broken: %s at row %d column %d, at %d seconds.\n +Simulation.FirstRodDepletedDetails=First Fuel Rod Depleted: %s at row %d column %d, at %d seconds.\n +Simulation.FuelRodsTime=Fuel rods (if any) stopped after %,d seconds.\n +Simulation.HeatOutputs=Total output after full simulation: %s HU (%s HU/t average, %s HU/t minimum, %s HU/t max)\n +Simulation.HeatOutputsBeforeBreak=Total output before first component broken: %s HU (%s HU/t average, %s HU/t minimum, %s HU/t max)\n +Simulation.HeatOutputsBeforeDepleted=Total output before first fuel rod depleted: %s HU (%s HU/t average, %s HU/t minimum, %s HU/t max)\n +Simulation.HullCooling=Hull cooling: %,.2f average of %,.0f possible.\n +Simulation.HullHeating=Hull heating: %,.2f average.\n +Simulation.InactiveTime=Reactor was inactive for a total of %,d seconds%s.\n +Simulation.InactiveTimeRange=\u0020(%,d to %,d seconds at a time) +Simulation.InactiveTimeSingle=\u0020(%,d seconds at a time) +Simulation.LapisUsed=Used %d Lapis Lazuli Blocks.\n +Simulation.MaxHeatGenerated=Max heat generated (internally, by fuel rods): %,.0f\n +Simulation.NoCooldown=No cooldown needed.\n +Simulation.NoFuelRods=No fuel rods found! Simulating a pulsed cycle makes no sense! +Simulation.ReactorCooldownTime=Reactor took %,d seconds to cool down.\n +Simulation.ReactorHeatBuildup=Reactor heat buildup per second (while all components are intact):%,.0f minimum, %,.0f maximum.\n +Simulation.ReactorMaxTemp=Reactor maximum temperature: %,.0f\n +Simulation.ReactorMaxTempBeforeDepleted=Reactor maximum temperature (before first fuel rod depleted): %,.0f\n +Simulation.ReactorMinTemp=Reactor minimum temperature: %,.0f\n +Simulation.ReactorMinTempBeforeDepleted=Reactor minimum temperature (before first fuel rod depleted): %,.0f\n +Simulation.ReactorOverheatedTime=Reactor overheated at %,d seconds.\n +Simulation.ReactorRemainingHeat=Reactor remained at %,.0f heat after main simulation finished.\n +Simulation.ReactorResidualHeat=Reactor remained at %,.0f heat even after cool down period of %,d seconds.\n +Simulation.RedstoneUsed=Used %d Blocks of Redstone.\n +Simulation.Started=Simulation started.\n +Simulation.TimeToBelow50=Reactor will dip below 50%% heat for the first time (after being above it) at %d seconds.\n +Simulation.TimeToBurn=Reactor will reach "Burn" temperature at %d seconds.\n +Simulation.TimeToEvaporate=Reactor will reach "Evaporate" temperature at %d seconds.\n +Simulation.TimeToHurt=Reactor will reach "Hurt" temperature at %d seconds.\n +Simulation.TimeToLava=Reactor will reach "Lava" temperature at %d seconds.\n +# Note: The "e" is deliberately dropped from "Explode" in the key name so that it will sort after the others. +Simulation.TimeToXplode=Reactor will explode at %d seconds.\n +Simulation.TimeWithoutExploding=\nReactor ran for %,d seconds without exploding.\n +Simulation.TotalCellCooling=Total Cell Cooling (peak usages): %,.2f\n +Simulation.TotalCondensatorCooling=Total Condensator Cooling (peak usages): %,.2f\n +Simulation.TotalCooldownTime=Other components took %,d seconds to cool down (as much as they would).\n +Simulation.TotalVentCooling=Total Vent Cooling (peak usages, theoretical maximum): %,.2f of %,.2f\n +Simulation.VentCooling=Vent cooling: %,.2f average of %,.0f possible.\n + +UI.AdvancedTab=Advanced +#Needs to be heavily abbreviated to fit on the button. +UI.AutomateButton=a +UI.AutomateButtonFont=Arial 10 +UI.AutomatedReactor=Automated Reactor +UI.AutomatedReactorTooltip=Turn on to allow automating of adding/removing of components. +UI.AutomationTooltip=Click to define automation rules for this component. +UI.CancelButton=Cancel +UI.ChosenComponentRowCol=%s at row %d column %d +UI.ClearGridButton=Clear Grid +UI.CodeLabel=Code: +UI.ComparisonTab=Comparison +UI.ComponentAutomationTab=Component Automation +#Needs to be heavily abbreviated to fit on the button. +UI.ComponentInfoButton=i +UI.ComponentInfoButtonFont=Arial 10 +UI.ComponentInfoButtonTooltip=Click for information about this component +UI.ComponentInfoDefault=Please run a simulation and select a component in the reactor grid above to see its details. +UI.ComponentInfoLastSimRowCol=%s at row %d column %d\n%s +UI.ComponentListTab=Component List +UI.ComponentPlacingDefault=Placing Component: None +UI.ComponentPlacingSpecific=Placing Component: %s +UI.ComponentTab=Component +UI.CopyCodeButton=Copy Code +UI.CopyComparisonData=Copy Comparison Data +UI.CSVBrowseButton=Browse +UI.CSVFileDefault=No File Selected +UI.CSVHelp=Warnings:
  1. Simulation will likely run much slower with CSV Output enabled, especially if the chosen file is on a mechanical hard drive.
  2. User is responsible for making sure target drive has enough space for the CSV file.
  3. Additional simulations will overwrite the CSV file unless the target is manually changed.
+UI.CSVTab=CSV +UI.EnableGT508Components=Enable GT 5.08 Components +UI.EnableGT509Components=Enable GT 5.09 Components +UI.ExpandAdvancedAlloy=Expand Advanced Alloy into constituent materials (invalid when using GregTech) +UI.GregTechVersion=GregTech Version: +UI.GregTechVersionNone=None +UI.GTReactorBehavior=GT 5.09 = (2x base EU). GTNH = (10x base EU, Naq Rods->not-MOX-like). Setting always applies to -only fuel rods regardless. +UI.InitialHeatDisplay=\u0020(initial heat: %,d) +UI.InitialReactorHeat=Initial Reactor Heat: +UI.InitialReactorHeatTooltip=Use this to set a heat value for testing MOX-like reactors. +UI.LockInTabCode=Lock in-tab code +UI.MainTitle=IC2 Experimental Reactor Planner +UI.MaterialDecimalFormat=#,##0.## +UI.MaterialsTab=Materials +UI.MaxHeatDefault=/10,000 +UI.MaxHeatSpecific=/%,.0f +UI.MaxSimulationTicks=Maximum time to simulate: +UI.MaxSimulationTicksTooltip=Forces simulation to stop after simulating this much time, even if reactor hasn't exploded or ceased outputting HU or EU. +UI.MinecraftVersion=Minecraft Version: +UI.NoComponentLastSimRowCol=No component at row %d column %d during last simulation. +UI.NoComponentRowCol=No component at row %d column %d. +UI.NoSimulationRun=No simulation run yet. +UI.OnlyShowDiffData=Only show data that is significantly different +UI.PasteCodeButton=Paste Code +UI.PulseConfigurationTab=Pulse Configuration +UI.PulsedReactor=Pulsed Reactor +UI.RemoveAddonComponentsTitle=Add-on Components Found +UI.RemoveGT508ComponentsText=GT 5.08 components found in current design. Remove them? +UI.RemoveGT509ComponentsText=GT 5.09 components found in current design. Remove them? +UI.ResetPulseConfig=Reset Pulse Configuration +UI.ShowComponentDetailButtons=Show Component Detail Buttons +UI.ShowComponentPreconfigControls=Show Component Pre-configuration Controls +UI.ShowOldStyleReactorCode=Show old-style (pre-2.3.1) reactor code +UI.SimulateButton=Simulate +UI.SimulationTab=Simulation +UI.SimulationTypeAutomation=Pulsed Automation +UI.SimulationTypePulsed=Pulsed Cycle +UI.SimulationTypeSimple=Simple Cycle +UI.TemperatureEffectsDefault=Burn: 4,000 Evaporate: 5,000 Hurt: 7,000 Lava: 8,500 Explode: 10,000 +UI.TemperatureEffectsSpecific=Burn: %,d Evaporate: %,d Hurt: %,d Lava: %,d Explode: %,d +UI.TexturePackBrowseButton=Browse +UI.TexturePackClearButton=Clear +UI.TexturePackDefault=Texture Pack: no file selected +UI.TexturePackHelp=(restart planner to see new textures) +UI.TexturePackSpecific=Texture Pack: %s +UI.UseGTRecipes=Use GregTech recipes for component materials (where applicable and unambiguous) +UI.UseUfcForCoolantCells=Use Universal Fluid Cells for coolant (incompatible with GregTech recipes option) +UI.VersionNumber=Version %s + +Warning.DepletedIsotope=Obsolete comp