diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/BearingCluster.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/BearingCluster.java index 5a45e226818..5cb451c601a 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/BearingCluster.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/BearingCluster.java @@ -10,7 +10,9 @@ import com.sap.sailing.domain.common.Util.Pair; /** * Contains a number of {@link Bearing} objects and maintains the average bearing. For a given {@link Bearing} it * can determine the difference to this cluster's average bearing. It can also split the cluster into two, based - * on the two bearings farthest apart.

+ * on the two bearings farthest apart. The cluster can contain multiple occurrences of the same and also + * multiple occurrences of mutually equal {@link Bearing} objects which is one possible way of computing a + * weighted average.

* * It is assumed that bearings added to this cluster are no further than 180 degrees apart. Violating this * rule will lead to unpredictable results. diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/EstimatedWindFixesAsNavigableSet.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/EstimatedWindFixesAsNavigableSet.java index 7834dc879a2..74a679f32e9 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/EstimatedWindFixesAsNavigableSet.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/EstimatedWindFixesAsNavigableSet.java @@ -15,7 +15,7 @@ import com.sap.sailing.util.impl.DescendingNavigableSet; /** * Emulates a collection of {@link Wind} fixes for a {@link TrackedRace}, computed using - * {@link TrackedRace#getEstimatedWindDirection(com.sap.sailing.domain.base.Position, TimePoint)}. If not contrained + * {@link TrackedRace#getEstimatedWindDirection(com.sap.sailing.domain.base.Position, TimePoint)}. If not constrained * by a {@link #from} and/or a {@link #to} time point, an equidistant time field is assumed, starting at * {@link TrackedRace#getStart()} and leading up to {@link TrackedRace#getTimePointOfNewestEvent()}. If * {@link TrackedRace#getStart()} returns null, {@link Long#MAX_VALUE} is used as the {@link #from} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackBasedEstimationWindTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackBasedEstimationWindTrackImpl.java index 7e4eb0f9863..a85b6deb0c9 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackBasedEstimationWindTrackImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackBasedEstimationWindTrackImpl.java @@ -26,6 +26,12 @@ import com.sap.sailing.util.impl.ArrayListNavigableSet; * computed from the tracked race's boat tracks. *

* + * The estimation is integrated into the {@link WindTrackImpl} concepts by redefining the {@link #getInternalRawFixes()} + * method such that it returns an {@link EstimatedWindFixesAsNavigableSet} object. It computes its values by asking back + * to {@link #getEstimatedWindDirection(Position, TimePoint)} which first performs a cache look-up. In case of a cache + * miss it determines the result based on {@link TrackedRace#getEstimatedWindDirection(Position, TimePoint)}. + *

+ * * Caching is done using the base class's {@link TrackImpl#fixes} field which is made accessible through * {@link #getCachedFixes()}. This track observes the {@link TrackedRace} for which it provides wind estimations. * Whenever a change occurs, all fixes whose derivation is potentially affected by the change are removed from the diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java index 69f3d72a86f..793eda26de7 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java @@ -555,7 +555,6 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { @Override public Wind getEstimatedWindDirection(Position position, TimePoint timePoint) { - int count = 0; // counts how many boats' courses were used in computing the result Map bearings = new HashMap(); for (LegType legType : LegType.values()) { bearings.put(legType, new BearingCluster()); @@ -573,6 +572,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { } if (legType != LegType.REACHING) { GPSFixTrack track = getTrack(competitor); + // TODO bug #167 could be fixed here by excluding competitors that are x seconds before/after a mark passing if (!track.hasDirectionChange(timePoint, getManeuverDegreeAngleThreshold())) { Bearing bearing = track.getEstimatedSpeed(timePoint).getBearing(); BearingCluster bearingClusters = bearings.get(legType); @@ -582,17 +582,20 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { } } Bearing upwindAverage = null; + int upwindConfidence = 0; BearingCluster[] bearingClustersUpwind = bearings.get(LegType.UPWIND).splitInTwo(getMinimumAngleBetweenDifferentTacksUpwind()); if (!bearingClustersUpwind[0].isEmpty() && !bearingClustersUpwind[1].isEmpty()) { upwindAverage = bearingClustersUpwind[0].getAverage().middle(bearingClustersUpwind[1].getAverage()); - count += bearingClustersUpwind[0].size() + bearingClustersUpwind[1].size(); + upwindConfidence = Math.min(bearingClustersUpwind[0].size(), bearingClustersUpwind[1].size()); } Bearing downwindAverage = null; + int downwindConfidence = 0; BearingCluster[] bearingClustersDownwind = bearings.get(LegType.DOWNWIND).splitInTwo(getMinimumAngleBetweenDifferentTacksDownwind()); if (!bearingClustersDownwind[0].isEmpty() && !bearingClustersDownwind[1].isEmpty()) { downwindAverage = bearingClustersDownwind[0].getAverage().middle(bearingClustersDownwind[1].getAverage()); - count += bearingClustersDownwind[0].size() + bearingClustersDownwind[1].size(); + downwindConfidence = Math.min(bearingClustersDownwind[0].size(), bearingClustersDownwind[1].size()); } + int confidence = upwindConfidence + downwindConfidence; Bearing bearing; if (upwindAverage == null) { if (downwindAverage == null) { @@ -608,7 +611,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { } } return new WindImpl(null, timePoint, - new KnotSpeedWithBearingImpl(/* speedInKnots */ count, bearing)); + new KnotSpeedWithBearingImpl(/* speedInKnots */ confidence, bearing)); } /** diff --git a/java/com.sap.sailing.targetplatform/definitions/race-analysis-p2-maven-central.target b/java/com.sap.sailing.targetplatform/definitions/race-analysis-p2-maven-central.target index 3f2a7fd2057..17624a5a035 100644 --- a/java/com.sap.sailing.targetplatform/definitions/race-analysis-p2-maven-central.target +++ b/java/com.sap.sailing.targetplatform/definitions/race-analysis-p2-maven-central.target @@ -16,7 +16,7 @@ - + diff --git a/java/com.sap.sailing.targetplatform/definitions/race-analysis-p2-maven-local.target b/java/com.sap.sailing.targetplatform/definitions/race-analysis-p2-maven-local.target index 5d0968c2905..397ae89848f 100644 --- a/java/com.sap.sailing.targetplatform/definitions/race-analysis-p2-maven-local.target +++ b/java/com.sap.sailing.targetplatform/definitions/race-analysis-p2-maven-local.target @@ -10,7 +10,9 @@ - + + +