java/com.sap.sailing.server.trackfiles.test/src/com/sap/sailing/server/trackfiles/test/DynamicTrackedRaceWithMarkPassingCalculator.java
... ...
@@ -0,0 +1,28 @@
1
+package com.sap.sailing.server.trackfiles.test;
2
+
3
+import com.sap.sailing.domain.base.RaceDefinition;
4
+import com.sap.sailing.domain.base.Sideline;
5
+import com.sap.sailing.domain.markpassingcalculation.MarkPassingCalculator;
6
+import com.sap.sailing.domain.markpassinghash.MarkPassingRaceFingerprintRegistry;
7
+import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver;
8
+import com.sap.sailing.domain.ranking.RankingMetricConstructor;
9
+import com.sap.sailing.domain.shared.tracking.TrackingConnectorInfo;
10
+import com.sap.sailing.domain.tracking.TrackedRegatta;
11
+import com.sap.sailing.domain.tracking.WindStore;
12
+import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
13
+
14
+public class DynamicTrackedRaceWithMarkPassingCalculator extends DynamicTrackedRaceImpl {
15
+ private static final long serialVersionUID = -8076705893930566222L;
16
+
17
+ public DynamicTrackedRaceWithMarkPassingCalculator(TrackedRegatta trackedRegatta, RaceDefinition race, Iterable<Sideline> sidelines,
18
+ WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind,
19
+ long millisecondsOverWhichToAverageSpeed, boolean useInternalMarkPassingAlgorithm,
20
+ RankingMetricConstructor rankingMetricConstructor, RaceLogAndTrackedRaceResolver raceLogResolver, TrackingConnectorInfo trackingConnectorInfo,
21
+ MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry) {
22
+ super(trackedRegatta, race, sidelines, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed, useInternalMarkPassingAlgorithm, rankingMetricConstructor, raceLogResolver, trackingConnectorInfo, markPassingRaceFingerprintRegistry);
23
+ }
24
+
25
+ public MarkPassingCalculator getMarkPassingCalculator() {
26
+ return markPassingCalculator;
27
+ }
28
+}
java/com.sap.sailing.server.trackfiles.test/src/com/sap/sailing/server/trackfiles/test/JumpyTrackSmootheningTest.java
... ...
@@ -68,7 +68,6 @@ import com.sap.sailing.domain.tracking.MarkPassing;
68 68
import com.sap.sailing.domain.tracking.TrackedRegatta;
69 69
import com.sap.sailing.domain.tracking.WindTrack;
70 70
import com.sap.sailing.domain.tracking.impl.DynamicGPSFixMovingTrackImpl;
71
-import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
72 71
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl;
73 72
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
74 73
import com.sap.sailing.domain.tracking.impl.OutlierFilter;
... ...
@@ -197,7 +196,7 @@ public class JumpyTrackSmootheningTest {
197 196
durationForOriginalTrack = startedAt.until(doneAt);
198 197
logger.info("Duration for computing mark passings with original track: "+durationForOriginalTrack);
199 198
assertNotNull(markPassings);
200
- assertEquals(13, markPassings.size());
199
+ assertEquals(5, markPassings.size()); // there are fewer mark passings with the spikes still included
201 200
}
202 201
assertTrue(durationForAdjustedTrack.times(2).compareTo(durationForOriginalTrack) < 0,
203 202
"Expected duration for mark passing analysis on adjusted track to be at least two times less than for original track: "+
... ...
@@ -238,9 +237,9 @@ public class JumpyTrackSmootheningTest {
238 237
* its calculation. As a result, a test may determine the impact filtering / adjusting the track may have on the
239 238
* mark passing analysis.
240 239
*/
241
- private DynamicTrackedRace createRace(DynamicGPSFixTrack<Competitor, GPSFixMoving> competitorTrack) throws PatchFailedException, ParseException {
240
+ private DynamicTrackedRace createRace(DynamicGPSFixTrack<Competitor, GPSFixMoving> competitorTrack) throws PatchFailedException, ParseException, InterruptedException {
242 241
final Competitor gallagherZelenka = competitorTrack.getTrackedItem();
243
- final DynamicTrackedRace trackedRace = createTrackedRace("Oak cliff DH Distance Race", "R1", BoatClassMasterdata.MELGES_24, gallagherZelenka);
242
+ final DynamicTrackedRaceWithMarkPassingCalculator trackedRace = createTrackedRace("Oak cliff DH Distance Race", "R1", BoatClassMasterdata.MELGES_24, gallagherZelenka);
244 243
final Series defaultSeries = trackedRace.getTrackedRegatta().getRegatta().getSeries().iterator().next();
245 244
final Fleet defaultFleet = defaultSeries.getFleets().iterator().next();
246 245
final RaceColumnInSeries r1RaceColumn = defaultSeries.getRaceColumns().iterator().next();
... ...
@@ -300,15 +299,11 @@ public class JumpyTrackSmootheningTest {
300 299
competitorTrack.unlockAfterRead();
301 300
}
302 301
trackedRace.setStatus(new TrackedRaceStatusImpl(TrackedRaceStatusEnum.TRACKING, 1.0)); // resumes mark passing calculator
303
- // FIXME is it possible that MarkPassingCalculator.Listen has applied only a subset of the changes from its queue when this method returns?
304
- // It scoops up a few events from the queue under the MPC write lock and collects the changes in various collections, but doesn't re-calculate while suspended;
305
- // When the lock is released prior to fetching the next set of events from the queue, the test case calling this method may call getMarkPassings(..., true)
306
- // and obtain the read lock, keeping the Listen thread from applying the next round of updates. Yes, the getMarkPassings(...) call may return something,
307
- // but that may be the result of only applying a subset of the changes, with other changes still in the queue...
302
+ trackedRace.getMarkPassingCalculator().waitUntilStopped(/* timeout in millis */ Duration.ONE_MINUTE.times(15).asMillis());
308 303
return trackedRace;
309 304
}
310 305
311
- private DynamicTrackedRace createTrackedRace(String regattaName, String name, BoatClassMasterdata boatClassMasterData, Competitor gallagherZelenka) {
306
+ private DynamicTrackedRaceWithMarkPassingCalculator createTrackedRace(String regattaName, String name, BoatClassMasterdata boatClassMasterData, Competitor gallagherZelenka) {
312 307
final BoatClassImpl boatClass = new BoatClassImpl(boatClassMasterData);
313 308
final TrackedRegatta trackedRegatta = new DynamicTrackedRegattaImpl(new RegattaImpl(regattaName, boatClass,
314 309
/* canBoatsOfCompetitorsChangePerRace */ false, /* competitorRegistrationType */ CompetitorRegistrationType.CLOSED,
... ...
@@ -320,7 +315,7 @@ public class JumpyTrackSmootheningTest {
320 315
final Map<Competitor, Boat> competitorsAndTheirBoats = Util.<Competitor, Boat>mapBuilder().put(gallagherZelenka, boat).build();
321 316
final Course course = new CourseImpl("R1 Course", Collections.emptySet());
322 317
final RaceDefinition race = new RaceDefinitionImpl(name, course, boatClass, competitorsAndTheirBoats, UUID.randomUUID());
323
- return new DynamicTrackedRaceImpl(trackedRegatta, race, /* sidelines */ Collections.emptySet(), new EmptyWindStore(), /* delayToLiveInMillis */ 1000,
318
+ return new DynamicTrackedRaceWithMarkPassingCalculator(trackedRegatta, race, /* sidelines */ Collections.emptySet(), new EmptyWindStore(), /* delayToLiveInMillis */ 1000,
324 319
WindTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_WIND, /* time over which to average speed: */ boatClass.getApproximateManeuverDurationInMilliseconds(),
325 320
/* useInternalMarkPassingAlgorithm */ true, OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null);
326 321
}