diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java
index c3a8cc858dc..77fad2de45a 100755
--- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java
+++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java
@@ -787,4 +787,16 @@ public class MockedTrackedRace implements DynamicTrackedRace {
// TODO Auto-generated method stub
}
+
+ @Override
+ public void invalidateStartTime() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void invalidateEndTime() {
+ // TODO Auto-generated method stub
+
+ }
}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicTrackedRace.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicTrackedRace.java
index f74c4fb9006..071c61008f1 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicTrackedRace.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DynamicTrackedRace.java
@@ -88,4 +88,8 @@ public interface DynamicTrackedRace extends TrackedRace {
* the new course design to be published
*/
void onCourseDesignChangedByRaceCommittee(CourseBase courseDesign);
+
+ void invalidateStartTime();
+
+ void invalidateEndTime();
}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java
index caeef494255..82f3f893b03 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java
@@ -51,10 +51,12 @@ public interface TrackedRace extends Serializable {
/**
* Computes the estimated start time for this race (not to be confused with the {@link #getStartOfTracking()} time
- * point which is expected to be before the race start time). When there are no {@link MarkPassing}s for the first
- * mark, null is returned. If there are mark passings for the first mark and the start time is less
- * than {@link #MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS} before the first mark passing for the
- * first mark. Otherwise, the first mark passing for the first mark minus
+ * point which is expected to be before the race start time). The highest precedence take the
+ * {@link #attachedRaceLogs race logs} and their start time events, followed by the field {@link #startTimeReceived}
+ * which can explicitly be set using {@link #setStartTimeReceived(TimePoint)}. When there are no {@link MarkPassing}s
+ * for the first mark, null is returned. If there are mark passings for the first mark and the start
+ * time is less than {@link #MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS} before the first mark
+ * passing for the first mark. Otherwise, the first mark passing for the first mark minus
* {@link #MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS} is returned as the race start time.
*
*
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceLogListener.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceLogListener.java
index 2676d8a4570..2b09dd2031d 100644
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceLogListener.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceLogListener.java
@@ -1,7 +1,6 @@
package com.sap.sailing.domain.tracking.impl;
import com.sap.sailing.domain.base.CourseBase;
-import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogCourseAreaChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogCourseDesignChangedEvent;
@@ -17,15 +16,12 @@ import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent;
import com.sap.sailing.domain.racelog.analyzing.impl.LastPublishedCourseDesignFinder;
import com.sap.sailing.domain.racelog.analyzing.impl.RaceStatusAnalyzer;
-import com.sap.sailing.domain.racelog.analyzing.impl.StartTimeFinder;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
public class DynamicTrackedRaceLogListener implements RaceLogEventVisitor {
private DynamicTrackedRace trackedRace;
- private StartTimeFinder startTimeFinder;
-
private RaceStatusAnalyzer statusAnalyzer;
private LastPublishedCourseDesignFinder courseDesignFinder;
@@ -36,7 +32,8 @@ public class DynamicTrackedRaceLogListener implements RaceLogEventVisitor {
public void addTo(RaceLog raceLog) {
raceLog.addListener(this);
- startTimeFinder = new StartTimeFinder(raceLog);
+ trackedRace.invalidateStartTime();
+ trackedRace.invalidateEndTime();
courseDesignFinder = new LastPublishedCourseDesignFinder(raceLog);
statusAnalyzer = new RaceStatusAnalyzer(raceLog);
analyze();
@@ -55,24 +52,10 @@ public class DynamicTrackedRaceLogListener implements RaceLogEventVisitor {
}
private void analyze() {
- analyzeStartTime();
analyzeStatus();
analyzeCourseDesign();
}
- private void analyzeStartTime() {
- TimePoint startTime = startTimeFinder.getStartTime();
-
- // Because this code can be triggered by an obsolete (delayed) event or on an empty pass...
- // ... the current pass's start time might be null
- if (startTime != null) {
- // ... or setStartTimeReceived(TimePoint) might be called more than once with the same start time.
- trackedRace.setStartTimeReceived(startTime);
- } else {
- // TODO: Can we somehow withdraw a previously set start time?
- }
- }
-
private void analyzeStatus() {
/* RaceLogRaceStatus newStatus = */statusAnalyzer.getStatus();
@@ -92,13 +75,11 @@ public class DynamicTrackedRaceLogListener implements RaceLogEventVisitor {
@Override
public void visit(RaceLogPassChangeEvent event) {
- analyzeStartTime();
analyzeStatus();
}
@Override
public void visit(RaceLogStartTimeEvent event) {
- analyzeStartTime();
analyzeStatus();
}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java
index cffccdc17b2..410f9a3fd67 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java
@@ -72,6 +72,7 @@ import com.sap.sailing.domain.confidence.Weigher;
import com.sap.sailing.domain.confidence.impl.HyperbolicTimeDifferenceWeigher;
import com.sap.sailing.domain.confidence.impl.PositionAndTimePointWeigher;
import com.sap.sailing.domain.racelog.RaceLog;
+import com.sap.sailing.domain.racelog.analyzing.impl.StartTimeFinder;
import com.sap.sailing.domain.tracking.GPSFix;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.GPSFixTrack;
@@ -257,6 +258,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
long millisecondsOverWhichToAverageSpeed, long delayForWindEstimationCacheInvalidation) {
super();
locksForMarkPassings = new IdentityHashMap<>();
+ attachedRaceLogs = new HashMap<>();
this.status = new TrackedRaceStatusImpl(TrackedRaceStatusEnum.PREPARED, 0.0);
this.statusNotifier = new Object[0];
this.serializationLock = new NamedReentrantReadWriteLock("Serialization lock for tracked race "
@@ -366,6 +368,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
*/
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
+ attachedRaceLogs = new HashMap<>();
markPassingsTimes = new ArrayList