package com.plectix.simulator.streaming; import java.util.Collection; import java.util.LinkedList; /*package*/ final class InterpolatingLiveDataConsumer extends AbstractLiveDataConsumer { private Collection<LiveDataPoint> allDataPoints = createLiveDataBuffer(); private final int pointsLimit; public InterpolatingLiveDataConsumer(LiveDataSourceInterface dataSource, int liveDataPoints) { super(dataSource, liveDataPoints); pointsLimit = liveDataPoints; } @Override protected final Collection<LiveDataPoint> processRawDataPoints(Collection<LiveDataPoint> rawDataPoints) { allDataPoints = this.join(allDataPoints, rawDataPoints); // We need to make return an independent copy: Collection<LiveDataPoint> copyOfAllDataPoints = createLiveDataBuffer(); copyOfAllDataPoints.addAll(allDataPoints); return copyOfAllDataPoints; } private final Collection<LiveDataPoint> join(Collection<LiveDataPoint> initial, Collection<LiveDataPoint> next) { LinkedList<LiveDataPoint> allPoints = new LinkedList<LiveDataPoint>(initial); allPoints.addAll(next); if (allPoints.size() <= pointsLimit) { return allPoints; } int pointsNumber = Math.min(pointsLimit, allPoints.size()); // we think that the time is counting from zero double initialTimePoint = allPoints.getFirst().getEventTime(); double lastTimePoint = allPoints.getLast().getEventTime(); double timeStep = (lastTimePoint - initialTimePoint) / (pointsNumber - 1); Collection<LiveDataPoint> result = new LinkedList<LiveDataPoint>(); int eventNumber = 0; double nextSnapshotTime = initialTimePoint; LiveDataPoint previousPoint = null; for (LiveDataPoint point : allPoints) { if (previousPoint == null) { double[] firstPointValues = point.getPlotValues(); result.add(new LiveDataPoint(eventNumber++, nextSnapshotTime, firstPointValues)); previousPoint = point; nextSnapshotTime += timeStep; continue; } LiveDataPoint newPointToAdd = createNewDataPoint(previousPoint, point, nextSnapshotTime, eventNumber); while (newPointToAdd != null) { result.add(newPointToAdd); eventNumber++; nextSnapshotTime += timeStep; newPointToAdd = createNewDataPoint(previousPoint, point, nextSnapshotTime, eventNumber); } previousPoint = point; } return result; } private final LiveDataPoint createNewDataPoint(LiveDataPoint p1, LiveDataPoint p2, double time, int eventNumber) { if (p1.getEventTime() < time && p2.getEventTime() >= time) { double[] averageValues = getAverageLiveData(p1, p2, time); LiveDataPoint result = new LiveDataPoint(eventNumber, time, averageValues); return result; } else { return null; } } private final double[] getAverageLiveData(LiveDataPoint p1, LiveDataPoint p2, double time) { double timeDeviation = p2.getEventTime() - p1.getEventTime(); double timeProportionValue = time - p1.getEventTime(); int observablesNumber = p1.getPlotValues().length; double[] result = new double[observablesNumber]; for (int index = 0; index < observablesNumber; index++) { double observableDeviation = p2.getPlotValues()[index] - p1.getPlotValues()[index]; result[index] = (timeProportionValue * observableDeviation / timeDeviation) + p1.getPlotValues()[index]; } return result; } }