Plan/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/json/graphs/line/LineGraph.java

127 lines
4.5 KiB
Java

/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.delivery.rendering.json.graphs.line;
import com.djrapitops.plan.delivery.domain.mutators.MutatorFunctions;
import com.djrapitops.plan.delivery.rendering.json.graphs.HighChart;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* This is a LineGraph for any set of Points, thus it is Abstract.
*
* @author AuroraLS3
*/
public class LineGraph implements HighChart {
private final List<Point> points;
private final GapStrategy gapStrategy;
public LineGraph(List<Point> points, boolean displayGaps) {
this(points, new GapStrategy(
displayGaps,
TimeUnit.MINUTES.toMillis(3), // Acceptable gap
TimeUnit.MINUTES.toMillis(1), // To first filler
TimeUnit.MINUTES.toMillis(30), // Filler frequency
null
));
}
public LineGraph(List<Point> points, GapStrategy gapStrategy) {
this.points = points;
this.gapStrategy = gapStrategy;
}
@Override
public String toHighChartsSeries() {
StringBuilder arrayBuilder = new StringBuilder("[");
int size = points.size();
Long lastX = null;
for (int i = 0; i < size; i++) {
Point point = points.get(i);
Double y = point.getY();
long date = (long) point.getX();
if (gapStrategy.fillGaps && lastX != null && date - lastX > gapStrategy.acceptableGapMs) {
addMissingPoints(arrayBuilder, lastX, date);
}
lastX = date;
arrayBuilder.append("[").append(date).append(",").append(y).append("]");
if (i < size - 1) {
arrayBuilder.append(",");
}
}
arrayBuilder.append("]");
return arrayBuilder.toString();
}
public List<Point> getPoints() {
if (gapStrategy.fillGaps) {
return MutatorFunctions.addMissing(points, gapStrategy);
}
return points;
}
public List<Number[]> getPointArrays() {
return getPoints().stream().map(Point::toArray).collect(Collectors.toList());
}
private void addMissingPoints(StringBuilder arrayBuilder, Long lastX, long date) {
long iterate = lastX + gapStrategy.diffToFirstGapPointMs;
while (iterate < date) {
arrayBuilder.append("[").append(iterate).append(",").append(gapStrategy.fillWith).append("],");
iterate += gapStrategy.fillFrequencyMs;
}
}
public static class GapStrategy {
public final boolean fillGaps;
public final long acceptableGapMs;
public final long diffToFirstGapPointMs;
public final long fillFrequencyMs;
public final Double fillWith;
/**
* Create a GapStrategy.
*
* @param fillGaps true/false, should the gaps in data be filled with something?
* @param acceptableGapMs How many milliseconds is acceptable between points before filling in points.
* @param diffToFirstGapPointMs How many milliseconds to last data point are added to add first filler point.
* @param fillFrequencyMs How many milliseconds should be added after each filler point.
* @param fillWith Data value for the fill, null for no data, value for some data.
*/
public GapStrategy(
boolean fillGaps,
long acceptableGapMs,
long diffToFirstGapPointMs,
long fillFrequencyMs,
Double fillWith
) {
this.fillGaps = fillGaps;
this.acceptableGapMs = acceptableGapMs;
this.diffToFirstGapPointMs = diffToFirstGapPointMs;
this.fillFrequencyMs = fillFrequencyMs;
this.fillWith = fillWith;
}
}
}