mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-04 19:33:52 +00:00
added RaceHandle return to addRace so clients can identify what they are tracking
Started working on a server test that works towards starting and stopping trackers for the same race / event, asserting that tracking structures are cleared in between
This commit is contained in:
1 parent
5354ba7e3f
commit
1e47a20edc
18 files changed
+222
-29
No files matched your search
@@ -0,0 +1,3 @@
|
||||
#Fri Jun 10 21:39:55 CEST 2011
|
||||
eclipse.preferences.version=1
|
||||
encoding//src/com/sap/sailing/domain/test/WindTest.java=UTF-8
|
||||
+9
-1
@@ -81,7 +81,10 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest {
|
||||
}
|
||||
});
|
||||
addListenersForStoredDataAndStartController(receivers);
|
||||
race = domainFactory.getRaceDefinition(getEvent().getRaceList().iterator().next());
|
||||
Race tractracRace = getEvent().getRaceList().iterator().next();
|
||||
// now we expect that there is no
|
||||
assertNull(domainFactory.getExistingRaceDefinitionForRace(tractracRace));
|
||||
race = domainFactory.getRaceDefinition(tractracRace);
|
||||
course = race.getCourse();
|
||||
assertNotNull(course);
|
||||
assertEquals(3, Util.size(course.getWaypoints()));
|
||||
@@ -91,6 +94,11 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest {
|
||||
assertEquals("top", course.getLegs().get(1).getFrom().getName());
|
||||
}
|
||||
|
||||
private void assertNull(RaceDefinition existingRaceDefinitionForRace) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the race course's legs have corresponding {@link TrackedLeg}s and the {@link TrackedLeg}s have
|
||||
* {@link TrackedLegOfCompetitor} for each of the race's competitors.
|
||||
|
||||
+5
@@ -117,6 +117,11 @@ public interface DomainFactory {
|
||||
DynamicTrackedRace trackRace(TrackedEvent trackedEvent, RaceDefinition raceDefinition,
|
||||
WindStore windStore, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, Event tractracEvent);
|
||||
|
||||
/**
|
||||
* Non-blocking call that returns <code>null</code> if the {@link RaceDefinition} for the TracTrac Event
|
||||
* hasn't been created yet, e.g., because the course definition hasn't been received yet or the listener
|
||||
* for receiving course information hasn't been registered (yet).
|
||||
*/
|
||||
RaceDefinition getRace(Event tractracEvent);
|
||||
|
||||
JSONService parseJSONURL(URL jsonURL) throws IOException, ParseException, org.json.simple.parser.ParseException;
|
||||
|
||||
+7
@@ -11,6 +11,13 @@ public interface RaceTracker {
|
||||
|
||||
com.sap.sailing.domain.base.Event getEvent();
|
||||
|
||||
/**
|
||||
* Non-blocking call that returns <code>null</code> if the {@link RaceDefinition} for the TracTrac Event
|
||||
* hasn't been created yet, e.g., because the course definition hasn't been received yet or the listener
|
||||
* for receiving course information hasn't been registered (yet).
|
||||
*/
|
||||
RaceDefinition getRace();
|
||||
|
||||
RaceHandle getRaceHandle();
|
||||
|
||||
}
|
||||
+17
-8
@@ -18,6 +18,7 @@ import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.WindStore;
|
||||
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
|
||||
import com.sap.sailing.domain.tractracadapter.DomainFactory;
|
||||
import com.sap.sailing.domain.tractracadapter.RaceHandle;
|
||||
import com.sap.sailing.domain.tractracadapter.RaceTracker;
|
||||
import com.sap.sailing.domain.tractracadapter.Receiver;
|
||||
import com.tractrac.clientmodule.Event;
|
||||
@@ -31,10 +32,15 @@ public class RaceTrackerImpl implements Listener, RaceTracker {
|
||||
private final Thread ioThread;
|
||||
private final DataController controller;
|
||||
private final Set<Receiver> receivers;
|
||||
private final DomainFactory domainFactory;
|
||||
|
||||
/**
|
||||
* Creates a race tracked for the specified URL/URIs and starts receiving all available existing and future push
|
||||
* data from there. Receiving continues until {@link #stop()} is called.
|
||||
* <p>
|
||||
*
|
||||
* A race tracker uses the <code>paramURL</code> for the TracTrac Java client to register for push data about one
|
||||
* race. The {@link RaceDefinition} for that race, however, cannot be created until the {@link Course} has been
|
||||
* race. The {@link RaceDefinition} for that race, however, isn't created until the {@link Course} has been
|
||||
* received. Therefore, the {@link RaceCourseReceiver} will create the {@link RaceDefinition} and will add it to the
|
||||
* {@link com.sap.sailing.domain.base.Event}.
|
||||
* <p>
|
||||
@@ -45,16 +51,14 @@ public class RaceTrackerImpl implements Listener, RaceTracker {
|
||||
* {@link Event} as argument that is used for its tracking.
|
||||
* <p>
|
||||
*
|
||||
* When {@link #getRace} is called on this object before the {@link RaceCourseReceiver} has created the
|
||||
* {@link RaceDefinition}, the call will block until this has happened.
|
||||
*
|
||||
* @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.
|
||||
* 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.
|
||||
*/
|
||||
protected RaceTrackerImpl(DomainFactory domainFactory, URL paramURL, URI liveURI, URI storedURI, WindStore windStore)
|
||||
throws URISyntaxException, MalformedURLException, FileNotFoundException {
|
||||
this.domainFactory = domainFactory;
|
||||
// Read event data from configuration file
|
||||
tractracEvent = KeyValue.setup(paramURL);
|
||||
|
||||
@@ -81,9 +85,14 @@ public class RaceTrackerImpl implements Listener, RaceTracker {
|
||||
addListenersForStoredDataAndStartController(typeControllers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RaceHandle getRaceHandle() {
|
||||
return new RaceHandleImpl(domainFactory, tractracEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RaceDefinition getRace() {
|
||||
return DomainFactory.INSTANCE.getRace(tractracEvent);
|
||||
return domainFactory.getRace(tractracEvent);
|
||||
}
|
||||
|
||||
protected void addListenersForStoredDataAndStartController(Iterable<TypeController> listenersForStoredData) {
|
||||
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
/bin
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.sap.sailing.server.test</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,8 @@
|
||||
#Mon Jun 13 17:15:33 CEST 2011
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
@@ -0,0 +1,4 @@
|
||||
#Mon Jun 13 17:15:33 CEST 2011
|
||||
eclipse.preferences.version=1
|
||||
pluginProject.extensions=false
|
||||
resolve.requirebundle=false
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Test
|
||||
Bundle-SymbolicName: com.sap.sailing.server.test
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Require-Bundle: com.sap.sailing.server,
|
||||
com.sap.sailing.domain,
|
||||
com.sap.sailing.domain.tractracadapter,
|
||||
org.junit4
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>root</artifactId>
|
||||
<groupId>com.sap.sailing</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>com.sap.sailing</groupId>
|
||||
<artifactId>com.sap.sailing.server.test</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<packaging>eclipse-test-plugin</packaging>
|
||||
</project>
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.sap.sailing.server.test;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
|
||||
import com.sap.sailing.domain.tractracadapter.DomainFactory;
|
||||
import com.sap.sailing.domain.tractracadapter.RaceHandle;
|
||||
import com.sap.sailing.server.RacingEventServiceImpl;
|
||||
|
||||
public class RaceTrackerTest {
|
||||
private final URL paramUrl;
|
||||
private final URI liveUri;
|
||||
private final URI storedUri;
|
||||
private RacingEventServiceImpl service;
|
||||
private DomainFactory domainFactory;
|
||||
private RaceHandle raceHandle;
|
||||
|
||||
public RaceTrackerTest() throws MalformedURLException, URISyntaxException {
|
||||
// for live simulation:
|
||||
// paramUrl = new URL("http://sapsimulation.tracdev.dk/simulateconf/j80race12.txt");
|
||||
// liveUri = new URI("tcp://sapsimulation.tracdev.dk:4420"); // or with tunneling: tcp://localhost:4420
|
||||
// storedUri = new URI("tcp://sapsimulation.tracdev.dk:4421"); // or with tunneling: tcp://localhost:4421
|
||||
// for stored race, non-real-time simulation:
|
||||
paramUrl = new URL("http://germanmaster.traclive.dk/events/event_20110505_SailingTea/clientparams.php?event=event_20110505_SailingTea&race=bd8c778e-7c65-11e0-8236-406186cbf87c");
|
||||
|
||||
// tunneled:
|
||||
//liveUri = new URI("tcp://localhost:4412");
|
||||
//storedUri = new URI("tcp://localhost:4413");
|
||||
|
||||
//no tunnel:
|
||||
liveUri = new URI("tcp://germanmaster.traclive.dk:4400");
|
||||
storedUri = new URI("tcp://germanmaster.traclive.dk:4401");
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws MalformedURLException, FileNotFoundException, URISyntaxException {
|
||||
service = new RacingEventServiceImpl();
|
||||
raceHandle = service.addRace(paramUrl, liveUri, storedUri, EmptyWindStore.INSTANCE);
|
||||
domainFactory = service.getDomainFactory();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitialization() {
|
||||
RaceDefinition race = raceHandle.getRace();
|
||||
assertNotNull(race);
|
||||
}
|
||||
}
|
||||
@@ -12,11 +12,32 @@ import java.text.ParseException;
|
||||
import com.sap.sailing.declination.DeclinationService;
|
||||
import com.sap.sailing.domain.base.Event;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.tracking.TrackedEvent;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.WindStore;
|
||||
import com.sap.sailing.domain.tractracadapter.DomainFactory;
|
||||
import com.sap.sailing.domain.tractracadapter.RaceHandle;
|
||||
import com.sap.sailing.domain.tractracadapter.RaceTracker;
|
||||
import com.sap.sailing.util.Util.Triple;
|
||||
|
||||
/**
|
||||
* An OSGi service that can be used to track boat races using a TracTrac connector that pushes
|
||||
* live GPS boat location, waypoint, coarse and mark passing data.<p>
|
||||
*
|
||||
* If a race/event is already being tracked, another {@link #addRace(URL, URI, URI, WindStore)} or
|
||||
* {@link #addEvent(URL, URI, URI, WindStore)} call will have no effect, even if a different
|
||||
* {@link WindStore} is requested.<p>
|
||||
*
|
||||
* TODO When the tracking of a race/event is {@link #stopTracking(Event, RaceDefinition) stopped}, the next
|
||||
* time it's started to be tracked, a new {@link TrackedRace} at least will be constructed. This also
|
||||
* means that when a {@link TrackedEvent} exists that still holds other {@link TrackedRace}s, the
|
||||
* no longer tracked {@link TrackedRace} will be removed from the {@link TrackedEvent}.
|
||||
* corresponding information is removed also from the {@link DomainFactory}'s caches to ensure that
|
||||
* clean, fresh data is received should another tracking request be issued later.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public interface RacingEventService {
|
||||
Iterable<Event> getAllEvents();
|
||||
|
||||
@@ -25,33 +46,31 @@ public interface RacingEventService {
|
||||
DomainFactory getDomainFactory();
|
||||
|
||||
/**
|
||||
* Defines the event and for each race listed in the JSON document creates a {@link RaceTracker} that
|
||||
* tracks the respective race. The {@link RaceDefinition}s obtained this way are all grouped into
|
||||
* the single {@link Event} produced for the event listed in the JSON response. Note that the
|
||||
* many race trackers will have their TracTrac <code>Event</code> each, all with the same name,
|
||||
* meaning the same event but being distinct.
|
||||
* Defines the event and for each race listed in the JSON document creates a {@link RaceTracker} that starts
|
||||
* tracking the respective race. The {@link RaceDefinition}s obtained this way are all grouped into the single
|
||||
* {@link Event} produced for the event listed in the JSON response. Note that the many race trackers will have
|
||||
* their TracTrac <code>Event</code> each, all with the same name, meaning the same event but being distinct.
|
||||
*
|
||||
* @param jsonURL
|
||||
* URL of a JSON response that contains an "event" object telling the event's name and ID, as well as a
|
||||
* JSON array named "races" which tells ID and replay URL for the race. From those replay URLs the
|
||||
* paramURL for the Java client can be derived.
|
||||
* @param windStore TODO
|
||||
*/
|
||||
void addEvent(URL jsonURL, URI liveURI, URI storedURI, WindStore windStore) throws MalformedURLException, FileNotFoundException,
|
||||
Event addEvent(URL jsonURL, URI liveURI, URI storedURI, WindStore windStore) throws MalformedURLException, FileNotFoundException,
|
||||
URISyntaxException, IOException, ParseException, org.json.simple.parser.ParseException;
|
||||
|
||||
/**
|
||||
* Adds a single race tracker, using the race's parameter URL which delivers the single configuration
|
||||
* text file for that race. While the result of passing this URL to the TracTrac <code>KeyValue.setup</code>
|
||||
* is a TracTrac <code>Event</code>, those events only manage a single race. In our domain model, we group
|
||||
* those races into a single instance of our {@link Event} class.<p>
|
||||
* Adds a single race tracker and starts tracking the race, using the race's parameter URL which delivers the single
|
||||
* configuration text file for that race. While the result of passing this URL to the TracTrac
|
||||
* <code>KeyValue.setup</code> is a TracTrac <code>Event</code>, those events only manage a single race. In our
|
||||
* domain model, we group those races into a single instance of our {@link Event} class.
|
||||
* <p>
|
||||
*
|
||||
* If this is the first race of an event, the {@link Event} is created as well. If the {@link RaceDefinition} for
|
||||
* the race already exists, it isn't created again. Also, if a {@link RaceTracker} for the given race already
|
||||
* exists, it is not added again.
|
||||
* @param windStore TODO
|
||||
*/
|
||||
void addRace(URL paramURL, URI liveURI, URI storedURI, WindStore windStore) throws MalformedURLException, FileNotFoundException,
|
||||
RaceHandle addRace(URL paramURL, URI liveURI, URI storedURI, WindStore windStore) throws MalformedURLException, FileNotFoundException,
|
||||
URISyntaxException;
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.WindStore;
|
||||
import com.sap.sailing.domain.tractracadapter.DomainFactory;
|
||||
import com.sap.sailing.domain.tractracadapter.JSONService;
|
||||
import com.sap.sailing.domain.tractracadapter.RaceHandle;
|
||||
import com.sap.sailing.domain.tractracadapter.RaceRecord;
|
||||
import com.sap.sailing.domain.tractracadapter.RaceTracker;
|
||||
import com.sap.sailing.expeditionconnector.UDPExpeditionReceiver;
|
||||
@@ -71,16 +72,18 @@ public class RacingEventServiceImpl implements RacingEventService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEvent(URL jsonURL, URI liveURI, URI storedURI, WindStore windStore) throws URISyntaxException, IOException, ParseException, org.json.simple.parser.ParseException {
|
||||
public Event addEvent(URL jsonURL, URI liveURI, URI storedURI, WindStore windStore) throws URISyntaxException, IOException, ParseException, org.json.simple.parser.ParseException {
|
||||
JSONService jsonService = getDomainFactory().parseJSONURL(jsonURL);
|
||||
Event event = null;
|
||||
for (RaceRecord rr : jsonService.getRaceRecords()) {
|
||||
URL paramURL = rr.getParamURL();
|
||||
addRace(paramURL, liveURI, storedURI, windStore);
|
||||
event = addRace(paramURL, liveURI, storedURI, windStore).getEvent();
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRace(URL paramURL, URI liveURI, URI storedURI, WindStore windStore) throws MalformedURLException, FileNotFoundException,
|
||||
public RaceHandle addRace(URL paramURL, URI liveURI, URI storedURI, WindStore windStore) throws MalformedURLException, FileNotFoundException,
|
||||
URISyntaxException {
|
||||
RaceTracker tracker = getDomainFactory().createRaceTracker(paramURL, liveURI, storedURI, windStore);
|
||||
Set<RaceTracker> trackers = raceTrackers.get(tracker.getEvent());
|
||||
@@ -98,6 +101,7 @@ public class RacingEventServiceImpl implements RacingEventService {
|
||||
} else {
|
||||
eventsByName.put(eventName, tracker.getEvent());
|
||||
}
|
||||
return tracker.getRaceHandle();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -128,6 +132,7 @@ public class RacingEventServiceImpl implements RacingEventService {
|
||||
}
|
||||
}
|
||||
}
|
||||
// FIXME remove TrackedRace from TrackedEvent
|
||||
// if the last tracked race was removed, remove the entire event
|
||||
if (raceTrackers.get(event).isEmpty()) {
|
||||
stopTracking(event);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<module>com.sap.sailing.expeditionconnector</module>
|
||||
<module>com.sap.sailing.expeditionconnector.test</module>
|
||||
<module>com.sap.sailing.server</module>
|
||||
<module>com.sap.sailing.server.test</module>
|
||||
<module>com.sap.sailing.mongodb</module>
|
||||
<module>com.sap.sailing.mongodb.test</module>
|
||||
<module>com.tractrac.clientmodule</module>
|
||||
|
||||
Reference in new issue
Block a user