java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseChangeBasedTrackApproximationWithTracTracDataTest.java
... ...
@@ -65,7 +65,9 @@ public class CourseChangeBasedTrackApproximationWithTracTracDataTest extends Onl
65 65
*/
66 66
@Test
67 67
public void testNoDiffBetweenEarlyAndLateInitialization() {
68
- final DynamicGPSFixTrack<Competitor, GPSFixMoving> trackCopy = new DynamicGPSFixMovingTrackImpl<Competitor>(sampleCompetitor, /* millisecondsOverWhichToAverage */ 15000);
68
+ final DynamicGPSFixTrack<Competitor, GPSFixMoving> trackCopy = new DynamicGPSFixMovingTrackImpl<Competitor>(
69
+ sampleCompetitor,
70
+ /* millisecondsOverWhichToAverage */ boatClass.getApproximateManeuverDurationInMilliseconds());
69 71
final CourseChangeBasedTrackApproximation earlyInitApproximation = new CourseChangeBasedTrackApproximation(trackCopy, sampleCompetitor.getBoat().getBoatClass());
70 72
final TimePoint from = sampleTrack.getFirstRawFix().getTimePoint();
71 73
final TimePoint to = sampleTrack.getLastRawFix().getTimePoint();
java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CourseChangeBasedTrackApproximation.java
... ...
@@ -6,6 +6,7 @@ import java.io.Serializable;
6 6
import java.util.ArrayList;
7 7
import java.util.Collections;
8 8
import java.util.Comparator;
9
+import java.util.Deque;
9 10
import java.util.LinkedList;
10 11
import java.util.List;
11 12
import java.util.ListIterator;
... ...
@@ -105,6 +106,17 @@ public class CourseChangeBasedTrackApproximation implements Serializable, GPSTra
105 106
private final LinkedList<GPSFixMoving> window;
106 107
107 108
/**
109
+ * New fixes shall be inserted into the {@link FixWindow} only when it is unlikely that newer fixes will still
110
+ * influence the calculation of its {@link GPSFixMoving#getCachedEstimatedSpeed() estimated speed}. This way,
111
+ * the differences between seeing and not seeing newer fixes is reduced, and so it isn't so relevant anymore
112
+ * whether the approximation is updated incrementally as fixes arrive, or after a race has been fully loaded.
113
+ * <p>
114
+ *
115
+ * See also bug 6209.
116
+ */
117
+ private final Deque<GPSFixMoving> queueOfNewFixes;
118
+
119
+ /**
108 120
* We need to remember the speed / bearing as we saw them when we inserted the fixes into the {@link #window}
109 121
* collection. Based on more fixes getting added to the track, things may change. In particular, fixes that may have
110 122
* had a valid speed when inserted may later have their cached speed/bearing invalidated, and computing it again
... ...
@@ -125,6 +137,7 @@ public class CourseChangeBasedTrackApproximation implements Serializable, GPSTra
125 137
126 138
FixWindow() {
127 139
this.window = new LinkedList<>();
140
+ this.queueOfNewFixes = new LinkedList<>();
128 141
this.speedForFixesInWindow = new LinkedList<>();
129 142
this.windowDuration = Duration.NULL;
130 143
// use twice the maneuver duration to also catch slowly-executed gybes
... ...
@@ -160,6 +173,18 @@ public class CourseChangeBasedTrackApproximation implements Serializable, GPSTra
160 173
* or {@code null} if no maneuver candidate became available
161 174
*/
162 175
GPSFixMoving add(GPSFixMoving next) {
176
+ final GPSFixMoving result;
177
+ queueOfNewFixes.add(next); // FIXME bug6209: the queueOfNewFixes needs to remain ordered by fix TimePoint!
178
+ final GPSFixMoving first = queueOfNewFixes.getFirst();
179
+ if (first.getTimePoint().until(next.getTimePoint()).asMillis() > track.getMillisecondsOverWhichToAverageSpeed()/2) {
180
+ result = addOldEnoughFix(queueOfNewFixes.removeFirst());
181
+ } else {
182
+ result = null;
183
+ }
184
+ return result;
185
+ }
186
+
187
+ private GPSFixMoving addOldEnoughFix(GPSFixMoving next) {
163 188
assert window.isEmpty() || !next.getTimePoint().before(window.peekFirst().getTimePoint());
164 189
final GPSFixMoving result;
165 190
final SpeedWithBearing nextSpeed = /* TODO this was the original code that can depend on fixes newer than next: */ next.isEstimatedSpeedCached() ? next.getCachedEstimatedSpeed() : track.getEstimatedSpeed(next.getTimePoint());