mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-05 11:53:53 +00:00
work towards a TracTrac simulator
This commit is contained in:
1 parent
ac854bb314
commit
1e01668a69
23 files changed
+209
-73
No files matched your search
+1
-1
@@ -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<Route, RouteData, Race> event) {
|
||||
synchronized (routeData) {
|
||||
|
||||
+5
-4
@@ -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());
|
||||
|
||||
+2
-1
@@ -90,7 +90,8 @@ public abstract class OnlineTracTracBasedTest extends AbstractTracTracLiveTest {
|
||||
setStoredDataLoaded(false);
|
||||
ArrayList<Receiver> receivers = new ArrayList<Receiver>();
|
||||
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) {
|
||||
}
|
||||
|
||||
+3
-3
@@ -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);
|
||||
|
||||
+4
-2
@@ -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) {
|
||||
}
|
||||
|
||||
+16
-6
@@ -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<Competitor> 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<Competitor> competitors = fourtyninerYellow_2.getRacesHandle().getRaces().iterator().next()
|
||||
.getCompetitors();
|
||||
for (Competitor competitor : competitors) {
|
||||
System.out.println(competitor.getName());
|
||||
}
|
||||
|
||||
+9
-7
@@ -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 <code>null</code>, 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 <code>null</code>, 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<Receiver> 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 <code>null</code>, 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<Receiver> 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;
|
||||
|
||||
|
||||
+7
-1
@@ -31,6 +31,7 @@ public abstract class AbstractReceiverWithQueue<A, B, C> 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<A, B, C> 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<Triple<A, B, C>>();
|
||||
}
|
||||
|
||||
@@ -76,6 +78,10 @@ public abstract class AbstractReceiverWithQueue<A, B, C> implements Runnable, Re
|
||||
queue.add(new Triple<A, B, C>(null, null, null));
|
||||
}
|
||||
|
||||
protected Simulator getSimulator() {
|
||||
return simulator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopAfterNotReceivingEventsForSomeTime(final long timeoutInMilliseconds) {
|
||||
receivedEventDuringTimeout = false;
|
||||
|
||||
+26
-17
@@ -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<Receiver> 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<Receiver> result = new ArrayList<Receiver>();
|
||||
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<Receiver> 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,
|
||||
|
||||
+2
-2
@@ -30,8 +30,8 @@ public class MarkPassingReceiver extends AbstractReceiverWithQueue<RaceCompetito
|
||||
private static final Logger logger = Logger.getLogger(MarkPassingReceiver.class.getName());
|
||||
|
||||
public MarkPassingReceiver(DynamicTrackedRegatta trackedRegatta, com.tractrac.clientmodule.Event tractracEvent,
|
||||
DomainFactory domainFactory) {
|
||||
super(domainFactory, tractracEvent, trackedRegatta);
|
||||
Simulator simulator, DomainFactory domainFactory) {
|
||||
super(domainFactory, tractracEvent, trackedRegatta, simulator);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-2
@@ -67,8 +67,8 @@ public class MarkPositionReceiver extends AbstractReceiverWithQueue<ControlPoint
|
||||
* particularly the mark position loading will be constrained to this end time.
|
||||
*/
|
||||
public MarkPositionReceiver(final DynamicTrackedRegatta trackedRegatta, com.tractrac.clientmodule.Event tractracEvent,
|
||||
TimePoint startOfTracking, TimePoint endOfTracking, final DomainFactory domainFactory) {
|
||||
super(domainFactory, tractracEvent, trackedRegatta);
|
||||
TimePoint startOfTracking, TimePoint endOfTracking, Simulator simulator, final DomainFactory domainFactory) {
|
||||
super(domainFactory, tractracEvent, trackedRegatta, simulator);
|
||||
this.startOfTracking = startOfTracking;
|
||||
this.endOfTracking = endOfTracking;
|
||||
// assumption: there is currently only one race per TracTrac Event object
|
||||
|
||||
+15
-6
@@ -8,10 +8,11 @@ import java.util.logging.Logger;
|
||||
import com.maptrack.client.io.TypeController;
|
||||
import com.sap.sailing.domain.base.ControlPoint;
|
||||
import com.sap.sailing.domain.base.Course;
|
||||
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.impl.Util.Triple;
|
||||
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.WindStore;
|
||||
import com.sap.sailing.domain.tractracadapter.DomainFactory;
|
||||
@@ -43,11 +44,15 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<Route, RouteDa
|
||||
public RaceCourseReceiver(DomainFactory domainFactory, DynamicTrackedRegatta trackedRegatta,
|
||||
com.tractrac.clientmodule.Event tractracEvent, WindStore windStore,
|
||||
DynamicRaceDefinitionSet raceDefinitionSetToUpdate, long delayToLiveInMillis,
|
||||
long millisecondsOverWhichToAverageWind) {
|
||||
super(domainFactory, tractracEvent, trackedRegatta);
|
||||
long millisecondsOverWhichToAverageWind, Simulator simulator) {
|
||||
super(domainFactory, tractracEvent, trackedRegatta, simulator);
|
||||
this.millisecondsOverWhichToAverageWind = millisecondsOverWhichToAverageWind;
|
||||
this.delayToLiveInMillis = delayToLiveInMillis;
|
||||
this.windStore = windStore;
|
||||
if (simulator == null) {
|
||||
this.windStore = windStore;
|
||||
} else {
|
||||
this.windStore = simulator.simulatingWindStore(windStore);
|
||||
}
|
||||
this.raceDefinitionSetToUpdate = raceDefinitionSetToUpdate;
|
||||
}
|
||||
|
||||
@@ -93,8 +98,12 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<Route, RouteDa
|
||||
} else {
|
||||
logger.log(Level.INFO, "Received course for non-existing race "+event.getC().getName()+". Creating RaceDefinition.");
|
||||
// create race definition and add to event
|
||||
getDomainFactory().getOrCreateRaceDefinitionAndTrackedRace(getTrackedRegatta(), event.getC(), course,
|
||||
windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, raceDefinitionSetToUpdate);
|
||||
DynamicTrackedRace trackedRace = getDomainFactory().getOrCreateRaceDefinitionAndTrackedRace(
|
||||
getTrackedRegatta(), event.getC(), course, windStore, delayToLiveInMillis,
|
||||
millisecondsOverWhichToAverageWind, raceDefinitionSetToUpdate);
|
||||
if (getSimulator() != null) {
|
||||
getSimulator().setTrackedRace(trackedRace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -31,8 +31,9 @@ import com.tractrac.clientmodule.data.StartStopTimesData;
|
||||
public class RaceStartedAndFinishedReceiver extends AbstractReceiverWithQueue<Race, StartStopTimesData, Boolean> {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-2
@@ -21,8 +21,9 @@ public class RawPositionReceiver extends AbstractReceiverWithQueue<RaceCompetito
|
||||
|
||||
private int received;
|
||||
|
||||
public RawPositionReceiver(DynamicTrackedRegatta trackedRegatta, com.tractrac.clientmodule.Event tractracEvent, DomainFactory domainFactory) {
|
||||
super(domainFactory, tractracEvent, trackedRegatta);
|
||||
public RawPositionReceiver(DynamicTrackedRegatta trackedRegatta, com.tractrac.clientmodule.Event tractracEvent,
|
||||
DomainFactory domainFactory, Simulator simulator) {
|
||||
super(domainFactory, tractracEvent, trackedRegatta, simulator);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Regular → Executable
+84
-1
@@ -1,5 +1,88 @@
|
||||
package com.sap.sailing.domain.tractracadapter.impl;
|
||||
|
||||
public class Simulator {
|
||||
import java.util.Map;
|
||||
|
||||
import com.sap.sailing.domain.base.Timed;
|
||||
import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl;
|
||||
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.Wind;
|
||||
import com.sap.sailing.domain.tracking.WindStore;
|
||||
import com.sap.sailing.domain.tracking.WindTrack;
|
||||
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
|
||||
import com.sap.sailing.domain.tracking.impl.WindImpl;
|
||||
|
||||
public class Simulator {
|
||||
private DynamicTrackedRace trackedRace;
|
||||
private WindStore windStore;
|
||||
private long advanceInMillis;
|
||||
/**
|
||||
* Creates a wind store which replays the wind store events against a tracked race, correcting the wind fixes with
|
||||
* the simulation delay. The wind store returned is an {@link EmptyWindStore}.
|
||||
*/
|
||||
public WindStore simulatingWindStore(WindStore windStore) {
|
||||
this.windStore = windStore;
|
||||
return EmptyWindStore.INSTANCE;
|
||||
}
|
||||
|
||||
public void setTrackedRace(DynamicTrackedRace trackedRace) {
|
||||
this.trackedRace = trackedRace;
|
||||
startWindPlayer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches a thread which re-plays all wind fixes from {@link #windStore}'s
|
||||
* {@link WindStore#loadWindTracks(com.sap.sailing.domain.tracking.TrackedRegatta, com.sap.sailing.domain.tracking.TrackedRace, long)
|
||||
* loaded tracks} on {@link #trackedRace}.
|
||||
*/
|
||||
private void startWindPlayer() {
|
||||
assert this.trackedRace != null;
|
||||
assert this.windStore != null;
|
||||
for (final Map.Entry<? extends WindSource, ? extends WindTrack> 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 <code>timed</code>'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);
|
||||
}
|
||||
}
|
||||
+9
-4
@@ -148,9 +148,14 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
|
||||
/**
|
||||
*
|
||||
* @param regatta if <code>null</code>, then <code>domainFactory.getOrCreateRegatta(tractracEvent)</code> will be used to
|
||||
* obtain a default regatta
|
||||
* @param simulateWithStartTimeNow TODO
|
||||
* @param regatta
|
||||
* if <code>null</code>, then <code>domainFactory.getOrCreateRegatta(tractracEvent)</code> will be used
|
||||
* to obtain a default regatta
|
||||
* @param simulateWithStartTimeNow
|
||||
* if <code>true</code>, 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<Receiver>();
|
||||
Set<TypeController> typeControllers = new HashSet<TypeController>();
|
||||
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);
|
||||
|
||||
@@ -39,7 +39,7 @@ public interface TrackedRegatta extends Serializable {
|
||||
* if not <code>null</code>, after creating the {@link TrackedRace}, the <code>raceDefinition</code> 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);
|
||||
|
||||
|
||||
+3
-1
@@ -244,7 +244,9 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
|
||||
}
|
||||
markPassingsTimes = new ArrayList<Pair<Waypoint, Pair<TimePoint, TimePoint>>>();
|
||||
windTracks = new HashMap<WindSource, WindTrack>();
|
||||
windTracks.putAll(windStore.loadWindTracks(trackedRegatta, this, millisecondsOverWhichToAverageWind));
|
||||
final Map<? extends WindSource, ? extends WindTrack> 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.
|
||||
|
||||
+7
-5
@@ -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) {
|
||||
|
||||
+1
-1
@@ -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<Void>() {
|
||||
+ ":" + TracTracConnectionConstants.PORT_STORED, false, false, /* simulateWithStartTimeNow */ false, new AsyncCallback<Void>() {
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
|
||||
+2
-1
@@ -73,7 +73,8 @@ public class TestStoringAndRetrievingWindTracksTest extends AbstractTracTracLive
|
||||
Regatta domainEvent = domainFactory.getOrCreateDefaultRegatta(getTracTracEvent(), /* trackedRegattaRegistry */ null);
|
||||
DynamicTrackedRegatta trackedRegatta = new RacingEventServiceImpl().getOrCreateTrackedRegatta(domainEvent);
|
||||
Iterable<Receiver> 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) {
|
||||
}
|
||||
|
||||
+2
-1
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user