diff --git a/src/main/java/appeng/client/gui/implementations/GuiCraftAmount.java b/src/main/java/appeng/client/gui/implementations/GuiCraftAmount.java index b1bf2661d00..5c90a77294d 100644 --- a/src/main/java/appeng/client/gui/implementations/GuiCraftAmount.java +++ b/src/main/java/appeng/client/gui/implementations/GuiCraftAmount.java @@ -24,7 +24,6 @@ import appeng.api.definitions.IParts; import appeng.api.storage.ITerminalHost; import appeng.client.gui.AEBaseGui; -import appeng.client.gui.widgets.GuiNumberBox; import appeng.client.gui.widgets.GuiTabButton; import appeng.container.AEBaseContainer; import appeng.container.implementations.ContainerCraftAmount; @@ -40,14 +39,17 @@ import appeng.parts.reporting.PartPatternTerminal; import appeng.parts.reporting.PartPatternTerminalEx; import appeng.parts.reporting.PartTerminal; +import appeng.util.calculators.ArithHelper; +import appeng.util.calculators.Calculator; import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiTextField; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.item.ItemStack; public class GuiCraftAmount extends AEBaseGui { - private GuiNumberBox amountToCraft; + private GuiTextField amountToCraft; private GuiTabButton originalGuiBtn; private GuiButton next; @@ -70,6 +72,7 @@ public GuiCraftAmount( final InventoryPlayer inventoryPlayer, final ITerminalHos } @Override + @SuppressWarnings( "unchecked" ) public void initGui() { super.initGui(); @@ -147,7 +150,7 @@ public void initGui() this.buttonList.add( this.originalGuiBtn = new GuiTabButton( this.guiLeft + 154, this.guiTop, myIcon, myIcon.getDisplayName(), itemRender ) ); } - this.amountToCraft = new GuiNumberBox( this.fontRendererObj, this.guiLeft + 62, this.guiTop + 57, 59, this.fontRendererObj.FONT_HEIGHT, Integer.class ); + this.amountToCraft = new GuiTextField( this.fontRendererObj, this.guiLeft + 62, this.guiTop + 57, 59, this.fontRendererObj.FONT_HEIGHT); this.amountToCraft.setEnableBackgroundDrawing( false ); this.amountToCraft.setMaxStringLength( 16 ); this.amountToCraft.setTextColor( 0xFFFFFF ); @@ -173,8 +176,19 @@ public void drawBG( final int offsetX, final int offsetY, final int mouseX, fina try { - Long.parseLong( this.amountToCraft.getText() ); - this.next.enabled = this.amountToCraft.getText().length() > 0; + String out = this.amountToCraft.getText(); + + double resultD = Calculator.conversion( out ); + int resultI; + + if( resultD <= 0 || Double.isNaN( resultD ) ) { + resultI = 0; + } + else { + resultI = (int) ArithHelper.round(resultD, 0); + } + + this.next.enabled = resultI > 0; } catch( final NumberFormatException e ) { @@ -193,44 +207,8 @@ protected void keyTyped( final char character, final int key ) { this.actionPerformed( this.next ); } - if( ( key == 211 || key == 205 || key == 203 || key == 14 || character == '-' || Character.isDigit( character ) ) && this.amountToCraft.textboxKeyTyped( character, key ) ) - { - try - { - String out = this.amountToCraft.getText(); - - boolean fixed = false; - while( out.startsWith( "0" ) && out.length() > 1 ) - { - out = out.substring( 1 ); - fixed = true; - } - - if( fixed ) - { - this.amountToCraft.setText( out ); - } - - if( out.isEmpty() ) - { - out = "0"; - } - - final long result = Long.parseLong( out ); - if( result < 0 ) - { - this.amountToCraft.setText( "1" ); - } - } - catch( final NumberFormatException e ) - { - // :P - } - } - else - { - super.keyTyped( character, key ); - } + this.amountToCraft.textboxKeyTyped( character, key ); + super.keyTyped( character, key ); } } @@ -247,9 +225,19 @@ protected void actionPerformed( final GuiButton btn ) NetworkHandler.instance.sendToServer( new PacketSwitchGuis( this.originalGui ) ); } - if( btn == this.next ) + if( btn == this.next && btn.enabled ) { - NetworkHandler.instance.sendToServer( new PacketCraftRequest( Integer.parseInt( this.amountToCraft.getText() ), isShiftKeyDown() ) ); + double resultD = Calculator.conversion( this.amountToCraft.getText() ); + int resultI; + + if( resultD <= 0 || Double.isNaN( resultD ) ) { + resultI = 1; + } + else { + resultI = (int) ArithHelper.round(resultD, 0); + } + + NetworkHandler.instance.sendToServer( new PacketCraftRequest( resultI, isShiftKeyDown() ) ); } } catch( final NumberFormatException e ) @@ -273,38 +261,23 @@ private void addQty( final int i ) { String out = this.amountToCraft.getText(); - boolean fixed = false; - while( out.startsWith( "0" ) && out.length() > 1 ) - { - out = out.substring( 1 ); - fixed = true; - } + double resultD = Calculator.conversion( out ); + int resultI; - if( fixed ) - { - this.amountToCraft.setText( out ); - } - - if( out.isEmpty() ) - { - out = "0"; - } + if( resultD <= 0 || Double.isNaN( resultD ) ) { + resultI = 1; + } + else { + resultI = (int) ArithHelper.round(resultD, 0); + } - long result = Integer.parseInt( out ); + resultI += i; + if( resultI < 1 ) { + resultI = 1; + } - if( result == 1 && i > 1 ) - { - result = 0; - } - - result += i; - if( result < 1 ) - { - result = 1; - } + out = Integer.toString( resultI ); - out = Long.toString( result ); - Integer.parseInt( out ); this.amountToCraft.setText( out ); } catch( final NumberFormatException e ) diff --git a/src/main/java/appeng/util/calculators/ArithHelper.java b/src/main/java/appeng/util/calculators/ArithHelper.java new file mode 100644 index 00000000000..b67da33f911 --- /dev/null +++ b/src/main/java/appeng/util/calculators/ArithHelper.java @@ -0,0 +1,91 @@ +package appeng.util.calculators; + +public class ArithHelper { + + private static final int DEF_DIV_SCALE = 16; + + private ArithHelper() { + } + + /** + * addition + * + * @param v1 p1 + * @param v2 p2 + * @return sum + */ + public static String add(String v1, String v2) { + java.math.BigDecimal b1 = new java.math.BigDecimal(v1); + java.math.BigDecimal b2 = new java.math.BigDecimal(v2); + return String.valueOf(b1.add(b2)); + } + + /** + * subtraction + * + * @param v1 p1 + * @param v2 p2 + * @return sub + */ + public static String sub(String v1, String v2) { + java.math.BigDecimal b1 = new java.math.BigDecimal(v1); + java.math.BigDecimal b2 = new java.math.BigDecimal(v2); + return String.valueOf(b1.subtract(b2)); + } + + /** + * multiplication + * + * @param v1 + * p1 + * @param v2 + * p2 + * @return mul + */ + public static String mul(String v1, String v2) { + java.math.BigDecimal b1 = new java.math.BigDecimal(v1); + java.math.BigDecimal b2 = new java.math.BigDecimal(v2); + return String.valueOf(b1.multiply(b2)); + } + + /** + * division. e = 10^-10 + * + * @param v1 + * p1 + * @param v2 + * p2 + * @return div + */ + public static String div(String v1, String v2) { + java.math.BigDecimal b1 = new java.math.BigDecimal(v1); + java.math.BigDecimal b2 = new java.math.BigDecimal(v2); + return String.valueOf(b1.divide(b2, DEF_DIV_SCALE, java.math.BigDecimal.ROUND_HALF_UP)); + } + + /** + * rounding + * + * @param v p + * @param scale scale + * @return result + */ + public static double round(double v, int scale) { + if (scale < 0) { + throw new IllegalArgumentException("The scale must be a positive integer or zero"); + } + java.math.BigDecimal b = new java.math.BigDecimal(Double.toString(v)); + java.math.BigDecimal one = new java.math.BigDecimal("1"); + return b.divide(one, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue(); + } + + public static String round(String v, int scale) { + if (scale < 0) { + throw new IllegalArgumentException("The scale must be a positive integer or zero"); + } + java.math.BigDecimal b = new java.math.BigDecimal(v); + java.math.BigDecimal one = new java.math.BigDecimal("1"); + return String.valueOf(b.divide(one, scale, java.math.BigDecimal.ROUND_HALF_UP)); + } + +} diff --git a/src/main/java/appeng/util/calculators/Calculator.java b/src/main/java/appeng/util/calculators/Calculator.java new file mode 100644 index 00000000000..5ed29fef29f --- /dev/null +++ b/src/main/java/appeng/util/calculators/Calculator.java @@ -0,0 +1,191 @@ +package appeng.util.calculators; + +import java.math.BigDecimal; +import java.util.Collections; +import java.util.Stack; + +public class Calculator { + private final Stack postfixStack = new Stack<>(); + private final Stack opStack = new Stack<>(); + private final int[] operatPriority = new int[] { 0, 3, 2, 1, -1, 1, 0, 2 }; + + public static double conversion(String expression) { + double result = 0; + + if( expression == null ) + return Double.NaN; + + expression = expression.replace( " ", "" ); + + Calculator cal = new Calculator(); + if( expression.length() == 1 && Character.isDigit( expression.charAt( 0 ) ) ) { + return expression.charAt( 0 ) - '0'; + } + try { + expression = transform(expression); + result = cal.calculate(expression); + } catch (Exception e) { + return Double.NaN; + } + // return new String().valueOf(result); + return result; + } + + /** + * replace '-' with '~' + * + * @param expression + * e.g.-2+-1*(-3E-2)-(-1) -> ~2+~1*(~3E~2)-(~1) + * @return + */ + private static String transform(String expression) { + char[] arr = expression.toCharArray(); + for (int i = 0; i < arr.length; i++) { + if (arr[i] == '-') { + if (i == 0) { + arr[i] = '~'; + } else { + char c = arr[i - 1]; + if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == 'E' || c == 'e') { + arr[i] = '~'; + } + } + } + } + if(arr[0]=='~'||arr[1]=='(') { + arr[0]='-'; + return "0" + new String(arr); + } else { + return new String(arr); + } + } + + /** + * Do calculation + * + * @param expression + * e.g.5+12*(3+5)/7 + * @return + */ + public double calculate(String expression) { + Stack resultStack = new Stack<>(); + prepare(expression); + Collections.reverse(postfixStack); + String firstValue, secondValue, currentValue; + while (!postfixStack.isEmpty()) { + currentValue = postfixStack.pop(); + if (!isOperator(currentValue.charAt(0))) { + currentValue = currentValue.replace("~", "-"); + resultStack.push(currentValue); + } else { + secondValue = resultStack.pop(); + firstValue = resultStack.pop(); + + firstValue = firstValue.replace("~", "-"); + secondValue = secondValue.replace("~", "-"); + + String tempResult = calculate(firstValue, secondValue, currentValue.charAt(0)); + resultStack.push(String.valueOf(tempResult)); + } + } + return Double.parseDouble(resultStack.pop()); + } + + /** + * Turn expression into postfix stack + * + * @param expression + */ + private void prepare(String expression) { + opStack.push(','); + char[] arr = expression.toCharArray(); + int currentIndex = 0; + int count = 0; + char currentOp, peekOp; + for (int i = 0; i < arr.length; i++) { + currentOp = arr[i]; + if (isOperator(currentOp)) { + if (count > 0) { + postfixStack.push(new String(arr, currentIndex, count)); + } + peekOp = opStack.peek(); + if (currentOp == ')') { + while (opStack.peek() != '(') { + postfixStack.push(String.valueOf(opStack.pop())); + } + opStack.pop(); + } else { + while (currentOp != '(' && peekOp != ',' && compare(currentOp, peekOp)) { + postfixStack.push(String.valueOf(opStack.pop())); + peekOp = opStack.peek(); + } + opStack.push(currentOp); + } + count = 0; + currentIndex = i + 1; + } else { + count++; + } + } + if (count > 1 || (count == 1 && !isOperator(arr[currentIndex]))) { + postfixStack.push(new String(arr, currentIndex, count)); + } + + while (opStack.peek() != ',') { + postfixStack.push(String.valueOf(opStack.pop())); + } + } + + /** + * Check is it a valid operator + * + * @param c + * @return + */ + public static boolean isOperator(char c) { + return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')'; + } + + /** + * priority + * + * @param cur + * @param peek + * @return + */ + public boolean compare(char cur, char peek) { + boolean result = false; + if (operatPriority[(peek) - 40] >= operatPriority[(cur) - 40]) { + result = true; + } + return result; + } + + /** + * Do calculator with operater + * + * @param firstValue + * @param secondValue + * @param currentOp + * @return + */ + private String calculate(String firstValue, String secondValue, char currentOp) { + String result = ""; + switch (currentOp) { + case '+': + result = ArithHelper.add(firstValue, secondValue); + break; + case '-': + result = ArithHelper.sub(firstValue, secondValue); + break; + case '*': + result = ArithHelper.mul(firstValue, secondValue); + break; + case '/': + result = ArithHelper.div(firstValue, secondValue); + break; + } + return result; + } + +}