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() {