update number formatter

This commit is contained in:
Lee 2024-06-30 07:34:03 +01:00
parent 5aa56c2955
commit 729e0b482b
9 changed files with 107 additions and 57 deletions

@ -4,7 +4,7 @@ import cc.fascinated.bat.Emojis;
import cc.fascinated.bat.command.BatCommand; import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.NumberUtils; import cc.fascinated.bat.common.NumberFormatter;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.model.BatUser;
import lombok.NonNull; import lombok.NonNull;
@ -52,17 +52,17 @@ public class MemberCountCommand extends BatCommand {
%s Idle: `%s` %s Idle: `%s`
%s Do Not Disturb: `%s` %s Do Not Disturb: `%s`
%s Offline: `%s`""".formatted( %s Offline: `%s`""".formatted(
NumberUtils.formatNumberCommas(totalMembers), NumberFormatter.format(totalMembers),
NumberUtils.formatNumberCommas(totalUsers), NumberFormatter.format(totalUsers),
NumberUtils.formatNumberCommas(totalBots), NumberFormatter.format(totalBots),
Emojis.ONLINE_EMOJI, Emojis.ONLINE_EMOJI,
NumberUtils.formatNumberCommas(memberCounts.getOrDefault(OnlineStatus.ONLINE, 0)), NumberFormatter.format(memberCounts.getOrDefault(OnlineStatus.ONLINE, 0)),
Emojis.IDLE_EMOJI, Emojis.IDLE_EMOJI,
NumberUtils.formatNumberCommas(memberCounts.getOrDefault(OnlineStatus.IDLE, 0)), NumberFormatter.format(memberCounts.getOrDefault(OnlineStatus.IDLE, 0)),
Emojis.DND_EMOJI, Emojis.DND_EMOJI,
NumberUtils.formatNumberCommas(memberCounts.getOrDefault(OnlineStatus.DO_NOT_DISTURB, 0)), NumberFormatter.format(memberCounts.getOrDefault(OnlineStatus.DO_NOT_DISTURB, 0)),
Emojis.OFFLINE_EMOJI, Emojis.OFFLINE_EMOJI,
NumberUtils.formatNumberCommas(memberCounts.getOrDefault(OnlineStatus.OFFLINE, 0)))); NumberFormatter.format(memberCounts.getOrDefault(OnlineStatus.OFFLINE, 0))));
interaction.replyEmbeds(embed.build()).queue(); interaction.replyEmbeds(embed.build()).queue();
} }
} }

@ -0,0 +1,83 @@
package cc.fascinated.bat.common;
import java.text.DecimalFormat;
import java.util.Locale;
/**
* @author Fascinated (fascinated7)
*/
public class NumberFormatter {
/**
* The suffixes for the numbers
*/
private static final String[] SUFFIXES = new String[] { "K", "M", "B", "T", "Q", "QT", "S", "SP", "O", "N", "D", "UD", "DD", "TD" };
private static final DecimalFormat FORMAT = new DecimalFormat("###.##");
/**
* Format the provided double
*
* @param input the value to format
* @return the formatted double, in the format of xx.xx[suffix]
*/
public static String format(double input) {
if (Double.isNaN(input)) {
return "ERROR";
}
if (Double.isInfinite(input) || input == Double.MAX_VALUE) {
return "";
}
if (1000 > input) {
return FORMAT.format(input);
}
double power = (int) Math.log10(input);
int index = (int) Math.floor(power / 3) - 1;
double factor = input / Math.pow(10, 3 + index * 3);
if (index >= SUFFIXES.length) {
return "ERROR";
}
return FORMAT.format(factor) + SUFFIXES[index];
}
/**
* Format the provided double with commas
*
* @param input the value to format
* @return the formatted double, in the format of xx,xxx,xxx
*/
public static String formatCommas(double input) {
return String.format("%,.0f", input);
}
/**
* Turns a provided string into a double, for example 1M -> 1000000.00
* Accepts decimal and negative values and is not case-sensitive
*
* @param input the string to convert
* @return the value the string represents
*/
public static double fromString(String input) {
if ((input = input.trim()).isEmpty()) {
return -1D;
}
try {
double value = Double.parseDouble(input); // parse pure numbers
if (Double.isNaN(value) || Double.isInfinite(value)) {
return -1;
}
return value;
} catch (NumberFormatException ignored) {
input = input.toUpperCase(Locale.UK);
for (int i = SUFFIXES.length - 1; i > 0; i--) {
String suffix = SUFFIXES[i];
if (!input.endsWith(suffix)) {
continue;
}
String amount = input.substring(0, input.length() - suffix.length());
if (!amount.isEmpty()) {
return Double.parseDouble(amount) * Math.pow(10, 3 + i * 3);
}
}
}
return -1;
}
}

