java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CourseChangeBasedTrackApproximation.java
... ...
@@ -30,6 +30,7 @@ import com.sap.sse.common.impl.TimeRangeImpl;
30 30
import com.sap.sse.common.scalablevalue.KadaneExtremeSubsequenceFinder;
31 31
import com.sap.sse.common.scalablevalue.KadaneExtremeSubsequenceFinderLinkedNodesImpl;
32 32
import com.sap.sse.common.scalablevalue.ScalableDouble;
33
+import com.sap.sse.common.scalablevalue.ScalableValueWithDistance;
33 34
34 35
/**
35 36
* Given a {@link GPSFixTrack} containing {@link GPSFixMoving}, an instance of this class finds areas on the track where
... ...
@@ -161,7 +162,7 @@ public class CourseChangeBasedTrackApproximation implements Serializable, GPSTra
161 162
GPSFixMoving add(GPSFixMoving next) {
162 163
assert window.isEmpty() || !next.getTimePoint().before(window.peekFirst().getTimePoint());
163 164
final GPSFixMoving result;
164
- 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()) */
165
+ 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()); */
165 166
next.getSpeed(); int TODO; // TODO bug6209: try without dependency on newer fixes and see if it helps produce equal results for early/late initialization
166 167
if (nextSpeed != null) { // TODO bug6209: this gets messy... if we drop a fix because no estimated speed can be determined for it, and later fix additions may change this, where would we get this fix from again?
167 168
numberOfFixesAdded++;
... ...
@@ -187,7 +188,7 @@ public class CourseChangeBasedTrackApproximation implements Serializable, GPSTra
187 188
// rather expensive ceil/floor search on the track; resort to track.getEstimatedSpeed if not cached
188 189
assert previousSpeed != null; // we wouldn't have added the fix in the previous run if it hadn't had a valid speed
189 190
final double courseChangeBetweenPreviousAndNextInDegrees = previousSpeed.getBearing().getDifferenceTo(nextSpeed.getBearing()).getDegrees();
190
- if (insertPosition == window.size()-1) { // if not appended to the end, the window duration won't change
191
+ if (insertPosition == window.size()-1) { // if appended to the end, the window duration changes
191 192
windowDuration = windowDuration.plus(previous.getTimePoint().until(next.getTimePoint()));
192 193
}
193 194
if (courseChangeBetweenFixesInWindow.isEmpty()) {
... ...
@@ -254,10 +255,10 @@ public class CourseChangeBasedTrackApproximation implements Serializable, GPSTra
254 255
private void removeFirst(int howManyElementsToRemove) {
255 256
assert !window.isEmpty();
256 257
for (int i=0; i<howManyElementsToRemove; i++) {
257
- final GPSFixMoving removed = window.removeFirst();
258
+ window.removeFirst();
258 259
speedForFixesInWindow.removeFirst();
259
- windowDuration = window.isEmpty() ? Duration.NULL : windowDuration.minus(removed.getTimePoint().until(window.getFirst().getTimePoint()));
260 260
}
261
+ windowDuration = window.isEmpty() ? Duration.NULL : window.getFirst().getTimePoint().until(window.getLast().getTimePoint());
261 262
// adjust totalCourseChangeFromBeginningOfWindow by subtracting the first course change from all others
262 263
// and shifting all by one position to the "left"
263 264
if (!courseChangeBetweenFixesInWindow.isEmpty()) {
... ...
@@ -280,8 +281,10 @@ public class CourseChangeBasedTrackApproximation implements Serializable, GPSTra
280 281
*/
281 282
private Pair<GPSFixMoving, Integer> getManeuverCandidate() {
282 283
final GPSFixMoving result;
283
- final double maximumCourseChangeToStarboard = courseChangeBetweenFixesInWindow.getMaxSum().divide(1);
284
- final double maximumCourseChangeToPort = -courseChangeBetweenFixesInWindow.getMinSum().divide(1);
284
+ final ScalableValueWithDistance<Double, Double> maxSum = courseChangeBetweenFixesInWindow.getMaxSum();
285
+ final double maximumCourseChangeToStarboard = maxSum == null ? Double.NEGATIVE_INFINITY : maxSum.divide(1);
286
+ final ScalableValueWithDistance<Double, Double> minSum = courseChangeBetweenFixesInWindow.getMinSum();
287
+ final double maximumCourseChangeToPort = minSum == null ? Double.NEGATIVE_INFINITY : -minSum.divide(1);
285 288
final double absoluteMaximumTotalCourseChangeFromBeginningOfWindowInDegrees = Math.max(maximumCourseChangeToStarboard, maximumCourseChangeToPort);
286 289
int indexOfMaximumAbsoluteCourseChangeInCorrectDirection = -1;
287 290
if (absoluteMaximumTotalCourseChangeFromBeginningOfWindowInDegrees >= maneuverAngleInDegreesThreshold) {
java/com.sap.sse.common/src/com/sap/sse/common/scalablevalue/KadaneExtremeSubsequenceFinderLinkedNodesImpl.java
... ...
@@ -1,7 +1,7 @@
1 1
package com.sap.sse.common.scalablevalue;
2 2
3
+import java.io.Serializable;
3 4
import java.util.Collections;
4
-import java.util.Comparator;
5 5
import java.util.Iterator;
6 6
import java.util.TreeSet;
7 7
import java.util.function.BiFunction;
... ...
@@ -9,6 +9,7 @@ import java.util.function.Consumer;
9 9
import java.util.function.Function;
10 10
11 11
import com.sap.sse.common.Util;
12
+import com.sap.sse.common.impl.SerializableComparator;
12 13
13 14
/**
14 15
* An implementation of Kadane's algorithm for "maximum sub-sequence sum" that works incrementally,
... ...
@@ -57,7 +58,8 @@ public class KadaneExtremeSubsequenceFinderLinkedNodesImpl<ValueType, AveragesTo
57 58
*
58 59
* @author Axel Uhl (d043530)
59 60
*/
60
- private static class Node<ValueType, AveragesTo extends Comparable<AveragesTo>, T extends ComparableScalableValueWithDistance<ValueType, AveragesTo>> {
61
+ private static class Node<ValueType, AveragesTo extends Comparable<AveragesTo>, T extends ComparableScalableValueWithDistance<ValueType, AveragesTo>> implements Serializable {
62
+ private static final long serialVersionUID = -2547142048423135013L;
61 63
private static int idCounter = 0;
62 64
private final T value;
63 65
private final int id;
... ...
@@ -235,11 +237,11 @@ public class KadaneExtremeSubsequenceFinderLinkedNodesImpl<ValueType, AveragesTo
235 237
this.size = 0;
236 238
this.first = null;
237 239
this.last = null;
238
- final Comparator<? super Node<ValueType, AveragesTo, T>> idComparator = (n1, n2)->Integer.compare(n1.getId(), n2.getId());
239
- final Comparator<Node<ValueType, AveragesTo, T>> minSumComparator = (n1, n2)->compare(n1.getMinSumEndingHere(), n2.getMinSumEndingHere());
240
- final Comparator<Node<ValueType, AveragesTo, T>> maxSumComparator = (n1, n2)->compare(n1.getMaxSumEndingHere(), n2.getMaxSumEndingHere());
241
- final Comparator<? super Node<ValueType, AveragesTo, T>> minSumOuterComparator = (n1,n2)->(n1==n2?0:minSumComparator.thenComparing(idComparator).compare(n1, n2));
242
- final Comparator<? super Node<ValueType, AveragesTo, T>> maxSumOuterComparator = (n1,n2)->(n1==n2?0:maxSumComparator.thenComparing(idComparator).compare(n1, n2));
240
+ final SerializableComparator<? super Node<ValueType, AveragesTo, T>> idComparator = (n1, n2)->Integer.compare(n1.getId(), n2.getId());
241
+ final SerializableComparator<Node<ValueType, AveragesTo, T>> minSumComparator = (n1, n2)->compare(n1.getMinSumEndingHere(), n2.getMinSumEndingHere());
242
+ final SerializableComparator<Node<ValueType, AveragesTo, T>> maxSumComparator = (n1, n2)->compare(n1.getMaxSumEndingHere(), n2.getMaxSumEndingHere());
243
+ final SerializableComparator<? super Node<ValueType, AveragesTo, T>> minSumOuterComparator = (n1,n2)->(n1==n2?0:minSumComparator.thenComparing(idComparator).compare(n1, n2));
244
+ final SerializableComparator<? super Node<ValueType, AveragesTo, T>> maxSumOuterComparator = (n1,n2)->(n1==n2?0:maxSumComparator.thenComparing(idComparator).compare(n1, n2));
243 245
this.nodesOrderedByMinSum = new TreeSet<>(minSumOuterComparator);
244 246
this.nodesOrderedByMaxSum = new TreeSet<>(maxSumOuterComparator);
245 247
}
... ...
@@ -557,7 +559,7 @@ public class KadaneExtremeSubsequenceFinderLinkedNodesImpl<ValueType, AveragesTo
557 559
@Override
558 560
public String toString() {
559 561
return "KadaneExtremeSubsequenceFinderLinkedNodesImpl [size=" + size
560
- + ", minChangePropagationStepsAvg=" + minChangePropagationStepsSum / minChangePropagationsCount
561
- + ", maxChangePropagationStepsAvg=" + maxChangePropagationStepsSum / maxChangePropagationsCount + "]";
562
+ + ", minChangePropagationStepsAvg=" + (minChangePropagationsCount==0?null:(minChangePropagationStepsSum / minChangePropagationsCount))
563
+ + ", maxChangePropagationStepsAvg=" + (maxChangePropagationsCount==0?null:(maxChangePropagationStepsSum / maxChangePropagationsCount)) + "]";
562 564
}
563 565
}
java/com.sap.sse.common/src/com/sap/sse/common/scalablevalue/ScalableDouble.java
... ...
@@ -1,6 +1,9 @@
1 1
package com.sap.sse.common.scalablevalue;
2 2
3
-public class ScalableDouble implements AbstractScalarValue<Double> {
3
+import java.io.Serializable;
4
+
5
+public class ScalableDouble implements AbstractScalarValue<Double>, Serializable {
6
+ private static final long serialVersionUID = -354261484569358609L;
4 7
private final double value;
5 8
6 9
public ScalableDouble(double value) {