diff --git a/src/main/java/nova/core/util/math/MathUtil.java b/src/main/java/nova/core/util/math/MathUtil.java
index aab57df04..d6f6925e5 100755
--- a/src/main/java/nova/core/util/math/MathUtil.java
+++ b/src/main/java/nova/core/util/math/MathUtil.java
@@ -108,6 +108,84 @@ public static int max(int... numbers) {
return max;
}
+ /**
+ * Returns the smaller number of a and b.
+ * @param a value.
+ * @param b value.
+ * @return min
+ */
+ public static long min(long a, long b) {
+ return a < b ? a : b;
+ }
+
+ /**
+ * Returns the smaller number of a, b and c.
+ * @param a value.
+ * @param b value.
+ * @param c value.
+ * @return min
+ */
+ public static long min(long a, long b, long c) {
+ return min(min(a, b), c);
+ }
+
+ /**
+ * Returns the smallest number contained in the provided array.
+ * @param numbers Array of numbers
+ * @return min
+ */
+ public static long min(long... numbers) {
+ if (numbers.length < 1) {
+ throw new IllegalArgumentException();
+ }
+ long min = numbers[0];
+ for (int i = 1; i < numbers.length; i++) {
+ if (numbers[i] < min) {
+ min = numbers[i];
+ }
+ }
+ return min;
+ }
+
+ /**
+ * Returns the bigger number of a and b.
+ * @param a value.
+ * @param b value.
+ * @return max
+ */
+ public static long max(long a, long b) {
+ return a > b ? a : b;
+ }
+
+ /**
+ * Returns the bigger number of a, b and c.
+ * @param a value.
+ * @param b value.
+ * @param c value.
+ * @return max
+ */
+ public static long max(long a, long b, long c) {
+ return max(max(a, b), c);
+ }
+
+ /**
+ * Returns the biggest number contained in the provided array.
+ * @param numbers Array of numbers
+ * @return max
+ */
+ public static long max(long... numbers) {
+ if (numbers.length < 1) {
+ throw new IllegalArgumentException();
+ }
+ long max = numbers[0];
+ for (int i = 1; i < numbers.length; i++) {
+ if (numbers[i] > max) {
+ max = numbers[i];
+ }
+ }
+ return max;
+ }
+
/**
* Returns the smaller number of a and b.
* @param a value.
@@ -263,7 +341,7 @@ public static float max(float... numbers) {
}
return max;
}
-
+
/**
* Clamps the given number so that {@code min <= a <= max}
* @param a value.
@@ -275,6 +353,17 @@ public static int clamp(int a, int min, int max) {
return min(max(a, min), max);
}
+ /**
+ * Clamps the given number so that {@code min <= a <= max}
+ * @param a value.
+ * @param min lower limit
+ * @param max upper limit
+ * @return {@code min <= a <= max}
+ */
+ public static long clamp(long a, long min, long max) {
+ return min(max(a, min), max);
+ }
+
/**
* Clamps the given number so that {@code min <= a <= max}
* @param a value.
@@ -297,23 +386,57 @@ public static double lerp(double a, double b, double f) {
return a + f * (b - a);
}
+ /**
+ * Linear interpolates isBetween point a and point b
+ * @param a value.
+ * @param b value.
+ * @param f A percentage value isBetween 0 to 1
+ * @return The interpolated value
+ */
public static float lerp(float a, float b, float f) {
return a + f * (b - a);
}
+ /**
+ * Linear interpolates isBetween point a and point b
+ * @param a value.
+ * @param b value.
+ * @param f A percentage value isBetween 0 to 1
+ * @return The interpolated value
+ */
public static Vector3D lerp(Vector3D a, Vector3D b, float f) {
return a.add((b.subtract(a)).scalarMultiply(f));
}
/**
- * Clamps a value isBetween -bounds to +bounds
- * @return A value capped isBetween two bounds.
+ * Clamps a value between -bounds to +bounds
+ * @return A value capped between two bounds.
+ */
+ public static int absClamp(int value, int bounds) {
+ return min(max(value, -bounds), bounds);
+ }
+
+ /**
+ * Clamps a value between -bounds to +bounds
+ * @return A value capped between two bounds.
+ */
+ public static long absClamp(long value, long bounds) {
+ return min(max(value, -bounds), bounds);
+ }
+
+ /**
+ * Clamps a value between -bounds to +bounds
+ * @return A value capped between two bounds.
*/
public static double absClamp(double value, double bounds) {
return min(max(value, -bounds), bounds);
}
- public static float absClamp(int value, int bounds) {
+ /**
+ * Clamps a value between -bounds to +bounds
+ * @return A value capped between two bounds.
+ */
+ public static float absClamp(float value, float bounds) {
return min(max(value, -bounds), bounds);
}
@@ -325,6 +448,10 @@ public static int log(int x, int base) {
return (int) (Math.log(x) / Math.log(base));
}
+ public static long log(long x, long base) {
+ return (long) (Math.log(x) / Math.log(base));
+ }
+
public static double log(double x, double base) {
return Math.log(x) / Math.log(base);
}
@@ -339,4 +466,20 @@ public static boolean isBetween(double a, double x, double b) {
return a <= x && x <= b;
}
+ /**
+ * Rounds a number to a specific number place places
+ *
+ * @param d - the number
+ * @return The rounded number
+ */
+ public static double roundDecimals(double d, int decimalPlaces) {
+ long i = Math.round(d * Math.pow(10, decimalPlaces));
+ return i / Math.pow(10, decimalPlaces);
+ }
+
+ public static String toString(double d, boolean removeTrailingZeroes) {
+ if (removeTrailingZeroes && d % 1 == 0)
+ return Long.toString((long) d);
+ return Double.toString(d);
+ }
}
diff --git a/src/main/java/nova/core/util/unit/Unit.java b/src/main/java/nova/core/util/unit/Unit.java
new file mode 100644
index 000000000..c13624f0e
--- /dev/null
+++ b/src/main/java/nova/core/util/unit/Unit.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2015 NOVA, All rights reserved.
+ * This library is free software, licensed under GNU Lesser General Public License version 3
+ *
+ * This file is part of NOVA.
+ *
+ * NOVA is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * NOVA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with NOVA. If not, see .
+ */
+
+package nova.core.util.unit;
+
+import nova.core.language.LanguageManager;
+import nova.core.language.Translateable;
+import nova.core.util.Identifiable;
+import nova.core.util.registry.Registry;
+
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * @author ExE Boss
+ */
+public final class Unit implements Identifiable, Translateable {
+ private static final Registry REGISTRY = new Registry<>();
+
+ public static final Unit METRE = getOrCreateUnit("nova:metre", "m");
+ public static final Unit LITRE = getOrCreateUnit("nova:litre", "l");
+ public static final Unit GRAM = getOrCreateUnit("nova:gram", "g", UnitPrefix.KILO);
+ // TODO: Define More Units
+
+ public static final Unit CELSIUS = getOrCreateUnit("nova:celsius", "°C");
+ public static final Unit KELVIN = getOrCreateUnit("nova:kelvin", "K");
+ public static final Unit FAHRENHEIT = getOrCreateUnit("nova:fahrenheit", "°F");
+
+ public static final Unit AMPERE = getOrCreateUnit("nova:ampere", "I");
+ public static final Unit AMP_HOUR = getOrCreateUnit("nova:amp_hour", "Ah");
+ public static final Unit VOLTAGE = getOrCreateUnit("nova:voltage", "V");
+ public static final Unit WATT = getOrCreateUnit("nova:watt", "W");
+ public static final Unit WATT_HOUR = getOrCreateUnit("nova:watt_hour", "Wh");
+ public static final Unit RESISTIVITY = getOrCreateUnit("nova:resistivity", "Ω");
+ public static final Unit CONDUCTIVITY = getOrCreateUnit("nova:conductivity", "S");
+ public static final Unit JOULE = getOrCreateUnit("nova:joule", "J");
+ public static final Unit NEWTON_METRE = getOrCreateUnit("nova:newton_metre", "Nm");
+
+ private final String id;
+ private final String unlocalizedName;
+ private final String symbol;
+ private UnitPrefix basePrefix = null;
+
+ private Unit(String id, String symbol) {
+ this(id, id.replace(':', '.'), symbol);
+ }
+
+ private Unit(String id, String unlocalizedName, String symbol) {
+ this.id = id;
+ this.unlocalizedName = unlocalizedName;
+ this.symbol = symbol;
+ }
+
+ private Unit setBasePrefix(UnitPrefix basePrefix) {
+ if (this.basePrefix == null)
+ this.basePrefix = basePrefix;
+ return this;
+ }
+
+ @Override
+ public String getUnlocalizedName() {
+ return "unit." + this.unlocalizedName;
+ }
+
+ @Override
+ public String getLocalizedName() {
+ return LanguageManager.instance().translate(this.getUnlocalizedName() + ".name", this.getReplacements());
+ }
+
+ public String getPluralName() {
+ return LanguageManager.instance().translate(this.getUnlocalizedName() + ".plural", this.getReplacements());
+ }
+
+ public String getSymbol() {
+ return this.symbol;
+ }
+
+ public UnitPrefix getBasePrefix() {
+ return basePrefix == null ? UnitPrefix.BASE : basePrefix;
+ }
+
+ @Override
+ public String getID() {
+ return id;
+ }
+
+ // TODO: Move to Registry
+ public Set getUnitsFromMod(String modId) {
+ return REGISTRY.stream().filter((e) -> {
+ String id = e.getID();
+ if (id.contains(":")) {
+ return id.substring(0, id.lastIndexOf(':')).equals(modId);
+ } else {
+ return modId == null || modId.isEmpty();
+ }
+ }).collect(Collectors.toSet());
+ }
+
+ public Optional getUnit(String id) {
+ return REGISTRY.get(id);
+ }
+
+ public static Unit getOrCreateUnit(String id, String unit) {
+ if (REGISTRY.contains(id)) return REGISTRY.get(id).get();
+ return REGISTRY.register(new Unit(id, unit));
+ }
+
+ public static Unit getOrCreateUnit(String id, String unlocalizedName, String unit) {
+ if (REGISTRY.contains(id)) return REGISTRY.get(id).get();
+ return REGISTRY.register(new Unit(id, unlocalizedName, unit));
+ }
+
+ public static Unit getOrCreateUnit(String id, String unit, UnitPrefix basePrefix) {
+ if (REGISTRY.contains(id)) return REGISTRY.get(id).get();
+ return REGISTRY.register(new Unit(id, unit)).setBasePrefix(basePrefix);
+ }
+
+ public static Unit getOrCreateUnit(String id, String unlocalizedName, String unit, UnitPrefix basePrefix) {
+ if (REGISTRY.contains(id)) return REGISTRY.get(id).get();
+ return REGISTRY.register(new Unit(id, unlocalizedName, unit)).setBasePrefix(basePrefix);
+ }
+}
diff --git a/src/main/java/nova/core/util/unit/UnitConversion.java b/src/main/java/nova/core/util/unit/UnitConversion.java
new file mode 100644
index 000000000..26532e89e
--- /dev/null
+++ b/src/main/java/nova/core/util/unit/UnitConversion.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2017 NOVA, All rights reserved.
+ * This library is free software, licensed under GNU Lesser General Public License version 3
+ *
+ * This file is part of NOVA.
+ *
+ * NOVA is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * NOVA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with NOVA. If not, see .
+ */
+
+package nova.core.util.unit;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * Convert between different units. (Where supported)
+ *
+ * @author ExE Boss
+ */
+public class UnitConversion {
+
+ private static final Map> CONVERSION = new HashMap<>();
+
+ private final Unit unit1, unit2;
+ private final double ratio, reverseRatio;
+ private final double offset;
+ private final UnitConversion reverse;
+
+ private UnitConversion(Unit unit1, Unit unit2, double ratio, double offset) {
+ this.unit1 = unit1;
+ this.unit2 = unit2;
+ this.ratio = ratio;
+ this.reverseRatio = 1/ratio;
+ this.offset = offset;
+ this.reverse = new UnitConversion(unit1, unit2, this.reverseRatio, -offset / ratio, this);
+ }
+ private UnitConversion(Unit unit1, Unit unit2, double ratio, double offset, UnitConversion reverse) {
+ this.unit1 = unit1;
+ this.unit2 = unit2;
+ this.ratio = ratio;
+ this.reverse = reverse;
+ this.offset = offset;
+ this.reverseRatio = this.reverse.ratio;
+ }
+ public double convert(double value) {
+ return (this.reverseRatio == 0 && this.ratio != 0 ? value / ratio : value * this.reverseRatio) + offset;
+ }
+
+ public Unit unit1() {
+ return unit1;
+ }
+ public Unit unit2() {
+ return unit2;
+ }
+ public double ratio() {
+ return ratio;
+ }
+ public UnitConversion reverse() {
+ return reverse;
+ }
+
+ public static Optional getConvertion(Unit unit1, Unit unit2) {
+ Map conv = CONVERSION.get(unit1);
+ if (conv == null) return Optional.empty();
+ return Optional.ofNullable(conv.get(unit2));
+ }
+
+ /**
+ *
+ * @param unit1 The unit to convert from
+ * @param unit2 The unit to convert to
+ * @param ratio unit1/unit2
+ * @return The UnitConversion instance.
+ * @throws IllegalArgumentException If ratio is 0
+ */
+ public static UnitConversion registerConversion(Unit unit1, Unit unit2, double ratio) throws IllegalArgumentException {
+ return registerConversion(unit1, unit2, ratio, 0);
+ }
+
+ /**
+ *
+ * @param unit1 The unit to convert from
+ * @param unit2 The unit to convert to
+ * @param ratio unit1/unit2
+ * @param offset the amount which to add to/subtract from the result of ratio conversion
+ * @return The UnitConversion instance.
+ * @throws IllegalArgumentException If ratio is 0
+ */
+ public static UnitConversion registerConversion(Unit unit1, Unit unit2, double ratio, double offset) throws IllegalArgumentException {
+ if (ratio == 0)
+ throw new IllegalArgumentException("Ratio cannot be 0");
+
+ Map conv1 = CONVERSION.get(unit1);
+ if (conv1 == null) {
+ conv1 = new HashMap<>();
+ CONVERSION.put(unit1, conv1);
+ }
+ if (conv1.containsKey(unit2)) return conv1.get(unit2);
+
+ Map conv2 = CONVERSION.get(unit2);
+ if (conv2 == null) {
+ conv2 = new HashMap<>();
+ CONVERSION.put(unit2, conv2);
+ }
+
+ UnitConversion uc = new UnitConversion(unit1, unit2, ratio, offset);
+
+ conv1.put(unit2, uc);
+ conv2.put(unit1, uc.reverse());
+
+ calculateConversions();
+ return uc;
+ }
+
+ /**
+ * If UnitA can be converted to UnitB
+ * and UnitB can be converted to UnitC,
+ * then UnitA must be convertible to UnitC.
+ */
+ public static void calculateConversions() {
+ // TODO
+ }
+
+ static {
+ registerConversion(Unit.CELSIUS, Unit.KELVIN, 1, 273.15);
+ registerConversion(Unit.CELSIUS, Unit.FAHRENHEIT, 9/5, 32);
+ registerConversion(Unit.KELVIN, Unit.FAHRENHEIT, 9/5, -459.67);
+ }
+}
diff --git a/src/main/java/nova/core/util/unit/UnitDisplay.java b/src/main/java/nova/core/util/unit/UnitDisplay.java
new file mode 100644
index 000000000..1a49579ea
--- /dev/null
+++ b/src/main/java/nova/core/util/unit/UnitDisplay.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2015 NOVA, All rights reserved.
+ * This library is free software, licensed under GNU Lesser General Public License version 3
+ *
+ * This file is part of NOVA.
+ *
+ * NOVA is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * NOVA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with NOVA. If not, see .
+ */
+
+package nova.core.util.unit;
+
+import nova.core.util.math.MathUtil;
+
+import java.util.Objects;
+import java.util.function.DoubleSupplier;
+
+/**
+ * An easy way to display information on electricity for the client.
+ *
+ * @author Calclavia
+ */
+public class UnitDisplay {
+ public final Unit unit;
+ public final DoubleSupplier value;
+ public final boolean useSymbol;
+ public final int decimalPlaces;
+ public final boolean isSimple;
+ public final boolean removeTrailingZeroes;
+
+ public UnitDisplay(Unit unit, DoubleSupplier value, boolean useSymbol, int decimalPlaces, boolean simple, boolean removeTrailingZeroes) {
+ this.unit = Objects.requireNonNull(unit, "unit");
+ this.value = Objects.requireNonNull(value, "value");
+ this.useSymbol = useSymbol;
+ this.decimalPlaces = decimalPlaces;
+ this.isSimple = simple;
+ this.removeTrailingZeroes = removeTrailingZeroes;
+ }
+
+ public UnitDisplay(Unit unit, DoubleSupplier value, boolean useSymbol, int decimalPlaces, boolean simple) {
+ this(unit, value, useSymbol, 2, simple, true);
+ }
+
+ public UnitDisplay(Unit unit, DoubleSupplier value, boolean useSymbol, boolean simple) {
+ this(unit, value, useSymbol, 2, simple);
+ }
+
+ public UnitDisplay(Unit unit, DoubleSupplier value, int decimalPlaces, boolean simple) {
+ this(unit, value, true, decimalPlaces, simple);
+ }
+
+ public UnitDisplay(Unit unit, DoubleSupplier value, boolean useSymbol, int decimalPlaces) {
+ this(unit, value, useSymbol, decimalPlaces, false);
+ }
+
+ public UnitDisplay(Unit unit, DoubleSupplier value, int decimalPlaces) {
+ this(unit, value, true, decimalPlaces, false);
+ }
+
+ public UnitDisplay(Unit unit, DoubleSupplier value, boolean simple) {
+ this(unit, value, true, 2, simple);
+ }
+
+ public UnitDisplay(Unit unit, DoubleSupplier value) {
+ this(unit, value, true, 2, false);
+ }
+
+ public UnitDisplay(Unit unit, double value, boolean useSymbol, int decimalPlaces, boolean simple) {
+ this(unit, () -> value, useSymbol, decimalPlaces, simple);
+ }
+
+ public UnitDisplay(Unit unit, double value, boolean useSymbol, boolean simple) {
+ this(unit, value, useSymbol, 2, simple);
+ }
+
+ public UnitDisplay(Unit unit, double value, int decimalPlaces, boolean simple) {
+ this(unit, value, true, decimalPlaces, simple);
+ }
+
+ public UnitDisplay(Unit unit, double value, boolean useSymbol, int decimalPlaces) {
+ this(unit, value, useSymbol, decimalPlaces, false);
+ }
+
+ public UnitDisplay(Unit unit, double value, int decimalPlaces) {
+ this(unit, value, true, decimalPlaces, false);
+ }
+
+ public UnitDisplay(Unit unit, double value, boolean simple) {
+ this(unit, value, true, 2, simple);
+ }
+
+ public UnitDisplay(Unit unit, double value) {
+ this(unit, value, true, 2, false);
+ }
+
+ public static double roundDecimals(double d) {
+ return MathUtil.roundDecimals(d, 2);
+ }
+
+ public UnitDisplay multiply(double value) {
+ return new UnitDisplay(unit, () -> this.value.getAsDouble() * value, isSimple, decimalPlaces, useSymbol, removeTrailingZeroes);
+ }
+
+ public UnitDisplay simple() {
+ return (isSimple ? this : new UnitDisplay(unit, value, true, decimalPlaces, useSymbol, removeTrailingZeroes));
+ }
+
+ public UnitDisplay notSimple() {
+ return (!isSimple ? this : new UnitDisplay(unit, value, false, decimalPlaces, useSymbol, removeTrailingZeroes));
+ }
+
+ public UnitDisplay symbol() {
+ return symbol(true);
+ }
+
+ public UnitDisplay symbol(boolean useSymbol) {
+ return (this.useSymbol ^ useSymbol ? new UnitDisplay(unit, value, isSimple, decimalPlaces, useSymbol, removeTrailingZeroes) : this);
+ }
+
+ public UnitDisplay decimal(int decimalPlaces) {
+ return (this.decimalPlaces == decimalPlaces ? this : new UnitDisplay(unit, value, isSimple, decimalPlaces, useSymbol, removeTrailingZeroes));
+ }
+
+ public UnitDisplay keepTrailingZeroes() {
+ return (this.removeTrailingZeroes ? new UnitDisplay(unit, value, isSimple, decimalPlaces, useSymbol, false) : this);
+ }
+
+ public UnitDisplay removeTrailingZeroes() {
+ return (this.removeTrailingZeroes ? this : new UnitDisplay(unit, value, isSimple, decimalPlaces, useSymbol, false));
+ }
+
+ @Override
+ public String toString() {
+ final String unitName;
+ double value = this.value.getAsDouble();
+ String prefix = "";
+
+ if (useSymbol)
+ unitName = unit.getSymbol();
+ else if (value > 1)
+ unitName = unit.getPluralName();
+ else
+ unitName = unit.getLocalizedName();
+
+ if (isSimple) {
+ if (value > 1) {
+ if (decimalPlaces < 1) {
+ return MathUtil.toString(value, removeTrailingZeroes) + " " + (useSymbol ? unit.getSymbol() : unit.getPluralName());
+ }
+
+ return MathUtil.toString(MathUtil.roundDecimals(value, decimalPlaces), removeTrailingZeroes) + " " + (useSymbol ? unit.getSymbol() : unit.getPluralName());
+ }
+
+ if (decimalPlaces < 1) {
+ return MathUtil.toString(value, removeTrailingZeroes) + " " + (useSymbol ? unit.getSymbol() : unit.getLocalizedName());
+ }
+
+ return MathUtil.toString(MathUtil.roundDecimals(value, decimalPlaces), removeTrailingZeroes) + " " + (useSymbol ? unit.getSymbol() : unit.getLocalizedName());
+ }
+
+ if (value < 0) {
+ value = Math.abs(value);
+ prefix = "-";
+ }
+
+ if (value == 0) {
+ return MathUtil.toString(value, removeTrailingZeroes) + " " + unitName;
+ } else {
+ for (int i = 0; i < UnitPrefix.getPrefixes().size(); i++) {
+ UnitPrefix lowerMeasure = UnitPrefix.getPrefixes().get(i);
+
+ if (lowerMeasure.isBellow(value) && i == 0) {
+ return prefix + MathUtil.toString(MathUtil.roundDecimals(lowerMeasure.process(value), decimalPlaces), removeTrailingZeroes) + " " + lowerMeasure.getName(useSymbol) + unitName;
+ }
+ if (i + 1 >= UnitPrefix.getPrefixes().size()) {
+ return prefix + MathUtil.toString(MathUtil.roundDecimals(lowerMeasure.process(value), decimalPlaces), removeTrailingZeroes) + " " + lowerMeasure.getName(useSymbol) + unitName;
+ }
+
+ UnitPrefix upperMeasure = UnitPrefix.getPrefixes().get(i + 1);
+
+ if ((lowerMeasure.isAbove(value) && upperMeasure.isBellow(value)) || lowerMeasure.value == value) {
+ return prefix + MathUtil.toString(MathUtil.roundDecimals(lowerMeasure.process(value), decimalPlaces), removeTrailingZeroes) + " " + lowerMeasure.getName(useSymbol) + unitName;
+ }
+ }
+ }
+
+ return prefix + MathUtil.toString(MathUtil.roundDecimals(value, decimalPlaces), removeTrailingZeroes) + " " + unitName;
+ }
+}
diff --git a/src/main/java/nova/core/util/unit/UnitPrefix.java b/src/main/java/nova/core/util/unit/UnitPrefix.java
new file mode 100644
index 000000000..78cdaf3a3
--- /dev/null
+++ b/src/main/java/nova/core/util/unit/UnitPrefix.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2015 NOVA, All rights reserved.
+ * This library is free software, licensed under GNU Lesser General Public License version 3
+ *
+ * This file is part of NOVA.
+ *
+ * NOVA is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * NOVA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with NOVA. If not, see .
+ */
+
+package nova.core.util.unit;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Metric system of measurement.
+ *
+ * @author Calclavia
+ */
+public class UnitPrefix {
+ private static final List UNIT_PREFIXES = new ArrayList<>();
+
+// public static final UnitPrefix YOCTO = new UnitPrefix("Yocto", "y", 0.000000000000000000000001);
+// public static final UnitPrefix ZEPTO = new UnitPrefix("Zepto", "z", 0.000000000000000000001);
+// public static final UnitPrefix ATTO = new UnitPrefix("Atto", "a", 0.000000000000000001);
+// public static final UnitPrefix FEMTO = new UnitPrefix("Femto", "p", 0.000000000000001);
+// public static final UnitPrefix PICO = new UnitPrefix("Pico", "p", 0.000000000001);
+// public static final UnitPrefix NANO = new UnitPrefix("Nano", "n", 0.000000001);
+ public static final UnitPrefix MICRO = new UnitPrefix("Micro", "µ", 0.000001);
+ public static final UnitPrefix MILLI = new UnitPrefix("Milli", "m", 0.001);
+ public static final UnitPrefix BASE = new UnitPrefix("", "", 1);
+ public static final UnitPrefix KILO = new UnitPrefix("Kilo", "k", 1000);
+ public static final UnitPrefix MEGA = new UnitPrefix("Mega", "M", 1000000);
+ public static final UnitPrefix GIGA = new UnitPrefix("Giga", "G", 1000000000);
+ public static final UnitPrefix TERA = new UnitPrefix("Tera", "T", 1000000000000d);
+ public static final UnitPrefix PETA = new UnitPrefix("Peta", "P", 1000000000000000d);
+ public static final UnitPrefix EXA = new UnitPrefix("Exa", "E", 1000000000000000000d);
+ public static final UnitPrefix ZETTA = new UnitPrefix("Zetta", "Z", 1000000000000000000000d);
+ public static final UnitPrefix YOTTA = new UnitPrefix("Yotta", "Y", 1000000000000000000000000d);
+
+ /**
+ * long name for the unit
+ */
+ public final String name;
+ /**
+ * short unit version of the unit
+ */
+ public final String symbol;
+ /**
+ * Point by which a number is consider to be of this unit
+ */
+ public final double value;
+
+ private UnitPrefix(String name, String symbol, double value) {
+ this.name = name;
+ this.symbol = symbol;
+ this.value = value;
+ UNIT_PREFIXES.add(this);
+ }
+
+ public String getName(boolean getShort) {
+ if (getShort) {
+ return symbol;
+ } else {
+ return name;
+ }
+ }
+
+ /**
+ * Divides the value by the unit value start
+ */
+ public double process(double value) {
+ return value / this.value;
+ }
+
+ /**
+ * Checks if a value is above the unit value start
+ */
+ public boolean isAbove(double value) {
+ return value > this.value;
+ }
+
+ /**
+ * Checks if a value is lower than the unit value start
+ */
+ public boolean isBellow(double value) {
+ return value < this.value;
+ }
+
+ public static List getPrefixes() {
+ return Collections.unmodifiableList(UNIT_PREFIXES);
+ }
+}
diff --git a/src/main/resources/assets/nova/lang/en-GB.lang b/src/main/resources/assets/nova/lang/en-GB.lang
index 50d9d2d92..3c6d1099d 100644
--- a/src/main/resources/assets/nova/lang/en-GB.lang
+++ b/src/main/resources/assets/nova/lang/en-GB.lang
@@ -1,3 +1,7 @@
+##================##
+## Unit convesion ##
+##================##
+
unit.nova.metre.name=Metre
unit.nova.metre.plural=Metres
unit.nova.litre.name=Litre
@@ -5,6 +9,13 @@ unit.nova.litre.plural=Litres
unit.nova.gram.name=Gram
unit.nova.gram.plural=Grams
+unit.nova.celsius.name=degree Celsius
+unit.nova.celsius.plural=degrees Celsius
+unit.nova.kelvin.name=kelvin
+unit.nova.kelvin.plural=kelvins
+unit.nova.fahrenheit.name=degree Fahrenheit
+unit.nova.fahrenheit.plural=degrees Fahrenheit
+
unit.nova.ampere.name=Amp
unit.nova.ampere.plural=Amps
unit.nova.amp_hour.name=Amp Hour
diff --git a/src/main/resources/assets/nova/lang/en-US.lang b/src/main/resources/assets/nova/lang/en-US.lang
index 4ad2bcadd..094456dd2 100644
--- a/src/main/resources/assets/nova/lang/en-US.lang
+++ b/src/main/resources/assets/nova/lang/en-US.lang
@@ -1,3 +1,7 @@
+##================##
+## Unit convesion ##
+##================##
+
unit.nova.metre.name=Meter
unit.nova.metre.plural=Meters
unit.nova.litre.name=Liter
@@ -5,6 +9,13 @@ unit.nova.litre.plural=Liters
unit.nova.gram.name=Gram
unit.nova.gram.plural=Grams
+unit.nova.celsius.name=degree Celsius
+unit.nova.celsius.plural=degrees Celsius
+unit.nova.kelvin.name=kelvin
+unit.nova.kelvin.plural=kelvins
+unit.nova.fahrenheit.name=degree Fahrenheit
+unit.nova.fahrenheit.plural=degrees Fahrenheit
+
unit.nova.ampere.name=Amp
unit.nova.ampere.plural=Amps
unit.nova.amp_hour.name=Amp Hour
diff --git a/src/test/java/nova/core/util/math/MathUtilTest.java b/src/test/java/nova/core/util/math/MathUtilTest.java
index 51c2a1889..eb055be7f 100755
--- a/src/test/java/nova/core/util/math/MathUtilTest.java
+++ b/src/test/java/nova/core/util/math/MathUtilTest.java
@@ -26,6 +26,7 @@
import org.junit.Test;
import static nova.testutils.NovaAssertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThat;
/**
@@ -35,57 +36,77 @@
public class MathUtilTest {
@Test
public void testMax() {
- assertThat(MathUtil.max(1,2)).isEqualTo(2);
- assertThat(MathUtil.max(2,1)).isEqualTo(2);
+ assertThat(MathUtil.max(1, 2)).isEqualTo(2);
+ assertThat(MathUtil.max(2, 1)).isEqualTo(2);
- assertThat(MathUtil.max(0,1,2)).isEqualTo(2);
- assertThat(MathUtil.max(0,2,1)).isEqualTo(2);
- assertThat(MathUtil.max(2,0,1)).isEqualTo(2);
+ assertThat(MathUtil.max(0, 1, 2)).isEqualTo(2);
+ assertThat(MathUtil.max(0, 2, 1)).isEqualTo(2);
+ assertThat(MathUtil.max(2, 0, 1)).isEqualTo(2);
- assertThat(MathUtil.max(0,1,2,4)).isEqualTo(4);
- assertThat(MathUtil.max(0,4,2,1)).isEqualTo(4);
- assertThat(MathUtil.max(4,2,0,1)).isEqualTo(4);
+ assertThat(MathUtil.max(0, 1, 2, 4)).isEqualTo(4);
+ assertThat(MathUtil.max(0, 4, 2, 1)).isEqualTo(4);
+ assertThat(MathUtil.max(4, 2, 0, 1)).isEqualTo(4);
- assertThat(MathUtil.max(1d,2d)).isEqualTo(2d);
- assertThat(MathUtil.max(2d,1d)).isEqualTo(2d);
+ assertThat(MathUtil.max(1l, 2l)).isEqualTo(2l);
+ assertThat(MathUtil.max(2l, 1l)).isEqualTo(2l);
- assertThat(MathUtil.max(0d,1d,2d)).isEqualTo(2d);
- assertThat(MathUtil.max(0d,2d,1d)).isEqualTo(2d);
- assertThat(MathUtil.max(2d,0d,1d)).isEqualTo(2d);
+ assertThat(MathUtil.max(0l, 1l, 2l)).isEqualTo(2l);
+ assertThat(MathUtil.max(0l, 2l, 1l)).isEqualTo(2l);
+ assertThat(MathUtil.max(2l, 0l, 1l)).isEqualTo(2l);
- assertThat(MathUtil.max(0d,1d,2d,4d)).isEqualTo(4d);
- assertThat(MathUtil.max(0d,4d,2d,1d)).isEqualTo(4d);
- assertThat(MathUtil.max(4d,2d,0d,1d)).isEqualTo(4d);
+ assertThat(MathUtil.max(0l, 1l, 2l, 4l)).isEqualTo(4l);
+ assertThat(MathUtil.max(0l, 4l, 2l, 1l)).isEqualTo(4l);
+ assertThat(MathUtil.max(4l, 2l, 0l, 1l)).isEqualTo(4l);
- assertThat(MathUtil.max(1d,2d)).isEqualTo(2d);
- assertThat(MathUtil.max(2d,1d)).isEqualTo(2d);
+ assertThat(MathUtil.max(1d, 2d)).isEqualTo(2d);
+ assertThat(MathUtil.max(2d, 1d)).isEqualTo(2d);
- assertThat(MathUtil.max(0f,1f,2f)).isEqualTo(2f);
- assertThat(MathUtil.max(0f,2f,1f)).isEqualTo(2f);
- assertThat(MathUtil.max(2f,0f,1f)).isEqualTo(2f);
+ assertThat(MathUtil.max(0d, 1d, 2d)).isEqualTo(2d);
+ assertThat(MathUtil.max(0d, 2d, 1d)).isEqualTo(2d);
+ assertThat(MathUtil.max(2d, 0d, 1d)).isEqualTo(2d);
- assertThat(MathUtil.max(0f,1f,2f,4f)).isEqualTo(4f);
- assertThat(MathUtil.max(0f,4f,2f,1f)).isEqualTo(4f);
- assertThat(MathUtil.max(4f,2f,0f,1f)).isEqualTo(4f);
+ assertThat(MathUtil.max(0d, 1d, 2d, 4d)).isEqualTo(4d);
+ assertThat(MathUtil.max(0d, 4d, 2d, 1d)).isEqualTo(4d);
+ assertThat(MathUtil.max(4d, 2d, 0d, 1d)).isEqualTo(4d);
+
+ assertThat(MathUtil.max(1d, 2d)).isEqualTo(2d);
+ assertThat(MathUtil.max(2d, 1d)).isEqualTo(2d);
+
+ assertThat(MathUtil.max(0f, 1f, 2f)).isEqualTo(2f);
+ assertThat(MathUtil.max(0f, 2f, 1f)).isEqualTo(2f);
+ assertThat(MathUtil.max(2f, 0f, 1f)).isEqualTo(2f);
+
+ assertThat(MathUtil.max(0f, 1f, 2f, 4f)).isEqualTo(4f);
+ assertThat(MathUtil.max(0f, 4f, 2f, 1f)).isEqualTo(4f);
+ assertThat(MathUtil.max(4f, 2f, 0f, 1f)).isEqualTo(4f);
}
@Test(expected = IllegalArgumentException.class)
- public void testMaxError() {
- MathUtil.max();
+ public void testMaxErrorInt() {
+ MathUtil.max(new int[]{});
+ }
+ @Test(expected = IllegalArgumentException.class)
+ public void testMaxErrorLong() {
+ MathUtil.max(new long[]{});
}
+
@Test(expected = IllegalArgumentException.class)
public void testMaxErrorDouble() {
MathUtil.max(new double[]{});
}
+ @Test(expected = IllegalArgumentException.class)
+ public void testMaxErrorFloat() {
+ MathUtil.max(new float[]{});
+ }
@Test
public void testMin() {
assertThat(MathUtil.min(1, 2)).isEqualTo(1);
assertThat(MathUtil.min(2, 1)).isEqualTo(1);
- assertThat(MathUtil.min(0,1,2)).isEqualTo(0);
+ assertThat(MathUtil.min(0, 1, 2)).isEqualTo(0);
assertThat(MathUtil.min(0, 2, 1)).isEqualTo(0);
assertThat(MathUtil.min(2, 0, 1)).isEqualTo(0);
@@ -93,21 +114,32 @@ public void testMin() {
assertThat(MathUtil.min(0, 4, 2, 1)).isEqualTo(0);
assertThat(MathUtil.min(4, 2, 0, 1)).isEqualTo(0);
+ assertThat(MathUtil.min(1l, 2l)).isEqualTo(1l);
+ assertThat(MathUtil.min(2l, 1l)).isEqualTo(1l);
+
+ assertThat(MathUtil.min(0l, 1l, 2l)).isEqualTo(0l);
+ assertThat(MathUtil.min(0l, 2l, 1l)).isEqualTo(0l);
+ assertThat(MathUtil.min(2l, 0l, 1l)).isEqualTo(0l);
+
+ assertThat(MathUtil.min(0l, 1l, 2l, 4l)).isEqualTo(0l);
+ assertThat(MathUtil.min(0l, 4l, 2l, 1l)).isEqualTo(0l);
+ assertThat(MathUtil.min(4l, 2l, 0l, 1l)).isEqualTo(0l);
+
assertThat(MathUtil.min(1d, 2d)).isEqualTo(1d);
assertThat(MathUtil.min(2d, 1d)).isEqualTo(1d);
- assertThat(MathUtil.min(0d,1d,2d)).isEqualTo(0d);
+ assertThat(MathUtil.min(0d, 1d, 2d)).isEqualTo(0d);
assertThat(MathUtil.min(0d, 2d, 1d)).isEqualTo(0d);
assertThat(MathUtil.min(2d, 0d, 1d)).isEqualTo(0d);
assertThat(MathUtil.min(0d, 1d, 2d, 4d)).isEqualTo(0d);
assertThat(MathUtil.min(0d, 4d, 2d, 1d)).isEqualTo(0d);
assertThat(MathUtil.min(4d, 2d, 0d, 1d)).isEqualTo(0d);
-
+
assertThat(MathUtil.min(1f, 2f)).isEqualTo(1f);
assertThat(MathUtil.min(2f, 1f)).isEqualTo(1f);
- assertThat(MathUtil.min(0f,1f,2f)).isEqualTo(0f);
+ assertThat(MathUtil.min(0f, 1f, 2f)).isEqualTo(0f);
assertThat(MathUtil.min(0f, 2f, 1f)).isEqualTo(0f);
assertThat(MathUtil.min(2f, 0f, 1f)).isEqualTo(0f);
@@ -117,8 +149,13 @@ public void testMin() {
}
@Test(expected = IllegalArgumentException.class)
- public void testMinError() {
- MathUtil.min();
+ public void testMinErrorInt() {
+ MathUtil.min(new int[]{});
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testMinErrorLong() {
+ MathUtil.min(new long[]{});
}
@Test(expected = IllegalArgumentException.class)
@@ -126,6 +163,11 @@ public void testMinErrorDouble() {
MathUtil.min(new double[]{});
}
+ @Test(expected = IllegalArgumentException.class)
+ public void testMinErrorFloat() {
+ MathUtil.min(new float[]{});
+ }
+
@Test
public void testClamp() {
assertThat(MathUtil.clamp(6, 2, 3)).isEqualTo(3);
@@ -133,10 +175,15 @@ public void testClamp() {
assertThat(MathUtil.clamp(3, 2, 3)).isEqualTo(3);
assertThat(MathUtil.clamp(1, 2, 3)).isEqualTo(2);
- assertThat(MathUtil.clamp(6D, 2, 3)).isEqualTo(3);
- assertThat(MathUtil.clamp(2D, 2, 3)).isEqualTo(2);
- assertThat(MathUtil.clamp(3D, 2, 3)).isEqualTo(3);
- assertThat(MathUtil.clamp(1D, 2, 3)).isEqualTo(2);
+ assertThat(MathUtil.clamp(6l, 2l, 3l)).isEqualTo(3l);
+ assertThat(MathUtil.clamp(2l, 2l, 3l)).isEqualTo(2l);
+ assertThat(MathUtil.clamp(3l, 2l, 3l)).isEqualTo(3l);
+ assertThat(MathUtil.clamp(1l, 2l, 3l)).isEqualTo(2l);
+
+ assertThat(MathUtil.clamp(6d, 2d, 3d)).isEqualTo(3);
+ assertThat(MathUtil.clamp(2d, 2d, 3d)).isEqualTo(2);
+ assertThat(MathUtil.clamp(3d, 2d, 3d)).isEqualTo(3);
+ assertThat(MathUtil.clamp(1d, 2d, 3d)).isEqualTo(2);
}
@Test
@@ -156,5 +203,14 @@ public void testLerp() {
assertThat(MathUtil.lerp(Vector3D.ZERO, Vector3DUtil.ONE, 1)).isAlmostEqualTo(Vector3DUtil.ONE);
}
+ @Test
+ public void testToString() {
+ assertThat(MathUtil.toString(0, false)).isEqualTo("0.0");
+ assertThat(MathUtil.toString(0.5, false)).isEqualTo("0.5");
+ assertThat(MathUtil.toString(1, false)).isEqualTo("1.0");
+ assertThat(MathUtil.toString(0, true)).isEqualTo("0");
+ assertThat(MathUtil.toString(0.5, true)).isEqualTo("0.5");
+ assertThat(MathUtil.toString(1, true)).isEqualTo("1");
+ }
}
diff --git a/src/test/java/nova/core/util/unit/UnitDisplayTest.java b/src/test/java/nova/core/util/unit/UnitDisplayTest.java
new file mode 100644
index 000000000..cfdfe94ce
--- /dev/null
+++ b/src/test/java/nova/core/util/unit/UnitDisplayTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 NOVA, All rights reserved.
+ * This library is free software, licensed under GNU Lesser General Public License version 3
+ *
+ * This file is part of NOVA.
+ *
+ * NOVA is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * NOVA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with NOVA. If not, see .
+ */
+
+package nova.core.util.unit;
+
+/**
+ * @author ExE Boss
+ */
+public class UnitDisplayTest {
+
+ public UnitDisplayTest() {
+ }
+
+ // TODO: Temporarily disabled because `Unit`'s initialization code depends on `LanguageManager` being instantiated
+// @Test
+// public void testUnitDisplay() {
+// UnitDisplay unitDisplay = new UnitDisplay(Unit.JOULE, 0);
+// assertThat(unitDisplay.toString()).isEqualTo("0 J");
+// }
+}
diff --git a/src/test/java/nova/core/util/unit/UnitPrefixTest.java b/src/test/java/nova/core/util/unit/UnitPrefixTest.java
new file mode 100644
index 000000000..51026d997
--- /dev/null
+++ b/src/test/java/nova/core/util/unit/UnitPrefixTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017 NOVA, All rights reserved.
+ * This library is free software, licensed under GNU Lesser General Public License version 3
+ *
+ * This file is part of NOVA.
+ *
+ * NOVA is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * NOVA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with NOVA. If not, see .
+ */
+package nova.core.util.unit;
+
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ *
+ * @author ExE Boss
+ */
+public class UnitPrefixTest {
+
+ public UnitPrefixTest() {
+ }
+
+ @Test
+ public void testGetName() {
+ assertThat(UnitPrefix.MEGA.getName(false)).isEqualTo(UnitPrefix.MEGA.name);
+ assertThat(UnitPrefix.MEGA.getName(true)).isEqualTo(UnitPrefix.MEGA.symbol);
+ }
+
+ @Test
+ public void testProcess() {
+ assertThat(UnitPrefix.MILLI.process(0.001)).isEqualTo(1);
+ assertThat(UnitPrefix.BASE.process(1)).isEqualTo(1);
+ assertThat(UnitPrefix.KILO.process(1000)).isEqualTo(1);
+ }
+
+ @Test
+ public void testAboveBellow() {
+ assertThat(UnitPrefix.BASE.isAbove(10)).isTrue();
+ assertThat(UnitPrefix.BASE.isAbove(0.1)).isFalse();
+
+ assertThat(UnitPrefix.BASE.isBellow(10)).isFalse();
+ assertThat(UnitPrefix.BASE.isBellow(0.1)).isTrue();
+ }
+
+ @Test
+ public void testGetPrefixes() {
+ List prefixes = UnitPrefix.getPrefixes();
+ assertThat(prefixes).contains(UnitPrefix.MILLI,
+ UnitPrefix.MICRO,
+ UnitPrefix.BASE,
+ UnitPrefix.KILO,
+ UnitPrefix.MEGA,
+ UnitPrefix.GIGA,
+ UnitPrefix.TERA,
+ UnitPrefix.PETA,
+ UnitPrefix.EXA,
+ UnitPrefix.ZETTA,
+ UnitPrefix.YOTTA);
+ }
+}