@ -1,27 +0,0 @@
package cc.fascinated.bat.common;
import lombok.experimental.UtilityClass;
import java.text.NumberFormat;
/**
* @author Fascinated (fascinated7)
*/
@UtilityClass
public class NumberUtils {
/**
* Formats a number with commas.
* <p>
* Example: 1000 -> 1,000 | Example: 1000.5 -> 1,000.5
* </p>
*
* @param number the number to format
* @return the formatted number
*/
public static String formatNumberCommas(double number) {
NumberFormat format = NumberFormat.getNumberInstance();
format.setGroupingUsed(true);
format.setMaximumFractionDigits(2);
return format.format(number);
}
}

@ -8,14 +8,10 @@ import cc.fascinated.bat.features.FeatureProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.model.BatUser;
import cc.fascinated.bat.service.FeatureService; import cc.fascinated.bat.service.FeatureService;
import cc.fascinated.bat.service.GuildService;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**

@ -1,6 +1,6 @@
package cc.fascinated.bat.features.scoresaber; package cc.fascinated.bat.features.scoresaber;
import cc.fascinated.bat.common.NumberUtils; import cc.fascinated.bat.common.NumberFormatter;
import cc.fascinated.bat.event.EventListener; import cc.fascinated.bat.event.EventListener;
import cc.fascinated.bat.features.scoresaber.profile.guild.NumberOneScoreFeedProfile; import cc.fascinated.bat.features.scoresaber.profile.guild.NumberOneScoreFeedProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
@ -41,7 +41,7 @@ public class NumberOneScoreFeedListener implements EventListener {
log.info("A new #1 score has been set by {} on {} ({})!", log.info("A new #1 score has been set by {} on {} ({})!",
player.getName(), player.getName(),
leaderboard.getSongName(), leaderboard.getSongName(),
"%s⭐".formatted(NumberUtils.formatNumberCommas(leaderboard.getStars())) "%s⭐".formatted(NumberFormatter.formatCommas(leaderboard.getStars()))
); );
for (Guild guild : DiscordService.JDA.getGuilds()) { for (Guild guild : DiscordService.JDA.getGuilds()) {

@ -3,7 +3,7 @@ package cc.fascinated.bat.features.scoresaber;
import cc.fascinated.bat.command.Category; import cc.fascinated.bat.command.Category;
import cc.fascinated.bat.common.DateUtils; import cc.fascinated.bat.common.DateUtils;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.NumberUtils; import cc.fascinated.bat.common.NumberFormatter;
import cc.fascinated.bat.common.ScoreSaberUtils; import cc.fascinated.bat.common.ScoreSaberUtils;
import cc.fascinated.bat.features.Feature; import cc.fascinated.bat.features.Feature;
import cc.fascinated.bat.features.scoresaber.command.numberone.NumberOneFeedCommand; import cc.fascinated.bat.features.scoresaber.command.numberone.NumberOneFeedCommand;
@ -55,10 +55,10 @@ public class ScoreSaberFeature extends Feature {
); );
String accuracy = leaderboardToken.getMaxScore() == 0 ? "N/A" : String accuracy = leaderboardToken.getMaxScore() == 0 ? "N/A" :
String.format("%s%%", NumberUtils.formatNumberCommas(((double) scoreToken.getBaseScore() / leaderboardToken.getMaxScore()) * 100)); String.format("%s%%", NumberFormatter.formatCommas(((double) scoreToken.getBaseScore() / leaderboardToken.getMaxScore()) * 100));
String rawPp = scoreToken.getPp() == 0 ? "Unranked" : NumberUtils.formatNumberCommas(scoreToken.getPp()); String rawPp = scoreToken.getPp() == 0 ? "Unranked" : NumberFormatter.formatCommas(scoreToken.getPp());
String rank = String.format("#%s", NumberUtils.formatNumberCommas(scoreToken.getRank())); String rank = String.format("#%s", NumberFormatter.formatCommas(scoreToken.getRank()));
String misses = String.format("%s", scoreToken.getMissedNotes()); String misses = String.format("%s", scoreToken.getMissedNotes());
String badCuts = String.format("%s", scoreToken.getBadCuts()); String badCuts = String.format("%s", scoreToken.getBadCuts());
String maxCombo = String.format("%s %s", String maxCombo = String.format("%s %s",

@ -5,7 +5,7 @@ import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.Colors; import cc.fascinated.bat.common.Colors;
import cc.fascinated.bat.common.DateUtils; import cc.fascinated.bat.common.DateUtils;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.common.NumberUtils; import cc.fascinated.bat.common.NumberFormatter;
import cc.fascinated.bat.exception.RateLimitException; import cc.fascinated.bat.exception.RateLimitException;
import cc.fascinated.bat.features.scoresaber.profile.user.ScoreSaberProfile; import cc.fascinated.bat.features.scoresaber.profile.user.ScoreSaberProfile;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
@ -84,9 +84,9 @@ public class ScoreSaberCommand extends BatCommand {
"https://cdn.scoresaber.com/avatars/%s.jpg".formatted(account.getId())) "https://cdn.scoresaber.com/avatars/%s.jpg".formatted(account.getId()))
.addField("Name", account.getName(), true) .addField("Name", account.getName(), true)
.addField("Country", account.getCountry(), true) .addField("Country", account.getCountry(), true)
.addField("Rank", "#" + NumberUtils.formatNumberCommas(account.getRank()), true) .addField("Rank", "#" + NumberFormatter.formatCommas(account.getRank()), true)
.addField("Country Rank", "#" + NumberUtils.formatNumberCommas(account.getCountryRank()), true) .addField("Country Rank", "#" + NumberFormatter.formatCommas(account.getCountryRank()), true)
.addField("PP", NumberUtils.formatNumberCommas(account.getPp()), true) .addField("PP", NumberFormatter.formatCommas(account.getPp()), true)
.addField("Joined", "<t:%s>".formatted(DateUtils.getDateFromString(account.getFirstSeen()).toInstant().toEpochMilli() / 1000), true) .addField("Joined", "<t:%s>".formatted(DateUtils.getDateFromString(account.getFirstSeen()).toInstant().toEpochMilli() / 1000), true)
.setTimestamp(LocalDateTime.now()) .setTimestamp(LocalDateTime.now())
.setFooter(fetchTime > 3 ? "Fetched in %sms".formatted(fetchTime) : "Cached", "https://flagcdn.com/h120/%s.png".formatted(account.getCountry().toLowerCase())) .setFooter(fetchTime > 3 ? "Fetched in %sms".formatted(fetchTime) : "Cached", "https://flagcdn.com/h120/%s.png".formatted(account.getCountry().toLowerCase()))

@ -1,5 +1,6 @@
package cc.fascinated.bat.service; package cc.fascinated.bat.service;
import cc.fascinated.bat.common.NumberFormatter;
import cc.fascinated.bat.common.TimerUtils; import cc.fascinated.bat.common.TimerUtils;
import lombok.Getter; import lombok.Getter;
import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDA;
@ -26,10 +27,9 @@ public class DiscordService {
public static JDA JDA; public static JDA JDA;
private final List<String> messages = List.of( private final List<String> messages = List.of(
"over {guilds} guilds", "{guilds} guilds",
"over {users} users", "{users} users",
"over ScoreSaber scores", "your ScoreSaber scores",
"your messages",
"/help for help" "/help for help"
); );
@ -60,8 +60,8 @@ public class DiscordService {
public void updateActivity() { public void updateActivity() {
int guildCount = JDA.getGuilds().size(); int guildCount = JDA.getGuilds().size();
JDA.getPresence().setActivity(Activity.watching(messages.get(guildCount % messages.size()) JDA.getPresence().setActivity(Activity.watching(messages.get(guildCount % messages.size())
.replace("{guilds}", String.valueOf(guildCount)) .replace("{guilds}", NumberFormatter.format(guildCount))
.replace("{users}", String.valueOf(JDA.getUsers().size())) .replace("{users}", NumberFormatter.format(JDA.getUsers().size()))
)); ));
} }
} }

@ -12,9 +12,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**