package de.invesdwin.util.math.decimal.scaled;
import java.nio.ByteBuffer;
import javax.annotation.concurrent.Immutable;
import de.invesdwin.util.math.decimal.ADecimal;
import de.invesdwin.util.math.decimal.AScaledDecimal;
import de.invesdwin.util.math.decimal.Decimal;
import de.invesdwin.util.time.duration.Duration;
import de.invesdwin.util.time.fdate.FTimeUnit;
@SuppressWarnings("serial")
@Immutable
public class Percent extends AScaledDecimal<Percent, PercentScale> implements IPercentData {
public static final PercentScale DEFAULT_SCALE;
public static final Percent THREE_HUNDRED_PERCENT;
public static final Percent TWO_HUNDRED_PERCENT;
public static final Percent ONE_HUNDRED_PERCENT;
public static final Percent NINETY_PERCENT;
public static final Percent SEVENTYFIVE_PERCENT;
public static final Percent FIFTY_PERCENT;
public static final Percent TWENTYFIVE_PERCENT;
public static final Percent TEN_PERCENT;
public static final Percent FIVE_PERCENT;
public static final Percent TWO_PERCENT;
public static final Percent ONE_PERCENT;
public static final Percent ZERO_PERCENT;
public static final Percent MINUS_ONE_PERCENT;
public static final Percent MINUS_TWO_PERCENT;
public static final Percent MINUS_FIVE_PERCENT;
public static final Percent MINUS_TEN_PERCENT;
static {
DEFAULT_SCALE = PercentScale.RATE;
THREE_HUNDRED_PERCENT = new Percent(Decimal.THREE, PercentScale.RATE);
TWO_HUNDRED_PERCENT = new Percent(Decimal.TWO, PercentScale.RATE);
ONE_HUNDRED_PERCENT = new Percent(Decimal.ONE, PercentScale.RATE);
NINETY_PERCENT = new Percent(new Decimal("90"), PercentScale.PERCENT);
SEVENTYFIVE_PERCENT = new Percent(new Decimal("75"), PercentScale.PERCENT);
FIFTY_PERCENT = new Percent(new Decimal("50"), PercentScale.PERCENT);
TWENTYFIVE_PERCENT = new Percent(new Decimal("25"), PercentScale.PERCENT);
TEN_PERCENT = new Percent(new Decimal("10"), PercentScale.PERCENT);
FIVE_PERCENT = new Percent(new Decimal("5"), PercentScale.PERCENT);
TWO_PERCENT = new Percent(new Decimal("2"), PercentScale.PERCENT);
ONE_PERCENT = new Percent(Decimal.ONE, PercentScale.PERCENT);
ZERO_PERCENT = new Percent(Decimal.ZERO, PercentScale.RATE);
MINUS_ONE_PERCENT = ONE_PERCENT.negate();
MINUS_TWO_PERCENT = TWO_PERCENT.negate();
MINUS_FIVE_PERCENT = FIVE_PERCENT.negate();
MINUS_TEN_PERCENT = TEN_PERCENT.negate();
}
public Percent(final Decimal value, final PercentScale scale) {
super(value, scale, DEFAULT_SCALE);
}
public Percent(final Number dividend, final Number divisor) {
this(Decimal.valueOf(dividend), Decimal.valueOf(divisor));
}
/**
* Use default values of the scaled decimal instead! This constructor is functioning as a compiler warning for a
* programming issue.
*/
@Deprecated
public Percent(final AScaledDecimal<?, ?> dividend, final Number divisor) throws Exception {
super(Decimal.ZERO, PercentScale.PERCENT, DEFAULT_SCALE);
throw new UnsupportedOperationException();
}
/**
* Use default values of the scaled decimal instead! This constructor is functioning as a compiler warning for a
* programming issue.
*/
@Deprecated
public Percent(final Number dividend, final AScaledDecimal<?, ?> divisor) throws Exception {
super(null, null, DEFAULT_SCALE);
throw new UnsupportedOperationException();
}
public Percent(final ADecimal<?> dividend, final ADecimal<?> divisor) {
this(dividend.getDefaultValue().divide(divisor.getDefaultValue()), PercentScale.RATE);
}
public Percent(final Duration dividend, final Duration divisor) {
this(dividend.doubleValue(FTimeUnit.MILLISECONDS), divisor.doubleValue(FTimeUnit.MILLISECONDS));
}
public <T extends AScaledDecimal<T, ?>> Percent(final AScaledDecimal<T, ?> dividend,
final AScaledDecimal<T, ?> divisor) {
this(dividend.getDefaultValue().divide(divisor.getDefaultValue()), PercentScale.RATE);
}
public Percent(final Percent percent) {
this(percent.getValue(percent.getScale()), percent.getScale());
}
@Override
protected Percent getGenericThis() {
return this;
}
@Override
protected Percent newValueCopy(final Decimal value, final PercentScale scale) {
return new Percent(value, scale);
}
@Override
public Percent zero() {
return ZERO_PERCENT;
}
public static Percent nullToZero(final Percent value) {
if (value == null) {
return ZERO_PERCENT;
} else {
return value;
}
}
@Override
public Decimal getRate() {
return getDefaultValue();
}
/**
* (newValue - oldValue) / abs(oldValue)
*/
public static <T extends ADecimal<T>> Percent relativeDifference(final ADecimal<T> oldValue,
final ADecimal<T> newValue) {
return new Percent(newValue.subtract(oldValue), oldValue.abs());
}
public static void putPercent(final ByteBuffer buffer, final Percent value) {
if (value == null) {
buffer.putDouble(Double.MIN_VALUE);
} else {
buffer.putDouble(value.getRate().doubleValueRaw());
}
}
public static Percent extractPercent(final ByteBuffer buffer, final int index) {
final double value = buffer.getDouble(index);
if (value == Double.MIN_VALUE) {
return null;
} else {
return new Percent(new Decimal(value), PercentScale.RATE);
}
}
}