Fixed Query viewfinder graph gap fill

This commit is contained in:
Risto Lahtela 2021-02-03 19:08:55 +02:00
parent 0b187ef20c
commit eebf3d28f9
4 changed files with 72 additions and 21 deletions

View File

@ -16,6 +16,7 @@
*/
package com.djrapitops.plan.delivery.domain.mutators;
import com.djrapitops.plan.delivery.rendering.json.graphs.line.LineGraph;
import com.djrapitops.plan.delivery.rendering.json.graphs.line.Point;
import com.djrapitops.plan.utilities.java.Lists;
import com.djrapitops.plugin.utilities.Verify;
@ -59,7 +60,7 @@ public class MutatorFunctions {
}
}
public static List<Point> addMissing(List<Point> points, long accuracy, Integer replacement) {
public static List<Point> addMissing(List<Point> points, LineGraph.GapStrategy gapStrategy) {
if (Verify.isEmpty(points)) return points;
List<Point> filled = new ArrayList<>();
@ -67,8 +68,8 @@ public class MutatorFunctions {
for (Point point : points) {
long date = (long) point.getX();
if (lastX != null && date - lastX > accuracy) {
addMissing(lastX, date, filled, accuracy, replacement);
if (lastX != null && date - lastX > gapStrategy.acceptableGapMs) {
addMissing(lastX, date, filled, gapStrategy);
}
lastX = date;
filled.add(point);
@ -77,11 +78,11 @@ public class MutatorFunctions {
return filled;
}
private static void addMissing(long from, long to, List<Point> points, long accuracy, Integer replacement) {
long iterate = from;
private static void addMissing(long from, long to, List<Point> points, LineGraph.GapStrategy gapStrategy) {
long iterate = from + gapStrategy.diffToFirstGapPointMs;
while (iterate < to) {
points.add(new Point(iterate, replacement));
iterate += accuracy;
points.add(new Point(iterate, gapStrategy.fillWith));
iterate += gapStrategy.fillFrequencyMs;
}
}

View File

@ -29,12 +29,22 @@ import java.util.concurrent.TimeUnit;
*/
public class LineGraph implements HighChart {
private final boolean displayGaps;
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.displayGaps = displayGaps;
this.gapStrategy = gapStrategy;
}
@Override
@ -48,7 +58,7 @@ public class LineGraph implements HighChart {
Double y = point.getY();
long date = (long) point.getX();
if (displayGaps && lastX != null && date - lastX > TimeUnit.MINUTES.toMillis(3L)) {
if (gapStrategy.fillGaps && lastX != null && date - lastX > gapStrategy.acceptableGapMs) {
addMissingPoints(arrayBuilder, lastX, date);
}
lastX = date;
@ -64,17 +74,48 @@ public class LineGraph implements HighChart {
}
public List<Point> getPoints() {
if (displayGaps) {
return MutatorFunctions.addMissing(points, TimeUnit.MINUTES.toMillis(1L), null);
if (gapStrategy.fillGaps) {
return MutatorFunctions.addMissing(points, gapStrategy);
}
return points;
}
private void addMissingPoints(StringBuilder arrayBuilder, Long lastX, long date) {
long iterate = lastX + TimeUnit.MINUTES.toMillis(1L);
long iterate = lastX + gapStrategy.diffToFirstGapPointMs;
while (iterate < date) {
arrayBuilder.append("[").append(iterate).append(",null],");
iterate += TimeUnit.MINUTES.toMillis(30L);
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;
}
}
}

View File

@ -52,6 +52,11 @@ public class LineGraphFactory {
return new LineGraph(points, displayGaps);
}
public LineGraph lineGraph(List<Point> points, LineGraph.GapStrategy gapStrategy) {
points.sort(new PointComparator());
return new LineGraph(points, gapStrategy);
}
public LineGraph chunkGraph(TPSMutator mutator) {
return new ChunkGraph(mutator, shouldDisplayGapsInData());
}

View File

@ -20,6 +20,7 @@ import com.djrapitops.plan.delivery.domain.DateObj;
import com.djrapitops.plan.delivery.formatting.Formatter;
import com.djrapitops.plan.delivery.formatting.Formatters;
import com.djrapitops.plan.delivery.rendering.json.graphs.Graphs;
import com.djrapitops.plan.delivery.rendering.json.graphs.line.LineGraph;
import com.djrapitops.plan.delivery.rendering.json.graphs.line.Point;
import com.djrapitops.plan.delivery.web.resolver.MimeType;
import com.djrapitops.plan.delivery.web.resolver.Resolver;
@ -91,12 +92,15 @@ public class FiltersJSONResolver implements Resolver {
Long earliestStart = dbSystem.getDatabase().query(SessionQueries.earliestSessionStart());
data.add(0, new DateObj<>(earliestStart, 1));
boolean displayGaps = true;
return graphs.line().lineGraph(Lists.map(data, Point::fromDateObj), displayGaps).getPoints()
.stream().map(point -> {
if (point.getY() == null) point.setY(0.0);
return point.toArray();
}).collect(Collectors.toList());
LineGraph.GapStrategy gapStrategy = new LineGraph.GapStrategy(
true,
TimeUnit.MINUTES.toMillis(16), // Acceptable gap
TimeUnit.MINUTES.toMillis(1),
TimeUnit.MINUTES.toMillis(30),
0.0
);
return graphs.line().lineGraph(Lists.map(data, Point::fromDateObj), gapStrategy).getPoints()
.stream().map(Point::toArray).collect(Collectors.toList());
}
/**