Merge branch 'gwt' into messagescripttest

Conflicts:
	java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/ScriptedStoreAndForwardTest.java
This commit is contained in:
Benjamin Ebling committed 2011-11-18 14:24:37 +01:00
commit 09fb009b05
38 files changed
+519 -293

No files matched your search

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/StoreAndForward.java"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.sap.sailing.domain.swisstimingadapter.persistence.StoreAndForward"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="3500 3501"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.domain.swisstimingadapter.persistence"/>
</launchConfiguration>
@@ -238,8 +238,7 @@ public class StoreAndForward implements Runnable {
public static void main(String[] args) throws InterruptedException, IOException {
int listenPort = Integer.valueOf(args[0]);
int clientPort = Integer.valueOf(args[1]);
StoreAndForward storeAndForward = new StoreAndForward(listenPort, clientPort, SwissTimingFactory.INSTANCE, SwissTimingAdapterPersistence.INSTANCE);
storeAndForward.run();
new StoreAndForward(listenPort, clientPort, SwissTimingFactory.INSTANCE, SwissTimingAdapterPersistence.INSTANCE);
}
public void run() {
@@ -108,15 +108,11 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
@Override
public List<SailMasterMessage> loadRaceMessages(String raceID) {
DBCollection racesMessagesCollection = database.getCollection(CollectionNames.RACES_MESSAGES.name());
BasicDBObject query = new BasicDBObject();
query.append(FieldNames.RACE_ID.name(), raceID);
DBCursor results = racesMessagesCollection.find(query);
DBCursor results = racesMessagesCollection.find(query).sort(new BasicDBObject().append(FieldNames.MESSAGE_SEQUENCE_NUMBER.name(), 1));
List<SailMasterMessage> result = new ArrayList<SailMasterMessage>();
for (DBObject o : results) {
SailMasterMessage msg = swissTimingFactory.createMessage((String) o.get(FieldNames.MESSAGE_CONTENT.name()),
(Long) o.get(FieldNames.MESSAGE_SEQUENCE_NUMBER.name()));
@@ -128,10 +124,8 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
@Override
public List<SailMasterMessage> loadCommandMessages() {
DBCollection cmdMessagesCollection = database.getCollection(CollectionNames.COMMAND_MESSAGES.name());
DBCursor results = cmdMessagesCollection.find();
DBCursor results = cmdMessagesCollection.find().sort(new BasicDBObject().append(FieldNames.MESSAGE_SEQUENCE_NUMBER.name(), 1));
List<SailMasterMessage> result = new ArrayList<SailMasterMessage>();
for (DBObject o : results) {
SailMasterMessage msg = swissTimingFactory.createMessage((String) o.get(FieldNames.MESSAGE_CONTENT.name()),
(Long) o.get(FieldNames.MESSAGE_SEQUENCE_NUMBER.name()));
@@ -148,9 +142,10 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
query.append(FieldNames.RACE_ID.name(), raceID);
DBObject o = races.findOne(query);
if (o != null) {
Long startTimeAsMillis = (Long) o.get(FieldNames.RACE_STARTTIME.name());
Race race = swissTimingFactory.createRace((String) o.get(FieldNames.RACE_ID.name()),
(String) o.get(FieldNames.RACE_DESCRIPTION.name()),
new MillisecondsTimePoint((Long) o.get(FieldNames.RACE_STARTTIME.name())));
startTimeAsMillis == null ? null : new MillisecondsTimePoint(startTimeAsMillis));
return race;
}
return null;
@@ -208,16 +203,25 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
messageCollection = database.getCollection(CollectionNames.COMMAND_MESSAGES.name());
}
messageCollection.insert(objToInsert);
if(message.getRaceID() != null && cachedRaces.containsKey(message.getRaceID()) == false) {
if(message.getType() == MessageType.RAC) {
// store the new race in the master data collection
List<Race> availableRaces = parseAvailableRacesMessage(message);
for (Race newRace : availableRaces) {
storeRace(newRace);
}
} else if (message.getRaceID() != null && !cachedRaces.containsKey(message.getRaceID())) {
// ah, we found a new raceID which is not in the list of known races
// in order to have a more intelligent conflict resolver mechanism we will forward the resolution to a special thread later on
boolean simpleResolution = true;
if(simpleResolution) {
if (simpleResolution) {
// first check if the missing race has been created in the mean time
Race checkRace = getRace(message.getRaceID());
if(checkRace != null) {
cachedRaces.put(checkRace.getRaceID(), checkRace);
Race raceFromDB = getRace(message.getRaceID());
if (raceFromDB != null) {
cachedRaces.put(raceFromDB.getRaceID(), raceFromDB);
} else {
logger.info("Didn't find race "+message.getRaceID()+" in race DB. Adding it.");
Race newRace = SwissTimingFactory.INSTANCE.createRace(message.getRaceID(), null, null);
storeRace(newRace);
cachedRaces.put(newRace.getRaceID(), newRace);
@@ -226,6 +230,16 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
}
}
private List<Race> parseAvailableRacesMessage(SailMasterMessage availableRacesMessage) {
int count = Integer.valueOf(availableRacesMessage.getSections()[1]);
List<Race> result = new ArrayList<Race>();
for (int i=0; i<count; i++) {
String[] idAndDescription = availableRacesMessage.getSections()[2+i].split(";");
result.add(SwissTimingFactory.INSTANCE.createRace(idAndDescription[0], idAndDescription[1], null));
}
return result;
}
@Override
public void storeRace(Race race) {
DBCollection racesCollection = database.getCollection(CollectionNames.RACES_MASTERDATA.name());
@@ -14,3 +14,4 @@ Require-Bundle: com.sap.sailing.domain.swisstimingadapter,
com.sap.sailing.mongodb
Bundle-ClassPath: resources/,
.
Import-Package: com.sap.sailing.server
@@ -1,3 +1,5 @@
RAC|2|4711;A wonderful test race|4712;Not such a wonderful race
STL|4711|2|GER 8414;GER;Polgar/Koy|GER 8140;GER;Schlonski/Bohn
STL|4712|3|GER 8340;GER;Stanjek/Kleen|GER 8433;GER;Babendererde/Jacobs|GER 8299;GER;Elsner/Schulz
CCG|4711|2|0;Mark1 Description;SailNumber1;SailNumber2|1;Mark2 Description;SailNumber3
CCG|4712|2|0;Mark2 Description;SailNumber1;SailNumber2|1;Mark7 Description;SailNumber4
@@ -1,47 +1,3 @@
RAC|1|W4702;A simulated SwissTiming race
STL|W4702|1|GER 12;GER;Competitor 25
STL|W4702|1|GBR 812;GBR;Competitor 19
STL|W4702|1|NED 24;NED;Competitor 35
STL|W4702|1|CRO 111;CRO;Competitor 11
STL|W4702|1|ARG 8;ARG;Competitor 0
STL|W4702|1|FRA 12;FRA;Competitor 16
STL|W4702|1|CAN 610;CAN;Competitor 6
STL|W4702|1|CHN 616;CHN;Competitor 10
STL|W4702|1|CHN 1261;CHN;Competitor 8
STL|W4702|1|ESP 133;ESP;Competitor 13
STL|W4702|1|GER 72;GER;Competitor 29
STL|W4702|1|EST 20;EST;Competitor 15
STL|W4702|1|NZL 75;NZL;Competitor 36
STL|W4702|1|SLO 64;SLO;Competitor 39
STL|W4702|1|GBR 831;GBR;Competitor 20
STL|W4702|1|RUS 12;RUS;Competitor 37
STL|W4702|1|ITA 23;ITA;Competitor 31
STL|W4702|1|ESP 696;ESP;Competitor 14
STL|W4702|1|GBR 847;GBR;Competitor 22
STL|W4702|1|DEN 143;DEN;Competitor 12
STL|W4702|1|ISR 311;ISR;Competitor 30
STL|W4702|1|GER 21;GER;Competitor 26
STL|W4702|1|NED 11;NED;Competitor 34
STL|W4702|1|GBR 850;GBR;Competitor 23
STL|W4702|1|BRA 177;BRA;Competitor 3
STL|W4702|1|AUT 431;AUT;Competitor 2
STL|W4702|1|FRA 9;FRA;Competitor 18
STL|W4702|1|FRA 4;FRA;Competitor 17
STL|W4702|1|GBR 855;GBR;Competitor 24
STL|W4702|1|BRA 1187;BRA;Competitor 4
STL|W4702|1|USA 1712;USA;Competitor 43
STL|W4702|1|SWE 344;SWE;Competitor 42
STL|W4702|1|GER 61;GER;Competitor 27
STL|W4702|1|SWE 342;SWE;Competitor 41
STL|W4702|1|CHN 1211;CHN;Competitor 7
STL|W4702|1|USA 1757;USA;Competitor 45
STL|W4702|1|GER 66;GER;Competitor 28
STL|W4702|1|SUI 14;SUI;Competitor 40
STL|W4702|1|JPN 4151;JPN;Competitor 32
STL|W4702|1|JPN 4321;JPN;Competitor 33
STL|W4702|1|CAN 11;CAN;Competitor 5
STL|W4702|1|AUS 7;AUS;Competitor 1
STL|W4702|1|USA 1736;USA;Competitor 44
STL|W4702|1|RUS 700;RUS;Competitor 38
STL|W4702|1|CHN 221;CHN;Competitor 9
STL|W4702|1|GBR 841;GBR;Competitor 21
STL|W4702|46|GER 12;GER;Competitor 25|GBR 812;GBR;Competitor 19|NED 24;NED;Competitor 35|CRO 111;CRO;Competitor 11|ARG 8;ARG;Competitor 0|FRA 12;FRA;Competitor 16|CAN 610;CAN;Competitor 6|CHN 616;CHN;Competitor 10|CHN 1261;CHN;Competitor 8|ESP 133;ESP;Competitor 13|GER 72;GER;Competitor 29|EST 20;EST;Competitor 15|NZL 75;NZL;Competitor 36|SLO 64;SLO;Competitor 39|GBR 831;GBR;Competitor 20|RUS 12;RUS;Competitor 37|ITA 23;ITA;Competitor 31|ESP 696;ESP;Competitor 14|GBR 847;GBR;Competitor 22|DEN 143;DEN;Competitor 12|ISR 311;ISR;Competitor 30|GER 21;GER;Competitor 26|NED 11;NED;Competitor 34|GBR 850;GBR;Competitor 23|BRA 177;BRA;Competitor 3|AUT 431;AUT;Competitor 2|FRA 9;FRA;Competitor 18|FRA 4;FRA;Competitor 17|GBR 855;GBR;Competitor 24|BRA 1187;BRA;Competitor 4|USA 1712;USA;Competitor 43|SWE 344;SWE;Competitor 42|GER 61;GER;Competitor 27|SWE 342;SWE;Competitor 41|CHN 1211;CHN;Competitor 7|USA 1757;USA;Competitor 45|GER 66;GER;Competitor 28|SUI 14;SUI;Competitor 40|JPN 4151;JPN;Competitor 32|JPN 4321;JPN;Competitor 33|CAN 11;CAN;Competitor 5|AUS 7;AUS;Competitor 1|USA 1736;USA;Competitor 44|RUS 700;RUS;Competitor 38|CHN 221;CHN;Competitor 9|GBR 841;GBR;Competitor 21
CCG|W4702|7|0;StartGate;M2;M3|1;Buoy4;M4|2;Buoy5;M5|3;Buoy6;M6|4;Buoy7;M7|5;Buoy1;M1|6;FinishGate;M2;M3
@@ -79,7 +79,7 @@ public class ActivelyConnectingStoreAndForwardTest {
}
swissTimingFactory = SwissTimingFactory.INSTANCE;
transceiver = swissTimingFactory.createSailMasterTransceiver();
connector = swissTimingFactory.getOrCreateSailMasterConnector("localhost", CLIENT_PORT, null); // will connect to RECEIVE_PORT
connector = swissTimingFactory.getOrCreateSailMasterConnector("localhost", CLIENT_PORT, null, /* canSendRequests */ true); // will connect to RECEIVE_PORT
DBCollection lastMessageCountCollection = db.getCollection(CollectionNames.LAST_MESSAGE_COUNT.name());
lastMessageCountCollection.update(new BasicDBObject(), new BasicDBObject().append(FieldNames.LAST_MESSAGE_COUNT.name(), 0l),
/* upsert */ true, /* multi */ false);
@@ -0,0 +1,222 @@
package com.sap.sailing.domain.swisstimingadapter.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.sap.sailing.domain.base.Buoy;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.swisstimingadapter.MessageType;
import com.sap.sailing.domain.swisstimingadapter.SailMasterConnector;
import com.sap.sailing.domain.swisstimingadapter.SailMasterTransceiver;
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
import com.sap.sailing.domain.swisstimingadapter.persistence.StoreAndForward;
import com.sap.sailing.domain.swisstimingadapter.persistence.SwissTimingAdapterPersistence;
import com.sap.sailing.domain.swisstimingadapter.persistence.impl.CollectionNames;
import com.sap.sailing.domain.swisstimingadapter.persistence.impl.FieldNames;
import com.sap.sailing.domain.tracking.DynamicTrackedEvent;
import com.sap.sailing.domain.tracking.RaceHandle;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
import com.sap.sailing.mongodb.Activator;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceImpl;
import com.sap.sailing.util.Util;
public class EndToEndListeningStoreAndFowardTest {
private static final Logger logger = Logger.getLogger(EndToEndListeningStoreAndFowardTest.class.getName());
private static final int RECEIVE_PORT = 6543;
private static final int CLIENT_PORT = 6544;
private DB db;
private StoreAndForward storeAndForward;
private Socket sendingSocket;
private OutputStream sendingStream;
private SailMasterTransceiver transceiver;
private SailMasterConnector connector;
private SwissTimingAdapterPersistence swissTimingAdapterPersistence;
private SwissTimingFactory swissTimingFactory;
private EmptyWindStore emptyWindStore;
private RacingEventService racingEventService;
private List<RaceHandle> raceHandles;
@Before
public void setUp() throws UnknownHostException, IOException, InterruptedException {
logger.info("EndToEndListeningStoreAndFowardTest.setUp");
db = Activator.getDefaultInstance().getDB();
swissTimingAdapterPersistence = SwissTimingAdapterPersistence.INSTANCE;
swissTimingAdapterPersistence.dropAllMessageData();
swissTimingAdapterPersistence.dropAllRaceMasterData();
storeAndForward = new StoreAndForward(RECEIVE_PORT, CLIENT_PORT, SwissTimingFactory.INSTANCE, swissTimingAdapterPersistence);
sendingSocket = new Socket("localhost", RECEIVE_PORT);
sendingStream = sendingSocket.getOutputStream();
swissTimingFactory = SwissTimingFactory.INSTANCE;
emptyWindStore = EmptyWindStore.INSTANCE;
transceiver = swissTimingFactory.createSailMasterTransceiver();
DBCollection lastMessageCountCollection = db.getCollection(CollectionNames.LAST_MESSAGE_COUNT.name());
lastMessageCountCollection.update(new BasicDBObject(), new BasicDBObject().append(FieldNames.LAST_MESSAGE_COUNT.name(), 0l),
/* upsert */ true, /* multi */ false);
racingEventService = new RacingEventServiceImpl();
raceHandles = new ArrayList<RaceHandle>();
}
@After
public void tearDown() throws InterruptedException, IOException {
logger.entering(getClass().getName(), "tearDown");
for(RaceHandle raceHandle: raceHandles) {
racingEventService.stopTracking(raceHandle.getEvent());
}
storeAndForward.stop();
logger.exiting(getClass().getName(), "tearDown");
}
// @Test
public void testEndToEndScenarioWithInitMessages() throws IOException, InterruptedException, ParseException {
String[] racesToTrack = new String[] { "4711", "4712" };
String scriptName = "/InitMessagesScript.txt";
setUpUsingScript(racesToTrack, scriptName);
Set<TrackedRace> allTrackedRaces = new HashSet<TrackedRace>();
Iterable<Event> allEvents = racingEventService.getAllEvents();
for (Event event : allEvents) {
DynamicTrackedEvent trackedEvent = racingEventService.getTrackedEvent(event);
Iterable<TrackedRace> trackedRaces = trackedEvent.getTrackedRaces();
for (TrackedRace trackedRace : trackedRaces) {
allTrackedRaces.add(trackedRace);
}
}
assertEquals(2, Util.size(allTrackedRaces));
Set<String> raceIDs = new HashSet<String>();
for (TrackedRace trackedRace : allTrackedRaces) {
RaceDefinition race = trackedRace.getRace();
raceIDs.add(race.getName());
}
Set<String> expectedRaceIDs = new HashSet<String>();
for (String raceIDToTrack : new String[] { "Not such a wonderful race", "A wonderful test race" }) {
expectedRaceIDs.add(raceIDToTrack);
}
assertEquals(expectedRaceIDs, raceIDs);
}
@Test
public void testLongRaceLog() throws IOException, InterruptedException, ParseException {
String[] racesToTrack = new String[] { "W4702" };
String scriptName1 = "/SailMasterDataInterfaceRACandSTL.txt";
String scriptName2 = "/SailMasterDataInterface-ExampleAsText.txt";
setUpUsingScript(racesToTrack, scriptName1, scriptName2);
Set<TrackedRace> allTrackedRaces = new HashSet<TrackedRace>();
Iterable<Event> allEvents = racingEventService.getAllEvents();
for (Event event : allEvents) {
DynamicTrackedEvent trackedEvent = racingEventService.getTrackedEvent(event);
Iterable<TrackedRace> trackedRaces = trackedEvent.getTrackedRaces();
for (TrackedRace trackedRace : trackedRaces) {
allTrackedRaces.add(trackedRace);
}
}
assertEquals(1, Util.size(allTrackedRaces));
Set<RaceDefinition> races = raceHandles.iterator().next().getRaceTracker().getRaces();
assertEquals(1, races.size());
RaceDefinition raceFromTracker = races.iterator().next();
assertNotNull(raceFromTracker);
Set<String> raceIDs = new HashSet<String>();
for (TrackedRace trackedRace : allTrackedRaces) {
RaceDefinition race = trackedRace.getRace();
raceIDs.add(race.getName());
assertEquals(46, Util.size(race.getCompetitors()));
assertEquals(7, Util.size(race.getCourse().getWaypoints()));
assertEquals(6, Util.size(race.getCourse().getLegs()));
for (Competitor competitor : race.getCompetitors()) {
if (!competitor.getName().equals("Competitor 35") && !competitor.getName().equals("Competitor 20")) {
assertTrue("Track of competitor "+competitor+" empty", !Util.isEmpty(trackedRace.getTrack(competitor).getRawFixes()));
}
}
Set<Buoy> buoys = new HashSet<Buoy>();
for (Waypoint waypoint : race.getCourse().getWaypoints()) {
for (Buoy buoy : waypoint.getBuoys()) {
buoys.add(buoy);
}
}
for (Buoy buoy : buoys) {
assertTrue("Track of buoy "+buoy+" empty", !Util.isEmpty(trackedRace.getOrCreateTrack(buoy).getRawFixes()));
}
}
Set<String> expectedRaceIDs = new HashSet<String>();
for (String raceIDToTrack : new String[] { "A simulated SwissTiming race" }) {
expectedRaceIDs.add(raceIDToTrack);
}
assertEquals(expectedRaceIDs, raceIDs);
}
@Test
public void testEndToEndWithSwissTimingData() throws IOException, InterruptedException, ParseException {
String[] racesToTrack = new String[] { "W4702" };
String scriptName1 = "/SailMasterDataInterfaceRACandSTL.txt";
String scriptName2 = "/SailMasterDataInterface-ExampleAsText.txt";
setUpUsingScript(racesToTrack, scriptName1, scriptName2);
Set<TrackedRace> allTrackedRaces = new HashSet<TrackedRace>();
Iterable<Event> allEvents = racingEventService.getAllEvents();
for (Event event : allEvents) {
DynamicTrackedEvent trackedEvent = racingEventService.getTrackedEvent(event);
Iterable<TrackedRace> trackedRaces = trackedEvent.getTrackedRaces();
for (TrackedRace trackedRace : trackedRaces) {
allTrackedRaces.add(trackedRace);
}
}
}
private void setUpUsingScript(String[] racesToTrack, String... scriptNames) throws InterruptedException,
UnknownHostException, IOException, ParseException {
for(String raceToTrack: racesToTrack) {
RaceHandle raceHandle = racingEventService.addSwissTimingRace(raceToTrack, "localhost", CLIENT_PORT, /* canSendRequests */
false, emptyWindStore, -1);
raceHandles.add(raceHandle);
if(connector == null) {
connector = racingEventService.getSwissTimingFactory().getOrCreateSailMasterConnector("localhost",
CLIENT_PORT, swissTimingAdapterPersistence, /* canSendRequests */ false);
}
}
ScriptedMessagesReader scriptedMessagesReader = new ScriptedMessagesReader();
for (String scriptName : scriptNames) {
InputStream is = getClass().getResourceAsStream(scriptName);
scriptedMessagesReader.addMessagesFromTextFile(is);
}
for (String msg: scriptedMessagesReader.getMessages()) {
transceiver.sendMessage(msg, sendingStream);
}
transceiver.sendMessage(swissTimingFactory.createMessage(MessageType._STOPSERVER.name(), null), sendingStream);
synchronized (connector) {
while (!connector.isStopped()) {
connector.wait();
}
}
}
}
@@ -56,7 +56,7 @@ public class ListeningStoreAndForwardTest {
sendingStream = sendingSocket.getOutputStream();
swissTimingFactory = SwissTimingFactory.INSTANCE;
transceiver = swissTimingFactory.createSailMasterTransceiver();
connector = swissTimingFactory.getOrCreateSailMasterConnector("localhost", CLIENT_PORT, null);
connector = swissTimingFactory.getOrCreateSailMasterConnector("localhost", CLIENT_PORT, null, /* canSendRequests */ false);
DBCollection lastMessageCountCollection = db.getCollection(CollectionNames.LAST_MESSAGE_COUNT.name());
lastMessageCountCollection.update(new BasicDBObject(), new BasicDBObject().append(FieldNames.LAST_MESSAGE_COUNT.name(), 0l),
/* upsert */ true, /* multi */ false);
@@ -69,7 +69,7 @@ public class OverlappingStoredAndReceivedMessagesTest implements RaceSpecificMes
}.start();
swissTimingFactory = SwissTimingFactory.INSTANCE;
transceiver = swissTimingFactory.createSailMasterTransceiver();
connector = swissTimingFactory.getOrCreateSailMasterConnector("localhost", PORT, this);
connector = swissTimingFactory.getOrCreateSailMasterConnector("localhost", PORT, this, /* canSendRequests */ false);
synchronized (this) {
while (sendingStream == null) {
wait();
@@ -54,7 +54,7 @@ public class SailMasterConnectivityTest {
Race race4712 = new RaceImpl("4712", "Not such a wonderful race");
swissTimingPersistence.storeRace(race4711);
swissTimingPersistence.storeRace(race4712);
connector = SwissTimingFactory.INSTANCE.getOrCreateSailMasterConnector("localhost", port, swissTimingPersistence);
connector = SwissTimingFactory.INSTANCE.getOrCreateSailMasterConnector("localhost", port, swissTimingPersistence, /* canSendRequests */ true);
connector.trackRace("W4702");
connector.trackRace(race4711.getRaceID());
connector.trackRace(race4712.getRaceID());
@@ -66,7 +66,7 @@ public class ScriptedStoreAndForwardTest {
sendingStream = sendingSocket.getOutputStream();
swissTimingFactory = SwissTimingFactory.INSTANCE;
transceiver = swissTimingFactory.createSailMasterTransceiver();
connector = swissTimingFactory.getOrCreateSailMasterConnector("localhost", CLIENT_PORT,
connector = swissTimingFactory.getOrCreateSailMasterConnector("localhost", CLIENT_PORT, swissTimingAdapterPersistence, /* canSendRequests */ false);
swissTimingAdapterPersistence);
DBCollection lastMessageCountCollection = db.getCollection(CollectionNames.LAST_MESSAGE_COUNT.name());
lastMessageCountCollection.update(new BasicDBObject(),
@@ -104,6 +104,7 @@ public class ScriptedStoreAndForwardTest {
final List<Race> racesReceived = new ArrayList<Race>();
final boolean[] receivedAll = new boolean[1];
final List<Competitor> receivedCompetitors = new ArrayList<Competitor>();
final List<Course> receivedCourses = new ArrayList<Course>();
connector.addSailMasterListener(new SailMasterAdapter() {
@Override
@@ -113,6 +114,14 @@ public class ScriptedStoreAndForwardTest {
receivedCompetitors.add(competitor);
receivedMessagesCount[0] = receivedMessagesCount[0] + 1;
}
@Override
public void receivedCourseConfiguration(String raceID, Course course) {
receivedCourses.add(course);
receivedMessagesCount[0] = receivedMessagesCount[0] + 1;
if (messageCount == receivedMessagesCount[0]) {
synchronized (ScriptedStoreAndForwardTest.this) {
@@ -122,7 +131,7 @@ public class ScriptedStoreAndForwardTest {
}
}
@Override
public void receivedAvailableRaces(Iterable<Race> races) {
@@ -133,7 +142,7 @@ public class ScriptedStoreAndForwardTest {
}
});
for (String msg : scriptedMessages.getMessages()) {
for(String msg: scriptedMessages.getMessages()) {
transceiver.sendMessage(msg, sendingStream);
}
@@ -144,103 +153,10 @@ public class ScriptedStoreAndForwardTest {
}
assertEquals(2, racesReceived.size());
assertEquals(5, receivedCompetitors.size());
for (String raceToTrack : racesToTrack)
assertEquals(2, receivedCourses.size());
for(String raceToTrack: racesToTrack)
connector.stopTrackingRace(raceToTrack);
}
@Test
public void testInitMessages2() throws IOException, InterruptedException, ParseException {
swissTimingAdapterPersistence.dropAllRaceMasterData();
swissTimingAdapterPersistence.dropAllMessageData();
String[] racesToTrack = new String[] { "4711" };
for (String raceToTrack : racesToTrack)
connector.trackRace(raceToTrack);
InputStream is = getClass().getResourceAsStream("/InitMessagesScript2.txt");
ScriptedMessages scriptedMessages = new ScriptedMessages(is);
final int messageCount = scriptedMessages.getMessages().size();
final int[] receivedMessagesCount = new int[] { 0 };
final List<Race> racesReceived = new ArrayList<Race>();
final boolean[] receivedAll = new boolean[1];
final List<Competitor> receivedCompetitors = new ArrayList<Competitor>();
connector.addSailMasterListener(new SailMasterAdapter() {
@Override
public void receivedRacePositionData(String raceID, RaceStatus status, TimePoint timePoint,
TimePoint startTime, Long millisecondsSinceRaceStart, Integer nextMarkIndexForLeader,
Distance distanceToNextMarkForLeader, Collection<Fix> fixes) {
// TODO Auto-generated method stub
countAndCheckAllMessagesRecieved(messageCount, receivedMessagesCount, receivedAll);
}
@Override
public void receivedClockAtMark(String raceID,
List<Triple<Integer, TimePoint, String>> markIndicesTimePointsAndBoatIDs) {
// TODO Auto-generated method stub
countAndCheckAllMessagesRecieved(messageCount, receivedMessagesCount, receivedAll);
}
@Override
public void receivedCourseConfiguration(String raceID, Course course) {
// TODO Auto-generated method stub
countAndCheckAllMessagesRecieved(messageCount, receivedMessagesCount, receivedAll);
}
@Override
public void receivedStartList(String raceID, StartList startList) {
for (Competitor competitor : startList.getCompetitors())
receivedCompetitors.add(competitor);
countAndCheckAllMessagesRecieved(messageCount, receivedMessagesCount, receivedAll);
}
@Override
public void receivedAvailableRaces(Iterable<Race> races) {
for (Race race : races) {
racesReceived.add(race);
}
countAndCheckAllMessagesRecieved(messageCount, receivedMessagesCount, receivedAll);
}
});
for (String msg : scriptedMessages.getMessages()) {
transceiver.sendMessage(msg, sendingStream);
}
synchronized (this) {
while (!receivedAll[0]) {
wait(2000l); // wait for two seconds to receive the messages
}
}
assertEquals(1, racesReceived.size());
assertEquals(2, receivedCompetitors.size());
for (String raceToTrack : racesToTrack)
connector.stopTrackingRace(raceToTrack);
}
private void countAndCheckAllMessagesRecieved(int messageCount, int[] receivedMessagesCount, boolean[] receivedAll) {
receivedMessagesCount[0] = receivedMessagesCount[0] + 1;
if (messageCount == receivedMessagesCount[0]) {
synchronized (ScriptedStoreAndForwardTest.this) {
receivedAll[0] = true;
ScriptedStoreAndForwardTest.this.notifyAll();
}
}
}
}
@@ -43,7 +43,8 @@ public class SwissTimingSailMasterLiveTest implements SailMasterListener {
@Before
public void connect() throws InterruptedException {
connector = SwissTimingFactory.INSTANCE.getOrCreateSailMasterConnector("gps.sportresult.com", 40300, SwissTimingAdapterPersistence.INSTANCE);
connector = SwissTimingFactory.INSTANCE.getOrCreateSailMasterConnector("gps.sportresult.com", 40300,
SwissTimingAdapterPersistence.INSTANCE, /* canSendRequests */true);
}
@After
@@ -0,0 +1,29 @@
package com.sap.sailing.domain.swisstimingadapter;
import java.util.Date;
public class RaceRecord {
private String raceID;
private String description;
private Date startTime;
public RaceRecord(String raceID, String description, Date startTime) {
this.raceID = raceID;
this.description = description;
this.startTime = startTime;
}
public String getRaceID() {
return raceID;
}
public String getDescription() {
return description;
}
public Date getStartTime() {
return startTime;
}
}
@@ -34,14 +34,15 @@ public interface SwissTimingFactory {
* {@link SailMasterConnector#trackRace} and {@link SailMasterConnector#stopTrackingRace} operations.
* {@link MessageType#isRaceSpecific() Race-specific messages} for other races are ignored and not forwarded to any
* listener.
* @param canSendRequests TODO
*/
SailMasterConnector getOrCreateSailMasterConnector(String hostname, int port, RaceSpecificMessageLoader messageLoader) throws InterruptedException;
SailMasterConnector getOrCreateSailMasterConnector(String hostname, int port, RaceSpecificMessageLoader messageLoader, boolean canSendRequests) throws InterruptedException;
SailMasterTransceiver createSailMasterTransceiver();
SwissTimingConfiguration createSwissTimingConfiguration(String name, String hostname, int port);
SwissTimingRaceTracker createRaceTracker(String raceID, String hostname, int port, WindStore windStore, RaceSpecificMessageLoader messageLoader, DomainFactory domainFactory, TrackedEventRegistry trackedEventRegistry) throws InterruptedException, UnknownHostException, IOException, ParseException;
SwissTimingRaceTracker createRaceTracker(String raceID, String hostname, int port, boolean canSendRequests, WindStore windStore, RaceSpecificMessageLoader messageLoader, DomainFactory domainFactory, TrackedEventRegistry trackedEventRegistry) throws InterruptedException, UnknownHostException, IOException, ParseException;
Race createRace(String raceId, String description, TimePoint startTime);
@@ -8,6 +8,7 @@ import java.util.List;
import java.util.Map;
import com.sap.sailing.domain.base.Boat;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Buoy;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.ControlPoint;
@@ -110,11 +111,17 @@ public class DomainFactoryImpl implements DomainFactory {
public RaceDefinition createRaceDefinition(Event event, Race race, StartList startList, Course course) {
com.sap.sailing.domain.base.Course domainCourse = createCourse(race.getDescription(), course);
Iterable<Competitor> competitors = createCompetitorList(startList);
RaceDefinition result = new RaceDefinitionImpl(race.getDescription(), domainCourse, /* boatClass */ null, competitors);
RaceDefinition result = new RaceDefinitionImpl(race.getDescription(), domainCourse,
getOrCreateBoatClassFromRaceID(race.getRaceID()), competitors);
event.addRace(result);
return result;
}
private BoatClass getOrCreateBoatClassFromRaceID(String raceID) {
// TODO extract boat class from raceID according to SwissTiming-internal mapping rules
return /* boatClass */ null;
}
private Iterable<Competitor> createCompetitorList(StartList startList) {
List<Competitor> result = new ArrayList<Competitor>();
for (com.sap.sailing.domain.swisstimingadapter.Competitor swissTimingCompetitor : startList.getCompetitors()) {
@@ -69,7 +69,10 @@ import com.sap.sailing.util.Util.Triple;
*
* Generally, the connector needs to be instructed for which races it shall handle events using calls to the
* {@link #trackRace} and {@link #stopTrackingRace} operations. {@link MessageType#isRaceSpecific() Race-specific
* messages} for other races are ignored and not forwarded to any listener.
* messages} for other races are ignored and not forwarded to any listener.<p>
*
* Clients that want to wait until the connector changes to {@link #isStopped()} can {@link Object#wait()} on this
* object because it notifies all waiters when changing from !{@link #isStopped()} to {@link #isStopped()}.
*
* @author Axel Uhl (d043530)
*
@@ -98,9 +101,11 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
* The only way known so far for how to find out the time zone relative to which the other time stamps
* are to be interpreted is to start with the current default time zone's offset and wait for an
* {@link MessageType#RPD RPD} event to be received. From this event, the time zone offset can be extracted
* and applied to all other time stamps.
* and applied to all other time stamps. It is stored using the race ID as key.
*/
private String lastTimeZoneSuffix;
private final Map<String, String> lastTimeZoneSuffixPerRaceID;
private final Map<String, TimePoint> startTimePerRaceID;
/**
* Used for the {@link #rendevouz(SailMasterMessage)} pattern. For each {@link MessageType} there
@@ -115,20 +120,23 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
private final RaceSpecificMessageLoader messageLoader;
public SailMasterConnectorImpl(String host, int port, RaceSpecificMessageLoader messageLoader) throws InterruptedException {
private final boolean canSendRequests;
public SailMasterConnectorImpl(String host, int port, RaceSpecificMessageLoader messageLoader, boolean canSendRequests) throws InterruptedException {
super();
this.messageLoader = messageLoader;
dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ");
idsOfTrackedRaces = new HashSet<String>();
this.host = host;
this.port = port;
this.canSendRequests = canSendRequests;
this.listeners = new HashSet<SailMasterListener>();
this.raceSpecificListeners = new HashMap<String, Set<SailMasterListener>>();
this.unprocessedMessagesByType = new HashMap<MessageType, BlockingQueue<SailMasterMessage>>();
raceSpecificMessageBuffers = new HashMap<String, List<SailMasterMessage>>();
sequenceNumberOfLastMessageForRaceID = new HashMap<String, Long>();
int offset = TimeZone.getDefault().getOffset(System.currentTimeMillis())/1000/3600;
lastTimeZoneSuffix = (offset<0?"-":"+") + new DecimalFormat("00").format(offset)+"00";
lastTimeZoneSuffixPerRaceID = new HashMap<String, String>();
startTimePerRaceID = new HashMap<String, TimePoint>();
receiverThread = new Thread(this, "SwissTiming SailMaster Receiver");
receiverThread.start();
synchronized (this) {
@@ -434,9 +442,14 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
String[] sections = message.getSections();
String raceID = sections[1];
RaceStatus status = RaceStatus.values()[Integer.valueOf(sections[2])];
TimePoint timePoint = new MillisecondsTimePoint(parseTimeAndDateISO(sections[3]));
TimePoint timePoint = new MillisecondsTimePoint(parseTimeAndDateISO(sections[3], raceID));
String dateISO = sections[3].substring(0, sections[3].indexOf('T'));
String startTimeEstimatedStartTimeISO = dateISO+"T"+sections[4]+lastTimeZoneSuffixPerRaceID.get(raceID);
TimePoint startTimeEstimatedStartTime = sections[4].trim().length() == 0 ? null : new MillisecondsTimePoint(
parseTimePrefixedWithISOToday(sections[4]));
parseTimeAndDateISO(startTimeEstimatedStartTimeISO, raceID));
if (startTimeEstimatedStartTime != null) {
startTimePerRaceID.put(raceID, startTimeEstimatedStartTime);
}
Long millisecondsSinceRaceStart = sections[5].trim().length() == 0 ? null : parseHHMMSSToMilliseconds(sections[5]);
Integer nextMarkIndexForLeader = sections[6].trim().length() == 0 ? null : Integer.valueOf(sections[6]);
Distance distanceToNextMarkForLeader = sections[7].trim().length() == 0 ? null : new MeterDistance(Double.valueOf(sections[7]));
@@ -504,10 +517,11 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
}
@Override
public void stop() throws IOException {
public synchronized void stop() throws IOException {
stopped = true;
socket.close();
socket = null;
notifyAll();
}
@Override
@@ -572,12 +586,17 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
}
}
private boolean canSendRequests() {
return canSendRequests;
}
@Override
public Iterable<Race> getRaces() throws UnknownHostException, IOException, InterruptedException {
Iterable<Race> result;
Iterable<Race> result = null;
if (messageLoader != null) {
result = messageLoader.getRaces();
} else {
}
if (result == null && canSendRequests()) {
SailMasterMessage response = sendRequestAndGetResponse(MessageType.RAC);
assertResponseType(MessageType.RAC, response);
result = parseAvailableRacesMessage(response);
@@ -616,17 +635,27 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
return new CourseImpl(courseConfigurationMessage.getSections()[1], marks);
}
private String prefixTimeWithISOTodayAndSuffixWithTimezoneIndicator(String time) {
private String getLastTimeZoneSuffix(String raceID) {
String result = lastTimeZoneSuffixPerRaceID.get(raceID);
if (result == null) {
int offset = TimeZone.getDefault().getOffset(System.currentTimeMillis())/1000/3600;
result = (offset<0?"-":"+") + new DecimalFormat("00").format(offset)+"00";
lastTimeZoneSuffixPerRaceID.put(raceID, result);
}
return result;
}
private String prefixTimeWithISOTodayAndSuffixWithTimezoneIndicator(String time, String raceID) {
synchronized (dateFormat) {
return dateFormat.format(new Date()).substring(0, "yyyy-mm-ddT".length())+time+lastTimeZoneSuffix;
return dateFormat.format(new Date()).substring(0, "yyyy-mm-ddT".length())+time+getLastTimeZoneSuffix(raceID);
}
}
private Date parseTimeAndDateISO(String timeAndDateISO) throws ParseException {
private Date parseTimeAndDateISO(String timeAndDateISO, String raceID) throws ParseException {
char timeZoneIndicator = timeAndDateISO.charAt(timeAndDateISO.length()-6);
if ((timeZoneIndicator == '+' || timeZoneIndicator == '-') && timeAndDateISO.charAt(timeAndDateISO.length()-3) == ':') {
timeAndDateISO = timeAndDateISO.substring(0, timeAndDateISO.length()-3)+timeAndDateISO.substring(timeAndDateISO.length()-2);
lastTimeZoneSuffix = timeAndDateISO.substring(timeAndDateISO.length()-5);
lastTimeZoneSuffixPerRaceID.put(raceID, timeAndDateISO.substring(timeAndDateISO.length()-5));
}
synchronized(dateFormat) {
return dateFormat.parse(timeAndDateISO);
@@ -694,16 +723,23 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
@Override
public TimePoint getStartTime(String raceID) throws UnknownHostException, IOException, ParseException, InterruptedException {
SailMasterMessage response = sendRequestAndGetResponse(MessageType.STT, raceID);
String[] sections = response.getSections();
assertResponseType(MessageType.STT, response);
assertRaceID(raceID, sections[1]);
return new MillisecondsTimePoint(parseTimePrefixedWithISOToday(sections[2]));
TimePoint result = null;
if (messageLoader != null) {
result = startTimePerRaceID.get(raceID);
}
if (result == null && canSendRequests()) {
SailMasterMessage response = sendRequestAndGetResponse(MessageType.STT, raceID);
String[] sections = response.getSections();
assertResponseType(MessageType.STT, response);
assertRaceID(raceID, sections[1]);
result = new MillisecondsTimePoint(parseTimePrefixedWithISOToday(sections[2], raceID));
}
return result;
}
private Date parseTimePrefixedWithISOToday(String timeHHMMSS) throws ParseException {
private Date parseTimePrefixedWithISOToday(String timeHHMMSS, String raceID) throws ParseException {
synchronized(dateFormat) {
return dateFormat.parse(prefixTimeWithISOTodayAndSuffixWithTimezoneIndicator(timeHHMMSS));
return dateFormat.parse(prefixTimeWithISOTodayAndSuffixWithTimezoneIndicator(timeHHMMSS, raceID));
}
}
@@ -795,7 +831,7 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
String[] clockAtMarkDetail = clockAtMarkMessage.getSections()[3+i].split(";");
int markIndex = Integer.valueOf(clockAtMarkDetail[0]);
TimePoint timePoint = clockAtMarkDetail.length <= 1 || clockAtMarkDetail[1].trim().length() == 0 ? null :
new MillisecondsTimePoint(parseTimePrefixedWithISOToday(clockAtMarkDetail[1]));
new MillisecondsTimePoint(parseTimePrefixedWithISOToday(clockAtMarkDetail[1], clockAtMarkMessage.getRaceID()));
result.add(new Triple<Integer, TimePoint, String>(
markIndex, timePoint, clockAtMarkDetail.length <= 2 ? null : clockAtMarkDetail[2]));
}
@@ -35,15 +35,15 @@ public class SwissTimingFactoryImpl implements SwissTimingFactory {
}
@Override
public SailMasterConnector getOrCreateSailMasterConnector(String host, int port, RaceSpecificMessageLoader messageLoader) throws InterruptedException {
public SailMasterConnector getOrCreateSailMasterConnector(String host, int port, RaceSpecificMessageLoader messageLoader, boolean canSendRequests) throws InterruptedException {
Triple<String, Integer, RaceSpecificMessageLoader> key = new Triple<String, Integer, RaceSpecificMessageLoader>(host, port, messageLoader);
SailMasterConnector result = connectors.get(key);
if (result == null) {
result = new SailMasterConnectorImpl(host, port, messageLoader);
result = new SailMasterConnectorImpl(host, port, messageLoader, canSendRequests);
connectors.put(key, result);
// TODO how do connectors get stopped, terminated and removed from the connectors map again?
} else if (result.isStopped()) {
result = new SailMasterConnectorImpl(host, port, messageLoader);
result = new SailMasterConnectorImpl(host, port, messageLoader, canSendRequests);
connectors.put(key, result);
}
return result;
@@ -55,10 +55,12 @@ public class SwissTimingFactoryImpl implements SwissTimingFactory {
}
@Override
public SwissTimingRaceTracker createRaceTracker(String raceID, String hostname, int port, WindStore windStore,
RaceSpecificMessageLoader messageLoader, DomainFactory domainFactory, TrackedEventRegistry trackedEventRegistry)
throws InterruptedException, UnknownHostException, IOException, ParseException {
return new SwissTimingRaceTrackerImpl(raceID, hostname, port, windStore, domainFactory, this, messageLoader, trackedEventRegistry);
public SwissTimingRaceTracker createRaceTracker(String raceID, String hostname, int port, boolean canSendRequests,
WindStore windStore, RaceSpecificMessageLoader messageLoader, DomainFactory domainFactory, TrackedEventRegistry trackedEventRegistry)
throws InterruptedException, UnknownHostException, IOException,
ParseException {
return new SwissTimingRaceTrackerImpl(raceID, hostname, port, windStore, domainFactory, this, messageLoader,
trackedEventRegistry, canSendRequests);
}
@Override
@@ -67,17 +67,18 @@ public class SwissTimingRaceTrackerImpl implements SwissTimingRaceTracker, SailM
protected SwissTimingRaceTrackerImpl(String raceID, String hostname, int port, WindStore windStore,
DomainFactory domainFactory, SwissTimingFactory factory, RaceSpecificMessageLoader messageLoader,
TrackedEventRegistry trackedEventRegistry) throws InterruptedException, UnknownHostException, IOException, ParseException {
this.connector = factory.getOrCreateSailMasterConnector(hostname, port, messageLoader);
TrackedEventRegistry trackedEventRegistry, boolean canSendRequests) throws InterruptedException, UnknownHostException, IOException, ParseException {
this.connector = factory.getOrCreateSailMasterConnector(hostname, port, messageLoader, canSendRequests);
this.domainFactory = domainFactory;
this.raceID = raceID;
this.messageLoader = messageLoader;
this.windStore = windStore;
this.id = new Triple<String, String, Integer>(raceID, hostname, port);
connector.addSailMasterListener(raceID, this);
connector.trackRace(raceID);
event = domainFactory.getOrCreateEvent(raceID);
trackedEvent = trackedEventRegistry.getOrCreateTrackedEvent(event);
connector.trackRace(raceID);
}
@Override
@@ -190,7 +191,7 @@ public class SwissTimingRaceTrackerImpl implements SwissTimingRaceTracker, SailM
for (Triple<Integer, Integer, Long> markIndexRankAndTimeSinceStartInMilliseconds : markIndicesRanksAndTimesSinceStartInMilliseconds) {
Waypoint waypoint = Util.get(trackedRace.getRace().getCourse().getWaypoints(),
markIndexRankAndTimeSinceStartInMilliseconds.getA());
MillisecondsTimePoint timePoint = new MillisecondsTimePoint(trackedRace.getStart().asMillis()
MillisecondsTimePoint timePoint = trackedRace.getStart()==null?null:new MillisecondsTimePoint(trackedRace.getStart().asMillis()
+ markIndexRankAndTimeSinceStartInMilliseconds.getC());
MarkPassing markPassing = domainFactory.createMarkPassing(raceID, boatID, waypoint, timePoint);
markPassingsByMarkIndex.put(markIndexRankAndTimeSinceStartInMilliseconds.getA(), markPassing);
@@ -218,15 +219,15 @@ public class SwissTimingRaceTrackerImpl implements SwissTimingRaceTracker, SailM
assert startList != null;
assert course != null;
// now we can create the RaceDefinition and most other things
Race race = messageLoader.getRace(raceID);
final RaceDefinition raceDefinition = domainFactory.createRaceDefinition(event, race, startList, course);
trackedRace = getTrackedEvent().createTrackedRace(raceDefinition, windStore,
Race swissTimingRace = messageLoader.getRace(raceID);
race = domainFactory.createRaceDefinition(event, swissTimingRace, startList, course);
trackedRace = getTrackedEvent().createTrackedRace(race, windStore,
WindTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_WIND, GPSFixTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_SPEED,
new DynamicRaceDefinitionSet() {
@Override
public void addRaceDefinition(RaceDefinition race) {
// we already know our single RaceDefinition
assert raceDefinition == race;
assert SwissTimingRaceTrackerImpl.this.race == race;
}
});
}
@@ -11,7 +11,6 @@ import java.net.URL;
import java.nio.charset.Charset;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import com.sap.sailing.domain.base.Competitor;
@@ -20,8 +19,9 @@ import com.sap.sailing.domain.tractracadapter.DomainFactory;
import com.sap.sailing.domain.tractracadapter.TracTracRaceTracker;
import com.sap.sailing.domain.tractracadapter.impl.DomainFactoryImpl;
@Ignore
public class UnicodeCharactersInCompetitorNamesTest {
protected static final boolean tractracTunnel = Boolean.valueOf(System.getProperty("tractrac.tunnel", "false"));
protected static final String tractracTunnelHost = System.getProperty("tractrac.tunnel.host", "localhost");
private DomainFactory domainFactory;
@Before
@@ -36,14 +36,14 @@ public class UnicodeCharactersInCompetitorNamesTest {
t.testFindUnicodeCharactersInCompetitorNames();
}
@Ignore
@Test
public void testFindUnicodeCharactersInCompetitorNames() throws MalformedURLException, FileNotFoundException, URISyntaxException {
TracTracRaceTracker fourtyninerYellow_2 = domainFactory
.createRaceTracker(
new URL(
"http://germanmaster.traclive.dk/events/event_20110609_KielerWoch/clientparams.php?event=event_20110609_KielerWoch&race=5b08a9ee-9933-11e0-85be-406186cbf87c"),
new URI("tcp://germanmaster.traclive.dk:1520"), new URI("tcp://germanmaster.traclive.dk:1521"),
tractracTunnel ? new URI("tcp://"+tractracTunnelHost+":4412") : new URI("tcp://germanmaster.traclive.dk:4400"),
tractracTunnel ? new URI("tcp://"+tractracTunnelHost+":4413") : new URI("tcp://germanmaster.traclive.dk:4401"),
EmptyWindStore.INSTANCE, new DummyTrackedEventRegistry());
Iterable<Competitor> competitors = fourtyninerYellow_2.getRaceHandle().getRace().getCompetitors();
@@ -46,6 +46,13 @@ public class Util {
}
}
public static <T> boolean isEmpty(Iterable<T> ts) {
if (ts instanceof Collection<?>) {
return ((Collection<?>) ts).isEmpty();
} else {
return !ts.iterator().hasNext();
}
}
public static class Pair<A, B> {
@@ -4,6 +4,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TabPanel;
@@ -36,10 +38,10 @@ public class AdminConsole extends AbstractEntryPoint implements EventRefresher {
eventDisplayers.add(windPanel);
windPanel.setSize("90%", "90%");
tabPanel.add(windPanel, stringConstants.wind(), /* asHTML */ false);
//final RaceMapPanel raceMapPanel = new RaceMapPanel(sailingService, this, this, stringConstants);
//eventDisplayers.add(raceMapPanel);
//raceMapPanel.setSize("90%", "90%");
//tabPanel.add(raceMapPanel, stringConstants.map(), /* asHTML */ false);
final RaceMapPanel raceMapPanel = new RaceMapPanel(sailingService, this, this, stringConstants);
eventDisplayers.add(raceMapPanel);
raceMapPanel.setSize("90%", "90%");
tabPanel.add(raceMapPanel, stringConstants.map(), /* asHTML */ false);
LeaderboardPanel defaultLeaderboardPanel = new LeaderboardPanel(sailingService, stringConstants.defaultLeaderboard(), this, stringConstants);
defaultLeaderboardPanel.setSize("90%", "90%");
tabPanel.add(defaultLeaderboardPanel, stringConstants.defaultLeaderboard(), /* asHTML */ false);
@@ -49,14 +51,14 @@ public class AdminConsole extends AbstractEntryPoint implements EventRefresher {
eventDisplayers.add(leaderboardConfigPanel);
tabPanel.selectTab(0);
/*tabPanel.addSelectionHandler(new SelectionHandler<Integer>() {
tabPanel.addSelectionHandler(new SelectionHandler<Integer>() {
@Override
public void onSelection(SelectionEvent<Integer> event) {
if(raceMapPanel.isVisible()) {
raceMapPanel.onResize();
}
}
});*/
});
fillEvents();
}
@@ -28,7 +28,7 @@ public class ExpandCollapseButtonCell extends AbstractCell<SafeHtml> {
this.column = column;
this.delegate = delegate;
this.html = new SafeHtmlBuilder().appendHtmlConstant(
"<input class=\"valignMiddle\" type=\"image\" src=\"/images/"+(column.isExpanded()?"close":"open")+".png\" />").toSafeHtml();
"<input class=\"valignMiddle\" type=\"image\" src=\"/images/"+(column.isExpanded()?"magnifier_slashed":"magnifier")+".png\" />").toSafeHtml();
}
@Override
@@ -15,7 +15,7 @@ import com.sap.sailing.gwt.ui.shared.LeaderboardEntryDAO;
import com.sap.sailing.gwt.ui.shared.MarkDAO;
import com.sap.sailing.gwt.ui.shared.Pair;
import com.sap.sailing.gwt.ui.shared.QuickRankDAO;
import com.sap.sailing.gwt.ui.shared.RaceRecordDAO;
import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDAO;
import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationDAO;
import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDAO;
import com.sap.sailing.gwt.ui.shared.TracTracConfigurationDAO;
@@ -32,9 +32,9 @@ public interface SailingService extends RemoteService {
List<EventDAO> listEvents();
Pair<String, List<RaceRecordDAO>> listTracTracRacesInEvent(String eventJsonURL) throws Exception;
Pair<String, List<TracTracRaceRecordDAO>> listTracTracRacesInEvent(String eventJsonURL) throws Exception;
void track(RaceRecordDAO rr, String liveURI, String storedURI, boolean trackWind, boolean correctWindByDeclination) throws Exception;
void track(TracTracRaceRecordDAO rr, String liveURI, String storedURI, boolean trackWind, boolean correctWindByDeclination) throws Exception;
void storeTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI) throws Exception;
@@ -108,10 +108,10 @@ public interface SailingService extends RemoteService {
List<SwissTimingConfigurationDAO> getPreviousSwissTimingConfigurations();
List<SwissTimingRaceRecordDAO> listSwissTimingRaces(String hostname, int port) throws Exception;
List<SwissTimingRaceRecordDAO> listSwissTimingRaces(String hostname, int port, boolean canSendRequests) throws Exception;
void storeSwissTimingConfiguration(String a, String hostname, int port);
void trackWithSwissTiming(SwissTimingRaceRecordDAO rr, String hostname, int port, boolean trackWind,
boolean correctWindByDeclination) throws Exception;
void trackWithSwissTiming(SwissTimingRaceRecordDAO rr, String hostname, int port, boolean canSendRequests,
boolean trackWind, boolean correctWindByDeclination) throws Exception;
}
@@ -17,7 +17,7 @@ import com.sap.sailing.gwt.ui.shared.LeaderboardEntryDAO;
import com.sap.sailing.gwt.ui.shared.MarkDAO;
import com.sap.sailing.gwt.ui.shared.Pair;
import com.sap.sailing.gwt.ui.shared.QuickRankDAO;
import com.sap.sailing.gwt.ui.shared.RaceRecordDAO;
import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDAO;
import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationDAO;
import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDAO;
import com.sap.sailing.gwt.ui.shared.TracTracConfigurationDAO;
@@ -33,15 +33,15 @@ public interface SailingServiceAsync {
/**
* The string returned in the callback's pair is the common event name
*/
void listTracTracRacesInEvent(String eventJsonURL, AsyncCallback<Pair<String, List<RaceRecordDAO>>> callback);
void listTracTracRacesInEvent(String eventJsonURL, AsyncCallback<Pair<String, List<TracTracRaceRecordDAO>>> callback);
/**
* @param liveURI may be <code>null</code> or the empty string in which case the server will
* use the {@link RaceRecordDAO#liveURI} from the <code>rr</code> race record.
* use the {@link TracTracRaceRecordDAO#liveURI} from the <code>rr</code> race record.
* @param storedURImay be <code>null</code> or the empty string in which case the server will
* use the {@link RaceRecordDAO#storedURI} from the <code>rr</code> race record.
* use the {@link TracTracRaceRecordDAO#storedURI} from the <code>rr</code> race record.
*/
void track(RaceRecordDAO rr, String liveURI, String storedURI, boolean trackWind, boolean correctWindByDeclination,
void track(TracTracRaceRecordDAO rr, String liveURI, String storedURI, boolean trackWind, boolean correctWindByDeclination,
AsyncCallback<Void> callback);
void getPreviousTracTracConfigurations(AsyncCallback<List<TracTracConfigurationDAO>> callback);
@@ -162,10 +162,11 @@ public interface SailingServiceAsync {
void getPreviousSwissTimingConfigurations(AsyncCallback<List<SwissTimingConfigurationDAO>> asyncCallback);
void listSwissTimingRaces(String hostname, int port, AsyncCallback<List<SwissTimingRaceRecordDAO>> asyncCallback);
void listSwissTimingRaces(String hostname, int port, boolean canSendRequests,
AsyncCallback<List<SwissTimingRaceRecordDAO>> asyncCallback);
void storeSwissTimingConfiguration(String a, String hostname, int port, AsyncCallback<Void> asyncCallback);
void trackWithSwissTiming(SwissTimingRaceRecordDAO rr, String hostname, int port, boolean trackWind,
boolean correctWindByDeclination, AsyncCallback<Void> asyncCallback);
void trackWithSwissTiming(SwissTimingRaceRecordDAO rr, String hostname, int port, boolean canSendRequests,
boolean trackWind, boolean correctWindByDeclination, AsyncCallback<Void> asyncCallback);
}
@@ -137,7 +137,7 @@ public class SwissTimingEventManagementPanel extends FormPanel implements EventD
TextColumn<SwissTimingRaceRecordDAO> raceStartTrackingColumn = new TextColumn<SwissTimingRaceRecordDAO>() {
@Override
public String getValue(SwissTimingRaceRecordDAO object) {
return object.raceStartTime.toString();
return object.raceStartTime==null?"":object.raceStartTime.toString();
}
};
raceNameColumn.setSortable(true);
@@ -267,7 +267,8 @@ public class SwissTimingEventManagementPanel extends FormPanel implements EventD
private void fillRaces(final SailingServiceAsync sailingService) {
final String hostname = hostnameTextbox.getValue();
final int port = portIntegerbox.getValue();
sailingService.listSwissTimingRaces(hostname, port, new AsyncCallback<List<SwissTimingRaceRecordDAO>>() {
sailingService.listSwissTimingRaces(hostname, port, /* TODO canSendRequests */ false,
new AsyncCallback<List<SwissTimingRaceRecordDAO>>() {
@Override
public void onFailure(Throwable caught) {
SwissTimingEventManagementPanel.this.errorReporter.reportError("Error trying to list races: "
@@ -309,7 +310,8 @@ public class SwissTimingEventManagementPanel extends FormPanel implements EventD
int port = portIntegerbox.getValue();
for (final SwissTimingRaceRecordDAO rr : raceList.getList()) {
if (raceTable.getSelectionModel().isSelected(rr)) {
sailingService.trackWithSwissTiming(rr, hostname, port, trackWind, correctWindByDeclination, new AsyncCallback<Void>() {
sailingService.trackWithSwissTiming(rr, hostname, port, /* TODO canSendRequests */false, trackWind,
correctWindByDeclination, new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError("Error trying to register race " + rr.ID + " for tracking: "
@@ -33,7 +33,7 @@ import com.google.gwt.view.client.MultiSelectionModel;
import com.sap.sailing.gwt.ui.shared.EventDAO;
import com.sap.sailing.gwt.ui.shared.Pair;
import com.sap.sailing.gwt.ui.shared.RaceDAO;
import com.sap.sailing.gwt.ui.shared.RaceRecordDAO;
import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDAO;
import com.sap.sailing.gwt.ui.shared.RegattaDAO;
import com.sap.sailing.gwt.ui.shared.TracTracConfigurationDAO;
import com.sap.sailing.gwt.ui.shared.Triple;
@@ -61,8 +61,8 @@ public class TracTracEventManagementPanel extends FormPanel implements EventDisp
private final IntegerBox livePortIntegerbox;
private final TextBox hostnameTextbox;
private final TextBox eventNameTextbox;
private final ListDataProvider<RaceRecordDAO> raceList;
private final CellTable<RaceRecordDAO> raceTable;
private final ListDataProvider<TracTracRaceRecordDAO> raceList;
private final CellTable<TracTracRaceRecordDAO> raceTable;
private final Map<String, TracTracConfigurationDAO> previousConfigurations;
private final ListBox previousConfigurationsComboBox;
private final Grid grid;
@@ -208,28 +208,28 @@ public class TracTracEventManagementPanel extends FormPanel implements EventDisp
Label lblTrackableRaces = new Label(stringConstants.trackableRaces());
grid.setWidget(5, 0, lblTrackableRaces);
TextColumn<RaceRecordDAO> raceNameColumn = new TextColumn<RaceRecordDAO>() {
TextColumn<TracTracRaceRecordDAO> raceNameColumn = new TextColumn<TracTracRaceRecordDAO>() {
@Override
public String getValue(RaceRecordDAO object) {
public String getValue(TracTracRaceRecordDAO object) {
return object.name;
}
};
TextColumn<RaceRecordDAO> raceStartTrackingColumn = new TextColumn<RaceRecordDAO>() {
TextColumn<TracTracRaceRecordDAO> raceStartTrackingColumn = new TextColumn<TracTracRaceRecordDAO>() {
@Override
public String getValue(RaceRecordDAO object) {
public String getValue(TracTracRaceRecordDAO object) {
return object.trackingStartTime.toString();
}
};
raceNameColumn.setSortable(true);
raceStartTrackingColumn.setSortable(true);
raceTable = new CellTable<RaceRecordDAO>(/* pageSize */ 100);
raceTable = new CellTable<TracTracRaceRecordDAO>(/* pageSize */ 100);
raceTable.addColumn(raceNameColumn, stringConstants.name());
raceTable.addColumn(raceStartTrackingColumn, stringConstants.raceStartTrackingColumn());
grid.setWidget(6, 0, raceTable);
grid.getCellFormatter().setHeight(6, 0, "100%");
raceTable.setWidth("100%");
raceTable.setSelectionModel(new MultiSelectionModel<RaceRecordDAO>() {});
raceList = new ListDataProvider<RaceRecordDAO>();
raceTable.setSelectionModel(new MultiSelectionModel<TracTracRaceRecordDAO>() {});
raceList = new ListDataProvider<TracTracRaceRecordDAO>();
raceList.addDataDisplay(raceTable);
Handler columnSortHandler = getRaceTableColumnSortHandler(raceList.getList(), raceNameColumn, raceStartTrackingColumn);
raceTable.addColumnSortHandler(columnSortHandler);
@@ -304,18 +304,18 @@ public class TracTracEventManagementPanel extends FormPanel implements EventDisp
});
}
private ListHandler<RaceRecordDAO> getRaceTableColumnSortHandler(List<RaceRecordDAO> raceRecords,
Column<RaceRecordDAO, ?> nameColumn, Column<RaceRecordDAO, ?> trackingStartColumn) {
ListHandler<RaceRecordDAO> result = new ListHandler<RaceRecordDAO>(raceRecords);
result.setComparator(nameColumn, new Comparator<RaceRecordDAO>() {
private ListHandler<TracTracRaceRecordDAO> getRaceTableColumnSortHandler(List<TracTracRaceRecordDAO> raceRecords,
Column<TracTracRaceRecordDAO, ?> nameColumn, Column<TracTracRaceRecordDAO, ?> trackingStartColumn) {
ListHandler<TracTracRaceRecordDAO> result = new ListHandler<TracTracRaceRecordDAO>(raceRecords);
result.setComparator(nameColumn, new Comparator<TracTracRaceRecordDAO>() {
@Override
public int compare(RaceRecordDAO o1, RaceRecordDAO o2) {
public int compare(TracTracRaceRecordDAO o1, TracTracRaceRecordDAO o2) {
return o1.name.compareTo(o2.name);
}
});
result.setComparator(trackingStartColumn, new Comparator<RaceRecordDAO>() {
result.setComparator(trackingStartColumn, new Comparator<TracTracRaceRecordDAO>() {
@Override
public int compare(RaceRecordDAO o1, RaceRecordDAO o2) {
public int compare(TracTracRaceRecordDAO o1, TracTracRaceRecordDAO o2) {
return o1.trackingStartTime == null ? -1 : o2.trackingStartTime == null ? 1 : o1.trackingStartTime
.compareTo(o2.trackingStartTime);
}
@@ -368,7 +368,7 @@ public class TracTracEventManagementPanel extends FormPanel implements EventDisp
final String jsonURL = jsonURLBox.getValue();
final String liveDataURI = liveURIBox.getValue();
final String storedDataURI = storedURIBox.getValue();
sailingService.listTracTracRacesInEvent(jsonURL, new AsyncCallback<Pair<String, List<RaceRecordDAO>>>() {
sailingService.listTracTracRacesInEvent(jsonURL, new AsyncCallback<Pair<String, List<TracTracRaceRecordDAO>>>() {
@Override
public void onFailure(Throwable caught) {
TracTracEventManagementPanel.this.errorReporter.reportError("Error trying to list races: "
@@ -376,7 +376,7 @@ public class TracTracEventManagementPanel extends FormPanel implements EventDisp
}
@Override
public void onSuccess(final Pair<String, List<RaceRecordDAO>> result) {
public void onSuccess(final Pair<String, List<TracTracRaceRecordDAO>> result) {
raceList.getList().clear();
if (result.getB() != null) {
raceList.getList().addAll(result.getB());
@@ -407,7 +407,7 @@ public class TracTracEventManagementPanel extends FormPanel implements EventDisp
private void trackSelectedRaces(boolean trackWind, boolean correctWindByDeclination) {
String liveURI = liveURIBox.getValue();
String storedURI = storedURIBox.getValue();
for (final RaceRecordDAO rr : raceList.getList()) {
for (final TracTracRaceRecordDAO rr : raceList.getList()) {
if (raceTable.getSelectionModel().isSelected(rr)) {
sailingService.track(rr, liveURI, storedURI, trackWind, correctWindByDeclination, new AsyncCallback<Void>() {
@Override
@@ -49,8 +49,6 @@ import com.sap.sailing.domain.leaderboard.ScoreCorrection.MaxPointsReason;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.domain.persistence.MongoWindStoreFactory;
import com.sap.sailing.domain.swisstimingadapter.Race;
import com.sap.sailing.domain.swisstimingadapter.SailMasterConnector;
import com.sap.sailing.domain.swisstimingadapter.SwissTimingConfiguration;
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
import com.sap.sailing.domain.swisstimingadapter.persistence.SwissTimingAdapterPersistence;
@@ -83,12 +81,12 @@ import com.sap.sailing.gwt.ui.shared.Pair;
import com.sap.sailing.gwt.ui.shared.PositionDAO;
import com.sap.sailing.gwt.ui.shared.QuickRankDAO;
import com.sap.sailing.gwt.ui.shared.RaceDAO;
import com.sap.sailing.gwt.ui.shared.RaceRecordDAO;
import com.sap.sailing.gwt.ui.shared.RegattaDAO;
import com.sap.sailing.gwt.ui.shared.SpeedWithBearingDAO;
import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationDAO;
import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDAO;
import com.sap.sailing.gwt.ui.shared.TracTracConfigurationDAO;
import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDAO;
import com.sap.sailing.gwt.ui.shared.WindDAO;
import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDAO;
import com.sap.sailing.gwt.ui.shared.WindTrackInfoDAO;
@@ -278,7 +276,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
for (Map.Entry<BoatClass, Set<RaceDefinition>> e : racesByBoatClass.entrySet()) {
List<RaceDAO> raceDAOsInBoatClass = getRaceDAOs(event, e.getValue());
if (!raceDAOsInBoatClass.isEmpty()) {
RegattaDAO regatta = new RegattaDAO(new BoatClassDAO(e.getKey().getName()), raceDAOsInBoatClass);
RegattaDAO regatta = new RegattaDAO(new BoatClassDAO(e.getKey()==null?"":e.getKey().getName()), raceDAOsInBoatClass);
result.add(regatta);
}
}
@@ -319,22 +317,22 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
}
@Override
public Pair<String, List<RaceRecordDAO>> listTracTracRacesInEvent(String eventJsonURL) throws MalformedURLException, IOException,
public Pair<String, List<TracTracRaceRecordDAO>> listTracTracRacesInEvent(String eventJsonURL) throws MalformedURLException, IOException,
ParseException, org.json.simple.parser.ParseException, URISyntaxException {
com.sap.sailing.util.Util.Pair<String,List<RaceRecord>> raceRecords;
raceRecords = getService().getTracTracRaceRecords(new URL(eventJsonURL));
List<RaceRecordDAO> result = new ArrayList<RaceRecordDAO>();
List<TracTracRaceRecordDAO> result = new ArrayList<TracTracRaceRecordDAO>();
for (RaceRecord raceRecord : raceRecords.getB()) {
result.add(new RaceRecordDAO(raceRecord.getID(), raceRecord.getEventName(), raceRecord.getName(),
result.add(new TracTracRaceRecordDAO(raceRecord.getID(), raceRecord.getEventName(), raceRecord.getName(),
raceRecord.getParamURL().toString(), raceRecord.getReplayURL(), raceRecord.getLiveURI().toString(),
raceRecord.getStoredURI().toString(), raceRecord.getTrackingStartTime().asDate(), raceRecord
.getTrackingEndTime().asDate(), raceRecord.getRaceStartTime().asDate()));
}
return new Pair<String, List<RaceRecordDAO>>(raceRecords.getA(), result);
return new Pair<String, List<TracTracRaceRecordDAO>>(raceRecords.getA(), result);
}
@Override
public void track(RaceRecordDAO rr, String liveURI, String storedURI, boolean trackWind, final boolean correctWindByDeclination) throws Exception {
public void track(TracTracRaceRecordDAO rr, String liveURI, String storedURI, boolean trackWind, final boolean correctWindByDeclination) throws Exception {
if (liveURI == null || liveURI.trim().length() == 0) {
liveURI = rr.liveURI;
}
@@ -1020,14 +1018,11 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
}
@Override
public List<SwissTimingRaceRecordDAO> listSwissTimingRaces(String hostname, int port)
public List<SwissTimingRaceRecordDAO> listSwissTimingRaces(String hostname, int port, boolean canSendRequests)
throws UnknownHostException, IOException, InterruptedException, ParseException {
List<SwissTimingRaceRecordDAO> result = new ArrayList<SwissTimingRaceRecordDAO>();
// FIXME can't rely on the connector being able to send a request; perhaps need to extract from SwissTiming persistence
SailMasterConnector swissTimingConnector = swissTimingFactory.getOrCreateSailMasterConnector(hostname, port, swissTimingAdapterPersistence);
for (Race race : swissTimingConnector.getRaces()) {
TimePoint startTime = swissTimingConnector.getStartTime(race.getRaceID());
result.add(new SwissTimingRaceRecordDAO(race.getRaceID(), race.getDescription(), startTime.asDate()));
for (com.sap.sailing.domain.swisstimingadapter.RaceRecord rr : getService().getSwissTimingRaceRecords(hostname, port, canSendRequests)) {
result.add(new SwissTimingRaceRecordDAO(rr.getRaceID(), rr.getDescription(), rr.getStartTime()));
}
return result;
}
@@ -1038,9 +1033,9 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
}
@Override
public void trackWithSwissTiming(SwissTimingRaceRecordDAO rr, String hostname, int port, boolean trackWind,
final boolean correctWindByDeclination) throws Exception {
final RaceHandle raceHandle = getService().addSwissTimingRace(rr.ID, hostname, port,
public void trackWithSwissTiming(SwissTimingRaceRecordDAO rr, String hostname, int port, boolean canSendRequests,
boolean trackWind, final boolean correctWindByDeclination) throws Exception {
final RaceHandle raceHandle = getService().addSwissTimingRace(rr.ID, hostname, port, canSendRequests,
MongoWindStoreFactory.INSTANCE.getMongoWindStore(mongoObjectFactory, domainObjectFactory),
TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS);
if (trackWind) {
@@ -4,7 +4,7 @@ import java.util.Date;
import com.google.gwt.user.client.rpc.IsSerializable;
public class RaceRecordDAO implements IsSerializable {
public class TracTracRaceRecordDAO implements IsSerializable {
public String eventName;
public String name;
public String replayURL;
@@ -16,9 +16,9 @@ public class RaceRecordDAO implements IsSerializable {
public Date trackingEndTime;
public Date raceStartTime;
public RaceRecordDAO() {}
public TracTracRaceRecordDAO() {}
public RaceRecordDAO(String id, String eventName, String name, String paramURL,
public TracTracRaceRecordDAO(String id, String eventName, String name, String paramURL,
String replayURL, String liveURI, String storedURI, Date trackingStartTime, Date trackingEndTime, Date raceStartTime) {
super();
this.eventName = eventName;
@@ -13,7 +13,7 @@ import com.sap.sailing.gwt.ui.client.StringConstants;
import com.sap.sailing.gwt.ui.shared.LeaderboardDAO;
import com.sap.sailing.gwt.ui.shared.LeaderboardRowDAO;
import com.sap.sailing.gwt.ui.shared.Pair;
import com.sap.sailing.gwt.ui.shared.RaceRecordDAO;
import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDAO;
public class TestColumnToggling extends GWTTestCase {
@@ -31,7 +31,7 @@ public class TestColumnToggling extends GWTTestCase {
private LeaderboardDAO leaderboard;
private RaceRecordDAO rrDao;
private TracTracRaceRecordDAO rrDao;
private ExpandableSortableColumn<LeaderboardRowDAO> rc;
@@ -51,7 +51,7 @@ public class TestColumnToggling extends GWTTestCase {
}
private void listRacesInEvent(){
service.listTracTracRacesInEvent(JSON_URL, new AsyncCallback<Pair<String,List<RaceRecordDAO>>>() {
service.listTracTracRacesInEvent(JSON_URL, new AsyncCallback<Pair<String,List<TracTracRaceRecordDAO>>>() {
@Override
public void onFailure(Throwable caught) {
@@ -59,9 +59,9 @@ public class TestColumnToggling extends GWTTestCase {
}
@Override
public void onSuccess(Pair<String, List<RaceRecordDAO>> result) {
public void onSuccess(Pair<String, List<TracTracRaceRecordDAO>> result) {
System.out.println("Listed races.");
for (RaceRecordDAO rr : result.getB()){
for (TracTracRaceRecordDAO rr : result.getB()){
if (rr.name.equals(TRACKED_RACE)){
rrDao = rr;
}
@@ -1,3 +1,2 @@
# Module com.sap.sailing.gwt.ui.AdminConsole
# RPC service class, partial path of RPC policy file
com.sap.sailing.gwt.ui.client.SailingService, 931D125823BB96957462DA30D18BF8B1.gwt.rpc
Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

@@ -137,6 +137,9 @@ public interface RacingEventService extends TrackedEventRegistry {
*/
Pair<String, List<RaceRecord>> getTracTracRaceRecords(URL jsonURL) throws IOException, ParseException,
org.json.simple.parser.ParseException, URISyntaxException;
List<com.sap.sailing.domain.swisstimingadapter.RaceRecord> getSwissTimingRaceRecords(String hostname, int port, boolean canSendRequests)
throws InterruptedException, UnknownHostException, IOException, ParseException;
boolean isRaceBeingTracked(RaceDefinition r);
@@ -177,8 +180,8 @@ public interface RacingEventService extends TrackedEventRegistry {
*/
void updateStoredLeaderboard(Leaderboard leaderboard);
RaceHandle addSwissTimingRace(String raceID, String hostname, int port, WindStore windStore,
long timeoutInMilliseconds) throws InterruptedException, UnknownHostException, IOException, ParseException;
RaceHandle addSwissTimingRace(String raceID, String hostname, int port, boolean canSendRequests,
WindStore windStore, long timeoutInMilliseconds) throws InterruptedException, UnknownHostException, IOException, ParseException;
SwissTimingFactory getSwissTimingFactory();
@@ -27,12 +27,15 @@ import java.util.logging.Logger;
import com.sap.sailing.domain.base.ControlPoint;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.TimePoint;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.impl.LeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl;
import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.domain.swisstimingadapter.Race;
import com.sap.sailing.domain.swisstimingadapter.SailMasterConnector;
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
import com.sap.sailing.domain.swisstimingadapter.persistence.SwissTimingAdapterPersistence;
import com.sap.sailing.domain.tracking.DynamicTrackedEvent;
@@ -231,13 +234,27 @@ public class RacingEventServiceImpl implements RacingEventService {
}
@Override
public synchronized RaceHandle addSwissTimingRace(String raceID, String hostname, int port, WindStore windStore,
long timeoutInMilliseconds) throws InterruptedException, UnknownHostException, IOException, ParseException {
public List<com.sap.sailing.domain.swisstimingadapter.RaceRecord> getSwissTimingRaceRecords(String hostname,
int port, boolean canSendRequests) throws InterruptedException, UnknownHostException, IOException, ParseException {
List<com.sap.sailing.domain.swisstimingadapter.RaceRecord> result = new ArrayList<com.sap.sailing.domain.swisstimingadapter.RaceRecord>();
SailMasterConnector swissTimingConnector = swissTimingFactory.getOrCreateSailMasterConnector(hostname, port, swissTimingAdapterPersistence,
canSendRequests);
for (Race race : swissTimingConnector.getRaces()) {
TimePoint startTime = swissTimingConnector.getStartTime(race.getRaceID());
result.add(new com.sap.sailing.domain.swisstimingadapter.RaceRecord(race.getRaceID(), race.getDescription(),
startTime==null?null:startTime.asDate()));
}
return result;
}
@Override
public synchronized RaceHandle addSwissTimingRace(String raceID, String hostname, int port, boolean canSendRequests,
WindStore windStore, long timeoutInMilliseconds) throws InterruptedException, UnknownHostException, IOException, ParseException {
Triple<String, String, Integer> key = new Triple<String, String, Integer>(raceID, hostname, port);
RaceTracker tracker = raceTrackersByID.get(key);
if (tracker == null) {
tracker = getSwissTimingFactory().createRaceTracker(raceID, hostname, port, windStore,
swissTimingAdapterPersistence, swissTimingDomainFactory, this);
tracker = getSwissTimingFactory().createRaceTracker(raceID, hostname, port, canSendRequests,
windStore, swissTimingAdapterPersistence, swissTimingDomainFactory, this);
raceTrackersByID.put(tracker.getID(), tracker);
Set<RaceTracker> trackers = raceTrackersByEvent.get(tracker.getEvent());
if (trackers == null) {
@@ -17,7 +17,6 @@ import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.Leg;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Speed;
import com.sap.sailing.domain.base.SpeedWithBearing;
import com.sap.sailing.domain.base.TimePoint;
import com.sap.sailing.domain.tracking.TrackedLeg;
import com.sap.sailing.domain.tracking.TrackedLeg.LegType;
@@ -96,12 +95,14 @@ public class RankPerLeg extends Action {
addColumn("" + (distanceSailed == null ? "null" : distanceSailed.getMeters()));
// position and tracking-related columns (see Kersten's mail of 2011-10-07T11:32:00CEST)
/*
SpeedWithBearing speedOverGround = trackedLegOfCompetitor.getSpeedOverGround(time);
addColumn(""+(speedOverGround==null?"null":speedOverGround.getKnots()));
Double estimatedTimeToNextMarkInSeconds = trackedLegOfCompetitor.getEstimatedTimeToNextMarkInSeconds(time);
addColumn(""+(estimatedTimeToNextMarkInSeconds==null?"null":estimatedTimeToNextMarkInSeconds));
Speed velocityMadeGood = trackedLegOfCompetitor.getVelocityMadeGood(time);
addColumn(""+(velocityMadeGood==null ? "null" : velocityMadeGood.getKnots()));
*/
}
}
previousLeg = trackedLeg;
@@ -17,7 +17,6 @@ import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.Leg;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Speed;
import com.sap.sailing.domain.base.SpeedWithBearing;
import com.sap.sailing.domain.base.TimePoint;
import com.sap.sailing.domain.tracking.TrackedLeg;
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
@@ -88,7 +87,7 @@ public class RankPerLeg2 extends Action {
addColumn(upOrDownwindLegText);
addColumn(legId);
if (legTime > 0) {
addColumn(legId + " " + markName);
addColumn(legId + " " + markName + "(" + upOrDownwinLeg + ")");
} else {
addColumn(markName);
}
@@ -126,6 +125,7 @@ public class RankPerLeg2 extends Action {
// position and tracking-related columns (see Kersten's
// mail
// of 2011-10-07T11:32:00CEST)
/*
SpeedWithBearing speedOverGround = trackedLegOfCompetitor.getSpeedOverGround(time);
addColumn("" + (speedOverGround == null ? "null" : speedOverGround.getKnots()));
Double estimatedTimeToNextMarkInSeconds = trackedLegOfCompetitor
@@ -133,7 +133,7 @@ public class RankPerLeg2 extends Action {
addColumn(""
+ (estimatedTimeToNextMarkInSeconds == null ? "null" : estimatedTimeToNextMarkInSeconds));
Speed velocityMadeGood = trackedLegOfCompetitor.getVelocityMadeGood(time);
addColumn("" + (velocityMadeGood == null ? "null" : velocityMadeGood.getKnots()));
addColumn("" + (velocityMadeGood == null ? "null" : velocityMadeGood.getKnots()));*/
}
}
previousLeg = trackedLeg;