diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java index 3cd5b837ca6..f6e7ef2b115 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java @@ -70,7 +70,7 @@ public class LeaderboardCacheManager { } @Override - public void markPositionChanged(GPSFix fix, Mark mark) { + public void markPositionChanged(GPSFix fix, Mark mark, boolean firstInTrack) { removeFromCache(leaderboard); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java index b16aa9d93d8..18206de4caa 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java @@ -312,7 +312,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race } @Override - public void markPositionChanged(GPSFix fix, Mark mark) { + public void markPositionChanged(GPSFix fix, Mark mark, boolean firstInTrack) { invalidateCacheAndRemoveThisListenerFromTrackedRace(); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/MarkPassingUpdateListener.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/MarkPassingUpdateListener.java index 86d441482f8..c1636f24013 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/MarkPassingUpdateListener.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/MarkPassingUpdateListener.java @@ -40,7 +40,7 @@ public class MarkPassingUpdateListener extends AbstractRaceChangeListener { } @Override - public void markPositionChanged(GPSFix fix, Mark mark) { + public void markPositionChanged(GPSFix fix, Mark mark, boolean firstInTrack) { queue.add(new Util.Pair(mark, fix)); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/GPSTrackListener.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/GPSTrackListener.java index dd0671903b2..1aaa7c23943 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/GPSTrackListener.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/GPSTrackListener.java @@ -3,7 +3,7 @@ package com.sap.sailing.domain.tracking; import java.io.Serializable; public interface GPSTrackListener extends Serializable { - void gpsFixReceived(FixType fix, ItemType item); + void gpsFixReceived(FixType fix, ItemType item, boolean firstFixInTrack); void speedAveragingChanged(long oldMillisecondsOverWhichToAverage, long newMillisecondsOverWhichToAverage); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/RaceChangeListener.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/RaceChangeListener.java index 09ecba9616c..5fe31595664 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/RaceChangeListener.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/RaceChangeListener.java @@ -13,7 +13,7 @@ import com.sap.sailing.domain.common.WindSource; public interface RaceChangeListener extends CourseListener { void competitorPositionChanged(GPSFixMoving fix, Competitor competitor); - void markPositionChanged(GPSFix fix, Mark mark); + void markPositionChanged(GPSFix fix, Mark mark, boolean firstInTrack); /** * Invoked after the mark passings have been updated in the {@link TrackedRace}. diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractRaceChangeListener.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractRaceChangeListener.java index 433b5488217..cb76097f12b 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractRaceChangeListener.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractRaceChangeListener.java @@ -33,7 +33,7 @@ public abstract class AbstractRaceChangeListener implements RaceChangeListener { } @Override - public void markPositionChanged(GPSFix fix, Mark mark) { + public void markPositionChanged(GPSFix fix, Mark mark, boolean firstInTrack) { } @Override diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CrossTrackErrorCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CrossTrackErrorCache.java index 20c12f64114..f56a09c6b79 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CrossTrackErrorCache.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CrossTrackErrorCache.java @@ -397,7 +397,7 @@ public class CrossTrackErrorCache extends AbstractRaceChangeListener { } @Override - public void markPositionChanged(GPSFix fix, Mark mark) { + public void markPositionChanged(GPSFix fix, Mark mark, boolean firstInTrack) { TimePoint from = owner.getOrCreateTrack(mark).getEstimatedPositionTimePeriodAffectedBy(fix).getA(); final List shuffledCompetitors = new ArrayList<>(cachePerCompetitor.keySet()); Collections.shuffle(shuffledCompetitors); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java index 5752ab13fae..c8511c9cc7a 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java @@ -212,20 +212,20 @@ DynamicTrackedRace, GPSTrackListener { /** * In addition to creating the track which is performed by the superclass implementation, this implementation registers - * a {@link GPSTrackListener} with the mark's track and {@link #notifyListeners(GPSFix, Mark) notifies the listeners} + * a {@link GPSTrackListener} with the mark's track and {@link #notifyListeners(GPSFix, Mark, boolean) notifies the listeners} * about updates. The {@link #updated(TimePoint)} method is not called with the mark fix's time point because * mark fixes may be received also from marks that don't belong to this race. */ @Override protected DynamicGPSFixTrackImpl createMarkTrack(Mark mark) { - DynamicGPSFixTrackImpl result = super.createMarkTrack(mark); + final DynamicGPSFixTrackImpl result = super.createMarkTrack(mark); result.addListener(new GPSTrackListener() { private static final long serialVersionUID = -2855787105725103732L; @Override - public void gpsFixReceived(GPSFix fix, Mark mark) { + public void gpsFixReceived(GPSFix fix, Mark mark, boolean firstFixInTrack) { triggerManeuverCacheRecalculationForAllCompetitors(); - notifyListeners(fix, mark); + notifyListeners(fix, mark, firstFixInTrack); } @Override @@ -306,8 +306,10 @@ DynamicTrackedRace, GPSTrackListener { GPSFixTrack markTrack = getOrCreateTrack(mark); markTrack.lockForRead(); try { + boolean firstInTrack = true; for (GPSFix fix : markTrack.getRawFixes()) { - listener.markPositionChanged(fix, mark); + listener.markPositionChanged(fix, mark, firstInTrack); + firstInTrack = false; } } finally { markTrack.unlockAfterRead(); @@ -437,14 +439,14 @@ DynamicTrackedRace, GPSTrackListener { notifyListenersWaypointRemoved(zeroBasedIndex, waypointThatGotRemoved); } - private void notifyListeners(GPSFix fix, Mark mark) { + private void notifyListeners(GPSFix fix, Mark mark, boolean firstInTrack) { RaceChangeListener[] listeners; synchronized (getListeners()) { listeners = getListeners().toArray(new RaceChangeListener[getListeners().size()]); } for (RaceChangeListener listener : listeners) { try { - listener.markPositionChanged(fix, mark); + listener.markPositionChanged(fix, mark, firstInTrack); } catch (Exception e) { logger.log(Level.SEVERE, "RaceChangeListener " + listener + " threw exception " + e.getMessage()); logger.log(Level.SEVERE, "notifyListeners(GPSFix, Competitor)", e); @@ -800,7 +802,7 @@ DynamicTrackedRace, GPSTrackListener { } @Override - public void gpsFixReceived(GPSFixMoving fix, Competitor competitor) { + public void gpsFixReceived(GPSFixMoving fix, Competitor competitor, boolean firstFixInTrack) { updated(fix.getTimePoint()); triggerManeuverCacheRecalculation(competitor); notifyListeners(fix, competitor); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java index 4745c89906a..dfee0e5a6e6 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java @@ -1009,8 +1009,10 @@ public class GPSFixTrackImpl extends TrackImpl @Override protected boolean add(FixType fix) { final boolean result; + final boolean firstFixInTrack; lockForWrite(); try { + firstFixInTrack = getRawFixes().isEmpty(); result = addWithoutLocking(fix); invalidateValidityAndDistanceCaches(fix); } finally { @@ -1034,7 +1036,7 @@ public class GPSFixTrackImpl extends TrackImpl } } for (GPSTrackListener listener : getListeners()) { - listener.gpsFixReceived(fix, getTrackedItem()); + listener.gpsFixReceived(fix, getTrackedItem(), firstFixInTrack); } return result; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/MaxSpeedCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/MaxSpeedCache.java index 25faf6bb51e..48cdcacc693 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/MaxSpeedCache.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/MaxSpeedCache.java @@ -79,7 +79,7 @@ public class MaxSpeedCache implements GPSTrack * outside of the invalidation interval, crop cache entry's interval such that it's overlap-free, otherwise remove. */ @Override - public void gpsFixReceived(FixType fix, ItemType item) { + public void gpsFixReceived(FixType fix, ItemType item, boolean firstFixInTrack) { // find the invalidation interval such that getFixesRelevantForSpeedEstimation, when passed any time point from that interval, produces "fix" Util.Pair invalidationInterval = track.getTimeIntervalWhoseEstimatedSpeedMayHaveChangedAfterAddingFix(fix); LockUtil.lockForWrite(lock); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackBasedEstimationWindTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackBasedEstimationWindTrackImpl.java index e23f82ee947..c2f4f47f4e8 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackBasedEstimationWindTrackImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackBasedEstimationWindTrackImpl.java @@ -693,7 +693,7 @@ public class TrackBasedEstimationWindTrackImpl extends VirtualWindTrackImpl impl } @Override - public void markPositionChanged(GPSFix fix, Mark mark) { + public void markPositionChanged(GPSFix fix, Mark mark, boolean firstInTrack) { assert fix != null && fix.getTimePoint() != null; // A mark position change can mean a leg type change. The interval over which the wind estimation is affected // depends on how the GPS track computes the estimated mark position. Ask it: diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java index 57ef50b7f71..8c96a34843f 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java @@ -285,7 +285,7 @@ public class TrackedLegImpl implements TrackedLeg, RaceChangeListener { } @Override - public void markPositionChanged(GPSFix fix, Mark mark) { + public void markPositionChanged(GPSFix fix, Mark mark, boolean firstInTrack) { clearCaches(); } 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 88412e6958e..549a4e1d88c 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 @@ -2487,7 +2487,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl } @Override - public void gpsFixReceived(GPSFix fix, Mark mark) { + public void gpsFixReceived(GPSFix fix, Mark mark, boolean firstFixInTrack) { clearDirectionFromStartToNextMarkCache(); } diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy).launch b/java/com.sap.sailing.server/SailingServer (No Proxy).launch index c132dcbaaf8..95e2b7af28e 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy).launch @@ -19,7 +19,7 @@ - + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch index 13b887d9041..a3cf7523b4d 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch @@ -18,7 +18,7 @@ - + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy).launch b/java/com.sap.sailing.server/SailingServer (Proxy).launch index f9e884ac7d2..a28538e295b 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy).launch @@ -19,7 +19,7 @@ - + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch b/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch index 63313b848a1..3d135d34a1c 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch @@ -18,7 +18,7 @@ - + diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java index 5f4aa764398..443665d3d93 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java @@ -163,6 +163,8 @@ import com.sap.sailing.server.operationaltransformation.CreateTrackedRace; import com.sap.sailing.server.operationaltransformation.DataImportFailed; import com.sap.sailing.server.operationaltransformation.RecordCompetitorGPSFix; import com.sap.sailing.server.operationaltransformation.RecordMarkGPSFix; +import com.sap.sailing.server.operationaltransformation.RecordMarkGPSFixForExistingTrack; +import com.sap.sailing.server.operationaltransformation.RecordMarkGPSFixForNewMarkTrack; import com.sap.sailing.server.operationaltransformation.RecordWindFix; import com.sap.sailing.server.operationaltransformation.RemoveDeviceConfiguration; import com.sap.sailing.server.operationaltransformation.RemoveEvent; @@ -1370,8 +1372,14 @@ public class RacingEventServiceImpl implements RacingEventServiceWithTestSupport } @Override - public void markPositionChanged(GPSFix fix, Mark mark) { - replicate(new RecordMarkGPSFix(getRaceIdentifier(), mark, fix)); + public void markPositionChanged(GPSFix fix, Mark mark, boolean firstInTrack) { + final RecordMarkGPSFix operation; + if (firstInTrack) { + operation = new RecordMarkGPSFixForNewMarkTrack(getRaceIdentifier(), mark, fix); + } else { + operation = new RecordMarkGPSFixForExistingTrack(getRaceIdentifier(), mark, fix); + } + replicate(operation); } @Override diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/RecordMarkGPSFix.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/RecordMarkGPSFix.java index e0ed4ded9f8..fc9144eed29 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/RecordMarkGPSFix.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/RecordMarkGPSFix.java @@ -1,51 +1,27 @@ package com.sap.sailing.server.operationaltransformation; -import java.io.Serializable; - -import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.GPSFix; import com.sap.sailing.server.RacingEventService; import com.sap.sailing.server.RacingEventServiceOperation; -public class RecordMarkGPSFix extends AbstractRaceOperation { +public abstract class RecordMarkGPSFix extends AbstractRaceOperation { private static final long serialVersionUID = -2149936580623244814L; - private final Serializable markID; private final GPSFix fix; - public RecordMarkGPSFix(RegattaAndRaceIdentifier raceIdentifier, Mark mark, GPSFix fix) { + public RecordMarkGPSFix(RegattaAndRaceIdentifier raceIdentifier, GPSFix fix) { super(raceIdentifier); - this.markID = mark.getId(); this.fix = fix; } - /** - * Operations of this type can be run in parallel to other operations; subsequent operations do not have to wait - * for this operation's completion. - */ - @Override - public boolean requiresSynchronousExecution() { - return false; + protected GPSFix getFix() { + return fix; } - @Override - public Void internalApplyTo(RacingEventService toState) throws Exception { + protected DynamicTrackedRace getTrackedRace(RacingEventService toState) { DynamicTrackedRace trackedRace = (DynamicTrackedRace) toState.getTrackedRace(getRaceIdentifier()); - Mark mark = getMarkById(trackedRace); - trackedRace.recordFix(mark, fix); - return null; - } - - private Mark getMarkById(DynamicTrackedRace trackedRace) { - Mark result = null; - for (Mark mark : trackedRace.getMarks()) { - if (mark.getId().equals(markID)) { - result = mark; - break; - } - } - return result; + return trackedRace; } @Override diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/RecordMarkGPSFixForExistingTrack.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/RecordMarkGPSFixForExistingTrack.java new file mode 100755 index 00000000000..5ab7436755d --- /dev/null +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/RecordMarkGPSFixForExistingTrack.java @@ -0,0 +1,48 @@ +package com.sap.sailing.server.operationaltransformation; + +import java.io.Serializable; + +import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.tracking.DynamicTrackedRace; +import com.sap.sailing.domain.tracking.GPSFix; +import com.sap.sailing.server.RacingEventService; + +public class RecordMarkGPSFixForExistingTrack extends RecordMarkGPSFix { + private static final long serialVersionUID = -3953907832324217209L; + private final Serializable markId; + + public RecordMarkGPSFixForExistingTrack(RegattaAndRaceIdentifier raceIdentifier, Mark mark, GPSFix fix) { + super(raceIdentifier, fix); + this.markId = mark.getId(); + } + + private Mark getMarkById(DynamicTrackedRace trackedRace) { + Mark result = null; + for (Mark mark : trackedRace.getMarks()) { + if (mark.getId().equals(markId)) { + result = mark; + break; + } + } + return result; + } + + @Override + public Void internalApplyTo(RacingEventService toState) throws Exception { + DynamicTrackedRace trackedRace = getTrackedRace(toState); + Mark mark = getMarkById(trackedRace); + trackedRace.recordFix(mark, getFix()); + return null; + } + + /** + * Operations of this type can be run in parallel to other operations; subsequent operations do not have to wait + * for this operation's completion. + */ + @Override + public boolean requiresSynchronousExecution() { + return false; + } + +} diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/RecordMarkGPSFixForNewMarkTrack.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/RecordMarkGPSFixForNewMarkTrack.java new file mode 100755 index 00000000000..7fc79dc1e2e --- /dev/null +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/RecordMarkGPSFixForNewMarkTrack.java @@ -0,0 +1,31 @@ +package com.sap.sailing.server.operationaltransformation; + +import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.tracking.DynamicTrackedRace; +import com.sap.sailing.domain.tracking.GPSFix; +import com.sap.sailing.server.RacingEventService; + +/** + * Records a mark fix for a mark whose track was just created. Such an operation carries the full {@link Mark} object + * because the receiver needs it in order to construct the mark track. + * + * @author Axel Uhl (d043530) + * + */ +public class RecordMarkGPSFixForNewMarkTrack extends RecordMarkGPSFix { + private static final long serialVersionUID = 6462303849651033783L; + private final Mark mark; + + public RecordMarkGPSFixForNewMarkTrack(RegattaAndRaceIdentifier raceIdentifier, Mark mark, GPSFix fix) { + super(raceIdentifier, fix); + this.mark = mark; + } + + @Override + public Void internalApplyTo(RacingEventService toState) throws Exception { + DynamicTrackedRace trackedRace = getTrackedRace(toState); + trackedRace.recordFix(mark, getFix()); + return null; + } +}