Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add locale based comma support for /pay #5962

Merged
merged 5 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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());
}
}
Loading