Javadoc and naming

This commit is contained in:
Vladislav Chumak committed 2018-03-23 18:08:21 +01:00
1 parent 9585901f02
commit c4c0b8ea74
8 files changed
+108 -90

No files matched your search

@@ -3,7 +3,7 @@ package com.sap.sailing.domain.maneuverdetection;
import java.util.List;
import com.sap.sailing.domain.tracking.Maneuver;
import com.sap.sailing.domain.tracking.ManeuverCurve;
import com.sap.sailing.domain.tracking.CompleteManeuverCurve;
/**
* An extension of {@link ManeuverDetector} which supports incremental maneuver detection within calls of
@@ -17,11 +17,16 @@ import com.sap.sailing.domain.tracking.ManeuverCurve;
public interface IncrementalManeuverDetector extends ManeuverDetector {
/**
* Gets the detected maneuvers during previous calls of {@link #detectManeuvers()}
* Gets the already detected maneuvers by previous calls of {@link #detectManeuvers()} and
* {@link #detectManeuverCurves()}.
*/
List<Maneuver> getAlreadyDetectedManeuvers();
List<ManeuverCurve> getAlreadyDetectedManeuverCurves();
/**
* Gets the already detected maneuver curves by previous calls of {@link #detectManeuvers()} and
* {@link #detectManeuverCurves()}.
*/
List<CompleteManeuverCurve> getAlreadyDetectedManeuverCurves();
/**
* Clears the whole state of the detector, which is used for incremental maneuver detection. The following calls of
@@ -2,12 +2,25 @@ package com.sap.sailing.domain.maneuverdetection;
import java.util.List;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.tracking.CompleteManeuverCurve;
import com.sap.sailing.domain.tracking.Maneuver;
import com.sap.sailing.domain.tracking.ManeuverCurve;
/**
* Determines maneuvers performed within a tracked race.
* Determines maneuvers performed within a tracked race by competitor associated with this
* {@link ManeuverDetector}-instance. The steps of maneuver detection look as follows:
* <ol>
* <li>Douglas-Peucker-fixes set is determined for the GPS-track of competitor. The analyzed GPS-fixes set gets limited
* by the set contained between the time points of crossing start line and finish-line. The limit does not apply if no
* start-line has been crossed by the competitor at all. In case of absent crossing of finish-line, the GPS-fix set gets
* analyzed until the last available GPS-fix.</li>
* <li>The bearings between DP-fixes are calculated</li>
* <li>Consecutive DP-fixes get grouped together if their sign of associated bearing is equal and the duration and
* distance limits between DP-fixes is satisfied.</li>
* <li>For each DP-fixes group a {@link CompleteManeuverCurve} gets determined</li>
* <li>For each {@link CompleteManeuverCurve}-instance appropriate {@link Maneuver}-instance(s) are determined. In
* contrast to maneuvers, the complete maneuver curves are not subject to any splitting logic for maneuvers with
* multiple "tacking" and "jibing".</li>
* <ol>
*
* @author Vladislav Chumak (D069712)
*
@@ -15,27 +28,36 @@ import com.sap.sailing.domain.tracking.ManeuverCurve;
public interface ManeuverDetector {
/**
* Tries to detect maneuvers on the <code>competitor</code>'s track based on a number of approximating fixes. The
* fixes contain bearing information, but this is not the bearing leading to the next approximation fix but the
* bearing the boat had at the time of the approximating fix which is taken from the original track.
* <p>
* Detects maneuvers performed within a GPS-track of the competitor associated with this
* {@link ManeuverDetector}-instance. See {@link ManeuverDetector} description for more info regarding the detection
* strategy.
*
* The time period assumed for a maneuver duration is taken from the
* {@link BoatClass#getApproximateManeuverDurationInMilliseconds() boat class}. If no maneuver is detected, an empty
* list is returned. Maneuvers can only be expected to be detected if at least three fixes are provided in
* <code>approximatedFixesToAnalyze</code>. For the inner approximating fixes (all except the first and the last
* approximating fix), their course changes according to the approximated path (and not the underlying actual
* tracked fixes) are computed. Subsequent course changes to the same direction are then grouped. Those in closer
* timely distance than {@link #getApproximateManeuverDurationInMilliseconds()} (including single course changes
* that have no surrounding other course changes to group) are grouped into one {@link Maneuver}.
*
* @return an empty list if no maneuver is detected for <code>competitor</code> between <code>from</code> and
* <code>to</code>, or else the list of maneuvers detected.
* @return an empty list if no maneuvers were detected, otherwise the list with detected maneuvers.
*/
List<Maneuver> detectManeuvers();
List<Maneuver> detectManeuvers(Iterable<ManeuverCurve> maneuverCurves);
/**
* Derives maneuvers from the provided {@code maneuverCurves}. Since the provided complete maneuver curves already
* include the calculated boundaries of each complete maneuvering spot, this method operates in a very
* performance-efficient manner.
*
* @param maneuverCurves
* The maneuver curves from which the maneuvers shall be derived
* @return The maneuvers derived from the provided maneuver curves. The list gets empty, if the provided maneuver
* curves list is also empty.
*/
List<Maneuver> detectManeuvers(Iterable<CompleteManeuverCurve> maneuverCurves);
List<ManeuverCurve> detectManeuverCurves();
/**
* Detects the complete maneuver curves performed within a GPS-track of the competitor associated with this
* {@link ManeuverDetector}-instance. In contrast to maneuvers determined by {@link #detectManeuvers()}, the
* complete maneuver curves are not subject to any splitting logic for maneuvers with multiple "tacking" and
* "jibing". See {@link ManeuverDetector} description for more info regarding the detection strategy.
*
* @return an empty list if no maneuver spots were detected, otherwise the list with detected maneuver curves.
* @see CompleteManeuverCurve
* @see ManeuverDetector
*/
List<CompleteManeuverCurve> detectManeuverCurves();
}
@@ -15,7 +15,7 @@ import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.maneuverdetection.ApproximatedFixesCalculator;
import com.sap.sailing.domain.maneuverdetection.IncrementalManeuverDetector;
import com.sap.sailing.domain.tracking.Maneuver;
import com.sap.sailing.domain.tracking.ManeuverCurve;
import com.sap.sailing.domain.tracking.CompleteManeuverCurve;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
@@ -105,7 +105,7 @@ public class IncrementalManeuverDetectorImpl extends ManeuverDetectorImpl implem
}
@Override
public List<ManeuverCurve> getAlreadyDetectedManeuverCurves() {
public List<CompleteManeuverCurve> getAlreadyDetectedManeuverCurves() {
ManeuverDetectionResult lastManeuverDetectionResult = this.lastManeuverDetectionResult;
if (lastManeuverDetectionResult != null) {
return lastManeuverDetectionResult.getManeuverSpots().stream().filter(maneuverSpot -> maneuverSpot.getManeuverCurve() != null)
@@ -200,7 +200,7 @@ public class IncrementalManeuverDetectorImpl extends ManeuverDetectorImpl implem
} else {
// New wind information has been received which considerably differs from previous
// maneuver spot calculation => recalculate maneuvers of existing maneuver curve
ManeuverCurve maneuverCurve = matchingManeuverSpotFromState.getManeuverCurve();
CompleteManeuverCurve maneuverCurve = matchingManeuverSpotFromState.getManeuverCurve();
ManeuverSpot maneuverSpot;
if (maneuverCurve != null) {
WindMeasurement windMeasurement = matchingManeuverSpotFromState
@@ -29,7 +29,7 @@ import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.maneuverdetection.ManeuverDetector;
import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.Maneuver;
import com.sap.sailing.domain.tracking.ManeuverCurve;
import com.sap.sailing.domain.tracking.CompleteManeuverCurve;
import com.sap.sailing.domain.tracking.ManeuverCurveBoundaries;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.SpeedWithBearingStep;
@@ -119,9 +119,9 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
}
@Override
public List<Maneuver> detectManeuvers(Iterable<ManeuverCurve> maneuverCurves) {
public List<Maneuver> detectManeuvers(Iterable<CompleteManeuverCurve> maneuverCurves) {
List<Maneuver> maneuvers = new ArrayList<>();
for (ManeuverCurve maneuverCurve : maneuverCurves) {
for (CompleteManeuverCurve maneuverCurve : maneuverCurves) {
TimePoint maneuverTimePoint = maneuverCurve.getManeuverCurveWithStableSpeedAndCourseBoundaries()
.getTimePoint();
Position maneuverPosition = track.getEstimatedPosition(maneuverTimePoint, /* extrapolate */false);
@@ -134,7 +134,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
}
@Override
public List<ManeuverCurve> detectManeuverCurves() {
public List<CompleteManeuverCurve> detectManeuverCurves() {
List<ManeuverSpot> maneuverSpots = detectManeuverSpots();
return maneuverSpots.stream().filter(maneuverSpot -> maneuverSpot.getManeuverCurve() != null)
.map(maneuverSpot -> maneuverSpot.getManeuverCurve()).collect(Collectors.toList());
@@ -209,19 +209,8 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
}
/**
* Tries to detect maneuvers on the <code>competitor</code>'s track based on a number of approximating fixes. The
* fixes contain bearing information, but this is not the bearing leading to the next approximation fix but the
* bearing the boat had at the time of the approximating fix which is taken from the original track.
* <p>
*
* The time period assumed for a maneuver duration is taken from the
* {@link BoatClass#getApproximateManeuverDurationInMilliseconds() boat class}. If no maneuver is detected, an empty
* list is returned. Maneuvers can only be expected to be detected if at least three fixes are provided in
* <code>approximatedFixesToAnalyze</code>. For the inner approximating fixes (all except the first and the last
* approximating fix), their course changes according to the approximated path (and not the underlying actual
* tracked fixes) are computed. Subsequent course changes to the same direction are then grouped. Those in closer
* timely distance than {@link #getApproximateManeuverDurationInMilliseconds()} (including single course changes
* that have no surrounding other course changes to group) are grouped into one {@link Maneuver}.
* Detects the maneuver spots with corresponding maneuvers within provided time frame. See step 1ff. in
* {@link ManeuverDetector} description.
*
* @param earliestManeuverStart
* maneuver start will not be before this time point; if a maneuver is found whose time point is at or
@@ -245,7 +234,9 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
/**
* Uses the provided {@code approximatingFixesToAnalyze} as douglas peucker fixes to detect maneuver spots with
* corresponding maneuvers.
* corresponding maneuvers. See step 2ff. in {@link ManeuverDetector} description. Maneuvers can only be expected to
* be detected if at least three fixes are provided in <code>approximatedFixesToAnalyze</code>. The first and the
* last DP-fix get never associated with a maneuver spot.
*/
protected List<ManeuverSpot> detectManeuvers(Iterable<GPSFixMoving> approximatingFixesToAnalyze,
TimePoint earliestManeuverStart, TimePoint latestManeuverEnd) {
@@ -289,10 +280,10 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
}
/**
* Maps the provided {@code courseChange} from {@link Bearing} to {@link NauticalSide}.
* Maps the provided {@code courseChangeInDegrees} from {@link Bearing} to {@link NauticalSide}.
*/
protected NauticalSide getDirectionOfCourseChange(Bearing courseChange) {
return courseChange.getDegrees() < 0 ? NauticalSide.PORT : NauticalSide.STARBOARD;
protected NauticalSide getDirectionOfCourseChange(double courseChangeInDegrees) {
return courseChangeInDegrees < 0 ? NauticalSide.PORT : NauticalSide.STARBOARD;
}
/**
@@ -353,7 +344,7 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
}
Bearing courseChangeOnOriginalFixes = getCourseChange(fromTimePointForCourseChangeAnalysis,
toTimePointForCourseChangeAnalysis);
return getDirectionOfCourseChange(courseChangeOnOriginalFixes);
return getDirectionOfCourseChange(courseChangeOnOriginalFixes.getDegrees());
}
/**
@@ -400,15 +391,11 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
* maneuver and the leg after the maneuver is not taken from a later time point, even if half the
* maneuver duration after the maneuver time point were after this time point.
* @return The derived list maneuver spots with corresponding maneuvers. The maneuver spot count {@code >= 0}.
* @throws NoWindException
* When no wind information during maneuver performance is available
* @see #groupChangesInSameDirectionIntoManeuvers(Competitor, List, boolean, TimePoint, TimePoint)
* @see #computeManeuverDetails(Competitor, ManeuverCurveDetailsWithBearingSteps, TimePoint, TimePoint)
*/
protected ManeuverSpot createManeuverSpotWithManeuversFromFixesGroup(List<GPSFixMoving> douglasPeuckerFixesGroup,
NauticalSide maneuverDirection, TimePoint earliestManeuverStart, TimePoint latestManeuverEnd) {
ManeuverCurve maneuverCurve = createManeuverCurveFromFixesGroup(douglasPeuckerFixesGroup, maneuverDirection,
earliestManeuverStart, latestManeuverEnd);
CompleteManeuverCurve maneuverCurve = createManeuverCurveFromFixesGroup(douglasPeuckerFixesGroup,
maneuverDirection, earliestManeuverStart, latestManeuverEnd);
if (maneuverCurve == null) {
return new ManeuverSpot(new ArrayList<>(douglasPeuckerFixesGroup), maneuverDirection, null,
new ArrayList<>(), null);
@@ -424,41 +411,25 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
}
/**
* Creates maneuvers from the provided {@code group} of douglas peucker fixes considering the provided time range
* limit. This method might return zero or more maneuvers. The maneuvers are determined by the following work-flow:
* <ol>
* <li>Main curve of maneuver within the time range of douglas peucker fixes +-
* ({@link BoatClass#getApproximateManeuverDuration() maneuver duration}{@code / 2}) is determined. The main curve
* is defined as the section of maneuver with the highest absolute course change towards the provided
* {@code maneuverDirection} ({@link Maneuver more info}).</li>
* <li>Maneuver start and end with stable speed and course are determined by analysis of speed maxima starting
* before and after the main curve, followed by extension to the points with stable course
* ({@link #computeManeuverDetails(Competitor, ManeuverCurveDetailsWithBearingSteps, TimePoint, TimePoint) more
* info})</li>
* <li>The maneuver type is determined considering the maneuver's main curve, marks and wind direction</li>
* </ol>
* Determines the complete maneuver curve for the provided DP-fixes group.
*
* @param douglasPeuckerFixesGroup
* The douglas peucker fixes which may represent the maneuver basis
* The douglas peucker fixes which represents the basis points of the complete maneuver curve.
* @param maneuverDirection
* The course change direction within douglas peucker fixes.
* @param earliestManeuverStart
* Maneuver start will not be before this time point; if a maneuver is found whose time point is at or
* after this time point, no matter how close it is, its start regarding speed and course into the
* Maneuver curve start will not be before this time point; if a maneuver is found whose time point is at
* or after this time point, no matter how close it is, its start regarding speed and course into the
* maneuver and the leg before the maneuver is not taken from an earlier time point, even if half the
* maneuver duration before the maneuver time point were before this time point.
* @param latestManeuverEnd
* Maneuver end will not be after this time point; if a maneuver is found whose time point is at or
* Maneuver curve end will not be after this time point; if a maneuver is found whose time point is at or
* before this time point, no matter how close it is, its end regarding speed and course out of the
* maneuver and the leg after the maneuver is not taken from a later time point, even if half the
* maneuver duration after the maneuver time point were after this time point.
* @return The derived list maneuver spots with corresponding maneuvers. The maneuver spot count {@code >= 0}.
* @throws NoWindException
* When no wind information during maneuver performance is available
* @see #groupChangesInSameDirectionIntoManeuvers(Competitor, List, boolean, TimePoint, TimePoint)
* @see #computeManeuverDetails(Competitor, ManeuverCurveDetailsWithBearingSteps, TimePoint, TimePoint)
*/
private ManeuverCurve createManeuverCurveFromFixesGroup(List<GPSFixMoving> douglasPeuckerFixesGroup,
private CompleteManeuverCurve createManeuverCurveFromFixesGroup(List<GPSFixMoving> douglasPeuckerFixesGroup,
NauticalSide maneuverDirection, TimePoint earliestManeuverStart, TimePoint latestManeuverEnd) {
long durationForDouglasPeuckerExtensionForMainCurveAnalysisInMillis = getDurationForDouglasPeuckerExtensionForMainCurveAnalysis(
getApproximateManeuverDuration()).asMillis();
@@ -482,10 +453,15 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
ManeuverCurveDetails maneuverDetails = computeManeuverDetails(maneuverMainCurveDetails, earliestManeuverStart,
latestManeuverEnd);
MarkPassing markPassing = getMarkPassingIfPresent(maneuverMainCurveDetails);
ManeuverCurve maneuverCurve = new ManeuverCurveImpl(maneuverMainCurveDetails, maneuverDetails, markPassing);
CompleteManeuverCurve maneuverCurve = new ManeuverCurveImpl(maneuverMainCurveDetails, maneuverDetails,
markPassing);
return maneuverCurve;
}
/**
* Gets the mark passing performed within the provided maneuver curve boundaries. {@code null} is returned when no
* mark passing is present.
*/
private MarkPassing getMarkPassingIfPresent(ManeuverCurveBoundaries maneuverCurveBoundaries) {
// the TrackedLegOfCompetitor variables may be null, e.g., in case the time points are before or after the race
TrackedLegOfCompetitor legBeforeManeuver = trackedRace.getTrackedLeg(competitor,
@@ -505,6 +481,11 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
return markPassing;
}
/**
* Derives maneuvers from the provided maneuver main curve and maneuver curve with stable speed and course before
* and after. This method gets called recursively if the splitting of main curve and maneuver curve boundaries is
* performed in order to extract multiple maneuvers for one complete maneuver curve.
*/
protected List<Maneuver> determineManeuversFromManeuverCurve(
ManeuverCurveDetailsWithBearingSteps maneuverMainCurveDetails, ManeuverCurveDetails maneuverDetails,
Wind wind, MarkPassing markPassing) {
@@ -667,8 +648,8 @@ public class ManeuverDetectorImpl implements ManeuverDetector {
ManeuverCurveDetailsWithBearingSteps maneuverMainCurveDetails, TimePoint timePoint) {
Pair<SpeedWithBearingStepsIterable, SpeedWithBearingStepsIterable> splitSteps = splitSpeedWithBearingStepsByTimePoint(
maneuverMainCurveDetails.getSpeedWithBearingSteps(), timePoint);
NauticalSide maneuverDirection = maneuverMainCurveDetails.getDirectionChangeInDegrees() < 0 ? NauticalSide.PORT
: NauticalSide.STARBOARD;
NauticalSide maneuverDirection = getDirectionOfCourseChange(
maneuverMainCurveDetails.getDirectionChangeInDegrees());
SpeedWithBearingStepsIterable stepsBeforeIterable = splitSteps.getA();
ManeuverCurveDetailsWithBearingSteps mainCurveBefore = stepsBeforeIterable == null ? null
: constructManeuverCurveDetailsWithBearingSteps(
@@ -3,7 +3,7 @@ package com.sap.sailing.domain.maneuverdetection.impl;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.Maneuver;
import com.sap.sailing.domain.tracking.ManeuverCurve;
import com.sap.sailing.domain.tracking.CompleteManeuverCurve;
/**
* Represents a spot within the track of competitor, where maneuvers have been detected by analysis of a douglas peucker
@@ -17,12 +17,12 @@ public class ManeuverSpot {
private final Iterable<GPSFixMoving> douglasPeuckerFixes;
private final NauticalSide maneuverSpotDirection;
private final ManeuverCurve maneuverCurve;
private final CompleteManeuverCurve maneuverCurve;
private final Iterable<Maneuver> maneuvers;
private final WindMeasurement windMeasurement;
public ManeuverSpot(Iterable<GPSFixMoving> douglasPeuckerFixes, NauticalSide maneuverSpotDirection,
ManeuverCurve maneuverCurve, Iterable<Maneuver> maneuvers, WindMeasurement windMeasurement) {
CompleteManeuverCurve maneuverCurve, Iterable<Maneuver> maneuvers, WindMeasurement windMeasurement) {
this.douglasPeuckerFixes = douglasPeuckerFixes;
this.maneuverCurve = maneuverCurve;
this.maneuvers = maneuvers;
@@ -44,7 +44,7 @@ public class ManeuverSpot {
return maneuverSpotDirection;
}
public ManeuverCurve getManeuverCurve() {
public CompleteManeuverCurve getManeuverCurve() {
return maneuverCurve;
}
@@ -4,17 +4,20 @@ import com.sap.sailing.domain.maneuverdetection.impl.ManeuverCurveDetails;
import com.sap.sailing.domain.maneuverdetection.impl.ManeuverCurveDetailsWithBearingSteps;
/**
* Represents a segment within a GPS-track where a maneuver is performed. In contrast to {@link Maneuver}, the
* boundaries of the curve are not split by maneuver type dependent logic, e.g. by cutting of the first 360 degrees of
* penalty circles and etc.
*
* @author Vladislav Chumak (D069712)
*
*/
public interface ManeuverCurve {
public interface CompleteManeuverCurve {
/**
* Gets time points and speeds with bearings of main curve beginning and end.
*
* @return Entering and exiting details of maneuver main curve
* @see ManeuverCurve
* @see CompleteManeuverCurve
*/
ManeuverCurveDetailsWithBearingSteps getMainCurveBoundaries();
@@ -24,12 +27,19 @@ public interface ManeuverCurve {
*
* @return Entering and exiting details of maneuver section, with stable speed and bearing before and after that
* section
* @see ManeuverCurve
* @see CompleteManeuverCurve
*/
ManeuverCurveDetails getManeuverCurveWithStableSpeedAndCourseBoundaries();
/**
* Gets the mark passing which is contained within maneuver curve. In case if no mark was passed, {@code null} is
* returned.
*/
MarkPassing getMarkPassing();
/**
* Determines whether a mark was crossed within the maneuver curve.
*/
boolean isMarkPassing();
}
@@ -144,7 +144,7 @@ public interface Maneuver extends GPSFix {
Speed getLowestSpeed();
/**
* Gets the mark passing which is contained within maneuver. In case if no mark passing was passed, {@code null} is
* Gets the mark passing which is contained within maneuver curve. In case if no mark was passed, {@code null} is
* returned.
*/
MarkPassing getMarkPassing();
@@ -2,14 +2,14 @@ package com.sap.sailing.domain.tracking.impl;
import com.sap.sailing.domain.maneuverdetection.impl.ManeuverCurveDetails;
import com.sap.sailing.domain.maneuverdetection.impl.ManeuverCurveDetailsWithBearingSteps;
import com.sap.sailing.domain.tracking.ManeuverCurve;
import com.sap.sailing.domain.tracking.CompleteManeuverCurve;
import com.sap.sailing.domain.tracking.MarkPassing;
/**
* @author Vladislav Chumak (D069712)
*
*/
public class ManeuverCurveImpl implements ManeuverCurve {
public class ManeuverCurveImpl implements CompleteManeuverCurve {
private final ManeuverCurveDetailsWithBearingSteps mainCurveBoundaries;
private final ManeuverCurveDetails maneuverCurveWithStableSpeedAndCourseBoundaries;