diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java
index b4e26c5d3e1..2897a93e774 100755
--- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java
+++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java
@@ -538,6 +538,12 @@ public class MockedTrackedRace implements DynamicTrackedRace {
// TODO Auto-generated method stub
return null;
}
+
+ @Override
+ public Tack getTack(Competitor competitor, TimePoint timePoint, Wind wind) {
+ // TODO Auto-generated method stub
+ return null;
+ }
@Override
public Wind getDirectionFromStartToNextMark(TimePoint at) {
diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java
index dd8dd878eb8..a1f722d9607 100755
--- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java
+++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java
@@ -315,6 +315,12 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace {
// TODO Auto-generated method stub
return null;
}
+
+ @Override
+ public Tack getTack(Competitor competitor, TimePoint timePoint, Wind wind) {
+ // TODO Auto-generated method stub
+ return null;
+ }
@Override
public TrackedRegatta getTrackedRegatta() {
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java
index a8c104c1c2e..ee4008f6276 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java
@@ -381,6 +381,15 @@ public interface TrackedRace extends Serializable {
*/
Tack getTack(Competitor competitor, TimePoint timePoint) throws NoWindException;
+ /**
+ * Determines whether the competitor is sailing on port or starboard tack at the timePoint
+ * requested.
+ * This method outperforms {@link #getTack(Competitor, TimePoint)}, but requires the correct wind for the given
+ * time and competitor position.
+ * This method monitors the competitors' GPS tracks.
+ */
+ Tack getTack(Competitor competitor, TimePoint timePoint, Wind wind);
+
TrackedRegatta getTrackedRegatta();
/**
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 ba306188b91..9150adb84f1 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
@@ -1851,6 +1851,43 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
return result;
}
+ /**
+ * This is probably best explained by example. If the wind bearing is from port to starboard, the situation looks
+ * like this:
+ *
+ *
+ * ^ + * Wind | Boat + * -----------> | + * | + * + *+ * + * In this case, the boat gets the wind from port, so the result has to be {@link Tack#PORT}. The angle between the + * boat's heading (which we can only approximate by the boat's course over ground) and the wind bearing in this case + * is 90 degrees.
wind.{@link Bearing#getDifferenceTo(Bearing) getDifferenceTo}(boat) in this case will
+ * return a bearing representing -90 degrees.
+ * + * + * If the wind is blowing the other way, the angle returned by {@link Bearing#getDifferenceTo(Bearing)} will + * correspond to +90 degrees. In other words, a negative angle means starboard tack, a positive angle represents + * port tack. + *
+ *
+ * For the unlikely case of 0 degrees difference, {@link Tack#STARBOARD} will result.
+ *
+ * @return null in case the boat's bearing cannot be determined for timePoint
+ */
+ @Override
+ public Tack getTack(Competitor competitor, TimePoint timePoint, Wind wind) {
+ final SpeedWithBearing estimatedSpeed = getTrack(competitor).getEstimatedSpeed(timePoint);
+ Tack result = null;
+ if (estimatedSpeed != null) {
+ result = getTack(wind, estimatedSpeed.getBearing());
+ }
+ return result;
+ }
+
/**
* Based on the wind direction at timePoint and at position where, compares the
* boatBearing to the wind's bearing at that time and place and determined the tack.
@@ -1861,15 +1898,22 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
*/
private Tack getTack(Position where, TimePoint timePoint, Bearing boatBearing) throws NoWindException {
final Wind wind = getWind(where, timePoint);
- Tack result;
if (wind == null) {
throw new NoWindException("Can't determine wind direction in position " + where + " at " + timePoint
+ ", therefore cannot determine tack");
}
+ return getTack(wind, boatBearing);
+ }
+
+
+ /**
+ * Based on the wind, compares the boatBearing to the wind's bearing at
+ * that time and place and determined the tack.
+ */
+ private Tack getTack(Wind wind, Bearing boatBearing) {
Bearing windBearing = wind.getBearing();
Bearing difference = windBearing.getDifferenceTo(boatBearing);
- result = difference.getDegrees() <= 0 ? Tack.PORT : Tack.STARBOARD;
- return result;
+ return difference.getDegrees() <= 0 ? Tack.PORT : Tack.STARBOARD;
}
@Override
diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java
index 5fe563b47a4..3018a726651 100755
--- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java
+++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java
@@ -539,6 +539,12 @@ public class MockedTrackedRace implements DynamicTrackedRace {
// TODO Auto-generated method stub
return null;
}
+
+ @Override
+ public Tack getTack(Competitor competitor, TimePoint timePoint, Wind wind) {
+ // TODO Auto-generated method stub
+ return null;
+ }
@Override
public Wind getDirectionFromStartToNextMark(TimePoint at) {
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java
index 8a82c58bf17..8df19710e9a 100755
--- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java
+++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java
@@ -1472,17 +1472,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
GPSFixMoving fix = fixIter.next();
while (fix != null && (fix.getTimePoint().compareTo(toTimePointExcluding) < 0 ||
(fix.getTimePoint().equals(toTimePointExcluding) && toTimePointExcluding.equals(fromTimePoint)))) {
- Tack tack;
- try {
- tack = trackedRace.getTack(competitor, fix.getTimePoint());
- } catch (NoWindException nwe) {
- tack = null;
- }
+ Wind wind = trackedRace.getWind(fix.getPosition(),toTimePointExcluding);
+ Tack tack = wind == null? null : trackedRace.getTack(competitor, fix.getTimePoint(), wind);
TrackedLegOfCompetitor trackedLegOfCompetitor = trackedRace.getTrackedLeg(competitor,
fix.getTimePoint());
LegType legType = trackedLegOfCompetitor == null ? null : trackedRace.getTrackedLeg(
trackedLegOfCompetitor.getLeg()).getLegType(fix.getTimePoint());
- Wind wind = trackedRace.getWind(fix.getPosition(),toTimePointExcluding);
WindDTO windDTO = wind == null ? null : createWindDTOFromAlreadyAveraged(wind, toTimePointExcluding);
GPSFixDTO fixDTO = createGPSFixDTO(fix, track.getEstimatedSpeed(fix.getTimePoint()), windDTO, tack, legType, /* extrapolate */
false);
@@ -1493,17 +1488,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
// check if fix was at date and if extrapolation is requested
if (!fix.getTimePoint().equals(toTimePointExcluding) && extrapolate) {
Position position = track.getEstimatedPosition(toTimePointExcluding, extrapolate);
- Tack tack2;
- try {
- tack2 = trackedRace.getTack(competitor, toTimePointExcluding);
- } catch (NoWindException nwe) {
- tack2 = null;
- }
+ Wind wind2 = trackedRace.getWind(position, toTimePointExcluding);
+ Tack tack2 = wind2 == null ? null : trackedRace.getTack(competitor, toTimePointExcluding, wind2);
LegType legType2 = trackedLegOfCompetitor == null ? null : trackedRace
.getTrackedLeg(trackedLegOfCompetitor.getLeg()).getLegType(
fix.getTimePoint());
SpeedWithBearing speedWithBearing = track.getEstimatedSpeed(toTimePointExcluding);
- Wind wind2 = trackedRace.getWind(position, toTimePointExcluding);
WindDTO windDTO2 = wind2 == null ? null : createWindDTOFromAlreadyAveraged(wind2, toTimePointExcluding);
GPSFixDTO extrapolated = new GPSFixDTO(
toPerCompetitorIdAsString.get(competitorDTO.getIdAsString()),
diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java
index 87d354c2a75..8137f2e4f7a 100644
--- a/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java
+++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java
@@ -277,6 +277,12 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials {
// TODO Auto-generated method stub
return null;
}
+
+ @Override
+ public Tack getTack(Competitor competitor, TimePoint timePoint, Wind wind) {
+ // TODO Auto-generated method stub
+ return null;
+ }
@Override
public TrackedRegatta getTrackedRegatta() {