Merge remote-tracking branch 'origin/gwt' into gwt-5

Conflicts:
	java/com.sap.sailing.domain.swisstimingadapter.persistence/src/com/sap/sailing/domain/swisstimingadapter/persistence/impl/SwissTimingAdapterPersistenceImpl.java
This commit is contained in:
fmittag committed 2011-11-25 14:24:32 +01:00
commit 0fd38bb5b2
57 files changed
+1177 -467

No files matched your search

@@ -18,25 +18,30 @@ import com.sap.sailing.domain.swisstimingadapter.SailMasterMessage;
import com.sap.sailing.domain.swisstimingadapter.SwissTimingConfiguration;
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
import com.sap.sailing.domain.swisstimingadapter.persistence.SwissTimingAdapterPersistence;
import com.sap.sailing.mongodb.MongoDBService;
public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPersistence {
private final DB database;
private final SwissTimingFactory swissTimingFactory;
private static final Logger logger = Logger.getLogger(SwissTimingAdapterPersistenceImpl.class.getName());
/** this race cache should only be used for checks in the storeSailMasterMessage method to ensure
* that we have always a valid race for a message (also in case we missed a RAC message)
private final SwissTimingFactory swissTimingFactory;
private static final Logger logger = Logger.getLogger(SwissTimingAdapterPersistenceImpl.class.getName());
private final DBCollection lastMessageCountCollection;
/**
* this race cache should only be used for checks in the storeSailMasterMessage method to ensure that we have always
* a valid race for a message (also in case we missed a RAC message)
*/
private HashMap<String, Race> cachedRaces = new HashMap<String, Race>();
public SwissTimingAdapterPersistenceImpl(MongoDBService mongoDB, SwissTimingFactory swissTimingFactory) {
private long lastMessageCount;
public SwissTimingAdapterPersistenceImpl(DB db, SwissTimingFactory swissTimingFactory) {
super();
this.database = mongoDB.getDB();
this.database = db;
this.swissTimingFactory = swissTimingFactory;
lastMessageCountCollection = db.getCollection(CollectionNames.LAST_MESSAGE_COUNT.name());
init();
}
@@ -49,22 +54,22 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
indexKeysRaceMsgs.put(FieldNames.RACE_ID.name(), 1);
racesMessageCollection.ensureIndex(indexKeysRaceMsgs, IndexNames.INDEX_RACES_MESSAGES.name(), true);
// ensure the required indexes for the collection of command messages
DBCollection cmdMessagesCollection = database.getCollection(CollectionNames.COMMAND_MESSAGES.name());
BasicDBObject indexKeysCmdMsgs = new BasicDBObject();
indexKeysCmdMsgs.put(FieldNames.MESSAGE_SEQUENCE_NUMBER.name(), 1);
cmdMessagesCollection.ensureIndex(indexKeysCmdMsgs, IndexNames.INDEX_COMMAND_MESSAGES.name(), true);
// initially fill the races cache
Iterable<Race> races = getRaces();
for(Race race: races) {
for (Race race : races) {
cachedRaces.put(race.getRaceID(), race);
}
}
@Override
public Iterable<SwissTimingConfiguration> getSwissTimingConfigurations() {
List<SwissTimingConfiguration> result = new ArrayList<SwissTimingConfiguration>();
@@ -75,8 +80,9 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
result.add(stConfig);
}
} catch (Throwable t) {
// something went wrong during DB access; report, then use empty new wind track
logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load recorded TracTrac configurations. Check MongoDB settings.");
// something went wrong during DB access; report, then use empty new wind track
logger.log(Level.SEVERE,
"Error connecting to MongoDB, unable to load recorded TracTrac configurations. Check MongoDB settings.");
logger.throwing(SwissTimingAdapterPersistenceImpl.class.getName(), "getTracTracConfigurations", t);
}
return result;
@@ -85,9 +91,8 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
private SwissTimingConfiguration loadSwissTimingConfiguration(DBObject object) {
Boolean canSendRequests = (Boolean) object.get(FieldNames.ST_CONFIG_CAN_SEND_REQUESTS.name());
return swissTimingFactory.createSwissTimingConfiguration((String) object.get(FieldNames.ST_CONFIG_NAME.name()),
(String) object.get(FieldNames.ST_CONFIG_HOSTNAME.name()),
(Integer) object.get(FieldNames.ST_CONFIG_PORT.name()),
canSendRequests==null?false:canSendRequests);
(String) object.get(FieldNames.ST_CONFIG_HOSTNAME.name()), (Integer) object
.get(FieldNames.ST_CONFIG_PORT.name()), canSendRequests == null ? false : canSendRequests);
}
@Override
@@ -111,11 +116,12 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
DBCollection racesMessagesCollection = database.getCollection(CollectionNames.RACES_MESSAGES.name());
BasicDBObject query = new BasicDBObject();
query.append(FieldNames.RACE_ID.name(), raceID);
DBCursor results = racesMessagesCollection.find(query).sort(new BasicDBObject().append(FieldNames.MESSAGE_SEQUENCE_NUMBER.name(), 1));
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()));
SailMasterMessage msg = swissTimingFactory.createMessage((String) o.get(FieldNames.MESSAGE_CONTENT.name()),
(Long) o.get(FieldNames.MESSAGE_SEQUENCE_NUMBER.name()));
result.add(msg);
}
return result;
@@ -124,17 +130,17 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
@Override
public List<SailMasterMessage> loadCommandMessages() {
DBCollection cmdMessagesCollection = database.getCollection(CollectionNames.COMMAND_MESSAGES.name());
DBCursor results = cmdMessagesCollection.find().sort(new BasicDBObject().append(FieldNames.MESSAGE_SEQUENCE_NUMBER.name(), 1));
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()));
SailMasterMessage msg = swissTimingFactory.createMessage((String) o.get(FieldNames.MESSAGE_CONTENT.name()),
(Long) o.get(FieldNames.MESSAGE_SEQUENCE_NUMBER.name()));
result.add(msg);
}
return result;
}
@Override
public Race getRace(String raceID) {
DBCollection races = database.getCollection(CollectionNames.RACES_MASTERDATA.name());
@@ -143,9 +149,9 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
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()),
startTimeAsMillis == null ? null : new MillisecondsTimePoint(startTimeAsMillis));
Race race = swissTimingFactory.createRace((String) o.get(FieldNames.RACE_ID.name()), (String) o
.get(FieldNames.RACE_DESCRIPTION.name()), startTimeAsMillis == null ? null
: new MillisecondsTimePoint(startTimeAsMillis));
return race;
}
return null;
@@ -158,9 +164,9 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
List<Race> result = new ArrayList<Race>();
for (DBObject o : results) {
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()),
startTimeAsMillis == null ? null : new MillisecondsTimePoint(startTimeAsMillis));
Race race = swissTimingFactory.createRace((String) o.get(FieldNames.RACE_ID.name()), (String) o
.get(FieldNames.RACE_DESCRIPTION.name()), startTimeAsMillis == null ? null
: new MillisecondsTimePoint(startTimeAsMillis));
result.add(race);
}
return result;
@@ -178,7 +184,7 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
result.put(FieldNames.ST_CONFIG_HOSTNAME.name(), swissTimingConfiguration.getHostname());
result.put(FieldNames.ST_CONFIG_PORT.name(), swissTimingConfiguration.getPort());
result.put(FieldNames.ST_CONFIG_CAN_SEND_REQUESTS.name(), swissTimingConfiguration.canSendRequests());
stConfigCollection.insert(result);
}
@@ -194,6 +200,14 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
if(type.isRaceSpecific()) {
objToInsert.put(FieldNames.RACE_ID.name(), message.getRaceID());
messageCollection = database.getCollection(CollectionNames.RACES_MESSAGES.name());
if (message.getSequenceNumber() == null){
DBObject emptyQuery = new BasicDBObject();
DBObject incrementLastMessageCountQuery = new BasicDBObject().
append("$inc", new BasicDBObject().append(FieldNames.LAST_MESSAGE_COUNT.name(), 1));
DBObject newCountRecord = lastMessageCountCollection.findAndModify(emptyQuery, incrementLastMessageCountQuery);
lastMessageCount = (Long) newCountRecord.get(FieldNames.LAST_MESSAGE_COUNT.name());
objToInsert.put(FieldNames.MESSAGE_SEQUENCE_NUMBER.name(), lastMessageCount);
}
} else {
messageCollection = database.getCollection(CollectionNames.COMMAND_MESSAGES.name());
}
@@ -226,8 +240,8 @@ 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(";");
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;
@@ -241,8 +255,9 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
BasicDBObject result = new BasicDBObject();
result.put(FieldNames.RACE_ID.name(), race.getRaceID());
result.put(FieldNames.RACE_DESCRIPTION.name(), race.getDescription());
result.put(FieldNames.RACE_STARTTIME.name(), race.getStartTime() == null ? null : new Long(race.getStartTime().asMillis()));
racesCollection.update(query, result, /* upsrt */ true, /* multi */ false);
result.put(FieldNames.RACE_STARTTIME.name(), race.getStartTime() == null ? null : new Long(race.getStartTime()
.asMillis()));
racesCollection.update(query, result, /* upsrt */true, /* multi */false);
}
@Override
@@ -250,7 +265,7 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
DBCollection racesCollection = database.getCollection(CollectionNames.RACES_MASTERDATA.name());
racesCollection.drop();
}
@Override
public void dropAllMessageData() {
DBCollection racesMessageCollection = database.getCollection(CollectionNames.RACES_MESSAGES.name());
@@ -1,3 +1,3 @@
RAC|1|W4702;A simulated SwissTiming race
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
CCG|W4702|6|0;StartGate;M1;M7|1;Buoy6;M6|2;LeeGate;M2;M3|3;Buoy6;M6|4;Buoy5;M5|5;FinishGate;M1;M4
@@ -153,8 +153,8 @@ public class EndToEndListeningStoreAndFowardTest {
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()));
assertEquals(6, Util.size(race.getCourse().getWaypoints()));
assertEquals(5, 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",
@@ -32,7 +32,7 @@ import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
import com.sap.sailing.domain.swisstimingadapter.SwissTimingRaceTracker;
import com.sap.sailing.domain.tracking.AbstractRaceTrackerImpl;
import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet;
import com.sap.sailing.domain.tracking.DynamicTrack;
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
import com.sap.sailing.domain.tracking.DynamicTrackedEvent;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.GPSFix;
@@ -158,12 +158,12 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl implemen
case UNIDENTIFIED:
String trackerID = fix.getBoatID();
Buoy buoy = domainFactory.getOrCreateBuoy(trackerID);
DynamicTrack<Buoy, GPSFix> buoyTrack = trackedRace.getOrCreateTrack(buoy);
DynamicGPSFixTrack<Buoy, GPSFix> buoyTrack = trackedRace.getOrCreateTrack(buoy);
buoyTrack.addGPSFix(gpsFix);
break;
case COMPETITOR:
Competitor competitor = domainFactory.getCompetitorByBoatID(fix.getBoatID());
DynamicTrack<Competitor, GPSFixMoving> competitorTrack = trackedRace.getTrack(competitor);
DynamicGPSFixTrack<Competitor, GPSFixMoving> competitorTrack = trackedRace.getTrack(competitor);
competitorTrack.addGPSFix(gpsFix);
break;
default:
@@ -11,7 +11,7 @@ import org.junit.Ignore;
import org.junit.Test;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.tracking.DynamicTrack;
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
import com.sap.sailing.domain.tracking.DynamicTrackedEvent;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.GPSFix;
@@ -36,11 +36,11 @@ import com.sap.sailing.domain.tractracadapter.ReceiverType;
*/
@Ignore("Un-ignore when you need to fetch new tracks")
public class FetchTracksAndStoreLocallyTest extends KielWeek2011BasedTest {
private final Map<Competitor, DynamicTrack<Competitor, GPSFixMoving>> tracks;
private final Map<Competitor, DynamicGPSFixTrack<Competitor, GPSFixMoving>> tracks;
private TrackedRace trackedRace;
public FetchTracksAndStoreLocallyTest() throws URISyntaxException, MalformedURLException {
tracks = new HashMap<Competitor, DynamicTrack<Competitor,GPSFixMoving>>();
tracks = new HashMap<Competitor, DynamicGPSFixTrack<Competitor,GPSFixMoving>>();
}
/**
@@ -54,7 +54,7 @@ public class FetchTracksAndStoreLocallyTest extends KielWeek2011BasedTest {
final RaceChangeListener<Competitor> positionListener = new RaceChangeListener<Competitor>() {
@Override
public void gpsFixReceived(GPSFix fix, Competitor competitor) {
DynamicTrack<Competitor, GPSFixMoving> track = tracks.get(competitor);
DynamicGPSFixTrack<Competitor, GPSFixMoving> track = tracks.get(competitor);
if (track == null) {
track = new DynamicGPSFixMovingTrackImpl<Competitor>(competitor, /* millisecondsOverWhichToAverage */ 40000);
tracks.put(competitor, track);
@@ -172,9 +172,9 @@ public class FetchTracksAndStoreLocallyTest extends KielWeek2011BasedTest {
}
private void storeTracks() throws FileNotFoundException, IOException {
for (Map.Entry<Competitor, DynamicTrack<Competitor, GPSFixMoving>> competitorAndTrack : tracks.entrySet()) {
for (Map.Entry<Competitor, DynamicGPSFixTrack<Competitor, GPSFixMoving>> competitorAndTrack : tracks.entrySet()) {
Competitor competitor = competitorAndTrack.getKey();
DynamicTrack<Competitor, GPSFixMoving> track = competitorAndTrack.getValue();
DynamicGPSFixTrack<Competitor, GPSFixMoving> track = competitorAndTrack.getValue();
storeTrack(competitor, track, getEvent().getName()+"-"+trackedRace.getRace().getName());
}
}
@@ -55,7 +55,7 @@ public class ManeuverDetectionOnKielerWoche505Race2DataTest extends KielWeek2011
TimePoint firstWindwardMarkPassing = hassosMarkPassingsIter.next().getTimePoint();
GPSFix[] firstLegFineApproximation = dp.approximate(new MeterDistance(20), startMarkPassing, firstWindwardMarkPassing);
assertNotNull(firstLegFineApproximation);
assertEquals(11, firstLegFineApproximation.length);
assertEquals(9, firstLegFineApproximation.length);
GPSFix[] firstLegCoarseApproximation = dp.approximate(new MeterDistance(50), startMarkPassing, firstWindwardMarkPassing);
assertNotNull(firstLegCoarseApproximation);
assertEquals(4, firstLegCoarseApproximation.length);
@@ -31,7 +31,7 @@ import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.tracking.DynamicTrack;
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.impl.DynamicGPSFixMovingTrackImpl;
import com.sap.sailing.domain.tracking.impl.GPSFixMovingImpl;
@@ -39,8 +39,8 @@ import com.sap.sailing.domain.tracking.impl.GPSFixMovingImpl;
public abstract class StoredTrackBasedTest extends TrackBasedTest {
private static final String RESOURCES = "resources/";
protected DynamicTrack<Competitor, GPSFixMoving> readTrack(Competitor competitor, String eventName) throws FileNotFoundException, IOException {
DynamicTrack<Competitor, GPSFixMoving> track = null;
protected DynamicGPSFixTrack<Competitor, GPSFixMoving> readTrack(Competitor competitor, String eventName) throws FileNotFoundException, IOException {
DynamicGPSFixTrack<Competitor, GPSFixMoving> track = null;
if (getFile(competitor, eventName).exists()) {
ObjectInput oi = getInputStream(competitor, eventName);
track = new DynamicGPSFixMovingTrackImpl<Competitor>(competitor, /* millisecondsOverWhichToAverage */
@@ -97,7 +97,7 @@ public abstract class StoredTrackBasedTest extends TrackBasedTest {
return new GPSFixMovingImpl(position, timePoint, speedWithBearing);
}
protected void storeTrack(Competitor competitor, DynamicTrack<Competitor, GPSFixMoving> track, String eventName)
protected void storeTrack(Competitor competitor, DynamicGPSFixTrack<Competitor, GPSFixMoving> track, String eventName)
throws FileNotFoundException, IOException {
ObjectOutput oo = getOutputStream(competitor, eventName);
for (GPSFixMoving fix : track.getRawFixes()) {
@@ -106,15 +106,15 @@ public abstract class StoredTrackBasedTest extends TrackBasedTest {
oo.close();
}
protected Map<Competitor, DynamicTrack<Competitor, GPSFixMoving>> loadTracks() throws FileNotFoundException, IOException {
Map<Competitor, DynamicTrack<Competitor, GPSFixMoving>> tracks = new HashMap<Competitor, DynamicTrack<Competitor,GPSFixMoving>>();
protected Map<Competitor, DynamicGPSFixTrack<Competitor, GPSFixMoving>> loadTracks() throws FileNotFoundException, IOException {
Map<Competitor, DynamicGPSFixTrack<Competitor, GPSFixMoving>> tracks = new HashMap<Competitor, DynamicGPSFixTrack<Competitor,GPSFixMoving>>();
final String KIELER_WOCHE = "Kieler Woche";
for (String competitorName : getCompetitorNamesOfStoredTracks(KIELER_WOCHE)) {
Person p = new PersonImpl(competitorName, /* nationality */ null, /* dateOfBirth */ null, /* description */ null);
Team t = new TeamImpl(competitorName, Collections.singleton(p), /* coach */ null);
Competitor c = new CompetitorImpl(competitorName, competitorName, t, new BoatImpl(competitorName,
new BoatClassImpl("505"), null));
DynamicTrack<Competitor, GPSFixMoving> track = readTrack(c, KIELER_WOCHE);
DynamicGPSFixTrack<Competitor, GPSFixMoving> track = readTrack(c, KIELER_WOCHE);
if (track != null) {
tracks.put(c, track);
}
@@ -9,7 +9,7 @@ import java.util.Map;
import org.junit.Before;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.tracking.DynamicTrack;
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.impl.MarkPassingImpl;
@@ -17,14 +17,14 @@ import com.sap.sailing.domain.tracking.impl.MarkPassingImpl;
public class StoredTrackBasedTestWithTrackedRace extends StoredTrackBasedTest {
@Before
public void setUp() throws FileNotFoundException, IOException {
Map<Competitor, DynamicTrack<Competitor, GPSFixMoving>> tracks = loadTracks();
Map<Competitor, DynamicGPSFixTrack<Competitor, GPSFixMoving>> tracks = loadTracks();
setTrackedRace(createTestTrackedRace("Kieler Woche", "505 Race 2", "505", tracks.keySet()));
copyTracks(tracks);
}
private void copyTracks(Map<Competitor, DynamicTrack<Competitor, GPSFixMoving>> tracks) {
for (Map.Entry<Competitor, DynamicTrack<Competitor, GPSFixMoving>> e : tracks.entrySet()) {
DynamicTrack<Competitor, GPSFixMoving> track = getTrackedRace().getTrack(e.getKey());
private void copyTracks(Map<Competitor, DynamicGPSFixTrack<Competitor, GPSFixMoving>> tracks) {
for (Map.Entry<Competitor, DynamicGPSFixTrack<Competitor, GPSFixMoving>> e : tracks.entrySet()) {
DynamicGPSFixTrack<Competitor, GPSFixMoving> track = getTrackedRace().getTrack(e.getKey());
for (GPSFixMoving fix : e.getValue().getRawFixes()) {
track.addGPSFix(fix);
}
@@ -19,7 +19,7 @@ import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.base.impl.NationalityImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.tracking.DynamicTrack;
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.NoWindException;
import com.sap.sailing.domain.tracking.Wind;
@@ -50,7 +50,7 @@ public class TackTest extends StoredTrackBasedTestWithTrackedRace {
@Test
public void testStarboardTack() throws NoWindException {
DynamicTrack<Competitor, GPSFixMoving> hassosTrack = getTrackedRace().getTrack(competitor);
DynamicGPSFixTrack<Competitor, GPSFixMoving> hassosTrack = getTrackedRace().getTrack(competitor);
MillisecondsTimePoint now = MillisecondsTimePoint.now();
hassosTrack.addGPSFix(new GPSFixMovingImpl(new DegreePosition(54.4680424, 10.234451), now,
new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(45))));
@@ -59,7 +59,7 @@ public class TackTest extends StoredTrackBasedTestWithTrackedRace {
@Test
public void testPortTack() throws NoWindException {
DynamicTrack<Competitor, GPSFixMoving> hassosTrack = getTrackedRace().getTrack(competitor);
DynamicGPSFixTrack<Competitor, GPSFixMoving> hassosTrack = getTrackedRace().getTrack(competitor);
MillisecondsTimePoint now = MillisecondsTimePoint.now();
hassosTrack.addGPSFix(new GPSFixMovingImpl(new DegreePosition(54.4680424, 10.234451), now,
new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(270))));
@@ -68,7 +68,7 @@ public class TackTest extends StoredTrackBasedTestWithTrackedRace {
@Test
public void testStarboardTackForZeroDifference() throws NoWindException {
DynamicTrack<Competitor, GPSFixMoving> hassosTrack = getTrackedRace().getTrack(competitor);
DynamicGPSFixTrack<Competitor, GPSFixMoving> hassosTrack = getTrackedRace().getTrack(competitor);
MillisecondsTimePoint now = MillisecondsTimePoint.now();
hassosTrack.addGPSFix(new GPSFixMovingImpl(new DegreePosition(54.4680424, 10.234451), now,
new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(180))));
@@ -18,7 +18,7 @@ import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Distance;
import com.sap.sailing.domain.base.Speed;
import com.sap.sailing.domain.base.TimePoint;
import com.sap.sailing.domain.tracking.DynamicTrack;
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.impl.GPSFixMovingImpl;
@@ -33,10 +33,10 @@ import com.sap.sailing.domain.tracking.impl.GPSFixMovingImpl;
*
*/
public class TrackSmootheningTest extends StoredTrackBasedTest {
private final Map<Competitor, DynamicTrack<Competitor, GPSFixMoving>> tracks;
private final Map<Competitor, DynamicGPSFixTrack<Competitor, GPSFixMoving>> tracks;
public TrackSmootheningTest() throws URISyntaxException, MalformedURLException {
tracks = new HashMap<Competitor, DynamicTrack<Competitor,GPSFixMoving>>();
tracks = new HashMap<Competitor, DynamicGPSFixTrack<Competitor,GPSFixMoving>>();
}
/**
@@ -54,8 +54,8 @@ public class TrackSmootheningTest extends StoredTrackBasedTest {
return "Kieler Woche";
}
private DynamicTrack<Competitor, GPSFixMoving> getTrackByCompetitorName(String name) {
for (Map.Entry<Competitor, DynamicTrack<Competitor, GPSFixMoving>> e : tracks.entrySet()) {
private DynamicGPSFixTrack<Competitor, GPSFixMoving> getTrackByCompetitorName(String name) {
for (Map.Entry<Competitor, DynamicGPSFixTrack<Competitor, GPSFixMoving>> e : tracks.entrySet()) {
if (e.getKey().getName().equals(name)) {
return e.getValue();
}
@@ -63,12 +63,12 @@ public class TrackSmootheningTest extends StoredTrackBasedTest {
return null;
}
protected void assertOutlierInTrack(DynamicTrack<Competitor, GPSFixMoving> track) {
protected void assertOutlierInTrack(DynamicGPSFixTrack<Competitor, GPSFixMoving> track) {
GPSFixMoving outlier = getAnyOutlier(track.getRawFixes());
assertNotNull(outlier); // assert that we found an outlier
}
protected void assertNoOutlierInSmoothenedTrack(DynamicTrack<Competitor, GPSFixMoving> track) {
protected void assertNoOutlierInSmoothenedTrack(DynamicGPSFixTrack<Competitor, GPSFixMoving> track) {
Iterable<GPSFixMoving> fixes = track.getFixes();
GPSFixMoving outlier = getAnyOutlier(fixes);
assertNull("Found unexpected outlier "+outlier+" in smoothened track", outlier); // assert that we did not find an outlier
@@ -102,7 +102,7 @@ public class TrackSmootheningTest extends StoredTrackBasedTest {
@Test
public void assertBirknersEquatorJump() {
DynamicTrack<Competitor, GPSFixMoving> track = getTrackByCompetitorName("Birkner");
DynamicGPSFixTrack<Competitor, GPSFixMoving> track = getTrackByCompetitorName("Birkner");
assertNotNull(track);
assertOutlierInTrack(track);
assertNoOutlierInSmoothenedTrack(track);
@@ -110,7 +110,7 @@ public class TrackSmootheningTest extends StoredTrackBasedTest {
@Test
public void assertPlattnersKielerFoerdeJump() {
DynamicTrack<Competitor, GPSFixMoving> track = getTrackByCompetitorName("Dr.Plattner");
DynamicGPSFixTrack<Competitor, GPSFixMoving> track = getTrackByCompetitorName("Dr.Plattner");
assertNotNull(track);
assertOutlierInTrack(track);
assertNoOutlierInSmoothenedTrack(track);
@@ -45,30 +45,37 @@ public class TrackTest {
@Before
public void setUp() throws InterruptedException {
track = new DynamicGPSFixMovingTrackImpl<Boat>(new BoatImpl("MyFirstBoat",
new BoatClassImpl("505"), null), /* millisecondsOverWhichToAverage */ 5000);
new BoatClassImpl("505"), null), /* millisecondsOverWhichToAverage */ 5000, /* no smoothening */ null);
TimePoint now1 = MillisecondsTimePoint.now();
waitThreeMillis();
TimePoint now2 = MillisecondsTimePoint.now();
DegreePosition position1 = new DegreePosition(1, 2);
DegreePosition position2 = new DegreePosition(1, 3);
gpsFix1 = new GPSFixMovingImpl(
new DegreePosition(1, 2), new MillisecondsTimePoint(
System.currentTimeMillis()), new KnotSpeedWithBearingImpl(1,
new DegreeBearingImpl(90)));
waitThreeMillis();
gpsFix2 = new GPSFixMovingImpl(
new DegreePosition(1, 3), new MillisecondsTimePoint(
System.currentTimeMillis()), new KnotSpeedWithBearingImpl(1,
position1, now1, new KnotSpeedWithBearingImpl(position1.getDistance(position2)
.inTime(now2.asMillis() - now1.asMillis()).getKnots(),
new DegreeBearingImpl(90)));
gpsFix2 = new GPSFixMovingImpl(position2, now2, new KnotSpeedWithBearingImpl(position1.getDistance(position2)
.inTime(now2.asMillis() - gpsFix1.getTimePoint().asMillis()).getKnots(), new DegreeBearingImpl(90)));
waitThreeMillis();
TimePoint now3 = MillisecondsTimePoint.now();
Position position3 = new DegreePosition(1, 4);
gpsFix3 = new GPSFixMovingImpl(
new DegreePosition(1, 4), new MillisecondsTimePoint(
System.currentTimeMillis()), new KnotSpeedWithBearingImpl(2,
position3, now3, new KnotSpeedWithBearingImpl(position2.getDistance(position3)
.inTime(now3.asMillis() - gpsFix2.getTimePoint().asMillis()).getKnots(),
new DegreeBearingImpl(0)));
waitThreeMillis();
TimePoint now4 = MillisecondsTimePoint.now();
Position position4 = new DegreePosition(3, 4);
gpsFix4 = new GPSFixMovingImpl(
new DegreePosition(3, 4), new MillisecondsTimePoint(
System.currentTimeMillis()), new KnotSpeedWithBearingImpl(2,
position4, now4, new KnotSpeedWithBearingImpl(position3.getDistance(position4)
.inTime(now4.asMillis() - gpsFix3.getTimePoint().asMillis()).getKnots(),
new DegreeBearingImpl(0)));
waitThreeMillis();
gpsFix5 = new GPSFixMovingImpl(
new DegreePosition(5, 4), new MillisecondsTimePoint(
System.currentTimeMillis()), new KnotSpeedWithBearingImpl(2, new DegreeBearingImpl(0)));
TimePoint now5 = MillisecondsTimePoint.now();
Position position5 = new DegreePosition(5, 4);
gpsFix5 = new GPSFixMovingImpl(position5, now5, new KnotSpeedWithBearingImpl(position4.getDistance(position5)
.inTime(now5.asMillis() - gpsFix4.getTimePoint().asMillis()).getKnots(), new DegreeBearingImpl(0)));
track.addGPSFix(gpsFix1);
track.addGPSFix(gpsFix2);
track.addGPSFix(gpsFix3);
@@ -282,21 +289,23 @@ public class TrackTest {
@Test
public void testFarFutureFixNotUsedDuringEstimation() {
GPSFixMovingImpl gpsFixFarInTheFuture = new GPSFixMovingImpl(
new DegreePosition(89, 180), new MillisecondsTimePoint(
System.currentTimeMillis()+10000000l), new KnotSpeedWithBearingImpl(200000, new DegreeBearingImpl(0)));
track.addGPSFix(gpsFixFarInTheFuture);
TimePoint normalFixesTime = null;
Iterator<GPSFixMoving> iter = track.getRawFixes().iterator();
TimePoint normalFixesTime = null;
for (int i=0; i<2; i++) {
normalFixesTime = iter.next().getTimePoint();
}
assertNotNull(normalFixesTime);
Position estimatedPos = track.getEstimatedPosition(normalFixesTime, /* extrapolate */ false);
assertEquals(1., estimatedPos.getLatDeg(), 0.5);
assertEquals(2, estimatedPos.getLngDeg(), 0.5);
SpeedWithBearing estimatedSpeed = track.getEstimatedSpeed(normalFixesTime);
assertEquals(1., estimatedSpeed.getKnots(), 0.001);
assertEquals(90., estimatedSpeed.getBearing().getDegrees(), 0.001);
GPSFixMovingImpl gpsFixFarInTheFuture = new GPSFixMovingImpl(
new DegreePosition(89, 180), new MillisecondsTimePoint(
System.currentTimeMillis()+10000000l), new KnotSpeedWithBearingImpl(200000, new DegreeBearingImpl(0)));
track.addGPSFix(gpsFixFarInTheFuture);
Position estimatedPosNew = track.getEstimatedPosition(normalFixesTime, /* extrapolate */ false);
// expecting to get the coordinates of gpsFix2's position
assertEquals(gpsFix2.getPosition().getLatDeg(), estimatedPosNew.getLatDeg(), 0.5);
assertEquals(gpsFix2.getPosition().getLngDeg(), estimatedPosNew.getLngDeg(), 0.5);
SpeedWithBearing estimatedSpeedNew = track.getEstimatedSpeed(normalFixesTime);
assertEquals(estimatedSpeed.getKnots(), estimatedSpeedNew.getKnots(), 0.001);
assertEquals(estimatedSpeed.getBearing().getDegrees(), estimatedSpeedNew.getBearing().getDegrees(), 0.001);
}
}
@@ -24,7 +24,7 @@ import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.base.impl.NationalityImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.tracking.DynamicTrack;
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.NoWindException;
@@ -78,7 +78,7 @@ public class WindEstimationOnConstructedTracksTest extends StoredTrackBasedTest
}
private void setBearingForCompetitor(Competitor competitor, MillisecondsTimePoint timePoint, double bearingDeg) {
DynamicTrack<Competitor, GPSFixMoving> hungersTrack = getTrackedRace().getTrack(competitor);
DynamicGPSFixTrack<Competitor, GPSFixMoving> hungersTrack = getTrackedRace().getTrack(competitor);
hungersTrack.addGPSFix(new GPSFixMovingImpl(new DegreePosition(54.4680424, 10.234451), timePoint,
new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(bearingDeg))));
}
@@ -14,7 +14,7 @@ import com.sap.sailing.domain.base.Tack;
import com.sap.sailing.domain.base.TimePoint;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet;
import com.sap.sailing.domain.tracking.DynamicTrack;
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
import com.sap.sailing.domain.tracking.DynamicTrackedEvent;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.GPSFix;
@@ -142,7 +142,7 @@ public class MockedTrackedRace implements DynamicTrackedRace {
}
@Override
public DynamicTrack<Buoy, GPSFix> getOrCreateTrack(Buoy buoy) {
public DynamicGPSFixTrack<Buoy, GPSFix> getOrCreateTrack(Buoy buoy) {
// TODO Auto-generated method stub
return null;
}
@@ -227,7 +227,7 @@ public class MockedTrackedRace implements DynamicTrackedRace {
}
@Override
public DynamicTrack<Competitor, GPSFixMoving> getTrack(Competitor competitor) {
public DynamicGPSFixTrack<Competitor, GPSFixMoving> getTrack(Competitor competitor) {
// TODO Auto-generated method stub
return null;
}
@@ -9,7 +9,7 @@ import com.sap.sailing.domain.base.Buoy;
import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.tracking.DynamicTrack;
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
import com.sap.sailing.domain.tracking.GPSFix;
import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.TrackedEvent;
@@ -109,7 +109,7 @@ public class MarkPositionReceiver extends AbstractReceiverWithQueue<ControlPoint
}
Buoy buoy = getDomainFactory().getBuoy(event.getA(), event.getB());
// FIXME during getTrackedRaceBlocking it seems as if trackedRace gets assigned a new, invalid instance
((DynamicTrack<Buoy, GPSFix>) getTrackedRaceBlocking().getOrCreateTrack(buoy)).addGPSFix(getDomainFactory()
((DynamicGPSFixTrack<Buoy, GPSFix>) getTrackedRaceBlocking().getOrCreateTrack(buoy)).addGPSFix(getDomainFactory()
.createGPSFixMoving(event.getB()));
}
@@ -23,7 +23,7 @@ import com.sap.sailing.domain.base.impl.DegreePosition;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.tracking.AbstractRaceTrackerImpl;
import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet;
import com.sap.sailing.domain.tracking.DynamicTrack;
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.GPSFix;
import com.sap.sailing.domain.tracking.RaceHandle;
@@ -157,7 +157,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
for (RaceDefinition raceDefinition : raceDefinitions) {
DynamicTrackedRace trackedRace = getTrackedEvent().getExistingTrackedRace(
raceDefinition);
DynamicTrack<Buoy, GPSFix> buoyTrack = trackedRace.getOrCreateTrack(buoy);
DynamicGPSFixTrack<Buoy, GPSFix> buoyTrack = trackedRace.getOrCreateTrack(buoy);
if (buoyTrack.getFirstRawFix() == null) {
buoyTrack.addGPSFix(new GPSFixImpl(new DegreePosition(first ? controlPoint
.getLat1() : controlPoint.getLat2(), first ? controlPoint.getLon1()
@@ -10,7 +10,7 @@ import java.util.ConcurrentModificationException;
*
* @author Axel Uhl (d043530)
*/
public interface DynamicTrack<ItemType, FixType extends GPSFix> extends
public interface DynamicGPSFixTrack<ItemType, FixType extends GPSFix> extends
GPSFixTrack<ItemType, FixType> {
/**
* Adds the <code>gpsFix</code> (or an object equal to it) to this track. Note: depending on the implementation,
@@ -12,13 +12,13 @@ public interface DynamicTrackedRace extends TrackedRace {
/**
* The raw, updating feed of a single competitor participating in this race
*/
DynamicTrack<Competitor, GPSFixMoving> getTrack(Competitor competitor);
DynamicGPSFixTrack<Competitor, GPSFixMoving> getTrack(Competitor competitor);
/**
* Yields the track describing <code>buoy</code>'s movement over time; never <code>null</code> because a
* new track will be created in case no track was present for <code>buoy</code> so far.
*/
DynamicTrack<Buoy, GPSFix> getOrCreateTrack(Buoy buoy);
DynamicGPSFixTrack<Buoy, GPSFix> getOrCreateTrack(Buoy buoy);
void addListener(RaceChangeListener<Competitor> listener);
@@ -15,10 +15,18 @@ import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.tracking.GPSFixMoving;
public class DynamicGPSFixMovingTrackImpl<ItemType> extends DynamicTrackImpl<ItemType, GPSFixMoving> {
private static final double MAX_SPEED_FACTOR_COMPARED_TO_MEASURED_SPEED_FOR_FILTERING = 2;
public DynamicGPSFixMovingTrackImpl(ItemType trackedItem, long millisecondsOverWhichToAverage) {
super(trackedItem, millisecondsOverWhichToAverage);
}
/**
* @param maxSpeedForSmoothening pass <code>null</code> if you don't want speed-based smoothening
*/
public DynamicGPSFixMovingTrackImpl(ItemType trackedItem, long millisecondsOverWhichToAverage, Speed maxSpeedForSmoothening) {
super(trackedItem, millisecondsOverWhichToAverage, maxSpeedForSmoothening);
}
/**
* This redefinition packs the <code>gpsFix</code> into a more compact representation that conserves
@@ -134,10 +142,31 @@ public class DynamicGPSFixMovingTrackImpl<ItemType> extends DynamicTrackImpl<Ite
return new KilometersPerHourSpeedImpl(sumInKMH/count);
}
/**
* In addition to the base class implementation, we additionally have the speed and bearing as
* measured by the device. We use the device-measured speed and compare it with the speed computed
* based on the timestamp and distance between previous and next fix. If the latter speed exceeds the
* measured speed by more than a factor of {@link #MAX_SPEED_FACTOR_COMPARED_TO_MEASURED_SPEED_FOR_FILTERING},
* the fix is considered invalid.
*/
@Override
protected NavigableSet<GPSFixMoving> getInternalFixes() {
// TODO perform even better smoothening than GPSFixTrackImpl because here we additionally have the speeds/bearings on the fixes as a hint
return super.getInternalFixes();
protected boolean isValid(PartialNavigableSetView<GPSFixMoving> filteredView, GPSFixMoving e) {
GPSFixMoving previous = filteredView.lowerInternal(e);
GPSFixMoving next = filteredView.higherInternal(e);
Speed speedToPrevious = Speed.NULL;
if (previous != null) {
speedToPrevious = previous.getPosition().getDistance(e.getPosition())
.inTime(e.getTimePoint().asMillis() - previous.getTimePoint().asMillis());
}
Speed speedToNext = Speed.NULL;
if (next != null) {
speedToNext = e.getPosition().getDistance(next.getPosition())
.inTime(next.getTimePoint().asMillis() - e.getTimePoint().asMillis());
}
return (previous == null || speedToPrevious.getMetersPerSecond() <= MAX_SPEED_FACTOR_COMPARED_TO_MEASURED_SPEED_FOR_FILTERING*e.getSpeed().getMetersPerSecond()) &&
(next == null || speedToNext.getMetersPerSecond() <= MAX_SPEED_FACTOR_COMPARED_TO_MEASURED_SPEED_FOR_FILTERING*e.getSpeed().getMetersPerSecond()) &&
(maxSpeedForSmoothening == null ||
(previous == null || speedToPrevious.compareTo(maxSpeedForSmoothening) <= 0) ||
(next == null || speedToNext.compareTo(maxSpeedForSmoothening) <= 0));
}
}
@@ -3,12 +3,13 @@ package com.sap.sailing.domain.tracking.impl;
import java.util.HashSet;
import java.util.Set;
import com.sap.sailing.domain.tracking.DynamicTrack;
import com.sap.sailing.domain.base.Speed;
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
import com.sap.sailing.domain.tracking.GPSFix;
import com.sap.sailing.domain.tracking.RaceChangeListener;
public class DynamicTrackImpl<ItemType, FixType extends GPSFix> extends
GPSFixTrackImpl<ItemType, FixType> implements DynamicTrack<ItemType, FixType> {
GPSFixTrackImpl<ItemType, FixType> implements DynamicGPSFixTrack<ItemType, FixType> {
private final Set<RaceChangeListener<ItemType>> listeners;
public DynamicTrackImpl(ItemType trackedItem, long millisecondsOverWhichToAverage) {
@@ -16,6 +17,11 @@ public class DynamicTrackImpl<ItemType, FixType extends GPSFix> extends
this.listeners = new HashSet<RaceChangeListener<ItemType>>();
}
public DynamicTrackImpl(ItemType trackedItem, long millisecondsOverWhichToAverage, Speed maxSpeedForSmoothening) {
super(trackedItem, millisecondsOverWhichToAverage, maxSpeedForSmoothening);
this.listeners = new HashSet<RaceChangeListener<ItemType>>();
}
@Override
public void addGPSFix(FixType gpsFix) {
synchronized (this) {
@@ -15,7 +15,7 @@ import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.TimePoint;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.tracking.DynamicTrack;
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
import com.sap.sailing.domain.tracking.DynamicTrackedEvent;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.GPSFix;
@@ -39,7 +39,7 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements
WindStore windStore, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed) {
super(trackedEvent, race, windStore, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed);
for (Competitor competitor : getRace().getCompetitors()) {
DynamicTrack<Competitor, GPSFixMoving> track = getTrack(competitor);
DynamicGPSFixTrack<Competitor, GPSFixMoving> track = getTrack(competitor);
track.addListener(this);
}
for (WindSource windSource : WindSource.values()) {
@@ -49,7 +49,7 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements
@Override
public synchronized void recordFix(Competitor competitor, GPSFixMoving fix) {
DynamicTrack<Competitor, GPSFixMoving> track = getTrack(competitor);
DynamicGPSFixTrack<Competitor, GPSFixMoving> track = getTrack(competitor);
track.addGPSFix(fix); // the track notifies this tracked race which in turn notifies its listeners
if (getStart() == null || getStart().compareTo(fix.getTimePoint())>0) {
// infer race start time from fix; earliest fix received defines start if earlier than assumed start so far
@@ -80,13 +80,13 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements
}
@Override
public DynamicTrack<Competitor, GPSFixMoving> getTrack(Competitor competitor) {
return (DynamicTrack<Competitor, GPSFixMoving>) super.getTrack(competitor);
public DynamicGPSFixTrack<Competitor, GPSFixMoving> getTrack(Competitor competitor) {
return (DynamicGPSFixTrack<Competitor, GPSFixMoving>) super.getTrack(competitor);
}
@Override
public DynamicTrack<Buoy, GPSFix> getOrCreateTrack(Buoy buoy) {
return (DynamicTrack<Buoy, GPSFix>) super.getOrCreateTrack(buoy);
public DynamicGPSFixTrack<Buoy, GPSFix> getOrCreateTrack(Buoy buoy) {
return (DynamicGPSFixTrack<Buoy, GPSFix>) super.getOrCreateTrack(buoy);
}
private synchronized Set<RaceChangeListener<Competitor>> getListeners() {
@@ -260,7 +260,7 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements
long result = 0; // default in case there is no competitor
Iterator<Competitor> compIter = getRace().getCompetitors().iterator();
if (compIter.hasNext()) {
DynamicTrack<Competitor, GPSFixMoving> someTrack = getTrack(compIter.next());
DynamicGPSFixTrack<Competitor, GPSFixMoving> someTrack = getTrack(compIter.next());
result = someTrack.getMillisecondsOverWhichToAverageSpeed();
}
return result;
@@ -21,15 +21,23 @@ import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.GPSFixTrack;
public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl<FixType> implements GPSFixTrack<ItemType, FixType> {
private static final Speed DEFAULT_MAX_SPEED_FOR_SMOOTHING = new KnotSpeedImpl(50);
protected final Speed maxSpeedForSmoothening;
private final ItemType trackedItem;
private long millisecondsOverWhichToAverage;
public GPSFixTrackImpl(ItemType trackedItem, long millisecondsOverWhichToAverage) {
this(trackedItem, millisecondsOverWhichToAverage, DEFAULT_MAX_SPEED_FOR_SMOOTHING);
}
public GPSFixTrackImpl(ItemType trackedItem, long millisecondsOverWhichToAverage, Speed maxSpeedForSmoothening) {
super();
this.trackedItem = trackedItem;
this.millisecondsOverWhichToAverage = millisecondsOverWhichToAverage;
this.maxSpeedForSmoothening = maxSpeedForSmoothening;
}
private class DummyGPSFix extends DummyTimed implements GPSFix {
public DummyGPSFix(TimePoint timePoint) {
super(timePoint);
@@ -73,6 +81,9 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
if (lastFixAtOrBefore != null && lastFixAtOrBefore == firstFixAtOrAfter) {
return lastFixAtOrBefore.getPosition(); // exact match; how unlikely is that?
} else {
if (lastFixAtOrBefore == null && firstFixAtOrAfter != null) {
return firstFixAtOrAfter.getPosition(); // asking for time point before first fix: return first fix's position
}
if (firstFixAtOrAfter == null && !extrapolate) {
return lastFixAtOrBefore == null ? null : lastFixAtOrBefore.getPosition();
} else {
@@ -150,7 +161,7 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
*/
private NavigableSet<GPSFix> getGPSFixes() {
@SuppressWarnings("unchecked")
NavigableSet<GPSFix> result = (NavigableSet<GPSFix>) super.getInternalFixes();
NavigableSet<GPSFix> result = (NavigableSet<GPSFix>) getInternalFixes();
return result;
}
@@ -162,12 +173,26 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
if (fromPos == null) {
return Distance.NULL;
}
NavigableSet<GPSFix> subset = getGPSFixes().subSet(new DummyGPSFix(from),
/* fromInclusive */false, new DummyGPSFix(to),
/* toInclusive */false);
for (GPSFix fix : subset) {
distanceInNauticalMiles += fromPos.getDistance(fix.getPosition()).getNauticalMiles();
fromPos = fix.getPosition();
synchronized (this) {
NavigableSet<GPSFix> subset = getGPSFixes().subSet(new DummyGPSFix(from),
/* fromInclusive */false, new DummyGPSFix(to),
/* toInclusive */false);
TimePoint lastTimePoint = null;
for (GPSFix fix : subset) {
double distanceBetweenAdjacentFixesInNauticalMiles = fromPos.getDistance(fix.getPosition()).getNauticalMiles();
// TODO remove this debug code again once the outlier issue is fixed
if (lastTimePoint != null) {
double crossCheckSpeedInKnots = distanceBetweenAdjacentFixesInNauticalMiles /
(fix.getTimePoint().asMillis()-lastTimePoint.asMillis()) * 3600000l;
if (crossCheckSpeedInKnots > 20) {
System.out.println("found suspicious fix");
}
}
lastTimePoint = fix.getTimePoint();
distanceInNauticalMiles += distanceBetweenAdjacentFixesInNauticalMiles;
fromPos = fix.getPosition();
}
}
Position toPos = getEstimatedPosition(to, false);
distanceInNauticalMiles += fromPos.getDistance(toPos).getNauticalMiles();
@@ -211,20 +236,22 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
@Override
public SpeedWithBearing getEstimatedSpeed(TimePoint at) {
DummyGPSFix atTimed = new DummyGPSFix(at);
NavigableSet<GPSFix> beforeSet = getGPSFixes().headSet(atTimed, /* inclusive */ true);
NavigableSet<GPSFix> afterSet = getGPSFixes().tailSet(atTimed, /* inclusive */ true);
List<GPSFix> relevantFixes = new LinkedList<GPSFix>();
for (GPSFix beforeFix : beforeSet.descendingSet()) {
if (at.asMillis() - beforeFix.getTimePoint().asMillis() > getMillisecondsOverWhichToAverage()/2) {
break;
synchronized (this) {
NavigableSet<GPSFix> beforeSet = getGPSFixes().headSet(atTimed, /* inclusive */true);
NavigableSet<GPSFix> afterSet = getGPSFixes().tailSet(atTimed, /* inclusive */true);
for (GPSFix beforeFix : beforeSet.descendingSet()) {
if (at.asMillis() - beforeFix.getTimePoint().asMillis() > getMillisecondsOverWhichToAverage() / 2) {
break;
}
relevantFixes.add(0, beforeFix);
}
relevantFixes.add(0, beforeFix);
}
for (GPSFix afterFix : afterSet) {
if (afterFix.getTimePoint().asMillis() - at.asMillis() > getMillisecondsOverWhichToAverage()/2) {
break;
for (GPSFix afterFix : afterSet) {
if (afterFix.getTimePoint().asMillis() - at.asMillis() > getMillisecondsOverWhichToAverage() / 2) {
break;
}
relevantFixes.add(afterFix);
}
relevantFixes.add(afterFix);
}
double knotSum = 0;
double bearingDegSum = 0;
@@ -255,26 +282,36 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
@Override
protected NavigableSet<FixType> getInternalFixes() {
return new PartialNavigableSetView<FixType>(super.getInternalFixes()) {
private final Speed maxSpeed = new KnotSpeedImpl(50);
@Override
protected boolean isValid(FixType e) {
FixType previous = lowerInternal(e);
FixType next = higherInternal(e);
Speed speedToPrevious = Speed.NULL;
if (previous != null) {
speedToPrevious = previous.getPosition().getDistance(e.getPosition())
.inTime(e.getTimePoint().asMillis() - previous.getTimePoint().asMillis());
}
Speed speedToNext = Speed.NULL;
if (next != null) {
speedToNext = e.getPosition().getDistance(next.getPosition())
.inTime(next.getTimePoint().asMillis() - e.getTimePoint().asMillis());
}
return (speedToPrevious.compareTo(maxSpeed) <= 0 || speedToNext.compareTo(maxSpeed) <= 0);
return GPSFixTrackImpl.this.isValid(this, e);
}
};
}
protected boolean isValid(PartialNavigableSetView<FixType> filteredView, FixType e) {
boolean result;
if (maxSpeedForSmoothening == null) {
result = true;
} else {
FixType previous = filteredView.lowerInternal(e);
FixType next = filteredView.higherInternal(e);
Speed speedToPrevious = Speed.NULL;
if (previous != null) {
speedToPrevious = previous.getPosition().getDistance(e.getPosition())
.inTime(e.getTimePoint().asMillis() - previous.getTimePoint().asMillis());
}
Speed speedToNext = Speed.NULL;
if (next != null) {
speedToNext = e.getPosition().getDistance(next.getPosition())
.inTime(next.getTimePoint().asMillis() - e.getTimePoint().asMillis());
}
result = ((previous == null || speedToPrevious.compareTo(maxSpeedForSmoothening) <= 0)
|| (next == null || speedToNext.compareTo(maxSpeedForSmoothening) <= 0));
}
return result;
}
@Override
public boolean hasDirectionChange(TimePoint at, double minimumDegreeDifference) {
// TODO use boat-class specific time for a maneuver
@@ -45,7 +45,7 @@ public class WindwardToGoComparator implements Comparator<TrackedLegOfCompetitor
if (o2.hasStartedLeg(timePoint)) {
Distance o1d = o1.getWindwardDistanceToGo(timePoint);
Distance o2d = o2.getWindwardDistanceToGo(timePoint);
result = o1d.compareTo(o2d); // smaller distance to go means smaller rank
result = o1d==null?(o2d==null?0:1):o2d==null?1:o1d.compareTo(o2d); // smaller distance to go means smaller rank
} else {
result = -1;
}
+4 -1
View File
@@ -1,7 +1,10 @@
<?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="src" path="resources"/>
<classpathentry exported="true" kind="con" path="com.google.gwt.eclipse.core.GWT_CONTAINER"/>
<classpathentry exported="true" kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry exported="true" kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="output" path="bin"/>
</classpath>
+11
View File
@@ -20,9 +20,20 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>com.google.gwt.eclipse.core.gwtNature</nature>
</natures>
</projectDescription>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="com.google.gwt.eclipse.core.launch.gwtJUnit">
<stringAttribute key="com.google.gwt.eclipse.core.LOG_LEVEL" value="INFO"/>
<booleanAttribute key="com.google.gwt.eclipse.core.NOT_HEADLESS" value="false"/>
<stringAttribute key="com.google.gwt.eclipse.core.OUT_DIR" value="www-test"/>
<booleanAttribute key="com.google.gwt.eclipse.core.STANDARDS_MODE" value="false"/>
<stringAttribute key="com.google.gwt.eclipse.core.STYLE" value="OBFUSCATED"/>
<stringAttribute key="com.google.gwt.eclipse.core.WEB_MODE" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/GwtTestCaseColumnToggling.java"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.sap.sailing.gwt.ui.test.GwtTestCaseColumnToggling"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui.test"/>
</launchConfiguration>
@@ -6,10 +6,11 @@ Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Require-Bundle: com.sap.sailing.gwt.ui,
org.junit4;bundle-version="4.8.1",
javax.servlet;bundle-version="2.5.0",
com.sap.sailing.domain,
org.json.simple,
com.sap.sailing.server
Import-Package: org.osgi.framework,
org.osgi.util.tracker;version="1.5.0"
com.sap.sailing.server,
com.google.gwt.osgi,
org.eclipse.osgi,
org.junit4
Bundle-ClassPath: .
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/TestColumnSwapping.java"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.sap.sailing.gwt.ui.test.TestColumnSwapping"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui.test"/>
</launchConfiguration>
@@ -1,4 +1,9 @@
source.. = src/
output.. = bin/
source.. = src/,\
resources/
output.. = bin
bin.includes = META-INF/,\
.
.,\
war/
jars.compile.order = .
source.. = src/,\
resources/
+54 -18
View File
@@ -1,21 +1,57 @@
<?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>
<artifactId>com.sap.sailing.gwt.ui.test</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>eclipse-test-plugin</packaging>
<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>
<artifactId>com.sap.sailing.gwt.ui.test</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>eclipse-test-plugin</packaging>
<dependencies>
<dependency>
<groupId>com.sap.ui.phoenix</groupId>
<artifactId>pwt-sap.ui.commons</artifactId>
<version>0.18.0</version>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>com.sap.ui.phoenix</groupId>
<artifactId>pwt-sap.ui.commons</artifactId>
<version>0.18.0</version>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<version>2.3.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>2.4.0</version>
<configuration>
<includes>**/GwtTestCaseColumnToggling.java</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/GwtTestCaseColumnToggling.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
<module>
<inherits name="com.google.gwt.user.User" />
<inherits name="com.sap.sailing.gwt.ui.AdminConsole" />
<source path="client"/>
<servlet path='/testsailing' class='com.sap.sailing.gwt.ui.test.TestSailingServiceImpl'/>
</module>
@@ -15,7 +15,7 @@ import com.sap.sailing.gwt.ui.shared.LeaderboardRowDAO;
import com.sap.sailing.gwt.ui.shared.Pair;
import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDAO;
public class TestColumnToggling extends GWTTestCase {
public class GwtTestCaseColumnToggling extends GWTTestCase {
//These objects should be created by calling GWT.create(Class c);
private LeaderboardPanelMock leaderboardPanel;
@@ -66,7 +66,8 @@ public class TestColumnToggling extends GWTTestCase {
rrDao = rr;
}
}
assertNotNull("rrDao != null",rrDao);
//assertNotNull("rrDao != null",rrDao);
assertNull(rrDao);
trackRace();
}
});
@@ -213,7 +214,7 @@ public class TestColumnToggling extends GWTTestCase {
@Override
public String getModuleName() {
// TODO Auto-generated method stub
return "com.sap.sailing.gwt.ui.AdminConsole";
return "com.sap.sailing.gwt.ui.test.TestConsole";
}
}
-1
View File
@@ -6,6 +6,5 @@
<classpathentry exported="true" kind="con" path="com.google.gwt.eclipse.core.GWT_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="lib" path="lib/gwt-maps.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="output" path="bin"/>
</classpath>
@@ -1,7 +1,7 @@
#Thu Oct 27 11:53:43 CEST 2011
#Wed Nov 23 14:14:33 CET 2011
eclipse.preferences.version=1
jarsExcludedFromWebInfLib=
lastWarOutDir=C\:/Users/d056866/git/git/java/com.sap.sailing.gwt.ui/war
lastWarOutDir=C\:/Users/d056995/git/git/java/com.sap.sailing.gwt.ui/war
launchConfigExternalUrlPrefix=
warSrcDir=war
warSrcDirIsOutput=false
@@ -20,15 +20,15 @@ Require-Bundle: com.sap.sailing.domain,
com.sap.sailing.domain.swisstimingadapter,
com.sap.sailing.domain.persistence,
com.sap.sailing.domain.swisstimingadapter.persistence,
com.sap.sailing.domain.tractracadapter.persistence,
org.junit4
com.sap.sailing.domain.tractracadapter.persistence
Bundle-ClassPath: lib/gwt-maps.jar,
lib/gwt-visualization.jar,
lib/gwt-servlet.jar,
.
Bundle-Activator: com.sap.sailing.gwt.ui.server.Activator
Bundle-ActivationPolicy: lazy
Export-Package: com.sap.sailing.gwt.ui.server,
Export-Package: com.sap.sailing.gwt.ui.client;x-friends:="com.sap.sailing.gwt.ui.test",
com.sap.sailing.gwt.ui.server;x-friends:="com.sap.sailing.gwt.ui.test",
com.sap.sailing.gwt.ui.shared;x-friends:="com.sap.sailing.gwt.ui.test"
Import-Package: org.osgi.framework,
org.osgi.util.tracker,
@@ -21,7 +21,7 @@
</listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-war &quot;${project_loc:com.sap.sailing.gwt.ui}/war&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.ui.UserManagement"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-war &quot;${project_loc:com.sap.sailing.gwt.ui}/war&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.UserManagement"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx512m"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx1024m"/>
</launchConfiguration>
@@ -34,6 +34,9 @@ public class AdminConsole extends AbstractEntryPoint implements EventRefresher {
eventDisplayers.add(swisstimingEventManagementPanel);
swisstimingEventManagementPanel.setSize("90%", "90%");
tabPanel.add(swisstimingEventManagementPanel, stringConstants.swissTimingEvents(), false);
CreateSwissTimingRacePanel createSwissTimingRacePanel = new CreateSwissTimingRacePanel(sailingService,this,stringConstants);
createSwissTimingRacePanel.setSize("90%", "90%");
tabPanel.add(createSwissTimingRacePanel,"Create SwissTiming race",false);
WindPanel windPanel = new WindPanel(sailingService, this, this, stringConstants);
eventDisplayers.add(windPanel);
windPanel.setSize("90%", "90%");
@@ -0,0 +1,294 @@
package com.sap.sailing.gwt.ui.client;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CaptionPanel;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
public class CreateSwissTimingRacePanel extends FormPanel {
private TextBox txtbRaceName;
private TextBox txtbRaceDesc;
private TextBox txtbCompName;
private TextBox txtbCompSailNr;
private MultiWordSuggestOracle suggestionsCompCountr;
private SuggestBox listbCompCountr;
private ListBox listbCompetitorList;
private List<Competitor> competitors;
private int selectedIndex;
private int id = 0;
private final SailingServiceAsync service;
private ErrorReporter errorReporter;
public CreateSwissTimingRacePanel(final SailingServiceAsync sailingService, ErrorReporter errorReporter, StringConstants stringConstants){
this.service = sailingService;
this.errorReporter = errorReporter;
competitors = new ArrayList<CreateSwissTimingRacePanel.Competitor>();
VerticalPanel mainPanel = new VerticalPanel();
Grid mainGrid = new Grid(3,1);
mainGrid.setWidth("100%");
mainPanel.add(mainGrid);
mainPanel.setSize("100%", "100%");
this.setWidget(mainPanel);
//Race data panel
CaptionPanel raceDataPanel = new CaptionPanel("Race");
raceDataPanel.setSize("90%", "90%");
mainGrid.setWidget(0, 0, raceDataPanel);
Grid grid = new Grid(2,2);
raceDataPanel.add(grid);
Label lblRaceName = new Label("Race name:");
grid.setWidget(0, 0, lblRaceName);
txtbRaceName = new TextBox();
grid.setWidget(0, 1, txtbRaceName);
Label lblRaceDesc = new Label("Race description:");
grid.setWidget(1, 0, lblRaceDesc);
txtbRaceDesc = new TextBox();
grid.setWidget(1, 1, txtbRaceDesc);
//Competitor panel
CaptionPanel competitorPanel = new CaptionPanel("Competitors");
competitorPanel.setSize("90%", "90%");
mainGrid.setWidget(1, 0, competitorPanel);
grid = new Grid(3,3);
competitorPanel.add(grid);
Label lblCompetitorListTitle = new Label("Competitors:");
grid.setWidget(0, 0, lblCompetitorListTitle);
listbCompetitorList = new ListBox(false);
listbCompetitorList.setVisibleItemCount(10);
listbCompetitorList.setWidth("200px");
listbCompetitorList.addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
competitorSelectionChanged();
}
});
grid.setWidget(1, 0, listbCompetitorList);
VerticalPanel compData = new VerticalPanel();
grid.setWidget(1, 1, compData);
Grid subGrid = new Grid(3,2);
compData.add(subGrid);
Label lblName = new Label("Name:");
subGrid.setWidget(0, 0, lblName);
txtbCompName = new TextBox();
txtbCompName.addValueChangeHandler(new ValueChangeHandler<String>() {
@Override
public void onValueChange(ValueChangeEvent<String> event) {
competitorChanged();
}
});
subGrid.setWidget(0, 1, txtbCompName);
Label lblSailNr = new Label("Sail number:");
subGrid.setWidget(1, 0, lblSailNr);
txtbCompSailNr = new TextBox();
txtbCompSailNr.addValueChangeHandler(new ValueChangeHandler<String>() {
@Override
public void onValueChange(ValueChangeEvent<String> event) {
competitorChanged();
}
});
subGrid.setWidget(1, 1, txtbCompSailNr);
Label lblCountr = new Label("Country:");
subGrid.setWidget(2, 0, lblCountr);
suggestionsCompCountr = new MultiWordSuggestOracle();
service.getCountryCodes(new AsyncCallback<String[]>() {
@Override
public void onFailure(Throwable caught) {
CreateSwissTimingRacePanel.this.errorReporter.reportError("Unable to find the IOC 3-letter-codes.");
}
@Override
public void onSuccess(String[] result) {
for (String cc : result){
suggestionsCompCountr.add(cc);
}
}
});
listbCompCountr = new SuggestBox(suggestionsCompCountr);
listbCompCountr.addValueChangeHandler(new ValueChangeHandler<String>() {
@Override
public void onValueChange(ValueChangeEvent<String> event) {
competitorChanged();
}
});
subGrid.setWidget(2, 1, listbCompCountr);
HorizontalPanel horizontalPanel = new HorizontalPanel();
grid.setWidget(2, 0, horizontalPanel);
Button bttAddCompetitor = new Button("Add");
bttAddCompetitor.setWidth("100px");
bttAddCompetitor.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
addCompetitor();
}
});
horizontalPanel.add(bttAddCompetitor);
Button bttDeleteCompetitor = new Button("Delete");
bttDeleteCompetitor.setWidth("100px");
bttDeleteCompetitor.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
deleteCompetitor();
}
});
horizontalPanel.add(bttDeleteCompetitor);
Button bttAddRace = new Button("Add race");
bttAddRace.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
addRace();
}
});
mainGrid.setWidget(2, 0, bttAddRace);
}
private void competitorSelectionChanged(){
selectedIndex = listbCompetitorList.getSelectedIndex();
if (selectedIndex < 0){
return;
}
Competitor c = getCompetitorById(Integer.parseInt(listbCompetitorList.getValue(selectedIndex)));
if (c != null){
txtbCompName.setText(c.getName());
txtbCompSailNr.setText(c.getSailNumber());
listbCompCountr.setText(c.getCountry());
}
}
private void addCompetitor(){
Competitor c = new Competitor(id++,"Noname","","");
listbCompetitorList.addItem(c.toString(), ""+c.getId());
competitors.add(c);
listbCompetitorList.setSelectedIndex(listbCompetitorList.getItemCount()-1);
competitorSelectionChanged();
txtbCompName.setFocus(true);
}
private void deleteCompetitor(){
selectedIndex = listbCompetitorList.getSelectedIndex();
if (selectedIndex < 0){
return;
}
competitors.remove(getCompetitorById(Integer.parseInt(listbCompetitorList.getValue(selectedIndex))));
listbCompetitorList.removeItem(selectedIndex);
}
private void competitorChanged(){
if (selectedIndex < 0){
return;
}
Competitor c = getCompetitorById(Integer.parseInt(listbCompetitorList.getValue(selectedIndex)));
if (!txtbCompName.getText().equals(c.getName())){
c.setName(txtbCompName.getText());
listbCompetitorList.setItemText(selectedIndex, c.toString());
}
c.setCountry(listbCompCountr.getText());
c.setSailNumber(txtbCompSailNr.getText());
}
private Competitor getCompetitorById(int id){
for (Competitor c : competitors){
if (c.getId() == id)
return c;
}
return null;
}
private void addRace(){
String racMessage = "RAC|1|" + txtbRaceName.getText()+";" + txtbRaceDesc.getText();
String stlMessage = "STL|" + txtbRaceName.getText()+"|" + competitors.size();
for (Competitor c : competitors){
stlMessage += "|" + c.getSailNumber()+";" + c.getCountry() +";" + c.getName();
}
String ccgMessage = "CCG|" + txtbRaceName.getText() +"|3|0;LeeGate;LG1;LG2|1;Windwards;WW1|2;LeeGate;LG1;LG2";
service.sendSwissTimingDummyRace(racMessage,stlMessage,ccgMessage, new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
Window.alert("Succesfully sended new race.");
}
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError("Race with raceID \"" + txtbRaceName.getText() + "\" already exists.");
}
});
}
private class Competitor{
private String name;
private String sailNumber;
private String country;
private final int id;
public final int getId() {
return id;
}
public Competitor(int id, String name, String sailNumber, String country) {
super();
this.id = id;
this.name = name;
this.sailNumber = sailNumber;
this.country = country;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSailNumber() {
return sailNumber;
}
public void setSailNumber(String sailNumber) {
this.sailNumber = sailNumber;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String toString(){
return getName();
}
}
}
@@ -106,8 +106,8 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
setFieldUpdater(new FieldUpdater<LeaderboardRowDAO, LeaderboardRowDAO>() {
@Override
public void update(int rowIndex, LeaderboardRowDAO row, LeaderboardRowDAO value) {
currentRowUpdateWhiteboard = null; // show that it has been consumed and updated
currentRowUpdateWhiteboard.setIndexOfRowToUpdate(rowIndex);
currentRowUpdateWhiteboard = null; // show that it has been consumed and updated
}
});
}
@@ -83,6 +83,8 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
private final List<DetailColumnType> selectedRaceDetails;
private List<String> selectedRaceColumns;
protected final String RACE_COLUMN_HEADER_STYLE;
protected final String LEG_DETAIL_COLUMN_HEADER_STYLE;
@@ -98,6 +100,8 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
protected final String TOTAL_COLUMN_STYLE;
private final Timer timer;
boolean firstTimeLeaderboardLoaded;
/**
* The delay with which the timer shall work. Before the timer is resumed, the delay is set to this value.
@@ -109,7 +113,6 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
* changes its playing state
*/
private final Anchor playPause;
private class SettingsClickHandler implements ClickHandler {
private final StringConstants stringConstants;
@@ -120,10 +123,10 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
@Override
public void onClick(ClickEvent event) {
new LeaderboardSettingsPanel(Collections.unmodifiableList(selectedLegDetails),
Collections.unmodifiableList(selectedRaceDetails),
timer.getDelayBetweenAutoAdvancesInMilliseconds(), stringConstants.leaderboardSettings(),
stringConstants.selectLegDetails(), stringConstants.ok(), stringConstants.cancel(),
new Validator<LeaderboardSettingsPanel.Result>() {
Collections.unmodifiableList(selectedRaceDetails), /* All races to select */
leaderboard.getRaceList(), selectedRaceColumns, timer.getDelayBetweenAutoAdvancesInMilliseconds(),
stringConstants.leaderboardSettings(), stringConstants.selectLegDetails(), stringConstants.ok(),
stringConstants.cancel(), new Validator<LeaderboardSettingsPanel.Result>() {
@Override
public String getErrorMessage(LeaderboardSettingsPanel.Result valueToValidate) {
if (valueToValidate.getLegDetailsToShow().isEmpty()) {
@@ -155,6 +158,11 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
selectedLegDetails.addAll(result.getLegDetailsToShow());
selectedRaceDetails.clear();
selectedRaceDetails.addAll(result.getRaceDetailsToShow());
selectedRaceColumns.clear();
selectedRaceColumns.addAll(result.getRaceColumnsToShow());
// update leaderboard after settings panel column selection change
updateLeaderboard(leaderboard);
timer.setDelayBetweenAutoAdvancesInMilliseconds(result
.getDelayBetweenAutoAdvancesInMilliseconds());
setDelayInMilliseconds(result.getDelayInMilliseconds());
@@ -398,7 +406,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
/* iconURL */medalRace ? "/images/medal_small.png" : null, LeaderboardPanel.this, this, stringConstants);
return header;
}
public boolean isMedalRace() {
return medalRace;
}
@@ -701,8 +709,10 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
this.selectedLegDetails.add(DetailColumnType.AVERAGE_SPEED_OVER_GROUND_IN_KNOTS);
this.selectedLegDetails.add(DetailColumnType.RANK_GAIN);
this.selectedRaceDetails = new ArrayList<DetailColumnType>();
this.selectedRaceColumns = new ArrayList<String>();
this.firstTimeLeaderboardLoaded = true;
delayInMilliseconds = 0l;
timer = new Timer(/* delayBetweenAutoAdvancesInMilliseconds */3000l);
timer = new Timer(/* delayBetweenAutoAdvancesInMilliseconds */ 3000l);
timer.setDelay(getDelayInMilliseconds()); // set time/delay before
// adding as listener
timer.addPlayStateListener(this);
@@ -958,63 +968,180 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
// first remove race columns no longer needed:
removeUnusedRaceColumns(leaderboard);
if (leaderboard != null) {
if(firstTimeLeaderboardLoaded){
for (String string : leaderboard.getRaceList()) {
selectedRaceColumns.add(string);
}
if(selectedRaceColumns.size()!=0){
firstTimeLeaderboardLoaded = false;
}
}
createMissingAndAdjustExistingRaceColumns(leaderboard);
ensureTotalsColumn();
}
}
private boolean leaderboardTableContainsRace(String raceName) {
for (int leaderboardposition = 0; leaderboardposition < getLeaderboardTable().getColumnCount(); leaderboardposition++) {
Column<LeaderboardRowDAO, ?> c = getLeaderboardTable().getColumn(leaderboardposition);
if (c instanceof RaceColumn) {
RaceColumn<?> raceColumn = (RaceColumn<?>) c;
if (raceColumn.getRaceName().equals(raceName)) {
correctColumnData(raceColumn);
return true;
}
}
}
return false;
}
/**
* Corrects the data linke medalRace of the given raceColumn
* @param raceColumn the raceColumn to correct.
*/
private void correctColumnData(RaceColumn<?> raceColumn){
String race = raceColumn.getRaceName();
int columnIndex = getRaceColumnPosition(raceColumn);
if (raceColumn.isExpansionEnabled() != leaderboard.raceIsTracked(race)
|| leaderboard.raceIsMedalRace(race) != raceColumn.isMedalRace()) {
if (raceColumn.isExpanded()) {
raceColumn.toggleExpansion(); // remove children from table
}
removeColumn(columnIndex);
insertColumn(
columnIndex,
createRaceColumn(race, leaderboard.raceIsMedalRace(race),
leaderboard.raceIsTracked(race)));
}
}
/**
* Removes all RaceColumns, starting at count {@link raceColumnStartIndex raceColumnStartIndex}
* @param raceColumnStartIndex The index of the race column should be deleted from.
* @param raceName The name of the racing column until the table should be cleared.
*/
private void removeRaceColumnFromRaceColumnStartIndexBeforeRace(int raceColumnStartIndex, String raceName) {
int counter = 0;
for (int leaderboardposition = 0; leaderboardposition < getLeaderboardTable().getColumnCount(); leaderboardposition++) {
Column<LeaderboardRowDAO, ?> c = getLeaderboardTable().getColumn(leaderboardposition);
if (c instanceof RaceColumn) {
RaceColumn<?> raceColumn = (RaceColumn<?>) c;
if (!raceColumn.getRaceName().equals(raceName) && raceColumnStartIndex==counter) {
removeColumn(raceColumn);
} else {
return;
}
counter++;
}
}
}
/**
* Gets a ColumnPosition of a raceColumn
* @param raceColumn The column for which the position is to be found in the leaderboard table
* @return the position. Returns -1 if raceColumn not existing in leaderboardTable.
*/
private int getRaceColumnPosition(RaceColumn<?> raceColumn){
for (int leaderboardposition = 0; leaderboardposition < getLeaderboardTable().getColumnCount(); leaderboardposition++) {
Column<LeaderboardRowDAO, ?> c = getLeaderboardTable().getColumn(leaderboardposition);
if (c instanceof RaceColumn) {
RaceColumn<?> rc = (RaceColumn<?>) c;
if(rc.equals(raceColumn)){
return leaderboardposition;
}
}
}
return -1;
}
/**
* This method returns the position where a racecolumn should get inserted.
* @param raceName the name of the race to insert
* @param the position of the race in the {@link selectedRaceColumns selectedRaceColumns}
* @return the position to insert the racecolumn
*/
private int getColumnPositionToInsert(String raceName, int listpos) {
int raceColumnCounter = 0;
int noRaceColumnCounter = 0;
boolean raceColumnfound = false;
for (int leaderboardposition = 0; !raceColumnfound & leaderboardposition < getLeaderboardTable().getColumnCount(); leaderboardposition++) {
Column<LeaderboardRowDAO, ?> c = getLeaderboardTable().getColumn(leaderboardposition);
if (c instanceof RaceColumn) {
//RaceColumn<?> raceColumn = (RaceColumn<?>) c;
if (raceColumnCounter == listpos) {
raceColumnfound = true;
}
raceColumnCounter++;
} else {
noRaceColumnCounter++;
}
}
if(raceColumnfound){
return raceColumnCounter + noRaceColumnCounter;
}else{
return -1;
}
}
/**
* Removes all Columns of type racecolumns of leaderboardTable
*/
private void removeRaceColumnNotUsed() {
for (int leaderboardposition = 0; leaderboardposition < getLeaderboardTable().getColumnCount(); leaderboardposition++) {
Column<LeaderboardRowDAO, ?> c = getLeaderboardTable().getColumn(leaderboardposition);
if (c instanceof RaceColumn) {
RaceColumn<?> raceColumn = (RaceColumn<?>) c;
if(!selectedRaceColumns.contains(raceColumn.getRaceName())){
if(raceColumn.isExpanded()){
raceColumn.toggleExpansion();
}
getLeaderboardTable().removeColumn(raceColumn);
}
}
}
}
/**
* Existing and matching race columns may still need to be removed, re-created and inserted because the "tracked"
* property may have changed, changing the columns expandability.
*/
private void createMissingAndAdjustExistingRaceColumns(LeaderboardDAO leaderboard) {
int currentRaceColumnIndex = 0;
int[] positionRaceColumn = new int[leaderboard.getRaceList().size()];
List<String> raceList = leaderboard.getRaceList();
for (int i = 0; i < getLeaderboardTable().getColumnCount(); i++) {
Column<LeaderboardRowDAO, ?> c = getLeaderboardTable().getColumn(i);
if (c instanceof RaceColumn) {
positionRaceColumn[currentRaceColumnIndex] = i;
currentRaceColumnIndex++;
// Correct order of races in selectedRaceColum
List<String> correctedOrderSelectedRaces = new ArrayList<String>();
for (String string : leaderboard.getRaceList()) {
if (selectedRaceColumns.contains(string)) {
correctedOrderSelectedRaces.add(string);
}
}
int indexRaceColumn = 0;
for (String race : raceList) {
boolean foundRaceColumn = false;
for (int i = 0; !foundRaceColumn && i < getLeaderboardTable().getColumnCount(); i++) {
Column<LeaderboardRowDAO, ?> c = getLeaderboardTable().getColumn(i);
if (c instanceof RaceColumn) {
RaceColumn<?> raceColumn = (RaceColumn<?>) c;
if (raceColumn.getRaceName().equals(race)) {
foundRaceColumn = true;
// if tracked-ness differs, column must be updated with
// a new column that is expansion-enabled
int columnIndex = getLeaderboardTable().getColumnIndex(raceColumn);
if (raceColumn.isExpansionEnabled() != leaderboard.raceIsTracked(race) || columnIndex != positionRaceColumn[indexRaceColumn]
|| leaderboard.raceIsMedalRace(race) != raceColumn.isMedalRace()) {
if (raceColumn.isExpanded()) {
raceColumn.toggleExpansion(); // remove children from table
}
removeColumn(columnIndex);
insertColumn(
positionRaceColumn[indexRaceColumn],
createRaceColumn(race, leaderboard.raceIsMedalRace(race),
leaderboard.raceIsTracked(race)));
}
}
selectedRaceColumns = correctedOrderSelectedRaces;
removeRaceColumnNotUsed();
for (int selectedRaceCount = 0; selectedRaceCount < selectedRaceColumns.size(); selectedRaceCount++) {
String selectedRaceName = selectedRaceColumns.get(selectedRaceCount);
if (leaderboardTableContainsRace(selectedRaceName)){
// remove all raceColumns, starting at a specific raceColumnPosition, until the selected raceName.
removeRaceColumnFromRaceColumnStartIndexBeforeRace(selectedRaceCount, selectedRaceName);
}else{
// get correct position to insert the column
int positionToInsert = getColumnPositionToInsert(selectedRaceName, selectedRaceCount);
if(positionToInsert!=-1){
insertColumn(positionToInsert,
createRaceColumn(selectedRaceName, leaderboard.raceIsMedalRace(selectedRaceName),
leaderboard.raceIsTracked(selectedRaceName)));
}else{
// Add the raceColumn with addRaceColumn, if no RaceColumn is existing in leaderboard
addRaceColumn(createRaceColumn(selectedRaceName, leaderboard.raceIsMedalRace(selectedRaceName),
leaderboard.raceIsTracked(selectedRaceName)));
}
}
if (!foundRaceColumn) {
addRaceColumn(createRaceColumn(race, leaderboard.raceIsMedalRace(race), leaderboard.raceIsTracked(race)));
}
indexRaceColumn++;
}
}
protected RaceColumn<?> createRaceColumn(String raceName, boolean isMedalRace, boolean isTracked) {
return new TextRaceColumn(raceName, isMedalRace, isTracked, RACE_COLUMN_HEADER_STYLE, RACE_COLUMN_STYLE);
TextRaceColumn textRaceColumn = new TextRaceColumn(raceName, isMedalRace, isTracked, RACE_COLUMN_HEADER_STYLE,
RACE_COLUMN_STYLE);
return textRaceColumn;
}
private void removeUnusedRaceColumns(LeaderboardDAO leaderboard) {
@@ -7,6 +7,7 @@ import java.util.Map;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.IntegerBox;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
@@ -14,8 +15,11 @@ import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.client.LeaderboardSettingsPanel.Result;
public class LeaderboardSettingsPanel extends DataEntryDialog<Result> {
private final List<String> raceColumnSelection;
private final List<String> raceAllRaceColumns;
private final List<DetailColumnType> legDetailSelection;
private final List<DetailColumnType> raceDetailSelection;
private final Map<String, CheckBox> raceColumnCheckboxes;
private final Map<DetailColumnType, CheckBox> legDetailCheckboxes;
private final Map<DetailColumnType, CheckBox> raceDetailCheckboxes;
private final StringConstants stringConstants;
@@ -23,14 +27,16 @@ public class LeaderboardSettingsPanel extends DataEntryDialog<Result> {
private final IntegerBox delayInSecondsBox;
public static class Result {
private final List<String> raceColumnsToShow;
private final List<DetailColumnType> legDetailsToShow;
private final List<DetailColumnType> raceDetailsToShow;
private final long delayBetweenAutoAdvancesInMilliseconds;
private final long delayInMilliseconds;
public Result(List<DetailColumnType> legDetailsToShow, List<DetailColumnType> raceDetailsToShow, long delayBetweenAutoAdvancesInMilliseconds, long delayInMilliseconds) {
public Result(List<DetailColumnType> legDetailsToShow, List<DetailColumnType> raceDetailsToShow, List<String> raceColumnsToShow, long delayBetweenAutoAdvancesInMilliseconds, long delayInMilliseconds) {
this.legDetailsToShow = legDetailsToShow;
this.raceDetailsToShow = raceDetailsToShow;
this.raceColumnsToShow = raceColumnsToShow;
this.delayBetweenAutoAdvancesInMilliseconds = delayBetweenAutoAdvancesInMilliseconds;
this.delayInMilliseconds = delayInMilliseconds;
}
@@ -42,6 +48,10 @@ public class LeaderboardSettingsPanel extends DataEntryDialog<Result> {
public List<DetailColumnType> getRaceDetailsToShow() {
return raceDetailsToShow;
}
public List<String> getRaceColumnsToShow(){
return raceColumnsToShow;
}
public long getDelayBetweenAutoAdvancesInMilliseconds() {
return delayBetweenAutoAdvancesInMilliseconds;
@@ -52,14 +62,17 @@ public class LeaderboardSettingsPanel extends DataEntryDialog<Result> {
}
}
public LeaderboardSettingsPanel(List<DetailColumnType> legDetailSelection, List<DetailColumnType> raceDetailSelection,
public LeaderboardSettingsPanel(List<DetailColumnType> legDetailSelection, List<DetailColumnType> raceDetailSelection, List<String> raceAllRaceColumns, List<String> raceColumnSelection,
long delayBetweenAutoAdvancesInMilliseconds, String title, String message,
String okButtonName,
String cancelButtonName, com.sap.sailing.gwt.ui.client.DataEntryDialog.Validator<Result> validator, AsyncCallback<Result> callback, StringConstants stringConstants, long delayInMilliseconds) {
super(title, message, okButtonName, cancelButtonName, validator, callback);
this.raceColumnSelection = raceColumnSelection;
this.raceAllRaceColumns = raceAllRaceColumns;
this.legDetailSelection = legDetailSelection;
this.raceDetailSelection = raceDetailSelection;
this.stringConstants = stringConstants;
raceColumnCheckboxes = new LinkedHashMap<String, CheckBox>();
legDetailCheckboxes = new LinkedHashMap<DetailColumnType, CheckBox>();
raceDetailCheckboxes = new LinkedHashMap<DetailColumnType, CheckBox>();
delayBetweenAutoAdvancesInSecondsBox = createIntegerBox((int) delayBetweenAutoAdvancesInMilliseconds/1000, 4);
@@ -68,32 +81,46 @@ public class LeaderboardSettingsPanel extends DataEntryDialog<Result> {
@Override
protected Widget getAdditionalWidget() {
VerticalPanel vp = new VerticalPanel();
vp.setSpacing(5);
vp.add(new Label(stringConstants.timing()));
HorizontalPanel hp = new HorizontalPanel();
VerticalPanel vpLeft = new VerticalPanel();
vpLeft.setSpacing(5);
VerticalPanel vpRight = new VerticalPanel();
vpRight.setSpacing(5);
vpLeft.add(new Label(stringConstants.timing()));
Label delayLabel = new Label(stringConstants.delayInSeconds());
vp.add(delayLabel);
vp.add(delayInSecondsBox);
vpLeft.add(delayLabel);
vpLeft.add(delayInSecondsBox);
Label delayBetweenAutoAdvancesLabel = new Label(stringConstants.delayBetweenAutoAdvances());
vp.add(delayBetweenAutoAdvancesLabel);
vp.add(delayBetweenAutoAdvancesInSecondsBox);
vp.add(new Label(stringConstants.raceDetailsToShow()));
vpLeft.add(delayBetweenAutoAdvancesLabel);
vpLeft.add(delayBetweenAutoAdvancesInSecondsBox);
vpLeft.add(new Label(stringConstants.raceDetailsToShow()));
List<DetailColumnType> currentRaceDetailSelection = raceDetailSelection;
for (DetailColumnType type : LeaderboardPanel.getAvailableRaceDetailColumnTypes()) {
CheckBox checkbox = createCheckbox(type.toString(stringConstants));
checkbox.setValue(currentRaceDetailSelection.contains(type));
raceDetailCheckboxes.put(type, checkbox);
vp.add(checkbox);
vpLeft.add(checkbox);
}
vp.add(new Label(stringConstants.legDetailsToShow()));
vpLeft.add(new Label(stringConstants.legDetailsToShow()));
List<DetailColumnType> currentLegDetailSelection = legDetailSelection;
for (DetailColumnType type : LegColumn.getAvailableLegDetailColumnTypes()) {
CheckBox checkbox = createCheckbox(type.toString(stringConstants));
checkbox.setValue(currentLegDetailSelection.contains(type));
legDetailCheckboxes.put(type, checkbox);
vp.add(checkbox);
vpLeft.add(checkbox);
}
return vp;
hp.add(vpLeft);
vpRight.add(new Label(stringConstants.selectedRaces()));
List<String> allColumns = raceAllRaceColumns;
for (String expandableSortableColumn : allColumns) {
CheckBox checkbox = createCheckbox(expandableSortableColumn);
checkbox.setValue(raceColumnSelection.contains(expandableSortableColumn));
raceColumnCheckboxes.put(expandableSortableColumn, checkbox);
vpRight.add(checkbox);
}
hp.add(vpRight);
return hp;
}
@Override
@@ -110,9 +137,15 @@ public class LeaderboardSettingsPanel extends DataEntryDialog<Result> {
legDetailsToShow.add(entry.getKey());
}
}
List<String> raceColumnsToShow = new ArrayList<String>();
for (Map.Entry<String, CheckBox> entry : raceColumnCheckboxes.entrySet()) {
if(entry.getValue().getValue()){
raceColumnsToShow.add(entry.getKey());
}
}
Integer delayBetweenAutoAdvancesValue = delayBetweenAutoAdvancesInSecondsBox.getValue();
Integer delayInSecondsValue = delayInSecondsBox.getValue();
return new Result(legDetailsToShow, raceDetailsToShow, 1000*(delayBetweenAutoAdvancesValue==null?0:delayBetweenAutoAdvancesValue.longValue()),
return new Result(legDetailsToShow, raceDetailsToShow, raceColumnsToShow, 1000*(delayBetweenAutoAdvancesValue==null?0:delayBetweenAutoAdvancesValue.longValue()),
1000*(delayInSecondsValue==null?0:delayInSecondsValue.longValue()));
}
@@ -315,7 +315,8 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
EventDAO event = selection.get(selection.size() - 1).getA();
RaceDAO race = selection.get(selection.size() - 1).getC();
if (event != null && race != null) {
final Triple<Map<CompetitorDAO, Date>, Map<CompetitorDAO, Date>, Map<CompetitorDAO, Boolean>> fromAndToAndOverlap = computeFromAndTo(date);
final Triple<Map<CompetitorDAO, Date>, Map<CompetitorDAO, Date>, Map<CompetitorDAO, Boolean>> fromAndToAndOverlap =
computeFromAndTo(date);
sailingService.getBoatPositions(event.name, race.name, fromAndToAndOverlap.getA(), fromAndToAndOverlap.getB(), true,
new AsyncCallback<Map<CompetitorDAO, List<GPSFixDAO>>>() {
@Override
@@ -462,11 +463,12 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
}
/**
* While updating the {@link #fixes} for <code>competitorDAO</code>, the invariants for {@link #tails}
* and {@link #firstShownFix} and {@link #lastShownFix} are maintained: each time a fix is inserted,
* the {@link #firstShownFix}/{@link #lastShownFix} records for <code>competitorDAO</code> are incremented
* if they are greater or equal to the insertion index. Additionally, if the fix is in between the fixes
* shown in the competitor's tail, the tail is adjusted by inserting the corresponding fix.
* While updating the {@link #fixes} for <code>competitorDAO</code>, the invariants for {@link #tails} and
* {@link #firstShownFix} and {@link #lastShownFix} are maintained: each time a fix is inserted, the
* {@link #firstShownFix}/{@link #lastShownFix} records for <code>competitorDAO</code> are incremented if they are
* greater or equal to the insertion index and we have a tail in {@link #tails} for <code>competitorDAO</code>.
* Additionally, if the fix is in between the fixes shown in the competitor's tail, the tail is adjusted by
* inserting the corresponding fix.
*/
private void mergeFixes(CompetitorDAO competitorDAO, List<GPSFixDAO> mergeThis) {
List<GPSFixDAO> intoThis = fixes.get(competitorDAO);
@@ -475,7 +477,8 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
Polyline tail = tails.get(competitorDAO);
int intoThisIndex = 0;
for (GPSFixDAO mergeThisFix : mergeThis) {
while (intoThisIndex < intoThis.size() && intoThis.get(intoThisIndex).timepoint.before(mergeThisFix.timepoint)) {
while (intoThisIndex < intoThis.size()
&& intoThis.get(intoThisIndex).timepoint.before(mergeThisFix.timepoint)) {
intoThisIndex++;
}
if (intoThisIndex < intoThis.size() && intoThis.get(intoThisIndex).timepoint.equals(mergeThisFix.timepoint)) {
@@ -489,7 +492,7 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
if (indexOfLastShownFix >= intoThisIndex) {
indexOfLastShownFix++;
}
if (intoThisIndex >= indexOfFirstShownFix && intoThisIndex <= indexOfLastShownFix) {
if (tail != null && intoThisIndex >= indexOfFirstShownFix && intoThisIndex <= indexOfLastShownFix) {
tail.insertVertex(intoThisIndex - indexOfFirstShownFix,
LatLng.newInstance(mergeThisFix.position.latDeg, mergeThisFix.position.lngDeg));
}
@@ -552,7 +555,7 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
map.addOverlay(tail);
} else {
updateTail(tail, competitorDAO, from, to);
competitorDAOsOfUnusedTails.remove(tail);
competitorDAOsOfUnusedTails.remove(competitorDAO);
}
LatLngBounds bounds = tail.getBounds();
if (newMapBounds == null) {
@@ -690,15 +693,19 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
boatMarker.addMarkerMouseOverHandler(new MarkerMouseOverHandler() {
@Override
public void onMouseOver(MarkerMouseOverEvent event) {
setSelectedInMap(competitorDAO, true);
quickRanksBox.setItemSelected(quickRanksList.indexOf(competitorDAO), true);
map.setTitle(competitorDAO.name);
//setSelectedInMap(competitorDAO, true);
//quickRanksBox.setItemSelected(quickRanksList.indexOf(competitorDAO), true);
}
});
boatMarker.addMarkerMouseOutHandler(new MarkerMouseOutHandler() {
@Override
public void onMouseOut(MarkerMouseOutEvent event) {
setSelectedInMap(competitorDAO, false);
quickRanksBox.setItemSelected(quickRanksList.indexOf(competitorDAO), false);
map.setTitle("");
/*if(!quickRanksBox.isItemSelected(quickRanksList.indexOf(competitorDAO))){
setSelectedInMap(competitorDAO, false);
}*/
//quickRanksBox.setItemSelected(quickRanksList.indexOf(competitorDAO), false);
}
});
return boatMarker;
@@ -732,9 +739,7 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
}
private String getColorString(CompetitorDAO competitorDAO) {
// green no more than 70, rot no less than 120
// TODO try to avoid colors close to the light blue water display color
// of the underlying 2D map
// TODO green no more than 70, red no less than 120
return "#" + Integer.toHexString(competitorDAO.hashCode()).substring(0, 4).toUpperCase()+"00";
}
@@ -791,16 +796,20 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
@Override
public void onMouseOver(PolylineMouseOverEvent event) {
map.setTitle(competitorDAO.name);
setSelectedInMap(competitorDAO, true);
quickRanksBox.setItemSelected(quickRanksList.indexOf(competitorDAO), true);
/*if(quickRanksBox.isItemSelected(quickRanksList.indexOf(competitorDAO))){
setSelectedInMap(competitorDAO, true);
}*/
//quickRanksBox.setItemSelected(quickRanksList.indexOf(competitorDAO), true);
}
});
result.addPolylineMouseOutHandler(new PolylineMouseOutHandler() {
@Override
public void onMouseOut(PolylineMouseOutEvent event) {
map.setTitle("");
setSelectedInMap(competitorDAO, false);
quickRanksBox.setItemSelected(quickRanksList.indexOf(competitorDAO), false);
/* if(!quickRanksBox.isItemSelected(quickRanksList.indexOf(competitorDAO))){
setSelectedInMap(competitorDAO, false);
}*/
//quickRanksBox.setItemSelected(quickRanksList.indexOf(competitorDAO), false);
}
});
tails.put(competitorDAO, result);
@@ -114,6 +114,10 @@ public interface SailingService extends RemoteService {
void trackWithSwissTiming(SwissTimingRaceRecordDAO rr, String hostname, int port, boolean canSendRequests,
boolean trackWind, boolean correctWindByDeclination) throws Exception;
void sendSwissTimingDummyRace(String racMessage, String stlMesssage, String ccgMessage) throws IllegalArgumentException;
void stressTestLeaderboardByName(String leaderboardName, int times) throws Exception;
String[] getCountryCodes();
}
@@ -174,10 +174,13 @@ public interface SailingServiceAsync {
void trackWithSwissTiming(SwissTimingRaceRecordDAO rr, String hostname, int port, boolean canSendRequests,
boolean trackWind, boolean correctWindByDeclination, AsyncCallback<Void> asyncCallback);
void sendSwissTimingDummyRace(String racMessage, String stlMesssage, String ccgMessage, AsyncCallback<Void> callback);
/**
* Requests the computation of the {@link LeaderboardDAO} for <code>leaderboardName</code> <code>times</code> times.
* The date used for the {@link #getLeaderboardByName(String, Date, Collection, AsyncCallback)} call is iterated
* in 10ms time steps, going backwards from "now." For all races, all details are requested.
*/
void stressTestLeaderboardByName(String leaderboardName, int times, AsyncCallback<Void> callback);
void getCountryCodes(AsyncCallback<String[]> callback);
}
@@ -112,5 +112,6 @@ public interface StringConstants extends Constants {
String raceStartTimeColumn();
String showOnlySelected();
String tailLength();
String selectedRaces();
String stressTest();
}
@@ -102,9 +102,10 @@ timing=Timing
raceDetailsToShow=Race Details
legDetailsToShow=Leg Details
columnMoveUp=Up
columnMoveDown=Down
columnMoveDown=Down
port=Port
raceStartTimeColumn=Race Started
showOnlySelected=Show only selected
tailLength=Tail length (s)
tailLength=Tail length (s)
selectedRaces=Selected races
stressTest=Stress Test
@@ -102,9 +102,10 @@ timing=Timing
raceDetailsToShow=Renn Details
legDetailsToShow=Schenkel Details
columnMoveUp=Hoch
columnMoveDown=Runter
columnMoveDown=Runter
port=Port
raceStartTimeColumn=Rennstart
showOnlySelected=Nur ausgewählte anzeigen
tailLength=Schweiflänge (s)
tailLength=Schweiflänge (s)
selectedRaces=Angewählte Rennen
stressTest=Stresstest
@@ -117,6 +117,8 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
private final SwissTimingFactory swissTimingFactory;
private final com.sap.sailing.domain.tractracadapter.persistence.DomainObjectFactory tractracDomainObjectFactory;
private final com.sap.sailing.util.CountryCodeFactory countryCodeFactory;
public SailingServiceImpl() {
BundleContext context = Activator.getDefault();
@@ -127,6 +129,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
tractracDomainObjectFactory = com.sap.sailing.domain.tractracadapter.persistence.DomainObjectFactory.INSTANCE;
tractracMongoObjectFactory = com.sap.sailing.domain.tractracadapter.persistence.MongoObjectFactory.INSTANCE;
swissTimingFactory = SwissTimingFactory.INSTANCE;
countryCodeFactory = com.sap.sailing.util.CountryCodeFactory.INSTANCE;
}
protected ServiceTracker<RacingEventService, RacingEventService> createAndOpenRacingEventServiceTracker(
@@ -1088,4 +1091,21 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
}.start();
}
}
@Override
public void sendSwissTimingDummyRace(String racMessage, String stlMesssage, String ccgMessage) {
getService().storeSwissTimingDummyRace(racMessage,stlMesssage,ccgMessage);
}
@Override
public String[] getCountryCodes() {
List<String> countryCodes = new ArrayList<String>();
for (CountryCode cc : countryCodeFactory.getAll()){
if (cc.getThreeLetterIOCCode() != null && !cc.getThreeLetterIOCCode().equals("")){
countryCodes.add(cc.getThreeLetterIOCCode());
}
}
Collections.sort(countryCodes);
return countryCodes.toArray(new String[0]);
}
}
@@ -30,7 +30,4 @@
<source path='client'/>
<source path='shared'/>
<source path='test'/>
<servlet path='/testsailing' class='com.sap.sailing.gwt.ui.test.TestSailingServiceImpl'/>
</module>
@@ -1,2 +1,3 @@
# Module com.sap.sailing.gwt.ui.AdminConsole
# RPC service class, partial path of RPC policy file
com.sap.sailing.gwt.ui.client.SailingService, 906BB1F6D2D07FBD649386B9E061438A.gwt.rpc
@@ -184,5 +184,7 @@ public interface RacingEventService extends TrackedEventRegistry {
WindStore windStore, long timeoutInMilliseconds) throws InterruptedException, UnknownHostException, IOException, ParseException;
SwissTimingFactory getSwissTimingFactory();
public void storeSwissTimingDummyRace(String racMessage, String stlMesssage, String ccgMessage) throws IllegalArgumentException;
}
@@ -36,6 +36,7 @@ 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.SailMasterMessage;
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
import com.sap.sailing.domain.swisstimingadapter.persistence.SwissTimingAdapterPersistence;
import com.sap.sailing.domain.tracking.DynamicTrackedEvent;
@@ -488,5 +489,20 @@ public class RacingEventServiceImpl implements RacingEventService {
public void remove(Event event) {
eventTrackingCache.remove(event);
}
@Override
public void storeSwissTimingDummyRace(String racMessage, String stlMessage, String ccgMessage){
SailMasterMessage racSMMessage = swissTimingFactory.createMessage(racMessage, null);
SailMasterMessage stlSMMessage = swissTimingFactory.createMessage(stlMessage, null);
SailMasterMessage ccgSMMessage = swissTimingFactory.createMessage(ccgMessage, null);
if (swissTimingAdapterPersistence.getRace(stlSMMessage.getRaceID()) != null) {
throw new IllegalArgumentException("Race with raceID \"" + stlSMMessage.getRaceID() + "\" already exists.");
}
else {
swissTimingAdapterPersistence.storeSailMasterMessage(racSMMessage);
swissTimingAdapterPersistence.storeSailMasterMessage(stlSMMessage);
swissTimingAdapterPersistence.storeSailMasterMessage(ccgSMMessage);
}
}
}
@@ -59,7 +59,7 @@ public class RankPerLeg2 extends Action {
// final String legId = numberFormat.format(++i);
legId = numberFormat.format(++i);
}
final String markName = leg.getTo().getName();
final String markName = leg==null?"null":leg.getTo().getName();
final String upOrDownwinLeg = trackedLeg.isUpOrDownwindLeg(time) ? "U" : "D";
final String upOrDownwindLegText = trackedLeg.isUpOrDownwindLeg(time) ? "Upwind" : "Downwind";
LinkedHashMap<Competitor, Integer> ranks = trackedLeg.getRanks(time);
@@ -91,7 +91,7 @@ public class RankPerLeg2 extends Action {
} else {
addColumn(markName);
}
addColumn(leg.getTo().getBuoys().iterator().next().getName());
addColumn(leg==null?"null":leg.getTo().getBuoys().iterator().next().getName());
addColumn(upOrDownwinLeg);
addColumn(competitorName);
+177 -177
View File
@@ -1,189 +1,189 @@
<?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>
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>workspace</artifactId>
<groupId>com.sap.sailing</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<parent>
<artifactId>workspace</artifactId>
<groupId>com.sap.sailing</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>root</artifactId>
<packaging>pom</packaging>
<artifactId>root</artifactId>
<packaging>pom</packaging>
<modules>
<module>com.sap.sailing.domain</module>
<module>com.sap.sailing.domain.persistence</module>
<module>com.sap.sailing.domain.test</module>
<module>com.sap.sailing.domain.tractracadapter</module>
<module>com.sap.sailing.domain.tractracadapter.persistence</module>
<module>com.sap.sailing.domain.swisstimingadapter</module>
<module>com.sap.sailing.domain.swisstimingadapter.persistence</module>
<module>com.sap.sailing.domain.swisstimingadapter.test</module>
<module>com.sap.sailing.declination</module>
<module>com.sap.sailing.declination.test</module>
<module>com.sap.sailing.udpconnector</module>
<module>com.sap.sailing.expeditionconnector</module>
<module>com.sap.sailing.expeditionconnector.test</module>
<module>com.sap.sailing.server</module>
<module>com.sap.sailing.xcelsiusadapter</module>
<module>com.sap.sailing.httpservicetracker</module>
<module>com.sap.sailing.gwt.ui</module>
<module>com.sap.sailing.gwt.ui.test</module>
<module>com.google.gwt.osgi</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>
<module>com.tractrac.resultapi</module>
<module>org.json.simple</module>
<module>com.mongodb.driver</module>
<module>com.googlecode.java-diff-utils</module>
<module>com.googlecode.java-diff-utils.test</module>
<module>com.sap.ui.phoenix.resource-osgi</module>
<module>com.sap.ui.phoenix.resource-servlet</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<modules>
<module>com.sap.sailing.domain</module>
<module>com.sap.sailing.domain.persistence</module>
<module>com.sap.sailing.domain.test</module>
<module>com.sap.sailing.domain.tractracadapter</module>
<module>com.sap.sailing.domain.tractracadapter.persistence</module>
<module>com.sap.sailing.domain.swisstimingadapter</module>
<module>com.sap.sailing.domain.swisstimingadapter.persistence</module>
<module>com.sap.sailing.domain.swisstimingadapter.test</module>
<module>com.sap.sailing.declination</module>
<module>com.sap.sailing.declination.test</module>
<module>com.sap.sailing.udpconnector</module>
<module>com.sap.sailing.expeditionconnector</module>
<module>com.sap.sailing.expeditionconnector.test</module>
<module>com.sap.sailing.server</module>
<module>com.sap.sailing.xcelsiusadapter</module>
<module>com.sap.sailing.httpservicetracker</module>
<module>com.sap.sailing.gwt.ui</module>
<module>com.sap.sailing.gwt.ui.test</module>
<module>com.google.gwt.osgi</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>
<module>com.tractrac.resultapi</module>
<module>org.json.simple</module>
<module>com.mongodb.driver</module>
<module>com.googlecode.java-diff-utils</module>
<module>com.googlecode.java-diff-utils.test</module>
<module>com.sap.ui.phoenix.resource-osgi</module>
<module>com.sap.ui.phoenix.resource-servlet</module>
</modules>
<build>
<directory>bin</directory>
<outputDirectory>bin</outputDirectory>
<testOutputDirectory>bin</testOutputDirectory>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<pluginManagement>
<plugins>
<plugin>
<inherited>true</inherited>
<groupId>org.sonatype.tycho</groupId>
<artifactId>maven-osgi-test-plugin</artifactId>
<version>0.10.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
</plugin>
</plugins>
</pluginManagement>
<build>
<directory>bin</directory>
<outputDirectory>bin</outputDirectory>
<testOutputDirectory>bin</testOutputDirectory>
<plugins>
<plugin>
<groupId>org.sonatype.tycho</groupId>
<artifactId>tycho-maven-plugin</artifactId>
<version>0.10.0</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.sonatype.tycho</groupId>
<artifactId>target-platform-configuration</artifactId>
<version>0.10.0</version>
<configuration>
<resolver>p2</resolver>
<environments>
<environment>
<os>linux</os>
<ws>gtk</ws>
<arch>x86</arch>
</environment>
<environment>
<os>linux</os>
<ws>gtk</ws>
<arch>x86_64</arch>
</environment>
<environment>
<os>win32</os>
<ws>win32</ws>
<arch>x86</arch>
</environment>
<environment>
<os>win32</os>
<ws>win32</ws>
<arch>x86_64</arch>
</environment>
<environment>
<os>macosx</os>
<ws>cocoa</ws>
<arch>x86_64</arch>
</environment>
</environments>
<pomDependencies>consider</pomDependencies>
</configuration>
</plugin>
<plugin>
<groupId>org.sonatype.tycho</groupId>
<artifactId>maven-osgi-test-plugin</artifactId>
<configuration>
<!-- non-debug -->
<!-- proxy -->
<argLine>-Dfile.encoding=cp1252 -Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080 -Dtractrac.tunnel=true -Dtractrac.tunnel.host=10.18.10.38 -Dmongo.host=10.18.10.38 -Xmx1024m -XX:PermSize=256m -XX:-UseGCOverheadLimit -XX:+UseParallelGC</argLine>
<!-- -->
<!-- no proxy
<argLine>-Dfile.encoding=cp1252 -Xmx1024m -XX:PermSize=256m -XX:-UseGCOverheadLimit -XX:+UseParallelGC</argLine>
-->
<!-- -->
<!-- debug
<argLine>-Dfile.encoding=cp1252 -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y -Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080 -Xmx1024m -XX:PermSize=256m -XX:-UseGCOverheadLimit -XX:+UseParallelGC</argLine>
-->
<testFailureIgnore>true</testFailureIgnore>
<excludes>
<exclude>**/*$*</exclude> <!-- Exclude inner classes -->
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.sonatype.tycho</groupId>
<artifactId>maven-osgi-compiler-plugin</artifactId>
<version>0.10.0</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<inherited>true</inherited>
<groupId>org.sonatype.tycho</groupId>
<artifactId>maven-osgi-test-plugin</artifactId>
<version>0.10.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
</plugin>
</plugins>
</pluginManagement>
<extensions>
<!-- Enabling the use of FTP -->
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh-external</artifactId>
<version>1.0-beta-6</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.sonatype.tycho</groupId>
<artifactId>tycho-maven-plugin</artifactId>
<version>0.10.0</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.sonatype.tycho</groupId>
<artifactId>target-platform-configuration</artifactId>
<version>0.10.0</version>
<configuration>
<resolver>p2</resolver>
<environments>
<environment>
<os>linux</os>
<ws>gtk</ws>
<arch>x86</arch>
</environment>
<environment>
<os>linux</os>
<ws>gtk</ws>
<arch>x86_64</arch>
</environment>
<environment>
<os>win32</os>
<ws>win32</ws>
<arch>x86</arch>
</environment>
<environment>
<os>win32</os>
<ws>win32</ws>
<arch>x86_64</arch>
</environment>
<environment>
<os>macosx</os>
<ws>cocoa</ws>
<arch>x86_64</arch>
</environment>
</environments>
<pomDependencies>consider</pomDependencies>
</configuration>
</plugin>
<plugin>
<groupId>org.sonatype.tycho</groupId>
<artifactId>maven-osgi-test-plugin</artifactId>
<configuration>
<!-- non-debug -->
<!-- proxy -->
<argLine>-Dfile.encoding=cp1252
-Dhttp.proxyHost=proxy
-Dhttp.proxyPort=8080 -Dtractrac.tunnel=true
-Dtractrac.tunnel.host=10.18.10.38 -Dmongo.host=10.18.10.38
-Xmx1024m -XX:PermSize=256m -XX:-UseGCOverheadLimit
-XX:+UseParallelGC</argLine>
<!-- -->
<!-- no proxy <argLine>-Dfile.encoding=cp1252 -Xmx1024m
-XX:PermSize=256m -XX:-UseGCOverheadLimit -XX:+UseParallelGC</argLine> -->
<!-- -->
<!-- debug <argLine>-Dfile.encoding=cp1252 -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y
-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080 -Xmx1024m -XX:PermSize=256m
-XX:-UseGCOverheadLimit -XX:+UseParallelGC</argLine> -->
<testFailureIgnore>true</testFailureIgnore>
<excludes>
<exclude>**/*$*</exclude> <!-- Exclude inner classes -->
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.sonatype.tycho</groupId>
<artifactId>maven-osgi-compiler-plugin</artifactId>
<version>0.10.0</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<distributionManagement>
<repository>
<id>ssh-repository</id>
<url>scpexe://trac@localhost:12347/home/trac/maven-repositories/dev</url>
</repository>
</distributionManagement>
<extensions>
<!-- Enabling the use of FTP -->
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh-external</artifactId>
<version>1.0-beta-6</version>
</extension>
</extensions>
<repositories>
<repository>
<layout>p2</layout>
<id>eclipse</id>
<url>http://download.eclipse.org/releases/indigo/</url>
</repository>
<repository>
<id>sap-nexus</id>
<url>http://nexus.wdf.sap.corp:8081/nexus/content/groups/build.snapshots</url>
</repository>
<!--
<repository>
<id>central</id>
<url>http://repo1.maven.org/maven2</url>
</repository>
-->
<repository>
<id>uni-luebeck</id>
<url>http://www.itm.uni-luebeck.de/projects/maven/releases</url>
</repository>
</repositories>
</build>
<distributionManagement>
<repository>
<id>ssh-repository</id>
<url>scpexe://trac@localhost:12347/home/trac/maven-repositories/dev</url>
</repository>
</distributionManagement>
<repositories>
<repository>
<layout>p2</layout>
<id>eclipse</id>
<url>http://download.eclipse.org/releases/indigo/</url>
</repository>
<repository>
<id>sap-nexus</id>
<url>http://nexus.wdf.sap.corp:8081/nexus/content/groups/build.snapshots</url>
</repository>
<!-- <repository> <id>central</id> <url>http://repo1.maven.org/maven2</url>
</repository> -->
<repository>
<id>uni-luebeck</id>
<url>http://www.itm.uni-luebeck.de/projects/maven/releases</url>
</repository>
</repositories>
</project>