eu.hansolo.medusa.tools.MovingAverage Maven / Gradle / Ivy
/*
* Copyright (c) 2016 by Gerrit Grunwald
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package eu.hansolo.medusa.tools;
import java.time.Duration;
import java.time.Instant;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* Created by hansolo on 01.11.16.
*/
public class MovingAverage {
public static final int MAX_PERIOD = 1000;
private static final int DEFAULT_PERIOD = 10;
private final Queue window;
private int numberPeriod;
private double sum;
// ******************** Constructors **************************************
public MovingAverage() {
this(DEFAULT_PERIOD);
}
public MovingAverage(final int NUMBER_PERIOD) {
numberPeriod = Helper.clamp(0, MAX_PERIOD, NUMBER_PERIOD);
window = new ConcurrentLinkedQueue<>();
}
// ******************** Methods *******************************************
public void addData(final Data DATA) {
sum += DATA.getValue();
window.add(DATA);
if (window.size() > numberPeriod) {
sum -= window.remove().getValue();
}
}
public void addValue(final double VALUE) {
addData(new Data(VALUE));
}
public Queue getWindow() { return new LinkedList<>(window); }
public double getAverage() {
if (window.isEmpty()) return 0; // technically the average is undefined
return (sum / window.size());
}
public double getTimeBasedAverageOf(final Duration DURATION) {
assert !DURATION.isNegative() : "Time period must be positive";
Instant now = Instant.now();
double average = window.stream()
.filter(v -> v.getTimestamp().isAfter(now.minus(DURATION)))
.mapToDouble(Data::getValue)
.average()
.getAsDouble();
return average;
}
public void reset() { window.clear(); }
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy