diff --git a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandpay.java b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandpay.java index b58d26001d6..264a3effcf7 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/commands/Commandpay.java +++ b/Essentials/src/main/java/com/earth2me/essentials/commands/Commandpay.java @@ -18,11 +18,6 @@ import java.util.concurrent.atomic.AtomicBoolean; public class Commandpay extends EssentialsLoopCommand { - private static final BigDecimal THOUSAND = new BigDecimal(1000); - private static final BigDecimal MILLION = new BigDecimal(1_000_000); - private static final BigDecimal BILLION = new BigDecimal(1_000_000_000); - private static final BigDecimal TRILLION = new BigDecimal(1_000_000_000_000L); - public Commandpay() { super("pay"); } @@ -45,34 +40,13 @@ public void run(final Server server, final User user, final String commandLabel, throw new NotEnoughArgumentsException(); } - BigDecimal tempAmount = new BigDecimal(sanitizedString); - switch (ogStr.replace(sanitizedString, "")) { - case "": { - break; - } - case "k": { - tempAmount = tempAmount.multiply(THOUSAND); - break; - } - case "m": { - tempAmount = tempAmount.multiply(MILLION); - break; - } - case "b": { - tempAmount = tempAmount.multiply(BILLION); - break; - } - case "t": { - tempAmount = tempAmount.multiply(TRILLION); - break; - } - default: { - throw new InvalidModifierException(); - } + final BigDecimal amount; + if (ess.getSettings().isPerPlayerLocale()) { + amount = NumberUtil.parseStringToBDecimal(ogStr, user.getPlayerLocale(ess.getPlayerLocaleProvider().getLocale(user.getBase()))); + } else { + amount = NumberUtil.parseStringToBDecimal(ogStr); } - final BigDecimal amount = tempAmount; - if (amount.compareTo(ess.getSettings().getMinimumPayAmount()) < 0) { // Check if amount is less than minimum-pay-amount throw new TranslatableException("minimumPayAmount", AdventureUtil.parsed(NumberUtil.displayCurrencyExactly(ess.getSettings().getMinimumPayAmount(), ess))); } diff --git a/Essentials/src/main/java/com/earth2me/essentials/utils/NumberUtil.java b/Essentials/src/main/java/com/earth2me/essentials/utils/NumberUtil.java index cd1aef9d3c4..bc8e3fa963a 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/utils/NumberUtil.java +++ b/Essentials/src/main/java/com/earth2me/essentials/utils/NumberUtil.java @@ -1,5 +1,6 @@ package com.earth2me.essentials.utils; +import com.earth2me.essentials.commands.InvalidModifierException; import net.ess3.api.IEssentials; import java.math.BigDecimal; @@ -7,18 +8,25 @@ import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.NumberFormat; +import java.text.ParseException; import java.util.Locale; import static com.earth2me.essentials.I18n.tlLiteral; public final class NumberUtil { + private static final BigDecimal THOUSAND = new BigDecimal(1000); + private static final BigDecimal MILLION = new BigDecimal(1_000_000); + private static final BigDecimal BILLION = new BigDecimal(1_000_000_000); + private static final BigDecimal TRILLION = new BigDecimal(1_000_000_000_000L); + private static final DecimalFormat twoDPlaces = new DecimalFormat("#,###.##"); private static final DecimalFormat currencyFormat = new DecimalFormat("#0.00", DecimalFormatSymbols.getInstance(Locale.US)); // This field is likely to be modified in com.earth2me.essentials.Settings when loading currency format. // This ensures that we can supply a constant formatting. - private static NumberFormat PRETTY_FORMAT = NumberFormat.getInstance(Locale.US); + private static Locale PRETTY_LOCALE = Locale.US; + private static NumberFormat PRETTY_FORMAT = NumberFormat.getInstance(PRETTY_LOCALE); static { twoDPlaces.setRoundingMode(RoundingMode.HALF_UP); @@ -139,6 +147,52 @@ public static boolean isHexadecimal(final String sNum) { } } + public static BigDecimal parseStringToBDecimal(final String sArg, final Locale locale) throws ParseException, InvalidModifierException { + if (sArg.isEmpty()) { + throw new IllegalArgumentException(); + } + + final String sanitizedString = sArg.replaceAll("[^0-9.,]", ""); + BigDecimal multiplier = null; + + switch (sArg.replace(sanitizedString, "").toUpperCase()) { + case "": { + break; + } + case "K": { + multiplier = THOUSAND; + break; + } + case "M": { + multiplier = MILLION; + break; + } + case "B": { + multiplier = BILLION; + break; + } + case "T": { + multiplier = TRILLION; + break; + } + default: + throw new InvalidModifierException(); + } + + final NumberFormat format = NumberFormat.getInstance(locale); + final Number parsed = format.parse(sanitizedString); + BigDecimal amount = new BigDecimal(parsed.toString()); + + if (multiplier != null) { + amount = amount.multiply(multiplier); + } + return amount; + } + + public static BigDecimal parseStringToBDecimal(final String sArg) throws ParseException, InvalidModifierException { + return parseStringToBDecimal(sArg, PRETTY_LOCALE); + } + /** * Backport from Guava. */ diff --git a/Essentials/src/test/java/com/earth2me/essentials/utils/NumberUtilTest.java b/Essentials/src/test/java/com/earth2me/essentials/utils/NumberUtilTest.java new file mode 100644 index 00000000000..22f33aa5784 --- /dev/null +++ b/Essentials/src/test/java/com/earth2me/essentials/utils/NumberUtilTest.java @@ -0,0 +1,73 @@ +package com.earth2me.essentials.utils; + +import com.earth2me.essentials.commands.InvalidModifierException; +import org.junit.Test; + +import java.math.BigDecimal; +import java.text.ParseException; +import java.util.Locale; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertThrows; + +public class NumberUtilTest { + + @Test + public void testStringParseBDecimal() throws ParseException, InvalidModifierException { + + final BigDecimal decimal = NumberUtil.parseStringToBDecimal("10,000,000.5"); + assertEquals("10000000.5", decimal.toString()); + + final BigDecimal decimal2 = NumberUtil.parseStringToBDecimal("10.000.000,5"); + assertNotEquals("10000000.5", decimal2.toString()); + + final BigDecimal decimal3 = NumberUtil.parseStringToBDecimal("10000000,5"); + assertNotEquals("10000000.5", decimal3.toString()); + + final BigDecimal decimal4 = NumberUtil.parseStringToBDecimal("10000000.5"); + assertEquals("10000000.5", decimal4.toString()); + + final BigDecimal decimal5 = NumberUtil.parseStringToBDecimal("10000000.50000"); + assertEquals("10000000.5", decimal5.toString()); + + final BigDecimal decimal6 = NumberUtil.parseStringToBDecimal(".50000"); + assertEquals("0.5", decimal6.toString()); + + final BigDecimal decimal7 = NumberUtil.parseStringToBDecimal("00000.50000"); + assertEquals("0.5", decimal7.toString()); + + final BigDecimal decimal8 = NumberUtil.parseStringToBDecimal(",50000"); + assertEquals("50000", decimal8.toString()); + + assertThrows(InvalidModifierException.class, ()-> NumberUtil.parseStringToBDecimal("abc")); + + assertThrows(IllegalArgumentException.class, ()-> NumberUtil.parseStringToBDecimal("")); + + assertThrows(ParseException.class, ()-> NumberUtil.parseStringToBDecimal("M")); + } + + @Test + public void testStringParseBDecimalLocale() throws ParseException, InvalidModifierException { + + final Locale locale = Locale.GERMANY; + + final BigDecimal decimal = NumberUtil.parseStringToBDecimal("10,000,000.5", locale); + assertNotEquals("10000000.5", decimal.toString()); + + final BigDecimal decimal2 = NumberUtil.parseStringToBDecimal("10.000.000,5", locale); + assertEquals("10000000.5", decimal2.toString()); + + final BigDecimal decimal3 = NumberUtil.parseStringToBDecimal("10000000,5", locale); + assertEquals("10000000.5", decimal3.toString()); + + final BigDecimal decimal4 = NumberUtil.parseStringToBDecimal("10000000.5", locale); + assertNotEquals("10000000.5", decimal4.toString()); + + final BigDecimal decimal5 = NumberUtil.parseStringToBDecimal(",5", locale); + assertEquals("0.5", decimal5.toString()); + + final BigDecimal decimal6 = NumberUtil.parseStringToBDecimal(".50000", locale); + assertEquals("50000", decimal6.toString()); + } +}