From 1e01668a69a7816f221d6ab3c3f7bc0c88f4e1cb Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Mon, 18 Jun 2012 20:29:51 +0200 Subject: [PATCH] work towards a TracTrac simulator --- .../sailing/domain/test/CourseUpdateTest.java | 2 +- .../test/MultipleClassesInRegattaTest.java | 9 +- .../domain/test/OnlineTracTracBasedTest.java | 3 +- .../test/ReceiveMarkPassingDataTest.java | 6 +- .../domain/test/ReceiveTrackingDataTest.java | 6 +- ...nicodeCharactersInCompetitorNamesTest.java | 22 +++-- .../domain/tractracadapter/DomainFactory.java | 16 ++-- .../impl/AbstractReceiverWithQueue.java | 8 +- .../impl/DomainFactoryImpl.java | 43 ++++++---- .../impl/MarkPassingReceiver.java | 4 +- .../impl/MarkPositionReceiver.java | 4 +- .../impl/RaceCourseReceiver.java | 21 +++-- .../impl/RaceStartedAndFinishedReceiver.java | 5 +- .../impl/RawPositionReceiver.java | 5 +- .../tractracadapter/impl/Simulator.java | 85 ++++++++++++++++++- .../impl/TracTracRaceTrackerImpl.java | 13 ++- .../domain/tracking/TrackedRegatta.java | 2 +- .../domain/tracking/impl/TrackedRaceImpl.java | 4 +- .../tracking/impl/TrackedRegattaImpl.java | 12 +-- .../ui/test/GwtTestCaseColumnToggling.java | 2 +- ...estStoringAndRetrievingWindTracksTest.java | 3 +- .../test/TrackRaceReplicationTest.java | 3 +- .../sailing/server/RacingEventService.java | 4 +- 23 files changed, 209 insertions(+), 73 deletions(-) mode change 100644 => 100755 java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/Simulator.java diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java index 7399320cac6..5a21ace9051 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java @@ -75,7 +75,7 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest { @Override public void addRaceDefinition(RaceDefinition race) {} }, /* delayToLiveInMillis */ 0l, - /* millisecondsOverWhichToAverageWind */ 30000) { + /* millisecondsOverWhichToAverageWind */ 30000, /* simulator */ null) { @Override protected void handleEvent(Triple event) { synchronized (routeData) { diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MultipleClassesInRegattaTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MultipleClassesInRegattaTest.java index b4805f95153..aeb1f24f2b6 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MultipleClassesInRegattaTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MultipleClassesInRegattaTest.java @@ -49,25 +49,26 @@ public class MultipleClassesInRegattaTest { new URL( httpAndHost+"/events/event_20110505_SailingTea/clientparams.php?event=event_20110505_SailingTea&race=cce678c8-97e6-11e0-9aed-406186cbf87c"), new URI(liveURI), new URI(storedURI), - /* startOfTracking */ null, /* endOfTracking */ null, /* delayToLiveInMillis */ 0l, simulateWithStartTimeNow, simulateWithStartTimeNow, EmptyWindStore.INSTANCE, new DummyTrackedRegattaRegistry()); + /* startOfTracking */ null, /* endOfTracking */ null, /* delayToLiveInMillis */ 0l, /* simulateWithStartTimeNow */ false, + EmptyWindStore.INSTANCE, new DummyTrackedRegattaRegistry()); kiwotest2 = domainFactory .createRaceTracker( new URL( httpAndHost+"/events/event_20110505_SailingTea/clientparams.php?event=event_20110505_SailingTea&race=11290bd6-97e7-11e0-9aed-406186cbf87c"), new URI(liveURI), new URI(storedURI), - /* startOfTracking */ null, /* endOfTracking */ null, /* delayToLiveInMillis */ 0l, simulateWithStartTimeNow, simulateWithStartTimeNow, EmptyWindStore.INSTANCE, new DummyTrackedRegattaRegistry()); + /* startOfTracking */ null, /* endOfTracking */ null, /* delayToLiveInMillis */ 0l, /* simulateWithStartTimeNow */ false, EmptyWindStore.INSTANCE, new DummyTrackedRegattaRegistry()); kiwotest3 = domainFactory .createRaceTracker( new URL( httpAndHost+"/events/event_20110505_SailingTea/clientparams.php?event=event_20110505_SailingTea&race=39635b24-97e7-11e0-9aed-406186cbf87c"), new URI(liveURI), new URI(storedURI), - /* startOfTracking */ null, /* endOfTracking */ null, /* delayToLiveInMillis */ 0l, simulateWithStartTimeNow, simulateWithStartTimeNow, EmptyWindStore.INSTANCE, new DummyTrackedRegattaRegistry()); + /* startOfTracking */ null, /* endOfTracking */ null, /* delayToLiveInMillis */ 0l, /* simulateWithStartTimeNow */ false, EmptyWindStore.INSTANCE, new DummyTrackedRegattaRegistry()); weym470may112014_2 = domainFactory .createRaceTracker( new URL( httpAndHost+"/events/event_20110505_SailingTea/clientparams.php?event=event_20110505_SailingTea&race=04498426-7dfd-11e0-8236-406186cbf87c"), new URI(liveURI), new URI(storedURI), - /* startOfTracking */ null, /* endOfTracking */ null, /* delayToLiveInMillis */ 0l, simulateWithStartTimeNow, simulateWithStartTimeNow, EmptyWindStore.INSTANCE, new DummyTrackedRegattaRegistry()); + /* startOfTracking */ null, /* endOfTracking */ null, /* delayToLiveInMillis */ 0l, /* simulateWithStartTimeNow */ false, EmptyWindStore.INSTANCE, new DummyTrackedRegattaRegistry()); assertEquals("STG", kiwotest1.getRegatta().getBoatClass().getName()); assertEquals("505", kiwotest2.getRegatta().getBoatClass().getName()); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java index 56681029bf7..d9b25f541a4 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java @@ -90,7 +90,8 @@ public abstract class OnlineTracTracBasedTest extends AbstractTracTracLiveTest { setStoredDataLoaded(false); ArrayList receivers = new ArrayList(); for (Receiver r : domainFactory.getUpdateReceivers(trackedRegatta, getTracTracEvent(), EmptyWindStore.INSTANCE, - /* startOfTracking */ null, /* endOfTracking */ null, /* delayToLiveInMillis */ 0l, new DynamicRaceDefinitionSet() { + /* startOfTracking */null, /* endOfTracking */null, /* delayToLiveInMillis */0l, /* simulateWithStartTimeNow */ false, + new DynamicRaceDefinitionSet() { @Override public void addRaceDefinition(RaceDefinition race) { } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveMarkPassingDataTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveMarkPassingDataTest.java index f07d660f143..a46c16b2f7a 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveMarkPassingDataTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveMarkPassingDataTest.java @@ -95,11 +95,11 @@ public class ReceiveMarkPassingDataTest extends AbstractTracTracLiveTest { for (Receiver r : DomainFactory.INSTANCE.getUpdateReceivers( new DynamicTrackedRegattaImpl(DomainFactory.INSTANCE.getOrCreateDefaultRegatta(getTracTracEvent(), /* trackedRegattaRegistry */ null)), getTracTracEvent(), EmptyWindStore.INSTANCE, /* startOfTracking */ null, /* endOfTracking */ null, /* delayToLiveInMillis */ 0l, - new DynamicRaceDefinitionSet() { + /* simulateWithStartTimeNow */ false, new DynamicRaceDefinitionSet() { @Override public void addRaceDefinition(RaceDefinition race) {} - }, /* trackedRegattaRegistry */ null, - ReceiverType.RACECOURSE, ReceiverType.MARKPOSITIONS, ReceiverType.RACESTARTFINISH, ReceiverType.RAWPOSITIONS)) { + }, + /* trackedRegattaRegistry */ null, ReceiverType.RACECOURSE, ReceiverType.MARKPOSITIONS, ReceiverType.RACESTARTFINISH, ReceiverType.RAWPOSITIONS)) { receivers.add(r); } addListenersForStoredDataAndStartController(receivers); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java index 348d048f74d..2f0027c870a 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java @@ -78,7 +78,8 @@ public class ReceiveTrackingDataTest extends AbstractTracTracLiveTest { } }); for (Receiver receiver : domainFactory.getUpdateReceivers(trackedRegatta, getTracTracEvent(), /* start of tracking */ null, - /* end of tracking */ null, /* delayToLiveInMillis */ 0l, EmptyWindStore.INSTANCE, new DynamicRaceDefinitionSet() { + /* end of tracking */null, /* delayToLiveInMillis */0l, /* simulateWithStartTimeNow */false, + EmptyWindStore.INSTANCE, new DynamicRaceDefinitionSet() { @Override public void addRaceDefinition(RaceDefinition race) { } @@ -88,7 +89,8 @@ public class ReceiveTrackingDataTest extends AbstractTracTracLiveTest { } } addListenersForStoredDataAndStartController(domainFactory.getUpdateReceivers(trackedRegatta, getTracTracEvent(), - /* start of tracking */ null, /* end of tracking */ null, /* delayToLiveInMillis */ 0l, EmptyWindStore.INSTANCE, new DynamicRaceDefinitionSet() { + /* start of tracking */null, /* end of tracking */null, /* delayToLiveInMillis */0l, /* simulateWithStartTimeNow */ + false, EmptyWindStore.INSTANCE, new DynamicRaceDefinitionSet() { @Override public void addRaceDefinition(RaceDefinition race) { } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/UnicodeCharactersInCompetitorNamesTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/UnicodeCharactersInCompetitorNamesTest.java index 06afc78a5d2..0b8ecf5cc7c 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/UnicodeCharactersInCompetitorNamesTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/UnicodeCharactersInCompetitorNamesTest.java @@ -42,12 +42,22 @@ public class UnicodeCharactersInCompetitorNamesTest { TracTracRaceTracker fourtyninerYellow_2 = domainFactory .createRaceTracker( new URL( - "http://" + TracTracConnectionConstants.HOST_NAME + "/events/event_20110609_KielerWoch/clientparams.php?event=event_20110609_KielerWoch&race=5b08a9ee-9933-11e0-85be-406186cbf87c"), - tractracTunnel ? new URI("tcp://"+tractracTunnelHost+":"+TracTracConnectionConstants.PORT_TUNNEL_LIVE) : new URI("tcp://" + TracTracConnectionConstants.HOST_NAME + ":" + TracTracConnectionConstants.PORT_LIVE), - tractracTunnel ? new URI("tcp://"+tractracTunnelHost+":"+TracTracConnectionConstants.PORT_TUNNEL_STORED) : new URI("tcp://" + TracTracConnectionConstants.HOST_NAME + ":" + TracTracConnectionConstants.PORT_STORED), - /* startOfTracking */ null, /* endOfTracking */ null, /* delayToLiveInMillis */ 0l, simulateWithStartTimeNow, simulateWithStartTimeNow, EmptyWindStore.INSTANCE, new DummyTrackedRegattaRegistry()); - - Iterable competitors = fourtyninerYellow_2.getRacesHandle().getRaces().iterator().next().getCompetitors(); + "http://" + + TracTracConnectionConstants.HOST_NAME + + "/events/event_20110609_KielerWoch/clientparams.php?event=event_20110609_KielerWoch&race=5b08a9ee-9933-11e0-85be-406186cbf87c"), + tractracTunnel ? new URI("tcp://" + tractracTunnelHost + ":" + + TracTracConnectionConstants.PORT_TUNNEL_LIVE) : new URI("tcp://" + + TracTracConnectionConstants.HOST_NAME + ":" + TracTracConnectionConstants.PORT_LIVE), + tractracTunnel ? new URI("tcp://" + tractracTunnelHost + ":" + + TracTracConnectionConstants.PORT_TUNNEL_STORED) + : new URI("tcp://" + TracTracConnectionConstants.HOST_NAME + ":" + + TracTracConnectionConstants.PORT_STORED), + /* startOfTracking */null, /* endOfTracking */null, /* delayToLiveInMillis */0l, + /* simulateWithStartTimeNow */ false, EmptyWindStore.INSTANCE, + new DummyTrackedRegattaRegistry()); + + Iterable competitors = fourtyninerYellow_2.getRacesHandle().getRaces().iterator().next() + .getCompetitors(); for (Competitor competitor : competitors) { System.out.println(competitor.getName()); } diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java index 0603849129d..46e700b0493 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java @@ -23,14 +23,15 @@ import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.impl.Util.Pair; import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet; +import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; import com.sap.sailing.domain.tracking.GPSFixMoving; import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.RaceTracker; import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParameters; +import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.TrackedRegatta; import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; -import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.WindStore; import com.sap.sailing.domain.tracking.WindTrack; import com.sap.sailing.domain.tracking.impl.EmptyWindStore; @@ -115,15 +116,15 @@ public interface DomainFactory { * if null, all stored data until the "end of time" will be loaded that the event has * to provide, particularly for the mark positions which are stored per event, not per race; otherwise, * particularly the mark position loading will be constrained to this end time. - * @param simulateWithStartTimeNow TODO * @param windStore * Provides the capability to obtain the {@link WindTrack}s for the different wind sources. A trivial * implementation is {@link EmptyWindStore} which simply provides new, empty tracks. This is always * available but loses track of the wind, e.g., during server restarts. */ TracTracRaceTracker createRaceTracker(URL paramURL, URI liveURI, URI storedURI, TimePoint startOfTracking, - TimePoint endOfTracking, long delayToLiveInMillis, boolean simulateWithStartTimeNow, WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry) - throws MalformedURLException, FileNotFoundException, URISyntaxException; + TimePoint endOfTracking, long delayToLiveInMillis, boolean simulateWithStartTimeNow, WindStore windStore, + TrackedRegattaRegistry trackedRegattaRegistry) throws MalformedURLException, FileNotFoundException, + URISyntaxException; /** * Same as {@link #createRaceTracker(URL, URI, URI, TimePoint, TimePoint, WindStore, TrackedRegattaRegistry)}, only that @@ -155,13 +156,14 @@ public interface DomainFactory { * if null, all stored data until the "end of time" will be loaded that the event has to * provide, particularly for the mark positions which are stored per event, not per race; otherwise, * particularly the mark position loading will be constrained to this end time. + * @param simulateWithStartTimeNow TODO * @param trackedRegattaRegistry TODO * @param tokenToRetrieveAssociatedRace * used to update the set of{@link RaceDefinition}s received by the * {@link RaceCourseReceiver} created by this call */ Iterable getUpdateReceivers(DynamicTrackedRegatta trackedRegatta, Event tractracEvent, TimePoint startOfTracking, - TimePoint endOfTracking, long delayToLiveInMillis, WindStore windStore, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, TrackedRegattaRegistry trackedRegattaRegistry); + TimePoint endOfTracking, long delayToLiveInMillis, boolean simulateWithStartTimeNow, WindStore windStore, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, TrackedRegattaRegistry trackedRegattaRegistry); /** * Creates a {@link RaceDefinition} from a TracTrac {@link Race} and a domain {@link Course} definition. The @@ -180,7 +182,7 @@ public interface DomainFactory { * if not null, after creating the {@link TrackedRace}, the {@link RaceDefinition} is * {@link DynamicRaceDefinitionSet#addRaceDefinition(RaceDefinition) added} to that object. */ - void getOrCreateRaceDefinitionAndTrackedRace(TrackedRegatta trackedRegatta, Race race, + DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(TrackedRegatta trackedRegatta, Race race, Course course, WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate); @@ -196,7 +198,7 @@ public interface DomainFactory { MarkPassing createMarkPassing(TimePoint timePoint, Waypoint passed, com.sap.sailing.domain.base.Competitor competitor); Iterable getUpdateReceivers(DynamicTrackedRegatta trackedRegatta, Event tractracEvent, WindStore windStore, - TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, TrackedRegattaRegistry trackedRegattaRegistry, ReceiverType... types); + TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis, boolean simulateWithStartTimeNow, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, TrackedRegattaRegistry trackedRegattaRegistry, ReceiverType... types); JSONService parseJSONURL(URL jsonURL) throws IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException; diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/AbstractReceiverWithQueue.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/AbstractReceiverWithQueue.java index dfdab3e6a85..b812ae685fb 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/AbstractReceiverWithQueue.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/AbstractReceiverWithQueue.java @@ -31,6 +31,7 @@ public abstract class AbstractReceiverWithQueue implements Runnable, Re private final DomainFactory domainFactory; private final com.tractrac.clientmodule.Event tractracEvent; private final DynamicTrackedRegatta trackedRegatta; + private final Simulator simulator; private Thread thread; /** @@ -40,11 +41,12 @@ public abstract class AbstractReceiverWithQueue implements Runnable, Re private boolean receivedEventDuringTimeout; public AbstractReceiverWithQueue(DomainFactory domainFactory, Event tractracEvent, - DynamicTrackedRegatta trackedRegatta) { + DynamicTrackedRegatta trackedRegatta, Simulator simulator) { super(); this.tractracEvent = tractracEvent; this.trackedRegatta = trackedRegatta; this.domainFactory = domainFactory; + this.simulator = simulator; this.queue = new LinkedBlockingQueue>(); } @@ -76,6 +78,10 @@ public abstract class AbstractReceiverWithQueue implements Runnable, Re queue.add(new Triple(null, null, null)); } + protected Simulator getSimulator() { + return simulator; + } + @Override public void stopAfterNotReceivingEventsForSomeTime(final long timeoutInMilliseconds) { receivedEventDuringTimeout = false; diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java index a7db60c62c3..b0c6acdaebc 100644 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java @@ -42,12 +42,12 @@ import com.sap.sailing.domain.common.impl.DegreePosition; import com.sap.sailing.domain.common.impl.Util; import com.sap.sailing.domain.common.impl.Util.Pair; import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet; +import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; import com.sap.sailing.domain.tracking.GPSFixMoving; import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.RaceTracker; import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParameters; -import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.TrackedRegatta; import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; import com.sap.sailing.domain.tracking.WindStore; @@ -286,7 +286,15 @@ public class DomainFactoryImpl implements DomainFactory { @Override public Iterable getUpdateReceivers(DynamicTrackedRegatta trackedRegatta, com.tractrac.clientmodule.Event tractracEvent, WindStore windStore, TimePoint startOfTracking, - TimePoint endOfTracking, long delayToLiveInMillis, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, TrackedRegattaRegistry trackedRegattaRegistry, ReceiverType... types) { + TimePoint endOfTracking, long delayToLiveInMillis, boolean simulateWithStartTimeNow, + DynamicRaceDefinitionSet raceDefinitionSetToUpdate, TrackedRegattaRegistry trackedRegattaRegistry, + ReceiverType... types) { + Simulator simulator; + if (simulateWithStartTimeNow) { + simulator = new Simulator(); + } else { + simulator = null; + } Collection result = new ArrayList(); for (ReceiverType type : types) { switch (type) { @@ -294,23 +302,23 @@ public class DomainFactoryImpl implements DomainFactory { result.add(new RaceCourseReceiver( this, trackedRegatta, tractracEvent, windStore, raceDefinitionSetToUpdate, delayToLiveInMillis, - WindTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_WIND)); + WindTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_WIND, simulator)); break; case MARKPOSITIONS: result.add(new MarkPositionReceiver( - trackedRegatta, tractracEvent, startOfTracking, endOfTracking, this)); + trackedRegatta, tractracEvent, startOfTracking, endOfTracking, simulator, this)); break; case RAWPOSITIONS: result.add(new RawPositionReceiver( - trackedRegatta, tractracEvent, this)); + trackedRegatta, tractracEvent, this, simulator)); break; case MARKPASSINGS: result.add(new MarkPassingReceiver( - trackedRegatta, tractracEvent, this)); + trackedRegatta, tractracEvent, simulator, this)); break; case RACESTARTFINISH: result.add(new RaceStartedAndFinishedReceiver( - trackedRegatta, tractracEvent, this)); + trackedRegatta, tractracEvent, simulator, this)); break; } } @@ -320,11 +328,12 @@ public class DomainFactoryImpl implements DomainFactory { @Override public Iterable getUpdateReceivers(DynamicTrackedRegatta trackedRegatta, com.tractrac.clientmodule.Event tractracEvent, TimePoint startOfTracking, TimePoint endOfTracking, - long delayToLiveInMillis, WindStore windStore, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, - TrackedRegattaRegistry trackedRegattaRegistry) { - return getUpdateReceivers(trackedRegatta, tractracEvent, windStore, startOfTracking, endOfTracking, delayToLiveInMillis, - raceDefinitionSetToUpdate, trackedRegattaRegistry, ReceiverType.RACECOURSE, - ReceiverType.MARKPASSINGS, ReceiverType.MARKPOSITIONS, ReceiverType.RACESTARTFINISH, ReceiverType.RAWPOSITIONS); + long delayToLiveInMillis, boolean simulateWithStartTimeNow, WindStore windStore, + DynamicRaceDefinitionSet raceDefinitionSetToUpdate, TrackedRegattaRegistry trackedRegattaRegistry) { + return getUpdateReceivers(trackedRegatta, tractracEvent, windStore, startOfTracking, endOfTracking, + delayToLiveInMillis, simulateWithStartTimeNow, raceDefinitionSetToUpdate, trackedRegattaRegistry, + ReceiverType.RACECOURSE, ReceiverType.MARKPASSINGS, ReceiverType.MARKPOSITIONS, + ReceiverType.RACESTARTFINISH, ReceiverType.RAWPOSITIONS); } @Override @@ -379,7 +388,7 @@ public class DomainFactoryImpl implements DomainFactory { } @Override - public void getOrCreateRaceDefinitionAndTrackedRace(TrackedRegatta trackedRegatta, + public DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(TrackedRegatta trackedRegatta, Race race, Course course, WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate) { synchronized (raceCache) { @@ -392,19 +401,19 @@ public class DomainFactoryImpl implements DomainFactory { // add to existing regatta only if boat class matches if (raceDefinition.getBoatClass() == trackedRegatta.getRegatta().getBoatClass()) { trackedRegatta.getRegatta().addRace(raceDefinition); - - createTrackedRace(trackedRegatta, raceDefinition, windStore, + DynamicTrackedRace trackedRace = createTrackedRace(trackedRegatta, raceDefinition, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, raceDefinitionSetToUpdate); logger.info("Added race "+raceDefinition+" to regatta "+trackedRegatta.getRegatta()); - synchronized (raceCache) { raceCache.put(race, raceDefinition); raceCache.notifyAll(); } + return trackedRace; } else { logger.warning("Not adding race "+raceDefinition+" to regatta "+trackedRegatta.getRegatta()+ " because boat class "+raceDefinition.getBoatClass()+" doesn't match regatta's boat class "+ trackedRegatta.getRegatta().getBoatClass()); + return null; } } else { throw new RuntimeException("Race "+race.getName()+" already exists"); @@ -412,7 +421,7 @@ public class DomainFactoryImpl implements DomainFactory { } } - private TrackedRace createTrackedRace(TrackedRegatta trackedRegatta, RaceDefinition race, WindStore windStore, + private DynamicTrackedRace createTrackedRace(TrackedRegatta trackedRegatta, RaceDefinition race, WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate) { return trackedRegatta.createTrackedRace(race, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPassingReceiver.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPassingReceiver.java index 15b243192f2..26758a59ce9 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPassingReceiver.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPassingReceiver.java @@ -30,8 +30,8 @@ public class MarkPassingReceiver extends AbstractReceiverWithQueue { private static final Logger logger = Logger.getLogger(RaceStartedAndFinishedReceiver.class.getName()); - public RaceStartedAndFinishedReceiver(DynamicTrackedRegatta trackedRegatta, com.tractrac.clientmodule.Event tractracEvent, DomainFactory domainFactory) { - super(domainFactory, tractracEvent, trackedRegatta); + public RaceStartedAndFinishedReceiver(DynamicTrackedRegatta trackedRegatta, + com.tractrac.clientmodule.Event tractracEvent, Simulator simulator, DomainFactory domainFactory) { + super(domainFactory, tractracEvent, trackedRegatta, simulator); } /** diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RawPositionReceiver.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RawPositionReceiver.java index 24c55c28852..7d459ebe7ac 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RawPositionReceiver.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RawPositionReceiver.java @@ -21,8 +21,9 @@ public class RawPositionReceiver extends AbstractReceiverWithQueue windSourceAndTrack : windStore.loadWindTracks( + trackedRace.getTrackedRegatta(), trackedRace, + /* millisecondsOverWhichToAverageWind doesn't matter because we only use raw fixes */ 10000).entrySet()) { + new Thread("Wind simulator for wind source "+windSourceAndTrack.getKey()+" for tracked race "+trackedRace.getRace().getName()) { + @Override + public void run() { + for (Wind wind : windSourceAndTrack.getValue().getRawFixes()) { + trackedRace.recordWind(delayWind(wind), windSourceAndTrack.getKey()); + } + } + }.start(); + } + } + + private Wind delayWind(Wind wind) { + TimePoint delayedTimePoint = delay(wind); + return new WindImpl(wind.getPosition(), delayedTimePoint, new KnotSpeedWithBearingImpl(wind.getKnots(), wind.getBearing())); + } + + private long getAdvanceInMillis() { + return advanceInMillis; + } + + /** + * Transforms timed's time point according to this simulator's delay and waits roughly until this time + * has passed. Then, returns the adjusted time point which therefore should roughly equal "now." + */ + private TimePoint delay(Timed timed) { + long now = System.currentTimeMillis(); + long then = timed.getTimePoint().asMillis(); + long transformedTimed = then + getAdvanceInMillis(); + long waitTimeInMillis = transformedTimed - now; + do { + if (waitTimeInMillis > 0) { + try { + Thread.sleep(waitTimeInMillis); + waitTimeInMillis = 0; + } catch (InterruptedException e) { + // try again: + waitTimeInMillis = transformedTimed - System.currentTimeMillis(); + } + } + } while (waitTimeInMillis > 0); + return new MillisecondsTimePoint(transformedTimed); + } } diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java index 28a9860fcff..98ca780032e 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java @@ -148,9 +148,14 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements /** * - * @param regatta if null, then domainFactory.getOrCreateRegatta(tractracEvent) will be used to - * obtain a default regatta - * @param simulateWithStartTimeNow TODO + * @param regatta + * if null, then domainFactory.getOrCreateRegatta(tractracEvent) will be used + * to obtain a default regatta + * @param simulateWithStartTimeNow + * if true, the connector will adjust the time stamps of all events received such that the + * first mark passing for the first waypoint will be set to "now." It will delay the forwarding of all + * events received such that they seem to be sent in "real-time." So, more or less the time points + * attached to the events sent to the receivers will again approximate the wall time. */ private TracTracRaceTrackerImpl(Event tractracEvent, final Regatta regatta, DomainFactory domainFactory, URL paramURL, URI liveURI, URI storedURI, TimePoint startOfTracking, TimePoint endOfTracking, @@ -193,7 +198,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements receivers = new HashSet(); Set typeControllers = new HashSet(); for (Receiver receiver : domainFactory.getUpdateReceivers(getTrackedRegatta(), tractracEvent, startOfTracking, - endOfTracking, delayToLiveInMillis, windStore, this, trackedRegattaRegistry)) { + endOfTracking, delayToLiveInMillis, simulateWithStartTimeNow, windStore, this, trackedRegattaRegistry)) { receivers.add(receiver); for (TypeController typeController : receiver.getTypeControllersAndStart()) { typeControllers.add(typeController); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRegatta.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRegatta.java index 1483cfd91a3..eb0bb6549e9 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRegatta.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRegatta.java @@ -39,7 +39,7 @@ public interface TrackedRegatta extends Serializable { * if not null, after creating the {@link TrackedRace}, the raceDefinition is * {@link DynamicRaceDefinitionSet#addRaceDefinition(RaceDefinition) added} to that object. */ - TrackedRace createTrackedRace(RaceDefinition raceDefinition, WindStore windStore, + DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, DynamicRaceDefinitionSet raceDefinitionSetToUpdate); 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 765de7c4e8b..809e6ddccfd 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 @@ -244,7 +244,9 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { } markPassingsTimes = new ArrayList>>(); windTracks = new HashMap(); - windTracks.putAll(windStore.loadWindTracks(trackedRegatta, this, millisecondsOverWhichToAverageWind)); + final Map loadedWindTracks = windStore.loadWindTracks( + trackedRegatta, this, millisecondsOverWhichToAverageWind); + windTracks.putAll(loadedWindTracks); // by default, a tracked race offers one course-based wind estimation, one track-based wind estimation track and // one "WEB" track for manual or REST-based wind reception; other wind tracks may be added as fixes are received // for them. diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRegattaImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRegattaImpl.java index 1f9dd01f008..18e16312dbd 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRegattaImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRegattaImpl.java @@ -13,14 +13,15 @@ import java.util.logging.Logger; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet; +import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.RaceListener; -import com.sap.sailing.domain.tracking.TrackedRegatta; import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.domain.tracking.TrackedRegatta; import com.sap.sailing.domain.tracking.WindStore; public class TrackedRegattaImpl implements TrackedRegatta { @@ -160,9 +161,10 @@ public class TrackedRegattaImpl implements TrackedRegatta { } @Override - public TrackedRace createTrackedRace(RaceDefinition raceDefinition, WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, - long millisecondsOverWhichToAverageSpeed, DynamicRaceDefinitionSet raceDefinitionSetToUpdate) { - logger.log(Level.INFO, "Creating DynamicTrackedRaceImpl for RaceDefinition "+raceDefinition.getName()); + public DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, WindStore windStore, long delayToLiveInMillis, + long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, + DynamicRaceDefinitionSet raceDefinitionSetToUpdate) { + logger.log(Level.INFO, "Creating DynamicTrackedRaceImpl for RaceDefinition " + raceDefinition.getName()); DynamicTrackedRaceImpl result = new DynamicTrackedRaceImpl(this, raceDefinition, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed); if (raceDefinitionSetToUpdate != null) { diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/GwtTestCaseColumnToggling.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/GwtTestCaseColumnToggling.java index 6070632c4af..2133ef0f50a 100644 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/GwtTestCaseColumnToggling.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/GwtTestCaseColumnToggling.java @@ -85,7 +85,7 @@ public class GwtTestCaseColumnToggling extends GWTTestCase { + TracTracConnectionConstants.PORT_TUNNEL_LIVE : "tcp://" + TracTracConnectionConstants.HOST_NAME + ":" + TracTracConnectionConstants.PORT_LIVE, tractracTunnel ? "tcp://" + tractracTunnelHost + ":" + TracTracConnectionConstants.PORT_TUNNEL_STORED : "tcp://" + TracTracConnectionConstants.HOST_NAME - + ":" + TracTracConnectionConstants.PORT_STORED, false, false, simulateWithStartTimeNow, new AsyncCallback() { + + ":" + TracTracConnectionConstants.PORT_STORED, false, false, /* simulateWithStartTimeNow */ false, new AsyncCallback() { @Override public void onFailure(Throwable caught) { diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java index 9a9bedc9565..a6fc7782a7e 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java @@ -73,7 +73,8 @@ public class TestStoringAndRetrievingWindTracksTest extends AbstractTracTracLive Regatta domainEvent = domainFactory.getOrCreateDefaultRegatta(getTracTracEvent(), /* trackedRegattaRegistry */ null); DynamicTrackedRegatta trackedRegatta = new RacingEventServiceImpl().getOrCreateTrackedRegatta(domainEvent); Iterable typeControllers = domainFactory.getUpdateReceivers(trackedRegatta, getTracTracEvent(), - EmptyWindStore.INSTANCE, /* startOfTracking */ null, /* endOfTracking */ null, /* delayToLiveInMillis */ 0l, new DynamicRaceDefinitionSet() { + EmptyWindStore.INSTANCE, /* startOfTracking */null, /* endOfTracking */null, /* delayToLiveInMillis */ + 0l, /* simulateWithStartTimeNow */false, new DynamicRaceDefinitionSet() { @Override public void addRaceDefinition(RaceDefinition race) { } diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackRaceReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackRaceReplicationTest.java index e7f21262471..a088d688472 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackRaceReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackRaceReplicationTest.java @@ -73,7 +73,8 @@ public class TrackRaceReplicationTest extends AbstractServerReplicationTest { } }); trackingParams = com.sap.sailing.domain.tractracadapter.DomainFactory.INSTANCE.createTrackingConnectivityParameters(paramURL, - liveURI, storedURI, startOfTracking, endOfTracking, /* delayToLiveInMillis */ 0l, simulateWithStartTimeNow, EmptyWindStore.INSTANCE); + liveURI, storedURI, startOfTracking, endOfTracking, /* delayToLiveInMillis */ + 0l, /* simulateWithStartTimeNow */false, EmptyWindStore.INSTANCE); } private void startTracking() throws Exception, InterruptedException { diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java index 19ddfd93ce3..3545838253f 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java @@ -145,10 +145,10 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch * created, with a single default series and a single default fleet. If a valid {@link RegattaIdentifier} * is specified, a regatta lookup is performed with that identifier; if the regatta is found, it is used * to add the races to. Otherwise, a default regatta as described above will be created and used. - * @param simulateWithStartTimeNow TODO */ RacesHandle addTracTracRace(RegattaIdentifier regattaToAddTo, URL paramURL, URI liveURI, URI storedURI, - TimePoint trackingStartTime, TimePoint trackingEndTime, WindStore windStore, long timeoutForReceivingRaceDefinitionInMilliseconds, boolean simulateWithStartTimeNow) + TimePoint trackingStartTime, TimePoint trackingEndTime, WindStore windStore, + long timeoutForReceivingRaceDefinitionInMilliseconds, boolean simulateWithStartTimeNow) throws MalformedURLException, FileNotFoundException, URISyntaxException, Exception; /**