wasteland/modtools/src/main/java/me/jamestmartin/wasteland/modtools/infraction/Duration.java

174 lines
5.0 KiB
Java

package me.jamestmartin.wasteland.modtools.infraction;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class Duration implements Comparable<Duration> {
public static final Duration ZERO = new Duration(0);
public static final Duration INFINITY = new Duration();
/** Durations of "none" are infinite. */
private final Optional<Long> seconds;
private Duration() {
this.seconds = Optional.empty();
}
private Duration(Optional<Long> seconds) {
this.seconds = seconds;
}
public Duration(long seconds) {
this.seconds = Optional.of(seconds);
}
public Optional<Long> getSeconds() {
return seconds;
}
public Duration max(Duration other) {
return new Duration(this.seconds.flatMap(x -> other.seconds.map(y -> Math.max(x, y))));
}
public static Optional<Duration> parse(String str) {
if (str.equals("0")) {
return Optional.of(ZERO);
}
if (str.equals("forever")) {
return Optional.of(INFINITY);
}
return DurationParts.parse(str).map(DurationParts::toDuration);
}
private Optional<DurationParts> toParts() {
if (seconds.isEmpty()) {
return Optional.empty();
}
long secs = seconds.get();
// Find the greatest prefix that gives an exact value.
List<DurationSuffix> suffixes = List.of(DurationSuffix.values());
Collections.reverse(suffixes);
DurationSuffix s = null;
for (DurationSuffix suffix : suffixes) {
if (secs % suffix.getSeconds() == 0) {
s = suffix;
}
}
return Optional.of(new DurationParts(secs / s.getSeconds(), s));
}
@Override
public String toString() {
return toParts().map(DurationParts::toString).orElse("forever");
}
public String toStringLong() {
return toParts().map(DurationParts::toStringLong).orElse("forever");
}
private static class DurationParts {
public final long value;
public final DurationSuffix suffix;
public DurationParts(long value, DurationSuffix suffix) {
this.value = value;
this.suffix = suffix;
}
public Duration toDuration() {
return new Duration(value * suffix.getSeconds());
}
@Override
public String toString() {
return value + suffix.toString();
}
public String toStringLong() {
return value + " " + suffix.toStingLong();
}
public static Optional<DurationParts> parse(String str) {
if (str.length() < 2) {
return Optional.empty();
}
Optional<DurationSuffix> suffix = DurationSuffix.fromChar(str.charAt(str.length() - 1));
if (suffix.isEmpty()) {
return Optional.empty();
}
String valueStr = str.substring(0, str.length() - 1);
if (!valueStr.matches("\\d+")) {
return Optional.empty();
}
return Optional.of(new DurationParts(Long.parseLong(valueStr), suffix.get()));
}
}
private static enum DurationSuffix {
SECONDS('s', "seconds", 1),
MINUTES('m', "minutes", 60),
HOURS('h', "hours", 3600),
DAYS('d', "days", 86400),
WEEKS('w', "weeks", 604800),
MONTHS('M', "months", 2628000),
YEARS('y', "years", 31540000);
private final char character;
private final String longName;
private final long seconds;
private DurationSuffix(char character, String longName, long seconds) {
this.character = character;
this.longName = longName;
this.seconds = seconds;
}
public long getSeconds() {
return seconds;
}
public char toChar() {
return character;
}
@Override
public String toString() {
return String.valueOf(toChar());
}
public String toStingLong() {
return longName;
}
public static Optional<DurationSuffix> fromChar(char c) {
for (DurationSuffix suffix : DurationSuffix.values()) {
if (suffix.character == c) {
return Optional.of(suffix);
}
}
return Optional.empty();
}
}
@Override
public int compareTo(Duration other) {
if (getSeconds().isEmpty() && other.getSeconds().isEmpty()) {
return 0;
}
if (getSeconds().isEmpty()) {
return 1;
}
if (other.getSeconds().isEmpty()) {
return -1;
}
return Long.compare(getSeconds().get(), other.getSeconds().get());
}
}