Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@
*/

dependencies {
embed2 'org.mariuszgromada.math:MathParser.org-mXparser:6.1.0'
embed2('org.joml:joml:1.10.8') { transitive = false }
embedSources("org.joml:joml:1.10.8:sources") { transitive = false }

compileOnly("org.projectlombok:lombok:1.18.42")
annotationProcessor("org.projectlombok:lombok:1.18.42")
testCompileOnly("org.projectlombok:lombok:1.18.42")
testAnnotationProcessor("org.projectlombok:lombok:1.18.42")

compileOnlyApi rfg.deobf("curse.maven:inventory-bogosorter-632327:7403680-sources-7403683")
if (project.debug_bogo.toBoolean()) {
runtimeOnly rfg.deobf("curse.maven:inventory-bogosorter-632327:7403680-sources-7403683")
Expand Down
6 changes: 0 additions & 6 deletions src/main/java/com/cleanroommc/modularui/ModularUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
import org.mariuszgromada.math.mxparser.License;

import java.util.function.Predicate;

Expand Down Expand Up @@ -40,11 +39,6 @@ public class ModularUI {
@Mod.Instance
public static ModularUI INSTANCE;

static {
// confirm mXparser license
License.iConfirmNonCommercialUse("CleanroomMC");
}

@Mod.EventHandler
public void preInit(FMLPreInitializationEvent event) {
proxy.preInit(event);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ default void drawAtZeroPadded(GuiContext context, Area area, WidgetTheme widgetT
draw(context, area.getPadding().getLeft(), area.getPadding().getTop(), area.paddedWidth(), area.paddedHeight(), widgetTheme);
}


/**
* @return if theme color can be applied on this drawable
*/
Expand Down
51 changes: 25 additions & 26 deletions src/main/java/com/cleanroommc/modularui/utils/MathUtils.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
package com.cleanroommc.modularui.utils;

import com.cleanroommc.modularui.utils.math.PostfixPercentOperator;

import net.minecraft.util.math.MathHelper;

import org.mariuszgromada.math.mxparser.Constant;
import org.mariuszgromada.math.mxparser.Expression;
import com.ezylang.evalex.BaseException;
import com.ezylang.evalex.Expression;
import com.ezylang.evalex.config.ExpressionConfiguration;
import com.ezylang.evalex.data.EvaluationValue;
import org.apache.commons.lang3.tuple.Pair;

import java.math.BigDecimal;

public class MathUtils {

Expand All @@ -12,23 +19,12 @@ public class MathUtils {
public static final float PI_HALF = PI / 2f;
public static final float PI_QUART = PI / 4f;

// SI prefixes
public static final Constant k = new Constant("k", 1e3);
public static final Constant M = new Constant("M", 1e6);
public static final Constant G = new Constant("G", 1e9);
public static final Constant T = new Constant("T", 1e12);
public static final Constant P = new Constant("P", 1e15);
public static final Constant E = new Constant("E", 1e18);
public static final Constant Z = new Constant("Z", 1e21);
public static final Constant Y = new Constant("Y", 1e24);
public static final Constant m = new Constant("m", 1e-3);
public static final Constant u = new Constant("u", 1e-6);
public static final Constant n = new Constant("n", 1e-9);
public static final Constant p = new Constant("p", 1e-12);
public static final Constant f = new Constant("f", 1e-15);
public static final Constant a = new Constant("a", 1e-18);
public static final Constant z = new Constant("z", 1e-21);
public static final Constant y = new Constant("y", 1e-24);
public static final ExpressionConfiguration MATH_CFG = ExpressionConfiguration.builder()
.arraysAllowed(false)
.structuresAllowed(false)
.stripTrailingZeros(true)
.build()
.withAdditionalOperators(Pair.of("%", new PostfixPercentOperator()));

public static ParseResult parseExpression(String expression) {
return parseExpression(expression, Double.NaN, false);
Expand All @@ -43,16 +39,19 @@ public static ParseResult parseExpression(String expression, double defaultValue
}

public static ParseResult parseExpression(String expression, double defaultValue, boolean useSiPrefixes) {
if (expression == null || expression.isEmpty()) return ParseResult.success(defaultValue);
Expression e = new Expression(expression);
if (expression == null || expression.isEmpty()) {
return ParseResult.success(EvaluationValue.numberValue(new BigDecimal(defaultValue)));
}

Expression e = new Expression(expression, MATH_CFG);
if (useSiPrefixes) {
e.addConstants(k, M, G, T, P, E, Z, Y, m, u, n, p, f, a, z, y);
SIPrefix.addAllToExpression(e);
}
double result = e.calculate();
if (Double.isNaN(result)) {
return ParseResult.failure(defaultValue, e.getErrorMessage());
try {
return ParseResult.success(e.evaluate());
} catch (BaseException exception) {
return ParseResult.failure(exception);
}
return ParseResult.success(result);
}

public static int clamp(int v, int min, int max) {
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/com/cleanroommc/modularui/utils/NumberFormat.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.cleanroommc.modularui.utils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
Expand All @@ -10,6 +11,8 @@
*/
public class NumberFormat {

public static final BigDecimal TEN_THOUSAND = new BigDecimal(10_000);

public static final Params DEFAULT = paramsBuilder()
.roundingMode(RoundingMode.HALF_UP)
.maxLength(4)
Expand Down Expand Up @@ -205,6 +208,32 @@ public static SIPrefix findBestPrefix(double number) {
return prefix;
}

public static SIPrefix findBestPrefix(BigDecimal number) {
if (number.compareTo(BigDecimal.ONE) >= 0 && number.compareTo(TEN_THOUSAND) < 0) return SIPrefix.One;
SIPrefix[] high = SIPrefix.HIGH;
SIPrefix[] low = SIPrefix.LOW;
int n = high.length - 1;
SIPrefix prefix;
if (number.compareTo(TEN_THOUSAND) >= 0) {
int index;
for (index = 0; index < n; index++) {
if (number.compareTo(high[index + 1].bigFactor) < 0) {
break;
}
}
prefix = high[index];
} else {
int index;
for (index = 0; index < n; index++) {
if (number.compareTo(low[index].bigFactor) >= 0) {
break;
}
}
prefix = low[index];
}
return prefix;
}

private static String formatInternal(double number, int maxLength, Params params) {
SIPrefix prefix = findBestPrefix(number);
return formatToString(number * prefix.oneOverFactor, prefix.symbol, maxLength, params);
Expand Down
29 changes: 19 additions & 10 deletions src/main/java/com/cleanroommc/modularui/utils/ParseResult.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
package com.cleanroommc.modularui.utils;

import com.ezylang.evalex.BaseException;
import com.ezylang.evalex.data.EvaluationValue;
import org.jetbrains.annotations.NotNull;

public class ParseResult {

private final double result;
private final String error;
private final EvaluationValue result;
private final BaseException error;

public static ParseResult success(double result) {
public static ParseResult success(EvaluationValue result) {
return new ParseResult(result, null);
}

public static ParseResult failure(@NotNull String error) {
return failure(Double.NaN, error);
public static ParseResult failure(@NotNull BaseException error) {
return failure(null, error);
}

public static ParseResult failure(double value, @NotNull String error) {
public static ParseResult failure(EvaluationValue value, @NotNull BaseException error) {
return new ParseResult(value, error);
}

private ParseResult(double result, String error) {
private ParseResult(EvaluationValue result, BaseException error) {
this.result = result;
this.error = error;
}
Expand All @@ -33,14 +35,21 @@ public boolean isFailure() {
}

public boolean hasValue() {
return !Double.isNaN(this.result);
return this.result != null;
}

public double getResult() {
public EvaluationValue getResult() {
return result;
}

public String getError() {
public BaseException getError() {
return error;
}

public String getErrorMessage() {
return isFailure() ?
String.format("%s for Token %s at %d:%d",
this.error.getMessage(), this.error.getTokenString(),
this.error.getStartPosition(), this.error.getEndPosition()) : null;
}
}
22 changes: 20 additions & 2 deletions src/main/java/com/cleanroommc/modularui/utils/SIPrefix.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package com.cleanroommc.modularui.utils;

import com.ezylang.evalex.Expression;

import java.math.BigDecimal;

public enum SIPrefix {

Quetta('Q', 30),
Ronna('R', 27),
Yotta('Y', 24),
Zetta('Z', 21),
Exa('E', 18),
Exa('X', 18), // this should actually be E, but this clashes with euler's number e = 2.71...
Peta('P', 15),
Tera('T', 12),
Giga('G', 9),
Expand All @@ -24,23 +28,31 @@ public enum SIPrefix {
Ronto('r', -27),
Quecto('q', -30);


public final char symbol;
public final String stringSymbol;
public final double factor;
public final double oneOverFactor;
public final BigDecimal bigFactor;
public final BigDecimal bigOneOverFactor;

SIPrefix(char symbol, int powerOfTen) {
this.symbol = symbol;
this.stringSymbol = symbol != Character.MIN_VALUE ? Character.toString(symbol) : "";
this.factor = Math.pow(10, powerOfTen);
this.oneOverFactor = 1 / this.factor;
this.bigFactor = new BigDecimal(this.factor);
this.bigOneOverFactor = new BigDecimal(this.oneOverFactor);
}

public boolean isOne() {
return this == One;
}

public void addToExpression(Expression e) {
e.with(String.valueOf(this.symbol), this.factor);
}

public static final SIPrefix[] VALUES = values();
public static final SIPrefix[] HIGH = new SIPrefix[values().length / 2];
public static final SIPrefix[] LOW = new SIPrefix[values().length / 2];

Expand All @@ -51,4 +63,10 @@ public boolean isOne() {
LOW[i] = values[HIGH.length + 1 + i];
}
}

public static void addAllToExpression(Expression e) {
for (SIPrefix siPrefix : VALUES) {
siPrefix.addToExpression(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.cleanroommc.modularui.utils.math;

import com.ezylang.evalex.EvaluationException;
import com.ezylang.evalex.Expression;
import com.ezylang.evalex.data.EvaluationValue;
import com.ezylang.evalex.operators.AbstractOperator;
import com.ezylang.evalex.operators.OperatorIfc;
import com.ezylang.evalex.operators.PostfixOperator;
import com.ezylang.evalex.parser.Token;

import java.math.BigDecimal;

@PostfixOperator(precedence = OperatorIfc.OPERATOR_PRECEDENCE_MULTIPLICATIVE - 1)
public class PostfixPercentOperator extends AbstractOperator {

public static final BigDecimal HUNDRED = new BigDecimal(100);

@Override
public EvaluationValue evaluate(Expression expression, Token operatorToken, EvaluationValue... operands) throws EvaluationException {
EvaluationValue operand = operands[0];

if (operand.isNumberValue()) {
return expression.convertValue(
operand.getNumberValue().divide(HUNDRED, expression.getConfiguration().getMathContext()));
} else {
throw EvaluationException.ofUnsupportedDataTypeInOperation(operatorToken);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ public class TextFieldWidget extends BaseTextFieldWidget<TextFieldWidget> {

public double parse(String num) {
ParseResult result = MathUtils.parseExpression(num, this.defaultNumber, true);
double value = result.getResult();
if (result.isFailure()) {
this.mathFailMessage = result.getError();
this.mathFailMessage = result.getErrorMessage();
ModularUI.LOGGER.error("Math expression error in {}: {}", this, this.mathFailMessage);
return defaultNumber;
}
return value;
return result.getResult().getNumberValue().doubleValue();
}

public IStringValue<?> createMathFailMessageValue() {
Expand Down
42 changes: 42 additions & 0 deletions src/main/java/com/ezylang/evalex/BaseException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
Copyright 2012-2022 Udo Klimaschewski

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package com.ezylang.evalex;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;

/**
* Base exception class used in EvalEx.
*/
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
@ToString
@Getter
public class BaseException extends Exception {

@EqualsAndHashCode.Include private final int startPosition;
@EqualsAndHashCode.Include private final int endPosition;
@EqualsAndHashCode.Include private final String tokenString;
@EqualsAndHashCode.Include private final String message;

public BaseException(int startPosition, int endPosition, String tokenString, String message) {
super(message);
this.startPosition = startPosition;
this.endPosition = endPosition;
this.tokenString = tokenString;
this.message = super.getMessage();
}
}
Loading