mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-06 19:12:23 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
fe128232d1
37 files changed
+478
-140
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, 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, 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, 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, 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, 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());
|
||||
}
|
||||
|
||||
+13
-10
@@ -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;
|
||||
@@ -107,7 +108,6 @@ public interface DomainFactory {
|
||||
* respond with the {@link RaceDefinition} when its {@link DomainFactory#getRaces(Event)} is called with the
|
||||
* TracTrac {@link Event} as argument that is used for its tracking.
|
||||
* <p>
|
||||
*
|
||||
* @param startOfTracking
|
||||
* if <code>null</code>, all stored data from the "beginning 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,
|
||||
@@ -122,16 +122,18 @@ public interface DomainFactory {
|
||||
* 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, 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
|
||||
* a predefined {@link Regatta} is used to hold the resulting races.
|
||||
*/
|
||||
RaceTracker createRaceTracker(Regatta regatta, URL paramURL, URI liveURI, URI storedURI, TimePoint startOfTracking,
|
||||
TimePoint endOfTracking, long delayToLiveInMillis, WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry)
|
||||
throws MalformedURLException, FileNotFoundException, URISyntaxException;
|
||||
TimePoint endOfTracking, long delayToLiveInMillis, boolean simulateWithStartTimeNow, WindStore windStore,
|
||||
TrackedRegattaRegistry trackedRegattaRegistry) throws MalformedURLException, FileNotFoundException,
|
||||
URISyntaxException;
|
||||
|
||||
BoatClass getOrCreateBoatClass(CompetitorClass competitorClass);
|
||||
|
||||
@@ -154,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
|
||||
@@ -179,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);
|
||||
|
||||
@@ -195,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;
|
||||
|
||||
@@ -230,7 +233,7 @@ public interface DomainFactory {
|
||||
Pair<List<com.sap.sailing.domain.base.Competitor>, BoatClass> getCompetitorsAndDominantBoatClass(Race race);
|
||||
|
||||
RaceTrackingConnectivityParameters createTrackingConnectivityParameters(URL paramURL, URI liveURI, URI storedURI,
|
||||
TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis, WindStore windStore);
|
||||
TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis, boolean simulateWithStartTimeNow, WindStore windStore);
|
||||
/**
|
||||
* Removes all knowledge about <code>tractracRace</code> which includes removing it from the race cache, from the
|
||||
* {@link com.sap.sailing.domain.base.Regatta} and, if a {@link TrackedRace} for the corresponding
|
||||
|
||||
+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;
|
||||
|
||||
+38
-25
@@ -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,
|
||||
@@ -481,18 +490,20 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
|
||||
@Override
|
||||
public TracTracRaceTracker createRaceTracker(URL paramURL, URI liveURI, URI storedURI, TimePoint startOfTracking,
|
||||
TimePoint endOfTracking, long delayToLiveInMillis, WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry)
|
||||
throws MalformedURLException, FileNotFoundException, URISyntaxException {
|
||||
TimePoint endOfTracking, long delayToLiveInMillis, boolean simulateWithStartTimeNow, WindStore windStore,
|
||||
TrackedRegattaRegistry trackedRegattaRegistry) throws MalformedURLException, FileNotFoundException,
|
||||
URISyntaxException {
|
||||
return new TracTracRaceTrackerImpl(this, paramURL, liveURI, storedURI, startOfTracking, endOfTracking, delayToLiveInMillis,
|
||||
windStore, trackedRegattaRegistry);
|
||||
simulateWithStartTimeNow, windStore, trackedRegattaRegistry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RaceTracker createRaceTracker(Regatta regatta, URL paramURL, URI liveURI, URI storedURI,
|
||||
TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis, WindStore windStore,
|
||||
TrackedRegattaRegistry trackedRegattaRegistry) throws MalformedURLException, FileNotFoundException, URISyntaxException {
|
||||
TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis,
|
||||
boolean simulateWithStartTimeNow, WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry)
|
||||
throws MalformedURLException, FileNotFoundException, URISyntaxException {
|
||||
return new TracTracRaceTrackerImpl(regatta, this, paramURL, liveURI, storedURI, startOfTracking, endOfTracking, delayToLiveInMillis,
|
||||
windStore, trackedRegattaRegistry);
|
||||
simulateWithStartTimeNow, windStore, trackedRegattaRegistry);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -507,8 +518,10 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
|
||||
@Override
|
||||
public RaceTrackingConnectivityParameters createTrackingConnectivityParameters(URL paramURL, URI liveURI,
|
||||
URI storedURI, TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis, WindStore windStore) {
|
||||
return new RaceTrackingConnectivityParametersImpl(paramURL, liveURI, storedURI, startOfTracking, endOfTracking, delayToLiveInMillis, windStore, this);
|
||||
URI storedURI, TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis,
|
||||
boolean simulateWithStartTimeNow, WindStore windStore) {
|
||||
return new RaceTrackingConnectivityParametersImpl(paramURL, liveURI, storedURI, startOfTracking, endOfTracking,
|
||||
delayToLiveInMillis, simulateWithStartTimeNow, windStore, this);
|
||||
}
|
||||
|
||||
}
|
||||
+8
-4
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,8 +90,12 @@ public class MarkPassingReceiver extends AbstractReceiverWithQueue<RaceCompetito
|
||||
markPassings.add(passing);
|
||||
}
|
||||
}
|
||||
trackedRace.updateMarkPassings(getDomainFactory().getOrCreateCompetitor(event.getA().getCompetitor()),
|
||||
markPassings);
|
||||
if (getSimulator() != null) {
|
||||
getSimulator().delayMarkPassings(getDomainFactory().getOrCreateCompetitor(event.getA().getCompetitor()), markPassings);
|
||||
} else {
|
||||
trackedRace.updateMarkPassings(getDomainFactory().getOrCreateCompetitor(event.getA().getCompetitor()),
|
||||
markPassings);
|
||||
}
|
||||
} else {
|
||||
logger.warning("Couldn't find tracked race for race " + event.getA().getRace().getName()
|
||||
+ ". Dropping mark passing event " + event);
|
||||
|
||||
+12
-6
@@ -7,15 +7,16 @@ import java.util.logging.Logger;
|
||||
import com.maptrack.client.io.TypeController;
|
||||
import com.sap.sailing.domain.base.Buoy;
|
||||
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.TimePoint;
|
||||
import com.sap.sailing.domain.common.impl.Util.Triple;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
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.GPSFixTrack;
|
||||
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.tractracadapter.DomainFactory;
|
||||
import com.tractrac.clientmodule.ControlPoint;
|
||||
import com.tractrac.clientmodule.Race;
|
||||
@@ -67,8 +68,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
|
||||
@@ -111,7 +112,12 @@ public class MarkPositionReceiver extends AbstractReceiverWithQueue<ControlPoint
|
||||
for (Race tractracRace : getTracTracEvent().getRaceList()) {
|
||||
DynamicTrackedRace trackedRace = getTrackedRace(tractracRace);
|
||||
if (trackedRace != null) {
|
||||
trackedRace.recordFix(buoy, getDomainFactory().createGPSFixMoving(event.getB()));
|
||||
GPSFixMoving markPosition = getDomainFactory().createGPSFixMoving(event.getB());
|
||||
if (getSimulator() != null) {
|
||||
getSimulator().scheduleMarkPosition(buoy, markPosition);
|
||||
} else {
|
||||
trackedRace.recordFix(buoy, markPosition);
|
||||
}
|
||||
} else {
|
||||
logger.warning("Couldn't find tracked race for race " + tractracRace.getName()
|
||||
+ ". Dropping mark position event " + event);
|
||||
|
||||
+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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+17
-9
@@ -7,12 +7,13 @@ 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.base.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.impl.Util.Triple;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
import com.sap.sailing.domain.tractracadapter.DomainFactory;
|
||||
import com.tractrac.clientmodule.Race;
|
||||
import com.tractrac.clientmodule.data.ICallbackData;
|
||||
@@ -31,8 +32,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,13 +64,19 @@ public class RaceStartedAndFinishedReceiver extends AbstractReceiverWithQueue<Ra
|
||||
DynamicTrackedRace trackedRace = getTrackedRace(event.getA());
|
||||
if (trackedRace != null) {
|
||||
StartStopTimesData startStopTimesData = event.getB();
|
||||
if(startStopTimesData != null) {
|
||||
if(startStopTimesData.getStartTime() > 0) {
|
||||
MillisecondsTimePoint startOfTracking = new MillisecondsTimePoint(startStopTimesData.getStartTime());
|
||||
if (startStopTimesData != null) {
|
||||
final long startTime = startStopTimesData.getStartTime();
|
||||
TimePoint startOfTracking = getSimulator() == null ?
|
||||
new MillisecondsTimePoint(startTime) :
|
||||
getSimulator().advance(new MillisecondsTimePoint(startTime));
|
||||
if (startTime > 0) {
|
||||
trackedRace.setStartOfTrackingReceived(startOfTracking);
|
||||
}
|
||||
if(startStopTimesData.getStopTime() > 0) {
|
||||
MillisecondsTimePoint endOfTracking = new MillisecondsTimePoint(startStopTimesData.getStopTime());
|
||||
final long stopTime = startStopTimesData.getStopTime();
|
||||
TimePoint endOfTracking = getSimulator() == null ?
|
||||
new MillisecondsTimePoint(stopTime) :
|
||||
getSimulator().advance(new MillisecondsTimePoint(stopTime));
|
||||
if (stopTime > 0) {
|
||||
trackedRace.setEndOfTrackingReceived(endOfTracking);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-4
@@ -24,9 +24,11 @@ public class RaceTrackingConnectivityParametersImpl implements RaceTrackingConne
|
||||
private final WindStore windStore;
|
||||
private final DomainFactory domainFactory;
|
||||
private final long delayToLiveInMillis;
|
||||
private final boolean simulateWithStartTimeNow;
|
||||
|
||||
public RaceTrackingConnectivityParametersImpl(URL paramURL, URI liveURI, URI storedURI,
|
||||
TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis, WindStore windStore, DomainFactory domainFactory) {
|
||||
public RaceTrackingConnectivityParametersImpl(URL paramURL, URI liveURI, URI storedURI, TimePoint startOfTracking,
|
||||
TimePoint endOfTracking, long delayToLiveInMillis, boolean simulateWithStartTimeNow, WindStore windStore,
|
||||
DomainFactory domainFactory) {
|
||||
super();
|
||||
this.paramURL = paramURL;
|
||||
this.liveURI = liveURI;
|
||||
@@ -36,13 +38,14 @@ public class RaceTrackingConnectivityParametersImpl implements RaceTrackingConne
|
||||
this.delayToLiveInMillis = delayToLiveInMillis;
|
||||
this.windStore = windStore;
|
||||
this.domainFactory = domainFactory;
|
||||
this.simulateWithStartTimeNow = simulateWithStartTimeNow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RaceTracker createRaceTracker(TrackedRegattaRegistry trackedRegattaRegistry) throws MalformedURLException,
|
||||
FileNotFoundException, URISyntaxException {
|
||||
RaceTracker tracker = domainFactory.createRaceTracker(paramURL, liveURI, storedURI, startOfTracking,
|
||||
endOfTracking, delayToLiveInMillis, windStore, trackedRegattaRegistry);
|
||||
endOfTracking, delayToLiveInMillis, simulateWithStartTimeNow, windStore, trackedRegattaRegistry);
|
||||
return tracker;
|
||||
}
|
||||
|
||||
@@ -50,7 +53,7 @@ public class RaceTrackingConnectivityParametersImpl implements RaceTrackingConne
|
||||
public RaceTracker createRaceTracker(Regatta regatta, TrackedRegattaRegistry trackedRegattaRegistry)
|
||||
throws Exception {
|
||||
RaceTracker tracker = domainFactory.createRaceTracker(regatta, paramURL, liveURI, storedURI, startOfTracking,
|
||||
endOfTracking, delayToLiveInMillis, windStore, trackedRegattaRegistry);
|
||||
endOfTracking, delayToLiveInMillis, simulateWithStartTimeNow, windStore, trackedRegattaRegistry);
|
||||
return tracker;
|
||||
}
|
||||
|
||||
|
||||
+8
-2
@@ -10,6 +10,7 @@ import com.sap.sailing.domain.common.impl.Util.Triple;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.tracking.impl.GPSFixMovingImpl;
|
||||
import com.sap.sailing.domain.tractracadapter.DomainFactory;
|
||||
import com.tractrac.clientmodule.Race;
|
||||
import com.tractrac.clientmodule.RaceCompetitor;
|
||||
@@ -21,8 +22,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,6 +60,10 @@ public class RawPositionReceiver extends AbstractReceiverWithQueue<RaceCompetito
|
||||
DynamicTrackedRace trackedRace = getTrackedRace(race);
|
||||
if (trackedRace != null) {
|
||||
GPSFixMoving fix = getDomainFactory().createGPSFixMoving(event.getB());
|
||||
if (getSimulator() != null) {
|
||||
fix = new GPSFixMovingImpl(fix.getPosition(), getSimulator().delay(
|
||||
fix.getTimePoint()), fix.getSpeed());
|
||||
}
|
||||
Competitor competitor = getDomainFactory().getOrCreateCompetitor(event.getA().getCompetitor());
|
||||
trackedRace.recordFix(competitor, fix);
|
||||
} else {
|
||||
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
package com.sap.sailing.domain.tractracadapter.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.base.Buoy;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
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.GPSFixMoving;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
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.GPSFixMovingImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.MarkPassingImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.WindImpl;
|
||||
|
||||
public class Simulator {
|
||||
private static final Logger logger = Logger.getLogger(Simulator.class.getName());
|
||||
|
||||
private DynamicTrackedRace trackedRace;
|
||||
private WindStore windStore;
|
||||
private long advanceInMillis = -1;
|
||||
private Timer timer = new Timer("Timer for TracTrac Simulator");
|
||||
|
||||
/**
|
||||
* 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 synchronized void setTrackedRace(DynamicTrackedRace trackedRace) {
|
||||
this.trackedRace = trackedRace;
|
||||
startWindPlayer();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is what everybody is waiting for :-). Notifies all waiters.
|
||||
*/
|
||||
public synchronized void setAdvanceInMillis(long advanceInMillis) {
|
||||
this.advanceInMillis = advanceInMillis;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.getTimePoint());
|
||||
return new WindImpl(wind.getPosition(), delayedTimePoint, new KnotSpeedWithBearingImpl(wind.getKnots(), wind.getBearing()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits until {@link #advanceInMillis} is set to something not equal to -1 which is its initial value. Unblocked by
|
||||
* {@link #setAdvanceInMillis(long)}.
|
||||
*/
|
||||
private synchronized long getAdvanceInMillis() {
|
||||
while (advanceInMillis == -1) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
logger.throwing(Simulator.class.getName(), "getAdvanceInMillis", e);
|
||||
// ignore; try again
|
||||
}
|
||||
}
|
||||
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."
|
||||
*/
|
||||
public TimePoint delay(TimePoint timePoint) {
|
||||
TimePoint transformedTimed = advance(timePoint);
|
||||
long waitTimeInMillis = getWaitTimeInMillisUntil(transformedTimed);
|
||||
do {
|
||||
if (waitTimeInMillis > 0) {
|
||||
try {
|
||||
Thread.sleep(waitTimeInMillis);
|
||||
waitTimeInMillis = 0;
|
||||
} catch (InterruptedException e) {
|
||||
// try again:
|
||||
waitTimeInMillis = transformedTimed.asMillis() - System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
} while (waitTimeInMillis > 0);
|
||||
return transformedTimed;
|
||||
}
|
||||
|
||||
private long getWaitTimeInMillisUntil(TimePoint transformedTimepoint) {
|
||||
long now = System.currentTimeMillis();
|
||||
long waitTimeInMillis = transformedTimepoint.asMillis() - now;
|
||||
return waitTimeInMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #delay}, only that it doesn't wait until <code>timePoint</code> is reached in wall time.
|
||||
*/
|
||||
public TimePoint advance(TimePoint timePoint) {
|
||||
return new MillisecondsTimePoint(timePoint.asMillis()+getAdvanceInMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* If {@link #advanceInMillis} is already set to a non-negative value, it is left alone, and {@link #delay(TimePoint)} is called.
|
||||
* Otherwise, <code>time</code> is taken to be the original start time of the race which is then used to compute
|
||||
* {@link #advanceInMillis} such that <code>time.asMillis() + advanceInMillis == System.currentTimeMillis()</code>.
|
||||
*/
|
||||
public TimePoint advanceMarkPassingTimePoint(TimePoint time) {
|
||||
if (isAdvanceInMilliseSet()) {
|
||||
return advance(time);
|
||||
} else {
|
||||
setAdvanceInMillis(System.currentTimeMillis() - time.asMillis());
|
||||
return advance(time);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAdvanceInMilliseSet() {
|
||||
return advanceInMillis != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delivers those mark passings for which we don't have to wait as a single list to the {@link #trackedRace} now.
|
||||
* The remaining mark passings are delayed as long as it takes for the first mark passing with a positive wait time
|
||||
* to match "now." The whole list is then re-submitted to this same method.
|
||||
*/
|
||||
public void delayMarkPassings(final Competitor competitor, List<MarkPassing> markPassings) {
|
||||
List<MarkPassing> deliverTransformedNow = new ArrayList<MarkPassing>();
|
||||
final List<MarkPassing> deliverLater = new ArrayList<MarkPassing>();
|
||||
Iterator<MarkPassing> i = markPassings.iterator();
|
||||
if (i.hasNext()) {
|
||||
MarkPassing markPassing = i.next();
|
||||
deliverLater.add(markPassing);
|
||||
TimePoint transformedTimepoint = advanceMarkPassingTimePoint(markPassing.getTimePoint());
|
||||
while (getWaitTimeInMillisUntil(transformedTimepoint) <= 0 && markPassing != null) {
|
||||
MarkPassing transformedMarkPassing = new MarkPassingImpl(transformedTimepoint,
|
||||
markPassing.getWaypoint(), markPassing.getCompetitor());
|
||||
deliverTransformedNow.add(transformedMarkPassing);
|
||||
if (i.hasNext()) {
|
||||
markPassing = i.next();
|
||||
transformedTimepoint = advanceMarkPassingTimePoint(markPassing.getTimePoint());
|
||||
deliverLater.add(markPassing);
|
||||
} else {
|
||||
markPassing = null;
|
||||
}
|
||||
}
|
||||
trackedRace.updateMarkPassings(competitor, deliverTransformedNow);
|
||||
if (markPassing != null) {
|
||||
// not consumed and delivered all mark passings now
|
||||
while (i.hasNext()) {
|
||||
deliverLater.add(i.next());
|
||||
}
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
delayMarkPassings(competitor, deliverLater);
|
||||
} catch (Throwable t) {
|
||||
logger.throwing(Simulator.class.getName(), "scheduleMarkPosition", t);
|
||||
}
|
||||
}
|
||||
}, transformedTimepoint.asDate());
|
||||
}
|
||||
} else {
|
||||
// deliver an empty list now
|
||||
trackedRace.updateMarkPassings(competitor, markPassings);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void scheduleMarkPosition(final Buoy buoy, GPSFixMoving markFix) {
|
||||
final TimePoint transformedTimepoint = advance(markFix.getTimePoint());
|
||||
final GPSFixMoving transformedMarkFix = new GPSFixMovingImpl(markFix.getPosition(), transformedTimepoint, markFix.getSpeed());
|
||||
long waitTime = getWaitTimeInMillisUntil(transformedMarkFix.getTimePoint());
|
||||
if (waitTime <= 0) {
|
||||
trackedRace.recordFix(buoy, transformedMarkFix);
|
||||
} else {
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
trackedRace.recordFix(buoy, transformedMarkFix);
|
||||
} catch (Throwable t) {
|
||||
logger.throwing(Simulator.class.getName(), "scheduleMarkPosition", t);
|
||||
}
|
||||
}
|
||||
}, transformedTimepoint.asDate());
|
||||
}
|
||||
}
|
||||
}
|
||||
+22
-16
@@ -100,7 +100,6 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
* respond with the {@link RaceDefinition} when its {@link DomainFactory#getRaces(Event)} is called with the
|
||||
* TracTrac {@link Event} as argument that is used for its tracking.
|
||||
* <p>
|
||||
*
|
||||
* @param startOfTracking
|
||||
* if <code>null</code>, all stored data from the "beginning 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,
|
||||
@@ -109,6 +108,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
* 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
|
||||
@@ -117,19 +117,19 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
* used to create the {@link TrackedRegatta} for the domain event
|
||||
*/
|
||||
protected TracTracRaceTrackerImpl(DomainFactory domainFactory, URL paramURL, URI liveURI, URI storedURI,
|
||||
TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis, WindStore windStore,
|
||||
TrackedRegattaRegistry trackedRegattaRegistry) throws URISyntaxException, MalformedURLException,
|
||||
FileNotFoundException {
|
||||
this(KeyValue.setup(paramURL), domainFactory, paramURL, liveURI, storedURI, startOfTracking, endOfTracking, delayToLiveInMillis, windStore,
|
||||
trackedRegattaRegistry);
|
||||
TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis,
|
||||
boolean simulateWithStartTimeNow, WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry)
|
||||
throws URISyntaxException, MalformedURLException, FileNotFoundException {
|
||||
this(KeyValue.setup(paramURL), domainFactory, paramURL, liveURI, storedURI, startOfTracking, endOfTracking,
|
||||
delayToLiveInMillis, simulateWithStartTimeNow, windStore, trackedRegattaRegistry);
|
||||
}
|
||||
|
||||
private TracTracRaceTrackerImpl(Event tractracEvent, DomainFactory domainFactory, URL paramURL, URI liveURI, URI storedURI,
|
||||
TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis, WindStore windStore,
|
||||
TrackedRegattaRegistry trackedRegattaRegistry) throws URISyntaxException, MalformedURLException,
|
||||
TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis, boolean simulateWithStartTimeNow,
|
||||
WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry) throws URISyntaxException, MalformedURLException,
|
||||
FileNotFoundException {
|
||||
this(tractracEvent, null, domainFactory, paramURL, liveURI, storedURI,
|
||||
startOfTracking, endOfTracking, delayToLiveInMillis, windStore, trackedRegattaRegistry);
|
||||
startOfTracking, endOfTracking, delayToLiveInMillis, simulateWithStartTimeNow, windStore, trackedRegattaRegistry);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,21 +139,27 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
* always be what you want.
|
||||
*/
|
||||
protected TracTracRaceTrackerImpl(Regatta regatta, DomainFactory domainFactory, URL paramURL, URI liveURI, URI storedURI,
|
||||
TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis, WindStore windStore,
|
||||
TrackedRegattaRegistry trackedRegattaRegistry) throws URISyntaxException, MalformedURLException,
|
||||
TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis, boolean simulateWithStartTimeNow,
|
||||
WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry) throws URISyntaxException, MalformedURLException,
|
||||
FileNotFoundException {
|
||||
this(KeyValue.setup(paramURL), regatta, domainFactory, paramURL, liveURI, storedURI, startOfTracking,
|
||||
endOfTracking, delayToLiveInMillis, windStore, trackedRegattaRegistry);
|
||||
endOfTracking, delayToLiveInMillis, simulateWithStartTimeNow, windStore, trackedRegattaRegistry);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param regatta if <code>null</code>, then <code>domainFactory.getOrCreateRegatta(tractracEvent)</code> will be used to
|
||||
* obtain a default regatta
|
||||
* @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,
|
||||
long delayToLiveInMillis, WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry)
|
||||
long delayToLiveInMillis, boolean simulateWithStartTimeNow, WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry)
|
||||
throws URISyntaxException, MalformedURLException, FileNotFoundException {
|
||||
super();
|
||||
this.tractracEvent = tractracEvent;
|
||||
@@ -192,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);
|
||||
|
||||
@@ -33,11 +33,11 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
*/
|
||||
public interface RaceTracker {
|
||||
/**
|
||||
* By default, wait five minutes for race data; sometimes, a tracking provider's server may be under heavy load and
|
||||
* By default, wait half a minute for race data; sometimes, a tracking provider's server may be under heavy load and
|
||||
* may serve races one after another. If many races are requested concurrently, this can lead to a queue
|
||||
* of several minutes length.
|
||||
*/
|
||||
static long TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS = 300000;
|
||||
static long TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS = 30000;
|
||||
|
||||
/**
|
||||
* Stops tracking the races.
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+2
-2
@@ -232,7 +232,7 @@ public class TrackBasedEstimationWindTrackImpl extends VirtualWindTrackImpl impl
|
||||
if (!scheduledInvalidationInterval.isSet()) {
|
||||
// according to the invariant this implies [1]==null
|
||||
scheduledInvalidationInterval.set(startOfInvalidation, endOfInvalidation);
|
||||
startSchedulerForInvalidation();
|
||||
startSchedulerForCacheRefresh();
|
||||
} else {
|
||||
// this means that an invalidation is already scheduled; as long as we're synchronized on scheduledInvalidationInterval
|
||||
// we can safely extend the interval; the invalidation won't start before we release the lock
|
||||
@@ -274,7 +274,7 @@ public class TrackBasedEstimationWindTrackImpl extends VirtualWindTrackImpl impl
|
||||
}
|
||||
}
|
||||
|
||||
private void startSchedulerForInvalidation() {
|
||||
private void startSchedulerForCacheRefresh() {
|
||||
synchronized (scheduledInvalidationInterval) {
|
||||
if (delayForCacheInvalidationInMilliseconds == 0) {
|
||||
invalidateCache();
|
||||
|
||||
+14
-7
@@ -4,6 +4,7 @@ import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -39,13 +40,13 @@ import com.sap.sailing.domain.base.impl.MeterDistance;
|
||||
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
|
||||
import com.sap.sailing.domain.common.LegType;
|
||||
import com.sap.sailing.domain.common.ManeuverType;
|
||||
import com.sap.sailing.domain.common.NoWindError;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
@@ -66,10 +67,10 @@ import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.GPSTrackListener;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.Wind;
|
||||
import com.sap.sailing.domain.tracking.WindStore;
|
||||
import com.sap.sailing.domain.tracking.WindTrack;
|
||||
@@ -243,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.
|
||||
@@ -875,7 +878,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
|
||||
.createWindAverager(timeWeigherThatPretendsToAlsoWeighPositions);
|
||||
List<WindWithConfidence<Pair<Position, TimePoint>>> windFixesWithConfidences = new ArrayList<WindWithConfidence<Pair<Position, TimePoint>>>();
|
||||
for (WindSource windSource : getWindSources()) {
|
||||
// TODO consider parallelizing
|
||||
// TODO consider parallelizing and consider caching
|
||||
if (!Util.contains(windSourcesToExclude, windSource)) {
|
||||
WindTrack track = getOrCreateWindTrack(windSource);
|
||||
WindWithConfidence<Pair<Position, TimePoint>> windWithConfidence = track.getAveragedWindWithConfidence(p, at);
|
||||
@@ -1659,8 +1662,12 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
|
||||
|
||||
@Override
|
||||
public Iterable<WindSource> getWindSources() {
|
||||
synchronized (windTracks) {
|
||||
return new ArrayList<WindSource>(windTracks.keySet());
|
||||
while (true) {
|
||||
try {
|
||||
return new ArrayList<WindSource>(windTracks.keySet());
|
||||
} catch (ConcurrentModificationException cme) {
|
||||
logger.info("Caught " + cme + "; trying again.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+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) {
|
||||
|
||||
+15
-2
@@ -2,6 +2,8 @@ package com.sap.sailing.domain.tracking.impl;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
@@ -21,10 +23,12 @@ import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
public class WindwardToGoComparator implements Comparator<TrackedLegOfCompetitor> {
|
||||
private final TrackedLeg trackedLeg;
|
||||
private final TimePoint timePoint;
|
||||
private final Map<TrackedLegOfCompetitor, Distance> wwdtgCache;
|
||||
|
||||
public WindwardToGoComparator(TrackedLeg trackedLeg, TimePoint timePoint) {
|
||||
this.trackedLeg = trackedLeg;
|
||||
this.timePoint = timePoint;
|
||||
wwdtgCache = new HashMap<TrackedLegOfCompetitor, Distance>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,8 +49,8 @@ public class WindwardToGoComparator implements Comparator<TrackedLegOfCompetitor
|
||||
// both didn't finish the leg yet; check which one has started:
|
||||
if (o1.hasStartedLeg(timePoint)) {
|
||||
if (o2.hasStartedLeg(timePoint)) {
|
||||
Distance o1d = o1.getWindwardDistanceToGo(timePoint);
|
||||
Distance o2d = o2.getWindwardDistanceToGo(timePoint);
|
||||
Distance o1d = getWindwardDistanceToGo(o1);
|
||||
Distance o2d = getWindwardDistanceToGo(o2);
|
||||
result = o1d==null?(o2d==null?0:1):o2d==null?1:o1d.compareTo(o2d); // smaller distance to go means smaller rank
|
||||
} else {
|
||||
result = -1;
|
||||
@@ -63,4 +67,13 @@ public class WindwardToGoComparator implements Comparator<TrackedLegOfCompetitor
|
||||
throw new NoWindError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Distance getWindwardDistanceToGo(TrackedLegOfCompetitor o1) throws NoWindException {
|
||||
Distance result = wwdtgCache.get(o1);
|
||||
if (result == null) {
|
||||
result = o1.getWindwardDistanceToGo(timePoint);
|
||||
wwdtgCache.put(o1, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+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, new AsyncCallback<Void>() {
|
||||
+ ":" + TracTracConnectionConstants.PORT_STORED, false, false, /* simulateWithStartTimeNow */ false, new AsyncCallback<Void>() {
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
|
||||
+9
-4
@@ -346,6 +346,11 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
|
||||
declinationCheckbox.setValue(true);
|
||||
trackPanel.add(declinationCheckbox);
|
||||
|
||||
final CheckBox simulateWithStartTimeNow = new CheckBox(stringMessages.simulateWithStartTimeNow());
|
||||
simulateWithStartTimeNow.setWordWrap(false);
|
||||
simulateWithStartTimeNow.setValue(false);
|
||||
trackPanel.add(simulateWithStartTimeNow);
|
||||
|
||||
trackedRacesPanel.add(trackedRacesListComposite);
|
||||
|
||||
HorizontalPanel racesButtonPanel = new HorizontalPanel();
|
||||
@@ -357,7 +362,7 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
|
||||
btnTrack.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
trackSelectedRaces(trackWindCheckbox.getValue(), declinationCheckbox.getValue());
|
||||
trackSelectedRaces(trackWindCheckbox.getValue(), declinationCheckbox.getValue(), simulateWithStartTimeNow.getValue());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -490,18 +495,18 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
|
||||
});
|
||||
}
|
||||
|
||||
private void trackSelectedRaces(boolean trackWind, boolean correctWindByDeclination) {
|
||||
private void trackSelectedRaces(boolean trackWind, boolean correctWindByDeclination, final boolean simulateWithStartTimeNow) {
|
||||
String liveURI = liveURIBox.getValue();
|
||||
String storedURI = storedURIBox.getValue();
|
||||
RegattaDTO selectedRegatta = getSelectedRegatta();
|
||||
RegattaIdentifier regattaIdentifier = null;
|
||||
if(selectedRegatta != null) {
|
||||
if (selectedRegatta != null) {
|
||||
regattaIdentifier = new RegattaName(selectedRegatta.name);
|
||||
}
|
||||
for (final TracTracRaceRecordDTO rr : raceList.getList()) {
|
||||
if (raceTable.getSelectionModel().isSelected(rr)) {
|
||||
sailingService.trackWithTracTrac(regattaIdentifier, rr, liveURI, storedURI, trackWind,
|
||||
correctWindByDeclination, new AsyncCallback<Void>() {
|
||||
correctWindByDeclination, simulateWithStartTimeNow, new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Error trying to register race " + rr.name + " for tracking: "
|
||||
|
||||
+2
-1
@@ -57,7 +57,8 @@ public interface SailingService extends RemoteService {
|
||||
|
||||
Pair<String, List<TracTracRaceRecordDTO>> listTracTracRacesInEvent(String eventJsonURL) throws Exception;
|
||||
|
||||
void trackWithTracTrac(RegattaIdentifier regattaToAddTo, TracTracRaceRecordDTO rr, String liveURI, String storedURI, boolean trackWind, boolean correctWindByDeclination) throws Exception;
|
||||
void trackWithTracTrac(RegattaIdentifier regattaToAddTo, TracTracRaceRecordDTO rr, String liveURI,
|
||||
String storedURI, boolean trackWind, boolean correctWindByDeclination, boolean simulateWithStartTimeNow) throws Exception;
|
||||
|
||||
void trackWithSwissTiming(RegattaIdentifier regattaToAddTo, SwissTimingRaceRecordDTO rr, String hostname, int port,
|
||||
boolean canSendRequests, boolean trackWind, boolean correctWindByDeclination) throws Exception;
|
||||
|
||||
+6
-1
@@ -64,13 +64,18 @@ public interface SailingServiceAsync {
|
||||
* @param liveURI
|
||||
* may be <code>null</code> or the empty string in which case the server will use the
|
||||
* {@link TracTracRaceRecordDTO#liveURI} from the <code>rr</code> race record.
|
||||
* @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.
|
||||
* @param storedURImay
|
||||
* be <code>null</code> or the empty string in which case the server will use the
|
||||
* {@link TracTracRaceRecordDTO#storedURI} from the <code>rr</code> race record.
|
||||
*/
|
||||
void trackWithTracTrac(RegattaIdentifier regattaToAddTo,
|
||||
TracTracRaceRecordDTO rr, String liveURI, String storedURI, boolean trackWind, boolean correctWindByDeclination,
|
||||
AsyncCallback<Void> callback);
|
||||
boolean simulateWithStartTimeNow, AsyncCallback<Void> callback);
|
||||
|
||||
void getPreviousTracTracConfigurations(AsyncCallback<List<TracTracConfigurationDTO>> callback);
|
||||
|
||||
|
||||
+1
@@ -334,4 +334,5 @@ public interface StringMessages extends Messages {
|
||||
String successfullyUpdatedScores();
|
||||
String errorUpdatingScoresForLeaderboard(String leaderboardName, String message);
|
||||
String maneuverTypesToShowWhenCompetitorIsClicked();
|
||||
String simulateWithStartTimeNow();
|
||||
}
|
||||
+2
-1
@@ -330,4 +330,5 @@ selectAll=Select all
|
||||
apply=Apply
|
||||
successfullyUpdatedScores=Successfully updated scores
|
||||
errorUpdatingScoresForLeaderboard=Error updating scores for leaderboard {0}: {1}
|
||||
maneuverTypesToShowWhenCompetitorIsClicked=Maneuver types to show when competitor is clicked
|
||||
maneuverTypesToShowWhenCompetitorIsClicked=Maneuver types to show when competitor is clicked
|
||||
simulateWithStartTimeNow=Simulate with "now" as start time
|
||||
+2
-1
@@ -331,4 +331,5 @@ selectAll=Alle auswählen
|
||||
apply=Übernehmen
|
||||
successfullyUpdatedScores=Ergebnisse erfolgreich aktualisiert
|
||||
errorUpdatingScoresForLeaderboard=Fehler beim Aktualisieren der Ergebnisse für {0}: {1}
|
||||
maneuverTypesToShowWhenCompetitorIsClicked=Anzuzeigende Manövertypen für angeklickte Segler
|
||||
maneuverTypesToShowWhenCompetitorIsClicked=Anzuzeigende Manövertypen für angeklickte Segler
|
||||
simulateWithStartTimeNow=Simulieren mit "jetzt" als Startzeit
|
||||
+2
-2
@@ -609,7 +609,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
|
||||
@Override
|
||||
public void trackWithTracTrac(RegattaIdentifier regattaToAddTo, TracTracRaceRecordDTO rr, String liveURI, String storedURI,
|
||||
boolean trackWind, final boolean correctWindByDeclination) throws Exception {
|
||||
boolean trackWind, final boolean correctWindByDeclination, final boolean simulateWithStartTimeNow) throws Exception {
|
||||
if (liveURI == null || liveURI.trim().length() == 0) {
|
||||
liveURI = rr.liveURI;
|
||||
}
|
||||
@@ -620,7 +620,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
new URI(liveURI), new URI(storedURI), new MillisecondsTimePoint(rr.trackingStartTime),
|
||||
new MillisecondsTimePoint(rr.trackingEndTime),
|
||||
MongoWindStoreFactory.INSTANCE.getMongoWindStore(mongoObjectFactory, domainObjectFactory),
|
||||
RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS);
|
||||
RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS, simulateWithStartTimeNow);
|
||||
if (trackWind) {
|
||||
new Thread("Wind tracking starter for race "+rr.regattaName+"/"+rr.name) {
|
||||
public void run() {
|
||||
|
||||
Binary file not shown.
+1
-1
@@ -24,7 +24,7 @@ public class ResultListImpl extends AbstractNodeWrapper implements ResultList {
|
||||
|
||||
private final String sourceName;
|
||||
|
||||
private static final SimpleDateFormat df = new SimpleDateFormat("dd. MMM yyyy hh:mm", Locale.GERMAN);
|
||||
private static final SimpleDateFormat df = new SimpleDateFormat("dd. MMM yyyy HH:mm", Locale.GERMAN);
|
||||
|
||||
public ResultListImpl(Node node, String sourceName) {
|
||||
super(node);
|
||||
|
||||
+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, EmptyWindStore.INSTANCE);
|
||||
liveURI, storedURI, startOfTracking, endOfTracking, /* delayToLiveInMillis */
|
||||
0l, /* simulateWithStartTimeNow */false, EmptyWindStore.INSTANCE);
|
||||
}
|
||||
|
||||
private void startTracking() throws Exception, InterruptedException {
|
||||
|
||||
@@ -147,7 +147,8 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
|
||||
* to add the races to. Otherwise, a default regatta as described above will be created and used.
|
||||
*/
|
||||
RacesHandle addTracTracRace(RegattaIdentifier regattaToAddTo, URL paramURL, URI liveURI, URI storedURI,
|
||||
TimePoint trackingStartTime, TimePoint trackingEndTime, WindStore windStore, long timeoutForReceivingRaceDefinitionInMilliseconds)
|
||||
TimePoint trackingStartTime, TimePoint trackingEndTime, WindStore windStore,
|
||||
long timeoutForReceivingRaceDefinitionInMilliseconds, boolean simulateWithStartTimeNow)
|
||||
throws MalformedURLException, FileNotFoundException, URISyntaxException, Exception;
|
||||
|
||||
/**
|
||||
|
||||
+6
-6
@@ -577,10 +577,10 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
|
||||
public synchronized RacesHandle addTracTracRace(URL paramURL, URI liveURI, URI storedURI, WindStore windStore,
|
||||
long timeoutInMilliseconds) throws Exception {
|
||||
return addRace(
|
||||
/* regattaToAddTo */ null,
|
||||
getDomainFactory().createTrackingConnectivityParameters(paramURL, liveURI, storedURI,
|
||||
/* startOfTracking */ null,
|
||||
/* endOfTracking */null, delayToLiveInMillis, windStore), windStore, timeoutInMilliseconds);
|
||||
/* regattaToAddTo */null, getDomainFactory().createTrackingConnectivityParameters(paramURL, liveURI, storedURI,
|
||||
/* startOfTracking */null,
|
||||
/* endOfTracking */null, delayToLiveInMillis, /* simulateWithStartTimeNow */false, windStore), windStore,
|
||||
timeoutInMilliseconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -726,9 +726,9 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
|
||||
@Override
|
||||
public synchronized RacesHandle addTracTracRace(RegattaIdentifier regattaToAddTo, URL paramURL, URI liveURI,
|
||||
URI storedURI, TimePoint startOfTracking, TimePoint endOfTracking,
|
||||
WindStore windStore, long timeoutInMilliseconds) throws Exception {
|
||||
WindStore windStore, long timeoutInMilliseconds, boolean simulateWithStartTimeNow) throws Exception {
|
||||
return addRace(regattaToAddTo, getDomainFactory().createTrackingConnectivityParameters(paramURL, liveURI, storedURI, startOfTracking,
|
||||
endOfTracking, delayToLiveInMillis, windStore), windStore, timeoutInMilliseconds);
|
||||
endOfTracking, delayToLiveInMillis, simulateWithStartTimeNow, windStore), windStore, timeoutInMilliseconds);
|
||||
}
|
||||
|
||||
private void ensureRegattaIsObservedForDefaultLeaderboardAndAutoLeaderboardLinking(DynamicTrackedRegatta trackedRegatta) {
|
||||
|
||||
Reference in new issue
Block a user