5d8a94dfad271840d4da087f8c3ada33f518e95d
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()); |