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); + } +}