Merge branch 'gwt' into charts

This commit is contained in:
Benjamin Ebling committed 2011-12-05 15:36:05 +01:00
commit 95ef41f2c5
52 files changed
+1222 -765

No files matched your search

@@ -37,7 +37,7 @@ import com.sap.sailing.domain.swisstimingadapter.persistence.SwissTimingAdapterP
import com.sap.sailing.domain.swisstimingadapter.persistence.impl.CollectionNames;
import com.sap.sailing.domain.swisstimingadapter.persistence.impl.FieldNames;
import com.sap.sailing.domain.tracking.DynamicTrackedEvent;
import com.sap.sailing.domain.tracking.RaceHandle;
import com.sap.sailing.domain.tracking.RacesHandle;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
import com.sap.sailing.mongodb.MongoDBService;
@@ -63,7 +63,7 @@ public class EndToEndListeningStoreAndFowardTest {
private EmptyWindStore emptyWindStore;
private RacingEventService racingEventService;
private List<RaceHandle> raceHandles;
private List<RacesHandle> raceHandles;
@Before
public void setUp() throws UnknownHostException, IOException, InterruptedException {
@@ -85,13 +85,13 @@ public class EndToEndListeningStoreAndFowardTest {
new BasicDBObject().append(FieldNames.LAST_MESSAGE_COUNT.name(), 0l),
/* upsert */true, /* multi */false);
racingEventService = new RacingEventServiceImpl();
raceHandles = new ArrayList<RaceHandle>();
raceHandles = new ArrayList<RacesHandle>();
}
@After
public void tearDown() throws InterruptedException, IOException {
logger.entering(getClass().getName(), "tearDown");
for (RaceHandle raceHandle : raceHandles) {
for (RacesHandle raceHandle : raceHandles) {
racingEventService.stopTracking(raceHandle.getEvent());
}
logger.info("Calling StoreAndForward.stop() in tearDown");
@@ -292,7 +292,7 @@ public class EndToEndListeningStoreAndFowardTest {
private void setUpUsingScript(String[] racesToTrack, String... scriptNames) throws InterruptedException,
UnknownHostException, IOException, ParseException {
for (String raceToTrack : racesToTrack) {
RaceHandle raceHandle = racingEventService.addSwissTimingRace(raceToTrack, "localhost", CLIENT_PORT, /* canSendRequests */
RacesHandle raceHandle = racingEventService.addSwissTimingRace(raceToTrack, "localhost", CLIENT_PORT, /* canSendRequests */
false, emptyWindStore, -1);
raceHandles.add(raceHandle);
if (connector == null) {
@@ -76,14 +76,14 @@ public class DomainFactoryImpl implements DomainFactory {
SAM007000 Men's Keelboat = Starboot Männer
SAW010000 Women's Match Racing = Matchrace Damen Elliott 6M (modified)
*/
olympicClassesByID.put("102", new BoatClassImpl("RS:X"));
olympicClassesByID.put("004", new BoatClassImpl("Laser"));
olympicClassesByID.put("103", new BoatClassImpl("Laser Radial"));
olympicClassesByID.put("002", new BoatClassImpl("Finn"));
olympicClassesByID.put("005", new BoatClassImpl("470"));
olympicClassesByID.put("009", new BoatClassImpl("49er"));
olympicClassesByID.put("007", new BoatClassImpl("Star"));
olympicClassesByID.put("010", new BoatClassImpl("Elliott 6M"));
olympicClassesByID.put("102", baseDomainFactory.getOrCreateBoatClass("RS:X"));
olympicClassesByID.put("004", baseDomainFactory.getOrCreateBoatClass("Laser"));
olympicClassesByID.put("103", baseDomainFactory.getOrCreateBoatClass("Laser Radial"));
olympicClassesByID.put("002", baseDomainFactory.getOrCreateBoatClass("Finn"));
olympicClassesByID.put("005", baseDomainFactory.getOrCreateBoatClass("470"));
olympicClassesByID.put("009", baseDomainFactory.getOrCreateBoatClass("49er"));
olympicClassesByID.put("007", baseDomainFactory.getOrCreateBoatClass("Star"));
olympicClassesByID.put("010", baseDomainFactory.getOrCreateBoatClass("Elliott 6M"));
unknownBoatClass = new BoatClassImpl("Unknown");
}
@@ -38,7 +38,7 @@ import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.GPSFix;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.RaceHandle;
import com.sap.sailing.domain.tracking.RacesHandle;
import com.sap.sailing.domain.tracking.RaceTracker;
import com.sap.sailing.domain.tracking.TrackedEventRegistry;
import com.sap.sailing.domain.tracking.WindStore;
@@ -94,21 +94,21 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl implemen
}
@Override
public RaceHandle getRaceHandle() {
return new RaceHandle() {
public RacesHandle getRaceHandle() {
return new RacesHandle() {
@Override
public Event getEvent() {
return SwissTimingRaceTrackerImpl.this.getEvent();
}
@Override
public RaceDefinition getRace() {
return race;
public Set<RaceDefinition> getRaces() {
return Collections.singleton(race);
}
@Override
public RaceDefinition getRace(long timeoutInMilliseconds) {
return race;
public Set<RaceDefinition> getRaces(long timeoutInMilliseconds) {
return Collections.singleton(race);
}
@Override
@@ -46,7 +46,7 @@ public class UnicodeCharactersInCompetitorNamesTest {
tractracTunnel ? new URI("tcp://"+tractracTunnelHost+":4413") : new URI("tcp://germanmaster.traclive.dk:4401"),
EmptyWindStore.INSTANCE, new DummyTrackedEventRegistry());
Iterable<Competitor> competitors = fourtyninerYellow_2.getRaceHandle().getRace().getCompetitors();
Iterable<Competitor> competitors = fourtyninerYellow_2.getRaceHandle().getRaces().iterator().next().getCompetitors();
for (Competitor competitor : competitors) {
System.out.println(competitor.getName());
}
@@ -27,7 +27,6 @@ import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.domain.base.TimePoint;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.CompetitorImpl;
import com.sap.sailing.domain.base.impl.CourseImpl;
@@ -79,8 +78,6 @@ public class DomainFactoryImpl implements DomainFactory {
private final Map<String, Team> teamCache = new HashMap<String, Team>();
private final Map<CompetitorClass, BoatClass> boatClassCache = new HashMap<CompetitorClass, BoatClass>();
/**
* Caches events by their name and their boat class's name
*/
@@ -195,14 +192,7 @@ public class DomainFactoryImpl implements DomainFactory {
@Override
public BoatClass getOrCreateBoatClass(CompetitorClass competitorClass) {
synchronized (boatClassCache) {
BoatClass result = boatClassCache.get(competitorClass);
if (result == null) {
result = new BoatClassImpl(competitorClass == null ? "" : competitorClass.getName());
boatClassCache.put(competitorClass, result);
}
return result;
}
return baseDomainFactory.getOrCreateBoatClass(competitorClass == null ? "" : competitorClass.getName());
}
@Override
@@ -1,13 +1,17 @@
package com.sap.sailing.domain.tractracadapter.impl;
import java.util.HashSet;
import java.util.Set;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.tracking.DynamicTrackedEvent;
import com.sap.sailing.domain.tracking.RaceHandle;
import com.sap.sailing.domain.tracking.RacesHandle;
import com.sap.sailing.domain.tractracadapter.DomainFactory;
import com.sap.sailing.domain.tractracadapter.TracTracRaceTracker;
import com.tractrac.clientmodule.Event;
import com.tractrac.clientmodule.Race;
public class RaceHandleImpl implements RaceHandle {
public class RaceHandleImpl implements RacesHandle {
private final Event tractracEvent;
private final DomainFactory domainFactory;
private final DynamicTrackedEvent trackedEvent;
@@ -26,9 +30,12 @@ public class RaceHandleImpl implements RaceHandle {
}
@Override
public RaceDefinition getRace() {
// FIXME we assume there is exactly one Race per TracTrac event but during match racing there may be many
return domainFactory.getAndWaitForRaceDefinition(tractracEvent.getRaceList().iterator().next());
public Set<RaceDefinition> getRaces() {
Set<RaceDefinition> result = new HashSet<RaceDefinition>();
for (Race r : tractracEvent.getRaceList()) {
result.add(domainFactory.getAndWaitForRaceDefinition(r));
}
return result;
}
@Override
@@ -42,9 +49,12 @@ public class RaceHandleImpl implements RaceHandle {
}
@Override
public RaceDefinition getRace(long timeoutInMilliseconds) {
// FIXME we assume there is exactly one Race per TracTrac event but during match racing there may be many
return domainFactory.getAndWaitForRaceDefinition(tractracEvent.getRaceList().iterator().next(), timeoutInMilliseconds);
public Set<RaceDefinition> getRaces(long timeoutInMilliseconds) {
Set<RaceDefinition> result = new HashSet<RaceDefinition>();
for (Race r : tractracEvent.getRaceList()) {
result.add(domainFactory.getAndWaitForRaceDefinition(r, timeoutInMilliseconds));
}
return result;
}
}
@@ -26,7 +26,7 @@ import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet;
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;
import com.sap.sailing.domain.tracking.RacesHandle;
import com.sap.sailing.domain.tracking.TrackedEvent;
import com.sap.sailing.domain.tracking.TrackedEventRegistry;
import com.sap.sailing.domain.tracking.TrackedRace;
@@ -184,7 +184,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
}
@Override
public RaceHandle getRaceHandle() {
public RacesHandle getRaceHandle() {
return new RaceHandleImpl(domainFactory, tractracEvent, getTrackedEvent(), this);
}
@@ -19,4 +19,6 @@ public interface DomainFactory {
Waypoint createWaypoint(ControlPoint controlPoint);
MarkPassing createMarkPassing(TimePoint timePoint, Waypoint waypoint, Competitor competitor);
BoatClass getOrCreateBoatClass(String name);
}
@@ -4,6 +4,7 @@ import java.awt.TrayIcon.MessageType;
import java.util.HashMap;
import java.util.Map;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Buoy;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.ControlPoint;
@@ -23,10 +24,13 @@ public class DomainFactoryImpl implements DomainFactory {
private final Map<String, Nationality> nationalityCache;
private final Map<String, Buoy> buoyCache;
private final Map<String, BoatClass> boatClassCache;
public DomainFactoryImpl() {
nationalityCache = new HashMap<String, Nationality>();
buoyCache = new HashMap<String, Buoy>();
boatClassCache = new HashMap<String, BoatClass>();
}
@Override
@@ -71,4 +75,16 @@ public class DomainFactoryImpl implements DomainFactory {
return new MarkPassingImpl(timePoint, waypoint, competitor);
}
@Override
public BoatClass getOrCreateBoatClass(String name) {
synchronized (boatClassCache) {
BoatClass result = boatClassCache.get(name);
if (result == null) {
result = new BoatClassImpl(name);
boatClassCache.put(name, result);
}
return result;
}
}
}
@@ -379,8 +379,7 @@ public class LeaderboardImpl implements Named, Leaderboard {
}
@Override
public void setResultDiscardingRule(ThresholdBasedResultDiscardingRule discardingRule)
{
public void setResultDiscardingRule(ThresholdBasedResultDiscardingRule discardingRule) {
this.resultDiscardingRule = discardingRule;
}
}
@@ -3,6 +3,6 @@ package com.sap.sailing.domain.tracking;
import com.sap.sailing.domain.base.SpeedWithBearing;
import com.sap.sailing.domain.base.Timed;
public interface GPSFix extends Positioned, Timed {
public interface GPSFix extends Positioned, Timed, WithValidityCache {
SpeedWithBearing getSpeedAndBearingRequiredToReach(GPSFix to);
}
@@ -25,7 +25,7 @@ public interface RaceTracker {
Set<RaceDefinition> getRaces();
// TODO this is inconsistent with getRaces() which can return more than one race
RaceHandle getRaceHandle();
RacesHandle getRaceHandle();
DynamicTrackedEvent getTrackedEvent();
@@ -1,25 +1,27 @@
package com.sap.sailing.domain.tracking;
import java.util.Set;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.RaceDefinition;
/**
* Gives clients a way to refer to a specific race even though the {@link RaceDefinition} object may not have
* been created yet, but without exposing the TracTrac internals. The {@link #getRace()} call will block
* until the {@link RaceDefinition} has been created.
* Gives clients a way to refer to a specific set of races even though the {@link RaceDefinition} objects may not have
* been created yet, but without exposing the tracking provider's internals. The {@link #getRaces()} call will block
* until the {@link RaceDefinition}s have been created.
*
* @author Axel Uhl (d043530)
*
*/
public interface RaceHandle {
public interface RacesHandle {
Event getEvent();
/**
* Fetch the race definition. If the race definition represented by this handle hasn't been created yet, the call
* Fetch the race definitions. If the race definitions represented by this handle haven't been created yet, the call
* blocks until such a definition is provided by another call, usually by the {@link RaceCourseReceiver}.
*/
RaceDefinition getRace();
Set<RaceDefinition> getRaces();
/**
* Fetch the race definition. If the race definition represented by this handle hasn't been created yet, the call
@@ -29,7 +31,7 @@ public interface RaceHandle {
* <code>timeoutInMilliseconds</code> in case no modifications happen on the {@link DomainFactory}'s
* set of races during that time.
*/
RaceDefinition getRace(long timeoutInMilliseconds);
Set<RaceDefinition> getRaces(long timeoutInMilliseconds);
DynamicTrackedEvent getTrackedEvent();
@@ -15,8 +15,10 @@ public interface TrackedLegOfCompetitor {
Competitor getCompetitor();
/**
* How long did it take the competitor to complete this {@link #getLeg() leg}? If the competitor hasn't finished the
* leg yet, -1 is returned.
* How much time did the {@link #getCompetitor competitor} spend in this {@link #getLeg() leg} at
* <code>timePoint</code>? If the competitor hasn't started the leg yet at <code>timePoint</code>, 0 is returned. If the
* competitor has finished the leg already at <code>timePoint</code>, the time it took the competitor to
* complete the leg is returned.
*/
long getTimeInMilliSeconds(TimePoint timePoint);
@@ -0,0 +1,11 @@
package com.sap.sailing.domain.tracking;
public interface WithValidityCache {
boolean isValidityCached();
boolean isValid();
void invalidateCache();
void cacheValidity(boolean isValid);
}
@@ -47,5 +47,21 @@ public abstract class AbstractGPSFixImpl implements GPSFix {
return new KnotSpeedWithBearingImpl(speed.getKnots(), bearing);
}
@Override
public boolean isValidityCached() {
return false;
}
@Override
public boolean isValid() {
return false;
}
@Override
public void invalidateCache() {
}
@Override
public void cacheValidity(boolean isValid) {
}
}
@@ -6,11 +6,29 @@ import com.sap.sailing.domain.base.impl.AbstractPosition;
import com.sap.sailing.domain.base.impl.AbstractTimePoint;
import com.sap.sailing.domain.tracking.GPSFix;
public class CompactGPSFixImpl extends AbstractGPSFixImpl implements GPSFix {
/**
* A compact representation of a GPS fix which collects all primitive-typed attributes in one object to avoid
* memory overhead otherwise created by using too many individual fine-grained objects.<p>
*
* Objects of this type are assumed to be contained in at most one {@link DynamicGPSFixTrackImpl}. It is
* therefore permissible to cache information about validity to speed up the otherwise expensive
* {@link DynamicGPSFixTrackImpl#isValid(PartialNavigableSetView, GPSFix)} computation.
*
* @author Axel Uhl (d043530)
*
*/
public class CompactGPSFixImpl extends AbstractGPSFixImpl {
private final double latDeg;
private final double lngDeg;
private final long timePointAsMillis;
/**
* Tells if in the containing {@link DynamicGPSFixTrackImpl} this fix is considered valid. This cache
* needs to be invalidated as soon as fixes are added to the containing track which may have an impact
* on this fix's validity. -1 means "no value"; 0 means invalid, 1 means valid.
*/
private byte validityCache = -1;
private class CompactPosition extends AbstractPosition {
@Override
public double getLatDeg() {
@@ -55,4 +73,24 @@ public class CompactGPSFixImpl extends AbstractGPSFixImpl implements GPSFix {
return new CompactTimePoint();
}
@Override
public boolean isValidityCached() {
return validityCache != -1;
}
@Override
public boolean isValid() {
return validityCache == 1;
}
@Override
public void invalidateCache() {
validityCache = -1;
}
@Override
public void cacheValidity(boolean isValid) {
validityCache = (byte) (isValid ? 1 : 0);
}
}
@@ -126,6 +126,21 @@ public class DynamicGPSFixMovingTrackImpl<ItemType> extends DynamicTrackImpl<Ite
public SpeedWithBearing getSpeedAndBearingRequiredToReach(GPSFix to) {
return null;
}
@Override
public boolean isValidityCached() {
return false;
}
@Override
public boolean isValid() {
return false;
}
@Override
public void invalidateCache() {
}
@Override
public void cacheValidity(boolean isValid) {
}
}
@@ -156,22 +171,31 @@ public class DynamicGPSFixMovingTrackImpl<ItemType> extends DynamicTrackImpl<Ite
*/
@Override
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());
boolean result;
if (e.isValidityCached()) {
result = e.isValid();
} else {
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());
}
result = (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));
e.cacheValidity(result);
}
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));
return result;
}
}
@@ -26,6 +26,7 @@ public class DynamicTrackImpl<ItemType, FixType extends GPSFix> extends
public void addGPSFix(FixType gpsFix) {
synchronized (this) {
getInternalRawFixes().add(gpsFix);
invalidateValidityCaches(gpsFix);
}
for (RaceChangeListener<ItemType> listener : listeners) {
listener.gpsFixReceived(gpsFix, getTrackedItem());
@@ -19,6 +19,7 @@ import com.sap.sailing.domain.base.impl.NauticalMileDistance;
import com.sap.sailing.domain.tracking.GPSFix;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.WithValidityCache;
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);
@@ -50,6 +51,23 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
public SpeedWithBearing getSpeedAndBearingRequiredToReach(GPSFix to) {
return null;
}
@Override
public boolean isValidityCached() {
return false;
}
@Override
public boolean isValid() {
return false;
}
@Override
public void invalidateCache() {
}
@Override
public void cacheValidity(boolean isValid) {
}
}
protected void setMillisecondsOverWhichToAverage(long millisecondsOverWhichToAverage) {
@@ -282,29 +300,56 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
};
}
/**
* When redefining this method, make sure to redefine {@link #invalidateValidityCaches(GPSFix)} accordingly.
* This implementation checks the immediate previous and next fix for <code>e</code>. Therefore, when
* adding a fix, only immediately adjacent fix's validity caches need to be invalidated.
*/
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());
if (e.isValidityCached()) {
result = e.isValid();
} 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));
e.cacheValidity(result);
}
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;
}
/**
* After <code>gpsFix</code> was added to this track, invalidate the {@link WithValidityCache validity caches}
* of the fixes whose validity may be affected. If subclasses redefine {@link #isValid(PartialNavigableSetView, GPSFix)},
* they must make sure that this method is redefined accordingly.
*/
protected synchronized void invalidateValidityCaches(FixType gpsFix) {
gpsFix.invalidateCache();
FixType lower = getInternalRawFixes().lower(gpsFix);
if (lower != null) {
lower.invalidateCache();
}
FixType higher = getInternalRawFixes().higher(gpsFix);
if (higher != null) {
higher.invalidateCache();
}
}
@Override
public boolean hasDirectionChange(TimePoint at, double minimumDegreeDifference) {
TimePoint start = new MillisecondsTimePoint(at.asMillis()-getMillisecondsOverWhichToAverageSpeed());
@@ -13,6 +13,7 @@ import com.sap.sailing.domain.base.Speed;
import com.sap.sailing.domain.base.SpeedWithBearing;
import com.sap.sailing.domain.base.TimePoint;
import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.base.impl.MeterDistance;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.Maneuver;
@@ -58,15 +59,16 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor {
@Override
public long getTimeInMilliSeconds(TimePoint timePoint) {
long result = -1;
MarkPassing passedEndWaypoint = getTrackedRace().getMarkPassing(getCompetitor(), getTrackedLeg().getLeg().getTo());
if (passedEndWaypoint != null) {
MarkPassing passedStartWaypoint = getTrackedRace().getMarkPassing(getCompetitor(), getTrackedLeg().getLeg().getFrom());
if (passedStartWaypoint != null) {
long result = 0;
MarkPassing passedStartWaypoint = getTrackedRace().getMarkPassing(getCompetitor(),
getTrackedLeg().getLeg().getFrom());
if (passedStartWaypoint != null) {
MarkPassing passedEndWaypoint = getTrackedRace().getMarkPassing(getCompetitor(),
getTrackedLeg().getLeg().getTo());
if (passedEndWaypoint != null) {
result = passedEndWaypoint.getTimePoint().asMillis() - passedStartWaypoint.getTimePoint().asMillis();
} else {
throw new RuntimeException(""+getCompetitor()+" passed waypoint at end of leg "+
getLeg()+" without having passed waypoint at beginning of leg");
result = timePoint.asMillis() - passedStartWaypoint.getTimePoint().asMillis();
}
}
return result;
@@ -327,14 +329,33 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor {
public Distance getWindwardDistanceToOverallLeader(TimePoint timePoint) throws NoWindException {
Competitor leader = getTrackedLeg().getRanks(timePoint).keySet().iterator().next();
TrackedLegOfCompetitor leaderLeg = getTrackedRace().getCurrentLeg(leader, timePoint);
if (leaderLeg.getLeg() == getLeg()) {
// we're still in the same leg with leader; compute windward distance to leader
return getWindwardDistance(getTrackedRace().getTrack(leader).getEstimatedPosition(timePoint, /* extrapolate */ false),
getTrackedRace().getTrack(getCompetitor()).getEstimatedPosition(timePoint, /* extrapolate */ false), timePoint);
} else {
return null;
// TODO special case leader has finished race already
Distance result = null;
Position leaderPosition = getTrackedRace().getTrack(leader).getEstimatedPosition(timePoint, /* extrapolate */ false);
Position currentPosition = getTrackedRace().getTrack(getCompetitor()).getEstimatedPosition(timePoint, /* extrapolate */ false);
if (leaderPosition != null && currentPosition != null) {
result = Distance.NULL;
boolean foundCompetitorsLeg = false;
for (Leg leg : getTrackedRace().getRace().getCourse().getLegs()) {
if (leg == getLeg()) {
foundCompetitorsLeg = true;
}
if (foundCompetitorsLeg) {
// if the leaderLeg is null, the leader has already arrived
if (leaderLeg == null || leg != leaderLeg.getLeg()) {
// add distance to next mark
Position nextMarkPosition = getTrackedRace().getApproximatePosition(leg.getTo(), timePoint);
Distance distanceToNextMark = getWindwardDistance(currentPosition, nextMarkPosition, timePoint);
result = new MeterDistance(result.getMeters() + distanceToNextMark.getMeters());
} else {
// we're now in the same leg with leader; compute windward distance to leader
result = new MeterDistance(result.getMeters()
+ getWindwardDistance(leaderPosition, currentPosition, timePoint).getMeters());
break;
}
}
}
}
return result;
}
@Override
@@ -0,0 +1,23 @@
<?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"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080 -XX:+UseParallelGC -Dtractrac.tunnel=true"/>
</launchConfiguration>
@@ -15,7 +15,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.UserManagement com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.Leaderboard"/>
<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="-Xmx1024m"/>
</launchConfiguration>
+7
View File
@@ -39,6 +39,13 @@
<version>1.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<!-- This dependency is required because the GWT Maven Plugin searches other GWT modules only in Maven dependencies -->
<groupId>com.google.code</groupId>
<artifactId>gwt-visualization</artifactId>
<version>1.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
@@ -19,4 +19,7 @@ interface AdminConsoleResources extends ClientBundle {
@Source("com/sap/sailing/gwt/ui/client/images/open.png")
ImageResource openBrowserIcon();
@Source("com/sap/sailing/gwt/ui/client/images/dice.png")
ImageResource scoresIcon();
}
@@ -11,16 +11,18 @@ import com.google.gwt.text.shared.SafeHtmlRenderer;
public class LeaderboardConfigImagesBarCell extends ImagesBarCell {
interface ImagesBarTemplates extends SafeHtmlTemplates {
@SafeHtmlTemplates.Template("<div name=\"{0}\" style=\"{1}\">{2}</div>")
SafeHtml cell(String name, SafeStyles styles, SafeHtml value);
@SafeHtmlTemplates.Template("<div name=\"{0}\" style=\"{1}\" title=\"{2}\">{3}</div>")
SafeHtml cell(String name, SafeStyles styles, String title, SafeHtml value);
}
public LeaderboardConfigImagesBarCell() {
public LeaderboardConfigImagesBarCell(StringConstants stringConstants) {
super();
this.stringConstants = stringConstants;
}
public LeaderboardConfigImagesBarCell(SafeHtmlRenderer<String> renderer) {
public LeaderboardConfigImagesBarCell(SafeHtmlRenderer<String> renderer, StringConstants stringConstants) {
super();
this.stringConstants = stringConstants;
}
private static ImagesBarTemplates templates = GWT.create(ImagesBarTemplates.class);
@@ -32,7 +34,11 @@ public class LeaderboardConfigImagesBarCell extends ImagesBarCell {
private static final SafeHtml ICON_OPEN_BROWSER = makeImage(resources.openBrowserIcon());
private static final SafeHtml ICON_REMOVE = makeImage(resources.removeIcon());
private static final SafeHtml ICON_EDIT_SCORES = makeImage(resources.scoresIcon());
private StringConstants stringConstants;
@Override
protected void render(com.google.gwt.cell.client.Cell.Context context, SafeHtml data, SafeHtmlBuilder sb) {
/*
@@ -46,13 +52,16 @@ public class LeaderboardConfigImagesBarCell extends ImagesBarCell {
SafeStyles imgStyle = SafeStylesUtils.fromTrustedString("float:left;cursor:hand;cursor:pointer;padding-right:5px;");
SafeHtml rendered = templates.cell("ACTION_EDIT", imgStyle, ICON_EDIT);
SafeHtml rendered = templates.cell("ACTION_EDIT", imgStyle, stringConstants.actionEdit(), ICON_EDIT);
sb.append(rendered);
rendered = templates.cell("ACTION_OPEN_BROWSER", imgStyle, ICON_OPEN_BROWSER);
rendered = templates.cell("ACTION_EDIT_SCORES", imgStyle, stringConstants.actionEditScores(), ICON_EDIT_SCORES);
sb.append(rendered);
rendered = templates.cell("ACTION_OPEN_BROWSER", imgStyle, stringConstants.actionOpenBrowser(), ICON_OPEN_BROWSER);
sb.append(rendered);
rendered = templates.cell("ACTION_REMOVE", imgStyle, ICON_REMOVE);
rendered = templates.cell("ACTION_REMOVE", imgStyle, stringConstants.actionRemove(), ICON_REMOVE);
sb.append(rendered);
}
}
File diff suppressed because it is too large. Load diff
@@ -8,29 +8,9 @@ import com.sap.sailing.gwt.ui.shared.LeaderboardDAO;
public class LeaderboardCreateDialog extends LeaderboardDialog{
private static class LeaderboardCreateValidator extends LeaderboardParameterValidator{
private Collection<String> existingLeaderboardNames;
public LeaderboardCreateValidator(Collection<String> existingLeaderboardNames, StringConstants stringConstants) {
super(stringConstants);
this.existingLeaderboardNames = existingLeaderboardNames;
}
@Override
public String getErrorMessage(LeaderboardDAO valueToValidate) {
String errorMessage = super.getErrorMessage(valueToValidate);
boolean unique = !existingLeaderboardNames.contains(valueToValidate.name);
if(errorMessage==null && !unique){
errorMessage = stringConstants.leaderboardWithThisNameAlreadyExists();
}
return errorMessage;
}
}
public LeaderboardCreateDialog(Collection<String> existingLeaderboardNames, StringConstants stringConstants,
public LeaderboardCreateDialog(Collection<LeaderboardDAO> existingLeaderboards, StringConstants stringConstants,
ErrorReporter errorReporter, AsyncCallback<LeaderboardDAO> callback) {
super(new LeaderboardDAO(), stringConstants, errorReporter, new LeaderboardCreateValidator(existingLeaderboardNames, stringConstants), callback);
super(new LeaderboardDAO(), stringConstants, errorReporter, new LeaderboardDialog.LeaderboardParameterValidator(stringConstants, existingLeaderboards), callback);
entryField = createTextBox(null);
@@ -1,122 +0,0 @@
package com.sap.sailing.gwt.ui.client;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.shared.Pair;
public class LeaderboardCreationDialog extends DataEntryDialog<Pair<String, String[]>> {
private static final int MAX_NUMBER_OF_DISCARDED_RESULTS = 4;
private final TextBox entryField;
private final TextBox[] discardThresholdBoxes;
private final ErrorReporter errorReporter;
private final StringConstants stringConstants;
private static class LeaderboardParameterValidator implements Validator<Pair<String, String[]>> {
private final StringConstants stringConstants;
private final Collection<String> existingLeaderboardNames;
public LeaderboardParameterValidator(Collection<String> existingLeaderboardNames, StringConstants stringConstants) {
super();
this.existingLeaderboardNames = existingLeaderboardNames;
this.stringConstants = stringConstants;
}
@Override
public String getErrorMessage(Pair<String, String[]> valueToValidate) {
String errorMessage;
boolean nonEmpty = valueToValidate.getA() != null && valueToValidate.getA().trim().length() > 0;
boolean unique = !existingLeaderboardNames.contains(valueToValidate.getA());
boolean discardThresholdsAscending = true;
boolean discardThresholdsAreNumeric = valueToValidate.getB().length == 0 || valueToValidate.getB()[0] == null ||
valueToValidate.getB()[0].matches("[0-9]*");
for (int i=1; i<valueToValidate.getB().length; i++) {
if (valueToValidate.getB()[i] != null && valueToValidate.getB()[i].trim().length() > 0) {
try {
discardThresholdsAscending = discardThresholdsAscending &&
valueToValidate.getB()[i-1] != null && valueToValidate.getB()[i-1].trim().length() > 0 &&
Integer.valueOf(valueToValidate.getB()[i-1].trim()) < Integer.valueOf(valueToValidate.getB()[i].trim());
} catch (NumberFormatException e) {
discardThresholdsAreNumeric = false;
}
}
}
if (!nonEmpty) {
errorMessage = stringConstants.pleaseEnterNonEmptyName();
} else if (!unique) {
errorMessage = stringConstants.leaderboardWithThisNameAlreadyExists();
} else if (!discardThresholdsAreNumeric) {
errorMessage = stringConstants.discardThresholdsMustBeNumeric();
} else if (!discardThresholdsAscending) {
errorMessage = stringConstants.discardThresholdsMustBeAscending();
} else {
errorMessage = null;
}
return errorMessage;
}
}
public LeaderboardCreationDialog(Collection<String> existingLeaderboardNames, StringConstants stringConstants,
ErrorReporter errorReporter, AsyncCallback<Pair<String, String[]>> callback) {
super(stringConstants.leaderboardName(), stringConstants.leaderboardName(), stringConstants.ok(),
stringConstants.cancel(), new LeaderboardParameterValidator(existingLeaderboardNames, stringConstants), callback);
this.errorReporter = errorReporter;
this.stringConstants = stringConstants;
entryField = createTextBox(/* initial value */null);
discardThresholdBoxes = new TextBox[MAX_NUMBER_OF_DISCARDED_RESULTS];
for (int i=0; i<discardThresholdBoxes.length; i++) {
discardThresholdBoxes[i] = createTextBox(/* initialValue */ null);
discardThresholdBoxes[i].setVisibleLength(2);
}
}
@Override
protected Pair<String, String[]> getResult() {
List<String> discardThresholds = new ArrayList<String>();
for (int i=0; i<discardThresholdBoxes.length; i++) {
if (discardThresholdBoxes[i].getValue() != null && discardThresholdBoxes[i].getValue().trim().length() > 0) {
try {
Integer.valueOf(discardThresholdBoxes[i].getValue().trim()); // ensure there is no exception
discardThresholds.add(discardThresholdBoxes[i].getValue().trim());
} catch (NumberFormatException e) {
errorReporter.reportError("Internal error; NumberFormatException for "+discardThresholdBoxes[i].getValue()+
" which should have been caught by validation before");
}
}
}
String[] discardThresholdBoxesContents = discardThresholds.toArray(new String[discardThresholds.size()]);
return new Pair<String, String[]>(entryField.getValue(), discardThresholdBoxesContents);
}
@Override
protected Widget getAdditionalWidget() {
VerticalPanel panel = new VerticalPanel();
Widget additionalWidget = super.getAdditionalWidget();
if (additionalWidget != null) {
panel.add(additionalWidget);
}
panel.add(entryField);
panel.add(new Label(stringConstants.discardRacesFromHowManyStartedRacesOn()));
HorizontalPanel hp = new HorizontalPanel();
for (int i=0; i<discardThresholdBoxes.length; i++) {
hp.add(new Label(""+(i+1)+"."));
hp.add(discardThresholdBoxes[i]);
}
panel.add(hp);
return panel;
}
@Override
public void show() {
super.show();
entryField.setFocus(true);
}
}
@@ -1,6 +1,7 @@
package com.sap.sailing.gwt.ui.client;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -23,10 +24,12 @@ public abstract class LeaderboardDialog extends DataEntryDialog<LeaderboardDAO>
protected static class LeaderboardParameterValidator implements Validator<LeaderboardDAO> {
protected final StringConstants stringConstants;
protected final Collection<LeaderboardDAO> existingLeaderboards;
public LeaderboardParameterValidator(StringConstants stringConstants){
public LeaderboardParameterValidator(StringConstants stringConstants, Collection<LeaderboardDAO> existingLeaderboards){
super();
this.stringConstants = stringConstants;
this.existingLeaderboards = existingLeaderboards;
}
@Override
@@ -42,8 +45,18 @@ public abstract class LeaderboardDialog extends DataEntryDialog<LeaderboardDAO>
&& leaderboardToValidate.discardThresholds[i - 1] < leaderboardToValidate.discardThresholds[i];
}
}
boolean unique = true;
for (LeaderboardDAO dao : existingLeaderboards) {
if(dao.name.equals(leaderboardToValidate.name)){
unique = false;
}
}
if (!nonEmpty) {
errorMessage = stringConstants.pleaseEnterNonEmptyName();
} else if(!unique){
errorMessage = stringConstants.leaderboardWithThisNameAlreadyExists();
} else if (!discardThresholdsAscending) {
errorMessage = stringConstants.discardThresholdsMustBeAscending();
} else {
@@ -53,7 +66,7 @@ public abstract class LeaderboardDialog extends DataEntryDialog<LeaderboardDAO>
}
}
public LeaderboardDialog(LeaderboardDAO leaderboardDAO, StringConstants stringConstants,
public LeaderboardDialog(LeaderboardDAO leaderboardDAO, StringConstants stringConstants,
ErrorReporter errorReporter, LeaderboardParameterValidator validator, AsyncCallback<LeaderboardDAO> callback) {
super(stringConstants.leaderboardName(), stringConstants.leaderboardName(), stringConstants.ok(),
stringConstants.cancel(), validator, callback);
@@ -1,15 +1,17 @@
package com.sap.sailing.gwt.ui.client;
import java.util.Collection;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.IntegerBox;
import com.sap.sailing.gwt.ui.shared.LeaderboardDAO;
public class LeaderboardEditDialog extends LeaderboardDialog {
public LeaderboardEditDialog(LeaderboardDAO leaderboard, StringConstants stringConstants,
public LeaderboardEditDialog(Collection<LeaderboardDAO> otherExistingLeaderboards, LeaderboardDAO leaderboard, StringConstants stringConstants,
ErrorReporter errorReporter, AsyncCallback<LeaderboardDAO> callback) {
super(leaderboard, stringConstants, errorReporter, new LeaderboardDialog.LeaderboardParameterValidator(
stringConstants), callback);
stringConstants, otherExistingLeaderboards), callback);
entryField = createTextBox(leaderboard.name);
@@ -782,7 +782,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
refreshPanel.add(playPause);
Anchor chartsAnchor = new Anchor(new SafeHtmlBuilder().appendHtmlConstant(
"<img class=\"linkNoBorder\" src=\"/images/chart_small.png\"/>").toSafeHtml());
chartsAnchor.setTitle("Show charts");
chartsAnchor.setTitle(stringConstants.showCharts());
chartsAnchor.addClickHandler(new ClickHandler() {
@Override
@@ -1110,19 +1110,18 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
/**
* 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);
}
private void removeRaceColumnsNotSelected(List<String> selectedRaceColumns) {
List<Column<LeaderboardRowDAO, ?>> columnsToRemove = new ArrayList<Column<LeaderboardRowDAO, ?>>();
for (int i = 0; i < getLeaderboardTable().getColumnCount(); i++) {
Column<LeaderboardRowDAO, ?> c = getLeaderboardTable().getColumn(i);
if (c instanceof RaceColumn
&& (leaderboard == null || !selectedRaceColumns.contains(((RaceColumn<?>) c).getRaceName()))) {
columnsToRemove.add(c);
}
}
for (Column<LeaderboardRowDAO, ?> c : columnsToRemove) {
removeColumn(c);
}
}
/**
@@ -1139,7 +1138,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
}
selectedRaceColumns = correctedOrderSelectedRaces;
removeRaceColumnNotUsed();
removeRaceColumnsNotSelected(selectedRaceColumns);
for (int selectedRaceCount = 0; selectedRaceCount < selectedRaceColumns.size(); selectedRaceCount++) {
String selectedRaceName = selectedRaceColumns.get(selectedRaceCount);
@@ -10,17 +10,21 @@ import com.google.gwt.text.shared.SafeHtmlRenderer;
public class LeaderboardRaceConfigImagesBarCell extends ImagesBarCell {
private StringConstants stringConstants;
interface ImagesBarTemplates extends SafeHtmlTemplates {
@SafeHtmlTemplates.Template("<div name=\"{0}\" style=\"{1}\">{2}</div>")
SafeHtml cell(String name, SafeStyles styles, SafeHtml value);
@SafeHtmlTemplates.Template("<div name=\"{0}\" style=\"{1}\" title=\"{2}\">{3}</div>")
SafeHtml cell(String name, SafeStyles styles, String title, SafeHtml value);
}
public LeaderboardRaceConfigImagesBarCell() {
public LeaderboardRaceConfigImagesBarCell(StringConstants stringConstants) {
super();
this.stringConstants = stringConstants;
}
public LeaderboardRaceConfigImagesBarCell(SafeHtmlRenderer<String> renderer) {
public LeaderboardRaceConfigImagesBarCell(SafeHtmlRenderer<String> renderer, StringConstants stringConstants) {
super();
this.stringConstants = stringConstants;
}
private static ImagesBarTemplates templates = GWT.create(ImagesBarTemplates.class);
@@ -36,23 +40,23 @@ public class LeaderboardRaceConfigImagesBarCell extends ImagesBarCell {
@Override
protected void render(com.google.gwt.cell.client.Cell.Context context, SafeHtml data, SafeHtmlBuilder sb) {
/*
* Always do a null check on the value. Cell widgets can pass null to
* cells if the underlying data contains a null, or if the data arrives
* out of order.
* Always do a null check on the value. Cell widgets can pass null to cells if the underlying data contains a
* null, or if the data arrives out of order.
*/
if (data == null) {
return;
}
SafeStyles imgStyle = SafeStylesUtils.fromTrustedString("float:left;cursor:hand;cursor:pointer;padding-right:5px;");
SafeStyles imgStyle = SafeStylesUtils
.fromTrustedString("float:left;cursor:hand;cursor:pointer;padding-right:5px;");
SafeHtml rendered = templates.cell("ACTION_EDIT", imgStyle, ICON_EDIT);
SafeHtml rendered = templates.cell("ACTION_EDIT", imgStyle, stringConstants.actionRaceEdit(), ICON_EDIT);
sb.append(rendered);
rendered = templates.cell("ACTION_UNLINK", imgStyle, ICON_UNLINK);
rendered = templates.cell("ACTION_UNLINK", imgStyle, stringConstants.actionRaceUnlink(), ICON_UNLINK);
sb.append(rendered);
rendered = templates.cell("ACTION_REMOVE", imgStyle, ICON_REMOVE);
rendered = templates.cell("ACTION_REMOVE", imgStyle, stringConstants.actionRaceRemove(), ICON_REMOVE);
sb.append(rendered);
}
}
@@ -1,69 +0,0 @@
package com.sap.sailing.gwt.ui.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.TextBox;
import com.sap.sailing.gwt.ui.shared.Pair;
import com.sap.sailing.gwt.ui.shared.RaceDAO;
public class RaceDialog extends DataEntryDialog<Pair<RaceDAO, Boolean>>{
private final TextBox raceNameBox;
private final CheckBox isMedalRace;
private Pair<RaceDAO, Boolean> raceDaoAndIsMedalRace;
private static class RaceDialogValidator implements Validator<Pair<RaceDAO, Boolean>>{
private StringConstants stringConstants;
public RaceDialogValidator(StringConstants stringConstants) {
this.stringConstants = stringConstants;
}
@Override
public String getErrorMessage(Pair<RaceDAO, Boolean> valueToValidate) {
String errorMessage;
RaceDAO race = valueToValidate.getA();
Boolean isMedalRace = valueToValidate.getB();
boolean isNameNotEmpty = race!=null & race.name!=null & race.name!="";
boolean medalRaceNotNull = isMedalRace!=null;
if(!isNameNotEmpty){
errorMessage = "error"; // stringConstants.raceNameEmpty();
}else if(!medalRaceNotNull){
errorMessage = "error"; //stringConstants.medalRaceIsNull();
}else{
return errorMessage = null;
}
return errorMessage;
}
}
public RaceDialog(Pair<RaceDAO, Boolean> raceDaoAndIsMedalRace, StringConstants stringConstants,
AsyncCallback<Pair<RaceDAO, Boolean>> callback) {
super(stringConstants.name(), stringConstants.name(), stringConstants.ok(), stringConstants.cancel(), new RaceDialogValidator(stringConstants), callback);
this.raceDaoAndIsMedalRace = raceDaoAndIsMedalRace;
raceNameBox = createTextBox(raceDaoAndIsMedalRace.getA().name);
isMedalRace = createCheckbox(stringConstants.medalRace());
isMedalRace.setValue(raceDaoAndIsMedalRace.getB().booleanValue());
}
@Override
protected Pair<RaceDAO, Boolean> getResult() {
raceDaoAndIsMedalRace.getA().name = raceNameBox.getValue();
raceDaoAndIsMedalRace.setB(isMedalRace.getValue());
return raceDaoAndIsMedalRace;
}
@Override
public void show() {
super.show();
raceNameBox.setFocus(true);
}
}
@@ -0,0 +1,94 @@
package com.sap.sailing.gwt.ui.client;
import java.util.Collection;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.shared.RaceInLeaderboardDAO;
public class RaceInLeaderboardDialog extends DataEntryDialog<RaceInLeaderboardDAO> {
private final TextBox raceNameBox;
private final CheckBox isMedalRace;
private RaceInLeaderboardDAO raceInLeaderboard;
private static class RaceDialogValidator implements Validator<RaceInLeaderboardDAO> {
private StringConstants stringConstants;
private Collection<RaceInLeaderboardDAO> existingRaces;
public RaceDialogValidator(StringConstants stringConstants, Collection<RaceInLeaderboardDAO> existingRaces) {
this.stringConstants = stringConstants;
this.existingRaces = existingRaces;
}
@Override
public String getErrorMessage(RaceInLeaderboardDAO valueToValidate) {
String errorMessage;
String racename = valueToValidate.getRaceColumnName();
Boolean isMedalRace = valueToValidate.isMedalRace();
boolean isNameNotEmpty = racename != null & racename != "";
boolean medalRaceNotNull = isMedalRace != null;
boolean unique = true;
for (RaceInLeaderboardDAO dao : existingRaces) {
if (dao.getRaceColumnName().equals(valueToValidate.getRaceColumnName())) {
unique = false;
}
}
if (!isNameNotEmpty) {
errorMessage = stringConstants.raceNameEmpty();
} else if (!medalRaceNotNull) {
errorMessage = stringConstants.medalRaceIsNull();
} else if (!unique) {
errorMessage = stringConstants.raceWithThisNameAlreadyExists();
} else {
return errorMessage = null;
}
return errorMessage;
}
}
public RaceInLeaderboardDialog(Collection<RaceInLeaderboardDAO> existingRaces,
RaceInLeaderboardDAO raceInLeaderboard, StringConstants stringConstants,
AsyncCallback<RaceInLeaderboardDAO> callback) {
super(stringConstants.name(), stringConstants.name(), stringConstants.ok(), stringConstants.cancel(),
new RaceDialogValidator(stringConstants, existingRaces), callback);
this.raceInLeaderboard = raceInLeaderboard;
raceNameBox = createTextBox(raceInLeaderboard.getRaceColumnName());
isMedalRace = createCheckbox(stringConstants.medalRace());
isMedalRace.setValue(raceInLeaderboard.isMedalRace());
}
@Override
protected RaceInLeaderboardDAO getResult() {
raceInLeaderboard.setRaceColumnName(raceNameBox.getValue());
raceInLeaderboard.setMedalRace(isMedalRace.getValue());
return raceInLeaderboard;
}
@Override
protected Widget getAdditionalWidget() {
VerticalPanel panel = new VerticalPanel();
Widget additionalWidget = super.getAdditionalWidget();
if (additionalWidget != null) {
panel.add(additionalWidget);
}
panel.add(raceNameBox);
panel.add(isMedalRace);
return panel;
}
@Override
public void show() {
super.show();
raceNameBox.setFocus(true);
}
}
@@ -22,6 +22,7 @@ import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.Maps;
import com.google.gwt.maps.client.control.LargeMapControl3D;
import com.google.gwt.maps.client.control.MenuMapTypeControl;
import com.google.gwt.maps.client.control.ScaleControl;
import com.google.gwt.maps.client.event.MapDragEndHandler;
import com.google.gwt.maps.client.event.MapMouseMoveHandler;
import com.google.gwt.maps.client.event.MapZoomEndHandler;
@@ -94,6 +95,7 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
private final Set<CompetitorDAO> competitorsSelectedInMap;
private final Timer timer;
private List<Pair<CheckBox, String>> checkboxAndType;
private CheckBox checkBoxDouglasPeuckerPoints;
private long TAILLENGTHINMILLISECONDS = 30000l;
@@ -134,24 +136,44 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
private final Map<MarkDAO, Marker> buoyMarkers;
/**
* markers displayed in response to {@link SailingServiceAsync#getDouglasPoints(String, String, Map, Map, double, AsyncCallback)}
* markers displayed in response to
* {@link SailingServiceAsync#getDouglasPoints(String, String, Map, Map, double, AsyncCallback)}
*/
private Set<Marker> douglasMarkers;
/**
* markers displayed in response to {@link SailingServiceAsync#getDouglasPoints(String, String, Map, Map, double, AsyncCallback)}
* markers displayed in response to
* {@link SailingServiceAsync#getDouglasPoints(String, String, Map, Map, double, AsyncCallback)}
*/
private Set<Marker> maneuverMarkers;
// key for domain web4sap.com
private final String mapsAPIKey = "ABQIAAAAmvjPh3ZpHbnwuX3a66lDqRRLCigyC_gRDASMpyomD2do5awpNhRCyD_q-27hwxKe_T6ivSZ_0NgbUg";
private final CheckBox showOnlySelected;
private final IntegerBox tailLengthBox;
protected Map<CompetitorDAO, List<ManeuverDAO>> lastManeuverResult;
protected Map<CompetitorDAO, List<GPSFixDAO>> lastDouglasPeuckerResult;
/**
* RPC calls may receive responses out of order if there are multiple calls in-flight at the same time. If the time
* slider is moved quickly it generates many requests for boat positions quickly after each other. Sometimes,
* responses for requests send later may return before the responses to all earlier requests have been received and
* processed. This counter is used to number the requests. When processing of a response for a later request has
* already begun, responses to earlier requests will be ignored.
*/
private int boatPositionRequestIDCounter;
/**
* Corresponds to {@link #boatPositionRequestIDCounter}. As soon as the processing of a response for a request ID
* begins, this attribute is set to the ID. A response won't be processed if a later response is already being
* processed.
*/
private int startedProcessingRequestID;
public RaceMapPanel(SailingServiceAsync sailingService, ErrorReporter errorReporter,
final EventRefresher eventRefresher, StringConstants stringConstants) {
this.sailingService = sailingService;
@@ -163,21 +185,30 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
lastShownFix = new HashMap<CompetitorDAO, Integer>();
buoyMarkers = new HashMap<MarkDAO, Marker>();
boatMarkers = new HashMap<CompetitorDAO, Marker>();
checkboxAndType = new ArrayList<Pair<CheckBox,String>>();
VerticalPanel verticalCheckBoxPanel = new VerticalPanel();
checkboxAndType = new ArrayList<Pair<CheckBox, String>>();
final VerticalPanel verticalCheckBoxPanel = new VerticalPanel();
verticalCheckBoxPanel.add(new Label(stringConstants.maneuverTypes()));
checkboxAndType.add(new Pair<CheckBox, String>(new CheckBox("HEAD_UP"), "HEAD_UP"));
checkboxAndType.add(new Pair<CheckBox, String>(new CheckBox("BEAR_AWAY"), "BEAR_AWAY"));
checkboxAndType.add(new Pair<CheckBox, String>(new CheckBox("TACK"), "TACK"));
checkboxAndType.add(new Pair<CheckBox, String>(new CheckBox("JIBE"), "JIBE"));
checkboxAndType.add(new Pair<CheckBox, String>(new CheckBox("PENALTY_CIRCLE"), "PENALTY_CIRCLE"));
checkboxAndType.add(new Pair<CheckBox, String>(new CheckBox("MARK_PASSING"), "MARK_PASSING"));
checkboxAndType.add(new Pair<CheckBox, String>(new CheckBox("OTHER"), "OTHER"));
checkboxAndType.add(new Pair<CheckBox, String>(new CheckBox(stringConstants.headUp()), "HEAD_UP"));
checkboxAndType.add(new Pair<CheckBox, String>(new CheckBox(stringConstants.bearAway()), "BEAR_AWAY"));
CheckBox checkBoxTack = new CheckBox(stringConstants.tack());
checkBoxTack.setValue(true);
checkboxAndType.add(new Pair<CheckBox, String>(checkBoxTack, "TACK"));
CheckBox checkBoxJibe = new CheckBox(stringConstants.jibe());
checkBoxJibe.setValue(true);
checkboxAndType.add(new Pair<CheckBox, String>(checkBoxJibe, "JIBE"));
CheckBox checkBoxPenalty= new CheckBox(stringConstants.penaltyCircle());
checkBoxPenalty.setValue(true);
checkboxAndType
.add(new Pair<CheckBox, String>(checkBoxPenalty, "PENALTY_CIRCLE"));
CheckBox checkBoxMarkPassing = new CheckBox(stringConstants.markPassing());
checkBoxMarkPassing.setValue(true);
checkboxAndType.add(new Pair<CheckBox, String>(checkBoxMarkPassing, "MARK_PASSING"));
checkboxAndType.add(new Pair<CheckBox, String>(new CheckBox(stringConstants.otherManeuver()), "OTHER"));
for (Pair<CheckBox, String> pair : checkboxAndType) {
pair.getA().addValueChangeHandler(new ValueChangeHandler<Boolean>() {
@Override
public void onValueChange(ValueChangeEvent<Boolean> event) {
if (!timer.isPlaying() && lastManeuverResult!=null) {
if (!timer.isPlaying() && lastManeuverResult != null) {
removeAllManeuverMarkers();
showManeuvers(lastManeuverResult);
}
@@ -185,6 +216,20 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
});
verticalCheckBoxPanel.add(pair.getA());
}
checkBoxDouglasPeuckerPoints = new CheckBox(stringConstants.douglasPeuckerPoints());
checkBoxDouglasPeuckerPoints.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
@Override
public void onValueChange(ValueChangeEvent<Boolean> event) {
if (!timer.isPlaying() && lastDouglasPeuckerResult != null && event.getValue()) {
removeAllMarkDouglasPeuckerpoints();
showMarkDouglasPeuckerPoints(lastDouglasPeuckerResult);
} else if(!event.getValue()){
removeAllMarkDouglasPeuckerpoints();
}
}
});
verticalCheckBoxPanel.add(checkBoxDouglasPeuckerPoints);
fixes = new HashMap<CompetitorDAO, List<GPSFixDAO>>();
this.grid = new Grid(3, 2);
setWidget(grid);
@@ -248,15 +293,19 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
});
ranksAndCheckboxAndTailLength.add(quickRanksBox);
horizontalRanksVerticalAndCheckboxesManeuversPanel.add(ranksAndCheckboxAndTailLength);
horizontalRanksVerticalAndCheckboxesManeuversPanel.add(verticalCheckBoxPanel);
VerticalPanel verticalPanelRadioAndCheckboxes = new VerticalPanel();
verticalPanelRadioAndCheckboxes.add(verticalCheckBoxPanel);
horizontalRanksVerticalAndCheckboxesManeuversPanel.add(verticalPanelRadioAndCheckboxes);
grid.setWidget(2, 0, horizontalRanksVerticalAndCheckboxesManeuversPanel);
timePanel = new TimePanel(stringConstants, timer);
timer.addTimeListener(this);
timer.addTimeListener(windHistory);
grid.setWidget(1, 1, timePanel);
}
private boolean getCheckboxValueManeuver(String maneuverType){
private boolean getCheckboxValueManeuver(String maneuverType) {
for (Pair<CheckBox, String> pair : checkboxAndType) {
if (pair.getB().equals(maneuverType)) {
return pair.getA().getValue();
@@ -264,7 +313,7 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
}
return false;
}
private void updateBoatSelection() {
for (int i = 0; i < quickRanksBox.getItemCount(); i++) {
setSelectedInMap(quickRanksList.get(i), quickRanksBox.isItemSelected(i));
@@ -310,6 +359,7 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
map = new MapWidget();
map.addControl(new LargeMapControl3D());
map.addControl(new MenuMapTypeControl());
map.addControl(new ScaleControl());
// Add the map to the HTML host page
grid.setWidget(2, 1, map);
map.setSize("100%", "100%");
@@ -333,37 +383,50 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
lastMousePosition = event.getLatLng();
}
});
boatIcon = Icon.newInstance("/images/boat16.png");
boatIcon = Icon.newInstance("/images/blackdot.png");
boatIcon.setIconAnchor(Point.newInstance(8, 8));
boatIconHighlighted = Icon.newInstance("/images/boat-selected16.png");
boatIconHighlighted = Icon.newInstance("/images/reddot.png");
boatIconHighlighted.setIconAnchor(Point.newInstance(8, 8));
buoyIcon = Icon.newInstance("/images/safe-water-small.png");
buoyIcon.setIconAnchor(Point.newInstance(10, 19));
tackToStarboardIcon = Icon.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=T|00FF00|000000");
buoyIcon = Icon.newInstance("/images/reddiamond.png");
buoyIcon.setIconAnchor(Point.newInstance(7, 7));
tackToStarboardIcon = Icon
.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=T|00FF00|000000");
tackToStarboardIcon.setIconAnchor(Point.newInstance(10, 33));
tackToPortIcon = Icon.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=T|FF0000|000000");
tackToPortIcon = Icon
.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=T|FF0000|000000");
tackToPortIcon.setIconAnchor(Point.newInstance(10, 33));
jibeToStarboardIcon = Icon.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=J|00FF00|000000");
jibeToStarboardIcon = Icon
.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=J|00FF00|000000");
jibeToStarboardIcon.setIconAnchor(Point.newInstance(10, 33));
jibeToPortIcon = Icon.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=J|FF0000|000000");
jibeToPortIcon = Icon
.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=J|FF0000|000000");
jibeToPortIcon.setIconAnchor(Point.newInstance(10, 33));
headUpOnStarboardIcon = Icon.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=H|00FF00|000000");
headUpOnStarboardIcon = Icon
.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=H|00FF00|000000");
headUpOnStarboardIcon.setIconAnchor(Point.newInstance(10, 33));
headUpOnPortIcon = Icon.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=H|FF0000|000000");
headUpOnPortIcon = Icon
.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=H|FF0000|000000");
headUpOnPortIcon.setIconAnchor(Point.newInstance(10, 33));
bearAwayOnStarboardIcon = Icon.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=B|00FF00|000000");
bearAwayOnStarboardIcon = Icon
.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=B|00FF00|000000");
bearAwayOnStarboardIcon.setIconAnchor(Point.newInstance(10, 33));
bearAwayOnPortIcon = Icon.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=B|FF0000|000000");
bearAwayOnPortIcon = Icon
.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=B|FF0000|000000");
bearAwayOnPortIcon.setIconAnchor(Point.newInstance(10, 33));
markPassingToStarboardIcon = Icon.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=M|00FF00|000000");
markPassingToStarboardIcon = Icon
.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=M|00FF00|000000");
markPassingToStarboardIcon.setIconAnchor(Point.newInstance(10, 33));
markPassingToPortIcon = Icon.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=M|FF0000|000000");
markPassingToPortIcon = Icon
.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=M|FF0000|000000");
markPassingToPortIcon.setIconAnchor(Point.newInstance(10, 33));
unknownManeuverIcon = Icon.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=?|FFFFFF|000000");
unknownManeuverIcon = Icon
.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=?|FFFFFF|000000");
unknownManeuverIcon.setIconAnchor(Point.newInstance(10, 33));
penaltyCircleToStarboardIcon = Icon.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=P|00FF00|000000");
penaltyCircleToStarboardIcon = Icon
.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=P|00FF00|000000");
penaltyCircleToStarboardIcon.setIconAnchor(Point.newInstance(10, 33));
penaltyCircleToPortIcon = Icon.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=P|FF0000|000000");
penaltyCircleToPortIcon = Icon
.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=P|FF0000|000000");
penaltyCircleToPortIcon.setIconAnchor(Point.newInstance(10, 33));
}
});
@@ -407,8 +470,10 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
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);
sailingService.getBoatPositions(new EventNameAndRaceName(event.name, race.name), fromAndToAndOverlap.getA(),
fromAndToAndOverlap.getB(), true, new AsyncCallback<Map<CompetitorDAO, List<GPSFixDAO>>>() {
final int requestID = boatPositionRequestIDCounter++;
sailingService.getBoatPositions(new EventNameAndRaceName(event.name, race.name),
fromAndToAndOverlap.getA(), fromAndToAndOverlap.getB(), true,
new AsyncCallback<Map<CompetitorDAO, List<GPSFixDAO>>>() {
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError("Error obtaining boat positions: " + caught.getMessage());
@@ -416,39 +481,46 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
@Override
public void onSuccess(Map<CompetitorDAO, List<GPSFixDAO>> result) {
Date from = new Date(date.getTime() - TAILLENGTHINMILLISECONDS);
updateFixes(result, fromAndToAndOverlap.getC());
showBoatsOnMap(from, date);
if (douglasMarkers != null) {
removeAllMarkDouglasPeuckerpoints();
}
if (maneuverMarkers != null) {
removeAllManeuverMarkers();
// process response only if not received out of order
if (startedProcessingRequestID < requestID) {
startedProcessingRequestID = requestID;
Date from = new Date(date.getTime() - TAILLENGTHINMILLISECONDS);
updateFixes(result, fromAndToAndOverlap.getC());
showBoatsOnMap(from, date);
if (douglasMarkers != null) {
removeAllMarkDouglasPeuckerpoints();
}
if (maneuverMarkers != null) {
removeAllManeuverMarkers();
}
}
}
});
sailingService.getMarkPositions(new EventNameAndRaceName(event.name, race.name), date, new AsyncCallback<List<MarkDAO>>() {
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError("Error trying to obtain mark positions: " + caught.getMessage());
}
sailingService.getMarkPositions(new EventNameAndRaceName(event.name, race.name), date,
new AsyncCallback<List<MarkDAO>>() {
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError("Error trying to obtain mark positions: "
+ caught.getMessage());
}
@Override
public void onSuccess(List<MarkDAO> result) {
showMarksOnMap(result);
}
});
sailingService.getQuickRanks(new EventNameAndRaceName(event.name, race.name), date, new AsyncCallback<List<QuickRankDAO>>() {
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError("Error obtaining quick rankings: " + caught.getMessage());
}
@Override
public void onSuccess(List<MarkDAO> result) {
showMarksOnMap(result);
}
});
sailingService.getQuickRanks(new EventNameAndRaceName(event.name, race.name), date,
new AsyncCallback<List<QuickRankDAO>>() {
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError("Error obtaining quick rankings: " + caught.getMessage());
}
@Override
public void onSuccess(List<QuickRankDAO> result) {
showQuickRanks(result);
}
});
@Override
public void onSuccess(List<QuickRankDAO> result) {
showQuickRanks(result);
}
});
}
}
}
@@ -848,8 +920,8 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
from.put(competitorDAO, fixes.get(competitorDAO).get(firstShownFix.get(competitorDAO)).timepoint);
Map<CompetitorDAO, Date> to = new HashMap<CompetitorDAO, Date>();
to.put(competitorDAO, fixes.get(competitorDAO).get(lastShownFix.get(competitorDAO)).timepoint);
/* currently not showing Douglas-Peucker points; TODO use checkboxes to select what to show (Bug #6)
sailingService.getDouglasPoints(event.name, race.name, from, to, 3, // epsilon/meters
/* currently not showing Douglas-Peucker points; TODO use checkboxes to select what to show (Bug #6) */
sailingService.getDouglasPoints(new EventNameAndRaceName(event.name, race.name), from, to, 3,
new AsyncCallback<Map<CompetitorDAO, List<GPSFixDAO>>>() {
@Override
public void onFailure(Throwable caught) {
@@ -858,15 +930,17 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
@Override
public void onSuccess(Map<CompetitorDAO, List<GPSFixDAO>> result) {
RaceMapPanel.this.lastDouglasPeuckerResult = result;
if (douglasMarkers != null) {
removeAllMarkDouglasPeuckerpoints();
}
if (!timer.isPlaying()) {
showMarkDouglasPeuckerPoints(result);
if(checkBoxDouglasPeuckerPoints.getValue()){
showMarkDouglasPeuckerPoints(result);
}
}
}
});
*/
sailingService.getManeuvers(new EventNameAndRaceName(event.name, race.name), from, to,
new AsyncCallback<Map<CompetitorDAO, List<ManeuverDAO>>>() {
@Override
@@ -885,6 +959,7 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
}
}
});
}
}
return result;
@@ -892,7 +967,7 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
private String getColorString(CompetitorDAO competitorDAO) {
// TODO green no more than 70, red no less than 120
return "#" + Integer.toHexString(competitorDAO.hashCode()).substring(0, 4).toUpperCase() + "00";
return "#" + (Integer.toHexString(competitorDAO.hashCode()) + "000000").substring(0, 4).toUpperCase() + "00";
}
/**
@@ -979,8 +1054,10 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
}
private void removeAllMarkDouglasPeuckerpoints() {
for (Marker marker : douglasMarkers) {
map.removeOverlay(marker);
if (douglasMarkers != null) {
for (Marker marker : douglasMarkers) {
map.removeOverlay(marker);
}
}
douglasMarkers = null;
}
@@ -994,9 +1071,8 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
}
}
/* TODO see Bug #6, use checkboxes to select what to visualize
private void showMarkDouglasPeuckerPoints(
Map<CompetitorDAO, List<GPSFixDAO>> gpsFixPointMapForCompetitors) {
/* TODO see Bug #6, use checkboxes to select what to visualize */
private void showMarkDouglasPeuckerPoints(Map<CompetitorDAO, List<GPSFixDAO>> gpsFixPointMapForCompetitors) {
douglasMarkers = new HashSet<Marker>();
if (map != null && gpsFixPointMapForCompetitors != null) {
Set<CompetitorDAO> keySet = gpsFixPointMapForCompetitors.keySet();
@@ -1015,7 +1091,6 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
}
}
}
*/
private void showManeuvers(Map<CompetitorDAO, List<ManeuverDAO>> maneuvers) {
maneuverMarkers = new HashSet<Marker>();
@@ -1069,13 +1144,13 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
options.setIcon(markPassingToStarboardIcon);
}
} else {
if (getCheckboxValueManeuver("OTHER")) {
if (maneuver.type.equals("UNKNOWN") && getCheckboxValueManeuver("OTHER")) {
options.setIcon(unknownManeuverIcon);
} else {
showThisManeuver = false;
}
}
if (showThisManeuver){
if (showThisManeuver) {
Marker marker = new Marker(latLng, options);
maneuverMarkers.add(marker);
map.addOverlay(marker);
@@ -1083,7 +1158,5 @@ public class RaceMapPanel extends FormPanel implements EventDisplayer, TimeListe
}
}
}
}
}
@@ -72,6 +72,8 @@ public interface SailingService extends RemoteService {
Collection<String> namesOfRacesForWhichToLoadLegDetails) throws Exception;
List<LeaderboardDAO> getLeaderboards();
LeaderboardDAO getLeaderboardByName(String leaderboardName);
void updateLeaderboard(String leaderboardName, String newLeaderboardName, int[] newDiscardingThreasholds);
@@ -84,7 +86,7 @@ public interface SailingService extends RemoteService {
void renameLeaderboardColumn(String leaderboardName, String oldColumnName, String newColumnName);
void removeLeaderboardColumn(String leaderboardName, String columnName);
void addColumnToLeaderboard(String columnName, String leaderboardName, boolean medalRace);
void moveLeaderboardColumnUp(String leaderboardName, String columnName);
@@ -108,14 +108,16 @@ public interface SailingServiceAsync {
void getLeaderboardNames(AsyncCallback<List<String>> callback);
void getLeaderboards(AsyncCallback<List<LeaderboardDAO>> callback);
void getLeaderboardByName(String leaderboardName, AsyncCallback<LeaderboardDAO> callback);
void updateLeaderboard(String leaderboardName, String newLeaderboardName, int[] newDiscardingThreasholds,
AsyncCallback<Void> callback);
void createLeaderboard(String leaderboardName, int[] discardThresholds, AsyncCallback<Void> asyncCallback);
void removeLeaderboard(String leaderboardName, AsyncCallback<Void> asyncCallback);
void renameLeaderboard(String leaderboardName, String newLeaderboardName, AsyncCallback<Void> asyncCallback);
void addColumnToLeaderboard(String columnName, String leaderboardName, boolean medalRace,
@@ -186,5 +188,4 @@ public interface SailingServiceAsync {
AsyncCallback<Map<CompetitorDAO, List<ManeuverDAO>>> callback);
void getCompetitorAndTimePoints(RaceIdentifier race, int steps, AsyncCallback<CompetitorAndTimePointsDAO> callback);
}
@@ -126,8 +126,10 @@ public interface StringConstants extends Constants {
String tacks();
String jibes();
String penaltyCircles();
String configuration();
String medalRaceIsNull();
String maneuverTypes();
String raceNameEmpty();
String configuration();
String chooseChart();
String distanceTraveled();
String velocityMadeGoodLong();
@@ -148,4 +150,23 @@ public interface StringConstants extends Constants {
String no3LetterCodes();
String add();
String delete();
String showCharts();
String raceWithThisNameAlreadyExists();
String headUp();
String bearAway();
String tack();
String jibe();
String penaltyCircle();
String markPassing();
String otherManeuver();
String douglasPeuckerPoints();
String filterRacesByName();
String actionEdit();
String actionEditScores();
String actionOpenBrowser();
String actionRemove();
String actionRaceEdit();
String actionRaceUnlink();
String actionRaceRemove();
String filterLeaderboardsByName();
}
@@ -121,8 +121,10 @@ numberOfManeuvers=Maneuvers
tacks=Tacks
jibes=Jibes
penaltyCircles=Penalty Circles
medalRaceIsNull=Medalrace value not allowed
configuration=Configuration
maneuverTypes=Maneuver types
raceNameEmpty=The name of the race is empty
chooseChart=Choose chart
distanceTraveled=Distance Traveled
velocityMadeGoodLong=Velocity Made Good
@@ -142,4 +144,23 @@ sailNumber=Sail number
country=Country
no3LetterCodes=Unable to find the IOC 3-letter-codes.
add=Add
delete=Delete
delete=Delete
showCharts=Show charts
raceWithThisNameAlreadyExists=A race with that name already exists
headUp=Head up
bearAway=Bear away
tack=Tack
jibe=Jibe
penaltyCircle=Penalty circle
markPassing=Mark passing
otherManeuver=Unknown maneuver
douglasPeuckerPoints=Douglas peucker points
filterRacesByName=Filter races by name
actionEdit=Edit
actionEditScores=Edit scores
actionOpenBrowser=Open in Browser
actionRemove=Remove leaderboard
actionRaceEdit=Edit or rename race
actionRaceUnlink=Unlink race
actionRaceRemove=Remove race
filterLeaderboardsByName=Filter leaderboards by name
@@ -121,9 +121,12 @@ numberOfManeuvers=Manöver
tacks=Wenden
jibes=Halsen
penaltyCircles=Strafkringel
configuration=Konfiguration
medalRaceIsNull=Medialienwert nicht erlaubt
maneuverTypes=Manövertypen
raceNameEmpty=Der Name des Rennens ist leer
configuration=Konfiguration
chooseChart=Diagramm wählen
raceNameEmpty=Rennname leer
distanceTraveled=Zurückgelegte Strecke
velocityMadeGoodLong=Velocity Made Good
speedOverGroundLong=Speed Over Ground
@@ -134,7 +137,7 @@ distance=Strecke
in=in
secondsUnit=[s]
metersUnit=[m]
failedToLoadRaceData=Failed to laod race data.
failedToLoadRaceData=Renndaten konnten nicht geladen werden.
close=Close
compareCompetitors=Kompetitoren vergleichen
description=Beschreibung
@@ -142,4 +145,23 @@ sailNumber=Segelnummer
country=Land
no3LetterCodes=IOC 3-Buchstaben-Codes können nicht gefunden werden.
add=Hinzufügen
delete=Löschen
delete=Löschen
showCharts=Grafische Ansicht
raceWithThisNameAlreadyExists=Ein Rennen mit diesem Namen existiert schon
headUp=anluven
bearAway=abfallen
tack=Wende
jibe=Halse
penaltyCircle=Strafkringel
markPassing=Tonnenpassierung
otherManeuver=Manövertyp unbekannt
douglasPeuckerPoints=Douglas-Peucker-Punkte
filterRacesByName=Rennen nach Name filtern
actionEdit=Ändern
actionEditScores=Punkte ändern
actionOpenBrowser=Im Browser öffnen
actionRemove=Leaderboard entfernen
actionRaceEdit=Rennen ändern oder umbenennen
actionRaceUnlink=Rennverknüpfung entfernen
actionRaceRemove=Rennen entfernen
filterLeaderboardsByName=Leaderboards nach Name filtern
@@ -8,6 +8,8 @@ import java.util.Set;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
import com.google.gwt.text.client.DateTimeFormatRenderer;
@@ -16,8 +18,10 @@ import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.MultiSelectionModel;
@@ -59,6 +63,10 @@ public class TrackedEventsComposite extends FormPanel implements EventDisplayer,
private Button btnRemove = null;
private Button btnRefresh = null;
private TextBox filterRacesTextbox;
private List<Triple<EventDAO, RegattaDAO, RaceDAO>> availableRaceList;
public TrackedEventsComposite(final SailingServiceAsync sailingService, final ErrorReporter errorReporter, final EventRefresher eventRefresher,
StringConstants stringConstants, boolean hasMultiSelection) {
this.sailingService = sailingService;
@@ -66,12 +74,42 @@ public class TrackedEventsComposite extends FormPanel implements EventDisplayer,
this.eventRefresher = eventRefresher;
this.multiSelection = hasMultiSelection;
this.raceSelectionChangeListeners = new HashSet<RaceSelectionChangeListener>();
this.availableRaceList = new ArrayList<Triple<EventDAO,RegattaDAO,RaceDAO>>();
selectionModel = multiSelection ? new MultiSelectionModel<Triple<EventDAO, RegattaDAO, RaceDAO>>() : new SingleSelectionModel<Triple<EventDAO, RegattaDAO, RaceDAO>>();
panel = new VerticalPanel();
setWidget(panel);
HorizontalPanel filterPanel = new HorizontalPanel();
panel.add(filterPanel);
Label lblFilterEvents = new Label(stringConstants.filterRacesByName() + ":");
filterPanel.setSpacing(5);
filterPanel.add(lblFilterEvents);
filterPanel.setCellVerticalAlignment(lblFilterEvents, HasVerticalAlignment.ALIGN_MIDDLE);
filterRacesTextbox = new TextBox();
filterRacesTextbox.addKeyUpHandler(new KeyUpHandler() {
@Override
public void onKeyUp(KeyUpEvent event) {
String text = filterRacesTextbox.getText();
raceList.getList().clear();
if(text == null || text.isEmpty()) {
raceList.getList().addAll(availableRaceList);
} else {
String textAsUppercase = text.toUpperCase();
for (Triple<EventDAO, RegattaDAO, RaceDAO> triple : availableRaceList) {
if(triple.getC().name != null) {
if(triple.getC().name.toUpperCase().contains(textAsUppercase))
raceList.getList().add(triple);
}
}
}
}
});
filterPanel.add(filterRacesTextbox);
noTrackedRacesLabel = new Label(stringConstants.noRacesYet());
noTrackedRacesLabel.setWordWrap(false);
panel.add(noTrackedRacesLabel);
@@ -246,13 +284,19 @@ public class TrackedEventsComposite extends FormPanel implements EventDisplayer,
}
raceList.getList().clear();
availableRaceList.clear();
// Handler columnSortHandler = getRaceTableColumnSortHandler(raceList.getList(), raceNameColumn, raceStartTrackingColumn);
// raceTable.addColumnSortHandler(columnSortHandler);
for (EventDAO event : events) {
for (RegattaDAO regatta : event.regattas) {
for (RaceDAO race : regatta.races) {
raceList.getList().add(new Triple<EventDAO, RegattaDAO, RaceDAO>(event, regatta, race));
Triple<EventDAO, RegattaDAO, RaceDAO> triple = new Triple<EventDAO, RegattaDAO, RaceDAO>(event, regatta, race);
if (race != null){
availableRaceList.add(triple);
}
raceList.getList().add(triple);
}
}
}
@@ -8,6 +8,7 @@ import java.net.URL;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -64,7 +65,7 @@ import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.Maneuver;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.NoWindException;
import com.sap.sailing.domain.tracking.RaceHandle;
import com.sap.sailing.domain.tracking.RacesHandle;
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.Wind;
@@ -403,7 +404,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
if (storedURI == null || storedURI.trim().length() == 0) {
storedURI = rr.storedURI;
}
final RaceHandle raceHandle = getService().addTracTracRace(new URL(rr.paramURL), new URI(liveURI), new URI(storedURI),
final RacesHandle raceHandle = getService().addTracTracRace(new URL(rr.paramURL), new URI(liveURI), new URI(storedURI),
MongoWindStoreFactory.INSTANCE.getMongoWindStore(mongoObjectFactory, domainObjectFactory), TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS);
if (trackWind) {
new Thread("Wind tracking starter for race "+rr.eventName+"/"+rr.name) {
@@ -466,19 +467,20 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
}
/**
* @param timeoutInMilliseconds eventually passed to {@link RaceHandle#getRace(long)}. If the race definition
* @param timeoutInMilliseconds eventually passed to {@link RacesHandle#getRaces(long)}. If the race definition
* can be obtained within this timeout, wind for the race will be tracked; otherwise, the method returns without
* taking any effect.
*/
private void startTrackingWind(RaceHandle raceHandle, boolean correctByDeclination, long timeoutInMilliseconds) throws Exception {
private void startTrackingWind(RacesHandle raceHandle, boolean correctByDeclination, long timeoutInMilliseconds) throws Exception {
Event event = raceHandle.getEvent();
if (event != null) {
RaceDefinition race = raceHandle.getRace(timeoutInMilliseconds);
if (race != null) {
getService().startTrackingWind(event, race, correctByDeclination);
} else {
log("RaceDefinition wasn't received within "+timeoutInMilliseconds+"ms for a race in event "+event.getName()+
". Aborting wait; no wind tracking for this race.");
for (RaceDefinition race : raceHandle.getRaces(timeoutInMilliseconds)) {
if (race != null) {
getService().startTrackingWind(event, race, correctByDeclination);
} else {
log("RaceDefinition wasn't received within " + timeoutInMilliseconds + "ms for a race in event "
+ event.getName() + ". Aborting wait; no wind tracking for this race.");
}
}
}
}
@@ -859,7 +861,6 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
public List<LeaderboardDAO> getLeaderboards() {
Map<String, Leaderboard> leaderboards = getService().getLeaderboards();
List<LeaderboardDAO> results = new ArrayList<LeaderboardDAO>();
for(Leaderboard leaderboard: leaderboards.values()) {
LeaderboardDAO dao = new LeaderboardDAO();
dao.name = leaderboard.getName();
@@ -867,28 +868,39 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
for (RaceInLeaderboard raceColumn : leaderboard.getRaceColumns()) {
dao.addRace(raceColumn.getName(), raceColumn.isMedalRace(), raceColumn.getTrackedRace() != null);
}
dao.hasCarriedPoints = leaderboard.hasCarriedPoints();
dao.discardThresholds = leaderboard.getResultDiscardingRule().getDiscardIndexResultsStartingWithHowManyRaces();
results.add(dao);
}
return results;
}
public LeaderboardDAO getLeaderboardByName(String leaderboardName) {
Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName);
LeaderboardDAO dao = new LeaderboardDAO();
dao.name = leaderboard.getName();
dao.displayNames = new HashMap<CompetitorDAO, String>();
for (RaceInLeaderboard raceColumn : leaderboard.getRaceColumns()) {
dao.addRace(raceColumn.getName(), raceColumn.isMedalRace(), raceColumn.getTrackedRace() != null);
}
dao.hasCarriedPoints = leaderboard.hasCarriedPoints();
dao.discardThresholds = leaderboard.getResultDiscardingRule().getDiscardIndexResultsStartingWithHowManyRaces();
return dao;
}
@Override
public void updateLeaderboard(String leaderboardName, String newLeaderboardName, int[] newDiscardingThreasholds){
if(!leaderboardName.equals(newLeaderboardName))
public void updateLeaderboard(String leaderboardName, String newLeaderboardName, int[] newDiscardingThreasholds) {
if (!leaderboardName.equals(newLeaderboardName)) {
getService().renameLeaderboard(leaderboardName, newLeaderboardName);
}
Leaderboard leaderboard = getService().getLeaderboardByName(newLeaderboardName);
leaderboard.setResultDiscardingRule(new ResultDiscardingRuleImpl(newDiscardingThreasholds));
if (!Arrays.equals(leaderboard.getResultDiscardingRule().getDiscardIndexResultsStartingWithHowManyRaces(), newDiscardingThreasholds)) {
leaderboard.setResultDiscardingRule(new ResultDiscardingRuleImpl(newDiscardingThreasholds));
}
getService().updateStoredLeaderboard(leaderboard);
}
@Override
public void removeLeaderboard(String leaderboardName) {
getService().removeLeaderboard(leaderboardName);
@@ -1133,7 +1145,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
@Override
public void trackWithSwissTiming(SwissTimingRaceRecordDAO rr, String hostname, int port, boolean canSendRequests,
boolean trackWind, final boolean correctWindByDeclination) throws Exception {
final RaceHandle raceHandle = getService().addSwissTimingRace(rr.ID, hostname, port, canSendRequests,
final RacesHandle raceHandle = getService().addSwissTimingRace(rr.ID, hostname, port, canSendRequests,
MongoWindStoreFactory.INSTANCE.getMongoWindStore(mongoObjectFactory, domainObjectFactory),
TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS);
if (trackWind) {
@@ -1260,12 +1272,10 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
}
break;
}
return competitorData;
}
public Map<CompetitorDAO, List<GPSFixDAO>> getDouglasPoints(RaceIdentifier raceIdentifier,
public Map<CompetitorDAO, List<GPSFixDAO>> getDouglasPoints(RaceIdentifier raceIdentifier,
Map<CompetitorDAO, Date> from, Map<CompetitorDAO, Date> to,
double meters) {
Map<CompetitorDAO, List<GPSFixDAO>> result = new HashMap<CompetitorDAO, List<GPSFixDAO>>();
@@ -307,6 +307,10 @@ public class LeaderboardDAO implements IsSerializable {
return raceColumnNames;
}
public List<RaceInLeaderboardDAO> getRaceInLeaderboardList(){
return races;
}
public List<RaceInLeaderboardDAO> getRaceList(){
return races;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 846 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

@@ -1,5 +1,6 @@
package com.sap.sailing.server.test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
@@ -10,14 +11,15 @@ import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Set;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.tracking.RaceHandle;
import com.sap.sailing.domain.tracking.RaceListener;
import com.sap.sailing.domain.tracking.RacesHandle;
import com.sap.sailing.domain.tracking.TrackedEvent;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
@@ -30,7 +32,7 @@ public class RaceTrackerTest {
private final URI liveUri;
private final URI storedUri;
private RacingEventServiceImpl service;
private RaceHandle raceHandle;
private RacesHandle raceHandle;
public RaceTrackerTest() throws MalformedURLException, URISyntaxException {
// for live simulation:
@@ -85,8 +87,9 @@ public class RaceTrackerTest {
@Test
public void testInitialization() throws InterruptedException {
RaceDefinition race = raceHandle.getRace();
assertNotNull(race);
Set<RaceDefinition> races = raceHandle.getRaces();
assertNotNull(races);
assertFalse(races.isEmpty());
assertNotNull(getTrackedRace(raceHandle.getTrackedEvent()));
}
@@ -96,7 +99,7 @@ public class RaceTrackerTest {
TrackedRace oldTrackedRace = getTrackedRace(oldTrackedEvent);
RaceDefinition oldRaceDefinition = oldTrackedRace.getRace();
service.stopTracking(raceHandle.getEvent());
RaceHandle myRaceHandle = service.addTracTracRace(paramUrl, liveUri, storedUri, EmptyWindStore.INSTANCE, /* timeoutInMilliseconds */ 60000);
RacesHandle myRaceHandle = service.addTracTracRace(paramUrl, liveUri, storedUri, EmptyWindStore.INSTANCE, /* timeoutInMilliseconds */ 60000);
TrackedEvent newTrackedEvent = myRaceHandle.getTrackedEvent();
TrackedRace newTrackedRace = getTrackedRace(newTrackedEvent);
// expecting a new tracked race to be created when starting over with tracking
@@ -116,7 +119,7 @@ public class RaceTrackerTest {
public void testTrackingSameRaceWithoutStopping() throws MalformedURLException, IOException, InterruptedException, URISyntaxException {
TrackedEvent oldTrackedEvent = raceHandle.getTrackedEvent();
TrackedRace oldTrackedRace = getTrackedRace(oldTrackedEvent);
RaceHandle myRaceHandle = service.addTracTracRace(paramUrl, liveUri, storedUri, EmptyWindStore.INSTANCE, /* timeoutInMilliseconds */ 60000);
RacesHandle myRaceHandle = service.addTracTracRace(paramUrl, liveUri, storedUri, EmptyWindStore.INSTANCE, /* timeoutInMilliseconds */ 60000);
TrackedEvent newTrackedEvent = myRaceHandle.getTrackedEvent();
TrackedRace newTrackedRace = getTrackedRace(newTrackedEvent);
// expecting a new tracked race to be created when starting over with tracking
@@ -16,7 +16,7 @@ import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
import com.sap.sailing.domain.tracking.RaceHandle;
import com.sap.sailing.domain.tracking.RacesHandle;
import com.sap.sailing.domain.tracking.TrackedEvent;
import com.sap.sailing.domain.tracking.TrackedEventRegistry;
import com.sap.sailing.domain.tracking.TrackedRace;
@@ -91,7 +91,7 @@ public interface RacingEventService extends TrackedEventRegistry {
* if the race definition is not received for the race within this time, the race tracker for
* that race is stopped; use -1 to wait forever
*/
RaceHandle addTracTracRace(URL paramURL, URI liveURI, URI storedURI, WindStore windStore, long timeoutInMilliseconds)
RacesHandle addTracTracRace(URL paramURL, URI liveURI, URI storedURI, WindStore windStore, long timeoutInMilliseconds)
throws MalformedURLException, FileNotFoundException, URISyntaxException;
/**
@@ -180,7 +180,7 @@ public interface RacingEventService extends TrackedEventRegistry {
*/
void updateStoredLeaderboard(Leaderboard leaderboard);
RaceHandle addSwissTimingRace(String raceID, String hostname, int port, boolean canSendRequests,
RacesHandle addSwissTimingRace(String raceID, String hostname, int port, boolean canSendRequests,
WindStore windStore, long timeoutInMilliseconds) throws InterruptedException, UnknownHostException, IOException, ParseException;
SwissTimingFactory getSwissTimingFactory();
@@ -40,7 +40,7 @@ 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;
import com.sap.sailing.domain.tracking.RaceHandle;
import com.sap.sailing.domain.tracking.RacesHandle;
import com.sap.sailing.domain.tracking.RaceListener;
import com.sap.sailing.domain.tracking.RaceTracker;
import com.sap.sailing.domain.tracking.TrackedRace;
@@ -249,7 +249,7 @@ public class RacingEventServiceImpl implements RacingEventService {
}
@Override
public synchronized RaceHandle addSwissTimingRace(String raceID, String hostname, int port, boolean canSendRequests,
public synchronized RacesHandle addSwissTimingRace(String raceID, String hostname, int port, boolean canSendRequests,
WindStore windStore, long timeoutInMilliseconds) throws InterruptedException, UnknownHostException, IOException, ParseException {
Triple<String, String, Integer> key = new Triple<String, String, Integer>(raceID, hostname, port);
RaceTracker tracker = raceTrackersByID.get(key);
@@ -290,7 +290,7 @@ public class RacingEventServiceImpl implements RacingEventService {
}
@Override
public synchronized RaceHandle addTracTracRace(URL paramURL, URI liveURI, URI storedURI, WindStore windStore,
public synchronized RacesHandle addTracTracRace(URL paramURL, URI liveURI, URI storedURI, WindStore windStore,
long timeoutInMilliseconds) throws MalformedURLException, FileNotFoundException, URISyntaxException {
Triple<URL, URI, URI> key = new Triple<URL, URI, URI>(paramURL, liveURI, storedURI);
RaceTracker tracker = raceTrackersByID.get(key);