diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java index f6e4e77f27..4aac706e4f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java @@ -266,7 +266,7 @@ class XpInfoBox extends JPanel static String htmlLabel(String key, int value) { - String valueStr = StackFormatter.quantityToRSDecimalStack(value); + String valueStr = StackFormatter.quantityToRSDecimalStack(value, true); return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR), key, valueStr); } } diff --git a/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java b/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java index 40dda01a4e..c9282f7f46 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java +++ b/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java @@ -61,6 +61,14 @@ public class StackFormatter DecimalFormatSymbols.getInstance(Locale.ENGLISH) ); + /** + * A more precise decimal number formatter, outputting thousandths + */ + private static final NumberFormat PRECISE_DECIMAL_FORMATTER = new DecimalFormat( + "#,###.###", + DecimalFormatSymbols.getInstance(Locale.ENGLISH) + ); + /** * Convert a quantity to a nicely formatted stack size. * See the StackFormatterTest to see expected output. @@ -152,6 +160,24 @@ public class StackFormatter * with K after 100,000 and M after 10,000,000 */ public static String quantityToRSDecimalStack(int quantity) + { + return quantityToRSDecimalStack(quantity, false); + } + + /** + * Convert a quantity to stack size as it would + * appear in RuneScape. (with decimals) + *

+ * This differs from quantityToRSStack in that it displays + * decimals. Ex: 27100 is 27.1k (not 27k) + *

+ * + * @param quantity The quantity to convert. + * @param precise If true, the returned string will have thousandths precision if quantity is larger than 1 million. + * @return The stack size as it would appear in RS, with decimals, + * with K after 100,000 and M after 10,000,000 + */ + public static String quantityToRSDecimalStack(int quantity, boolean precise) { String quantityStr = String.valueOf(quantity); if (quantityStr.length() <= 4) @@ -160,7 +186,13 @@ public class StackFormatter } int power = (int) Math.log10(quantity); - return DECIMAL_FORMATTER.format(quantity / (Math.pow(10, (power / 3) * 3))) + SUFFIXES[power / 3]; + + // Output thousandths for values above a million + NumberFormat format = precise && power >= 6 + ? PRECISE_DECIMAL_FORMATTER + : DECIMAL_FORMATTER; + + return format.format(quantity / (Math.pow(10, (power / 3) * 3))) + SUFFIXES[power / 3]; } /** diff --git a/runelite-client/src/test/java/net/runelite/client/util/StackFormatterTest.java b/runelite-client/src/test/java/net/runelite/client/util/StackFormatterTest.java index 53a1c963d1..1e297a8513 100644 --- a/runelite-client/src/test/java/net/runelite/client/util/StackFormatterTest.java +++ b/runelite-client/src/test/java/net/runelite/client/util/StackFormatterTest.java @@ -97,6 +97,31 @@ public class StackFormatterTest assertEquals("-400B", StackFormatter.quantityToStackSize(-400_000_000_000L)); } + @Test + public void quantityToPreciseStackSize() + { + assertEquals("0", StackFormatter.quantityToRSDecimalStack(0)); + assertEquals("8500", StackFormatter.quantityToRSDecimalStack(8_500, true)); + assertEquals("10K", StackFormatter.quantityToRSDecimalStack(10_000, true)); + assertEquals("21.7K", StackFormatter.quantityToRSDecimalStack(21_710, true)); + assertEquals("100K", StackFormatter.quantityToRSDecimalStack(100_000, true)); + assertEquals("100.3K", StackFormatter.quantityToRSDecimalStack(100_310, true)); + assertEquals("1M", StackFormatter.quantityToRSDecimalStack(1_000_000, true)); + assertEquals("8.45M", StackFormatter.quantityToRSDecimalStack(8_450_000, true)); + assertEquals("8.451M", StackFormatter.quantityToRSDecimalStack(8_451_000, true)); + assertEquals("10M", StackFormatter.quantityToRSDecimalStack(10_000_000, true)); + assertEquals("12.8M", StackFormatter.quantityToRSDecimalStack(12_800_000, true)); + assertEquals("12.85M", StackFormatter.quantityToRSDecimalStack(12_850_000, true)); + assertEquals("12.851M", StackFormatter.quantityToRSDecimalStack(12_851_000, true)); + assertEquals("100M", StackFormatter.quantityToRSDecimalStack(100_000_000, true)); + assertEquals("250.1M", StackFormatter.quantityToRSDecimalStack(250_100_000, true)); + assertEquals("250.151M", StackFormatter.quantityToRSDecimalStack(250_151_000, true)); + assertEquals("1B", StackFormatter.quantityToRSDecimalStack(1_000_000_000, true)); + assertEquals("1.5B", StackFormatter.quantityToRSDecimalStack(1500_000_000, true)); + assertEquals("1.55B", StackFormatter.quantityToRSDecimalStack(1550_000_000, true)); + assertEquals("2.147B", StackFormatter.quantityToRSDecimalStack(Integer.MAX_VALUE, true)); + } + @Test public void stackSizeToQuantity() throws ParseException {