package de.invesdwin.util.time.duration;
import java.util.Collections;
import java.util.List;
import javax.annotation.concurrent.Immutable;
import de.invesdwin.util.collections.Lists;
import de.invesdwin.util.math.decimal.Decimal;
import de.invesdwin.util.time.fdate.FTimeUnit;
@Immutable
class DurationAggregate implements IDurationAggregate {
private final List<? extends Duration> values;
DurationAggregate(final List<? extends Duration> values) {
this.values = values;
}
@Override
public IDurationAggregate reverse() {
return new DurationAggregate(Lists.reverse(values));
}
/**
* Returns a weighted average where the first value has the least weight and the last value has the highest weight.
*/
@Override
public Duration avgWeightedAsc() {
return reverse().avgWeightedDesc();
}
/**
* Returns a weighted average where the first value has the highest weight and the last value has the least weight.
*/
@Override
public Duration avgWeightedDesc() {
long sumOfWeights = 0;
Decimal sumOfWeightedValues = Decimal.ZERO;
for (int i = 0, weight = count(); i < count(); i++, weight--) {
final Decimal weightedValue = new Decimal(values.get(i).decimalValue(FTimeUnit.NANOSECONDS))
.multiply(weight);
sumOfWeights += weight;
sumOfWeightedValues = sumOfWeightedValues.add(weightedValue);
}
return new Duration(sumOfWeightedValues.divide(sumOfWeights).longValue(), FTimeUnit.NANOSECONDS);
}
@Override
public Duration sum() {
Duration sum = Duration.ZERO;
for (final Duration value : values) {
if (value != null) {
sum = sum.add(value);
}
}
return sum;
}
/**
* x_quer = (x_1 + x_2 + ... + x_n) / n
*
* @see <a href="http://de.wikipedia.org/wiki/Arithmetisches_Mittel">Source</a>
*/
@Override
public Duration avg() {
Decimal sum = Decimal.ZERO;
for (final Duration value : values) {
if (value != null) {
sum = sum.add(value.decimalValue(FTimeUnit.NANOSECONDS));
}
}
return new Duration(sum.divide(count()).longValue(), FTimeUnit.NANOSECONDS);
}
@Override
public Duration max() {
Duration highest = null;
for (final Duration value : values) {
if (highest == null) {
highest = value;
} else if (value == null) {
continue;
} else if (highest.compareTo(value) < 0) {
highest = value;
}
}
return highest;
}
@Override
public Duration min() {
Duration lowest = null;
for (final Duration value : values) {
if (lowest == null) {
lowest = value;
} else if (value == null) {
continue;
} else if (value.compareTo(lowest) < 0) {
lowest = value;
}
}
return lowest;
}
@Override
public List<? extends Duration> values() {
return Collections.unmodifiableList(values);
}
public int count() {
return values.size();
}
@Override
public String toString() {
return values.toString();
}
}