Adds most of the code necessary for #11
This commit is contained in:
@ -0,0 +1,126 @@
|
||||
package net.knarcraft.blacksmith.formatting;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.knarcraft.blacksmith.formatting.StringFormatter.replacePlaceholder;
|
||||
|
||||
/**
|
||||
* A utility for formatting a string specifying an amount of time
|
||||
*/
|
||||
public final class TimeFormatter {
|
||||
|
||||
private static Map<Double, TranslatableMessage[]> timeUnits;
|
||||
private static List<Double> sortedUnits;
|
||||
|
||||
private TimeFormatter() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the given number of remaining seconds to the appropriate string
|
||||
*
|
||||
* @param exact <p>Whether to display the exact number of seconds, or some unclear expression</p>
|
||||
* @param seconds <p>The number of seconds remaining</p>
|
||||
* @return <p>The time formatted correctly</p>
|
||||
*/
|
||||
public static String formatTime(boolean exact, int seconds) {
|
||||
if (exact) {
|
||||
return getDurationString(seconds);
|
||||
} else {
|
||||
return formatUnclearTime(seconds);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a time format using vague wording to specify a known interval
|
||||
*
|
||||
* @param seconds <p>The number of seconds to format</p>
|
||||
* @return <p>Text describing approximate time remaining</p>
|
||||
*/
|
||||
private static String formatUnclearTime(int seconds) {
|
||||
List<TimeInterval> intervals = Arrays.stream(TimeInterval.values()).sorted().toList();
|
||||
for (TimeInterval interval : intervals) {
|
||||
if (seconds < interval.getIntervalMax()) {
|
||||
//Use the set message, or use the default
|
||||
//TODO: Check for commas in the message. If present, split on the comma and choose a random expression
|
||||
String text = Translator.getTranslatedMessage(TranslatableMessage.valueOf(interval.name()));
|
||||
if (text != null && !text.trim().isEmpty()) {
|
||||
return text;
|
||||
} else {
|
||||
return interval.getDefaultText();
|
||||
}
|
||||
}
|
||||
}
|
||||
return TimeInterval.INTERVAL_MORE_THAN_5_MINUTES.getDefaultText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string used for displaying this sign's duration
|
||||
*
|
||||
* @return <p>The string used for displaying this sign's duration</p>
|
||||
*/
|
||||
public static String getDurationString(int duration) {
|
||||
if (duration == 0) {
|
||||
return Translator.getTranslatedMessage(TranslatableMessage.UNIT_NOW);
|
||||
} else {
|
||||
if (sortedUnits == null) {
|
||||
initializeUnits();
|
||||
}
|
||||
for (Double unit : sortedUnits) {
|
||||
if (duration / unit >= 1) {
|
||||
double units = round(duration / unit);
|
||||
return formatDurationString(units, timeUnits.get(unit)[units == 1 ? 0 : 1],
|
||||
(units * 10) % 10 == 0);
|
||||
}
|
||||
}
|
||||
return formatDurationString(duration, TranslatableMessage.UNIT_SECONDS, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds a number to its last two digits
|
||||
*
|
||||
* @param number <p>The number to round</p>
|
||||
* @return <p>The rounded number</p>
|
||||
*/
|
||||
private static double round(double number) {
|
||||
return Math.round(number * 100.0) / 100.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a duration string
|
||||
*
|
||||
* @param duration <p>The duration to display</p>
|
||||
* @param translatableMessage <p>The time unit to display</p>
|
||||
* @param castToInt <p>Whether to cast the duration to an int</p>
|
||||
* @return <p>The formatted duration string</p>
|
||||
*/
|
||||
private static String formatDurationString(double duration, TranslatableMessage translatableMessage, boolean castToInt) {
|
||||
String durationFormat = Translator.getTranslatedMessage(TranslatableMessage.DURATION_FORMAT);
|
||||
durationFormat = replacePlaceholder(durationFormat, "{unit}",
|
||||
Translator.getTranslatedMessage(translatableMessage));
|
||||
return replacePlaceholder(durationFormat, "{duration}", castToInt ? String.valueOf((int) duration) :
|
||||
String.valueOf(duration));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the mapping of available time units for formatting permission sign duration
|
||||
*/
|
||||
private static void initializeUnits() {
|
||||
double minute = 60;
|
||||
|
||||
timeUnits = new HashMap<>();
|
||||
timeUnits.put(minute, new TranslatableMessage[]{TranslatableMessage.UNIT_MINUTE, TranslatableMessage.UNIT_MINUTES});
|
||||
timeUnits.put(1D, new TranslatableMessage[]{TranslatableMessage.UNIT_SECOND, TranslatableMessage.UNIT_SECONDS});
|
||||
|
||||
sortedUnits = new ArrayList<>(timeUnits.keySet());
|
||||
Collections.sort(sortedUnits);
|
||||
Collections.reverse(sortedUnits);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package net.knarcraft.blacksmith.formatting;
|
||||
|
||||
/**
|
||||
* The important intervals when not using exact wait times
|
||||
*/
|
||||
public enum TimeInterval {
|
||||
|
||||
/**
|
||||
* Less than 10 seconds left
|
||||
*/
|
||||
INTERVAL_LESS_THAN_10_SECONDS("momentarily", 10),
|
||||
|
||||
/**
|
||||
* Less than 30 seconds left
|
||||
*/
|
||||
INTERVAL_LESS_THAN_30_SECONDS("in a little while", 30),
|
||||
|
||||
/**
|
||||
* Less than 1 minute left
|
||||
*/
|
||||
INTERVAL_LESS_THAN_1_MINUTE("in a while", 60),
|
||||
|
||||
/**
|
||||
* Less than 5 minutes left
|
||||
*/
|
||||
INTERVAL_LESS_THAN_5_MINUTES("after some time", 300),
|
||||
|
||||
/**
|
||||
* More than 5 minutes left
|
||||
*/
|
||||
INTERVAL_MORE_THAN_5_MINUTES("in quite a while", Integer.MAX_VALUE);
|
||||
|
||||
private final String defaultText;
|
||||
private final int maxSeconds;
|
||||
|
||||
/**
|
||||
* Instantiates a new time interval
|
||||
*
|
||||
* @param defaultText <p>The default text used to describe the time interval</p>
|
||||
* @param maxSeconds <p>The maximum number of seconds to fall within this interval</p>
|
||||
*/
|
||||
TimeInterval(String defaultText, int maxSeconds) {
|
||||
this.defaultText = defaultText;
|
||||
this.maxSeconds = maxSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default text to display for this interval
|
||||
*
|
||||
* @return <p>The default text to display for this interval</p>
|
||||
*/
|
||||
public String getDefaultText() {
|
||||
return this.defaultText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum number of seconds before exceeding this interval
|
||||
*
|
||||
* @return <p>The max seconds of this interval</p>
|
||||
*/
|
||||
public int getIntervalMax() {
|
||||
return maxSeconds;
|
||||
}
|
||||
|
||||
}
|
@ -10,25 +10,155 @@ import static net.knarcraft.blacksmith.formatting.StringFormatter.replacePlaceho
|
||||
*/
|
||||
public enum TranslatableMessage {
|
||||
|
||||
/**
|
||||
* The message displayed when a configuration value has been successfully changed
|
||||
*/
|
||||
VALUE_CHANGED,
|
||||
|
||||
/**
|
||||
* The message displayed when a configuration value for one material or enchantment has been successfully changed
|
||||
*/
|
||||
VALUE_FOR_ITEM_CHANGED,
|
||||
|
||||
/**
|
||||
* The message displayed when showing the current value of a configuration option
|
||||
*/
|
||||
CURRENT_VALUE,
|
||||
|
||||
/**
|
||||
* The message displayed when showing the current value of a configuration option for one material or enchantment
|
||||
*/
|
||||
CURRENT_VALUE_FOR_ITEM,
|
||||
|
||||
/**
|
||||
* The translation of enchantment
|
||||
*/
|
||||
ITEM_TYPE_ENCHANTMENT,
|
||||
|
||||
/**
|
||||
* The translation of material
|
||||
*/
|
||||
ITEM_TYPE_MATERIAL,
|
||||
|
||||
/**
|
||||
* The message displayed when showing the "raw" value of messages
|
||||
*/
|
||||
RAW_VALUE,
|
||||
|
||||
/**
|
||||
* The message displayed when trying to change a blacksmith value before selecting a blacksmith
|
||||
*/
|
||||
NO_NPC_SELECTED,
|
||||
|
||||
/**
|
||||
* The message displayed if trying to change the default value of reforge-able item using commands
|
||||
*/
|
||||
DEFAULT_REFORGE_ABLE_ITEMS_UNCHANGEABLE,
|
||||
|
||||
/**
|
||||
* The message displayed if a string list is required, but something else is given
|
||||
*/
|
||||
INPUT_STRING_LIST_REQUIRED,
|
||||
|
||||
/**
|
||||
* The message displayed if a value between 0 and 100 is required, but something else is given
|
||||
*/
|
||||
INPUT_PERCENTAGE_REQUIRED,
|
||||
|
||||
/**
|
||||
* The message displayed if a string is required, but something else is given
|
||||
*/
|
||||
INPUT_STRING_REQUIRED,
|
||||
|
||||
/**
|
||||
* The message displayed if a positive double is required, but something else is given
|
||||
*/
|
||||
INPUT_POSITIVE_DOUBLE_REQUIRED,
|
||||
|
||||
/**
|
||||
* The message displayed if a positive integer is required, but something else is given
|
||||
*/
|
||||
INPUT_POSITIVE_INTEGER_REQUIRED,
|
||||
|
||||
/**
|
||||
* The message displayed if a player is missing the required permission for an action
|
||||
*/
|
||||
PERMISSION_DENIED,
|
||||
|
||||
/**
|
||||
* The message displayed if this plugin is successfully reloaded
|
||||
*/
|
||||
PLUGIN_RELOADED,
|
||||
|
||||
/**
|
||||
* The message displayed if a filter is specified which isn't supported by the specified preset
|
||||
*/
|
||||
INVALID_FILTER_FOR_PRESET,
|
||||
|
||||
/**
|
||||
* The message displayed if an invalid preset or an invalid filter is specified
|
||||
*/
|
||||
INVALID_PRESET_OR_FILTER,
|
||||
PRESET_MATERIALS;
|
||||
|
||||
/**
|
||||
* The message displayed when showing which materials are included in a preset
|
||||
*/
|
||||
PRESET_MATERIALS,
|
||||
|
||||
/**
|
||||
* The format for displaying the exact duration of a blacksmith's cool-down or delay
|
||||
*/
|
||||
DURATION_FORMAT,
|
||||
|
||||
/**
|
||||
* The text to display for 0 seconds
|
||||
*/
|
||||
UNIT_NOW,
|
||||
|
||||
/**
|
||||
* The text to display for 1 second
|
||||
*/
|
||||
UNIT_SECOND,
|
||||
|
||||
/**
|
||||
* The text to display for a number of seconds
|
||||
*/
|
||||
UNIT_SECONDS,
|
||||
|
||||
/**
|
||||
* The text to display for 1 minute
|
||||
*/
|
||||
UNIT_MINUTE,
|
||||
|
||||
/**
|
||||
* The text to display for a number of minutes
|
||||
*/
|
||||
UNIT_MINUTES,
|
||||
|
||||
/**
|
||||
* The text to display when describing less than 10 seconds remaining
|
||||
*/
|
||||
INTERVAL_LESS_THAN_10_SECONDS,
|
||||
|
||||
/**
|
||||
* The text to display when describing less than 30 seconds remaining
|
||||
*/
|
||||
INTERVAL_LESS_THAN_30_SECONDS,
|
||||
|
||||
/**
|
||||
* The text to display when describing less than 1 minute remaining
|
||||
*/
|
||||
INTERVAL_LESS_THAN_1_MINUTE,
|
||||
|
||||
/**
|
||||
* The text to display when describing less than 5 minutes remaining
|
||||
*/
|
||||
INTERVAL_LESS_THAN_5_MINUTES,
|
||||
|
||||
/**
|
||||
* The text to display when describing more than 5 minutes remaining
|
||||
*/
|
||||
INTERVAL_MORE_THAN_5_MINUTES;
|
||||
|
||||
/**
|
||||
* Gets the message to display when displaying the raw value of messages
|
||||
|
Reference in New Issue
Block a user