From 86ff9e2c2666b4548ac265511af42ea51cd38415 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 7 Jun 2013 23:22:56 +0200 Subject: [PATCH] extract start time dynamically from attached race logs instead of updating startTimeReceived from race log events --- .../domain/test/mock/MockedTrackedRace.java | 12 ++++ .../domain/tracking/DynamicTrackedRace.java | 4 ++ .../sailing/domain/tracking/TrackedRace.java | 10 +-- .../impl/DynamicTrackedRaceLogListener.java | 23 +------ .../domain/tracking/impl/TrackedRaceImpl.java | 66 +++++++++++-------- .../gwt/ui/test/MockedTrackedRace.java | 12 ++++ 6 files changed, 76 insertions(+), 51 deletions(-) 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>>(); cacheInvalidationTimerLock = new Object(); windStore = EmptyWindStore.INSTANCE; @@ -452,11 +455,11 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { return endOfTrackingReceived; } - protected void invalidateStartTime() { + public void invalidateStartTime() { startTime = null; } - protected void invalidateEndTime() { + public void invalidateEndTime() { endTime = null; } @@ -467,35 +470,46 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { } /** - * Calculates the start time of the race from various sources + * Calculates the start time of the race from various sources. The highest precedence take the {@link #attachedRaceLogs race logs}, + * followed by the field {@link #startTimeReceived} which can explicitly be set using {@link #setStartTimeReceived(TimePoint)}. + * If that does not provide any start time either, a start time is attempted to be inferred from the time points + * of the start mark passing events. */ @Override public TimePoint getStartOfRace() { if (startTime == null) { - startTime = startTimeReceived; - // If not null, check if the first mark passing for the start line is too much after the startTimeReceived; - // if so, return an adjusted, later start time. - // If no official start time was received, try to estimate the start time using the mark passings for the - // start line. - final Waypoint firstWaypoint = getRace().getCourse().getFirstWaypoint(); - if (firstWaypoint != null) { - if (startTimeReceived != null) { - TimePoint timeOfFirstMarkPassing = getFirstPassingTime(firstWaypoint); - if (timeOfFirstMarkPassing != null) { - long startTimeReceived2timeOfFirstMarkPassingFirstMark = timeOfFirstMarkPassing.asMillis() - - startTimeReceived.asMillis(); - if (startTimeReceived2timeOfFirstMarkPassingFirstMark > MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS) { - startTime = new MillisecondsTimePoint(timeOfFirstMarkPassing.asMillis() - - MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS); - } else { - startTime = startTimeReceived; + for (RaceLog raceLog : attachedRaceLogs.values()) { + startTime = new StartTimeFinder(raceLog).getStartTime(); + if (startTime != null) { + break; + } + } + if (startTime == null) { + startTime = startTimeReceived; + // If not null, check if the first mark passing for the start line is too much after the + // startTimeReceived; if so, return an adjusted, later start time. + // If no official start time was received, try to estimate the start time using the mark passings for + // the start line. + final Waypoint firstWaypoint = getRace().getCourse().getFirstWaypoint(); + if (firstWaypoint != null) { + if (startTimeReceived != null) { + TimePoint timeOfFirstMarkPassing = getFirstPassingTime(firstWaypoint); + if (timeOfFirstMarkPassing != null) { + long startTimeReceived2timeOfFirstMarkPassingFirstMark = timeOfFirstMarkPassing.asMillis() + - startTimeReceived.asMillis(); + if (startTimeReceived2timeOfFirstMarkPassingFirstMark > MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS) { + startTime = new MillisecondsTimePoint(timeOfFirstMarkPassing.asMillis() + - MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS); + } else { + startTime = startTimeReceived; + } + } + } else { + final NavigableSet markPassingsForFirstWaypointInOrder = getMarkPassingsInOrderAsNavigableSet(firstWaypoint); + if (markPassingsForFirstWaypointInOrder != null) { + startTime = calculateStartOfRaceFromMarkPassings(markPassingsForFirstWaypointInOrder, + getRace().getCompetitors()); } - } - } else { - final NavigableSet markPassingsForFirstWaypointInOrder = getMarkPassingsInOrderAsNavigableSet(firstWaypoint); - if (markPassingsForFirstWaypointInOrder != null) { - startTime = calculateStartOfRaceFromMarkPassings(markPassingsForFirstWaypointInOrder, getRace() - .getCompetitors()); } } } diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java index 6aff8583e1a..0297d62bc68 100644 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java @@ -789,4 +789,16 @@ public class MockedTrackedRace implements DynamicTrackedRace { } + @Override + public void invalidateStartTime() { + // TODO Auto-generated method stub + + } + + @Override + public void invalidateEndTime() { + // TODO Auto-generated method stub + + } + }