0823e0c28c3479e5b903953f9a5158421bd2fc5f
java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/FieldNames.java
| ... | ... | @@ -198,7 +198,7 @@ public enum FieldNames { |
| 198 | 198 | MARK_PASSINGS_FINGERPRINT, MARK_PASSINGS, |
| 199 | 199 | |
| 200 | 200 | // MANEUVERS collection: |
| 201 | - MANEUVER_FINGERPRINT, MANEUVERS, TYPE, TACK, POSITION_LAT_RAD, POSITION_LNG_RAD, TIMEPOINT, MAIN_CURVE_BOUNDARIES, |
|
| 201 | + MANEUVER_FINGERPRINT, MANEUVERS, SIMPLE_CLASS_NAME, TYPE, TACK, POSITION_LAT_RAD, POSITION_LNG_RAD, TIMEPOINT, MAIN_CURVE_BOUNDARIES, |
|
| 202 | 202 | MANEUVER_CURVE_WITH_STABLE_SPEED_AND_COURSE_BOUNDERIES, MAX_TURNING_RATE_IN_DEGREE_PER_SECOUND, MANEUVER_LOSS, |
| 203 | 203 | // MANEUVERS main curve boundaries properties, see MAIN_CURVE_BOUNDARIES field above |
| 204 | 204 | MANEUVER_TIMEPOINT_BEFORE, MANEUVER_TIMEPOINT_AFTER, MANEUVER_SPEED_WITH_BEARING_BEFORE, MANEUVER_SPEED_WITH_BEARING_AFTER, |
java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java
| ... | ... | @@ -262,7 +262,6 @@ import com.sap.sailing.domain.tracking.TrackedRace; |
| 262 | 262 | import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; |
| 263 | 263 | import com.sap.sailing.domain.tracking.WindTrack; |
| 264 | 264 | import com.sap.sailing.domain.tracking.impl.ManeuverCurveBoundariesImpl; |
| 265 | -import com.sap.sailing.domain.tracking.impl.ManeuverWithMainCurveBoundariesImpl; |
|
| 266 | 265 | import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; |
| 267 | 266 | import com.sap.sailing.domain.tracking.impl.WindTrackImpl; |
| 268 | 267 | import com.sap.sailing.server.gateway.deserialization.impl.BoatJsonDeserializer; |
| ... | ... | @@ -3353,7 +3352,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { |
| 3353 | 3352 | } |
| 3354 | 3353 | |
| 3355 | 3354 | private Maneuver loadManeuver(Competitor competitor, Document maneuverDoc, Course course, TrackedRace trackedRace) { |
| 3356 | - final TimePoint timePoint = TimePoint.of( maneuverDoc.getLong(FieldNames.TIMEPOINT.name())); |
|
| 3355 | + final String simpleClassName = maneuverDoc.getString(FieldNames.SIMPLE_CLASS_NAME.name()); |
|
| 3356 | + final TimePoint timePoint = TimePoint.of(maneuverDoc.getLong(FieldNames.TIMEPOINT.name())); |
|
| 3357 | 3357 | final double maxTurningRateInDegreesPerSecond = maneuverDoc.getDouble(FieldNames.MAX_TURNING_RATE_IN_DEGREE_PER_SECOUND.name()); |
| 3358 | 3358 | final String typeName = maneuverDoc.getString(FieldNames.TYPE.name()); |
| 3359 | 3359 | final ManeuverType type = ManeuverType.valueOf(typeName); |
| ... | ... | @@ -3372,7 +3372,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { |
| 3372 | 3372 | } else { |
| 3373 | 3373 | markPassing = new MarkPassingProxy(timePoint, waypointIndex, competitor.getId(), trackedRace); |
| 3374 | 3374 | } |
| 3375 | - return new ManeuverWithMainCurveBoundariesImpl(type, newTack, position, timePoint, mainCurveBoundaries, |
|
| 3375 | + return Maneuver.create(simpleClassName, type, newTack, position, timePoint, mainCurveBoundaries, |
|
| 3376 | 3376 | maneuverCurveWithStableSpeedAndCourseBoundaries, maxTurningRateInDegreesPerSecond, markPassing, |
| 3377 | 3377 | maneuverLoss); |
| 3378 | 3378 | } |
| ... | ... | @@ -3405,21 +3405,21 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { |
| 3405 | 3405 | private ManeuverCurveBoundaries loadManeuverCurveBoundaries(Document document) { |
| 3406 | 3406 | final TimePoint timePointBefore = TimePoint.of(document.getLong(FieldNames.MANEUVER_TIMEPOINT_BEFORE.name())); |
| 3407 | 3407 | final TimePoint timePointAfter = TimePoint.of(document.getLong(FieldNames.MANEUVER_TIMEPOINT_AFTER.name())); |
| 3408 | - final Double SpeedWithBearingBeforeDegrees = document.getDouble(FieldNames.MANEUVER_SPEED_WITH_BEARING_BEFORE_DEGREES.name()); |
|
| 3409 | - final Double SpeedWithBearingBeforeSpeed = document.getDouble(FieldNames.MANEUVER_SPEED_WITH_BEARING_BEFORE_SPEED.name()); |
|
| 3410 | - final Bearing bearingBefore = new DegreeBearingImpl(SpeedWithBearingBeforeDegrees); |
|
| 3411 | - final SpeedWithBearing SpeedWithBearingBefore = new KnotSpeedWithBearingImpl(SpeedWithBearingBeforeSpeed, bearingBefore); |
|
| 3412 | - final Double SpeedWithBearingAfterDegrees = document.getDouble(FieldNames.MANEUVER_SPEED_WITH_BEARING_AFTER_DEGREES.name()); |
|
| 3413 | - final Double SpeedWithBearingAfterSpeed = document.getDouble(FieldNames.MANEUVER_SPEED_WITH_BEARING_AFTER_SPEED.name()); |
|
| 3414 | - final Bearing bearingAfter = new DegreeBearingImpl(SpeedWithBearingAfterSpeed); |
|
| 3415 | - final SpeedWithBearing SpeedWithBearingAfter = new KnotSpeedWithBearingImpl(SpeedWithBearingAfterDegrees, bearingAfter); |
|
| 3408 | + final Double speedWithBearingBeforeDegrees = document.getDouble(FieldNames.MANEUVER_SPEED_WITH_BEARING_BEFORE_DEGREES.name()); |
|
| 3409 | + final Double speedWithBearingBeforeSpeed = document.getDouble(FieldNames.MANEUVER_SPEED_WITH_BEARING_BEFORE_SPEED.name()); |
|
| 3410 | + final Bearing bearingBefore = new DegreeBearingImpl(speedWithBearingBeforeDegrees); |
|
| 3411 | + final SpeedWithBearing speedWithBearingBefore = new KnotSpeedWithBearingImpl(speedWithBearingBeforeSpeed, bearingBefore); |
|
| 3412 | + final Double speedWithBearingAfterDegrees = document.getDouble(FieldNames.MANEUVER_SPEED_WITH_BEARING_AFTER_DEGREES.name()); |
|
| 3413 | + final Double speedWithBearingAfterSpeed = document.getDouble(FieldNames.MANEUVER_SPEED_WITH_BEARING_AFTER_SPEED.name()); |
|
| 3414 | + final Bearing bearingAfter = new DegreeBearingImpl(speedWithBearingAfterSpeed); |
|
| 3415 | + final SpeedWithBearing speedWithBearingAfter = new KnotSpeedWithBearingImpl(speedWithBearingAfterDegrees, bearingAfter); |
|
| 3416 | 3416 | final double directionChangeInDegrees = document.getDouble(FieldNames.MANEUVER_DIRECTION_CHANGE_IN_DEGREES.name()); |
| 3417 | 3417 | final double lowestSpeedDouble = document.getDouble(FieldNames.MANEUVER_LOWEST_SPEED.name()); |
| 3418 | 3418 | final Speed lowestSpeed = new KnotSpeedImpl(lowestSpeedDouble); |
| 3419 | 3419 | final double highestSpeedDouble = document.getDouble(FieldNames.MANEUVER_HIGHEST_SPEED.name()); |
| 3420 | 3420 | final Speed highestSpeed = new KnotSpeedImpl(highestSpeedDouble); |
| 3421 | - ManeuverCurveBoundaries maneuverCurveBoundaries = new ManeuverCurveBoundariesImpl(timePointBefore, |
|
| 3422 | - timePointAfter, SpeedWithBearingBefore, SpeedWithBearingAfter, directionChangeInDegrees, lowestSpeed, |
|
| 3421 | + final ManeuverCurveBoundaries maneuverCurveBoundaries = new ManeuverCurveBoundariesImpl(timePointBefore, |
|
| 3422 | + timePointAfter, speedWithBearingBefore, speedWithBearingAfter, directionChangeInDegrees, lowestSpeed, |
|
| 3423 | 3423 | highestSpeed); |
| 3424 | 3424 | return maneuverCurveBoundaries; |
| 3425 | 3425 | } |
java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java
| ... | ... | @@ -2046,6 +2046,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { |
| 2046 | 2046 | if (e.getValue() != null) { |
| 2047 | 2047 | for (final Maneuver maneuver : e.getValue()) { |
| 2048 | 2048 | final Document maneuverDoc = new Document(); |
| 2049 | + maneuverDoc.put(FieldNames.SIMPLE_CLASS_NAME.name(), maneuver.getClass().getSimpleName()); |
|
| 2049 | 2050 | maneuverDoc.put(FieldNames.TYPE.name(), maneuver.getType().name()); |
| 2050 | 2051 | maneuverDoc.put(FieldNames.TACK.name(), maneuver.getNewTack().name()); |
| 2051 | 2052 | maneuverDoc.put(FieldNames.POSITION_LAT_RAD.name(), maneuver.getPosition().getLatRad()); |
| ... | ... | @@ -2070,12 +2071,12 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { |
| 2070 | 2071 | |
| 2071 | 2072 | private Document storeManeuverLoss(ManeuverLoss maneuverLoss) { |
| 2072 | 2073 | final Document maneuverLossDoc = new Document(); |
| 2073 | - maneuverLossDoc.put(FieldNames.MANEUVER_DISTANCE_SAILED_POMA.name(), maneuverLoss.getDistanceSailedIfNotManeuveringProjectedOnMiddleManeuverAngle().getMeters()); |
|
| 2074 | + maneuverLossDoc.put(FieldNames.MANEUVER_DISTANCE_SAILED_POMA.name(), maneuverLoss.getDistanceSailedProjectedOnMiddleManeuverAngle().getMeters()); |
|
| 2074 | 2075 | maneuverLossDoc.put(FieldNames.MANEUVER_DISTANCE_SAILED_INMPOMA.name(), maneuverLoss.getDistanceSailedIfNotManeuveringProjectedOnMiddleManeuverAngle().getMeters()); |
| 2075 | 2076 | maneuverLossDoc.put(FieldNames.MANEUVER_START_POSITION_LAT_RAD.name(), maneuverLoss.getManeuverStartPosition().getLatRad()); |
| 2076 | 2077 | maneuverLossDoc.put(FieldNames.MANEUVER_START_POSITION_LNG_RAD.name(), maneuverLoss.getManeuverStartPosition().getLngRad()); |
| 2077 | - maneuverLossDoc.put(FieldNames.MANEUVER_END_POSITION_LAT_RAD.name(), maneuverLoss.getManeuverStartPosition().getLngRad()); |
|
| 2078 | - maneuverLossDoc.put(FieldNames.MANEUVER_END_POSITION_LNG_RAD.name(), maneuverLoss.getManeuverStartPosition().getLngRad()); |
|
| 2078 | + maneuverLossDoc.put(FieldNames.MANEUVER_END_POSITION_LAT_RAD.name(), maneuverLoss.getManeuverEndPosition().getLatRad()); |
|
| 2079 | + maneuverLossDoc.put(FieldNames.MANEUVER_END_POSITION_LNG_RAD.name(), maneuverLoss.getManeuverEndPosition().getLngRad()); |
|
| 2079 | 2080 | maneuverLossDoc.put(FieldNames.MANEUVER_SPEED_WITH_BEARING_BEFORE_DEGREES.name(), maneuverLoss.getSpeedWithBearingBefore().getBearing().getDegrees()); |
| 2080 | 2081 | maneuverLossDoc.put(FieldNames.MANEUVER_SPEED_WITH_BEARING_BEFORE_SPEED.name(), maneuverLoss.getSpeedWithBearingBefore().getKnots()); |
| 2081 | 2082 | maneuverLossDoc.put(FieldNames.MIDDLE_MAEUVER_ANGLE.name(), maneuverLoss.getMiddleManeuverAngle().getDegrees()); |
java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/Maneuver.java
| ... | ... | @@ -5,7 +5,11 @@ import com.sap.sailing.domain.common.NauticalSide; |
| 5 | 5 | import com.sap.sailing.domain.common.Tack; |
| 6 | 6 | import com.sap.sailing.domain.common.tracking.GPSFix; |
| 7 | 7 | import com.sap.sailing.domain.maneuverdetection.impl.ManeuverDetectorImpl; |
| 8 | +import com.sap.sailing.domain.tracking.impl.ManeuverWithCoarseGrainedBoundariesImpl; |
|
| 9 | +import com.sap.sailing.domain.tracking.impl.ManeuverWithMainCurveBoundariesImpl; |
|
| 10 | +import com.sap.sailing.domain.tracking.impl.ManeuverWithStableSpeedAndCourseBoundariesImpl; |
|
| 8 | 11 | import com.sap.sse.common.Duration; |
| 12 | +import com.sap.sse.common.Position; |
|
| 9 | 13 | import com.sap.sse.common.Speed; |
| 10 | 14 | import com.sap.sse.common.SpeedWithBearing; |
| 11 | 15 | import com.sap.sse.common.TimePoint; |
| ... | ... | @@ -38,6 +42,26 @@ import com.sap.sse.datamining.annotations.Statistic; |
| 38 | 42 | * |
| 39 | 43 | */ |
| 40 | 44 | public interface Maneuver extends GPSFix { |
| 45 | + static Maneuver create(String simpleClassName, ManeuverType type, Tack newTack, Position position, TimePoint timePoint, |
|
| 46 | + ManeuverCurveBoundaries mainCurveBoundaries, |
|
| 47 | + ManeuverCurveBoundaries maneuverCurveWithStableSpeedAndCourseBoundaries, |
|
| 48 | + double maxTurningRateInDegreesPerSecond, MarkPassing markPassing, ManeuverLoss maneuverLoss) { |
|
| 49 | + final Maneuver result; |
|
| 50 | + if (simpleClassName.equals(ManeuverWithCoarseGrainedBoundariesImpl.class.getSimpleName())) { |
|
| 51 | + result = new ManeuverWithCoarseGrainedBoundariesImpl(type, newTack, position, timePoint, mainCurveBoundaries); |
|
| 52 | + } else if (simpleClassName.equals(ManeuverWithMainCurveBoundariesImpl.class.getSimpleName())) { |
|
| 53 | + result = new ManeuverWithMainCurveBoundariesImpl(type, newTack, position, timePoint, mainCurveBoundaries, |
|
| 54 | + maneuverCurveWithStableSpeedAndCourseBoundaries, maxTurningRateInDegreesPerSecond, markPassing, |
|
| 55 | + maneuverLoss); |
|
| 56 | + } else if (simpleClassName.equals(ManeuverWithStableSpeedAndCourseBoundariesImpl.class.getSimpleName())) { |
|
| 57 | + result = new ManeuverWithStableSpeedAndCourseBoundariesImpl(type, newTack, position, timePoint, mainCurveBoundaries, |
|
| 58 | + maneuverCurveWithStableSpeedAndCourseBoundaries, maxTurningRateInDegreesPerSecond, markPassing, |
|
| 59 | + maneuverLoss); |
|
| 60 | + } else { |
|
| 61 | + throw new IllegalArgumentException("Unsupported Maneuver implementation with simple class name: " + simpleClassName); |
|
| 62 | + } |
|
| 63 | + return result; |
|
| 64 | + } |
|
| 41 | 65 | /** |
| 42 | 66 | * Gets the type of this maneuver, e.g. whether its a tack, jibe and etc. The maneuver type is determined |
| 43 | 67 | * considering the boat's course change, wind bearing and marks. |
java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/ManeuverRaceFingerprintConversionTest.java
| ... | ... | @@ -7,6 +7,7 @@ import java.net.MalformedURLException; |
| 7 | 7 | import java.net.URISyntaxException; |
| 8 | 8 | import java.net.UnknownHostException; |
| 9 | 9 | import java.util.HashMap; |
| 10 | +import java.util.Iterator; |
|
| 10 | 11 | import java.util.List; |
| 11 | 12 | import java.util.Map; |
| 12 | 13 | |
| ... | ... | @@ -26,6 +27,7 @@ import com.sap.sailing.domain.persistence.PersistenceFactory; |
| 26 | 27 | import com.sap.sailing.domain.persistence.impl.MongoObjectFactoryImpl; |
| 27 | 28 | import com.sap.sailing.domain.test.OnlineTracTracBasedTest; |
| 28 | 29 | import com.sap.sailing.domain.tracking.Maneuver; |
| 30 | +import com.sap.sailing.domain.tracking.ManeuverLoss; |
|
| 29 | 31 | import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl; |
| 30 | 32 | import com.sap.sailing.domain.tractracadapter.ReceiverType; |
| 31 | 33 | import com.sap.sse.mongodb.MongoDBConfiguration; |
| ... | ... | @@ -69,8 +71,8 @@ public class ManeuverRaceFingerprintConversionTest extends OnlineTracTracBasedTe |
| 69 | 71 | final RaceIdentifier raceIdentifier = trackedRace1.getRaceIdentifier(); |
| 70 | 72 | final Map<Competitor, List<Maneuver>> maneuvers = new HashMap<>(); |
| 71 | 73 | for (final Competitor competitor : getRace().getCompetitors()) { |
| 72 | - final List<Maneuver> maneuversForCompetitor = (List<Maneuver>) trackedRace1.getManeuvers(competitor, true); |
|
| 73 | - maneuvers.put(competitor,maneuversForCompetitor); |
|
| 74 | + final List<Maneuver> maneuversForCompetitor = (List<Maneuver>) trackedRace1.getManeuvers(competitor, /* wait for latest */ true); |
|
| 75 | + maneuvers.put(competitor, maneuversForCompetitor); |
|
| 74 | 76 | } |
| 75 | 77 | new MongoObjectFactoryImpl(firstDatabase).storeManeuvers(raceIdentifier, fingerprint, trackedRace1.getRace().getCourse(), maneuvers); |
| 76 | 78 | final DomainObjectFactory dF = PersistenceFactory.INSTANCE.getDomainObjectFactory(dbConfiguration.getService(), getDomainFactory().getBaseDomainFactory()); |
| ... | ... | @@ -78,6 +80,32 @@ public class ManeuverRaceFingerprintConversionTest extends OnlineTracTracBasedTe |
| 78 | 80 | final ManeuverRaceFingerprint fingerprintAfterDB = fingerprintHashMap.get(trackedRace1.getRaceIdentifier()); |
| 79 | 81 | assertTrue(fingerprintAfterDB.matches(trackedRace1), "Original and de-serialized copy are equal"); |
| 80 | 82 | final Map<Competitor, List<Maneuver>> maneuversLoaded = dF.loadManeuvers(trackedRace1, trackedRace1.getRace().getCourse()); |
| 81 | - assertEquals(maneuvers, maneuversLoaded); |
|
| 83 | + assertEquals(maneuvers, maneuversLoaded); // this only checks the equality based on AbstractGPSFixImpl.equals, so lat/lng, cog/sog and time stamp |
|
| 84 | + for (final Competitor c : maneuversLoaded.keySet()) { |
|
| 85 | + final Iterator<Maneuver> maneuverIter = maneuvers.get(c).iterator(); |
|
| 86 | + for (final Maneuver m : maneuversLoaded.get(c)) { |
|
| 87 | + final Maneuver maneuverDetected = maneuverIter.next(); |
|
| 88 | + assertEqualManeuverLoss(maneuverDetected.getManeuverLoss(), m.getManeuverLoss()); |
|
| 89 | + assertEquals(maneuverDetected.getAvgTurningRateInDegreesPerSecond(), m.getAvgTurningRateInDegreesPerSecond(), 0.000001); |
|
| 90 | + assertEquals(maneuverDetected.getDirectionChangeInDegrees(), m.getDirectionChangeInDegrees()); |
|
| 91 | + } |
|
| 92 | + } |
|
| 93 | + } |
|
| 94 | + |
|
| 95 | + private void assertEqualManeuverLoss(ManeuverLoss maneuverLoss1, ManeuverLoss maneuverLoss2) { |
|
| 96 | + if (maneuverLoss1 != null) { |
|
| 97 | + assertEquals(maneuverLoss1.getManeuverStartPosition(), maneuverLoss2.getManeuverStartPosition()); |
|
| 98 | + assertEquals(maneuverLoss1.getManeuverEndPosition(), maneuverLoss2.getManeuverEndPosition()); |
|
| 99 | + assertEquals(maneuverLoss1.getDistanceSailedIfNotManeuveringProjectedOnMiddleManeuverAngle().getMeters(), |
|
| 100 | + maneuverLoss2.getDistanceSailedIfNotManeuveringProjectedOnMiddleManeuverAngle().getMeters(), 0.000001); |
|
| 101 | + assertEquals(maneuverLoss1.getDistanceSailedProjectedOnMiddleManeuverAngle().getMeters(), |
|
| 102 | + maneuverLoss2.getDistanceSailedProjectedOnMiddleManeuverAngle().getMeters(), 0.000001); |
|
| 103 | + assertEquals(maneuverLoss1.getManeuverDuration().asSeconds(), maneuverLoss2.getManeuverDuration().asSeconds(), 0.000001); |
|
| 104 | + assertEquals(maneuverLoss1.getMiddleManeuverAngle().getDegrees(), maneuverLoss2.getMiddleManeuverAngle().getDegrees(), 0.000001); |
|
| 105 | + assertEquals(maneuverLoss1.getProjectedDistanceLost().getMeters(), maneuverLoss2.getProjectedDistanceLost().getMeters(), 0.000001); |
|
| 106 | + assertEquals(maneuverLoss1.getRatioBetweenDistanceSailedWithAndWithoutManeuver(), maneuverLoss2.getRatioBetweenDistanceSailedWithAndWithoutManeuver(), 0.000001); |
|
| 107 | + assertEquals(maneuverLoss1.getSpeedWithBearingBefore().getKnots(), maneuverLoss2.getSpeedWithBearingBefore().getKnots(), 0.000001); |
|
| 108 | + assertEquals(maneuverLoss1.getSpeedWithBearingBefore().getBearing().getDegrees(), maneuverLoss2.getSpeedWithBearingBefore().getBearing().getDegrees(), 0.000001); |
|
| 109 | + } |
|
| 82 | 110 | } |
| 83 | 111 | } |