Skip to content

Commit

Permalink
rewrite large number formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
brachy84 committed Oct 2, 2023
1 parent 199a9a1 commit 8867324
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 67 deletions.
2 changes: 1 addition & 1 deletion src/main/java/com/cleanroommc/modularui/test/TestTile.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
public class TestTile extends TileEntity implements IGuiHolder, ITickable {

private final FluidTank fluidTank = new FluidTank(10000);
private final FluidTank fluidTankPhantom = new FluidTank(10000);
private final FluidTank fluidTankPhantom = new FluidTank(Integer.MAX_VALUE);
private long time = 0;
private int val, val2 = 0;
private String value = "";
Expand Down
99 changes: 42 additions & 57 deletions src/main/java/com/cleanroommc/modularui/utils/NumberFormat.java
Original file line number Diff line number Diff line change
@@ -1,75 +1,60 @@
package com.cleanroommc.modularui.utils;

import org.jetbrains.annotations.NotNull;
import org.apache.commons.lang3.StringUtils;

import java.text.DecimalFormat;
import java.util.Map;
import java.util.NavigableMap;
import java.util.TreeMap;

public class NumberFormat {

private static final NavigableMap<Double, String> suffixesByPower = new TreeMap<>();
private static final java.text.NumberFormat[] NUMBER_FORMAT = {
new DecimalFormat("0."),
new DecimalFormat("0.#"),
new DecimalFormat("0.##"),
new DecimalFormat("0.###"),
new DecimalFormat("0.####"),
new DecimalFormat("0.#####"),
new DecimalFormat("0.######"),
new DecimalFormat("0.#######"),
new DecimalFormat("0.########"),
new DecimalFormat("0.#########"),
};
public static final DecimalFormat FORMAT = new DecimalFormat("0.###");

static {
suffixesByPower.put(0.000_000_000_000_000_001D, "a");
suffixesByPower.put(0.000_000_000_000_001D, "f");
suffixesByPower.put(0.000_000_000_001D, "p");
suffixesByPower.put(0.000_000_001D, "n");
suffixesByPower.put(0.000_001D, "u");
suffixesByPower.put(0.001D, "m");
suffixesByPower.put(1_000D, "k");
suffixesByPower.put(1_000_000D, "M");
suffixesByPower.put(1_000_000_000D, "G");
suffixesByPower.put(1_000_000000_000D, "T");
suffixesByPower.put(1_000_000000_000_000D, "P");
suffixesByPower.put(1_000_000000_000_000_000D, "E");
private static final double[] FACTORS_HIGH = {1e3, 1e6, 1e9, 1e12, 1e15, 1e18};
private static final double[] FACTORS_LOW = {1e-3, 1e-6, 1e-9, 1e-12, 1e-15, 1e-18};
private static final String[] SUFFIX_HIGH = {"k", "M", "G", "T", "P", "E"};
private static final String[] SUFFIX_LOW = {"m", "u", "n", "p", "f", "a"};

public static String formatWithMaxDigits(double value) {
return format(value, 4, true);
}

@NotNull
public static String format(double value, int precision) {
//Double.MIN_VALUE == -Double.MIN_VALUE so we need an adjustment here
if (value == Double.MIN_VALUE) return format(Double.MIN_VALUE + 1, precision);
if (value == 0) return "0";
if (value < 0) return '-' + format(-value, precision);
double divideBy;
String suffix;
if (value < pow(10, precision)) {
divideBy = 1;
suffix = "";
} else {
Map.Entry<Double, String> e = suffixesByPower.floorEntry(value);
divideBy = e.getKey();
suffix = e.getValue();
}
public static String formatWithMaxDigits(double value, int maxDigits) {
return format(value, maxDigits, true);
}

double truncated = value / (divideBy / 10); //the number part of the output times 10
boolean hasDecimal = truncated < 100 && (truncated / 10D) != (truncated / 10);
return hasDecimal ? NUMBER_FORMAT[precision].format(truncated / 10D) + suffix : NUMBER_FORMAT[precision].format(truncated / 10) + suffix;
public static String formatWithMaxDecimals(double value, int decimals) {
return format(value, decimals, false);
}

@NotNull
public static String format(double value) {
return format(value, 3);
private static String format(double value, int precision, boolean maxDigits) {
if (value >= 1000) {
int index;
for (index = 0; index < 5; index++) {
if (value < FACTORS_HIGH[index + 1]) {
break;
}
}
return formatToString(value / FACTORS_HIGH[index], precision, maxDigits, SUFFIX_HIGH[index]);
}
if (value < 1) {
int index;
for (index = 0; index < 5; index++) {
if (value >= FACTORS_LOW[index]) {
break;
}
}
return formatToString(value / FACTORS_LOW[index], precision, maxDigits, SUFFIX_LOW[index]);
}
return formatToString(value, precision, maxDigits, StringUtils.EMPTY);
}

private static int pow(int num, int e) {
int result = num;
for (int i = 0; i < e; i++) {
result *= num;
private static String formatToString(double value, int precision, boolean maxDigits, String suffix) {
if (maxDigits) {
String[] parts = String.valueOf(value).split("\\.");
if (parts.length > 1) {
precision -= parts[0].length();
}
}
return result;
FORMAT.setMaximumFractionDigits(precision);
return FORMAT.format(value) + suffix;
}
}
25 changes: 20 additions & 5 deletions src/main/java/com/cleanroommc/modularui/widgets/FluidSlot.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@

public class FluidSlot extends Widget<FluidSlot> implements Interactable, JeiGhostIngredientSlot<FluidStack>, JeiIngredientProvider {

private static final String UNIT_BUCKET = "B";
private static final String UNIT_LITER = "L";

private static final IFluidTank EMPTY = new FluidTank(0);

private final TextRenderer textRenderer = new TextRenderer();
Expand All @@ -46,16 +49,15 @@ public FluidSlot() {
flex().startDefaultMode()
.size(18, 18)
.endDefaultMode();

tooltip().setAutoUpdate(true).setHasTitleMargin(true);
tooltipBuilder(tooltip -> {
tooltip.setHasTitleMargin(true);
IFluidTank fluidTank = getFluidTank();
FluidStack fluid = this.syncHandler.getValue();
if (this.syncHandler.isPhantom()) {
if (fluid != null) {
tooltip.addLine(IKey.str(fluid.getLocalizedName()));
if (this.syncHandler.controlsAmount()) {
tooltip.addLine(IKey.format("modularui.fluid.phantom.amount", fluid.amount));
tooltip.addLine(IKey.format("modularui.fluid.phantom.amount", formatFluidAmount(fluid.amount), getBaseUnit()));
}
} else {
tooltip.addLine(IKey.format("modularui.fluid.empty"));
Expand All @@ -66,7 +68,7 @@ public FluidSlot() {
} else {
if (fluid != null) {
tooltip.addLine(IKey.str(fluid.getLocalizedName()));
tooltip.addLine(IKey.format("modularui.fluid.amount", fluid.amount, fluidTank.getCapacity()));
tooltip.addLine(IKey.format("modularui.fluid.amount", formatFluidAmount(fluid.amount), formatFluidAmount(fluidTank.getCapacity()), getBaseUnit()));
addAdditionalFluidInfo(tooltip, fluid);
} else {
tooltip.addLine(IKey.format("modularui.fluid.empty"));
Expand All @@ -92,6 +94,19 @@ public FluidSlot() {
public void addAdditionalFluidInfo(Tooltip tooltip, FluidStack fluidStack) {
}

public String formatFluidAmount(double amount) {
NumberFormat.FORMAT.setMaximumFractionDigits(3);
return NumberFormat.FORMAT.format(getBaseUnitAmount(amount));
}

protected double getBaseUnitAmount(double amount) {
return amount / 1000;
}

protected String getBaseUnit() {
return UNIT_BUCKET;
}

@Override
public void onInit() {
this.textRenderer.setShadow(true);
Expand Down Expand Up @@ -127,7 +142,7 @@ public void draw(GuiContext context, WidgetTheme widgetTheme) {
this.overlayTexture.draw(context, getArea());
}
if (content != null && this.syncHandler.controlsAmount()) {
String s = NumberFormat.format(content.amount);
String s = NumberFormat.formatWithMaxDigits(getBaseUnitAmount(content.amount)) + getBaseUnit();
this.textRenderer.setAlignment(Alignment.CenterRight, getArea().width - this.contentOffsetX - 1f);
this.textRenderer.setPos((int) (this.contentOffsetX + 0.5f), (int) (getArea().height - 5.5f));
this.textRenderer.draw(s);
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/cleanroommc/modularui/widgets/ItemSlot.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ public class ItemSlot extends Widget<ItemSlot> implements IVanillaSlot, Interact
private ItemSlotSH syncHandler;

public ItemSlot() {
tooltip().setAutoUpdate(true).setHasTitleMargin(true);
tooltipBuilder(tooltip -> {
tooltip.setAutoUpdate(true).setHasTitleMargin(true);
tooltip.excludeArea(getArea());
if (!isSynced()) return;
ItemStack stack = getSlot().getStack();
Expand Down Expand Up @@ -218,7 +218,7 @@ private void drawSlot(Slot slotIn) {
}
// render the amount overlay
if (amount > 1 || format != null) {
String amountText = NumberFormat.format(amount, 2);
String amountText = NumberFormat.formatWithMaxDigits(amount);
if (format != null) {
amountText = format + amountText;
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/assets/modularui/lang/en_us.lang
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ modularui.increment.tooltip=§7Click to increase the number by §6%d§7\nHold sh
modularui.decrement.tooltip=§7Click to decrease the number by §6%d§7\nHold shift[§6%d§7], ctrl[§6%d§7] or shift+ctrl[§6%d§7]
modularui.amount=§9Amount: %,d
modularui.fluid.empty=Empty
modularui.fluid.amount=§9Amount: %,d/%,d L
modularui.fluid.phantom.amount=§9Amount: %,d L
modularui.fluid.amount=§9Amount: %s/%s %s
modularui.fluid.phantom.amount=§9Amount: %s %s
modularui.fluid.phantom.control=§7Scroll wheel up increases amount, down decreases.\n§7Shift[§6x10§7],Ctrl[§ex100§7],Alt[§ax1000§7]\n§7Right click increases amount, left click decreases.\n§7Shift + left click to clear.
modularui.item.phantom.control=§7Scroll wheel up increases amount, down decreases.\n§7Shift[§6x4§7],Ctrl[§ex16§7],Alt[§ax64§7]\n§7Right click increases amount, left click decreases.\n§7Shift + left click to clear.

Expand Down

0 comments on commit 8867324

Please sign in to comment.