diff --git a/java/com.sap.sailing.datamining.test/src/com/sap/sailing/datamining/impl/components/TestSegmentsTackType.java b/java/com.sap.sailing.datamining.test/src/com/sap/sailing/datamining/impl/components/TestSegmentsTackType.java index 539b22374ad..a3d9ec17488 100644 --- a/java/com.sap.sailing.datamining.test/src/com/sap/sailing/datamining/impl/components/TestSegmentsTackType.java +++ b/java/com.sap.sailing.datamining.test/src/com/sap/sailing/datamining/impl/components/TestSegmentsTackType.java @@ -80,13 +80,13 @@ public class TestSegmentsTackType extends StoredTrackBasedTest { DynamicGPSFixTrack competitorATrack = trackedRace.getTrack(competitorA); final KnotSpeedWithBearingImpl sogCog = new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(45)); TimePoint timePoint = trackedRace.getStartOfTracking().plus(10); - GPSFixMovingImpl currentGPS = new GPSFixMovingImpl(new DegreePosition(54.4680424, 10.234451), timePoint, sogCog); + GPSFixMovingImpl currentGPS = new GPSFixMovingImpl(new DegreePosition(54.4680424, 10.234451), timePoint, sogCog, /* optionalTrueHeading */ null); final Duration timeBetweenFixes = Duration.ofMillis(490); for (int i=0; i<20; i++) { competitorATrack.addGPSFix(currentGPS); final Position currentPosition = sogCog.travelTo(currentGPS.getPosition(), timeBetweenFixes); timePoint = timePoint.plus(timeBetweenFixes); - currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCog); + currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCog, /* optionalTrueHeading */ null); } TimePoint markPassingTimePoint = trackedRace.getStartOfTracking().plus(20); final List markPassingsForCompetitor = new ArrayList<>(); @@ -114,13 +114,13 @@ public class TestSegmentsTackType extends StoredTrackBasedTest { DynamicGPSFixTrack competitorATrack = trackedRace.getTrack(competitorA); final KnotSpeedWithBearingImpl sogCog = new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(45)); TimePoint timePoint = trackedRace.getStartOfTracking().plus(10); - GPSFixMovingImpl currentGPS = new GPSFixMovingImpl(new DegreePosition(54.4680424, 10.234451), timePoint, sogCog); + GPSFixMovingImpl currentGPS = new GPSFixMovingImpl(new DegreePosition(54.4680424, 10.234451), timePoint, sogCog, /* optionalTrueHeading */ null); final Duration timeBetweenFixes = Duration.ofMillis(490); for (int i=0; i<20; i++) { competitorATrack.addGPSFix(currentGPS); final Position currentPosition = sogCog.travelTo(currentGPS.getPosition(), timeBetweenFixes); timePoint = timePoint.plus(timeBetweenFixes); - currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCog); + currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCog, /* optionalTrueHeading */ null); } // now run the actual test: final Iterable allTTSegments = retrieveData(); @@ -138,14 +138,14 @@ public class TestSegmentsTackType extends StoredTrackBasedTest { final Position middleOfStartLine = trackedRace.getApproximatePosition(trackedRace.getRace().getCourse().getFirstWaypoint(), timePoint); final Position topMarkPosition = trackedRace.getApproximatePosition(Util.get(trackedRace.getRace().getCourse().getWaypoints(), 1), timePoint); // start straight "under" the top mark - GPSFixMovingImpl currentGPS = new GPSFixMovingImpl(new DegreePosition(middleOfStartLine.getLatDeg(), topMarkPosition.getLngDeg()), timePoint, sogCogPortTackUpwind); + GPSFixMovingImpl currentGPS = new GPSFixMovingImpl(new DegreePosition(middleOfStartLine.getLatDeg(), topMarkPosition.getLngDeg()), timePoint, sogCogPortTackUpwind, /* optionalTrueHeading */ null); expectedSegmentStarts.add(timePoint); final Duration timeBetweenFixes = Duration.ofMillis(490); for (int i=0; i<20; i++) { competitorATrack.addGPSFix(currentGPS); final Position currentPosition = sogCogPortTackUpwind.travelTo(currentGPS.getPosition(), timeBetweenFixes); timePoint = timePoint.plus(timeBetweenFixes); - currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCogPortTackUpwind); + currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCogPortTackUpwind, /* optionalTrueHeading */ null); } // now tack onto starboard tack: final KnotSpeedWithBearingImpl sogCogStarboardTackUpwind = new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(315)); @@ -154,7 +154,7 @@ public class TestSegmentsTackType extends StoredTrackBasedTest { competitorATrack.addGPSFix(currentGPS); final Position currentPosition = sogCogStarboardTackUpwind.travelTo(currentGPS.getPosition(), timeBetweenFixes); timePoint = timePoint.plus(timeBetweenFixes); - currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCogStarboardTackUpwind); + currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCogStarboardTackUpwind, /* optionalTrueHeading */ null); } final List markPassingsForCompetitor = new ArrayList<>(); final TimePoint startMarkPassingTimePoint = trackedRace.getStartOfTracking().plus(20); @@ -170,7 +170,7 @@ public class TestSegmentsTackType extends StoredTrackBasedTest { competitorATrack.addGPSFix(currentGPS); final Position currentPosition = sogCogStarboardTackDownwind.travelTo(currentGPS.getPosition(), timeBetweenFixes); timePoint = timePoint.plus(timeBetweenFixes); - currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCogPortTackUpwind); + currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCogPortTackUpwind, /* optionalTrueHeading */ null); } // now gybe onto port tack: final KnotSpeedWithBearingImpl sogCogPortTackDownwind = new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(135)); @@ -179,7 +179,7 @@ public class TestSegmentsTackType extends StoredTrackBasedTest { competitorATrack.addGPSFix(currentGPS); final Position currentPosition = sogCogPortTackDownwind.travelTo(currentGPS.getPosition(), timeBetweenFixes); timePoint = timePoint.plus(timeBetweenFixes); - currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCogPortTackDownwind); + currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCogPortTackDownwind, /* optionalTrueHeading */ null); } // now run the actual test: final Iterable allTTSegments = retrieveData(); diff --git a/java/com.sap.sailing.domain.bravoadapter/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.bravoadapter/META-INF/MANIFEST.MF index bf82dd29560..8e698b77bdf 100755 --- a/java/com.sap.sailing.domain.bravoadapter/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.bravoadapter/META-INF/MANIFEST.MF @@ -5,7 +5,8 @@ Bundle-SymbolicName: com.sap.sailing.domain.bravoadapter Bundle-Version: 1.0.0.qualifier Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Import-Package: org.osgi.framework;version="1.8.0" +Import-Package: com.sap.sailing.declination, + org.osgi.framework;version="1.8.0" Require-Bundle: com.sap.sailing.domain, com.sap.sailing.server.trackfiles, com.sap.sailing.domain.common, diff --git a/java/com.sap.sailing.domain.bravoadapter/src/com/sap/sailing/domain/bravoadapter/impl/BravoGPSFixImporter.java b/java/com.sap.sailing.domain.bravoadapter/src/com/sap/sailing/domain/bravoadapter/impl/BravoGPSFixImporter.java index a553971258f..0bf29f20231 100755 --- a/java/com.sap.sailing.domain.bravoadapter/src/com/sap/sailing/domain/bravoadapter/impl/BravoGPSFixImporter.java +++ b/java/com.sap.sailing.domain.bravoadapter/src/com/sap/sailing/domain/bravoadapter/impl/BravoGPSFixImporter.java @@ -3,10 +3,14 @@ package com.sap.sailing.domain.bravoadapter.impl; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; +import java.text.ParseException; import java.util.Arrays; import java.util.Date; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.sap.sailing.declination.DeclinationService; import com.sap.sailing.domain.common.impl.DegreePosition; import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; import com.sap.sailing.domain.common.sensordata.BravoExtendedSensorDataMetadata; @@ -19,9 +23,12 @@ import com.sap.sailing.domain.trackimport.FormatNotSupportedException; import com.sap.sailing.domain.trackimport.GPSFixImporter; import com.sap.sailing.server.gateway.windimport.bravo.FunnyDegreeConverter; import com.sap.sailing.server.trackfiles.impl.BravoExtendedDataImporterImpl; +import com.sap.sse.common.Bearing; import com.sap.sse.common.impl.DegreeBearingImpl; public class BravoGPSFixImporter implements GPSFixImporter { + private static final Logger logger = Logger.getLogger(BravoGPSFixImporter.class.getName()); + @Override public boolean importFixes(InputStream inputStream, Charset charset, Callback callback, boolean inferSpeedAndBearing, final String filename) throws FormatNotSupportedException, IOException { @@ -30,12 +37,27 @@ public class BravoGPSFixImporter implements GPSFixImporter { new BravoExtendedDataImporterImpl().importFixes(inputStream, charset, (Iterable fixes, TrackFileImportDeviceIdentifier deviceIdentifier)->{ for (final DoubleVectorFix fix : fixes) { + final DegreePosition position = new DegreePosition(FunnyDegreeConverter.funnyLatLng(fix.get(BravoExtendedSensorDataMetadata.LAT.getColumnIndex())), + FunnyDegreeConverter.funnyLatLng(fix.get(BravoExtendedSensorDataMetadata.LON.getColumnIndex()))); + Bearing optionalTrueHeading; + if (fix.get(BravoExtendedSensorDataMetadata.EXPEDITION_HDG.getColumnIndex()) != null) { + try { + optionalTrueHeading = new DegreeBearingImpl(fix.get(BravoExtendedSensorDataMetadata.EXPEDITION_HDG.getColumnIndex())).add( + DeclinationService.INSTANCE.getDeclination(fix.getTimePoint(), position, /* timeout for online lookup in millis */ 100) + .getBearingCorrectedTo(fix.getTimePoint())); + } catch (IOException | ParseException e) { + logger.log(Level.WARNING, "Problem looking up magnetic declination for Bravo fix", e); + optionalTrueHeading = null; + } + } else { + optionalTrueHeading = null; + } GPSFixMoving gpsFix = new GPSFixMovingImpl( - new DegreePosition(FunnyDegreeConverter.funnyLatLng(fix.get(BravoExtendedSensorDataMetadata.LAT.getColumnIndex())), - FunnyDegreeConverter.funnyLatLng(fix.get(BravoExtendedSensorDataMetadata.LON.getColumnIndex()))), + position, fix.getTimePoint(), new KnotSpeedWithBearingImpl(fix.get(BravoExtendedSensorDataMetadata.SOG.getColumnIndex()), - new DegreeBearingImpl(fix.get(BravoExtendedSensorDataMetadata.COG.getColumnIndex())))); + new DegreeBearingImpl(fix.get(BravoExtendedSensorDataMetadata.COG.getColumnIndex()))), + optionalTrueHeading); callback.addFix(gpsFix, device); importedFixes.set(true); } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/GPSFixMoving.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/GPSFixMoving.java index 1b6fccba159..69766f8986b 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/GPSFixMoving.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/GPSFixMoving.java @@ -1,6 +1,15 @@ package com.sap.sailing.domain.common.tracking; import com.sap.sailing.domain.common.Moving; +import com.sap.sse.common.Bearing; public interface GPSFixMoving extends GPSFix, Moving { + /** + * Some sensors have a compass or IMU built in that can deliver a true heading. This usually requires a fixed mount + * that guarantees a well-defined orientation of the sensor relative to the object it tracks. + * + * @return a true (free of magnetic declination) heading of the object tracked, e.g., for a boat the true direction + * the bow points to; or {@code null} if the sensor did not deliver this attribute + */ + Bearing getOptionalTrueHeading(); } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/AbstractCompactGPSFixMovingImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/AbstractCompactGPSFixMovingImpl.java index d6f5da54c42..095f1dbab7c 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/AbstractCompactGPSFixMovingImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/AbstractCompactGPSFixMovingImpl.java @@ -10,6 +10,7 @@ import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sse.common.Bearing; import com.sap.sse.common.Speed; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util; /** * A memory-conserving representation of a {@link GPSFixMoving} object that produces the fine-grained @@ -96,6 +97,7 @@ public abstract class AbstractCompactGPSFixMovingImpl extends AbstractCompactGPS @Override public boolean equals(Object other) { - return super.equals(other) && other instanceof GPSFixMoving && getSpeed().equals(((GPSFixMoving) other).getSpeed()); + return super.equals(other) && other instanceof GPSFixMoving && getSpeed().equals(((GPSFixMoving) other).getSpeed()) + && Util.equalsWithNull(getOptionalTrueHeading(), ((GPSFixMoving) other).getOptionalTrueHeading()); } } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.java index bd99bf9c5e8..8f274f33a16 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.java @@ -19,4 +19,6 @@ public class FlatSmartphoneUuidAndGPSFixMovingJsonSerializer { public static final String TIME_ISO = "timestamp-iso"; public static final String SPEED_M_PER_S = "speed"; public static final String BEARING_DEG = "course"; + public static final String TRUE_HEADING_DEG = "hdt"; + public static final String MAGNETIC_HEADING_DEG = "hdg"; } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/GPSFixMovingImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/GPSFixMovingImpl.java index d107b8c2334..71e7a296de1 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/GPSFixMovingImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/GPSFixMovingImpl.java @@ -5,6 +5,7 @@ import com.sap.sailing.domain.common.SpeedWithBearing; import com.sap.sailing.domain.common.impl.DegreePosition; import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sse.common.Bearing; import com.sap.sse.common.TimePoint; import com.sap.sse.common.impl.DegreeBearingImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; @@ -12,10 +13,12 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public class GPSFixMovingImpl extends GPSFixImpl implements GPSFixMoving { private static final long serialVersionUID = 6508021498142383100L; private final SpeedWithBearing speed; + private final Bearing optionalTrueHeading; - public GPSFixMovingImpl(Position position, TimePoint timePoint, SpeedWithBearing speed) { + public GPSFixMovingImpl(Position position, TimePoint timePoint, SpeedWithBearing speed, Bearing optionalTrueHeading) { super(position, timePoint); this.speed = speed; + this.optionalTrueHeading = optionalTrueHeading; } @Override @@ -23,6 +26,11 @@ public class GPSFixMovingImpl extends GPSFixImpl implements GPSFixMoving { return speed; } + @Override + public Bearing getOptionalTrueHeading() { + return optionalTrueHeading; + } + @Override public String toString() { return super.toString()+" with "+getSpeed(); @@ -39,9 +47,10 @@ public class GPSFixMovingImpl extends GPSFixImpl implements GPSFixMoving { } public static GPSFixMovingImpl create(double lonDeg, double latDeg, long timeMillis, - double speedInKnots, double bearingDeg) { + double speedInKnots, double bearingDeg, Double optionalTrueHeadingDeg) { return new GPSFixMovingImpl(new DegreePosition(latDeg, lonDeg), new MillisecondsTimePoint(timeMillis), new KnotSpeedWithBearingImpl( - speedInKnots, new DegreeBearingImpl(bearingDeg))); + speedInKnots, new DegreeBearingImpl(bearingDeg)), + optionalTrueHeadingDeg==null?null:new DegreeBearingImpl(optionalTrueHeadingDeg)); } } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/PreciseCompactGPSFixMovingImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/PreciseCompactGPSFixMovingImpl.java index a88a9e2c12f..7a167f1db5c 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/PreciseCompactGPSFixMovingImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/PreciseCompactGPSFixMovingImpl.java @@ -24,6 +24,12 @@ public class PreciseCompactGPSFixMovingImpl extends AbstractCompactGPSFixMovingI private final double lngDeg; private final double knotSpeed; private final double degBearing; + + /** + * Valid only if {@link #trueHeadingDegSet} is {@code true} + */ + private final double trueHeadingDeg; + private final boolean trueHeadingDegSet; /** * When {@link #whatIsCached}&{@link #IS_ESTIMATED_SPEED_CACHED} != 0, this field tells the estimated speed's @@ -61,6 +67,15 @@ public class PreciseCompactGPSFixMovingImpl extends AbstractCompactGPSFixMovingI } } + private class PreciseCompactTrueHeading extends AbstractBearing { + private static final long serialVersionUID = -1837422977159746992L; + + @Override + public double getDegrees() { + return trueHeadingDeg; + } + } + public class PreciseCompactPosition extends AbstractPosition { private static final long serialVersionUID = 5621506820766614178L; @@ -98,16 +113,23 @@ public class PreciseCompactGPSFixMovingImpl extends AbstractCompactGPSFixMovingI } } - public PreciseCompactGPSFixMovingImpl(Position position, TimePoint timePoint, SpeedWithBearing speed) { + public PreciseCompactGPSFixMovingImpl(Position position, TimePoint timePoint, SpeedWithBearing speed, Bearing optionalTrueHeading) { super(timePoint); latDeg = position.getLatDeg(); lngDeg = position.getLngDeg(); knotSpeed = speed==null?0:speed.getKnots(); degBearing = speed==null?0:speed.getBearing().getDegrees(); + if (optionalTrueHeading == null) { + trueHeadingDegSet = false; + trueHeadingDeg = 0.0; + } else { + trueHeadingDegSet = true; + trueHeadingDeg = optionalTrueHeading.getDegrees(); + } } public PreciseCompactGPSFixMovingImpl(GPSFixMoving gpsFixMoving) { - this(gpsFixMoving.getPosition(), gpsFixMoving.getTimePoint(), gpsFixMoving.getSpeed()); + this(gpsFixMoving.getPosition(), gpsFixMoving.getTimePoint(), gpsFixMoving.getSpeed(), gpsFixMoving.getOptionalTrueHeading()); } @Override @@ -119,6 +141,11 @@ public class PreciseCompactGPSFixMovingImpl extends AbstractCompactGPSFixMovingI public Position getPosition() { return new PreciseCompactPosition(); } + + @Override + public Bearing getOptionalTrueHeading() { + return trueHeadingDegSet ? new PreciseCompactTrueHeading() : null; + } @Override public SpeedWithBearing getCachedEstimatedSpeed() { diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/VeryCompactGPSFixMovingImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/VeryCompactGPSFixMovingImpl.java index 287cf22c770..0e1a8e3bf8b 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/VeryCompactGPSFixMovingImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/VeryCompactGPSFixMovingImpl.java @@ -46,6 +46,13 @@ public class VeryCompactGPSFixMovingImpl extends AbstractCompactGPSFixMovingImpl */ private final short degreeBearingScaled; + /** + * See {@link CompactPositionHelper}; valid if and only if {@link #trueHeadingDegreesSet} is {@code true}. + */ + private final short trueHeadingDegreesScaled; + + private final boolean trueHeadingDegreesSet; + /** * When {@link #whatIsCached}&{@link #IS_ESTIMATED_SPEED_CACHED} != 0, this field tells the estimated speed's * true "bearing" (true course over ground) in degrees, scaled into a short value using {@link CompactPositionHelper}. @@ -95,6 +102,15 @@ public class VeryCompactGPSFixMovingImpl extends AbstractCompactGPSFixMovingImpl } } + private class VeryCompactTrueHeading extends AbstractBearing { + private static final long serialVersionUID = 1130980861113826462L; + + @Override + public double getDegrees() { + return CompactPositionHelper.getDegreeBearing(trueHeadingDegreesScaled); + } + } + private class VeryCompactEstimatedSpeedBearing extends AbstractBearing { private static final long serialVersionUID = 8549231429037883121L; @@ -118,7 +134,7 @@ public class VeryCompactGPSFixMovingImpl extends AbstractCompactGPSFixMovingImpl } } - public VeryCompactGPSFixMovingImpl(Position position, TimePoint timePoint, SpeedWithBearing speed) throws CompactionNotPossibleException { + public VeryCompactGPSFixMovingImpl(Position position, TimePoint timePoint, SpeedWithBearing speed, Bearing optionalTrueHeading) throws CompactionNotPossibleException { super(timePoint); latDegScaled = CompactPositionHelper.getLatDegScaled(position); lngDegScaled = CompactPositionHelper.getLngDegScaled(position); @@ -129,16 +145,28 @@ public class VeryCompactGPSFixMovingImpl extends AbstractCompactGPSFixMovingImpl speedInKnotsScaled = CompactPositionHelper.getKnotSpeedScaled(speed); degreeBearingScaled = CompactPositionHelper.getDegreeBearingScaled(speed.getBearing()); } + if (optionalTrueHeading == null) { + trueHeadingDegreesSet = false; + trueHeadingDegreesScaled = 0; + } else { + trueHeadingDegreesSet = true; + trueHeadingDegreesScaled = CompactPositionHelper.getDegreeBearingScaled(optionalTrueHeading); + } } public VeryCompactGPSFixMovingImpl(GPSFixMoving gpsFixMoving) throws CompactionNotPossibleException { - this(gpsFixMoving.getPosition(), gpsFixMoving.getTimePoint(), gpsFixMoving.getSpeed()); + this(gpsFixMoving.getPosition(), gpsFixMoving.getTimePoint(), gpsFixMoving.getSpeed(), gpsFixMoving.getOptionalTrueHeading()); } @Override public SpeedWithBearing getSpeed() { return new VeryCompactSpeedWithBearing(); } + + @Override + public Bearing getOptionalTrueHeading() { + return trueHeadingDegreesSet ? new VeryCompactTrueHeading() : null; + } @Override public Position getPosition() { diff --git a/java/com.sap.sailing.domain.deckmanadapter/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.deckmanadapter/META-INF/MANIFEST.MF index a66f486b0c4..dc0b280476d 100644 --- a/java/com.sap.sailing.domain.deckmanadapter/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.deckmanadapter/META-INF/MANIFEST.MF @@ -10,6 +10,7 @@ Require-Bundle: com.sap.sailing.domain, com.sap.sailing.domain.shared.android, com.sap.sailing.server.trackfiles, com.sap.sse.common -Import-Package: org.osgi.framework +Import-Package: com.sap.sailing.declination, + org.osgi.framework Bundle-Activator: com.sap.sailing.domain.deckmanadapter.impl.Activator Automatic-Module-Name: com.sap.sailing.domain.deckmanadapter diff --git a/java/com.sap.sailing.domain.deckmanadapter/src/com/sap/sailing/domain/deckmanadapter/Record.java b/java/com.sap.sailing.domain.deckmanadapter/src/com/sap/sailing/domain/deckmanadapter/Record.java index 1f1e20afc4f..6f26009a59d 100755 --- a/java/com.sap.sailing.domain.deckmanadapter/src/com/sap/sailing/domain/deckmanadapter/Record.java +++ b/java/com.sap.sailing.domain.deckmanadapter/src/com/sap/sailing/domain/deckmanadapter/Record.java @@ -1,11 +1,15 @@ package com.sap.sailing.domain.deckmanadapter; +import java.io.IOException; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.sap.sailing.declination.DeclinationService; import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.Positioned; import com.sap.sailing.domain.common.SpeedWithBearing; @@ -16,12 +20,15 @@ import com.sap.sailing.domain.common.impl.WindImpl; import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; import com.sap.sailing.domain.deckmanadapter.impl.FieldType; +import com.sap.sse.common.Bearing; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Timed; import com.sap.sse.common.impl.DegreeBearingImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; public class Record implements Timed, Positioned { + private static final Logger logger = Logger.getLogger(Record.class.getName()); + private static final long serialVersionUID = -7939775022865795801L; private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); @@ -47,9 +54,18 @@ public class Record implements Timed, Positioned { Double.valueOf(this.fieldsAsString.get(FieldType.longitude))); final SpeedWithBearing speed = new KnotSpeedWithBearingImpl(Double.valueOf(this.fieldsAsString.get(FieldType.sog)), new DegreeBearingImpl(Double.valueOf(this.fieldsAsString.get(FieldType.cog)))); + Bearing optionalTrueHeading; + try { + optionalTrueHeading = this.fieldsAsString.get(FieldType.heading) == null ? null : + new DegreeBearingImpl(Double.valueOf(this.fieldsAsString.get(FieldType.heading))).add( + DeclinationService.INSTANCE.getDeclination(timePoint, position, /* timeout in ms */ 1000).getBearingCorrectedTo(timePoint)); + } catch (NumberFormatException | IOException | ParseException e) { + logger.log(Level.WARNING, "Problem obtaining magnetic declination for converting Deckman magnetic heading value to true", e); + optionalTrueHeading = null; + } wind = new WindImpl(position, timePoint, new KnotSpeedWithBearingImpl(Double.valueOf(this.fieldsAsString .get(FieldType.tws)), new DegreeBearingImpl(Double.valueOf(this.fieldsAsString.get(FieldType.twd))))); - gpsFix = new GPSFixMovingImpl(position, timePoint, speed); + gpsFix = new GPSFixMovingImpl(position, timePoint, speed, optionalTrueHeading); } public String getField(FieldType fieldType) { diff --git a/java/com.sap.sailing.domain.deckmanadapter/src/com/sap/sailing/domain/deckmanadapter/impl/DeckmanGPSFixImporter.java b/java/com.sap.sailing.domain.deckmanadapter/src/com/sap/sailing/domain/deckmanadapter/impl/DeckmanGPSFixImporter.java index 5b1c66fbb7f..a5a32d992c8 100755 --- a/java/com.sap.sailing.domain.deckmanadapter/src/com/sap/sailing/domain/deckmanadapter/impl/DeckmanGPSFixImporter.java +++ b/java/com.sap.sailing.domain.deckmanadapter/src/com/sap/sailing/domain/deckmanadapter/impl/DeckmanGPSFixImporter.java @@ -29,7 +29,7 @@ public class DeckmanGPSFixImporter implements GPSFixImporter { try { for (Iterator i = deckmanAdapter.parseLogFile(new InputStreamReader(inputStream)); i.hasNext();) { Record record = i.next(); - callback.addFix(new GPSFixMovingImpl(record.getPosition(), record.getTimePoint(), record.getGpsFix().getSpeed()), + callback.addFix(new GPSFixMovingImpl(record.getPosition(), record.getTimePoint(), record.getGpsFix().getSpeed(), record.getGpsFix().getOptionalTrueHeading()), device); importedFixes.set(true); } diff --git a/java/com.sap.sailing.domain.expeditionadapter/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.expeditionadapter/META-INF/MANIFEST.MF index 94cff8d7e27..7c916e3580f 100755 --- a/java/com.sap.sailing.domain.expeditionadapter/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.expeditionadapter/META-INF/MANIFEST.MF @@ -5,7 +5,8 @@ Bundle-SymbolicName: com.sap.sailing.domain.expeditionadapter Bundle-Version: 1.0.0.qualifier Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Import-Package: org.osgi.framework +Import-Package: com.sap.sailing.declination, + org.osgi.framework Require-Bundle: com.sap.sailing.server.trackfiles, com.sap.sailing.domain, com.sap.sse.common, diff --git a/java/com.sap.sailing.domain.expeditionadapter/src/com/sap/sailing/domain/expeditionadapter/impl/ExpeditionGPSFixImporter.java b/java/com.sap.sailing.domain.expeditionadapter/src/com/sap/sailing/domain/expeditionadapter/impl/ExpeditionGPSFixImporter.java index 2bf5d2c5394..1124cde734c 100755 --- a/java/com.sap.sailing.domain.expeditionadapter/src/com/sap/sailing/domain/expeditionadapter/impl/ExpeditionGPSFixImporter.java +++ b/java/com.sap.sailing.domain.expeditionadapter/src/com/sap/sailing/domain/expeditionadapter/impl/ExpeditionGPSFixImporter.java @@ -5,11 +5,15 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; +import java.text.ParseException; import java.util.Date; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.sap.sailing.declination.DeclinationService; import com.sap.sailing.domain.common.impl.DegreePosition; import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; import com.sap.sailing.domain.common.tracking.GPSFixMoving; @@ -21,13 +25,17 @@ import com.sap.sailing.domain.trackimport.GPSFixImporter; import com.sap.sailing.server.trackfiles.impl.CompressedStreamsUtil; import com.sap.sailing.server.trackfiles.impl.ExpeditionExtendedDataImporterImpl; import com.sap.sailing.server.trackfiles.impl.ExpeditionImportFileHandler; +import com.sap.sse.common.Bearing; import com.sap.sse.common.impl.DegreeBearingImpl; public class ExpeditionGPSFixImporter implements GPSFixImporter { + private static final Logger logger = Logger.getLogger(ExpeditionGPSFixImporter.class.getName()); + private static final String LAT_COLUMN_HEADING = ExpeditionExtendedDataImporterImpl.COL_NAME_LAT; private static final String LON_COLUMN_HEADING = ExpeditionExtendedDataImporterImpl.COL_NAME_LON; private static final String COG_COLUMN_HEADING = "cog"; private static final String SOG_COLUMN_HEADING = "sog"; + private static final String HDT_COLUMN_HEADING = "hdt"; @Override public boolean importFixes(InputStream inputStream, Charset charset, Callback callback, @@ -56,10 +64,23 @@ public class ExpeditionGPSFixImporter implements GPSFixImporter { .parseDouble(columnValues[columns.get(COG_COLUMN_HEADING)]); final double sogKnots = Double .parseDouble(columnValues[columns.get(SOG_COLUMN_HEADING)]); + final DegreePosition position = new DegreePosition(latDeg, lonDeg); + Bearing optionalTrueHeading; + if (columns.containsKey(HDT_COLUMN_HEADING)) { + try { + optionalTrueHeading = new DegreeBearingImpl(Double.parseDouble(columnValues[columns.get(HDT_COLUMN_HEADING)])) + .add(DeclinationService.INSTANCE.getDeclination(timePoint, position, /* timeout ms */ 1000).getBearingCorrectedTo(timePoint)); + } catch (NumberFormatException | IOException | ParseException e) { + logger.log(Level.WARNING, "Problem obtaining declination for Expedition fix heading", e); + optionalTrueHeading = null; + } + } else { + optionalTrueHeading = null; + } final GPSFixMoving fix = new GPSFixMovingImpl( - new DegreePosition(latDeg, lonDeg), timePoint, + position, timePoint, new KnotSpeedWithBearingImpl(sogKnots, - new DegreeBearingImpl(cogDeg))); + new DegreeBearingImpl(cogDeg)), optionalTrueHeading); callback.addFix(fix, device); importedFixes.set(true); }); diff --git a/java/com.sap.sailing.domain.oceanraceadapter/src/com/sap/sailing/domain/oceanraceadapter/impl/OceanRaceGPSFixImporter.java b/java/com.sap.sailing.domain.oceanraceadapter/src/com/sap/sailing/domain/oceanraceadapter/impl/OceanRaceGPSFixImporter.java index afc428abd4f..24d9cd30277 100755 --- a/java/com.sap.sailing.domain.oceanraceadapter/src/com/sap/sailing/domain/oceanraceadapter/impl/OceanRaceGPSFixImporter.java +++ b/java/com.sap.sailing.domain.oceanraceadapter/src/com/sap/sailing/domain/oceanraceadapter/impl/OceanRaceGPSFixImporter.java @@ -100,7 +100,7 @@ public class OceanRaceGPSFixImporter implements GPSFixImporter { } else { sogInKnots = 0.0; } - return new GPSFixMovingImpl(position, timePoint, new KnotSpeedWithBearingImpl(sogInKnots, cog)); + return new GPSFixMovingImpl(position, timePoint, new KnotSpeedWithBearingImpl(sogInKnots, cog), /* optionalTrueHeading */ null); } @Override diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/FieldNames.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/FieldNames.java index 3beb5eabf62..f3e43b80951 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/FieldNames.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/FieldNames.java @@ -3,7 +3,7 @@ package com.sap.sailing.domain.persistence; public enum FieldNames { // general: - TIME_AS_MILLIS, KNOT_SPEED, DEGREE_BEARING, LAT_DEG, LNG_DEG, + TIME_AS_MILLIS, KNOT_SPEED, DEGREE_BEARING, LAT_DEG, LNG_DEG, TRUE_HEADING_DEG, FLEET, RACE_IDENTIFIERS, diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index bdafdab831d..f0d11fe39be 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -389,6 +389,16 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return new KnotSpeedWithBearingImpl(((Number) object.get(FieldNames.KNOT_SPEED.name())).doubleValue(), new DegreeBearingImpl(((Number) object.get(FieldNames.DEGREE_BEARING.name())).doubleValue())); } + + public Bearing loadOptionalTrueHeading(Document object) { + final Bearing result; + if (object.containsKey(FieldNames.TRUE_HEADING_DEG.name())) { + result = new DegreeBearingImpl(((Number) object.get(FieldNames.TRUE_HEADING_DEG.name())).doubleValue()); + } else { + result = null; + } + return result; + } @Override public RaceIdentifier loadRaceIdentifier(Document dbObject) { diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index 7bfb2f448a9..556ce2c4f4c 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -238,7 +238,12 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { public void storeSpeedWithBearing(SpeedWithBearing speedWithBearing, Document result) { storeSpeed(speedWithBearing, result); storeBearing(speedWithBearing.getBearing(), result); - + } + + public void storeOptionalTrueHeading(Bearing optionalTrueHeading, Document result) { + if (optionalTrueHeading != null) { + result.put(FieldNames.TRUE_HEADING_DEG.name(), optionalTrueHeading.getDegrees()); + } } public void storeBearing(Bearing bearing, Document result) { diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/racelog/tracking/impl/GPSFixMovingMongoHandlerImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/racelog/tracking/impl/GPSFixMovingMongoHandlerImpl.java index 577024c2ec0..b44fc7e4e2b 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/racelog/tracking/impl/GPSFixMovingMongoHandlerImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/racelog/tracking/impl/GPSFixMovingMongoHandlerImpl.java @@ -1,5 +1,7 @@ package com.sap.sailing.domain.persistence.racelog.tracking.impl; +import static com.sap.sailing.shared.persistence.impl.DomainObjectFactoryImpl.loadPosition; + import org.bson.Document; import com.sap.sailing.domain.common.Position; @@ -11,7 +13,7 @@ import com.sap.sailing.domain.persistence.MongoObjectFactory; import com.sap.sailing.domain.persistence.impl.DomainObjectFactoryImpl; import com.sap.sailing.domain.persistence.impl.MongoObjectFactoryImpl; import com.sap.sailing.domain.persistence.racelog.tracking.FixMongoHandler; -import static com.sap.sailing.shared.persistence.impl.DomainObjectFactoryImpl.loadPosition; +import com.sap.sse.common.Bearing; import com.sap.sse.common.TimePoint; public class GPSFixMovingMongoHandlerImpl implements FixMongoHandler { @@ -27,17 +29,19 @@ public class GPSFixMovingMongoHandlerImpl implements FixMongoHandler 0); @@ -721,7 +716,7 @@ public class SensorFixStoreAndLoadTest { final SpeedWithBearing doubledSpeed = speed.add(speed); final GPSFixMoving fix3Faster = new GPSFixMovingImpl( pos2.translateGreatCircle(course, doubledSpeed.travel(timePoint2.until(timePoint3))), - timePoint3, doubledSpeed); + timePoint3, doubledSpeed, /* optionalTrueHeading */ null); gpsFixTrack.add(fix3Faster, /* replace */ true); final Distance distanceTraveledFaster = gpsFixTrack.getDistanceTraveled(timePoint, timePoint3); assertTrue(distanceTraveledFaster.compareTo(distanceTraveled) > 0); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreTest.java index 98b9ffaec64..585aaa15ca1 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreTest.java @@ -18,13 +18,9 @@ import com.mongodb.ReadConcern; import com.mongodb.WriteConcern; import com.mongodb.client.MongoDatabase; import com.sap.sailing.domain.common.DeviceIdentifier; -import com.sap.sailing.domain.common.impl.DegreePosition; -import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; import com.sap.sailing.domain.common.sensordata.BravoSensorDataMetadata; import com.sap.sailing.domain.common.tracking.DoubleVectorFix; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.common.tracking.impl.DoubleVectorFixImpl; -import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; import com.sap.sailing.domain.persistence.PersistenceFactory; import com.sap.sailing.domain.persistence.impl.CollectionNames; import com.sap.sailing.domain.persistence.racelog.tracking.impl.MongoSensorFixStoreImpl; @@ -35,7 +31,6 @@ import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifie import com.sap.sse.common.NoCorrespondingServiceRegisteredException; import com.sap.sse.common.Timed; import com.sap.sse.common.TransformationException; -import com.sap.sse.common.impl.DegreeBearingImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.common.impl.TimeRangeImpl; @@ -49,11 +44,6 @@ public class SensorFixStoreTest { protected final DeviceIdentifier device2 = new SmartphoneImeiIdentifier("b"); protected SensorFixStore store; - protected GPSFixMoving createFix(long millis, double lat, double lng, double knots, double degrees) { - return new GPSFixMovingImpl(new DegreePosition(lat, lng), new MillisecondsTimePoint(millis), - new KnotSpeedWithBearingImpl(knots, new DegreeBearingImpl(degrees))); - } - @Before public void setUp() throws UnknownHostException, MongoException { dropPersistedData(); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/manual/PostFixes.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/manual/PostFixes.java index accaae52048..6147b9e19e2 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/manual/PostFixes.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/manual/PostFixes.java @@ -88,7 +88,7 @@ public class PostFixes extends AbstractJsonOverHttpTest { lastFix = fix; try { - recordFix(new GPSFixMovingImpl(fix.getPosition(), fix.getTimePoint(), speed)); + recordFix(new GPSFixMovingImpl(fix.getPosition(), fix.getTimePoint(), speed, /* optionalTrueHeading */ null)); } catch (IOException e) { e.printStackTrace(); } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java index 37d42af7854..c3ec998018c 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java @@ -379,7 +379,7 @@ public class DomainFactoryImpl implements DomainFactory { @Override public GPSFixMoving createGPSFix(TimePoint timePointOfTransmission, Fix fix) { GPSFixMoving result = new GPSFixMovingImpl(fix.getPosition(), new MillisecondsTimePoint( - timePointOfTransmission.asMillis() + fix.getAgeOfDataInMilliseconds()), fix.getSpeed()); + timePointOfTransmission.asMillis() + fix.getAgeOfDataInMilliseconds()), fix.getSpeed(), /* optionalTrueHeading */ null); return result; } diff --git a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java index 52626664962..91e1446af89 100755 --- a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java +++ b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java @@ -494,7 +494,7 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter i TimePoint raceTimePoint = raceTimePerRaceID.containsKey(currentRaceID) ? raceTimePerRaceID.get(currentRaceID) : referenceTimePoint; Bearing bearing = new DegreeBearingImpl(cog); SpeedWithBearing speed = new KnotSpeedWithBearingImpl(((double) sog_Knots_x10) / 10., bearing); - GPSFixMoving fix = new GPSFixMovingImpl(position, raceTimePoint, speed); + GPSFixMoving fix = new GPSFixMovingImpl(position, raceTimePoint, speed, /* optionalTrueHeading */ null); Mark mark = markByHashValue.get(hashValue); if (mark != null) { Iterator> i = windAtControlPoint.entrySet().iterator(); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImplWhiteBoxTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImplWhiteBoxTest.java index f2bc1915824..be89bc6d489 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImplWhiteBoxTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImplWhiteBoxTest.java @@ -188,9 +188,9 @@ public class CandidateFinderImplWhiteBoxTest { final Position beforeStartPosition = startLinePosition.translateGreatCircle(startLineCrossingSpeed.getBearing().reverse(), startLineCrossingSpeed.travel(Duration.ONE_SECOND)); final Position atStartPosition = startLinePosition; final Position afterStartPosition = startLinePosition.translateGreatCircle(startLineCrossingSpeed.getBearing(), startLineCrossingSpeed.travel(Duration.ONE_SECOND)); - trackedRace.getTrack(competitor).add(new GPSFixMovingImpl(beforeStartPosition, timeForStartLinePassing.minus(Duration.ONE_SECOND), startLineCrossingSpeed)); - trackedRace.getTrack(competitor).add(new GPSFixMovingImpl(atStartPosition, timeForStartLinePassing, startLineCrossingSpeed)); - trackedRace.getTrack(competitor).add(new GPSFixMovingImpl(afterStartPosition, timeForStartLinePassing.plus(Duration.ONE_SECOND), startLineCrossingSpeed)); + trackedRace.getTrack(competitor).add(new GPSFixMovingImpl(beforeStartPosition, timeForStartLinePassing.minus(Duration.ONE_SECOND), startLineCrossingSpeed, /* optionalTrueHeading */ null)); + trackedRace.getTrack(competitor).add(new GPSFixMovingImpl(atStartPosition, timeForStartLinePassing, startLineCrossingSpeed, /* optionalTrueHeading */ null)); + trackedRace.getTrack(competitor).add(new GPSFixMovingImpl(afterStartPosition, timeForStartLinePassing.plus(Duration.ONE_SECOND), startLineCrossingSpeed, /* optionalTrueHeading */ null)); } @Test diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/StationarySequenceBasedFilterTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/StationarySequenceBasedFilterTest.java index 082c3959d80..834d97a593a 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/StationarySequenceBasedFilterTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/StationarySequenceBasedFilterTest.java @@ -50,7 +50,7 @@ public class StationarySequenceBasedFilterTest extends AbstractCandidateFilterTe if (previousTimePoint != null) { position = verySmallSpeed.travelTo(position, durationBetweenFixes); } - track.add(new GPSFixMovingImpl(position, timePoint, verySmallSpeed)); + track.add(new GPSFixMovingImpl(position, timePoint, verySmallSpeed, /* optionalTrueHeading */ null)); timePoint = timePoint.plus(durationBetweenFixes); } previousTimePoint = candidate.getTimePoint(); @@ -88,7 +88,7 @@ public class StationarySequenceBasedFilterTest extends AbstractCandidateFilterTe outlierCourse, StationarySequence.CANDIDATE_FILTER_DISTANCE.scale(2)); final TimePoint inBetweenTimePoint = fixAtC2.getTimePoint().plus(fixAtC2.getTimePoint().until(fixAfterFixAtC2.getTimePoint()).divide(2)); final Speed outlierSpeed = fixAtC2.getPosition().getDistance(outlierPosition).inTime(fixAtC2.getTimePoint().until(inBetweenTimePoint)); - final GPSFixMoving fixInBetween = new GPSFixMovingImpl(outlierPosition, inBetweenTimePoint, new KnotSpeedWithBearingImpl(outlierSpeed.getKnots(), outlierCourse)); + final GPSFixMoving fixInBetween = new GPSFixMovingImpl(outlierPosition, inBetweenTimePoint, new KnotSpeedWithBearingImpl(outlierSpeed.getKnots(), outlierCourse), /* optionalTrueHeading */ null); track.add(fixInBetween); TreeSet candidatesEffectivelyAdded = new TreeSet<>(candidateComparator); TreeSet candidatesEffectivelyRemoved = new TreeSet<>(candidateComparator); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/StationarySequenceTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/StationarySequenceTest.java index 8bc1a670ade..084b6ae05a8 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/StationarySequenceTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/StationarySequenceTest.java @@ -69,7 +69,7 @@ public class StationarySequenceTest extends AbstractCandidateFilterTestSupport { if (previousTimePoint != null) { position = verySmallSpeed.travelTo(position, durationBetweenFixes); } - track.add(new GPSFixMovingImpl(position, timePoint, verySmallSpeed)); + track.add(new GPSFixMovingImpl(position, timePoint, verySmallSpeed, /* optionalTrueHeading */ null)); timePoint = timePoint.plus(durationBetweenFixes); } previousTimePoint = candidate.getTimePoint(); @@ -108,7 +108,7 @@ public class StationarySequenceTest extends AbstractCandidateFilterTestSupport { final Position originalPosition = track.getEstimatedPosition(timePointForNewFix, /* extrapolate */ false); final Position westPosition = originalPosition.translateGreatCircle(new DegreeBearingImpl(270), StationarySequence.CANDIDATE_FILTER_DISTANCE.scale(0.5)); final Position eastPosition = originalPosition.translateGreatCircle(new DegreeBearingImpl(90), StationarySequence.CANDIDATE_FILTER_DISTANCE.scale(0.5)); - final GPSFixMovingImpl westFix = new GPSFixMovingImpl(westPosition, timePointForNewFix, originalPosition.getSpeedWithBearingToReachOnGreatCircle(westPosition, c2.getTimePoint().until(timePointForNewFix))); + final GPSFixMovingImpl westFix = new GPSFixMovingImpl(westPosition, timePointForNewFix, originalPosition.getSpeedWithBearingToReachOnGreatCircle(westPosition, c2.getTimePoint().until(timePointForNewFix)), /* optionalTrueHeading */ null); track.add(westFix); final Set candidatesEffectivelyAdded = new HashSet<>(); final Set candidatesEffectivelyRemoved = new HashSet<>(); @@ -118,7 +118,7 @@ public class StationarySequenceTest extends AbstractCandidateFilterTestSupport { assertEquals(3, Util.size(stationarySequence.getAllCandidates())); // and all candidates should still be part of the sequence assertTrue(candidatesEffectivelyAdded.isEmpty()); assertTrue(candidatesEffectivelyRemoved.isEmpty()); - final GPSFixMovingImpl eastFix = new GPSFixMovingImpl(eastPosition, timePointForNewFix, originalPosition.getSpeedWithBearingToReachOnGreatCircle(eastPosition, c2.getTimePoint().until(timePointForNewFix))); + final GPSFixMovingImpl eastFix = new GPSFixMovingImpl(eastPosition, timePointForNewFix, originalPosition.getSpeedWithBearingToReachOnGreatCircle(eastPosition, c2.getTimePoint().until(timePointForNewFix)), /* optionalTrueHeading */ null); track.add(eastFix, /* replace */ true); final StationarySequence resultForEastFix = stationarySequence.tryToAddFix(eastFix, candidatesEffectivelyAdded, candidatesEffectivelyRemoved, stationarySequenceSetToUpdate, /* isReplacement */ true); assertNull(resultForEastFix); // again no split should have been necessary diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestCrossFleetScoring.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestCrossFleetScoring.java index 6406e5b65d8..d00cbfacae3 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestCrossFleetScoring.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestCrossFleetScoring.java @@ -232,7 +232,7 @@ public class TestCrossFleetScoring extends LeaderboardScoringAndRankingTestBase Competitor competitor = competitors.get(competitorName); MarkPassingImpl markPassing = new MarkPassingImpl(startOfRace, start, competitor); GPSFixMovingImpl gpsFix = new GPSFixMovingImpl(new DegreePosition(0.0, 0), startOfRace, - new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(45))); + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(45)), /* optionalTrueHeading */ null); addMarkPassingAndGPSFix(competitorsAndMarkPassingsWithGpsFixes, competitor, markPassing, gpsFix); } @@ -257,7 +257,7 @@ public class TestCrossFleetScoring extends LeaderboardScoringAndRankingTestBase Map, List>> competitorsAndMarkPassingsWithGpsFixes, String competitorName, DegreePosition position, TimePoint timePoint) { GPSFixMovingImpl gpsFix = new GPSFixMovingImpl(position, timePoint, - new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(45))); + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(45)), /* optionalTrueHeading */ null); competitorsAndMarkPassingsWithGpsFixes.get(competitors.get(competitorName)).getB().add(gpsFix); } @@ -478,13 +478,13 @@ public class TestCrossFleetScoring extends LeaderboardScoringAndRankingTestBase Competitor fastYellow = competitors.get("FastYellowBoat"); MarkPassingImpl markPassingFastYellow = new MarkPassingImpl(markRounding, windward, fastYellow); GPSFixMovingImpl gpsFixFastYellow = new GPSFixMovingImpl(new DegreePosition(1.0, 0), markRounding, - new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(180))); + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(180)), /* optionalTrueHeading */ null); addMarkPassingAndGPSFix(competitorsAndMarkPassingsWithGpsFixes, fastYellow, markPassingFastYellow, gpsFixFastYellow); // markRounding for SlowYellow Competitor slowYellow = competitors.get("SlowYellowBoat"); MarkPassingImpl markPassingSlowYellow = new MarkPassingImpl(markRounding, windward, slowYellow); GPSFixMovingImpl gpsFixSlowYellow = new GPSFixMovingImpl(new DegreePosition(1.0, 0), markRounding, - new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(180))); + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(180)), /* optionalTrueHeading */ null); addMarkPassingAndGPSFix(competitorsAndMarkPassingsWithGpsFixes, slowYellow, markPassingSlowYellow, gpsFixSlowYellow); // add current Position appendGPSFixForCompetitor(competitorsAndMarkPassingsWithGpsFixes, "FastYellowBoat", new DegreePosition(0.4, 0), @@ -516,25 +516,25 @@ public class TestCrossFleetScoring extends LeaderboardScoringAndRankingTestBase Competitor fastYellow = competitors.get("FastYellowBoat"); MarkPassingImpl markPassingFastYellow = new MarkPassingImpl(markRounding, windward, fastYellow); GPSFixMovingImpl gpsFixFastYellow = new GPSFixMovingImpl(new DegreePosition(1.0, 0), markRounding, - new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(180))); + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(180)), /* optionalTrueHeading */ null); addMarkPassingAndGPSFix(competitorsAndMarkPassingsWithGpsFixes, fastYellow, markPassingFastYellow, gpsFixFastYellow); // markRounding for SlowYellow Competitor slowYellow = competitors.get("SlowYellowBoat"); MarkPassingImpl markPassingSlowYellow = new MarkPassingImpl(markRounding, windward, slowYellow); GPSFixMovingImpl gpsFixSlowYellow = new GPSFixMovingImpl(new DegreePosition(1.0, 0), markRounding, - new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(180))); + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(180)), /* optionalTrueHeading */ null); addMarkPassingAndGPSFix(competitorsAndMarkPassingsWithGpsFixes, slowYellow, markPassingSlowYellow, gpsFixSlowYellow); // markRounding for FastBlue Competitor fastBlue = competitors.get("FastYellowBoat"); MarkPassingImpl markPassingFastBlue = new MarkPassingImpl(markRounding, windward, fastBlue); GPSFixMovingImpl gpsFixFastBlue = new GPSFixMovingImpl(new DegreePosition(1.0, 0), markRounding, - new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(180))); + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(180)), /* optionalTrueHeading */ null); addMarkPassingAndGPSFix(competitorsAndMarkPassingsWithGpsFixes, fastBlue, markPassingFastBlue, gpsFixFastBlue); // markRounding for SlowYellow Competitor slowBlue = competitors.get("SlowYellowBoat"); MarkPassingImpl markPassingSlowslowBlue = new MarkPassingImpl(markRounding, windward, slowBlue); GPSFixMovingImpl gpsFixSlowslowBlue = new GPSFixMovingImpl(new DegreePosition(1.0, 0), markRounding, - new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(180))); + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(180)), /* optionalTrueHeading */ null); addMarkPassingAndGPSFix(competitorsAndMarkPassingsWithGpsFixes, slowBlue, markPassingSlowslowBlue, gpsFixSlowslowBlue); // add current Position appendGPSFixForCompetitor(competitorsAndMarkPassingsWithGpsFixes, "FastYellowBoat", new DegreePosition(0.1, 0), diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java index 97eabc7d30a..4d725523152 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java @@ -154,16 +154,16 @@ public class TestFarthestAheadWithSkippedMarkPassing { Arrays. asList(new MarkPassingImpl(startOfRace, start, c1))); trackedRace.getTrack(c1).add( new GPSFixMovingImpl(new DegreePosition(0.0, 0), startOfRace, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(45)))); + new DegreeBearingImpl(45)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c2).add( new GPSFixMovingImpl(new DegreePosition(0.0, 0), startOfRace, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(315)))); + new DegreeBearingImpl(315)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c1).add( new GPSFixMovingImpl(new DegreePosition(0.5, 0), middleOfFirstLeg, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(45)))); + new DegreeBearingImpl(45)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c2).add( new GPSFixMovingImpl(new DegreePosition(0.5, 0), middleOfFirstLeg, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(315)))); + new DegreeBearingImpl(315)), /* optionalTrueHeading */ null)); // Both boats have climbed half of the first upwind beat; c1 is rated the faster boat (2.0), c2 has time-on-time factor 1.0. // Therefore, c2 is expected to lead after applying the corrections. final RankingInfo rankingInfo = rankingMetric.getRankingInfo(middleOfFirstLeg); @@ -192,24 +192,24 @@ public class TestFarthestAheadWithSkippedMarkPassing { // they both start at the start line trackedRace.getTrack(c1).add( new GPSFixMovingImpl(new DegreePosition(0.0, 0), startOfRace, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(45)))); + new DegreeBearingImpl(45)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c2).add( new GPSFixMovingImpl(new DegreePosition(0.0, 0), startOfRace, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(315)))); + new DegreeBearingImpl(315)), /* optionalTrueHeading */ null)); // both round the windward mark at the same time trackedRace.getTrack(c1).add( new GPSFixMovingImpl(new DegreePosition(1.0, 0), endOfFirstLeg, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(45)))); + new DegreeBearingImpl(45)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c2).add( new GPSFixMovingImpl(new DegreePosition(1.0, 0), endOfFirstLeg, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(315)))); + new DegreeBearingImpl(315)), /* optionalTrueHeading */ null)); // c2 is further down the wind already at the middle of the second leg: trackedRace.getTrack(c1).add( new GPSFixMovingImpl(new DegreePosition(0.5, 0), middleOfSecondLeg, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(180)))); + new DegreeBearingImpl(180)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c2).add( new GPSFixMovingImpl(new DegreePosition(0.2, 0), middleOfSecondLeg, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(180)))); + new DegreeBearingImpl(180)), /* optionalTrueHeading */ null)); // Assert that c2 is the boat farthest ahead final RankingInfo rankingInfo = rankingMetric.getRankingInfo(middleOfSecondLeg); assertSame(c2, rankingInfo.getCompetitorFarthestAhead()); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestSimpleTimeOnTimeRankingWithOneUpwindLeg.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestSimpleTimeOnTimeRankingWithOneUpwindLeg.java index c3dd8e27d3c..97829c9d0da 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestSimpleTimeOnTimeRankingWithOneUpwindLeg.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestSimpleTimeOnTimeRankingWithOneUpwindLeg.java @@ -129,16 +129,16 @@ public class TestSimpleTimeOnTimeRankingWithOneUpwindLeg { .getFirstWaypoint(), c2))); trackedRace.getTrack(c1).add( new GPSFixMovingImpl(new DegreePosition(0.0, 0), startOfRace, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(45)))); + new DegreeBearingImpl(45)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c2).add( new GPSFixMovingImpl(new DegreePosition(0.0, 0), startOfRace, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(315)))); + new DegreeBearingImpl(315)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c1).add( new GPSFixMovingImpl(new DegreePosition(0.5, 0), middleOfFirstLeg, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(45)))); + new DegreeBearingImpl(45)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c2).add( new GPSFixMovingImpl(new DegreePosition(0.5, 0), middleOfFirstLeg, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(315)))); + new DegreeBearingImpl(315)), /* optionalTrueHeading */ null)); // Both boats have climbed half of the first upwind beat; c1 is rated the faster boat (2.0), c2 has time-on-time factor 1.0. // Therefore, c2 is expected to lead after applying the corrections. Comparator comparator = tot.getRaceRankingComparator(middleOfFirstLeg); @@ -160,16 +160,16 @@ public class TestSimpleTimeOnTimeRankingWithOneUpwindLeg { .getFirstWaypoint(), c2))); trackedRace.getTrack(c1).add( new GPSFixMovingImpl(new DegreePosition(0.0, 0), startOfRace, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(45)))); + new DegreeBearingImpl(45)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c2).add( new GPSFixMovingImpl(new DegreePosition(0.0, 0), startOfRace, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(315)))); + new DegreeBearingImpl(315)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c1).add( new GPSFixMovingImpl(new DegreePosition(1.0, 0), middleOfFirstLeg, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(45)))); + new DegreeBearingImpl(45)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c2).add( new GPSFixMovingImpl(new DegreePosition(0.5, 0), middleOfFirstLeg, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(315)))); + new DegreeBearingImpl(315)), /* optionalTrueHeading */ null)); // Using a white-box test, assert that the ranking-relevant numbers are sufficiently close to each other final RankingMetric.RankingInfo rankingInfo = tot.getRankingInfo(middleOfFirstLeg); assertSame(c1, rankingInfo.getCompetitorFarthestAhead()); @@ -195,16 +195,16 @@ public class TestSimpleTimeOnTimeRankingWithOneUpwindLeg { .getFirstWaypoint(), c2))); trackedRace.getTrack(c1).add( new GPSFixMovingImpl(new DegreePosition(0.0, 0), startOfRace, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(45)))); + new DegreeBearingImpl(45)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c2).add( new GPSFixMovingImpl(new DegreePosition(0.0, 0), startOfRace, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(315)))); + new DegreeBearingImpl(315)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c1).add( new GPSFixMovingImpl(new DegreePosition(0.5, 0), middleOfFirstLeg, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(45)))); + new DegreeBearingImpl(45)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c2).add( new GPSFixMovingImpl(new DegreePosition(0.5, 0), middleOfFirstLeg, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(315)))); + new DegreeBearingImpl(315)), /* optionalTrueHeading */ null)); // Both boats have climbed half of the first upwind beat; c1 is rated the faster boat (2.0), c2 has time-on-time factor 1.0. // Therefore, c2 is expected to lead after applying the corrections. Comparator comparator = tot.getRaceRankingComparator(middleOfFirstLeg); @@ -226,16 +226,16 @@ public class TestSimpleTimeOnTimeRankingWithOneUpwindLeg { .getFirstWaypoint(), c2))); trackedRace.getTrack(c1).add( new GPSFixMovingImpl(new DegreePosition(0.0, 0), startOfRace, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(45)))); + new DegreeBearingImpl(45)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c2).add( new GPSFixMovingImpl(new DegreePosition(0.0, 0), startOfRace, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(315)))); + new DegreeBearingImpl(315)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c1).add( new GPSFixMovingImpl(new DegreePosition(1.0, 0), middleOfFirstLeg, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(45)))); + new DegreeBearingImpl(45)), /* optionalTrueHeading */ null)); trackedRace.getTrack(c2).add( new GPSFixMovingImpl(new DegreePosition(0.5, 0), middleOfFirstLeg, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(315)))); + new DegreeBearingImpl(315)), /* optionalTrueHeading */ null)); // Using a white-box test, assert that the ranking-relevant numbers are sufficiently close to each other, // in this case .05 seconds per nautical mile for the reciproke VMG measured in seconds per nautical mile final RankingMetric.RankingInfo rankingInfo = tot.getRankingInfo(middleOfFirstLeg); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/BravoFixTrackFoiledDistanceCacheTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/BravoFixTrackFoiledDistanceCacheTest.java index e6a3e28c3b1..57007af3551 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/BravoFixTrackFoiledDistanceCacheTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/BravoFixTrackFoiledDistanceCacheTest.java @@ -220,7 +220,7 @@ public class BravoFixTrackFoiledDistanceCacheTest { private GPSFixMoving createGPSFix(long timePointAsMillis, double lat, double lng, double cogInDeg, double sogInKnots) { return new GPSFixMovingImpl(new DegreePosition(lat, lng), new MillisecondsTimePoint(timePointAsMillis), - new KnotSpeedWithBearingImpl(sogInKnots, new DegreeBearingImpl(cogInDeg))); + new KnotSpeedWithBearingImpl(sogInKnots, new DegreeBearingImpl(cogInDeg)), /* optionalTrueHeading */ null); } private MillisecondsTimePoint t(long timePointAsMillis) { diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseChangeBasedTrackApproximationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseChangeBasedTrackApproximationTest.java index 359d40cc782..fcef8b395e6 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseChangeBasedTrackApproximationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseChangeBasedTrackApproximationTest.java @@ -61,12 +61,12 @@ public class CourseChangeBasedTrackApproximationTest { } private GPSFixMoving fix(long timepoint, double lat, double lon, double speedInKnots, double cogDeg) { - return new GPSFixMovingImpl(new DegreePosition(lat, lon), new MillisecondsTimePoint(timepoint), new KnotSpeedWithBearingImpl(speedInKnots, new DegreeBearingImpl(cogDeg))); + return new GPSFixMovingImpl(new DegreePosition(lat, lon), new MillisecondsTimePoint(timepoint), new KnotSpeedWithBearingImpl(speedInKnots, new DegreeBearingImpl(cogDeg)), /* optionalTrueHeading */ null); } private GPSFixMoving travel(GPSFixMoving fix, long durationInMillis, double speedInKnots, double cogDeg) { return new GPSFixMovingImpl(fix.getPosition().translateGreatCircle(new DegreeBearingImpl(cogDeg), new KnotSpeedImpl(speedInKnots).travel(new MillisecondsDurationImpl(durationInMillis))), - fix.getTimePoint().plus(durationInMillis), new KnotSpeedWithBearingImpl(speedInKnots, new DegreeBearingImpl(cogDeg))); + fix.getTimePoint().plus(durationInMillis), new KnotSpeedWithBearingImpl(speedInKnots, new DegreeBearingImpl(cogDeg)), /* optionalTrueHeading */ null); } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DistanceCacheInvalidationAfterLoadingFinishedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DistanceCacheInvalidationAfterLoadingFinishedTest.java index 68b862a2208..58b61e9711c 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DistanceCacheInvalidationAfterLoadingFinishedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DistanceCacheInvalidationAfterLoadingFinishedTest.java @@ -57,9 +57,9 @@ public class DistanceCacheInvalidationAfterLoadingFinishedTest extends TrackBase final Position startPos = new DegreePosition(0, 0); final DegreeBearingImpl bearing = new DegreeBearingImpl(10); final KnotSpeedWithBearingImpl speed = new KnotSpeedWithBearingImpl(10, bearing); - trackedRace.recordFix(competitor, new GPSFixMovingImpl(startPos, now, speed)); + trackedRace.recordFix(competitor, new GPSFixMovingImpl(startPos, now, speed, /* optionalTrueHeading */ null)); final Distance distance = speed.travel(Duration.ONE_SECOND); - trackedRace.recordFix(competitor, new GPSFixMovingImpl(startPos.translateGreatCircle(bearing, distance), now.plus(Duration.ONE_SECOND), speed)); + trackedRace.recordFix(competitor, new GPSFixMovingImpl(startPos.translateGreatCircle(bearing, distance), now.plus(Duration.ONE_SECOND), speed, /* optionalTrueHeading */ null)); trackedRace.onStatusChanged(tdl, new TrackedRaceStatusImpl(TrackedRaceStatusEnum.TRACKING, /* progress */ 1.0)); assertEquals(distance.getMeters(), trackedRace.getDistanceTraveled(competitor, now.plus(Duration.ONE_SECOND.times(2))).getMeters(), 0.01); // ask 1s after the second fix } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LineAnalysisTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LineAnalysisTest.java index 47ba2ace978..d559226fbe1 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LineAnalysisTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LineAnalysisTest.java @@ -70,7 +70,7 @@ public class LineAnalysisTest extends TrackBasedTest { final Position lineMiddle = leftPos.translateGreatCircle(lineBearingFromLeftToRight, leftPos.getDistance(rightPos).scale(0.5)); final Distance distanceBehindLine = new MeterDistance(10); final Position behindMiddleOfLine = lineMiddle.translateGreatCircle(awayFromCourseSideOrthogonalToLine, distanceBehindLine); - trackedRace.getTrack(competitor).add(new GPSFixMovingImpl(behindMiddleOfLine, now, new KnotSpeedWithBearingImpl(5, new DegreeBearingImpl(45)))); + trackedRace.getTrack(competitor).add(new GPSFixMovingImpl(behindMiddleOfLine, now, new KnotSpeedWithBearingImpl(5, new DegreeBearingImpl(45)), /* optionalTrueHeading */ null)); assertEquals(distanceBehindLine.getMeters(), trackedRace.getDistanceToStartLine(competitor, now).getMeters(), 0.01); } @@ -85,7 +85,7 @@ public class LineAnalysisTest extends TrackBasedTest { final Position outsideOfLine = rightPos.translateGreatCircle(lineBearingFromLeftToRight, new MeterDistance(30)); // 30m right of start boat final Distance distanceBehindLine = new MeterDistance(10); final Position behindOutsideOfLine = outsideOfLine.translateGreatCircle(awayFromCourseSideOrthogonalToLine, distanceBehindLine); - trackedRace.getTrack(competitor).add(new GPSFixMovingImpl(behindOutsideOfLine, now, new KnotSpeedWithBearingImpl(5, new DegreeBearingImpl(45)))); + trackedRace.getTrack(competitor).add(new GPSFixMovingImpl(behindOutsideOfLine, now, new KnotSpeedWithBearingImpl(5, new DegreeBearingImpl(45)), /* optionalTrueHeading */ null)); // the distance is that of the hypotenuse formed by the two cathesuses of 10m and 30m length, respectively: assertEquals(Math.sqrt(10.*10.+30.*30.), trackedRace.getDistanceToStartLine(competitor, now).getMeters(), 0.01); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MarkPositionTimeFilterTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MarkPositionTimeFilterTest.java index 57fd95b851e..272fd938411 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MarkPositionTimeFilterTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MarkPositionTimeFilterTest.java @@ -51,7 +51,7 @@ public class MarkPositionTimeFilterTest { @Test public void testAddFixForMark() { trackedRace.recordFix(m, new GPSFixMovingImpl(new DegreePosition(12, 13), MillisecondsTimePoint.now(), - new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))), /* onlyWhenInTrackingInterval */ true); + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null), /* onlyWhenInTrackingInterval */ true); track.lockForRead(); try { assertEquals(1, track.getRawFixes().size()); @@ -68,7 +68,7 @@ public class MarkPositionTimeFilterTest { when(trackedRace.getStartOfTracking()).thenReturn(start); when(trackedRace.getEndOfTracking()).thenReturn(end); trackedRace.recordFix(m, new GPSFixMovingImpl(new DegreePosition(12, 13), fix, - new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))), /* onlyWhenInTrackingInterval */ true); + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null), /* onlyWhenInTrackingInterval */ true); track.lockForRead(); try { assertEquals(1, track.getRawFixes().size()); @@ -85,7 +85,7 @@ public class MarkPositionTimeFilterTest { when(trackedRace.getStartOfTracking()).thenReturn(start); when(trackedRace.getEndOfTracking()).thenReturn(end); trackedRace.recordFix(m, new GPSFixMovingImpl(new DegreePosition(12, 13), fix, - new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))), /* onlyWhenInTrackingInterval */ true); + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null), /* onlyWhenInTrackingInterval */ true); track.lockForRead(); try { assertTrue(track.getRawFixes().isEmpty()); @@ -102,7 +102,7 @@ public class MarkPositionTimeFilterTest { when(trackedRace.getStartOfTracking()).thenReturn(start); when(trackedRace.getEndOfTracking()).thenReturn(end); trackedRace.recordFix(m, new GPSFixMovingImpl(new DegreePosition(12, 13), fix, - new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))), /* onlyWhenInTrackingInterval */ true); + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null), /* onlyWhenInTrackingInterval */ true); track.lockForRead(); try { assertTrue(track.getRawFixes().isEmpty()); @@ -111,7 +111,7 @@ public class MarkPositionTimeFilterTest { } when(trackedRace.getEndOfTracking()).thenReturn(fix.plus(10000)); trackedRace.recordFix(m, new GPSFixMovingImpl(new DegreePosition(12, 13), fix, - new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))), /* onlyWhenInTrackingInterval */ true); + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null), /* onlyWhenInTrackingInterval */ true); track.lockForRead(); try { assertEquals(1, track.getRawFixes().size()); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/PositionTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/PositionTest.java index ae65e8689d2..3d1c15c5962 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/PositionTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/PositionTest.java @@ -64,7 +64,7 @@ public class PositionTest { public void testEqualityBetweenCompactAndVerboseSpeedWithBearing() throws CompactionNotPossibleException { Position p1 = new DegreePosition(49.2, 008.3); SpeedWithBearing swb = new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123)); - VeryCompactGPSFixMovingImpl compactFix = new VeryCompactGPSFixMovingImpl(p1, MillisecondsTimePoint.now(), swb); + VeryCompactGPSFixMovingImpl compactFix = new VeryCompactGPSFixMovingImpl(p1, MillisecondsTimePoint.now(), swb, /* optionalTrueHeading */ null); assertNotSame(p1, compactFix.getPosition()); PositionAssert.assertPositionEquals(p1, compactFix.getPosition(), 0.000001); assertNotSame(swb, compactFix.getSpeed()); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReachingLegTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReachingLegTest.java index 447a9fd36df..7d6a912c5ae 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReachingLegTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReachingLegTest.java @@ -193,11 +193,11 @@ public class ReachingLegTest extends TrackBasedTest { getTrackedRace().recordFix( hunger, new GPSFixMovingImpl(offsetMarkPos, timePointInReaching, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(270)))); + new DegreeBearingImpl(270)), /* optionalTrueHeading */ null)); getTrackedRace().recordFix( plattner, new GPSFixMovingImpl(windwardMarkPos, timePointInReaching, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(270)))); + new DegreeBearingImpl(270)), /* optionalTrueHeading */ null)); assertEquals(0., getTrackedRace().getTrack(hunger).getEstimatedPosition(timePointInReaching, /* extrapolate */false) .getDistance(offsetMarkPos).getMeters(), 0.00001); @@ -223,11 +223,11 @@ public class ReachingLegTest extends TrackBasedTest { getTrackedRace().recordFix( hunger, new GPSFixMovingImpl(offsetMarkPos, timePointInReaching, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(270)))); + new DegreeBearingImpl(270)), /* optionalTrueHeading */ null)); getTrackedRace().recordFix( plattner, new GPSFixMovingImpl(windwardMarkPos, timePointInReaching, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(270)))); + new DegreeBearingImpl(270)), /* optionalTrueHeading */ null)); assertEquals(0., getTrackedRace().getTrack(hunger).getEstimatedPosition(timePointInReaching, /* extrapolate */false) .getDistance(offsetMarkPos).getMeters(), 0.00001); @@ -253,11 +253,11 @@ public class ReachingLegTest extends TrackBasedTest { getTrackedRace().recordFix( hunger, new GPSFixMovingImpl(offsetMarkPos, timePointInReaching, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(270)))); + new DegreeBearingImpl(270)), /* optionalTrueHeading */ null)); getTrackedRace().recordFix( plattner, new GPSFixMovingImpl(windwardMarkPos, timePointInReaching, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(270)))); + new DegreeBearingImpl(270)), /* optionalTrueHeading */ null)); assertEquals(0., getTrackedRace().getTrack(hunger).getEstimatedPosition(timePointInReaching, /* extrapolate */false) .getDistance(offsetMarkPos).getMeters(), 0.00001); @@ -288,11 +288,11 @@ public class ReachingLegTest extends TrackBasedTest { getTrackedRace().recordFix( hunger, new GPSFixMovingImpl(offsetMarkPos, timePointToConsider, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(270)))); + new DegreeBearingImpl(270)), /* optionalTrueHeading */ null)); getTrackedRace().recordFix( plattner, new GPSFixMovingImpl(leewardPos, timePointToConsider, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(0)))); + new DegreeBearingImpl(0)), /* optionalTrueHeading */ null)); assertEquals(0., getTrackedRace().getTrack(hunger).getEstimatedPosition(timePointToConsider, /* extrapolate */false) .getDistance(offsetMarkPos).getMeters(), 0.00001); @@ -326,17 +326,17 @@ public class ReachingLegTest extends TrackBasedTest { getTrackedRace().recordFix( hunger, new GPSFixMovingImpl(offsetMarkPos, timePointToConsider, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(270)))); + new DegreeBearingImpl(270)), /* optionalTrueHeading */ null)); getTrackedRace().recordFix( schomaeker, new GPSFixMovingImpl(offsetMarkPos.translateGreatCircle( offsetMarkPos.getBearingGreatCircle(leewardPos), offsetMarkPos.getDistance(leewardPos) .scale(0.5)), timePointToConsider, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(180)))); + new DegreeBearingImpl(180)), /* optionalTrueHeading */ null)); getTrackedRace().recordFix( plattner, new GPSFixMovingImpl(leewardPos, timePointToConsider, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(0)))); + new DegreeBearingImpl(0)), /* optionalTrueHeading */ null)); assertEquals(0., getTrackedRace().getTrack(hunger).getEstimatedPosition(timePointToConsider, /* extrapolate */false) .getDistance(offsetMarkPos).getMeters(), 0.00001); @@ -367,13 +367,13 @@ public class ReachingLegTest extends TrackBasedTest { hunger, new GPSFixMovingImpl(windwardMarkPos.translateGreatCircle(new DegreeBearingImpl(reachingLegBearing.getDegrees()-45), distanceOfReachingLeg.scale(1./Math.sqrt(2.))), timePointToConsider, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(270)))); + new DegreeBearingImpl(270)), /* optionalTrueHeading */ null)); // Plattner turns right after the windward mark; both travel the same distance projected along the leg getTrackedRace().recordFix( plattner, new GPSFixMovingImpl(windwardMarkPos.translateGreatCircle(new DegreeBearingImpl(reachingLegBearing.getDegrees()+45), distanceOfReachingLeg.scale(1./Math.sqrt(2.))), timePointToConsider, new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(270)))); + new DegreeBearingImpl(270)), /* optionalTrueHeading */ null)); // with 90deg separating them, traveling 1/sqrt(2) the distance of the leg should put them the distance of the leg apart geometrically assertEquals( distanceOfReachingLeg.getMeters(), diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java index eaec9b7796b..d88fdbcf764 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java @@ -124,7 +124,7 @@ public abstract class StoredTrackBasedTest extends TrackBasedTest { TimePoint timePoint = new MillisecondsTimePoint(oi.readLong()); Position position = new DegreePosition(oi.readDouble(), oi.readDouble()); SpeedWithBearing speedWithBearing = new KnotSpeedWithBearingImpl(oi.readDouble(), new DegreeBearingImpl(oi.readDouble())); - return new GPSFixMovingImpl(position, timePoint, speedWithBearing); + return new GPSFixMovingImpl(position, timePoint, speedWithBearing, /* optionalTrueHeading */ null); // legacy fixes only; no need to worry about true heading } protected void storeTrack(Competitor competitor, Boat boat, DynamicGPSFixTrack track, String regattaName) diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java index 7c29ebe6f4e..57fb6e4bceb 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java @@ -67,7 +67,7 @@ public class TackTest extends StoredTrackBasedTestWithTrackedRace { DynamicGPSFixTrack hassosTrack = getTrackedRace().getTrack(competitor); TimePoint now = MillisecondsTimePoint.now(); hassosTrack.addGPSFix(new GPSFixMovingImpl(new DegreePosition(54.4680424, 10.234451), now, - new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(45)))); + new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(45)), /* optionalTrueHeading */ null)); assertEquals(Tack.PORT, getTrackedRace().getTack(competitor, now)); } @@ -76,7 +76,7 @@ public class TackTest extends StoredTrackBasedTestWithTrackedRace { DynamicGPSFixTrack hassosTrack = getTrackedRace().getTrack(competitor); TimePoint now = MillisecondsTimePoint.now(); hassosTrack.addGPSFix(new GPSFixMovingImpl(new DegreePosition(54.4680424, 10.234451), now, - new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(270)))); + new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(270)), /* optionalTrueHeading */ null)); assertEquals(Tack.STARBOARD, getTrackedRace().getTack(competitor, now)); } @@ -85,7 +85,7 @@ public class TackTest extends StoredTrackBasedTestWithTrackedRace { DynamicGPSFixTrack hassosTrack = getTrackedRace().getTrack(competitor); TimePoint now = MillisecondsTimePoint.now(); hassosTrack.addGPSFix(new GPSFixMovingImpl(new DegreePosition(54.4680424, 10.234451), now, - new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(180)))); + new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(180)), /* optionalTrueHeading */ null)); assertEquals(Tack.PORT, getTrackedRace().getTack(competitor, now)); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java index fafb08f8b17..fbdc68f978b 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java @@ -85,25 +85,25 @@ public class TrackTest { gpsFix1 = new GPSFixMovingImpl( position1, now1, new KnotSpeedWithBearingImpl(position1.getDistance(position2) .inTime(now2.asMillis() - now1.asMillis()).getKnots(), - new DegreeBearingImpl(90))); + new DegreeBearingImpl(90)), /* optionalTrueHeading */ null); gpsFix2 = new GPSFixMovingImpl(position2, now2, new KnotSpeedWithBearingImpl(position1.getDistance(position2) - .inTime(now2.asMillis() - gpsFix1.getTimePoint().asMillis()).getKnots(), new DegreeBearingImpl(90))); + .inTime(now2.asMillis() - gpsFix1.getTimePoint().asMillis()).getKnots(), new DegreeBearingImpl(90)), /* optionalTrueHeading */ null); TimePoint now3 = addMillisToTimepoint(now2, MILLIS_BETWEEN_FIXES); Position position3 = new DegreePosition(1, 4); gpsFix3 = new GPSFixMovingImpl( position3, now3, new KnotSpeedWithBearingImpl(position2.getDistance(position3) .inTime(now3.asMillis() - gpsFix2.getTimePoint().asMillis()).getKnots(), - new DegreeBearingImpl(0))); + new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); TimePoint now4 = addMillisToTimepoint(now3, MILLIS_BETWEEN_FIXES); Position position4 = new DegreePosition(3, 4); gpsFix4 = new GPSFixMovingImpl( position4, now4, new KnotSpeedWithBearingImpl(position3.getDistance(position4) .inTime(now4.asMillis() - gpsFix3.getTimePoint().asMillis()).getKnots(), - new DegreeBearingImpl(0))); + new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); TimePoint now5 = addMillisToTimepoint(now4, MILLIS_BETWEEN_FIXES); Position position5 = new DegreePosition(5, 4); gpsFix5 = new GPSFixMovingImpl(position5, now5, new KnotSpeedWithBearingImpl(position4.getDistance(position5) - .inTime(now5.asMillis() - gpsFix4.getTimePoint().asMillis()).getKnots(), new DegreeBearingImpl(0))); + .inTime(now5.asMillis() - gpsFix4.getTimePoint().asMillis()).getKnots(), new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); track.addGPSFix(gpsFix1); track.addGPSFix(gpsFix2); track.addGPSFix(gpsFix3); @@ -136,8 +136,8 @@ public class TrackTest { DegreePosition p2 = new DegreePosition(90, 0); TimePoint t1 = MillisecondsTimePoint.now(); TimePoint t2 = t1.plus(30); - gpsFix1 = new GPSFixMovingImpl(p1, t1, new KnotSpeedWithBearingImpl(0, new DegreeBearingImpl(0))); - gpsFix2 = new GPSFixMovingImpl(p2, t2, new KnotSpeedWithBearingImpl(0, new DegreeBearingImpl(0))); + gpsFix1 = new GPSFixMovingImpl(p1, t1, new KnotSpeedWithBearingImpl(0, new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); + gpsFix2 = new GPSFixMovingImpl(p2, t2, new KnotSpeedWithBearingImpl(0, new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); track.addGPSFix(gpsFix1); track.addGPSFix(gpsFix2); track.lockForRead(); @@ -246,7 +246,7 @@ public class TrackTest { TimePoint start, Position pos, SpeedWithBearing speed, int numberOfFixes) { TimePoint now = start; for (int i = 0; i < numberOfFixes; i++) { - GPSFixMoving fix1 = new GPSFixMovingImpl(pos, now, speed); + GPSFixMoving fix1 = new GPSFixMovingImpl(pos, now, speed, /* optionalTrueHeading */ null); track.addGPSFix(fix1); now = now.plus(1000); } @@ -299,7 +299,7 @@ public class TrackTest { } }; GPSFixMoving fix1 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(0), new KnotSpeedWithBearingImpl( - 1, new DegreeBearingImpl(123))); + 1, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null); track.addGPSFix(fix1); // The following getMaximumSpeedOverGround call will trigger a computeMaxSpeed(...) and a cache(...) call new Thread(()-> @@ -308,17 +308,17 @@ public class TrackTest { // now don't release the cacheBarrier as yet but add more fixes new Thread(() -> { GPSFixMoving fix2 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(3600000), - new KnotSpeedWithBearingImpl(2, new DegreeBearingImpl(123))); + new KnotSpeedWithBearingImpl(2, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null); track.addGPSFix(fix2); }).start(); new Thread(() -> { GPSFixMoving fix3 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(7200000), - new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(123))); + new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null); track.addGPSFix(fix3); }).start(); new Thread(() -> { GPSFixMoving fix4 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(10800000), - new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(123))); + new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null); track.addGPSFix(fix4); }).start(); cacheBarrier.await(); // releasing the creation of the cache entry from way above; this would now add a stale entry @@ -375,18 +375,18 @@ public class TrackTest { public void testMaxSpeedForMovingTrackWithFixAtIntervalBoundary() { DynamicGPSFixMovingTrackImpl track = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l); GPSFixMoving fix1 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(0), new KnotSpeedWithBearingImpl( - 1, new DegreeBearingImpl(123))); + 1, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null); track.addGPSFix(fix1); GPSFixMoving fix2 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(3600000), new KnotSpeedWithBearingImpl( - 2, new DegreeBearingImpl(123))); + 2, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null); track.addGPSFix(fix2); GPSFixMoving fix3 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(7200000), new KnotSpeedWithBearingImpl( - 1, new DegreeBearingImpl(123))); + 1, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null); track.addGPSFix(fix3); assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(7200000)). getB().getKnots(), 0.01); // produces a cache entry that ends GPSFixMoving fix4 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(10800000), new KnotSpeedWithBearingImpl( - 1, new DegreeBearingImpl(123))); + 1, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null); track.addGPSFix(fix4); assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(10800000)). getB().getKnots(), 0.01); @@ -396,9 +396,9 @@ public class TrackTest { public void testMaxSpeedForFixOverwrittenWithLowerSpeed() { DynamicGPSFixMovingTrackImpl track = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l); GPSFixMoving slow = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(3600000), new KnotSpeedWithBearingImpl( - 1, new DegreeBearingImpl(123))); + 1, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null); GPSFixMoving fast = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(3600000), new KnotSpeedWithBearingImpl( - 2, new DegreeBearingImpl(123))); + 2, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null); track.addGPSFix(fast); assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(10800000)). getB().getKnots(), 0.01); @@ -417,18 +417,18 @@ public class TrackTest { public void testMaxSpeedForMovingTrackWithFixAtIntervalBoundaryAfterQuery() { DynamicGPSFixMovingTrackImpl track = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l); GPSFixMoving fix1 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(0), new KnotSpeedWithBearingImpl( - 1, new DegreeBearingImpl(123))); + 1, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null); track.addGPSFix(fix1); GPSFixMoving fix2 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(3600000), new KnotSpeedWithBearingImpl( - 2, new DegreeBearingImpl(123))); + 2, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null); track.addGPSFix(fix2); assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(7200000)). getB().getKnots(), 0.01); // produces a cache entry that ends GPSFixMoving fix3 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(7200000), new KnotSpeedWithBearingImpl( - 1, new DegreeBearingImpl(123))); + 1, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null); track.addGPSFix(fix3); GPSFixMoving fix4 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(10800000), new KnotSpeedWithBearingImpl( - 1, new DegreeBearingImpl(123))); + 1, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null); track.addGPSFix(fix4); assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(10800000)). getB().getKnots(), 0.01); @@ -489,9 +489,9 @@ public class TrackTest { TimePoint t1 = new MillisecondsTimePoint(1000); TimePoint t2 = new MillisecondsTimePoint(2000); TimePoint t3 = new MillisecondsTimePoint(3000); - GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); - GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(2./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(150, new DegreeBearingImpl(0))); // outrageous speed; to be ignored by getEstimatedSpeed - GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); + GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); + GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(2./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(150, new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); // outrageous speed; to be ignored by getEstimatedSpeed + GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); track.addGPSFix(f1); track.addGPSFix(f2); track.addGPSFix(f3); @@ -504,9 +504,9 @@ public class TrackTest { TimePoint t1 = new MillisecondsTimePoint(1000); TimePoint t2 = new MillisecondsTimePoint(2000); TimePoint t3 = new MillisecondsTimePoint(3000); - GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); - GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(150./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(150, new DegreeBearingImpl(0))); // outrageous speed; to be ignored by getEstimatedSpeed - GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); + GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); + GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(150./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(150, new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); // outrageous speed; to be ignored by getEstimatedSpeed + GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); track.addGPSFix(f1); track.addGPSFix(f2); track.addGPSFix(f3); @@ -519,9 +519,9 @@ public class TrackTest { TimePoint t1 = new MillisecondsTimePoint(1000); TimePoint t2 = new MillisecondsTimePoint(2000); TimePoint t3 = new MillisecondsTimePoint(3000); - GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); - GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(2./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(0))); // outrageous speed; to be ignored by getEstimatedSpeed - GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); + GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); + GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(2./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); // outrageous speed; to be ignored by getEstimatedSpeed + GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); track.addGPSFix(f1); track.addGPSFix(f2); track.addGPSFix(f3); @@ -535,9 +535,9 @@ public class TrackTest { TimePoint t1 = new MillisecondsTimePoint(1000); TimePoint t2 = new MillisecondsTimePoint(2000); TimePoint t3 = new MillisecondsTimePoint(3000); - GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); - GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(2./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(150, new DegreeBearingImpl(0))); // outrageous speed; to be ignored by getEstimatedSpeed - GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); + GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); + GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(2./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(150, new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); // outrageous speed; to be ignored by getEstimatedSpeed + GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); track.addGPSFix(f1); track.addGPSFix(f2); track.addGPSFix(f3); @@ -552,9 +552,9 @@ public class TrackTest { TimePoint t1 = new MillisecondsTimePoint(1000); TimePoint t2 = new MillisecondsTimePoint(2000); TimePoint t3 = new MillisecondsTimePoint(3000); - GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(0, 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(45))); - GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(0.00001, 0.00001), t2, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); - GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(0.00002, 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(315))); + GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(0, 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(45)), /* optionalTrueHeading */ null); + GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(0.00001, 0.00001), t2, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0)), /* optionalTrueHeading */ null); + GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(0.00002, 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(315)), /* optionalTrueHeading */ null); track.addGPSFix(f1); track.addGPSFix(f2); track.addGPSFix(f3); @@ -582,7 +582,7 @@ public class TrackTest { // now add a fix: TimePoint now6 = addMillisToTimepoint(gpsFix5.getTimePoint(), 3); track.addGPSFix(new GPSFixMovingImpl( - new DegreePosition(6, 5), now6, new KnotSpeedWithBearingImpl(2, new DegreeBearingImpl(0)))); + new DegreePosition(6, 5), now6, new KnotSpeedWithBearingImpl(2, new DegreeBearingImpl(0)), /* optionalTrueHeading */ null)); try { GPSFixMoving secondOfSubset = subsetIter.next(); PositionAssert.assertGPSFixEquals(gpsFix3, secondOfSubset, /* pos deg delta */ 0.000001, /* bearing deg delta */ 0.01, /* knot delta */ 0.01); @@ -903,7 +903,7 @@ public class TrackTest { TimePoint next = null; GPSFixMoving fix = null; for (int i=0; i void scheduleFixRecording(final T object, GPSFixMoving fix, final RecordGPSFix recorder) { final TimePoint transformedTimepoint = advance(fix.getTimePoint()); - final GPSFixMoving transformedFix = new GPSFixMovingImpl(fix.getPosition(), transformedTimepoint, fix.getSpeed()); + final GPSFixMoving transformedFix = new GPSFixMovingImpl(fix.getPosition(), transformedTimepoint, fix.getSpeed(), fix.getOptionalTrueHeading()); long waitTime = getWaitTimeInMillisUntil(transformedFix.getTimePoint()); if (waitTime <= 0) { recorder.recordFix(object, transformedFix); diff --git a/java/com.sap.sailing.domain.yellowbrickadapter/src/com/sap/sailing/domain/yellowbrickadapter/impl/TeamPosition.java b/java/com.sap.sailing.domain.yellowbrickadapter/src/com/sap/sailing/domain/yellowbrickadapter/impl/TeamPosition.java index 828d5458c26..cc962e3e144 100755 --- a/java/com.sap.sailing.domain.yellowbrickadapter/src/com/sap/sailing/domain/yellowbrickadapter/impl/TeamPosition.java +++ b/java/com.sap.sailing.domain.yellowbrickadapter/src/com/sap/sailing/domain/yellowbrickadapter/impl/TeamPosition.java @@ -41,7 +41,7 @@ public class TeamPosition implements Timed { } public GPSFixMoving getGPSFixMoving() { - return new GPSFixMovingImpl(getPosition(), getTimePoint(), getMotionVector()); + return new GPSFixMovingImpl(getPosition(), getTimePoint(), getMotionVector(), /* optionalTrueHeading */ null); } @Override diff --git a/java/com.sap.sailing.domain.yellowbrickadapter/src/com/sap/sailing/domain/yellowbrickadapter/impl/YellowBrickRaceTrackerImpl.java b/java/com.sap.sailing.domain.yellowbrickadapter/src/com/sap/sailing/domain/yellowbrickadapter/impl/YellowBrickRaceTrackerImpl.java index 1ab1841e15d..82d71c8315a 100755 --- a/java/com.sap.sailing.domain.yellowbrickadapter/src/com/sap/sailing/domain/yellowbrickadapter/impl/YellowBrickRaceTrackerImpl.java +++ b/java/com.sap.sailing.domain.yellowbrickadapter/src/com/sap/sailing/domain/yellowbrickadapter/impl/YellowBrickRaceTrackerImpl.java @@ -207,7 +207,7 @@ implements TrackingDataLoader { for (final TeamPositions teamPositions : storedData.getTeams()) { progressCallback.ifPresent(cb->cb.accept((double) i[0]++ / numberOfTeams)); for (final TeamPosition position : teamPositions.getPositions()) { - final GPSFixMoving fix = new GPSFixMovingImpl(position.getPosition(), position.getTimePoint(), position.getMotionVector()); + final GPSFixMoving fix = new GPSFixMovingImpl(position.getPosition(), position.getTimePoint(), position.getMotionVector(), /* optionalTrueHeading */ null); final int deviceSerialNumber = teamPositions.getDeviceSerialNumber(); trackedRace.getTrack(competitorByDeviceSerialNumber.get(deviceSerialNumber)).add(fix); updateTimePointOfLastFixPerDeviceSerialNumber(deviceSerialNumber, position.getTimePoint()); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/GpsFixWithEstimationDataImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/GpsFixWithEstimationDataImpl.java deleted file mode 100644 index a9566317518..00000000000 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverdetection/impl/GpsFixWithEstimationDataImpl.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.sap.sailing.domain.maneuverdetection.impl; - -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.SpeedWithBearing; -import com.sap.sailing.domain.common.Wind; -import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; -import com.sap.sailing.domain.maneuverdetection.GpsFixWithEstimationData; -import com.sap.sse.common.Bearing; -import com.sap.sse.common.Distance; -import com.sap.sse.common.TimePoint; - -/** - * - * @author Vladislav Chumak (D069712) - * - */ -public class GpsFixWithEstimationDataImpl extends GPSFixMovingImpl implements GpsFixWithEstimationData { - - private static final long serialVersionUID = -6952863819352430365L; - - private Wind wind; - private Bearing relativeBearingToNextMarkAfterManeuver; - private Distance distanceToClosestMark; - - public GpsFixWithEstimationDataImpl(Position position, TimePoint timePoint, SpeedWithBearing speedWithBearing, - Wind wind, Bearing relativeBearingToNextMarkAfterManeuver, Distance distanceToClosestMark) { - super(position, timePoint, speedWithBearing); - this.wind = wind; - this.relativeBearingToNextMarkAfterManeuver = relativeBearingToNextMarkAfterManeuver; - this.distanceToClosestMark = distanceToClosestMark; - } - - @Override - public Wind getWind() { - return wind; - } - - @Override - public Bearing getRelativeBearingToNextMarkAfterManeuver() { - return relativeBearingToNextMarkAfterManeuver; - } - - @Override - public Distance getDistanceToClosestMark() { - return distanceToClosestMark; - } - -} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/MarkGPSFix.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/MarkGPSFix.java deleted file mode 100755 index 5c6ae98f386..00000000000 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/MarkGPSFix.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.sap.sailing.domain.tracking; - -import com.sap.sailing.domain.base.Mark; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; - -public interface MarkGPSFix extends GPSFixMoving { - Mark getMark(); -} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CourseChangeBasedTrackApproximation.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CourseChangeBasedTrackApproximation.java index 01d11906d34..6511b706e5d 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CourseChangeBasedTrackApproximation.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CourseChangeBasedTrackApproximation.java @@ -431,7 +431,7 @@ public class CourseChangeBasedTrackApproximation implements Serializable, GPSTra } private GPSFixMovingImpl createDummyFix(TimePoint timePoint) { - return new GPSFixMovingImpl(/* position */ null, timePoint, /* speed */ null); + return new GPSFixMovingImpl(/* position */ null, timePoint, /* speed */ null, /* optionalTrueHeading */ null); } @Override diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/OutlierFilter.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/OutlierFilter.java index aa805009357..ec723934c1e 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/OutlierFilter.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/OutlierFilter.java @@ -227,7 +227,7 @@ public class OutlierFilter { // between the adjacent fixes proportionately based on "fix"'s distances to each of the two adjacent fixes: final TimePoint inferredTimePointForFix = lastFix.getTimePoint().plus(lastFix.getTimePoint().until(currentFix.getTimePoint()).times( alongTrackDistanceFromLastFix.divide(lastFix.getPosition().getDistance(currentFix.getPosition())))); - result = new GPSFixMovingImpl(fixPosition, inferredTimePointForFix, fix.getSpeed()); + result = new GPSFixMovingImpl(fixPosition, inferredTimePointForFix, fix.getSpeed(), fix.getOptionalTrueHeading()); distanceRatio = distanceFromSegment.divide(lastFix.getPosition().getDistance(currentFix.getPosition())); } else { // we found a minimum after fix: foundMinimum = true; diff --git a/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/impl/ExpeditionMessageImpl.java b/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/impl/ExpeditionMessageImpl.java index c8c6f06812f..e2571cd7428 100755 --- a/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/impl/ExpeditionMessageImpl.java +++ b/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/impl/ExpeditionMessageImpl.java @@ -1,5 +1,7 @@ package com.sap.sailing.expeditionconnector.impl; +import java.io.IOException; +import java.text.ParseException; import java.util.Calendar; import java.util.Collections; import java.util.GregorianCalendar; @@ -8,7 +10,10 @@ import java.util.Map; import java.util.Set; import java.util.TimeZone; import java.util.TreeSet; +import java.util.logging.Level; +import java.util.logging.Logger; +import com.sap.sailing.declination.DeclinationService; import com.sap.sailing.domain.common.SpeedWithBearing; import com.sap.sailing.domain.common.impl.DegreePosition; import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; @@ -23,6 +28,8 @@ import com.sap.sse.common.impl.DegreeBearingImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; public class ExpeditionMessageImpl implements ExpeditionMessage { + private static final Logger logger = Logger.getLogger(ExpeditionMessageImpl.class.getName()); + private final String originalMessage; private final int boatID; private final Map values; @@ -148,8 +155,21 @@ public class ExpeditionMessageImpl implements ExpeditionMessage { if (hasValue(ID_GPS_LAT) && hasValue(ID_GPS_LNG)) { final SpeedWithBearing cogSog = getSpeedOverGround(); if (cogSog != null) { - result = new GPSFixMovingImpl(new DegreePosition(getValue(ID_GPS_LAT), getValue(ID_GPS_LNG)), getTimePoint(), - getSpeedOverGround()); + final DegreePosition position = new DegreePosition(getValue(ID_GPS_LAT), getValue(ID_GPS_LNG)); + Bearing optionalTrueHeading; + if (hasValue(ID_HEADING)) { + try { + optionalTrueHeading = new DegreeBearingImpl(getValue(ID_HEADING)).add( + DeclinationService.INSTANCE.getDeclination(getTimePoint(), position, /* timeoutForOnlineFetchInMilliseconds */ 1000).getBearingCorrectedTo(getTimePoint())); + } catch (IOException | ParseException e) { + logger.log(Level.WARNING, "Problem obtaining the magnetic declination for Expedition fix", e); + optionalTrueHeading = null; + } + } else { + optionalTrueHeading = null; + } + result = new GPSFixMovingImpl(position, getTimePoint(), + getSpeedOverGround(), optionalTrueHeading); } else { result = null; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/domain/common/tracking/impl/PreciseCompactGPSFixMovingImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/domain/common/tracking/impl/PreciseCompactGPSFixMovingImpl.java index 8f61768def4..2c06d6c6682 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/domain/common/tracking/impl/PreciseCompactGPSFixMovingImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/domain/common/tracking/impl/PreciseCompactGPSFixMovingImpl.java @@ -28,7 +28,7 @@ public final class PreciseCompactGPSFixMovingImpl { final double latDeg = streamReader.readDouble(); final double lngDeg = streamReader.readDouble(); return (PreciseCompactPosition) new com.sap.sailing.domain.common.tracking.impl.PreciseCompactGPSFixMovingImpl( - new DegreePosition(latDeg, lngDeg), /* timePoint */null, /* speedWithBearing */ null).getPosition(); + new DegreePosition(latDeg, lngDeg), /* timePoint */null, /* speedWithBearing */ null, /* optionalTrueHeading */ null).getPosition(); } @Override @@ -70,7 +70,7 @@ public final class PreciseCompactGPSFixMovingImpl { final double speedInKnots = streamReader.readDouble(); final double bearingDeg = streamReader.readDouble(); return (PreciseCompactSpeedWithBearing) new com.sap.sailing.domain.common.tracking.impl.PreciseCompactGPSFixMovingImpl( - /* dummy position */ new DegreePosition(0, 0), /* timePoint */null, new KnotSpeedWithBearingImpl(speedInKnots, new DegreeBearingImpl(bearingDeg))).getSpeed(); + /* dummy position */ new DegreePosition(0, 0), /* timePoint */null, new KnotSpeedWithBearingImpl(speedInKnots, new DegreeBearingImpl(bearingDeg)), /* optionalTrueHeading */ null).getSpeed(); } @Override @@ -113,7 +113,7 @@ public final class PreciseCompactGPSFixMovingImpl { final double bearingDeg = streamReader.readDouble(); final KnotSpeedWithBearingImpl speed = new KnotSpeedWithBearingImpl(speedInKnots, new DegreeBearingImpl(bearingDeg)); final com.sap.sailing.domain.common.tracking.impl.PreciseCompactGPSFixMovingImpl preciseCompactGPSFixMovingImpl = new com.sap.sailing.domain.common.tracking.impl.PreciseCompactGPSFixMovingImpl( - /* dummy position */ new DegreePosition(0, 0), /* timePoint */null, speed); + /* dummy position */ new DegreePosition(0, 0), /* timePoint */null, speed, /* optionalTrueHeading */ null); preciseCompactGPSFixMovingImpl.cacheEstimatedSpeed(speed); return (PreciseCompactEstimatedSpeed) preciseCompactGPSFixMovingImpl.getSpeed(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/domain/common/tracking/impl/VeryCompactGPSFixMovingImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/domain/common/tracking/impl/VeryCompactGPSFixMovingImpl.java index 355eec4bcad..c507477b7bf 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/domain/common/tracking/impl/VeryCompactGPSFixMovingImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/domain/common/tracking/impl/VeryCompactGPSFixMovingImpl.java @@ -35,7 +35,7 @@ public final class VeryCompactGPSFixMovingImpl { final double lngDeg = streamReader.readDouble(); try { return (VeryCompactPosition) new com.sap.sailing.domain.common.tracking.impl.VeryCompactGPSFixMovingImpl( - new DegreePosition(latDeg, lngDeg), /* timePoint */null, /* speed with bearing */ null).getPosition(); + new DegreePosition(latDeg, lngDeg), /* timePoint */null, /* speed with bearing */ null, /* optionalTrueHeading */ null).getPosition(); } catch (CompactionNotPossibleException e) { logger.log(Level.SEVERE, "Internal error: an object that was a very compact position and was serialized "+ "couldn't be de-serialized again as such an object", e); @@ -83,7 +83,7 @@ public final class VeryCompactGPSFixMovingImpl { final double bearingDeg = streamReader.readDouble(); try { return (VeryCompactSpeedWithBearing) new com.sap.sailing.domain.common.tracking.impl.VeryCompactGPSFixMovingImpl( - /* position */ null, /* timePoint */null, new KnotSpeedWithBearingImpl(knotSpeed, new DegreeBearingImpl(bearingDeg))).getSpeed(); + /* position */ null, /* timePoint */null, new KnotSpeedWithBearingImpl(knotSpeed, new DegreeBearingImpl(bearingDeg)), /* optionalTrueHeading */ null).getSpeed(); } catch (CompactionNotPossibleException e) { logger.log(Level.SEVERE, "Internal error: an object that was a very compact position and was serialized "+ "couldn't be de-serialized again as such an object", e); @@ -132,7 +132,7 @@ public final class VeryCompactGPSFixMovingImpl { try { final KnotSpeedWithBearingImpl speed = new KnotSpeedWithBearingImpl(knotSpeed, new DegreeBearingImpl(bearingDeg)); com.sap.sailing.domain.common.tracking.impl.VeryCompactGPSFixMovingImpl fix = new com.sap.sailing.domain.common.tracking.impl.VeryCompactGPSFixMovingImpl( - /* dummy position */ new DegreePosition(0, 0), /* timePoint */null, speed); + /* dummy position */ new DegreePosition(0, 0), /* timePoint */null, speed, /* optionalTrueHeading */ null); fix.cacheEstimatedSpeed(speed); return (VeryCompactEstimatedSpeed) fix.getCachedEstimatedSpeed(); } catch (CompactionNotPossibleException e) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/gwt/ui/shared/GPSFixDTOWithSpeedWindTackAndLegTypeIterable_CustomFieldSerializer.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/gwt/ui/shared/GPSFixDTOWithSpeedWindTackAndLegTypeIterable_CustomFieldSerializer.java index affd84b752f..6897c8e6e95 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/gwt/ui/shared/GPSFixDTOWithSpeedWindTackAndLegTypeIterable_CustomFieldSerializer.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/gwt/ui/shared/GPSFixDTOWithSpeedWindTackAndLegTypeIterable_CustomFieldSerializer.java @@ -15,6 +15,8 @@ import com.sap.sailing.domain.common.impl.DegreePosition; import com.sap.sailing.gwt.ui.shared.GPSFixDTOWithSpeedWindTackAndLegType; import com.sap.sailing.gwt.ui.shared.GPSFixDTOWithSpeedWindTackAndLegTypeIterable; import com.sap.sailing.gwt.ui.shared.SpeedWithBearingDTO; +import com.sap.sse.common.Bearing; +import com.sap.sse.common.impl.DegreeBearingImpl; /** * Serializes the {@link GPSFixDTOWithSpeedWindTackAndLegType} objects one by one, writing only primitive values to the @@ -33,6 +35,7 @@ public class GPSFixDTOWithSpeedWindTackAndLegTypeIterable_CustomFieldSerializer private static final int MASK_HAS_TACK = 1 << 4; private static final int MASK_HAS_POSITION = 1 << 5; private static final int MASK_HAS_TIMEPOINT = 1 << 6; + private static final int MASK_HAS_TRUE_HEADING = 1 << 7; @Override public void serializeInstance(SerializationStreamWriter streamWriter, GPSFixDTOWithSpeedWindTackAndLegTypeIterable instance) @@ -68,6 +71,9 @@ public class GPSFixDTOWithSpeedWindTackAndLegTypeIterable_CustomFieldSerializer if (fix.timepoint != null) { streamWriter.writeLong(fix.timepoint.getTime()); } + if (fix.optionalTrueHeading != null) { + streamWriter.writeDouble(fix.optionalTrueHeading.getDegrees()); + } } streamWriter.writeInt(-1); // encodes a "mask" that marks the end of the iterable } @@ -124,7 +130,13 @@ public class GPSFixDTOWithSpeedWindTackAndLegTypeIterable_CustomFieldSerializer } else { timepoint = null; } - list.add(new GPSFixDTOWithSpeedWindTackAndLegType(timepoint, position, speedWithBearing, degreesBoatToTheWind, tack, legType, extrapolated, detailValue)); + final Bearing optionalTrueHeading; + if ((mask & MASK_HAS_TRUE_HEADING) != 0) { + optionalTrueHeading = new DegreeBearingImpl(streamReader.readDouble()); + } else { + optionalTrueHeading = null; + } + list.add(new GPSFixDTOWithSpeedWindTackAndLegType(timepoint, position, speedWithBearing, optionalTrueHeading, degreesBoatToTheWind, tack, legType, extrapolated, detailValue)); } return new GPSFixDTOWithSpeedWindTackAndLegTypeIterable(list); } @@ -138,6 +150,7 @@ public class GPSFixDTOWithSpeedWindTackAndLegTypeIterable_CustomFieldSerializer | (fix.tack == null ? 0 : MASK_HAS_TACK) | (fix.position == null ? 0 : MASK_HAS_POSITION) | (fix.timepoint == null ? 0 : MASK_HAS_TIMEPOINT) + | (fix.optionalTrueHeading == null ? 0 : MASK_HAS_TRUE_HEADING) ; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/EditMarkPositionPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/EditMarkPositionPanel.java index 48e1baf95f8..db7fca63137 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/EditMarkPositionPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/EditMarkPositionPanel.java @@ -614,7 +614,7 @@ public class EditMarkPositionPanel extends AbstractRaceChart i } public void addMarkFix(final MarkDTO mark, final Date timepoint, final Position fixPosition) { - final GPSFixDTOWithSpeedWindTackAndLegType fix = new GPSFixDTOWithSpeedWindTackAndLegType(timepoint, fixPosition, null, new WindDTO(), null, null, false); + final GPSFixDTOWithSpeedWindTackAndLegType fix = new GPSFixDTOWithSpeedWindTackAndLegType(timepoint, fixPosition, null, /* optionalTrueHeading */ null, new WindDTO(), null, null, false); markPositionService.addMarkFix( raceIdentifierToLeaderboardRaceColumnAndFleetMapper.getLeaderboardNameAndRaceColumnNameAndFleetName(selectedRaceIdentifier), mark, fix, new AsyncCallback() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/FixPositionChooser.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/FixPositionChooser.java index a449b7cda5b..9d7d93732f9 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/FixPositionChooser.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/FixPositionChooser.java @@ -96,7 +96,7 @@ public class FixPositionChooser { fix = new GPSFixDTO(oldFix.timepoint, oldFix.position); this.moveOverlay = new FixOverlay(map, overlay.getZIndex(), fix, overlay.getType(), "#f00", coordinateSystem, stringMessages.dragToChangePosition()); } else { - fix = new GPSFixDTOWithSpeedWindTackAndLegType(editMarkPositionPanel.getTimepoint(), coordinateSystem.getPosition(startPos), null, new WindDTO(), null, null, false); + fix = new GPSFixDTOWithSpeedWindTackAndLegType(editMarkPositionPanel.getTimepoint(), coordinateSystem.getPosition(startPos), null, /* optionalTrueHeading */ null, new WindDTO(), null, null, false); this.moveOverlay = new FixOverlay(map, EditMarkPositionPanel.FIX_OVERLAY_Z_ORDER+1, fix, FixType.BUOY, "#f00", coordinateSystem, stringMessages.dragToChangePosition()); } redTimeLine.setValue(fix.timepoint.getTime()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMap.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMap.java index e2ac42fe28b..d4abc3df49b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMap.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMap.java @@ -3011,7 +3011,7 @@ public class RaceMap extends AbstractCompositeComponent impleme final GPSFixDTOWithSpeedWindTackAndLegType result; final List competitorFixes = fixesAndTails.getFixes(competitorDTO); if (competitorFixes != null && !competitorFixes.isEmpty()) { - int i = Collections.binarySearch(competitorFixes, new GPSFixDTOWithSpeedWindTackAndLegType(date, null, null, (WindDTO) null, null, null, false), + int i = Collections.binarySearch(competitorFixes, new GPSFixDTOWithSpeedWindTackAndLegType(date, null, null, /* optionalTrueHeading */ null, (WindDTO) null, null, null, false), new Comparator() { @Override public int compare(GPSFixDTOWithSpeedWindTackAndLegType o1, GPSFixDTOWithSpeedWindTackAndLegType o2) { @@ -3060,8 +3060,9 @@ public class RaceMap extends AbstractCompositeComponent impleme factorForBefore*(fixBefore.speedWithBearing==null?0:fixBefore.speedWithBearing.speedInKnots) + factorForAfter*(fixAfter.speedWithBearing==null?0:fixAfter.speedWithBearing.speedInKnots), betweenBearing); - result = new GPSFixDTOWithSpeedWindTackAndLegType(date, betweenPosition, betweenSpeed, closer.degreesBoatToTheWind, - closer.tack, closer.legType, fixBefore.extrapolated || fixAfter.extrapolated); + result = new GPSFixDTOWithSpeedWindTackAndLegType(date, betweenPosition, betweenSpeed, + interpolateOptionalTrueHeading(fixBefore, factorForBefore, fixAfter, factorForAfter), + closer.degreesBoatToTheWind, closer.tack, closer.legType, fixBefore.extrapolated || fixAfter.extrapolated); } } else { // perfect match @@ -3073,6 +3074,16 @@ public class RaceMap extends AbstractCompositeComponent impleme } return result; } + + private Bearing interpolateOptionalTrueHeading(GPSFixDTOWithSpeedWindTackAndLegType fixBefore, double factorForBefore, GPSFixDTOWithSpeedWindTackAndLegType fixAfter, double factorForAfter) { + assert fixBefore != null && fixAfter != null; + return (fixBefore == null || fixBefore.optionalTrueHeading == null) ? (fixAfter == null || fixAfter.optionalTrueHeading == null) + ? null + : fixAfter.optionalTrueHeading + : (fixAfter == null || fixAfter.optionalTrueHeading == null) + ? fixBefore.optionalTrueHeading + : new DegreeBearingImpl(factorForBefore * fixBefore.optionalTrueHeading.getDegrees() + factorForAfter * fixAfter.optionalTrueHeading.getDegrees()); + } public RaceMapSettings getSettings() { return settings; 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 b8220bc9b55..bcbe5dcb82d 100644 --- 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 @@ -1912,9 +1912,10 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet .getBearing().getDegrees()); } - public GPSFixDTOWithSpeedWindTackAndLegType createGPSFixDTO(GPSFix fix, SpeedWithBearing speedWithBearing, WindDTO windDTO, Tack tack, LegType legType, boolean extrapolated, Double detailValue) { + public GPSFixDTOWithSpeedWindTackAndLegType createGPSFixDTO(GPSFix fix, SpeedWithBearing speedWithBearing, + Bearing optionalTrueHeading, WindDTO windDTO, Tack tack, LegType legType, boolean extrapolated, Double detailValue) { return new GPSFixDTOWithSpeedWindTackAndLegType(fix.getTimePoint().asDate(), fix.getPosition()==null?null:fix.getPosition(), - speedWithBearing==null?null:createSpeedWithBearingDTO(speedWithBearing), windDTO, tack, legType, extrapolated, detailValue); + speedWithBearing==null?null:createSpeedWithBearingDTO(speedWithBearing), optionalTrueHeading, windDTO, tack, legType, extrapolated, detailValue); } @Override @@ -3241,8 +3242,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet trackedLegOfCompetitor.getLeg()).getLegType(fix.getTimePoint()); Wind wind = trackedRace.getWind(fix.getPosition(), fix.getTimePoint()); WindDTO windDTO = createWindDTOFromAlreadyAveraged(wind, fix.getTimePoint()); - GPSFixDTOWithSpeedWindTackAndLegType fixDTO = createGPSFixDTO(fix, speedWithBearing, windDTO, tack, legType, /* extrapolated */ - false, null); + GPSFixDTOWithSpeedWindTackAndLegType fixDTO = createGPSFixDTO(fix, speedWithBearing, /* optionalTrueHeading */ null, windDTO, tack, /* extrapolated */ + legType, false, null); return fixDTO; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/GPSFixDTOWithSpeedWindTackAndLegType.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/GPSFixDTOWithSpeedWindTackAndLegType.java index 2464f2ea221..872fbfbb0ec 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/GPSFixDTOWithSpeedWindTackAndLegType.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/GPSFixDTOWithSpeedWindTackAndLegType.java @@ -6,10 +6,13 @@ import com.google.gwt.user.client.rpc.IsSerializable; import com.sap.sailing.domain.common.LegType; import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.Tack; +import com.sap.sse.common.Bearing; import com.sap.sse.common.impl.DegreeBearingImpl; public class GPSFixDTOWithSpeedWindTackAndLegType extends GPSFixDTO implements IsSerializable { public SpeedWithBearingDTO speedWithBearing; + + public Bearing optionalTrueHeading; /** * tells if this fix was computed by extrapolation instead of having been captured by a device directly @@ -37,33 +40,35 @@ public class GPSFixDTOWithSpeedWindTackAndLegType extends GPSFixDTO implements I public Double detailValue; - public GPSFixDTOWithSpeedWindTackAndLegType() {} + @Deprecated // GWT serialization only + GPSFixDTOWithSpeedWindTackAndLegType() {} - public GPSFixDTOWithSpeedWindTackAndLegType(Date timepoint, Position position, SpeedWithBearingDTO speedWithBearing, WindDTO wind, - Tack tack, LegType legType, boolean extrapolated) { - this(timepoint, position, speedWithBearing, (speedWithBearing != null && wind != null) ? - new DegreeBearingImpl(speedWithBearing.bearingInDegrees).getDifferenceTo( - new DegreeBearingImpl(wind.dampenedTrueWindFromDeg)).getDegrees() : null, tack, legType, extrapolated); + public GPSFixDTOWithSpeedWindTackAndLegType(Date timepoint, Position position, SpeedWithBearingDTO speedWithBearing, Bearing optionalTrueHeading, + WindDTO wind, Tack tack, LegType legType, boolean extrapolated) { + this(timepoint, position, speedWithBearing, optionalTrueHeading, (speedWithBearing != null && wind != null) ? + new DegreeBearingImpl(speedWithBearing.bearingInDegrees).getDifferenceTo( + new DegreeBearingImpl(wind.dampenedTrueWindFromDeg)).getDegrees() : null, tack, legType, extrapolated); } - public GPSFixDTOWithSpeedWindTackAndLegType(Date timepoint, Position position, SpeedWithBearingDTO speedWithBearing, WindDTO wind, - Tack tack, LegType legType, boolean extrapolated, Double detailValue) { - this(timepoint, position, speedWithBearing, (speedWithBearing != null && wind != null) ? - new DegreeBearingImpl(speedWithBearing.bearingInDegrees).getDifferenceTo( - new DegreeBearingImpl(wind.dampenedTrueWindFromDeg)).getDegrees() : null, tack, legType, extrapolated, detailValue); + public GPSFixDTOWithSpeedWindTackAndLegType(Date timepoint, Position position, SpeedWithBearingDTO speedWithBearing, Bearing optionalTrueHeading, + WindDTO wind, Tack tack, LegType legType, boolean extrapolated, Double detailValue) { + this(timepoint, position, speedWithBearing, optionalTrueHeading, (speedWithBearing != null && wind != null) ? + new DegreeBearingImpl(speedWithBearing.bearingInDegrees).getDifferenceTo( + new DegreeBearingImpl(wind.dampenedTrueWindFromDeg)).getDegrees() : null, tack, legType, extrapolated, detailValue); } - public GPSFixDTOWithSpeedWindTackAndLegType(Date timepoint, Position position, SpeedWithBearingDTO speedWithBearing, Double degreesBoatToTheWind, - Tack tack, LegType legType, boolean extrapolated) { - this(timepoint, position, speedWithBearing, degreesBoatToTheWind, tack, legType, extrapolated, /* detailValue */ null); + public GPSFixDTOWithSpeedWindTackAndLegType(Date timepoint, Position position, SpeedWithBearingDTO speedWithBearing, Bearing optionalTrueHeading, + Double degreesBoatToTheWind, Tack tack, LegType legType, boolean extrapolated) { + this(timepoint, position, speedWithBearing, optionalTrueHeading, degreesBoatToTheWind, tack, legType, extrapolated, /* detailValue */ null); } - public GPSFixDTOWithSpeedWindTackAndLegType(Date timepoint, Position position, SpeedWithBearingDTO speedWithBearing, Double degreesBoatToTheWind, - Tack tack, LegType legType, boolean extrapolated, Double detailValue) { + public GPSFixDTOWithSpeedWindTackAndLegType(Date timepoint, Position position, SpeedWithBearingDTO speedWithBearing, Bearing optionalTrueHeading, + Double degreesBoatToTheWind, Tack tack, LegType legType, boolean extrapolated, Double detailValue) { super(timepoint, position); this.timepoint = timepoint; this.position = position; this.speedWithBearing = speedWithBearing; + this.optionalTrueHeading = optionalTrueHeading; this.tack = tack; this.legType = legType; this.extrapolated = extrapolated; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/GPSFixDTOWithSpeedWindTackAndLegTypeIterable.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/GPSFixDTOWithSpeedWindTackAndLegTypeIterable.java index 30f09b6a03a..ad6cc45c075 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/GPSFixDTOWithSpeedWindTackAndLegTypeIterable.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/GPSFixDTOWithSpeedWindTackAndLegTypeIterable.java @@ -213,7 +213,7 @@ public class GPSFixDTOWithSpeedWindTackAndLegTypeIterable implements IsSerializa Position estimatedPosition = track.getEstimatedPosition(middle, extrapolate); SpeedWithBearing estimatedSpeed = track.getEstimatedSpeed(middle); if (estimatedPosition != null && estimatedSpeed != null) { - GPSFixMoving estimatedFix = new GPSFixMovingImpl(estimatedPosition, middle, estimatedSpeed); + GPSFixMoving estimatedFix = new GPSFixMovingImpl(estimatedPosition, middle, estimatedSpeed, /* optionalTrueHeading */ null); // TODO bug5970: could try to estimate heading from neighboring fixes if (logger.getLevel() != null && logger.getLevel().equals(Level.FINEST)) { logger.finest(""+competitor.getName()+": " + estimatedFix+" (estimated)"); } @@ -282,7 +282,8 @@ public class GPSFixDTOWithSpeedWindTackAndLegTypeIterable implements IsSerializa detailValue = null; } } - result = sailingService.createGPSFixDTO(fix, estimatedSpeed, windDTO, tack, legType, /* extrapolate */ extrapolatedFixes.contains(fix), detailValue); + result = sailingService.createGPSFixDTO(fix, estimatedSpeed, fix.getOptionalTrueHeading(), windDTO, + tack, legType, /* extrapolate */ extrapolatedFixes.contains(fix), detailValue); } else if (isExtrapolate()) { final TrackedLegOfCompetitor trackedLegOfCompetitor = trackedRace.getTrackedLeg(competitor, lastFix.getTimePoint()); Position position = track.getEstimatedPosition(toTimePointExcluding, extrapolate); @@ -312,8 +313,8 @@ public class GPSFixDTOWithSpeedWindTackAndLegTypeIterable implements IsSerializa WindDTO windDTO2 = wind2 == null ? null : sailingService.createWindDTOFromAlreadyAveraged(wind2, toTimePointExcluding); result = new GPSFixDTOWithSpeedWindTackAndLegType( toTimePointExcluding.asDate(), position==null?null:position, - estimatedSpeed2==null?null:sailingService.createSpeedWithBearingDTO(estimatedSpeed2), windDTO2, - tack2, legType2, /* extrapolated */ true); + estimatedSpeed2==null?null:sailingService.createSpeedWithBearingDTO(estimatedSpeed2), /* optionalTrueHeading */ null, // no heading for extrapolated fixes + windDTO2, tack2, legType2, /* extrapolated */ true); } else { throw new NoSuchElementException(); } diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/deserialization/test/GPSFixMovingJsonDeserializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/deserialization/test/GPSFixMovingJsonDeserializerTest.java index 6f156a4ac6c..1ce06328b1c 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/deserialization/test/GPSFixMovingJsonDeserializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/deserialization/test/GPSFixMovingJsonDeserializerTest.java @@ -25,11 +25,9 @@ public class GPSFixMovingJsonDeserializerTest { @Test public void testGPSFixMovingDeserializer() throws ParseException, JsonDeserializationException { - GPSFixMoving gpsFix = GPSFixMovingImpl.create(8.0, 55.0, System.currentTimeMillis(), 5.0, 14.0); - + GPSFixMoving gpsFix = GPSFixMovingImpl.create(8.0, 55.0, System.currentTimeMillis(), 5.0, 14.0, /* optionalTrueHeadingDeg */ 15.0); JSONObject gpsFixSerialized = serializer.serialize(gpsFix); GPSFixMoving gpsFixDeserialized = deserializer.deserialize(gpsFixSerialized); - assertEquals(gpsFix, gpsFixDeserialized); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/FlatSmartphoneUuidAndGPSFixMovingJsonDeserializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/FlatSmartphoneUuidAndGPSFixMovingJsonDeserializerTest.java index 392ef34859a..e5ff9a29135 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/FlatSmartphoneUuidAndGPSFixMovingJsonDeserializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/FlatSmartphoneUuidAndGPSFixMovingJsonDeserializerTest.java @@ -31,14 +31,14 @@ public class FlatSmartphoneUuidAndGPSFixMovingJsonDeserializerTest { " \"latitude\" : 54.325246,\n" + " \"longitude\" : 10.148556,\n" + " \"speed\" : 3.61,\n" + - " \"course\" : 258.11,\n" + + " \"course\" : 258.11\n" + " },\n" + " {\n" + " \"timestamp\" : 14144168490000,\n" + " \"latitude\" : 55.12456,\n" + " \"longitude\" : 8.03456,\n" + " \"speed\" : 5.1,\n" + - " \"course\" : 14.2,\n" + + " \"course\" : 14.2\n" + " },\n" + " {\n" + " \"timestamp-iso\" : \"2418-03-18T15:41:30Z\",\n" + @@ -46,19 +46,19 @@ public class FlatSmartphoneUuidAndGPSFixMovingJsonDeserializerTest { " \"longitude\" : -2.03456,\n" + " \"speed\" : 19.3,\n" + " \"course\" : 359.99,\n" + + " \"hdt\" : 358.57\n" + " }\n" + " ]\n" + "}"; JsonDeserializer>> deserializer = new FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer(); - Pair> result = deserializer.deserialize(Helpers.toJSONObjectSafe(JSONValue.parseWithException(json))); assertThat("uuid", result.getA(), equalTo(UUID.fromString("af855a56-9726-4a9c-a77e-da955bd289bf"))); assertThat("number of fixes", result.getB().size(), equalTo(3)); - TimePoint tp3 = result.getB().get(2).getTimePoint(); assertThat(tp3.asMillis(), equalTo(14144168490000L)); + assertThat(result.getB().get(2).getOptionalTrueHeading().getDegrees(), equalTo(358.57)); } @Test diff --git a/java/com.sap.sailing.server.gateway.serialization/META-INF/MANIFEST.MF b/java/com.sap.sailing.server.gateway.serialization/META-INF/MANIFEST.MF index eb35804d421..61d7a6aeb52 100644 --- a/java/com.sap.sailing.server.gateway.serialization/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.server.gateway.serialization/META-INF/MANIFEST.MF @@ -6,6 +6,7 @@ Bundle-Version: 1.0.0.qualifier Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Import-Package: + com.sap.sailing.declination, org.json.simple Require-Bundle: com.sap.sailing.domain.common, com.sap.sailing.domain.shared.android, diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.java index 69665fe6752..2be9f2b94d3 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.java @@ -1,19 +1,27 @@ package com.sap.sailing.server.gateway.deserialization.impl; +import java.io.IOException; +import java.text.ParseException; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import com.sap.sailing.declination.DeclinationService; +import com.sap.sailing.domain.common.impl.DegreePosition; import com.sap.sailing.domain.common.impl.MeterPerSecondSpeedImpl; import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.common.tracking.impl.FlatSmartphoneUuidAndGPSFixMovingJsonSerializer; import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; +import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util.Pair; +import com.sap.sse.common.impl.DegreeBearingImpl; import com.sap.sse.shared.json.JsonDeserializationException; import com.sap.sse.shared.json.JsonDeserializer; @@ -23,8 +31,10 @@ import com.sap.sse.shared.json.JsonDeserializer; * @author Fredrik Teschke * */ -public class FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer implements - JsonDeserializer>> { +public class FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer + implements JsonDeserializer>> { + private static final Logger logger = Logger.getLogger(FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.class.getName()); + public static final String ACCURACY = "accuracy"; @Override @@ -40,7 +50,23 @@ public class FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer implements double speedMperS = Double.parseDouble(fixObject.get(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.SPEED_M_PER_S).toString()); double speedKnots = new MeterPerSecondSpeedImpl(speedMperS).getKnots(); double bearingDeg = Double.parseDouble(fixObject.get(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.BEARING_DEG).toString()); - GPSFixMoving fix = GPSFixMovingImpl.create(lonDeg, latDeg, timeMillis, speedKnots, bearingDeg); + Double optionalTrueHeadingDeg; + if (fixObject.containsKey(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.TRUE_HEADING_DEG)) { + optionalTrueHeadingDeg = Double.parseDouble(fixObject.get(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.TRUE_HEADING_DEG).toString()); + } else if (fixObject.containsKey(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.MAGNETIC_HEADING_DEG)) { + final TimePoint timePoint = TimePoint.of(timeMillis); + try { + optionalTrueHeadingDeg = new DegreeBearingImpl(Double.parseDouble(fixObject.get(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.MAGNETIC_HEADING_DEG).toString())) + .add(DeclinationService.INSTANCE.getDeclination(timePoint, new DegreePosition(latDeg, lonDeg), /* timeout in ms */ 1000) + .getBearingCorrectedTo(timePoint)).getDegrees(); + } catch (NumberFormatException | IOException | ParseException e) { + logger.log(Level.WARNING, "Problem obtaining magnetic declination for heading provided in JSON fix", e); + optionalTrueHeadingDeg = null; + } + } else { + optionalTrueHeadingDeg = null; + } + GPSFixMoving fix = GPSFixMovingImpl.create(lonDeg, latDeg, timeMillis, speedKnots, bearingDeg, optionalTrueHeadingDeg); fixes.add(fix); } diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/GPSFixMovingJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/GPSFixMovingJsonDeserializer.java index d775bd90249..f5cb27aa963 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/GPSFixMovingJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/GPSFixMovingJsonDeserializer.java @@ -17,19 +17,26 @@ public class GPSFixMovingJsonDeserializer extends TypeBasedJsonDeserializer result.put(TypeBasedJsonDeserializer.FIELD_TYPE, GPSFixMovingJsonDeserializer.TYPE); result.put(GPSFixMovingJsonDeserializer.FIELD_BEARING_DEG, speedWithCourse.getBearing().getDegrees()); result.put(GPSFixMovingJsonDeserializer.FIELD_SPEED_KNOTS, speedWithCourse.getKnots()); - + if (object.getOptionalTrueHeading() != null) { + result.put(GPSFixMovingJsonDeserializer.FIELD_TRUE_HEADING_DEG, object.getOptionalTrueHeading().getDegrees()); + } return result; } } diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/gpsFixesPostDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/gpsFixesPostDoc.html index 795441b7425..c2f0acd27e7 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/gpsFixesPostDoc.html +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/gpsFixesPostDoc.html @@ -75,13 +75,15 @@ These can be mapped to a competitor or a mark via the DeviceMappings in the Race "longitude" : 10.148556, "speed" : 3.61, "course" : 258.11, + "hdt" : 259.0 }, { "timestamp" : 14144168490000, "latitude" : 55.12456, "longitude" : 8.03456, "speed" : 5.1, - "course" : 14.2, + "course" : 14.2 + "hdt" : 14.7 } ] } @@ -89,7 +91,10 @@ These can be mapped to a competitor or a mark via the DeviceMappings in the Race Note that the "speed" field is provided in meters per second (m/s). The course is the course over ground (COG) in - true degrees. + true degrees. The "hdt" field is optional and may be used to represent a true (not magnetic) heading in degrees. + Note how this is different from "hdg" which can be used instead of "hdt" to specify a magnetic heading in degrees. + The magnetic declination at time and location of the fix will be used then to convert this internally to a true + heading.
Back to Web Service Overview diff --git a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/ImportMasterDataOperation.java b/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/ImportMasterDataOperation.java index 4c39de00504..b228f1ded1a 100755 --- a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/ImportMasterDataOperation.java +++ b/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/ImportMasterDataOperation.java @@ -526,7 +526,7 @@ public class ImportMasterDataOperation extends if (fixToAdd instanceof VeryCompactGPSFixMovingImpl) { VeryCompactGPSFixMovingImpl gpsFix = (VeryCompactGPSFixMovingImpl) fixToAdd; fixToAdd = new GPSFixMovingImpl(gpsFix.getPosition(), fixToAdd.getTimePoint(), - ((VeryCompactGPSFixMovingImpl) fixToAdd).getSpeed()); + ((VeryCompactGPSFixMovingImpl) fixToAdd).getSpeed(), gpsFix.getOptionalTrueHeading()); } else if (fixToAdd instanceof VeryCompactGPSFixImpl) { VeryCompactGPSFixImpl gpsFix = (VeryCompactGPSFixImpl) fixToAdd; fixToAdd = new GPSFixImpl(gpsFix.getPosition(), fixToAdd.getTimePoint()); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/BoatReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/BoatReplicationTest.java index 3844ab2bc48..de10b8016c8 100644 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/BoatReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/BoatReplicationTest.java @@ -128,7 +128,7 @@ public class BoatReplicationTest extends AbstractServerReplicationTest { EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 3000, /* millisecondsOverWhichToAverageWind */ 30000l, /* millisecondsOverWhichToAverageSpeed */ 30000l, null)); trackedRace.getTrack(competitor).addGPSFix(new GPSFixMovingImpl(new DegreePosition(49.425, 8.293), MillisecondsTimePoint.now(), - new KnotSpeedWithBearingImpl(12.3, new DegreeBearingImpl(242.3)))); + new KnotSpeedWithBearingImpl(12.3, new DegreeBearingImpl(242.3)), /* optionalTrueHeading */ null)); Thread.sleep(1000); TrackedRace replicatedTrackedRace = replica.getTrackedRace(raceIdentifier); assertNotNull(replicatedTrackedRace); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java index 1b35d9cb9da..093fd71c37d 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java @@ -148,7 +148,7 @@ public class CompetitorReplicationTest extends AbstractServerReplicationTest { EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 3000, /* millisecondsOverWhichToAverageWind */ 30000l, /* millisecondsOverWhichToAverageSpeed */ 30000l, null)); trackedRace.getTrack(competitor).addGPSFix(new GPSFixMovingImpl(new DegreePosition(49.425, 8.293), MillisecondsTimePoint.now(), - new KnotSpeedWithBearingImpl(12.3, new DegreeBearingImpl(242.3)))); + new KnotSpeedWithBearingImpl(12.3, new DegreeBearingImpl(242.3)), /* optionalTrueHeading */ null)); Thread.sleep(1000); TrackedRace replicatedTrackedRace = replica.getTrackedRace(raceIdentifier); assertNotNull(replicatedTrackedRace); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceContentsReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceContentsReplicationTest.java index 4d8d138a2e7..404dd9d63f4 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceContentsReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceContentsReplicationTest.java @@ -127,7 +127,7 @@ public class TrackedRaceContentsReplicationTest extends AbstractServerReplicatio @Test public void testGPSFixReplication() throws InterruptedException { final GPSFixMovingImpl fix = new GPSFixMovingImpl(new DegreePosition(1, 2), new MillisecondsTimePoint(12345), - new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))); + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123)), /* optionalTrueHeading */ new DegreeBearingImpl(124)); trackedRace.recordFix(competitor, fix); Thread.sleep(1000); TrackedRace replicaTrackedRace = replica.getTrackedRace(raceIdentifier); @@ -137,8 +137,10 @@ public class TrackedRaceContentsReplicationTest extends AbstractServerReplicatio competitorTrack.lockForRead(); try { assertEquals(1, Util.size(competitorTrack.getRawFixes())); - PositionAssert.assertGPSFixEquals(fix, competitorTrack.getRawFixes().iterator().next(), /* pos deg delta */ 0.0000001, /* bearing deg delta */ 0.01, /* knot speed delta */ 0.01); - assertNotSame(fix, competitorTrack.getRawFixes().iterator().next()); + final GPSFixMoving replicatedFix = competitorTrack.getRawFixes().iterator().next(); + PositionAssert.assertGPSFixEquals(fix, replicatedFix, /* pos deg delta */ 0.0000001, /* bearing deg delta */ 0.01, /* knot speed delta */ 0.01); + assertEquals(fix.getOptionalTrueHeading().getDegrees(), replicatedFix.getOptionalTrueHeading().getDegrees(), 0.01); + assertNotSame(fix, replicatedFix); } finally { competitorTrack.unlockAfterRead(); } @@ -166,7 +168,7 @@ public class TrackedRaceContentsReplicationTest extends AbstractServerReplicatio @Test public void testMarkFixReplication() throws InterruptedException { final GPSFixMovingImpl fix = new GPSFixMovingImpl(new DegreePosition(2, 3), new MillisecondsTimePoint(3456), - new KnotSpeedWithBearingImpl(13, new DegreeBearingImpl(234))); + new KnotSpeedWithBearingImpl(13, new DegreeBearingImpl(234)), /* optionalTrueHeading */ null); final Mark masterMark = trackedRace.getRace().getCourse().getFirstWaypoint().getMarks().iterator().next(); trackedRace.recordFix(masterMark, fix); Thread.sleep(1000); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceWithSensorFixStoreContentsReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceWithSensorFixStoreContentsReplicationTest.java index 5259db6b49c..47a8e4bd3aa 100644 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceWithSensorFixStoreContentsReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceWithSensorFixStoreContentsReplicationTest.java @@ -153,7 +153,7 @@ public class TrackedRaceWithSensorFixStoreContentsReplicationTest extends Abstra @Test public void testGPSFixReplication() throws InterruptedException { final GPSFixMovingImpl fix = new GPSFixMovingImpl(new DegreePosition(1, 2), new MillisecondsTimePoint(12345), - new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))); + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123)), /* optionalTrueHeading */ null); trackedRace.recordFix(competitor, fix); Thread.sleep(1000); final TrackedRace replicaTrackedRace = replica.getTrackedRace(raceIdentifier); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/statistics/StatisticsTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/statistics/StatisticsTest.java index 0277e3a9310..809ab259679 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/statistics/StatisticsTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/statistics/StatisticsTest.java @@ -112,47 +112,47 @@ public class StatisticsTest { public void testTrackedRaceStatisticsCacheWithFixes() throws Exception { trackedRace.recordFix(comp, new GPSFixMovingImpl(new DegreePosition(49.295970, 8.638958), new MillisecondsTimePoint(START_OF_RACE), - new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)))); + new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)), /* optionalTrueHeading */ null)); trackedRace.recordFix(comp, new GPSFixMovingImpl(new DegreePosition(49.295911, 8.638971), new MillisecondsTimePoint(START_OF_RACE + 10), - new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)))); + new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)), /* optionalTrueHeading */ null)); trackedRace.recordFix(comp, new GPSFixMovingImpl(new DegreePosition(49.295866, 8.638986), new MillisecondsTimePoint(START_OF_RACE + 20), - new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)))); + new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)), /* optionalTrueHeading */ null)); trackedRace.recordFix(comp, new GPSFixMovingImpl(new DegreePosition(49.295822, 8.639010), new MillisecondsTimePoint(START_OF_RACE + 30), - new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)))); + new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)), /* optionalTrueHeading */ null)); trackedRace.recordFix(comp, new GPSFixMovingImpl(new DegreePosition(49.295785, 8.639057), new MillisecondsTimePoint(START_OF_RACE + 40), - new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)))); + new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)), /* optionalTrueHeading */ null)); trackedRace.recordFix(comp, new GPSFixMovingImpl(new DegreePosition(49.295768, 8.639108), new MillisecondsTimePoint(START_OF_RACE + 50), - new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)))); + new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)), /* optionalTrueHeading */ null)); trackedRace.recordFix(comp, new GPSFixMovingImpl(new DegreePosition(49.295761, 8.639180), new MillisecondsTimePoint(START_OF_RACE + 60), - new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)))); + new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)), /* optionalTrueHeading */ null)); trackedRace.recordFix(comp, new GPSFixMovingImpl(new DegreePosition(49.295765, 8.639278), new MillisecondsTimePoint(START_OF_RACE + 70), - new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)))); + new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)), /* optionalTrueHeading */ null)); trackedRace.recordFix(comp, new GPSFixMovingImpl(new DegreePosition(49.295785, 8.639353), new MillisecondsTimePoint(START_OF_RACE + 80), - new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)))); + new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)), /* optionalTrueHeading */ null)); trackedRace.recordFix(comp, new GPSFixMovingImpl(new DegreePosition(49.295817, 8.639406), new MillisecondsTimePoint(START_OF_RACE + 90), - new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)))); + new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)), /* optionalTrueHeading */ null)); trackedRace.recordFix(comp, new GPSFixMovingImpl(new DegreePosition(49.295861, 8.639449), new MillisecondsTimePoint(START_OF_RACE + 100), - new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)))); + new KilometersPerHourSpeedWithBearingImpl(1, new DegreeBearingImpl(100)), /* optionalTrueHeading */ null)); List markPassings = new ArrayList<>(); markPassings.add(new MarkPassingImpl(new MillisecondsTimePoint(START_OF_RACE), waypoint1, comp)); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java index 05cebab2e31..88c8084377c 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java @@ -360,7 +360,7 @@ public class MasterDataImportTest { logTimePoint3); regatta.getRegattaLog().add(mappingEvent); GPSFix gpsFix = new GPSFixMovingImpl(new DegreePosition(54.333, 10.133), logTimePoint2, - new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(90))); + new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(90)), /* optionalTrueHeading */ null); sourceService.getSensorFixStore().storeFix(deviceIdentifier, gpsFix); // test to check that batch-import of fixes works as intended DeviceIdentifier deviceBatch1 = addDeviceMappingWithFixes(sourceService, regatta, competitor, logTimePoint, logTimePoint3, logTimePoint4, "x", 4999); @@ -524,7 +524,7 @@ public class MasterDataImportTest { List fixesToSave = new ArrayList<>(numFixes); for(int i = 1; i <= numFixes; i++) { fixesToSave.add(new GPSFixMovingImpl(new DegreePosition(54.333, 10.133), logTimePoint.plus(i), - new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(90)))); + new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(90)), /* optionalTrueHeading */ null)); } sourceService.getSensorFixStore().storeFixes(deviceIdentifier, fixesToSave, /* returnManeuverUpdate */ false, /* returnLiveDelay */ false); return deviceIdentifier; diff --git a/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/common/BaseGPSFixImporterImpl.java b/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/common/BaseGPSFixImporterImpl.java index d530cc9b023..0144e0f37e6 100644 --- a/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/common/BaseGPSFixImporterImpl.java +++ b/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/common/BaseGPSFixImporterImpl.java @@ -33,7 +33,7 @@ public abstract class BaseGPSFixImporterImpl implements GPSFixImporter { return; } SpeedWithBearing speedWithBearing = previousFix.getSpeedAndBearingRequiredToReach(fix); - fix = new GPSFixMovingImpl(fix.getPosition(), fix.getTimePoint(), speedWithBearing); + fix = new GPSFixMovingImpl(fix.getPosition(), fix.getTimePoint(), speedWithBearing, /* optionalTrueHeading */ null); } previousFix = fix; callback.addFix(fix, device); diff --git a/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/RouteConverterGPSFixImporterImpl.java b/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/RouteConverterGPSFixImporterImpl.java index 00d517ab9f4..0e5a7d9dd1a 100644 --- a/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/RouteConverterGPSFixImporterImpl.java +++ b/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/RouteConverterGPSFixImporterImpl.java @@ -209,7 +209,7 @@ public class RouteConverterGPSFixImporterImpl extends BaseRouteConverterGPSFixIm if (speedInKilometersPerHour != null && heading != null) { SpeedWithBearing speedWithBearing = new KilometersPerHourSpeedWithBearingImpl( speedInKilometersPerHour, new DegreeBearingImpl(heading)); - result = new GPSFixMovingImpl(pos, timePoint, speedWithBearing); + result = new GPSFixMovingImpl(pos, timePoint, speedWithBearing, /* optionalTrueHeading */ null); // we assume the Wgs84Position.getHeading() method returns COG, not HDG/HDT } else { result = new GPSFixImpl(pos, timePoint); }