org.lanternpowered.server.statistic.StatisticNumberFormats.java Source code

Java tutorial

Introduction

Here is the source code for org.lanternpowered.server.statistic.StatisticNumberFormats.java

Source

/*
 * This file is part of LanternServer, licensed under the MIT License (MIT).
 *
 * Copyright (c) LanternPowered <https://www.lanternpowered.org>
 * Copyright (c) SpongePowered <https://www.spongepowered.org>
 * Copyright (c) contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the Software), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.lanternpowered.server.statistic;

import com.google.common.base.Throwables;
import org.apache.commons.lang3.StringUtils;
import org.lanternpowered.server.util.functions.Long2ObjectFunction;
import org.lanternpowered.server.util.functions.Object2LongThrowableFunction;

import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.Locale;

/**
 * An enumeration of all the statistic formats in vanilla minecraft.
 */
public final class StatisticNumberFormats {

    private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("########0.00");

    /**
     * A statistic without a format.
     */
    public static NumberFormat COUNT = NumberFormat.getIntegerInstance();

    /**
     * A statistic measured in centimeters, meters, or kilometers depending on
     * the magnitude. The input is taken as centimeters with a scale of 1 block
     * equaling 1 meter.
     */
    public static NumberFormat DISTANCE = of(value -> {
        if (value <= 50) {
            return value + " cm";
        }
        final double meters = (double) value / 100.0;
        if (meters <= 500) {
            return DECIMAL_FORMAT.format(meters) + " m";
        }
        return DECIMAL_FORMAT.format(meters / 1000.0) + " km";
    }, object -> {
        object = StringUtils.normalizeSpace(object);
        final int index = object.lastIndexOf(' ');
        final String type = object.substring(index + 1).toLowerCase(Locale.ENGLISH);
        final Number value = DECIMAL_FORMAT.parse(object.substring(0, index));
        switch (type) {
        case "cm":
            return value.longValue();
        case "km":
            return (long) (value.doubleValue() * 100000.0);
        case "m":
            return (long) (value.doubleValue() * 100.0);
        default:
            throw new IllegalArgumentException("Invalid distance formatted string: " + object);
        }
    });

    /**
     * A statistic measured in 0.1 steps.
     */
    public static NumberFormat FRACTIONAL = of(value -> DECIMAL_FORMAT.format((double) value * 0.1),
            object -> (long) (DECIMAL_FORMAT.parse(object).doubleValue() / 0.1));

    /**
     * A statistic measured in seconds, minutes, hours, or days depending on the
     * magnitude. The input is taken as ticks with 20 ticks equaling one second.
     */
    public static NumberFormat TIME = of(value -> {
        final double seconds = (double) value / 20.0;
        if (seconds <= 30) {
            return DECIMAL_FORMAT.format(seconds) + " s";
        }
        final double minutes = seconds / 60.0;
        if (minutes <= 30) {
            return DECIMAL_FORMAT.format(minutes) + " m";
        }
        final double hours = seconds / 60.0;
        if (hours <= 12) {
            return DECIMAL_FORMAT.format(hours) + " h";
        }
        final double days = seconds / 24.0;
        if (days <= 183) {
            return DECIMAL_FORMAT.format(days) + " d";
        }
        return DECIMAL_FORMAT.format(days / 365.0) + " y";
    }, object -> {
        object = StringUtils.normalizeSpace(object);
        final int index = object.lastIndexOf(' ');
        final String type = object.substring(index + 1).toLowerCase(Locale.ENGLISH);
        final double value = DECIMAL_FORMAT.parse(object.substring(0, index)).doubleValue();
        switch (type) {
        case "s":
            return (long) (value * 20.0);
        case "m":
            return (long) (value * 1200.0);
        case "h":
            return (long) (value * 72000.0);
        case "d":
            return (long) (value * 1728000.0);
        case "y":
            return (long) (value * 630720000.0);
        default:
            throw new IllegalArgumentException("Invalid distance formatted string: " + object);
        }
    });

    /**
     * Creates a new {@link NumberFormat} with the specified formatter function.
     *
     * @param formatter The formatter
     * @return The number format
     */
    public static NumberFormat of(Long2ObjectFunction<String> formatter,
            Object2LongThrowableFunction<String, ParseException> parser) {
        return new NumberFormat() {
            @Override
            public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
                return format((long) number, toAppendTo, pos);
            }

            @Override
            public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
                return toAppendTo.append(formatter.apply(number));
            }

            @Override
            public Number parse(String source, ParsePosition parsePosition) {
                try {
                    return parser.apply(source);
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                }
            }
        };
    }

    private StatisticNumberFormats() {
    }
}