Skip to content

Commit

Permalink
Add locale based comma support for /pay (#5962)
Browse files Browse the repository at this point in the history
Co-authored-by: JRoy <[email protected]>
  • Loading branch information
Kyriakum and JRoy authored Nov 25, 2024
1 parent 9590d4c commit 3f0a412
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand All @@ -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)));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
package com.earth2me.essentials.utils;

import com.earth2me.essentials.commands.InvalidModifierException;
import net.ess3.api.IEssentials;

import java.math.BigDecimal;
import java.math.RoundingMode;
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);
Expand Down Expand 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.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -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());
}
}

0 comments on commit 3f0a412

Please sign in to comment.