ce7c8aa1904fced7117c2e1961e489dfa9056592
java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java
| ... | ... | @@ -196,7 +196,6 @@ import com.sap.sailing.domain.common.MarkType; |
| 196 | 196 | import com.sap.sailing.domain.common.MaxPointsReason; |
| 197 | 197 | import com.sap.sailing.domain.common.PassingInstruction; |
| 198 | 198 | import com.sap.sailing.domain.common.Position; |
| 199 | -import com.sap.sailing.domain.common.RaceFetcher; |
|
| 200 | 199 | import com.sap.sailing.domain.common.RaceIdentifier; |
| 201 | 200 | import com.sap.sailing.domain.common.RankingMetrics; |
| 202 | 201 | import com.sap.sailing.domain.common.RegattaName; |
| ... | ... | @@ -270,7 +269,6 @@ import com.sap.sailing.domain.tracking.TrackedRace; |
| 270 | 269 | import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; |
| 271 | 270 | import com.sap.sailing.domain.tracking.WindTrack; |
| 272 | 271 | import com.sap.sailing.domain.tracking.impl.ManeuverCurveBoundariesImpl; |
| 273 | -import com.sap.sailing.domain.tracking.impl.ManeuverImpl; |
|
| 274 | 272 | import com.sap.sailing.domain.tracking.impl.ManeuverWithMainCurveBoundariesImpl; |
| 275 | 273 | import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; |
| 276 | 274 | import com.sap.sailing.domain.tracking.impl.WindTrackImpl; |
| ... | ... | @@ -3427,8 +3425,4 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { |
| 3427 | 3425 | ManeuverCurveBoundaries maneuverCurveBoundaries = new ManeuverCurveBoundariesImpl(timePointBefore, timePointAfter, SpeedWithBearingBefore, SpeedWithBearingAfter, directionChangeInDegrees, lowestSpeed, highestSpeed ); |
| 3428 | 3426 | return maneuverCurveBoundaries; |
| 3429 | 3427 | } |
| 3430 | - |
|
| 3431 | - |
|
| 3432 | - |
|
| 3433 | - |
|
| 3434 | 3428 | } |
| ... | ... | \ No newline at end of file |
java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java
| ... | ... | @@ -128,16 +128,15 @@ import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; |
| 128 | 128 | import com.sap.sailing.domain.leaderboard.SettableScoreCorrection; |
| 129 | 129 | import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; |
| 130 | 130 | import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprint; |
| 131 | -import com.sap.sailing.domain.maneuverhash.MarkPassingProxy; |
|
| 132 | 131 | import com.sap.sailing.domain.markpassinghash.MarkPassingRaceFingerprint; |
| 133 | 132 | import com.sap.sailing.domain.persistence.FieldNames; |
| 134 | 133 | import com.sap.sailing.domain.persistence.MongoObjectFactory; |
| 135 | 134 | import com.sap.sailing.domain.racelog.RaceLogIdentifier; |
| 136 | 135 | import com.sap.sailing.domain.regattalike.RegattaLikeIdentifier; |
| 137 | -import com.sap.sailing.domain.tracking.MarkPassing; |
|
| 138 | 136 | import com.sap.sailing.domain.tracking.Maneuver; |
| 139 | 137 | import com.sap.sailing.domain.tracking.ManeuverCurveBoundaries; |
| 140 | 138 | import com.sap.sailing.domain.tracking.ManeuverLoss; |
| 139 | +import com.sap.sailing.domain.tracking.MarkPassing; |
|
| 141 | 140 | import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParameters; |
| 142 | 141 | import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParametersHandler; |
| 143 | 142 | import com.sap.sailing.domain.tracking.TrackedRace; |
java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java
| ... | ... | @@ -137,7 +137,7 @@ public class AbstractGPSFixStoreTest extends RaceLogTrackingTestHelper { |
| 137 | 137 | /* endDate */null, null, null, "a", null, /* registrationLinkSecret */ UUID.randomUUID().toString())); |
| 138 | 138 | return new DynamicTrackedRaceImpl(regatta, raceDefinition, Collections.<Sideline> emptyList(), |
| 139 | 139 | EmptyWindStore.INSTANCE, 0, 0, 0, /* useMarkPassingCalculator */ false, OneDesignRankingMetric::new, |
| 140 | - mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 140 | + mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 141 | 141 | } |
| 142 | 142 | |
| 143 | 143 | protected void testNumberOfRawFixes(Track<?> track, long expected) { |
java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/RaceLogFixTrackerManagerTest.java
| ... | ... | @@ -97,7 +97,7 @@ public class RaceLogFixTrackerManagerTest { |
| 97 | 97 | /* registrationLinkSecret */ UUID.randomUUID().toString())); |
| 98 | 98 | trackedRace = new DynamicTrackedRaceImpl(regatta, race, Collections.<Sideline> emptyList(), |
| 99 | 99 | EmptyWindStore.INSTANCE, 0, 0, 0, /* useMarkPassingCalculator */ false, OneDesignRankingMetric::new, |
| 100 | - mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 100 | + mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 101 | 101 | } |
| 102 | 102 | |
| 103 | 103 | /** |
java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java
| ... | ... | @@ -171,7 +171,7 @@ public class SensorFixStoreAndLoadTest { |
| 171 | 171 | regatta.getRegatta().setControlTrackingFromStartAndFinishTimes(true); |
| 172 | 172 | trackedRace = new DynamicTrackedRaceImpl(regatta, race, Collections.<Sideline> emptyList(), |
| 173 | 173 | EmptyWindStore.INSTANCE, 0, 0, 0, /* useMarkPassingCalculator */ false, OneDesignRankingMetric::new, |
| 174 | - mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 174 | + mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 175 | 175 | } |
| 176 | 176 | |
| 177 | 177 | private void dropPersistedData() { |
java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java
| ... | ... | @@ -85,7 +85,7 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { |
| 85 | 85 | final DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race, |
| 86 | 86 | Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE, 0, 0, 0, |
| 87 | 87 | /* useMarkPassingCalculator */ false, |
| 88 | - OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 88 | + OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 89 | 89 | |
| 90 | 90 | MillisecondsTimePoint startOfRaceInRaceLog = new MillisecondsTimePoint(10000); |
| 91 | 91 | MillisecondsTimePoint endOfRaceInRaceLog = new MillisecondsTimePoint(20000); |
| ... | ... | @@ -163,7 +163,7 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { |
| 163 | 163 | final DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race, |
| 164 | 164 | Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE, 0, 0, 0, |
| 165 | 165 | /* useMarkPassingCalculator */ false, |
| 166 | - OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 166 | + OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 167 | 167 | trackedRace.attachRaceLog(raceLog); |
| 168 | 168 | final TimePoint[] oldAndNewStartTimeNotifiedByRace = new TimePoint[2]; |
| 169 | 169 | trackedRace.addListener(new AbstractRaceChangeListener() { |
| ... | ... | @@ -208,7 +208,7 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { |
| 208 | 208 | final DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race, |
| 209 | 209 | Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE, 0, 0, 0, |
| 210 | 210 | /* useMarkPassingCalculator */ false, |
| 211 | - OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 211 | + OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 212 | 212 | final TimePoint[] oldAndNewStartTimeNotifiedByRace = new TimePoint[2]; |
| 213 | 213 | trackedRace.addListener(new AbstractRaceChangeListener() { |
| 214 | 214 | @Override |
| ... | ... | @@ -257,7 +257,7 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { |
| 257 | 257 | final DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race, |
| 258 | 258 | Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE, 0, 0, 0, |
| 259 | 259 | /* useMarkPassingCalculator */ false, |
| 260 | - OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 260 | + OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 261 | 261 | trackedRace.attachRaceLog(raceLog); |
| 262 | 262 | trackedRace.attachRegattaLog(regattaLog); |
| 263 | 263 | final TimePoint[] newStartAndEndOfTrackingNotifiedByRace = new TimePoint[2]; |
| ... | ... | @@ -365,7 +365,7 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { |
| 365 | 365 | final DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race, |
| 366 | 366 | Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE, 0, 0, 0, |
| 367 | 367 | /* useMarkPassingCalculator */ false, |
| 368 | - OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 368 | + OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 369 | 369 | trackedRace.attachRaceLog(raceLog); |
| 370 | 370 | final TimePoint[] oldAndNewStartTimeNotifiedByRace = new TimePoint[2]; |
| 371 | 371 | trackedRace.addListener(new AbstractRaceChangeListener() { |
java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java
| ... | ... | @@ -355,7 +355,7 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl<RaceLogConne |
| 355 | 355 | boatClass.getApproximateManeuverDurationInMilliseconds(), null, /*useMarkPassingCalculator*/ true, raceLogResolver, |
| 356 | 356 | /* Not needed because the RaceTracker is not active on a replica */ Optional.empty(), |
| 357 | 357 | new TrackingConnectorInfoImpl(RaceLogTrackingAdapter.NAME, RaceLogTrackingAdapter.DEFAULT_URL, /* no webUrl */ null), |
| 358 | - markPassingRaceFingerprintRegistry); |
|
| 358 | + markPassingRaceFingerprintRegistry, /* maneuverRaceFingerprintRegistry */ null); |
|
| 359 | 359 | notifyRaceCreationListeners(); |
| 360 | 360 | logger.info(String.format("Started tracking race-log race (%s)", raceLog)); |
| 361 | 361 | // this wakes up all waiting race handles |
java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingRaceTrackerImpl.java
| ... | ... | @@ -545,7 +545,7 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl<SwissTim |
| 545 | 545 | } |
| 546 | 546 | }, useInternalMarkPassingAlgorithm, raceLogResolver, |
| 547 | 547 | /* Not needed because the RaceTracker is not active on a replica */ Optional.empty(), |
| 548 | - new TrackingConnectorInfoImpl(SwissTimingAdapter.NAME, SwissTimingAdapter.DEFAULT_URL,/*no api connection to query the webUrl*/ null), markPassingRaceFingerprintRegistry); |
|
| 548 | + new TrackingConnectorInfoImpl(SwissTimingAdapter.NAME, SwissTimingAdapter.DEFAULT_URL,/*no api connection to query the webUrl*/ null), markPassingRaceFingerprintRegistry,/*maneuverRaceFingerprintRegistry*/ null); |
|
| 549 | 549 | addUpdateHandlers(); |
| 550 | 550 | notifyRaceCreationListeners(); |
| 551 | 551 | logger.info("Created SwissTiming RaceDefinition and TrackedRace for "+race.getName()); |
java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java
| ... | ... | @@ -422,7 +422,7 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter i |
| 422 | 422 | /* time over which to average speed: */ race.getBoatClass().getApproximateManeuverDurationInMilliseconds(), |
| 423 | 423 | /* raceDefinitionSetToUpdate */ null, useInternalMarkPassingAlgorithm, raceLogResolver, |
| 424 | 424 | /* Not needed because the RaceTracker is not active on a replica */ Optional.empty(), |
| 425 | - new TrackingConnectorInfoImpl(SwissTimingAdapter.NAME, SwissTimingAdapter.DEFAULT_URL,/*no api connection to query the webUrl*/ null), markPassingRaceFingerprintRegistry); |
|
| 425 | + new TrackingConnectorInfoImpl(SwissTimingAdapter.NAME, SwissTimingAdapter.DEFAULT_URL,/*no api connection to query the webUrl*/ null), markPassingRaceFingerprintRegistry, /*maneuverRaceFingerprintRegistry*/ null); |
|
| 426 | 426 | trackedRace.onStatusChanged(this, new TrackedRaceStatusImpl(TrackedRaceStatusEnum.LOADING, 0)); |
| 427 | 427 | TimePoint bestStartTimeKnownSoFar = bestStartTimePerRaceID.get(currentRaceID); |
| 428 | 428 | if (bestStartTimeKnownSoFar != null) { |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassing/impl/WaypointPositionAndDistanceCacheTest.java
| ... | ... | @@ -79,7 +79,7 @@ public class WaypointPositionAndDistanceCacheTest { |
| 79 | 79 | trackedRace = new DynamicTrackedRaceImpl(trackedRegatta, race, Collections.emptyList(), EmptyWindStore.INSTANCE, |
| 80 | 80 | /* delayToLiveInMillis */ 8000, /* millisecondsOverWhichToAverageWind */ 30000, |
| 81 | 81 | /* millisecondsOverWhichToAverageSpeed */ 15000, /* delayForCacheInvalidationOfWindEstimation */ 10000, |
| 82 | - /* useInternalMarkPassingAlgorithm */ false, OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 82 | + /* useInternalMarkPassingAlgorithm */ false, OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 83 | 83 | timeRangeResolution = Duration.ONE_MINUTE; |
| 84 | 84 | now = new MillisecondsTimePoint(MillisecondsTimePoint.now().asMillis() / timeRangeResolution.asMillis() * timeRangeResolution.asMillis()); |
| 85 | 85 | trackedRace.getOrCreateTrack(pinEnd).addGPSFix(new GPSFixImpl(new DegreePosition(0, -0.0000001), now)); |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestCrossFleetScoring.java
| ... | ... | @@ -144,7 +144,7 @@ public class TestCrossFleetScoring extends LeaderboardScoringAndRankingTestBase |
| 144 | 144 | /* delay for wind estimation cache invalidation */ 0, /* useMarkPassingCalculator */ false, |
| 145 | 145 | tr -> new TimeOnTimeAndDistanceRankingMetric(tr, timeOnTimeFactors, // time-on-time |
| 146 | 146 | c -> new MillisecondsDurationImpl((long) (1000. * timeOnDistanceAllowance.apply(c)))), |
| 147 | - mock(RaceLogAndTrackedRaceResolver.class), null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 147 | + mock(RaceLogAndTrackedRaceResolver.class), null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 148 | 148 | // in this simplified artificial course, the top mark is exactly north of the right leeward gate |
| 149 | 149 | DegreePosition topPosition = new DegreePosition(1, 0); |
| 150 | 150 | trackedRace.getOrCreateTrack(left) |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java
| ... | ... | @@ -128,7 +128,7 @@ public class TestFarthestAheadWithSkippedMarkPassing { |
| 128 | 128 | /* delayToLiveInMillis */ 0, |
| 129 | 129 | /* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 30000, |
| 130 | 130 | /* delay for wind estimation cache invalidation */ 0, /*useMarkPassingCalculator*/ false, |
| 131 | - tr->new OneDesignRankingMetric(tr), mock(RaceLogAndTrackedRaceResolver.class), null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 131 | + tr->new OneDesignRankingMetric(tr), mock(RaceLogAndTrackedRaceResolver.class), null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 132 | 132 | // in this simplified artificial course, the top mark is exactly north of the right leeward gate |
| 133 | 133 | DegreePosition topPosition = new DegreePosition(1, 0); |
| 134 | 134 | trackedRace.getOrCreateTrack(left).addGPSFix(new GPSFixImpl(new DegreePosition(0, -0.000001), timePointForFixes)); |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestSimpleTimeOnTimeRankingWithOneUpwindLeg.java
| ... | ... | @@ -102,7 +102,7 @@ public class TestSimpleTimeOnTimeRankingWithOneUpwindLeg { |
| 102 | 102 | /* delay for wind estimation cache invalidation */ 0, /*useMarkPassingCalculator*/ false, |
| 103 | 103 | tr->new TimeOnTimeAndDistanceRankingMetric(tr, |
| 104 | 104 | timeOnTimeFactors, // time-on-time |
| 105 | - c->new MillisecondsDurationImpl((long) (1000.*timeOnDistanceFactors.apply(c)))), mock(RaceLogAndTrackedRaceResolver.class), null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 105 | + c->new MillisecondsDurationImpl((long) (1000.*timeOnDistanceFactors.apply(c)))), mock(RaceLogAndTrackedRaceResolver.class), null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 106 | 106 | // in this simplified artificial course, the top mark is exactly north of the right leeward gate |
| 107 | 107 | DegreePosition topPosition = new DegreePosition(1, 0); |
| 108 | 108 | trackedRace.getOrCreateTrack(left).addGPSFix(new GPSFixImpl(new DegreePosition(0, -0.000001), timePointForFixes)); |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseTest.java
| ... | ... | @@ -322,7 +322,7 @@ public class CourseTest { |
| 322 | 322 | Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE, /* delayToLiveInMillis */3000, |
| 323 | 323 | /* millisecondsOverWhichToAverageWind */30000, |
| 324 | 324 | /* millisecondsOverWhichToAverageSpeed */8000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new, |
| 325 | - mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 325 | + mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 326 | 326 | assertLegStructure(course, trackedRace); |
| 327 | 327 | course.removeWaypoint(0); |
| 328 | 328 | assertLegStructure(course, trackedRace); |
| ... | ... | @@ -358,7 +358,7 @@ public class CourseTest { |
| 358 | 358 | EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 3000, |
| 359 | 359 | /* millisecondsOverWhichToAverageWind */ 30000, |
| 360 | 360 | /* millisecondsOverWhichToAverageSpeed */ 8000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new, |
| 361 | - mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 361 | + mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 362 | 362 | assertLegStructure(course, trackedRace); |
| 363 | 363 | final WaypointImpl wp1_5 = new WaypointImpl(new MarkImpl("Test Mark 1.5")); |
| 364 | 364 | assertWaypointIndexes(course); |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateDuringNonAtomicSerializationTest.java
| ... | ... | @@ -88,7 +88,7 @@ public class CourseUpdateDuringNonAtomicSerializationTest implements Serializabl |
| 88 | 88 | EmptyWindStore.INSTANCE, |
| 89 | 89 | /* delayToLiveInMillis */10000, /* millisecondsOverWhichToAverageWind */30000, /* millisecondsOverWhichToAverageSpeed */ |
| 90 | 90 | 7000, /* useMarkPassingCalculator */ false, OneDesignRankingMetric::new, |
| 91 | - mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null) { |
|
| 91 | + mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null) { |
|
| 92 | 92 | private static final long serialVersionUID = 9114777576548711763L; |
| 93 | 93 | |
| 94 | 94 | @Override |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardCourseChangeTest.java
| ... | ... | @@ -140,7 +140,7 @@ public class LeaderboardCourseChangeTest { |
| 140 | 140 | TrackedRace spyedTrackedRace = spy(new DynamicTrackedRaceImpl(mockedTrackedRegatta, mockedRace, |
| 141 | 141 | new HashSet<Sideline>(), EmptyWindStore.INSTANCE, 5000, 20000, 20000, |
| 142 | 142 | /* useMarkPassingCalculator */ false, OneDesignRankingMetric::new, |
| 143 | - mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null)); |
|
| 143 | + mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null)); |
|
| 144 | 144 | |
| 145 | 145 | return spyedTrackedRace; |
| 146 | 146 | } |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceColumnCacheTest.java
| ... | ... | @@ -130,7 +130,7 @@ public class RaceColumnCacheTest extends AbstractLeaderboardTest { |
| 130 | 130 | new HashSet<Sideline>(), EmptyWindStore.INSTANCE, 5000, 20000, 20000, |
| 131 | 131 | /* useMarkPassingCalculator */ false, OneDesignRankingMetric::new, |
| 132 | 132 | mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, |
| 133 | - /* markPassingRaceFingerprintRegistry */ null)); |
|
| 133 | + /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null)); |
|
| 134 | 134 | return spyedTrackedRace; |
| 135 | 135 | } |
| 136 | 136 |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReachingLegTest.java
| ... | ... | @@ -119,7 +119,7 @@ public class ReachingLegTest extends TrackBasedTest { |
| 119 | 119 | /* delayToLiveInMillis */ 0, |
| 120 | 120 | /* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 30000, |
| 121 | 121 | /* delay for wind estimation cache invalidation */ 0, /*useMarkPassingCalculator*/ false, |
| 122 | - OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 122 | + OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 123 | 123 | // in this simplified artificial course, the top mark is exactly north of the right leeward gate, the offset |
| 124 | 124 | // mark is slightly west of the top mark; wind from the north makes the leg from top to offset a reaching leg |
| 125 | 125 | Position leftPosition = new DegreePosition(0, -0.00001); |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/SerializeRankingMetricTest.java
| ... | ... | @@ -42,7 +42,7 @@ public class SerializeRankingMetricTest extends AbstractSerializationTest { |
| 42 | 42 | new RaceDefinitionImpl("Race", new CourseImpl("Course", Collections.<Waypoint>emptyList()) , |
| 43 | 43 | /* boatClass */ _49er, Collections.<Competitor,Boat>emptyMap()), |
| 44 | 44 | Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE, 0l, 0l, 0l, |
| 45 | - false, TimeOnTimeAndDistanceRankingMetric::new, null, /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 45 | + false, TimeOnTimeAndDistanceRankingMetric::new, null, /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* mneuverRaceFingerprintRegistry */ null); |
|
| 46 | 46 | RankingMetric clone = cloneBySerialization(trackedRace.getRankingMetric(), DomainFactory.INSTANCE); |
| 47 | 47 | assertNotNull(clone); |
| 48 | 48 | assertTrue(clone instanceof TimeOnTimeAndDistanceRankingMetric); |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StarbordSideOfStartLineRecognitionTest.java
| ... | ... | @@ -91,7 +91,7 @@ public class StarbordSideOfStartLineRecognitionTest { |
| 91 | 91 | |
| 92 | 92 | public MockedTrackedRaceImpl() { |
| 93 | 93 | super(null, null, Collections.<Sideline> emptyList(), null, 0, 0, 0, 0, false, OneDesignRankingMetric::new, |
| 94 | - mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 94 | + mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 95 | 95 | } |
| 96 | 96 | |
| 97 | 97 | @Override |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackBasedTest.java
| ... | ... | @@ -201,7 +201,7 @@ public abstract class TrackBasedTest { |
| 201 | 201 | /* delayToLiveInMillis */ 0, |
| 202 | 202 | /* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 30000, |
| 203 | 203 | /* delay for wind estimation cache invalidation */ 0, useMarkPassingCalculator, |
| 204 | - rankingMetricConstructor, raceLogResolver, /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 204 | + rankingMetricConstructor, raceLogResolver, /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 205 | 205 | // in this simplified artificial course, the top mark is exactly north of the right leeward gate |
| 206 | 206 | DegreePosition topPosition = new DegreePosition(54.48, 10.24); |
| 207 | 207 | TimePoint afterTheRace = new MillisecondsTimePoint(timePointForFixes.asMillis() + 36000000); // 10h after the fix timed |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/UpdateMarkPassingTest.java
| ... | ... | @@ -53,7 +53,7 @@ public class UpdateMarkPassingTest { |
| 53 | 53 | race, Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE, /* delayToLiveInMillis */1000, |
| 54 | 54 | /* millisecondsOverWhichToAverageWind */30000, /* millisecondsOverWhichToAverageSpeed */30000, |
| 55 | 55 | /* useMarkPassingCalculator */ false, OneDesignRankingMetric::new, |
| 56 | - mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 56 | + mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 57 | 57 | TimePoint now = MillisecondsTimePoint.now(); |
| 58 | 58 | TimePoint later = now.plus(1000); |
| 59 | 59 | trackedRace.updateMarkPassings(competitor, Arrays.asList(new MarkPassing[] { new MarkPassingImpl(now, waypoint, competitor) })); |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindEstimationLockingUnderLoadTest.java
| ... | ... | @@ -108,7 +108,7 @@ public class WindEstimationLockingUnderLoadTest { |
| 108 | 108 | /* sidelines */ Collections.emptySet(), EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 10000, |
| 109 | 109 | /* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 15000, |
| 110 | 110 | /* useInternalMarkPassingAlgorithm */ false, regatta.getRankingMetricConstructor(), /* raceLogResolver */ null, |
| 111 | - /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null) { |
|
| 111 | + /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null) { |
|
| 112 | 112 | private static final long serialVersionUID = 1L; |
| 113 | 113 | |
| 114 | 114 | @Override |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java
| ... | ... | @@ -356,7 +356,7 @@ public class WindTest { |
| 356 | 356 | EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 1000, |
| 357 | 357 | /* millisecondsOverWhichToAverageWind */ 30000, |
| 358 | 358 | /* millisecondsOverWhichToAverageSpeed */ 30000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new, |
| 359 | - mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 359 | + mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 360 | 360 | TimePoint start = MillisecondsTimePoint.now(); |
| 361 | 361 | TimePoint topMarkRounding = start.plus(30000); |
| 362 | 362 | TimePoint finish = topMarkRounding.plus(30000); |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/maneuverhash/ManeuverRaceFingerprintJsonSerilizationTest.java
| ... | ... | @@ -9,45 +9,26 @@ import static org.junit.jupiter.api.Assertions.assertTrue; |
| 9 | 9 | |
| 10 | 10 | import java.net.MalformedURLException; |
| 11 | 11 | import java.net.URISyntaxException; |
| 12 | -import java.util.HashMap; |
|
| 13 | -import java.util.Map; |
|
| 14 | 12 | import java.util.UUID; |
| 15 | 13 | |
| 16 | 14 | import org.json.simple.JSONObject; |
| 17 | 15 | import org.junit.jupiter.api.BeforeEach; |
| 18 | 16 | import org.junit.jupiter.api.Test; |
| 19 | 17 | |
| 20 | -import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; |
|
| 21 | -import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; |
|
| 22 | -import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; |
|
| 23 | -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFixedMarkPassingEventImpl; |
|
| 24 | 18 | import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; |
| 25 | -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogSuppressedMarkPassingsEventImpl; |
|
| 26 | 19 | import com.sap.sailing.domain.base.Competitor; |
| 27 | -import com.sap.sailing.domain.base.ControlPoint; |
|
| 28 | -import com.sap.sailing.domain.base.ControlPointWithTwoMarks; |
|
| 29 | -import com.sap.sailing.domain.base.Mark; |
|
| 30 | -import com.sap.sailing.domain.base.Waypoint; |
|
| 31 | -import com.sap.sailing.domain.base.impl.ControlPointWithTwoMarksImpl; |
|
| 32 | -import com.sap.sailing.domain.base.impl.MarkImpl; |
|
| 33 | -import com.sap.sailing.domain.base.impl.WaypointImpl; |
|
| 34 | -import com.sap.sailing.domain.common.PassingInstruction; |
|
| 35 | 20 | import com.sap.sailing.domain.common.Position; |
| 36 | 21 | import com.sap.sailing.domain.common.SpeedWithBearing; |
| 37 | -import com.sap.sailing.domain.common.abstractlog.NotRevokableException; |
|
| 38 | 22 | import com.sap.sailing.domain.common.impl.DegreePosition; |
| 39 | 23 | import com.sap.sailing.domain.common.tracking.GPSFixMoving; |
| 40 | -import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl; |
|
| 41 | 24 | import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; |
| 42 | -import com.sap.sailing.domain.markpassingcalculation.MarkPassingCalculator; |
|
| 43 | -import com.sap.sailing.domain.markpassinghash.MarkPassingRaceFingerprint; |
|
| 44 | 25 | import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprint; |
| 45 | 26 | import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprintFactory; |
| 27 | +import com.sap.sailing.domain.markpassingcalculation.MarkPassingCalculator; |
|
| 46 | 28 | import com.sap.sailing.domain.test.OnlineTracTracBasedTest; |
| 47 | 29 | import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl; |
| 48 | 30 | import com.sap.sailing.domain.tractracadapter.ReceiverType; |
| 49 | 31 | import com.sap.sse.common.TimePoint; |
| 50 | -import com.sap.sse.common.impl.MillisecondsTimePoint; |
|
| 51 | 32 | |
| 52 | 33 | public class ManeuverRaceFingerprintJsonSerilizationTest extends OnlineTracTracBasedTest { |
| 53 | 34 | DynamicTrackedRaceImpl trackedRace1; |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractExportedPositionsBasedTest.java
| ... | ... | @@ -107,7 +107,7 @@ public abstract class AbstractExportedPositionsBasedTest { |
| 107 | 107 | EmptyWindStore.INSTANCE, |
| 108 | 108 | /* delayToLiveInMillis */ 3000, /* millisecondsOverWhichToAverageWind */ 15000, |
| 109 | 109 | /* millisecondsOverWhichToAverageSpeed */ 10000, /* useInternalMarkPassingAlgorithm */ true, |
| 110 | - OneDesignRankingMetric::new, /* raceLogResolver */ null, /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 110 | + OneDesignRankingMetric::new, /* raceLogResolver */ null, /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 111 | 111 | result.setStatus(new TrackedRaceStatusImpl(TrackedRaceStatusEnum.LOADING, 0.0)); |
| 112 | 112 | for (final Entry<CompetitorWithBoat, Iterable<GPSFixMoving>> e : competitorsAndTheirTracks.entrySet()) { |
| 113 | 113 | final DynamicGPSFixTrack<Competitor, GPSFixMoving> track = result.getTrack(e.getKey()); |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractMockedRaceMarkPassingTest.java
| ... | ... | @@ -88,7 +88,7 @@ public class AbstractMockedRaceMarkPassingTest { |
| 88 | 88 | race = new DynamicTrackedRaceImpl(new DynamicTrackedRegattaImpl(r), raceDef, new ArrayList<Sideline>(), |
| 89 | 89 | new EmptyWindStore(), 0, 10000, 10000, /* useMarkPassingCalculator */ false, |
| 90 | 90 | OneDesignRankingMetric::new, |
| 91 | - mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 91 | + mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */null); |
|
| 92 | 92 | race.setStartTimeReceived(new MillisecondsTimePoint(10000)); |
| 93 | 93 | TimePoint t = new MillisecondsTimePoint(30000); |
| 94 | 94 | List<Util.Pair<Mark, Position>> pos = Arrays.asList(new Util.Pair<Mark, Position>(m, new DegreePosition(0, 0)), |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java
| ... | ... | @@ -55,6 +55,7 @@ import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCalculationReuse |
| 55 | 55 | import com.sap.sailing.domain.leaderboard.impl.CompetitorAndRankComparable; |
| 56 | 56 | import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike; |
| 57 | 57 | import com.sap.sailing.domain.leaderboard.impl.RankAndRankComparable; |
| 58 | +import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprintRegistry; |
|
| 58 | 59 | import com.sap.sailing.domain.markpassinghash.MarkPassingRaceFingerprintRegistry; |
| 59 | 60 | import com.sap.sailing.domain.polars.PolarDataService; |
| 60 | 61 | import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver; |
| ... | ... | @@ -695,7 +696,7 @@ public class MockedTrackedRace implements DynamicTrackedRace { |
| 695 | 696 | DynamicRaceDefinitionSet raceDefinitionSetToUpdate, boolean useMarkPassingcalculator, |
| 696 | 697 | RaceLogAndTrackedRaceResolver raceLogResolver, |
| 697 | 698 | Optional<ThreadLocalTransporter> threadLocalTransporter, |
| 698 | - TrackingConnectorInfo trackingConnectorInfo, MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry) { |
|
| 699 | + TrackingConnectorInfo trackingConnectorInfo, MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry, ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry ) { |
|
| 699 | 700 | return null; |
| 700 | 701 | } |
| 701 | 702 | |
| ... | ... | @@ -1416,4 +1417,8 @@ public class MockedTrackedRace implements DynamicTrackedRace { |
| 1416 | 1417 | WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { |
| 1417 | 1418 | return null; |
| 1418 | 1419 | } |
| 1419 | -} |
|
| 1420 | + |
|
| 1421 | + @Override |
|
| 1422 | + public void updateManeuvers(Competitor competitor, Iterable<Maneuver> maneuvers) { |
|
| 1423 | + } |
|
| 1424 | +} |
|
| ... | ... | \ No newline at end of file |
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/impl/TrackedRegattaTest.java
| ... | ... | @@ -124,6 +124,6 @@ public class TrackedRegattaTest { |
| 124 | 124 | RaceDefinition race1 = new RaceDefinitionImpl(name, course, boatClass, Collections.emptyMap()); |
| 125 | 125 | return new DynamicTrackedRaceImpl(regatta, race1, Collections.<Sideline> emptyList(), |
| 126 | 126 | EmptyWindStore.INSTANCE, 0, 0, 0, /* useMarkPassingCalculator */ false, OneDesignRankingMetric::new, |
| 127 | - mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 127 | + mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 128 | 128 | } |
| 129 | 129 | } |
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java
| ... | ... | @@ -783,7 +783,7 @@ public class DomainFactoryImpl implements DomainFactory { |
| 783 | 783 | windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, |
| 784 | 784 | /* time over which to average speed: */ race.getBoatClass().getApproximateManeuverDurationInMilliseconds(), |
| 785 | 785 | raceDefinitionSetToUpdate, useMarkPassingCalculator, raceLogResolver, Optional.empty(), |
| 786 | - trackingConnectorInfo, markPassingRaceFingerprintRegistry); |
|
| 786 | + trackingConnectorInfo, markPassingRaceFingerprintRegistry, /*maneuverRaceFingerprintRegistry*/ null); |
|
| 787 | 787 | } |
| 788 | 788 | |
| 789 | 789 | /** |
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceCourseReceiver.java
| ... | ... | @@ -264,7 +264,7 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<IControlRoute, |
| 264 | 264 | /* ThreadLocalTransporter not needed because the RaceTracker is not active on a replica */ Optional |
| 265 | 265 | .empty(), |
| 266 | 266 | new TrackingConnectorInfoImpl(TracTracAdapter.NAME, TracTracAdapter.DEFAULT_URL, |
| 267 | - webUrlString), markPassingRaceFingerprintRegistry); |
|
| 267 | + webUrlString), markPassingRaceFingerprintRegistry, /* maneuverRaceFingerprintRegistry */ null); |
|
| 268 | 268 | if (runAfterCreatingTrackedRace != null) { |
| 269 | 269 | runAfterCreatingTrackedRace.accept(trackedRace); |
| 270 | 270 | } |
java/com.sap.sailing.domain.yellowbrickadapter/src/com/sap/sailing/domain/yellowbrickadapter/impl/YellowBrickRaceTrackerImpl.java
| ... | ... | @@ -148,7 +148,7 @@ implements TrackingDataLoader { |
| 148 | 148 | } |
| 149 | 149 | }, /* useInternalMarkPassingAlgorithm */ true, raceLogResolver, |
| 150 | 150 | /* Not needed because the RaceTracker is not active on a replica */ Optional.empty(), |
| 151 | - new TrackingConnectorInfoImpl(YellowBrickTrackingAdapter.NAME, "https://www.ybtracking.com/", /* TODO any default YB tracker URL? */ null), /* markPassingRaceFingerprintRegistry */ null); |
|
| 151 | + new TrackingConnectorInfoImpl(YellowBrickTrackingAdapter.NAME, "https://www.ybtracking.com/", /* TODO any default YB tracker URL? */ null), /* markPassingRaceFingerprintRegistry */ null, /*maneuverRaceFingerprintRegistry*/ null); |
|
| 152 | 152 | addRaceLogListenerForCourseUpdates(); |
| 153 | 153 | loadStoredData(); |
| 154 | 154 | schedulePeriodicPollingTask(); |
java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverhash/MarkPassingProxy.java
| ... | ... | @@ -4,7 +4,6 @@ import java.io.Serializable; |
| 4 | 4 | |
| 5 | 5 | import com.sap.sailing.domain.base.Competitor; |
| 6 | 6 | import com.sap.sailing.domain.base.Waypoint; |
| 7 | -import com.sap.sailing.domain.common.RaceIdentifier; |
|
| 8 | 7 | import com.sap.sailing.domain.tracking.MarkPassing; |
| 9 | 8 | import com.sap.sailing.domain.tracking.TrackedRace; |
| 10 | 9 | import com.sap.sse.common.TimePoint; |
| ... | ... | @@ -36,8 +35,8 @@ public class MarkPassingProxy implements MarkPassing { |
| 36 | 35 | |
| 37 | 36 | @Override |
| 38 | 37 | public TimePoint getTimePoint() { |
| 39 | - isMarkPassing(); |
|
| 40 | - return markPassing.getTimePoint(); |
|
| 38 | +// isMarkPassing(); |
|
| 39 | + return timePoint; |
|
| 41 | 40 | } |
| 42 | 41 | |
| 43 | 42 | @Override |
java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverhash/impl/ManeuverCacheDelegate.java
| ... | ... | @@ -0,0 +1,197 @@ |
| 1 | +package com.sap.sailing.domain.maneuverhash.impl; |
|
| 2 | + |
|
| 3 | +import java.util.ArrayList; |
|
| 4 | +import java.util.Collections; |
|
| 5 | +import java.util.List; |
|
| 6 | +import java.util.Map; |
|
| 7 | +import java.util.Set; |
|
| 8 | +import java.util.logging.Level; |
|
| 9 | +import java.util.logging.Logger; |
|
| 10 | + |
|
| 11 | +import com.sap.sailing.domain.base.CPUMeteringType; |
|
| 12 | +import com.sap.sailing.domain.base.Competitor; |
|
| 13 | +import com.sap.sailing.domain.common.NoWindException; |
|
| 14 | +import com.sap.sailing.domain.maneuverdetection.ManeuverDetector; |
|
| 15 | +import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprint; |
|
| 16 | +import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprintFactory; |
|
| 17 | +import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprintRegistry; |
|
| 18 | +import com.sap.sailing.domain.tracking.DynamicTrackedRace; |
|
| 19 | +import com.sap.sailing.domain.tracking.Maneuver; |
|
| 20 | +import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl; |
|
| 21 | +import com.sap.sse.common.Duration; |
|
| 22 | +import com.sap.sse.util.ManeuverCache; |
|
| 23 | +import com.sap.sse.util.SmartFutureCache; |
|
| 24 | +import com.sap.sse.util.SmartFutureCache.AbstractCacheUpdater; |
|
| 25 | +import com.sap.sse.util.SmartFutureCache.EmptyUpdateInterval; |
|
| 26 | +import com.sap.sse.util.SmartFutureCache.UpdateInterval; |
|
| 27 | + |
|
| 28 | +public class ManeuverCacheDelegate implements ManeuverCache<Competitor, List<Maneuver>, EmptyUpdateInterval> { |
|
| 29 | + |
|
| 30 | + |
|
| 31 | + private final TrackedRaceImpl race; |
|
| 32 | + private static final Logger logger = Logger.getLogger(ManeuverCacheDelegate.class.getName()); |
|
| 33 | + private final ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry; |
|
| 34 | + private ManeuverCache<Competitor, List<Maneuver>, EmptyUpdateInterval> maneuverCache; |
|
| 35 | + private ManeuverFromDatabase cache; |
|
| 36 | + private SmartFutureCache<Competitor, List<Maneuver>, EmptyUpdateInterval> smartFutureCache; |
|
| 37 | + Map<Competitor, List<Maneuver>> maneuvers; |
|
| 38 | +// // flag suspended / resume |
|
| 39 | + private boolean cachesSuspended; |
|
| 40 | + private boolean triggerManeuverCacheInvalidationForAllCompetitors; |
|
| 41 | + |
|
| 42 | + public ManeuverCacheDelegate(TrackedRaceImpl race, |
|
| 43 | + ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry) { |
|
| 44 | + super(); |
|
| 45 | + this.race = race; |
|
| 46 | + this.maneuverRaceFingerprintRegistry = maneuverRaceFingerprintRegistry; |
|
| 47 | + this.cache = new ManeuverFromDatabase( false, race, maneuverRaceFingerprintRegistry); |
|
| 48 | + this.smartFutureCache = new SmartFutureCache<Competitor, List<Maneuver>, EmptyUpdateInterval>( |
|
| 49 | + new AbstractCacheUpdater<Competitor, List<Maneuver>, EmptyUpdateInterval>() { |
|
| 50 | + @Override |
|
| 51 | + public List<Maneuver> computeCacheUpdate(Competitor competitor, EmptyUpdateInterval updateInterval) |
|
| 52 | + throws NoWindException { |
|
| 53 | + return race.getTrackedRegatta().callWithCPUMeterWithException(()->{ |
|
| 54 | + Duration averageIntervalBetweenRawFixes = race.getTrack(competitor).getAverageIntervalBetweenRawFixes(); |
|
| 55 | + if (averageIntervalBetweenRawFixes != null) { |
|
| 56 | + ManeuverDetector maneuverDetector; |
|
| 57 | + // FIXME The LowGPSSamplingRateManeuverDetectorImpl doesn't work very well; it recognizes many tacks only as bear-away and doesn't seem to have any noticeable benefits... See ORC Worlds 2019 ORC A Long Offshore |
|
| 58 | + // if (averageIntervalBetweenRawFixes.asSeconds() >= 30) { |
|
| 59 | + // maneuverDetector = new LowGPSSamplingRateManeuverDetectorImpl(TrackedRaceImpl.this, competitor); |
|
| 60 | + // } else { |
|
| 61 | + maneuverDetector = race.getManeuverDetectorPerCompetitorCache().getValue(competitor); |
|
| 62 | + |
|
| 63 | + // } |
|
| 64 | + List<Maneuver> maneuvers = race.computeManeuvers(competitor, maneuverDetector); |
|
| 65 | + return maneuvers; |
|
| 66 | + } else { |
|
| 67 | + return Collections.emptyList(); |
|
| 68 | + } |
|
| 69 | + }, CPUMeteringType.MANEUVER_DETECTION.name()); |
|
| 70 | + } |
|
| 71 | + }, /* nameForLocks */ "Maneuver cache for race " + race.getRace().getName()); |
|
| 72 | + } |
|
| 73 | + |
|
| 74 | + @Override |
|
| 75 | + public void resume() { |
|
| 76 | + // richtigen Ort bestimmen |
|
| 77 | + if (triggerManeuverCacheInvalidationForAllCompetitors) { |
|
| 78 | + triggerManeuverCacheRecalculationForAllCompetitors(); |
|
| 79 | + } |
|
| 80 | + |
|
| 81 | + ManeuverRaceFingerprint fingerprint; |
|
| 82 | + race.getRace().getCourse().lockForRead(); |
|
| 83 | + try { |
|
| 84 | + synchronized (this) { |
|
| 85 | + if (maneuverRaceFingerprintRegistry != null) { |
|
| 86 | + fingerprint = maneuverRaceFingerprintRegistry.getManeuverRaceFingerprint(race.getRaceIdentifier()); |
|
| 87 | + } else { |
|
| 88 | + fingerprint = null; |
|
| 89 | + } |
|
| 90 | + if (fingerprint != null && fingerprint.matches(race)) { |
|
| 91 | + cache.resume(); |
|
| 92 | + } else { |
|
| 93 | + new Thread(()->{ |
|
| 94 | + smartFutureCache.resume(); |
|
| 95 | + for(Competitor competitor : race.getRace().getCompetitors()) { |
|
| 96 | + maneuvers.put(competitor, (List<Maneuver>) smartFutureCache.get(competitor, true)); |
|
| 97 | + } |
|
| 98 | + maneuverRaceFingerprintRegistry.storeManeuvers(race.getRaceIdentifier(), ManeuverRaceFingerprintFactory.INSTANCE.createFingerprint(race), maneuvers, race.getRace().getCourse()); |
|
| 99 | + }, "Waiting for mark passings for "+race.getName()+" after having resumed to store the results in registry") |
|
| 100 | + .start(); |
|
| 101 | + } |
|
| 102 | + } |
|
| 103 | + } finally { |
|
| 104 | + race.getRace().getCourse().unlockAfterRead(); |
|
| 105 | + } |
|
| 106 | + } |
|
| 107 | + |
|
| 108 | + @Override |
|
| 109 | + public List<Maneuver> get(Competitor competitor, boolean waitForLatest) { |
|
| 110 | + ManeuverRaceFingerprint fingerprint; |
|
| 111 | + race.getRace().getCourse().lockForRead(); |
|
| 112 | + try { |
|
| 113 | + synchronized (this) { |
|
| 114 | + if (maneuverRaceFingerprintRegistry != null) { |
|
| 115 | + fingerprint = maneuverRaceFingerprintRegistry.getManeuverRaceFingerprint(race.getRaceIdentifier()); |
|
| 116 | + } else { |
|
| 117 | + fingerprint = null; |
|
| 118 | + } |
|
| 119 | + if (fingerprint != null && fingerprint.matches(race)) { |
|
| 120 | + return cache.get(competitor, waitForLatest); |
|
| 121 | + } else { |
|
| 122 | + return smartFutureCache.get(competitor, waitForLatest); |
|
| 123 | + } |
|
| 124 | + } |
|
| 125 | + } finally { |
|
| 126 | + race.getRace().getCourse().unlockAfterRead(); |
|
| 127 | + } |
|
| 128 | + } |
|
| 129 | + |
|
| 130 | + @Override |
|
| 131 | + public void suspend() { |
|
| 132 | + ManeuverRaceFingerprint fingerprint; |
|
| 133 | + race.getRace().getCourse().lockForRead(); |
|
| 134 | + try { |
|
| 135 | + synchronized (this) { |
|
| 136 | + if (maneuverRaceFingerprintRegistry != null) { |
|
| 137 | + fingerprint = maneuverRaceFingerprintRegistry.getManeuverRaceFingerprint(race.getRaceIdentifier()); |
|
| 138 | + } else { |
|
| 139 | + fingerprint = null; |
|
| 140 | + } |
|
| 141 | + if (fingerprint != null && fingerprint.matches(race)) { |
|
| 142 | + cache.suspend(); |
|
| 143 | + } else { |
|
| 144 | + smartFutureCache.suspend(); |
|
| 145 | + } |
|
| 146 | + } |
|
| 147 | + } finally { |
|
| 148 | + race.getRace().getCourse().unlockAfterRead(); |
|
| 149 | + } |
|
| 150 | + } |
|
| 151 | + |
|
| 152 | + @Override |
|
| 153 | + public void triggerUpdate(Competitor competitor, EmptyUpdateInterval updateInterval) { |
|
| 154 | + ManeuverRaceFingerprint fingerprint; |
|
| 155 | + race.getRace().getCourse().lockForRead(); |
|
| 156 | + try { |
|
| 157 | + synchronized (this) { |
|
| 158 | + if (maneuverRaceFingerprintRegistry != null) { |
|
| 159 | + fingerprint = maneuverRaceFingerprintRegistry.getManeuverRaceFingerprint(race.getRaceIdentifier()); |
|
| 160 | + } else { |
|
| 161 | + fingerprint = null; |
|
| 162 | + } |
|
| 163 | + if (fingerprint != null && fingerprint.matches(race)) { |
|
| 164 | + cache.triggerUpdate(competitor, updateInterval); |
|
| 165 | + } else { |
|
| 166 | + smartFutureCache.triggerUpdate(competitor, updateInterval);; |
|
| 167 | + } |
|
| 168 | + } |
|
| 169 | + } finally { |
|
| 170 | + race.getRace().getCourse().unlockAfterRead(); |
|
| 171 | + } |
|
| 172 | + } |
|
| 173 | + |
|
| 174 | + |
|
| 175 | + public void triggerManeuverCacheRecalculationForAllCompetitors() { |
|
| 176 | + if (cachesSuspended) { |
|
| 177 | + triggerManeuverCacheInvalidationForAllCompetitors = true; |
|
| 178 | + } else { |
|
| 179 | + final List<Competitor> shuffledCompetitors = new ArrayList<>(); |
|
| 180 | + for (Competitor competitor : (race.getRace().getCompetitors())) { |
|
| 181 | + shuffledCompetitors.add(competitor); |
|
| 182 | + } |
|
| 183 | + Collections.shuffle(shuffledCompetitors); |
|
| 184 | + for (Competitor competitor : shuffledCompetitors) { |
|
| 185 | + triggerManeuverCacheRecalculation(competitor); |
|
| 186 | + } |
|
| 187 | + } |
|
| 188 | + } |
|
| 189 | + |
|
| 190 | + public void triggerManeuverCacheRecalculation(final Competitor competitor) { |
|
| 191 | + if (cachesSuspended) { |
|
| 192 | + triggerManeuverCacheInvalidationForAllCompetitors = true; |
|
| 193 | + } else { |
|
| 194 | + maneuverCache.triggerUpdate(competitor, /* updateInterval */null); |
|
| 195 | + } |
|
| 196 | + } |
|
| 197 | +} |
java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverhash/impl/ManeuverFromDatabase.java
| ... | ... | @@ -0,0 +1,60 @@ |
| 1 | +package com.sap.sailing.domain.maneuverhash.impl; |
|
| 2 | + |
|
| 3 | +import java.util.List; |
|
| 4 | +import java.util.Map; |
|
| 5 | +import java.util.logging.Level; |
|
| 6 | +import java.util.logging.Logger; |
|
| 7 | + |
|
| 8 | +import com.sap.sailing.domain.base.Competitor; |
|
| 9 | +import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprintRegistry; |
|
| 10 | +import com.sap.sailing.domain.tracking.Maneuver; |
|
| 11 | +import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl; |
|
| 12 | +import com.sap.sse.util.ManeuverCache; |
|
| 13 | +import com.sap.sse.util.SmartFutureCache.EmptyUpdateInterval; |
|
| 14 | + |
|
| 15 | +public class ManeuverFromDatabase implements ManeuverCache<Competitor, List<Maneuver>, EmptyUpdateInterval> { |
|
| 16 | + |
|
| 17 | + public ManeuverFromDatabase(boolean suspended, TrackedRaceImpl race, |
|
| 18 | + ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry) { |
|
| 19 | + super(); |
|
| 20 | + this.suspended = suspended; |
|
| 21 | + this.race = race; |
|
| 22 | + this.maneuverRaceFingerprintRegistry = maneuverRaceFingerprintRegistry; |
|
| 23 | + } |
|
| 24 | + |
|
| 25 | + boolean suspended; |
|
| 26 | + private TrackedRaceImpl race; |
|
| 27 | + private ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry; |
|
| 28 | + private static final Logger logger = Logger.getLogger(ManeuverFromDatabase.class.getName()); |
|
| 29 | + Map<Competitor, List<Maneuver>> maneuvers; |
|
| 30 | + |
|
| 31 | + public void resume() { |
|
| 32 | + logger.info("Found stored set of maneuvers for race "+race.getName()+" with matching fingerprint; loading instead of computing..."); |
|
| 33 | + updateManeuversFromRegistry(); |
|
| 34 | + suspended = false; |
|
| 35 | + } |
|
| 36 | + |
|
| 37 | + private void updateManeuversFromRegistry() { |
|
| 38 | + maneuvers = maneuverRaceFingerprintRegistry.loadManeuvers(race, race.getRace().getCourse()); |
|
| 39 | +// for (final Entry<Competitor,List<Maneuver>> e : maneuverRaceFingerprintRegistry.loadManeuvers( |
|
| 40 | +// race, race.getRace().getCourse()).entrySet()) { |
|
| 41 | +//// race.updateManeuvers(e.getKey(), e.getValue().stream().sorted(TimedComparator.INSTANCE).collect(Collectors.toList())); |
|
| 42 | +// } |
|
| 43 | + } |
|
| 44 | + |
|
| 45 | + public void suspend() { |
|
| 46 | + synchronized (this) { |
|
| 47 | + logger.finest("Suspended ManeuverFromDatabase"); |
|
| 48 | + suspended = true; |
|
| 49 | + } |
|
| 50 | + } |
|
| 51 | + |
|
| 52 | + public List<Maneuver> get(Competitor competitor, boolean waitForLatest) { |
|
| 53 | + return maneuvers.get(competitor); |
|
| 54 | + } |
|
| 55 | + |
|
| 56 | + @Override |
|
| 57 | + public void triggerUpdate(Competitor key, EmptyUpdateInterval updateInterval) { |
|
| 58 | + logger.log(Level.WARNING, "If Fingerprint matches, no Update should be triggered"); |
|
| 59 | + } |
|
| 60 | +} |
|
| ... | ... | \ No newline at end of file |
java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverhash/impl/ManeuverFromDatabaseTest.java
| ... | ... | @@ -0,0 +1,64 @@ |
| 1 | +package com.sap.sailing.domain.maneuverhash.impl; |
|
| 2 | + |
|
| 3 | +import java.util.List; |
|
| 4 | +import java.util.Map; |
|
| 5 | +import java.util.Map.Entry; |
|
| 6 | +import java.util.stream.Collectors; |
|
| 7 | + |
|
| 8 | +import com.sap.sailing.domain.base.Competitor; |
|
| 9 | +import com.sap.sailing.domain.base.Waypoint; |
|
| 10 | +import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprint; |
|
| 11 | +import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprintRegistry; |
|
| 12 | +import com.sap.sailing.domain.tracking.DynamicTrackedRace; |
|
| 13 | +import com.sap.sailing.domain.tracking.Maneuver; |
|
| 14 | +import com.sap.sailing.domain.tracking.MarkPassing; |
|
| 15 | +import com.sap.sailing.domain.tracking.impl.TimedComparator; |
|
| 16 | +import com.sap.sse.util.SmartFutureCache; |
|
| 17 | + |
|
| 18 | +public class ManeuverFromDatabaseTest extends SmartFutureCache{ |
|
| 19 | + private final DynamicTrackedRace race; |
|
| 20 | + private final ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry; |
|
| 21 | + |
|
| 22 | + public ManeuverFromDatabaseTest(CacheUpdater cacheUpdateComputer, String nameForLocks,DynamicTrackedRace race, ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry ) { |
|
| 23 | + super(cacheUpdateComputer, nameForLocks); |
|
| 24 | + this.race = race; |
|
| 25 | + this.maneuverRaceFingerprintRegistry = maneuverRaceFingerprintRegistry; |
|
| 26 | + // TODO Auto-generated constructor stub |
|
| 27 | + } |
|
| 28 | + |
|
| 29 | + |
|
| 30 | + public void resume() { |
|
| 31 | + ManeuverRaceFingerprint fingerprint; |
|
| 32 | + race.getRace().getCourse().lockForRead(); |
|
| 33 | + try { |
|
| 34 | + synchronized (this) { |
|
| 35 | + if (maneuverRaceFingerprintRegistry != null) { |
|
| 36 | + fingerprint = maneuverRaceFingerprintRegistry.getManeuverRaceFingerprint(race.getRaceIdentifier()); |
|
| 37 | + } else { |
|
| 38 | + fingerprint = null; |
|
| 39 | + } |
|
| 40 | + if (fingerprint != null && fingerprint.matches(race)) { |
|
| 41 | + |
|
| 42 | + } |
|
| 43 | + |
|
| 44 | + } |
|
| 45 | + |
|
| 46 | + } finally { |
|
| 47 | + race.getRace().getCourse().unlockAfterRead(); |
|
| 48 | + } |
|
| 49 | + } |
|
| 50 | + |
|
| 51 | + private void updateManeuversFromRegistry() { |
|
| 52 | + Map<Competitor, List<Maneuver>> maneuvers = maneuverRaceFingerprintRegistry.loadManeuvers( |
|
| 53 | + race, race.getRace().getCourse()); |
|
| 54 | + for (final Competitor e : maneuvers.keySet()) { |
|
| 55 | + List<Maneuver> competitorManeuvers = maneuvers.get(e); |
|
| 56 | + |
|
| 57 | + race.updateManeuvers(e, competitorManeuvers.stream().sorted(TimedComparator.INSTANCE).collect(Collectors.toList())); |
|
| 58 | + |
|
| 59 | + |
|
| 60 | + } |
|
| 61 | + } |
|
| 62 | + |
|
| 63 | + |
|
| 64 | +} |
java/com.sap.sailing.domain/src/com/sap/sailing/domain/maneuverhash/impl/ManeuverRaceFingerprintImpl.java
| ... | ... | @@ -2,6 +2,7 @@ package com.sap.sailing.domain.maneuverhash.impl; |
| 2 | 2 | |
| 3 | 3 | |
| 4 | 4 | import java.util.Map; |
| 5 | +import java.util.stream.Collectors; |
|
| 5 | 6 | |
| 6 | 7 | import org.json.simple.JSONObject; |
| 7 | 8 | |
| ... | ... | @@ -224,7 +225,10 @@ public class ManeuverRaceFingerprintImpl implements ManeuverRaceFingerprint { |
| 224 | 225 | int res = 0; |
| 225 | 226 | String regattaName = trackedRace.getTrackedRegatta().getRegatta().getName(); |
| 226 | 227 | Map<? extends WindSource, ? extends WindTrack> windTrack = trackedRace.getWindStore().loadWindTracks(regattaName, trackedRace, 10000); |
| 227 | - for (Map.Entry<? extends WindSource, ? extends WindTrack> w : windTrack.entrySet() ) { |
|
| 228 | + Map<WindSource, WindTrack> gefilterteMap = windTrack.entrySet() |
|
| 229 | + .stream().filter(entry -> entry.getKey().getType().isObserved()) |
|
| 230 | + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); |
|
| 231 | + for (Map.Entry<? extends WindSource, ? extends WindTrack> w : gefilterteMap.entrySet() ) { |
|
| 228 | 232 | int k = w.getKey().hashCode(); |
| 229 | 233 | int v = w.getValue().hashCode(); |
| 230 | 234 | res = res ^ k; |
java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/MarkPassingCalculator.java
| ... | ... | @@ -614,6 +614,7 @@ public class MarkPassingCalculator { |
| 614 | 614 | try { |
| 615 | 615 | latchForRunningListenRun.await(); |
| 616 | 616 | final Map<Competitor, Map<Waypoint, MarkPassing>> markPassings = race.getMarkPassings(/* waitForLatestUpdates */ true); |
| 617 | + // Bei Live-Rennen Speicherung unnötig |
|
| 617 | 618 | markPassingRaceFingerprintRegistry.storeMarkPassings(race.getRaceIdentifier(), |
| 618 | 619 | MarkPassingRaceFingerprintFactory.INSTANCE.createFingerprint(race), |
| 619 | 620 | markPassings, race.getRace().getCourse()); |
java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicTrackedRace.java
| ... | ... | @@ -131,6 +131,8 @@ public interface DynamicTrackedRace extends TrackedRace { |
| 131 | 131 | * for the finish line that are affected will be {@link #updateMarkPassings(Competitor, Iterable) updated}. |
| 132 | 132 | */ |
| 133 | 133 | void updateMarkPassingsAfterRaceLogChanges(); |
| 134 | + |
|
| 135 | + void updateManeuvers(Competitor competitor, Iterable<Maneuver> maneuvers); |
|
| 134 | 136 | |
| 135 | 137 | /** |
| 136 | 138 | * Sets the start time as received from the tracking infrastructure. This isn't necessarily |
java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/RaceTrackingHandler.java
| ... | ... | @@ -18,6 +18,7 @@ import com.sap.sailing.domain.base.impl.DynamicCompetitor; |
| 18 | 18 | import com.sap.sailing.domain.base.impl.DynamicCompetitorWithBoat; |
| 19 | 19 | import com.sap.sailing.domain.base.impl.DynamicTeam; |
| 20 | 20 | import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; |
| 21 | +import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprintRegistry; |
|
| 21 | 22 | import com.sap.sailing.domain.markpassinghash.MarkPassingRaceFingerprintRegistry; |
| 22 | 23 | import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver; |
| 23 | 24 | import com.sap.sse.common.Color; |
| ... | ... | @@ -37,7 +38,7 @@ public interface RaceTrackingHandler { |
| 37 | 38 | long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, |
| 38 | 39 | DynamicRaceDefinitionSet raceDefinitionSetToUpdate, boolean useMarkPassingCalculator, |
| 39 | 40 | RaceLogAndTrackedRaceResolver raceLogResolver, Optional<ThreadLocalTransporter> threadLocalTransporter, |
| 40 | - TrackingConnectorInfo trackingConnectorInfo, MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry); |
|
| 41 | + TrackingConnectorInfo trackingConnectorInfo, MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry, ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry); |
|
| 41 | 42 | |
| 42 | 43 | DynamicCompetitor getOrCreateCompetitor(CompetitorAndBoatStore competitorAndBoatStore, Serializable competitorId, |
| 43 | 44 | String name, String shortName, Color displayColor, String email, URI flagImageURI, DynamicTeam team, |
| ... | ... | @@ -61,10 +62,10 @@ public interface RaceTrackingHandler { |
| 61 | 62 | long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, |
| 62 | 63 | DynamicRaceDefinitionSet raceDefinitionSetToUpdate, boolean useMarkPassingCalculator, |
| 63 | 64 | RaceLogAndTrackedRaceResolver raceLogResolver, Optional<ThreadLocalTransporter> threadLocalTransporter, |
| 64 | - TrackingConnectorInfo trackingConnectorInfo, MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry) { |
|
| 65 | + TrackingConnectorInfo trackingConnectorInfo, MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry, ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry) { |
|
| 65 | 66 | return trackedRegatta.createTrackedRace(raceDefinition, sidelines, windStore, delayToLiveInMillis, |
| 66 | 67 | millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed, raceDefinitionSetToUpdate, |
| 67 | - useMarkPassingCalculator, raceLogResolver, threadLocalTransporter, trackingConnectorInfo, markPassingRaceFingerprintRegistry); |
|
| 68 | + useMarkPassingCalculator, raceLogResolver, threadLocalTransporter, trackingConnectorInfo, markPassingRaceFingerprintRegistry, maneuverRaceFingerprintRegistry); |
|
| 68 | 69 | } |
| 69 | 70 | |
| 70 | 71 | @Override |
java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRegatta.java
| ... | ... | @@ -10,6 +10,7 @@ import com.sap.sailing.domain.base.Regatta; |
| 10 | 10 | import com.sap.sailing.domain.base.Sideline; |
| 11 | 11 | import com.sap.sailing.domain.base.impl.TrackedRaces; |
| 12 | 12 | import com.sap.sailing.domain.common.NoWindException; |
| 13 | +import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprintRegistry; |
|
| 13 | 14 | import com.sap.sailing.domain.markpassinghash.MarkPassingRaceFingerprintRegistry; |
| 14 | 15 | import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver; |
| 15 | 16 | import com.sap.sse.common.TimePoint; |
| ... | ... | @@ -70,7 +71,7 @@ public interface TrackedRegatta extends Serializable, HasCPUMeter { |
| 70 | 71 | long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, |
| 71 | 72 | DynamicRaceDefinitionSet raceDefinitionSetToUpdate, boolean useInternalMarkPassingAlgorithm, RaceLogAndTrackedRaceResolver raceLogResolver, |
| 72 | 73 | Optional<ThreadLocalTransporter> beforeAndAfterNotificationHandler, TrackingConnectorInfo trackingConnectorInfo, |
| 73 | - MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry); |
|
| 74 | + MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry, ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry); |
|
| 74 | 75 | |
| 75 | 76 | /** |
| 76 | 77 | * Obtains the tracked race for <code>race</code>. Blocks until the tracked race has been created |
java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java
| ... | ... | @@ -44,6 +44,7 @@ import com.sap.sailing.domain.common.racelog.Flags; |
| 44 | 44 | import com.sap.sailing.domain.common.tracking.GPSFix; |
| 45 | 45 | import com.sap.sailing.domain.common.tracking.GPSFixMoving; |
| 46 | 46 | import com.sap.sailing.domain.common.tracking.SensorFix; |
| 47 | +import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprintRegistry; |
|
| 47 | 48 | import com.sap.sailing.domain.markpassingcalculation.MarkPassingCalculator; |
| 48 | 49 | import com.sap.sailing.domain.markpassinghash.MarkPassingRaceFingerprintRegistry; |
| 49 | 50 | import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver; |
| ... | ... | @@ -56,6 +57,7 @@ import com.sap.sailing.domain.tracking.DynamicTrackedRace; |
| 56 | 57 | import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; |
| 57 | 58 | import com.sap.sailing.domain.tracking.GPSFixTrack; |
| 58 | 59 | import com.sap.sailing.domain.tracking.GPSTrackListener; |
| 60 | +import com.sap.sailing.domain.tracking.Maneuver; |
|
| 59 | 61 | import com.sap.sailing.domain.tracking.MarkPassing; |
| 60 | 62 | import com.sap.sailing.domain.tracking.RaceAbortedListener; |
| 61 | 63 | import com.sap.sailing.domain.tracking.RaceChangeListener; |
| ... | ... | @@ -123,11 +125,11 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> { |
| 123 | 125 | long millisecondsOverWhichToAverageSpeed, long delayForCacheInvalidationOfWindEstimation, |
| 124 | 126 | boolean useInternalMarkPassingAlgorithm, RankingMetricConstructor rankingMetricConstructor, |
| 125 | 127 | RaceLogAndTrackedRaceResolver raceLogResolver, TrackingConnectorInfo trackingConnectorInfo, |
| 126 | - MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry) { |
|
| 128 | + MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry, ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry) { |
|
| 127 | 129 | super(trackedRegatta, race, sidelines, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, |
| 128 | 130 | millisecondsOverWhichToAverageSpeed, delayForCacheInvalidationOfWindEstimation, |
| 129 | 131 | useInternalMarkPassingAlgorithm, rankingMetricConstructor, raceLogResolver, trackingConnectorInfo, |
| 130 | - markPassingRaceFingerprintRegistry); |
|
| 132 | + markPassingRaceFingerprintRegistry, maneuverRaceFingerprintRegistry); |
|
| 131 | 133 | raceStateBasedStartTimeChangedListener = createRaceStateStartTimeChangeListener(); |
| 132 | 134 | this.competitorResultsFromRaceLog = new HashMap<>(); |
| 133 | 135 | this.logListener = new DynamicTrackedRaceLogListener(this); |
| ... | ... | @@ -209,11 +211,11 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> { |
| 209 | 211 | WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, |
| 210 | 212 | long millisecondsOverWhichToAverageSpeed, boolean useInternalMarkPassingAlgorithm, |
| 211 | 213 | RankingMetricConstructor rankingMetricConstructor, RaceLogAndTrackedRaceResolver raceLogResolver, TrackingConnectorInfo trackingConnectorInfo, |
| 212 | - MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry) { |
|
| 214 | + MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry, ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry) { |
|
| 213 | 215 | this(trackedRegatta, race, sidelines, windStore, delayToLiveInMillis, |
| 214 | 216 | millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed, |
| 215 | 217 | millisecondsOverWhichToAverageWind / 2, useInternalMarkPassingAlgorithm, rankingMetricConstructor, raceLogResolver, trackingConnectorInfo, |
| 216 | - markPassingRaceFingerprintRegistry); |
|
| 218 | + markPassingRaceFingerprintRegistry, maneuverRaceFingerprintRegistry); |
|
| 217 | 219 | } |
| 218 | 220 | |
| 219 | 221 | @Override |
| ... | ... | @@ -337,7 +339,7 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> { |
| 337 | 339 | } |
| 338 | 340 | } |
| 339 | 341 | updated(/* time point */null); |
| 340 | - triggerManeuverCacheRecalculationForAllCompetitors(); |
|
| 342 | + maneuverCache.triggerManeuverCacheRecalculationForAllCompetitors(); |
|
| 341 | 343 | } |
| 342 | 344 | |
| 343 | 345 | @Override |
| ... | ... | @@ -348,7 +350,7 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> { |
| 348 | 350 | getOrCreateWindTrack(windSource).setMillisecondsOverWhichToAverage(millisecondsOverWhichToAverageWind); |
| 349 | 351 | } |
| 350 | 352 | updated(/* time point */null); |
| 351 | - triggerManeuverCacheRecalculationForAllCompetitors(); |
|
| 353 | + maneuverCache.triggerManeuverCacheRecalculationForAllCompetitors(); |
|
| 352 | 354 | notifyListenersWindAveragingChanged(oldMillisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageWind); |
| 353 | 355 | } |
| 354 | 356 | |
| ... | ... | @@ -405,7 +407,7 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> { |
| 405 | 407 | final GPSFix firstFixAfter = result.getFirstFixAfter(fixTimePoint); |
| 406 | 408 | invalidateDistancesFromStarboardSideOfStartLineProjectedOntoLineCache(TimeRange.create(lastFixBefore==null?null:lastFixBefore.getTimePoint(), |
| 407 | 409 | firstFixAfter==null?null:firstFixAfter.getTimePoint())); |
| 408 | - triggerManeuverCacheRecalculationForAllCompetitors(); |
|
| 410 | + maneuverCache.triggerManeuverCacheRecalculationForAllCompetitors(); |
|
| 409 | 411 | notifyListeners(fix, mark, firstFixInTrack, addedOrReplaced); |
| 410 | 412 | } |
| 411 | 413 | |
| ... | ... | @@ -922,7 +924,7 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> { |
| 922 | 924 | getRace().getCourse().unlockAfterRead(); |
| 923 | 925 | } |
| 924 | 926 | updated(timePointOfLatestEvent); |
| 925 | - triggerManeuverCacheRecalculation(competitor); |
|
| 927 | + maneuverCache.triggerManeuverCacheRecalculation(competitor); |
|
| 926 | 928 | // update the race times like start, end and the leg times |
| 927 | 929 | if (requiresStartTimeUpdate) { |
| 928 | 930 | invalidateStartTime(); |
| ... | ... | @@ -935,6 +937,122 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> { |
| 935 | 937 | LockUtil.unlockAfterRead(getSerializationLock()); |
| 936 | 938 | } |
| 937 | 939 | } |
| 940 | + |
|
| 941 | + |
|
| 942 | + @Override |
|
| 943 | + public void updateManeuvers(Competitor competitor, Iterable<Maneuver> maneuvers) { |
|
| 944 | + final CompetitorResult resultFromRaceLog = competitorResultsFromRaceLog.get(competitor); |
|
| 945 | + updateManeuversNotConsideringFinishingTimesFromRaceLog(competitor, maneuvers); |
|
| 946 | + } |
|
| 947 | + |
|
| 948 | + |
|
| 949 | + |
|
| 950 | + |
|
| 951 | + |
|
| 952 | + |
|
| 953 | + private void updateManeuversNotConsideringFinishingTimesFromRaceLog(Competitor competitor, |
|
| 954 | + Iterable<Maneuver> maneuvers) { |
|
| 955 | +// LockUtil.lockForRead(getSerializationLock()); // keep serializer from reading the mark passings collections |
|
| 956 | +// try { |
|
| 957 | +// List<Maneuver> oldManeuvers = new ArrayList<Maneuver>(); |
|
| 958 | +//// MarkPassing oldStartMarkPassing = null; |
|
| 959 | +// boolean requiresStartTimeUpdate = true; |
|
| 960 | +// final NavigableSet<Maneuver> maneuversForCompetitor = getManeuvers(competitor); |
|
| 961 | +// lockForRead(maneuversForCompetitor); |
|
| 962 | +// try { |
|
| 963 | +// for (MarkPassing oldMarkPassing : maneuversForCompetitor) { |
|
| 964 | +// if (oldStartMarkPassing == null) { |
|
| 965 | +// oldStartMarkPassing = oldMarkPassing; |
|
| 966 | +// } |
|
| 967 | +// oldMarkPassings.put(oldMarkPassing.getWaypoint(), oldMarkPassing); |
|
| 968 | +// } |
|
| 969 | +// } finally { |
|
| 970 | +// unlockAfterRead(maneuversForCompetitor); |
|
| 971 | +// } |
|
| 972 | +// final NamedReentrantReadWriteLock markPassingsLock = getMarkPassingsLock(maneuversForCompetitor); |
|
| 973 | +// TimePoint timePointOfLatestEvent = new MillisecondsTimePoint(0); |
|
| 974 | +// // Make sure that clearMarkPassings and the re-adding of the mark passings are non-interruptible by readers. |
|
| 975 | +// // Note that the write lock for the mark passings in order per waypoint is obtained inside |
|
| 976 | +// // clearMarkPassings(...) as well as inside the subsequent for-loop. It is important to always first obtain the mark passings lock |
|
| 977 | +// // for the competitor mark passings before obtaining the lock for the mark passings in order for the waypoint to avoid |
|
| 978 | +// // deadlocks. |
|
| 979 | +// getRace().getCourse().lockForRead(); |
|
| 980 | +// LockUtil.lockForWrite(markPassingsLock); |
|
| 981 | +// try { |
|
| 982 | +// clearMarkPassings(competitor); |
|
| 983 | +// for (MarkPassing markPassing : markPassings) { |
|
| 984 | +// // Now since this caller of this update may not have held the course lock, mark passings |
|
| 985 | +// // may already be obsolete and for waypoints that no longer exist. Check: |
|
| 986 | +// if (getRace().getCourse().getIndexOfWaypoint(markPassing.getWaypoint()) >= 0) { |
|
| 987 | +// // try to find corresponding old start mark passing |
|
| 988 | +// if (oldStartMarkPassing != null |
|
| 989 | +// && markPassing.getWaypoint().equals(oldStartMarkPassing.getWaypoint())) { |
|
| 990 | +// if (markPassing.getTimePoint() != null && oldStartMarkPassing.getTimePoint() != null |
|
| 991 | +// && markPassing.getTimePoint().equals(oldStartMarkPassing.getTimePoint())) { |
|
| 992 | +// requiresStartTimeUpdate = false; |
|
| 993 | +// } |
|
| 994 | +// } |
|
| 995 | +// if (!Util.contains(getRace().getCourse().getWaypoints(), markPassing.getWaypoint())) { |
|
| 996 | +// StringBuilder courseWaypointsWithID = new StringBuilder(); |
|
| 997 | +// boolean first = true; |
|
| 998 | +// for (Waypoint courseWaypoint : getRace().getCourse().getWaypoints()) { |
|
| 999 | +// if (first) { |
|
| 1000 | +// first = false; |
|
| 1001 | +// } else { |
|
| 1002 | +// courseWaypointsWithID.append(" -> "); |
|
| 1003 | +// } |
|
| 1004 | +// courseWaypointsWithID.append(courseWaypoint.toString()); |
|
| 1005 | +// courseWaypointsWithID.append(" (ID="); |
|
| 1006 | +// courseWaypointsWithID.append(courseWaypoint.getId()); |
|
| 1007 | +// courseWaypointsWithID.append(")"); |
|
| 1008 | +// } |
|
| 1009 | +// logger.severe("Received mark passing " + markPassing + " for race " + getRace() |
|
| 1010 | +// + " for waypoint ID" + markPassing.getWaypoint().getId() |
|
| 1011 | +// + " but the waypoint does not exist in course " + courseWaypointsWithID); |
|
| 1012 | +// } else { |
|
| 1013 | +// markPassingsForCompetitor.add(markPassing); |
|
| 1014 | +// } |
|
| 1015 | +// Collection<MarkPassing> markPassingsInOrderForWaypoint = getOrCreateMarkPassingsInOrderAsNavigableSet(markPassing |
|
| 1016 | +// .getWaypoint()); |
|
| 1017 | +// final NamedReentrantReadWriteLock markPassingsLock2 = getMarkPassingsLock(markPassingsInOrderForWaypoint); |
|
| 1018 | +// LockUtil.lockForWrite(markPassingsLock2); |
|
| 1019 | +// try { |
|
| 1020 | +// // The mark passings of competitor have been removed by the call to |
|
| 1021 | +// // clearMarkPassings(competitor) above |
|
| 1022 | +// // from both, the collection that holds the mark passings by waypoint and the one that holds the |
|
| 1023 | +// // mark passings per competitor; so we can simply add here: |
|
| 1024 | +// markPassingsInOrderForWaypoint.add(markPassing); |
|
| 1025 | +// } finally { |
|
| 1026 | +// LockUtil.unlockAfterWrite(markPassingsLock2); |
|
| 1027 | +// } |
|
| 1028 | +// if (markPassing.getTimePoint().compareTo(timePointOfLatestEvent) > 0) { |
|
| 1029 | +// timePointOfLatestEvent = markPassing.getTimePoint(); |
|
| 1030 | +// } |
|
| 1031 | +// } else { |
|
| 1032 | +// logger.warning("Received mark passing "+markPassing+ |
|
| 1033 | +// " for non-existing waypoint "+markPassing.getWaypoint()+ |
|
| 1034 | +// " in race "+getRace().getName()+". Ignoring."); |
|
| 1035 | +// } |
|
| 1036 | +// } |
|
| 1037 | +// } finally { |
|
| 1038 | +// LockUtil.unlockAfterWrite(markPassingsLock); |
|
| 1039 | +// getRace().getCourse().unlockAfterRead(); |
|
| 1040 | +// } |
|
| 1041 | +// updated(timePointOfLatestEvent); |
|
| 1042 | +// triggerManeuverCacheRecalculation(competitor); |
|
| 1043 | +// // update the race times like start, end and the leg times |
|
| 1044 | +// if (requiresStartTimeUpdate) { |
|
| 1045 | +// invalidateStartTime(); |
|
| 1046 | +// } |
|
| 1047 | +// invalidateMarkPassingTimes(); |
|
| 1048 | +// invalidateEndTime(); |
|
| 1049 | +// // notify *after* all mark passings have been re-established; should avoid flicker |
|
| 1050 | +// notifyListeners(competitor, oldMarkPassings, markPassings); |
|
| 1051 | +// } finally { |
|
| 1052 | +// LockUtil.unlockAfterRead(getSerializationLock()); |
|
| 1053 | +// } |
|
| 1054 | + |
|
| 1055 | + } |
|
| 938 | 1056 | |
| 939 | 1057 | /** |
| 940 | 1058 | * The {@link CompetitorResults} from the race log as cached in {@link #competitorResultsFromRaceLog} may optionally |
| ... | ... | @@ -1095,7 +1213,7 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> { |
| 1095 | 1213 | invalidateDistancesFromStarboardSideOfStartLineProjectedOntoLineCache(TimeRange.create( |
| 1096 | 1214 | fix.getTimePoint().minus(getMillisecondsOverWhichToAverageSpeed()), |
| 1097 | 1215 | fix.getTimePoint().plus(getMillisecondsOverWhichToAverageSpeed()))); |
| 1098 | - triggerManeuverCacheRecalculation(competitor); |
|
| 1216 | + maneuverCache.triggerManeuverCacheRecalculation(competitor); |
|
| 1099 | 1217 | notifyListeners(fix, competitor, addedOrReplaced); |
| 1100 | 1218 | // getAndSet call is atomic which means, that it can be ensured that the listeners are notified only once |
| 1101 | 1219 | final boolean oldGPSFixReceived = gpsFixReceived.getAndSet(true); |
java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRegattaImpl.java
| ... | ... | @@ -1,9 +1,19 @@ |
| 1 | 1 | package com.sap.sailing.domain.tracking.impl; |
| 2 | 2 | |
| 3 | +import java.util.Optional; |
|
| 4 | + |
|
| 3 | 5 | import com.sap.sailing.domain.base.RaceDefinition; |
| 4 | 6 | import com.sap.sailing.domain.base.Regatta; |
| 7 | +import com.sap.sailing.domain.base.Sideline; |
|
| 8 | +import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprintRegistry; |
|
| 9 | +import com.sap.sailing.domain.markpassinghash.MarkPassingRaceFingerprintRegistry; |
|
| 10 | +import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver; |
|
| 11 | +import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet; |
|
| 5 | 12 | import com.sap.sailing.domain.tracking.DynamicTrackedRace; |
| 6 | 13 | import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; |
| 14 | +import com.sap.sailing.domain.tracking.TrackingConnectorInfo; |
|
| 15 | +import com.sap.sailing.domain.tracking.WindStore; |
|
| 16 | +import com.sap.sse.util.ThreadLocalTransporter; |
|
| 7 | 17 | |
| 8 | 18 | public class DynamicTrackedRegattaImpl extends TrackedRegattaImpl implements DynamicTrackedRegatta { |
| 9 | 19 | private static final long serialVersionUID = -90155868534737120L; |
| ... | ... | @@ -27,4 +37,16 @@ public class DynamicTrackedRegattaImpl extends TrackedRegattaImpl implements Dyn |
| 27 | 37 | public DynamicTrackedRace getExistingTrackedRace(RaceDefinition race) { |
| 28 | 38 | return (DynamicTrackedRace) super.getExistingTrackedRace(race); |
| 29 | 39 | } |
| 40 | + |
|
| 41 | + @Override |
|
| 42 | + public DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, Iterable<Sideline> sidelines, |
|
| 43 | + WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, |
|
| 44 | + long millisecondsOverWhichToAverageSpeed, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, |
|
| 45 | + boolean useInternalMarkPassingAlgorithm, RaceLogAndTrackedRaceResolver raceLogResolver, |
|
| 46 | + Optional<ThreadLocalTransporter> beforeAndAfterNotificationHandler, |
|
| 47 | + TrackingConnectorInfo trackingConnectorInfo, |
|
| 48 | + MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry, ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry) { |
|
| 49 | + // TODO Auto-generated method stub |
|
| 50 | + return null; |
|
| 51 | + } |
|
| 30 | 52 | } |
java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java
| ... | ... | @@ -133,6 +133,9 @@ import com.sap.sailing.domain.maneuverdetection.IncrementalManeuverDetector; |
| 133 | 133 | import com.sap.sailing.domain.maneuverdetection.ManeuverDetector; |
| 134 | 134 | import com.sap.sailing.domain.maneuverdetection.ShortTimeAfterLastHitCache; |
| 135 | 135 | import com.sap.sailing.domain.maneuverdetection.impl.IncrementalManeuverDetectorImpl; |
| 136 | +import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprintRegistry; |
|
| 137 | +import com.sap.sailing.domain.maneuverhash.impl.ManeuverCacheDelegate; |
|
| 138 | +import com.sap.sailing.domain.maneuverhash.impl.ManeuverFromDatabase; |
|
| 136 | 139 | import com.sap.sailing.domain.markpassingcalculation.MarkPassingCalculator; |
| 137 | 140 | import com.sap.sailing.domain.markpassinghash.MarkPassingRaceFingerprintRegistry; |
| 138 | 141 | import com.sap.sailing.domain.orc.ORCPerformanceCurveRankingMetric; |
| ... | ... | @@ -188,6 +191,7 @@ import com.sap.sse.concurrent.NamedReentrantReadWriteLock; |
| 188 | 191 | import com.sap.sse.shared.util.impl.ApproximateTime; |
| 189 | 192 | import com.sap.sse.shared.util.impl.ArrayListNavigableSet; |
| 190 | 193 | import com.sap.sse.util.IdentityWrapper; |
| 194 | +import com.sap.sse.util.ManeuverCache; |
|
| 191 | 195 | import com.sap.sse.util.SmartFutureCache; |
| 192 | 196 | import com.sap.sse.util.SmartFutureCache.AbstractCacheUpdater; |
| 193 | 197 | import com.sap.sse.util.SmartFutureCache.EmptyUpdateInterval; |
| ... | ... | @@ -338,7 +342,9 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl |
| 338 | 342 | * computed. Clients wanting to know maneuvers for the competitor outside of this time interval need to (re-)compute |
| 339 | 343 | * them. |
| 340 | 344 | */ |
| 341 | - private transient SmartFutureCache<Competitor, List<Maneuver>, EmptyUpdateInterval> maneuverCache; |
|
| 345 | + public transient ManeuverCacheDelegate maneuverCache; |
|
| 346 | + |
|
| 347 | + private transient ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry; |
|
| 342 | 348 | |
| 343 | 349 | /** |
| 344 | 350 | * The values of this map are used by the {@link #approximate(Competitor, Distance, TimePoint, TimePoint)} method and |
| ... | ... | @@ -494,11 +500,11 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl |
| 494 | 500 | final WindStore windStore, long delayToLiveInMillis, final long millisecondsOverWhichToAverageWind, |
| 495 | 501 | long millisecondsOverWhichToAverageSpeed, long delayForWindEstimationCacheInvalidation, |
| 496 | 502 | boolean useInternalMarkPassingAlgorithm, RaceLogAndTrackedRaceResolver raceLogResolver, TrackingConnectorInfo trackingConnectorInfo, |
| 497 | - MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry) { |
|
| 503 | + MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry, ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry) { |
|
| 498 | 504 | this(trackedRegatta, race, sidelines, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, |
| 499 | 505 | millisecondsOverWhichToAverageSpeed, delayForWindEstimationCacheInvalidation, |
| 500 | 506 | useInternalMarkPassingAlgorithm, OneDesignRankingMetric::new, raceLogResolver, trackingConnectorInfo, |
| 501 | - markPassingRaceFingerprintRegistry); |
|
| 507 | + markPassingRaceFingerprintRegistry, maneuverRaceFingerprintRegistry); |
|
| 502 | 508 | } |
| 503 | 509 | |
| 504 | 510 | /** |
| ... | ... | @@ -518,7 +524,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl |
| 518 | 524 | long millisecondsOverWhichToAverageSpeed, long delayForWindEstimationCacheInvalidation, |
| 519 | 525 | boolean useInternalMarkPassingAlgorithm, RankingMetricConstructor rankingMetricConstructor, |
| 520 | 526 | RaceLogAndTrackedRaceResolver raceLogResolver, TrackingConnectorInfo trackingConnectorInfo, |
| 521 | - MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry) { |
|
| 527 | + MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry, ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry) { |
|
| 522 | 528 | super(race, trackedRegatta, windStore, millisecondsOverWhichToAverageWind); |
| 523 | 529 | distancesFromStarboardSideOfStartLineProjectedOntoLineCache = new ConcurrentHashMap<>(); |
| 524 | 530 | distancesFromStarboardSideOfStartLineProjectedOntoLineCacheLastAccessTimes = new ConcurrentHashMap<>(); |
| ... | ... | @@ -545,7 +551,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl |
| 545 | 551 | this.delayToLiveInMillis = delayToLiveInMillis; |
| 546 | 552 | this.startToNextMarkCacheInvalidationListeners = new ConcurrentHashMap<Mark, TrackedRaceImpl.StartToNextMarkCacheInvalidationListener>(); |
| 547 | 553 | this.maneuverDetectorPerCompetitorCache = createManeuverDetectorCache(); |
| 548 | - this.maneuverCache = createManeuverCache(); |
|
| 554 | + this.maneuverCache = createManeuverCache(maneuverRaceFingerprintRegistry); |
|
| 549 | 555 | this.markTracks = new ConcurrentHashMap<Mark, GPSFixTrack<Mark, GPSFix>>(); |
| 550 | 556 | int i = 0; |
| 551 | 557 | for (Waypoint waypoint : race.getCourse().getWaypoints()) { |
| ... | ... | @@ -684,7 +690,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl |
| 684 | 690 | result = windTrack.add(wind); |
| 685 | 691 | if (result) { |
| 686 | 692 | updated(wind.getTimePoint()); |
| 687 | - triggerManeuverCacheRecalculationForAllCompetitors(); |
|
| 693 | + maneuverCache.triggerManeuverCacheRecalculationForAllCompetitors(); |
|
| 688 | 694 | } |
| 689 | 695 | } else { |
| 690 | 696 | result = false; |
| ... | ... | @@ -696,7 +702,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl |
| 696 | 702 | public void removeWind(Wind wind, WindSource windSource) { |
| 697 | 703 | getOrCreateWindTrack(windSource).remove(wind); |
| 698 | 704 | updated(/* time point */null); // wind events shouldn't advance race time |
| 699 | - triggerManeuverCacheRecalculationForAllCompetitors(); |
|
| 705 | + maneuverCache.triggerManeuverCacheRecalculationForAllCompetitors(); |
|
| 700 | 706 | } |
| 701 | 707 | |
| 702 | 708 | @Override |
| ... | ... | @@ -787,7 +793,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl |
| 787 | 793 | competitorRankingsLocks = createCompetitorRankingsLockMap(); |
| 788 | 794 | directionFromStartToNextMarkCache = new ConcurrentHashMap<>(); |
| 789 | 795 | maneuverDetectorPerCompetitorCache = createManeuverDetectorCache(); |
| 790 | - maneuverCache = createManeuverCache(); |
|
| 796 | + maneuverCache = createManeuverCache(maneuverRaceFingerprintRegistry); |
|
| 791 | 797 | logger.info("Deserialized race " + getRace().getName()); |
| 792 | 798 | } |
| 793 | 799 | |
| ... | ... | @@ -803,7 +809,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl |
| 803 | 809 | } catch (PatchFailedException e) { |
| 804 | 810 | throw new RuntimeException(e); |
| 805 | 811 | } // a bit unclean: this also tries to work on the DynamicTrackedRaceImpl which isn't fully initialized yet; see also bug6039 |
| 806 | - triggerManeuverCacheRecalculationForAllCompetitors(); // a bit unclean: this also tries to work on the DynamicTrackedRaceImpl which isn't fully initialized yet; see also bug6039 |
|
| 812 | + maneuverCache.triggerManeuverCacheRecalculationForAllCompetitors(); // a bit unclean: this also tries to work on the DynamicTrackedRaceImpl which isn't fully initialized yet; see also bug6039 |
|
| 807 | 813 | } |
| 808 | 814 | |
| 809 | 815 | /** |
| ... | ... | @@ -849,30 +855,35 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl |
| 849 | 855 | competitor -> new IncrementalManeuverDetectorImpl(TrackedRaceImpl.this, competitor, windEstimation)); |
| 850 | 856 | } |
| 851 | 857 | |
| 852 | - private SmartFutureCache<Competitor, List<Maneuver>, EmptyUpdateInterval> createManeuverCache() { |
|
| 853 | - return new SmartFutureCache<Competitor, List<Maneuver>, EmptyUpdateInterval>( |
|
| 854 | - new AbstractCacheUpdater<Competitor, List<Maneuver>, EmptyUpdateInterval>() { |
|
| 855 | - @Override |
|
| 856 | - public List<Maneuver> computeCacheUpdate(Competitor competitor, EmptyUpdateInterval updateInterval) |
|
| 857 | - throws NoWindException { |
|
| 858 | - return getTrackedRegatta().callWithCPUMeterWithException(()->{ |
|
| 859 | - Duration averageIntervalBetweenRawFixes = getTrack(competitor).getAverageIntervalBetweenRawFixes(); |
|
| 860 | - if (averageIntervalBetweenRawFixes != null) { |
|
| 861 | - ManeuverDetector maneuverDetector; |
|
| 862 | - // FIXME The LowGPSSamplingRateManeuverDetectorImpl doesn't work very well; it recognizes many tacks only as bear-away and doesn't seem to have any noticeable benefits... See ORC Worlds 2019 ORC A Long Offshore |
|
| 863 | - // if (averageIntervalBetweenRawFixes.asSeconds() >= 30) { |
|
| 864 | - // maneuverDetector = new LowGPSSamplingRateManeuverDetectorImpl(TrackedRaceImpl.this, competitor); |
|
| 865 | - // } else { |
|
| 866 | - maneuverDetector = maneuverDetectorPerCompetitorCache.getValue(competitor); |
|
| 867 | - // } |
|
| 868 | - List<Maneuver> maneuvers = computeManeuvers(competitor, maneuverDetector); |
|
| 869 | - return maneuvers; |
|
| 870 | - } else { |
|
| 871 | - return Collections.emptyList(); |
|
| 872 | - } |
|
| 873 | - }, CPUMeteringType.MANEUVER_DETECTION.name()); |
|
| 874 | - } |
|
| 875 | - }, /* nameForLocks */ "Maneuver cache for race " + getRace().getName()); |
|
| 858 | + private ManeuverCacheDelegate createManeuverCache(ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry) { |
|
| 859 | + return new ManeuverCacheDelegate(this, maneuverRaceFingerprintRegistry); |
|
| 860 | + |
|
| 861 | + |
|
| 862 | +// new ManeuverFromDatabase(false, this, maneuverRaceFingerprintRegistry), |
|
| 863 | +// new SmartFutureCache( |
|
| 864 | +// new AbstractCacheUpdater<Competitor, List<Maneuver>, EmptyUpdateInterval>() { |
|
| 865 | +// @Override |
|
| 866 | +// public List<Maneuver> computeCacheUpdate(Competitor competitor, EmptyUpdateInterval updateInterval) |
|
| 867 | +// throws NoWindException { |
|
| 868 | +// return getTrackedRegatta().callWithCPUMeterWithException(()->{ |
|
| 869 | +// Duration averageIntervalBetweenRawFixes = getTrack(competitor).getAverageIntervalBetweenRawFixes(); |
|
| 870 | +// if (averageIntervalBetweenRawFixes != null) { |
|
| 871 | +// ManeuverDetector maneuverDetector; |
|
| 872 | +// // FIXME The LowGPSSamplingRateManeuverDetectorImpl doesn't work very well; it recognizes many tacks only as bear-away and doesn't seem to have any noticeable benefits... See ORC Worlds 2019 ORC A Long Offshore |
|
| 873 | +// // if (averageIntervalBetweenRawFixes.asSeconds() >= 30) { |
|
| 874 | +// // maneuverDetector = new LowGPSSamplingRateManeuverDetectorImpl(TrackedRaceImpl.this, competitor); |
|
| 875 | +// // } else { |
|
| 876 | +// maneuverDetector = maneuverDetectorPerCompetitorCache.getValue(competitor); |
|
| 877 | +// // } |
|
| 878 | +// List<Maneuver> maneuvers = computeManeuvers(competitor, maneuverDetector); |
|
| 879 | +// return maneuvers; |
|
| 880 | +// } else { |
|
| 881 | +// return Collections.emptyList(); |
|
| 882 | +// } |
|
| 883 | +// }, CPUMeteringType.MANEUVER_DETECTION.name()); |
|
| 884 | +// } |
|
| 885 | +// }, /* nameForLocks */ "Maneuver cache for race " + getRace().getName()); |
|
| 886 | + |
|
| 876 | 887 | } |
| 877 | 888 | |
| 878 | 889 | /** |
| ... | ... | @@ -2119,7 +2130,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl |
| 2119 | 2130 | } |
| 2120 | 2131 | if (!old.equals(new HashSet<>(getWindSourcesToExclude()))) { |
| 2121 | 2132 | clearAllCachesExceptManeuvers(); |
| 2122 | - triggerManeuverCacheRecalculationForAllCompetitors(); |
|
| 2133 | + maneuverCache.triggerManeuverCacheRecalculationForAllCompetitors(); |
|
| 2123 | 2134 | } |
| 2124 | 2135 | } |
| 2125 | 2136 | |
| ... | ... | @@ -2468,7 +2479,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl |
| 2468 | 2479 | } finally { |
| 2469 | 2480 | LockUtil.unlockAfterWrite(getMarkPassingsLock(markPassingsForOneCompetitor)); |
| 2470 | 2481 | } |
| 2471 | - triggerManeuverCacheRecalculation(competitor); |
|
| 2482 | + maneuverCache.triggerManeuverCacheRecalculation(competitor); |
|
| 2472 | 2483 | } |
| 2473 | 2484 | } |
| 2474 | 2485 | logger.info("done updating tracked race "+this+"'s data structures..."); |
| ... | ... | @@ -2882,30 +2893,30 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl |
| 2882 | 2893 | return maneuverApproximators.get(competitor).approximate(from, to); |
| 2883 | 2894 | } |
| 2884 | 2895 | |
| 2885 | - protected void triggerManeuverCacheRecalculationForAllCompetitors() { |
|
| 2886 | - if (cachesSuspended) { |
|
| 2887 | - triggerManeuverCacheInvalidationForAllCompetitors = true; |
|
| 2888 | - } else { |
|
| 2889 | - final List<Competitor> shuffledCompetitors = new ArrayList<>(); |
|
| 2890 | - for (Competitor competitor : (getRace().getCompetitors())) { |
|
| 2891 | - shuffledCompetitors.add(competitor); |
|
| 2892 | - } |
|
| 2893 | - Collections.shuffle(shuffledCompetitors); |
|
| 2894 | - for (Competitor competitor : shuffledCompetitors) { |
|
| 2895 | - triggerManeuverCacheRecalculation(competitor); |
|
| 2896 | - } |
|
| 2897 | - } |
|
| 2898 | - } |
|
| 2899 | - |
|
| 2900 | - public void triggerManeuverCacheRecalculation(final Competitor competitor) { |
|
| 2901 | - if (cachesSuspended) { |
|
| 2902 | - triggerManeuverCacheInvalidationForAllCompetitors = true; |
|
| 2903 | - } else { |
|
| 2904 | - maneuverCache.triggerUpdate(competitor, /* updateInterval */null); |
|
| 2905 | - } |
|
| 2906 | - } |
|
| 2907 | - |
|
| 2908 | - private List<Maneuver> computeManeuvers(Competitor competitor, ManeuverDetector maneuverDetector) |
|
| 2896 | +// protected void triggerManeuverCacheRecalculationForAllCompetitors() { |
|
| 2897 | +// if (cachesSuspended) { |
|
| 2898 | +// triggerManeuverCacheInvalidationForAllCompetitors = true; |
|
| 2899 | +// } else { |
|
| 2900 | +// final List<Competitor> shuffledCompetitors = new ArrayList<>(); |
|
| 2901 | +// for (Competitor competitor : (getRace().getCompetitors())) { |
|
| 2902 | +// shuffledCompetitors.add(competitor); |
|
| 2903 | +// } |
|
| 2904 | +// Collections.shuffle(shuffledCompetitors); |
|
| 2905 | +// for (Competitor competitor : shuffledCompetitors) { |
|
| 2906 | +// triggerManeuverCacheRecalculation(competitor); |
|
| 2907 | +// } |
|
| 2908 | +// } |
|
| 2909 | +// } |
|
| 2910 | +// |
|
| 2911 | +// public void triggerManeuverCacheRecalculation(final Competitor competitor) { |
|
| 2912 | +// if (cachesSuspended) { |
|
| 2913 | +// triggerManeuverCacheInvalidationForAllCompetitors = true; |
|
| 2914 | +// } else { |
|
| 2915 | +// maneuverCache.triggerUpdate(competitor, /* updateInterval */null); |
|
| 2916 | +// } |
|
| 2917 | +// } |
|
| 2918 | + |
|
| 2919 | + public List<Maneuver> computeManeuvers(Competitor competitor, ManeuverDetector maneuverDetector) |
|
| 2909 | 2920 | throws NoWindException { |
| 2910 | 2921 | logger.finest("computeManeuvers(" + competitor.getName() + ") called in tracked race " + this); |
| 2911 | 2922 | long startedAt = System.currentTimeMillis(); |
| ... | ... | @@ -3135,9 +3146,11 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl |
| 3135 | 3146 | markPassingCalculator.resume(); |
| 3136 | 3147 | } |
| 3137 | 3148 | crossTrackErrorCache.resume(); |
| 3138 | - if (triggerManeuverCacheInvalidationForAllCompetitors) { |
|
| 3139 | - triggerManeuverCacheRecalculationForAllCompetitors(); |
|
| 3140 | - } |
|
| 3149 | + |
|
| 3150 | +// if (triggerManeuverCacheInvalidationForAllCompetitors) { |
|
| 3151 | +// maneuverCache.triggerManeuverCacheRecalculationForAllCompetitors(); |
|
| 3152 | +// } |
|
| 3153 | + |
|
| 3141 | 3154 | maneuverCache.resume(); |
| 3142 | 3155 | } |
| 3143 | 3156 | |
| ... | ... | @@ -4087,7 +4100,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl |
| 4087 | 4100 | // complete maneuver curves can be fed directly into the windEstimation. |
| 4088 | 4101 | maneuverDetectorPerCompetitorCache.clearCache(); |
| 4089 | 4102 | shortTimeWindCache.clearCache(); |
| 4090 | - triggerManeuverCacheRecalculationForAllCompetitors(); |
|
| 4103 | + maneuverCache.triggerManeuverCacheRecalculationForAllCompetitors(); |
|
| 4091 | 4104 | } |
| 4092 | 4105 | |
| 4093 | 4106 | /** |
| ... | ... | @@ -4431,4 +4444,9 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl |
| 4431 | 4444 | } |
| 4432 | 4445 | return result; |
| 4433 | 4446 | } |
| 4447 | + |
|
| 4448 | + public ShortTimeAfterLastHitCache<Competitor, IncrementalManeuverDetector> getManeuverDetectorPerCompetitorCache() { |
|
| 4449 | + return maneuverDetectorPerCompetitorCache; |
|
| 4450 | + |
|
| 4451 | + } |
|
| 4434 | 4452 | } |
java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRegattaImpl.java
| ... | ... | @@ -22,6 +22,7 @@ import com.sap.sailing.domain.base.RaceDefinition; |
| 22 | 22 | import com.sap.sailing.domain.base.Regatta; |
| 23 | 23 | import com.sap.sailing.domain.base.Sideline; |
| 24 | 24 | import com.sap.sailing.domain.common.NoWindException; |
| 25 | +import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprintRegistry; |
|
| 25 | 26 | import com.sap.sailing.domain.markpassinghash.MarkPassingRaceFingerprintRegistry; |
| 26 | 27 | import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver; |
| 27 | 28 | import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet; |
| ... | ... | @@ -323,13 +324,13 @@ public abstract class TrackedRegattaImpl implements TrackedRegatta { |
| 323 | 324 | long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, |
| 324 | 325 | DynamicRaceDefinitionSet raceDefinitionSetToUpdate, boolean useInternalMarkPassingAlgorithm, RaceLogAndTrackedRaceResolver raceLogResolver, |
| 325 | 326 | Optional<ThreadLocalTransporter> threadLocalTransporter, TrackingConnectorInfo trackingConnectorInfo, |
| 326 | - MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry) { |
|
| 327 | + MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry,ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry ) { |
|
| 327 | 328 | logger.log(Level.INFO, "Creating DynamicTrackedRaceImpl for RaceDefinition " + raceDefinition.getName()); |
| 328 | 329 | DynamicTrackedRaceImpl result = new DynamicTrackedRaceImpl(this, raceDefinition, sidelines, windStore, |
| 329 | 330 | delayToLiveInMillis, millisecondsOverWhichToAverageWind, |
| 330 | 331 | millisecondsOverWhichToAverageSpeed, |
| 331 | 332 | /* useMarkPassingCalculator */useInternalMarkPassingAlgorithm, getRegatta().getRankingMetricConstructor(), raceLogResolver, |
| 332 | - trackingConnectorInfo, markPassingRaceFingerprintRegistry); |
|
| 333 | + trackingConnectorInfo, markPassingRaceFingerprintRegistry, maneuverRaceFingerprintRegistry); |
|
| 333 | 334 | // adding the raceDefinition to the raceDefinitionSetToUpdate BEFORE calling addTrackedRace helps those who |
| 334 | 335 | // are called back by RaceListener.raceAdded(TrackedRace) and who then expect the update to have happened |
| 335 | 336 | if (raceDefinitionSetToUpdate != null) { |
java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java
| ... | ... | @@ -107,7 +107,7 @@ public class TestStoringAndRetrievingWindTracksTest extends AbstractTracTracLive |
| 107 | 107 | public void addRaceDefinition(RaceDefinition race, DynamicTrackedRace trackedRace) { |
| 108 | 108 | } |
| 109 | 109 | }, /*useMarkPassingCalculator*/ false, mock(RaceLogAndTrackedRaceResolver.class), |
| 110 | - Optional.empty(), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 110 | + Optional.empty(), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /*maneuverRaceFingerprintRegistry*/ null); |
|
| 111 | 111 | WindSource windSource = new WindSourceImpl(WindSourceType.WEB); |
| 112 | 112 | MongoClient myFirstMongo = newMongo(); |
| 113 | 113 | MongoDatabase firstDatabase = myFirstMongo.getDatabase(dbConfiguration.getDatabaseName()); |
java/com.sap.sailing.server.test/src/com/sap/sailing/server/statistics/StatisticsTest.java
| ... | ... | @@ -84,7 +84,7 @@ public class StatisticsTest { |
| 84 | 84 | |
| 85 | 85 | trackedRace = new DynamicTrackedRaceImpl(regatta, race, Collections.<Sideline>emptyList(), |
| 86 | 86 | EmptyWindStore.INSTANCE, 0, 0, 0, /* useMarkPassingCalculator */ false, OneDesignRankingMetric::new, |
| 87 | - mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 87 | + mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 88 | 88 | trackedRace.setStartOfTrackingReceived(new MillisecondsTimePoint(START_OF_TRACKING)); |
| 89 | 89 | trackedRace.setEndOfTrackingReceived(new MillisecondsTimePoint(END_OF_TRACKING)); |
| 90 | 90 | trackedRace.setStartTimeReceived(new MillisecondsTimePoint(START_OF_RACE)); |
java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/ApplyScoresFromRaceLogTest.java
| ... | ... | @@ -140,7 +140,7 @@ public class ApplyScoresFromRaceLogTest extends LeaderboardScoringAndRankingTest |
| 140 | 140 | /* delayToLiveInMillis */ 5000, /* millisecondsOverWhichToAverageWind */ 15000, |
| 141 | 141 | /* millisecondsOverWhichToAverageSpeed */ 10000, |
| 142 | 142 | /* useInternalMarkPassingAlgorithm */ false, OneDesignRankingMetric::new, |
| 143 | - /* raceLogResolver */ service, /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 143 | + /* raceLogResolver */ service, /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 144 | 144 | final Fleet fleet = f1Column.getFleets().iterator().next(); |
| 145 | 145 | f1Column.setTrackedRace(fleet, newF1); |
| 146 | 146 | // Now add a CompetitorResult to the race log: |
java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceTrackerStartStopTest.java
| ... | ... | @@ -90,19 +90,19 @@ public class RaceTrackerStartStopTest { |
| 90 | 90 | /* windStore */ EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 0l, |
| 91 | 91 | /* millisecondsOverWhichToAverageWind */ 0l, |
| 92 | 92 | /* millisecondsOverWhichToAverageSpeed */ 0l, /* raceDefinitionSetToUpdate */ null, /*useMarkPassingCalculator*/ false, mock(RaceLogAndTrackedRaceResolver.class), |
| 93 | - Optional.empty(), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 93 | + Optional.empty(), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 94 | 94 | regatta.addRace(raceDef2); |
| 95 | 95 | trackedRegatta1.createTrackedRace(raceDef2, Collections.<Sideline> emptyList(), |
| 96 | 96 | /* windStore */ EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 0l, |
| 97 | 97 | /* millisecondsOverWhichToAverageWind */ 0l, |
| 98 | 98 | /* millisecondsOverWhichToAverageSpeed */ 0l, /* raceDefinitionSetToUpdate */ null, /*useMarkPassingCalculator*/ false, mock(RaceLogAndTrackedRaceResolver.class), |
| 99 | - Optional.empty(), null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 99 | + Optional.empty(), null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 100 | 100 | regatta.addRace(raceDef3); |
| 101 | 101 | trackedRegatta1.createTrackedRace(raceDef3, Collections.<Sideline> emptyList(), |
| 102 | 102 | /* windStore */ EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 0l, |
| 103 | 103 | /* millisecondsOverWhichToAverageWind */ 0l, |
| 104 | 104 | /* millisecondsOverWhichToAverageSpeed */ 0l, /* raceDefinitionSetToUpdate */ null, /*useMarkPassingCalculator*/ false, mock(RaceLogAndTrackedRaceResolver.class), |
| 105 | - Optional.empty(), null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 105 | + Optional.empty(), null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 106 | 106 | Long trackerID1 = Long.valueOf(1); |
| 107 | 107 | Long trackerID2 = Long.valueOf(2); |
| 108 | 108 | Long trackerID3 = Long.valueOf(3); |
java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RemoveLeaderboardTest.java
| ... | ... | @@ -104,7 +104,7 @@ public class RemoveLeaderboardTest { |
| 104 | 104 | /* windStore */ EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 0l, |
| 105 | 105 | /* millisecondsOverWhichToAverageWind */ 0l, /* millisecondsOverWhichToAverageSpeed */ 0l, |
| 106 | 106 | /* raceDefinitionSetToUpdate */ null, /* useMarkPassingCalculator */ false, |
| 107 | - mock(RaceLogAndTrackedRaceResolver.class), Optional.empty(), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 107 | + mock(RaceLogAndTrackedRaceResolver.class), Optional.empty(), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 108 | 108 | } |
| 109 | 109 | |
| 110 | 110 | @Test |
java/com.sap.sailing.server.trackfiles.test/src/com/sap/sailing/server/trackfiles/test/JumpyTrackSmootheningTest.java
| ... | ... | @@ -317,7 +317,7 @@ public class JumpyTrackSmootheningTest { |
| 317 | 317 | final RaceDefinition race = new RaceDefinitionImpl(name, course, boatClass, competitorsAndTheirBoats, UUID.randomUUID()); |
| 318 | 318 | return new DynamicTrackedRaceImpl(trackedRegatta, race, /* sidelines */ Collections.emptySet(), new EmptyWindStore(), /* delayToLiveInMillis */ 1000, |
| 319 | 319 | WindTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_WIND, /* time over which to average speed: */ boatClass.getApproximateManeuverDurationInMilliseconds(), |
| 320 | - /* useInternalMarkPassingAlgorithm */ true, OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null); |
|
| 320 | + /* useInternalMarkPassingAlgorithm */ true, OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null, /* maneuverRaceFingerprintRegistry */ null); |
|
| 321 | 321 | } |
| 322 | 322 | |
| 323 | 323 | private Mark createAndPlaceMark(DynamicTrackedRace trackedRace, String name, String shortName, double latDeg, double lngDeg, |
java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java
| ... | ... | @@ -197,6 +197,7 @@ import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardWithOtherTieBre |
| 197 | 197 | import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; |
| 198 | 198 | import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard; |
| 199 | 199 | import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprint; |
| 200 | +import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprintRegistry; |
|
| 200 | 201 | import com.sap.sailing.domain.markpassinghash.MarkPassingRaceFingerprint; |
| 201 | 202 | import com.sap.sailing.domain.markpassinghash.MarkPassingRaceFingerprintRegistry; |
| 202 | 203 | import com.sap.sailing.domain.orc.ORCPerformanceCurveRankingMetric; |
| ... | ... | @@ -1097,11 +1098,11 @@ Replicator { |
| 1097 | 1098 | DynamicRaceDefinitionSet raceDefinitionSetToUpdate, |
| 1098 | 1099 | boolean useMarkPassingCalculator, RaceLogAndTrackedRaceResolver raceLogResolver, |
| 1099 | 1100 | Optional<ThreadLocalTransporter> threadLocalTransporter, |
| 1100 | - TrackingConnectorInfo trackingConnectorInfo, MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry) { |
|
| 1101 | + TrackingConnectorInfo trackingConnectorInfo, MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry, ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry) { |
|
| 1101 | 1102 | final DynamicTrackedRace trackedRace = super.createTrackedRace(trackedRegatta, raceDefinition, sidelines, windStore, |
| 1102 | 1103 | delayToLiveInMillis, millisecondsOverWhichToAverageWind, |
| 1103 | 1104 | millisecondsOverWhichToAverageSpeed, raceDefinitionSetToUpdate, |
| 1104 | - useMarkPassingCalculator, raceLogResolver, threadLocalTransporter, trackingConnectorInfo, markPassingRaceFingerprintRegistry); |
|
| 1105 | + useMarkPassingCalculator, raceLogResolver, threadLocalTransporter, trackingConnectorInfo, markPassingRaceFingerprintRegistry, maneuverRaceFingerprintRegistry); |
|
| 1105 | 1106 | getSecurityService().migrateOwnership(trackedRace); |
| 1106 | 1107 | trackedRace.runWhenDoneLoading( |
| 1107 | 1108 | ()->numberOfTrackedRacesRestoredDoneLoading.incrementAndGet()); |
| ... | ... | @@ -2256,7 +2257,7 @@ Replicator { |
| 2256 | 2257 | /* raceDefinitionSetToUpdate */null, useMarkPassingCalculator, /* raceLogResolver */ this, |
| 2257 | 2258 | Optional.of(this |
| 2258 | 2259 | .getThreadLocalTransporterForCurrentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster()), |
| 2259 | - trackingConnectorInfo, /* markPassingRaceFingerprintRegistry */ this); |
|
| 2260 | + trackingConnectorInfo, /* markPassingRaceFingerprintRegistry */ this, /* maneuverRaceFingerprintRegistry */ this); |
|
| 2260 | 2261 | } |
| 2261 | 2262 | |
| 2262 | 2263 | private void ensureRegattaHasRaceAdditionListener(DynamicTrackedRegatta trackedRegatta) { |
java/com.sap.sailing.server/src/com/sap/sailing/server/security/PermissionAwareRaceTrackingHandler.java
| ... | ... | @@ -25,6 +25,7 @@ import com.sap.sailing.domain.base.impl.DynamicTeam; |
| 25 | 25 | import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; |
| 26 | 26 | import com.sap.sailing.domain.common.RegattaNameAndRaceName; |
| 27 | 27 | import com.sap.sailing.domain.common.security.SecuredDomainType; |
| 28 | +import com.sap.sailing.domain.maneuverhash.ManeuverRaceFingerprintRegistry; |
|
| 28 | 29 | import com.sap.sailing.domain.markpassinghash.MarkPassingRaceFingerprintRegistry; |
| 29 | 30 | import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver; |
| 30 | 31 | import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet; |
| ... | ... | @@ -106,13 +107,13 @@ public class PermissionAwareRaceTrackingHandler extends DefaultRaceTrackingHandl |
| 106 | 107 | long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, |
| 107 | 108 | DynamicRaceDefinitionSet raceDefinitionSetToUpdate, boolean useMarkPassingCalculator, |
| 108 | 109 | RaceLogAndTrackedRaceResolver raceLogResolver, Optional<ThreadLocalTransporter> threadLocalTransporter, |
| 109 | - TrackingConnectorInfo trackingConnectorInfo, MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry) { |
|
| 110 | + TrackingConnectorInfo trackingConnectorInfo, MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry, ManeuverRaceFingerprintRegistry maneuverRaceFingerprintRegistry) { |
|
| 110 | 111 | return setOwnershipForRace( |
| 111 | 112 | new RegattaNameAndRaceName(trackedRegatta.getRegatta().getName(), raceDefinition.getName()), |
| 112 | 113 | () -> super.createTrackedRace(trackedRegatta, raceDefinition, sidelines, windStore, delayToLiveInMillis, |
| 113 | 114 | millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed, |
| 114 | 115 | raceDefinitionSetToUpdate, useMarkPassingCalculator, raceLogResolver, threadLocalTransporter, |
| 115 | - trackingConnectorInfo, markPassingRaceFingerprintRegistry)); |
|
| 116 | + trackingConnectorInfo, markPassingRaceFingerprintRegistry,maneuverRaceFingerprintRegistry)); |
|
| 116 | 117 | } |
| 117 | 118 | |
| 118 | 119 | @Override |
java/com.sap.sse/src/com/sap/sse/util/ManeuverCache.java
| ... | ... | @@ -0,0 +1,15 @@ |
| 1 | +package com.sap.sse.util; |
|
| 2 | + |
|
| 3 | + |
|
| 4 | +import com.sap.sse.util.SmartFutureCache.UpdateInterval; |
|
| 5 | + |
|
| 6 | +public interface ManeuverCache<K, V, U extends UpdateInterval<U>>{ |
|
| 7 | + |
|
| 8 | + void resume(); |
|
| 9 | + |
|
| 10 | + V get(K key, boolean waitForLatest); |
|
| 11 | + |
|
| 12 | + void suspend(); |
|
| 13 | + |
|
| 14 | + void triggerUpdate(K key, U updateInterval); |
|
| 15 | +} |
|
| ... | ... | \ No newline at end of file |
java/com.sap.sse/src/com/sap/sse/util/SmartFutureCache.java
| ... | ... | @@ -77,7 +77,7 @@ import com.sap.sse.util.impl.KnowsExecutorAndTracingGetImpl; |
| 77 | 77 | * @author Axel Uhl (D043530) |
| 78 | 78 | * |
| 79 | 79 | */ |
| 80 | -public class SmartFutureCache<K, V, U extends UpdateInterval<U>> { |
|
| 80 | +public class SmartFutureCache<K, V, U extends UpdateInterval<U>> implements ManeuverCache<K, V, U> { |
|
| 81 | 81 | private static final Logger logger = Logger.getLogger(SmartFutureCache.class.getName()); |
| 82 | 82 | |
| 83 | 83 | /** |
| ... | ... | @@ -413,6 +413,7 @@ public class SmartFutureCache<K, V, U extends UpdateInterval<U>> { |
| 413 | 413 | } |
| 414 | 414 | } |
| 415 | 415 | |
| 416 | + @Override |
|
| 416 | 417 | public void suspend() { |
| 417 | 418 | logger.finest("suspending cache "+nameForLocks); |
| 418 | 419 | synchronized (ongoingRecalculations) { |
| ... | ... | @@ -420,6 +421,7 @@ public class SmartFutureCache<K, V, U extends UpdateInterval<U>> { |
| 420 | 421 | } |
| 421 | 422 | } |
| 422 | 423 | |
| 424 | + @Override |
|
| 423 | 425 | public void resume() { |
| 424 | 426 | synchronized (ongoingRecalculations) { |
| 425 | 427 | suspended = false; |
| ... | ... | @@ -457,6 +459,7 @@ public class SmartFutureCache<K, V, U extends UpdateInterval<U>> { |
| 457 | 459 | * If the running task has a different setting for the caller's waiting for the task, the task will be canceled |
| 458 | 460 | * (which may or may not work), and a new task with the joined update interval is scheduled. |
| 459 | 461 | */ |
| 462 | + @Override |
|
| 460 | 463 | public void triggerUpdate(final K key, U updateInterval) { |
| 461 | 464 | // establish and maintain the following invariant: after lock on ongoingRecalculations is released, |
| 462 | 465 | // no Future contained in it is in cancelled state |
| ... | ... | @@ -672,6 +675,7 @@ public class SmartFutureCache<K, V, U extends UpdateInterval<U>> { |
| 672 | 675 | * ongoing, the result of that ongoing re-calculation is returned. When {@link #remove(Object)} has been called for the {@code key} and |
| 673 | 676 | * no update has finished computing since then, this method will also return {@code null} in case {@code waitForLatest} is {@code false}. |
| 674 | 677 | */ |
| 678 | + @Override |
|
| 675 | 679 | public V get(final K key, boolean waitForLatest) { |
| 676 | 680 | final V value; |
| 677 | 681 | final Future<V> future; |