Separated the reading of "race times" (like start/stop, leg start times, etc) and "leg information" to avoid mixing of "leg start/end times" and other leg information like leg type

This commit is contained in:
fmittag committed 2012-04-30 11:25:35 +02:00
1 parent 4cdb8b85d0
commit 7a1da40ebf
10 files changed
+166 -104

No files matched your search

@@ -530,7 +530,7 @@ public class MockedTrackedRace implements DynamicTrackedRace {
}
@Override
public Iterable<Pair<TrackedLeg, TimePoint>> getStartTimesOfTrackedLegs() {
public Iterable<Pair<Waypoint, Pair<TimePoint, TimePoint>>> getMarkPassingsTimes() {
// TODO Auto-generated method stub
return null;
}
@@ -65,11 +65,9 @@ public interface TrackedRace extends Serializable {
TimePoint getAssumedEnd();
/**
* Returns a list of the start times of all legs as far as we know them
* The leg time of the first leg is equal to #{@link #getStart()}
* All other leg times are equal to the first mark passing of the leg
* Returns a list of the first and last mark passing times of all course waypoints
*/
Iterable<Pair<TrackedLeg, TimePoint>> getStartTimesOfTrackedLegs();
Iterable<Pair<Waypoint, Pair<TimePoint, TimePoint>>> getMarkPassingsTimes();
/**
* Shorthand for <code>{@link #getStart()}.{@link TimePoint#compareTo(TimePoint) compareTo(at)} &lt;= 0</code>
@@ -100,7 +100,7 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements
getOrCreateTrack(buoy).setMillisecondsOverWhichToAverage(millisecondsOverWhichToAverageSpeed);
}
}
updated(MillisecondsTimePoint.now());
updated(/* time point */null);
}
@Override
@@ -109,7 +109,7 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements
for (WindSource windSource : getWindSources()) {
getOrCreateWindTrack(windSource).setMillisecondsOverWhichToAverage(millisecondsOverWhichToAverageWind);
}
updated(MillisecondsTimePoint.now());
updated(/* time point */null);
}
@Override
@@ -311,7 +311,7 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements
if (requiresStartTimeUpdate) {
invalidateStartTime();
}
invalidateLegTimes();
invalidateMarkPassingTimes();
invalidateEndTime();
// notify *after* all mark passings have been re-established; should avoid flicker
@@ -367,13 +367,13 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements
@Override
public synchronized void recordWind(Wind wind, WindSource windSource) {
getOrCreateWindTrack(windSource).add(wind);
updated(null); // wind events shouldn't advance race time
updated(/* time point */null); // wind events shouldn't advance race time
}
@Override
public synchronized void removeWind(Wind wind, WindSource windSource) {
getOrCreateWindTrack(windSource).remove(wind);
updated(wind.getTimePoint());
updated(/* time point */null); // wind events shouldn't advance race time
}
@Override
@@ -125,9 +125,9 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
private TimePoint endTime;
/**
* The calculated start times of the legs
* The the first and last passing times of all course waypoints
*/
private final List<Pair<TrackedLeg, TimePoint>> startTimesOfLegs;
private final List<Pair<Waypoint, Pair<TimePoint, TimePoint>>> markPassingsTimes;
/**
* The latest time point contained by any of the events received and processed
@@ -237,7 +237,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
markPassingsForWaypoint.put(waypoint, new ConcurrentSkipListSet<MarkPassing>(
MarkPassingByTimeComparator.INSTANCE));
}
startTimesOfLegs = new ArrayList<Pair<TrackedLeg, TimePoint>>();
markPassingsTimes = new ArrayList<Pair<Waypoint, Pair<TimePoint, TimePoint>>>();
windTracks = new HashMap<WindSource, WindTrack>();
windTracks.putAll(windStore.loadWindTracks(trackedEvent, this, millisecondsOverWhichToAverageWind));
// by default, a tracked race offers one course-based wind estimation, one track-based wind estimation track and
@@ -294,8 +294,8 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
endTime = null;
}
protected void invalidateLegTimes() {
startTimesOfLegs.clear();
protected void invalidateMarkPassingTimes() {
markPassingsTimes.clear();
}
/**
@@ -425,7 +425,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
protected void setStartTimeReceived(TimePoint start) {
this.startTimeReceived = start;
invalidateStartTime();
invalidateLegTimes();
invalidateMarkPassingTimes();
}
@Override
@@ -439,24 +439,22 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
}
@Override
public Iterable<Pair<TrackedLeg, TimePoint>> getStartTimesOfTrackedLegs() {
if (startTimesOfLegs.isEmpty()) {
int legNumber = 1;
public Iterable<Pair<Waypoint, Pair<TimePoint, TimePoint>>> getMarkPassingsTimes() {
if (markPassingsTimes.isEmpty()) {
int wayPointNumber = 1;
// Remark: sometimes it can happen that a mark passing with a wrong time stamp breaks the right time order
// of the leg times
// of the waypoint times
Date previousLegPassingTime = null;
for (TrackedLeg trackedLeg : trackedLegs.values()) {
if (legNumber == 1) {
for (Waypoint waypoint: getRace().getCourse().getWaypoints()) {
Pair<TimePoint, TimePoint> timesPair = new Pair<TimePoint, TimePoint>(null, null);
markPassingsTimes.add(new Pair<Waypoint, Pair<TimePoint, TimePoint>>(waypoint, timesPair));
if (wayPointNumber == 1) {
// For the first leg the use of "firstPassingDate" is not correct,
// because boats can pass the start line before the actual start;
// therefore we are using the calculated start time here
TimePoint startOfRace = getStart();
if (startOfRace != null) {
startTimesOfLegs.add(new Pair<TrackedLeg, TimePoint>(trackedLeg, startOfRace));
}
}
Waypoint to = trackedLeg.getLeg().getTo();
NavigableSet<MarkPassing> markPassings = getMarkPassingsInOrderAsNavigableSet(to);
timesPair.setA(getStart());
} else {
NavigableSet<MarkPassing> markPassings = getMarkPassingsInOrderAsNavigableSet(waypoint);
if (markPassings != null && !markPassings.isEmpty()) {
// ensure the leg times are in the right time order; there may perhaps be left-overs for marks to be
// reached later that
@@ -466,18 +464,19 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
for (MarkPassing currentMarkPassing : markPassings) {
Date currentPassingDate = currentMarkPassing.getTimePoint().asDate();
if (previousLegPassingTime == null || currentPassingDate.after(previousLegPassingTime)) {
startTimesOfLegs.add(new Pair<TrackedLeg, TimePoint>(trackedLeg, currentMarkPassing.getTimePoint()));
timesPair.setA(currentMarkPassing.getTimePoint());
previousLegPassingTime = currentPassingDate;
break;
}
}
}
}
legNumber++;
}
wayPointNumber++;
}
}
return startTimesOfLegs;
return markPassingsTimes;
}
@Override
@@ -8,7 +8,7 @@ import com.sap.sailing.domain.common.EventAndRaceIdentifier;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.gwt.ui.client.Timer.PlayModes;
import com.sap.sailing.gwt.ui.client.Timer.PlayStates;
import com.sap.sailing.gwt.ui.shared.LegInfoDTO;
import com.sap.sailing.gwt.ui.shared.MarkPassingTimesDTO;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
import com.sap.sailing.gwt.ui.shared.components.SettingsDialogComponent;
@@ -50,7 +50,7 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
// in case the race is not tracked anymore we reset the timer
reset();
} else {
if ((raceTimesInfo.startOfTracking != null || raceTimesInfo.startOfRace != null) && raceTimesInfo.timePointOfNewestEvent != null) {
if ((raceTimesInfo.startOfTracking != null || raceTimesInfo.startOfRace != null) && raceTimesInfo.newestTrackingEvent != null) {
// we set here the min and max of the time slider, the start and end of the race as well as the known
// leg markers
boolean liveModeToBeMadePossible = isLiveModeToBeMadePossible();
@@ -80,8 +80,8 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
long liveTimePointInMillis = System.currentTimeMillis() - livePlayDelayInMillis;
RaceTimesInfoDTO lastRaceTimesInfo = raceTimesInfoProvider != null ? raceTimesInfoProvider.getRaceTimesInfo(selectedRace) : null;
return lastRaceTimesInfo != null &&
lastRaceTimesInfo.timePointOfNewestEvent != null &&
liveTimePointInMillis < lastRaceTimesInfo.timePointOfNewestEvent.getTime() + eventTimeoutTolerance &&
lastRaceTimesInfo.newestTrackingEvent != null &&
liveTimePointInMillis < lastRaceTimesInfo.newestTrackingEvent.getTime() + eventTimeoutTolerance &&
lastRaceTimesInfo.startOfTracking != null &&
liveTimePointInMillis > lastRaceTimesInfo.startOfTracking.getTime();
}
@@ -122,15 +122,15 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
switch (timer.getPlayMode()) {
case Live:
if (newRaceTimesInfo.startOfRace != null) {
long extensionTime = calculateRaceExtensionTime(newRaceTimesInfo.startOfRace, newRaceTimesInfo.timePointOfNewestEvent);
long extensionTime = calculateRaceExtensionTime(newRaceTimesInfo.startOfRace, newRaceTimesInfo.newestTrackingEvent);
min = new Date(newRaceTimesInfo.startOfRace.getTime() - extensionTime);
} else if (newRaceTimesInfo.startOfTracking != null) {
min = newRaceTimesInfo.startOfTracking;
}
if (newRaceTimesInfo.timePointOfNewestEvent != null) {
max = newRaceTimesInfo.timePointOfNewestEvent;
if (newRaceTimesInfo.newestTrackingEvent != null) {
max = newRaceTimesInfo.newestTrackingEvent;
}
break;
case Replay:
@@ -144,8 +144,8 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
if (newRaceTimesInfo.endOfRace != null) {
max = new Date(newRaceTimesInfo.endOfRace.getTime() + extensionTime);
} else if (newRaceTimesInfo.timePointOfNewestEvent != null) {
max = newRaceTimesInfo.timePointOfNewestEvent;
} else if (newRaceTimesInfo.newestTrackingEvent != null) {
max = newRaceTimesInfo.newestTrackingEvent;
}
break;
}
@@ -185,15 +185,15 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
// initialize timer position
switch (timer.getPlayMode()) {
case Live:
if (newRaceTimesInfo.timePointOfNewestEvent != null) {
timer.setTime(newRaceTimesInfo.timePointOfNewestEvent.getTime());
if (newRaceTimesInfo.newestTrackingEvent != null) {
timer.setTime(newRaceTimesInfo.newestTrackingEvent.getTime());
}
timer.play();
break;
case Replay:
// set time to end of race
if (newRaceTimesInfo.getLastLegTimes() != null) {
timer.setTime(newRaceTimesInfo.getLastLegTimes().firstPassingDate.getTime());
if (newRaceTimesInfo.getLastMarkPassingTimes() != null) {
timer.setTime(newRaceTimesInfo.getLastMarkPassingTimes().firstPassingDate.getTime());
} else if (newRaceTimesInfo.endOfRace != null) {
timer.setTime(newRaceTimesInfo.endOfRace.getTime());
} else if (newRaceTimesInfo.startOfRace != null) {
@@ -205,14 +205,15 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
}
private void updateLegMarkers(RaceTimesInfoDTO newRaceTimesInfo) {
List<LegInfoDTO> legTimepoints = newRaceTimesInfo.getLegTimes();
List<MarkPassingTimesDTO> markPassingTimes = newRaceTimesInfo.getMarkPassingTimes();
boolean requiresMarkerUpdate = true;
// updating the sliderbar markers requires a lot of time, therefore we need to do this only if required
if(lastRaceTimesInfo != null && lastRaceTimesInfo.legTimes.size() == newRaceTimesInfo.legTimes.size()) {
if(lastRaceTimesInfo != null && lastRaceTimesInfo.markPassingTimes.size() == newRaceTimesInfo.markPassingTimes.size()) {
requiresMarkerUpdate = false;
for(int i = 0; i < newRaceTimesInfo.legTimes.size(); i++) {
if(newRaceTimesInfo.legTimes.get(i).firstPassingDate.getTime() != lastRaceTimesInfo.legTimes.get(i).firstPassingDate.getTime()) {
int numberOfLegs = newRaceTimesInfo.markPassingTimes.size();
for(int i = 0; i < numberOfLegs; i++) {
if(newRaceTimesInfo.markPassingTimes.get(i).firstPassingDate.getTime() != lastRaceTimesInfo.markPassingTimes.get(i).firstPassingDate.getTime()) {
requiresMarkerUpdate = true;
break;
}
@@ -220,8 +221,8 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
}
if (requiresMarkerUpdate && sliderBar.isMinMaxInitialized()) {
sliderBar.clearMarkers();
for (LegInfoDTO legTimepointDTO : legTimepoints) {
sliderBar.addMarker(legTimepointDTO.name, new Double(legTimepointDTO.firstPassingDate.getTime()));
for (MarkPassingTimesDTO markPassingTimesDTO: markPassingTimes) {
sliderBar.addMarker(markPassingTimesDTO.name, new Double(markPassingTimesDTO.firstPassingDate.getTime()));
}
sliderBar.redraw();
}
@@ -121,6 +121,7 @@ import com.sap.sailing.gwt.ui.shared.LegEntryDTO;
import com.sap.sailing.gwt.ui.shared.LegInfoDTO;
import com.sap.sailing.gwt.ui.shared.ManeuverDTO;
import com.sap.sailing.gwt.ui.shared.MarkDTO;
import com.sap.sailing.gwt.ui.shared.MarkPassingTimesDTO;
import com.sap.sailing.gwt.ui.shared.MultiCompetitorRaceDataDTO;
import com.sap.sailing.gwt.ui.shared.PlacemarkDTO;
import com.sap.sailing.gwt.ui.shared.PlacemarkOrderDTO;
@@ -944,33 +945,54 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
public RaceTimesInfoDTO getRaceTimesInfo(RaceIdentifier raceIdentifier) {
RaceTimesInfoDTO raceTimesInfo = null;
TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier);
if (trackedRace != null) {
raceTimesInfo = new RaceTimesInfoDTO(raceIdentifier);
List<LegInfoDTO> legInfos = new ArrayList<LegInfoDTO>();
raceTimesInfo.setLegInfos(legInfos);
List<MarkPassingTimesDTO> markPassingTimesDTOs = new ArrayList<MarkPassingTimesDTO>();
raceTimesInfo.setMarkPassingTimes(markPassingTimesDTOs);
raceTimesInfo.setStartOfRace(trackedRace.getStart() == null ? null : trackedRace.getStart().asDate());
raceTimesInfo.startOfTracking = trackedRace.getStartOfTracking() == null ? null : trackedRace.getStartOfTracking().asDate();
raceTimesInfo.timePointOfLastEvent = trackedRace.getTimePointOfLastEvent() == null ? null : trackedRace.getTimePointOfLastEvent().asDate();
raceTimesInfo.timePointOfNewestEvent = trackedRace.getTimePointOfNewestEvent() == null ? null : trackedRace.getTimePointOfNewestEvent().asDate();
raceTimesInfo.newestTrackingEvent = trackedRace.getTimePointOfNewestEvent() == null ? null : trackedRace.getTimePointOfNewestEvent().asDate();
raceTimesInfo.endOfTracking = trackedRace.getEndOfTracking() == null ? null : trackedRace.getEndOfTracking().asDate();
raceTimesInfo.endOfRace = trackedRace.getAssumedEnd() == null ? null : trackedRace.getAssumedEnd().asDate();
List<LegInfoDTO> legTimes = new ArrayList<LegInfoDTO>();
raceTimesInfo.setLegTimes(legTimes);
Iterable<Pair<TrackedLeg, TimePoint>> startTimesOfTrackedLegs = trackedRace.getStartTimesOfTrackedLegs();
synchronized(startTimesOfTrackedLegs) {
Iterable<Pair<Waypoint, Pair<TimePoint, TimePoint>>> markPassingsTimes = trackedRace.getMarkPassingsTimes();
synchronized(markPassingsTimes) {
int numberOfWaypoints = Util.size(markPassingsTimes);
int wayPointNumber = 1;
for(Pair<Waypoint, Pair<TimePoint, TimePoint>> markPassingTimes: markPassingsTimes) {
MarkPassingTimesDTO markPassingTimesDTO = new MarkPassingTimesDTO();
markPassingTimesDTO.name = wayPointNumber == numberOfWaypoints ? "F" : "L" + wayPointNumber;
Pair<TimePoint, TimePoint> timesPair = markPassingTimes.getB();
TimePoint firstPassingTime = timesPair.getA();
TimePoint lastPassingTime = timesPair.getB();
markPassingTimesDTO.firstPassingDate = firstPassingTime == null ? null : firstPassingTime.asDate();
markPassingTimesDTO.lastPassingDate = lastPassingTime == null ? null : lastPassingTime.asDate();
markPassingTimesDTOs.add(markPassingTimesDTO);
wayPointNumber++;
}
}
Iterable<TrackedLeg> trackedLegs = trackedRace.getTrackedLegs();
synchronized(trackedLegs) {
int legNumber = 1;
for(Pair<TrackedLeg, TimePoint> legWithStarttime: startTimesOfTrackedLegs) {
for(TrackedLeg trackedLeg: trackedLegs) {
LegInfoDTO legInfoDTO = new LegInfoDTO(legNumber);
legInfoDTO.name = (legNumber == 1) ? "S" : "L" + legNumber;
TimePoint legStartTime = legWithStarttime.getB();
if(legStartTime != null) {
legInfoDTO.firstPassingDate = legStartTime.asDate();
legInfoDTO.name = "L" + legNumber;
try {
legInfoDTO.legType = legWithStarttime.getA().getLegType(legStartTime);
legInfoDTO.legBearingInDegrees = legWithStarttime.getA().getLegBearing(legStartTime).getDegrees();
MarkPassingTimesDTO markPassingTimesDTO = markPassingTimesDTOs.get(legNumber-1);
if(markPassingTimesDTO.firstPassingDate != null) {
TimePoint p = new MillisecondsTimePoint(markPassingTimesDTO.firstPassingDate);
legInfoDTO.legType = trackedLeg.getLegType(p);
legInfoDTO.legBearingInDegrees = trackedLeg.getLegBearing(p).getDegrees();
}
} catch (NoWindException e) {
// do nothing
}
}
legTimes.add(legInfoDTO);
legInfos.add(legInfoDTO);
legNumber++;
}
}
@@ -1,18 +1,9 @@
package com.sap.sailing.gwt.ui.shared;
import java.util.Date;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.sap.sailing.domain.common.LegType;
public class LegInfoDTO extends NamedDTO implements IsSerializable {
/**
* The time point when the leg was first entered by a competitor; for the first leg the semantics
* are slightly different: if the official race start time is known it is used instead of the first
* passing event.
*/
public Date firstPassingDate;
public int legNumber;
public LegType legType;
@@ -0,0 +1,22 @@
package com.sap.sailing.gwt.ui.shared;
import java.util.Date;
import com.google.gwt.user.client.rpc.IsSerializable;
public class MarkPassingTimesDTO extends NamedDTO implements IsSerializable {
/**
* The time point when the leg was first entered by a competitor; for the first leg the semantics
* are slightly different: if the official race start time is known it is used instead of the first
* passing event.
*/
public Date firstPassingDate;
public Date lastPassingDate;
public MarkPassingTimesDTO() {}
public MarkPassingTimesDTO(String name) {
this.name = name;
}
}
@@ -10,15 +10,17 @@ import com.sap.sailing.domain.common.RaceIdentifier;
public class RaceTimesInfoDTO implements IsSerializable {
private RaceIdentifier raceIdentifier;
public List<LegInfoDTO> legTimes;
public List<LegInfoDTO> legInfos;
public List<MarkPassingTimesDTO> markPassingTimes;
public Date startOfRace;
public Date startOfTracking;
public Date endOfTracking;
public Date endOfRace;
public Date timePointOfLastEvent;
public Date timePointOfNewestEvent;
public Date assumedEndOfRace;
public Date newestTrackingEvent;
public RaceTimesInfoDTO(RaceIdentifier raceIdentifier) {
this.raceIdentifier = raceIdentifier;
@@ -34,25 +36,18 @@ public class RaceTimesInfoDTO implements IsSerializable {
this.raceIdentifier = raceIdentifier;
}
public LegInfoDTO getLastLegTimes() {
if (legTimes == null || legTimes.isEmpty()) {
public MarkPassingTimesDTO getLastMarkPassingTimes() {
if (markPassingTimes == null || markPassingTimes.isEmpty()) {
return null;
}
LegInfoDTO lastLegTime = null;
Iterator<LegInfoDTO> iterator = legTimes.iterator();
MarkPassingTimesDTO lastTimes = null;
Iterator<MarkPassingTimesDTO> iterator = markPassingTimes.iterator();
while(iterator.hasNext()) {
lastLegTime = iterator.next();
lastTimes = iterator.next();
}
return lastLegTime;
return lastTimes;
}
public List<LegInfoDTO> getLegTimes() {
return legTimes;
}
public void setLegTimes(List<LegInfoDTO> legTimes) {
this.legTimes = legTimes;
}
public Date getStartOfRace() {
return startOfRace;
@@ -70,19 +65,51 @@ public class RaceTimesInfoDTO implements IsSerializable {
this.startOfTracking = startOfTracking;
}
public Date getTimePointOfLastEvent() {
return timePointOfLastEvent;
public Date getEndOfTracking() {
return endOfTracking;
}
public void setTimePointOfLastEvent(Date timePointOfLastEvent) {
this.timePointOfLastEvent = timePointOfLastEvent;
public void setEndOfTracking(Date endOfTracking) {
this.endOfTracking = endOfTracking;
}
public Date getTimePointOfNewestEvent() {
return timePointOfNewestEvent;
public Date getEndOfRace() {
return endOfRace;
}
public void setTimePointOfNewestEvent(Date timePointOfNewestEvent) {
this.timePointOfNewestEvent = timePointOfNewestEvent;
public void setEndOfRace(Date endOfRace) {
this.endOfRace = endOfRace;
}
public Date getAssumedEndOfRace() {
return assumedEndOfRace;
}
public void setAssumedEndOfRace(Date assumedEndOfRace) {
this.assumedEndOfRace = assumedEndOfRace;
}
public Date getNewestTrackingEvent() {
return newestTrackingEvent;
}
public void setNewestTrackingEvent(Date newestTrackingEvent) {
this.newestTrackingEvent = newestTrackingEvent;
}
public List<LegInfoDTO> getLegInfos() {
return legInfos;
}
public void setLegInfos(List<LegInfoDTO> legInfos) {
this.legInfos = legInfos;
}
public List<MarkPassingTimesDTO> getMarkPassingTimes() {
return markPassingTimes;
}
public void setMarkPassingTimes(List<MarkPassingTimesDTO> markPassingTimes) {
this.markPassingTimes = markPassingTimes;
}
}
@@ -646,8 +646,8 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
}
if (leadingCompetitorDTO != null && lastShownFix.containsKey(leadingCompetitorDTO) && lastShownFix.get(leadingCompetitorDTO) != -1
&& legOfLeaderCompetitor > 0 && legOfLeaderCompetitor <= lastRaceTimesInfo.getLegTimes().size()) {
LegInfoDTO legInfoDTO = lastRaceTimesInfo.getLegTimes().get(legOfLeaderCompetitor);
&& legOfLeaderCompetitor > 0 && legOfLeaderCompetitor <= lastRaceTimesInfo.getLegInfos().size()) {
LegInfoDTO legInfoDTO = lastRaceTimesInfo.getLegInfos().get(legOfLeaderCompetitor-1);
GPSFixDTO lastBoatFix = getBoatFix(leadingCompetitorDTO);
double advantageLineLengthInKm = 1.0;
double distanceFromBoatPosition = 0.005; // 5m
@@ -707,8 +707,10 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
}
private void showStartAndFinishLines(final CourseDTO courseDTO) {
if(map != null && courseDTO != null) {
if(courseDTO.startGate != null) {
if(map != null && courseDTO != null && quickRanks != null && !quickRanks.isEmpty() && lastRaceTimesInfo != null) {
int legOfLeadingCompetitor = quickRanks.get(0).legNumber;
int numberOfLegs = lastRaceTimesInfo.legInfos.size() - 1;
if(courseDTO.startGate != null && legOfLeadingCompetitor == 1) {
LatLng[] startGatePoints = new LatLng[2];
startGatePoints[0] = LatLng.newInstance(courseDTO.startGate.getA().position.latDeg, courseDTO.startGate.getA().position.lngDeg);
startGatePoints[1] = LatLng.newInstance(courseDTO.startGate.getB().position.latDeg, courseDTO.startGate.getB().position.lngDeg);
@@ -729,7 +731,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
startLine.deleteVertex(0);
}
}
if(courseDTO.finishGate != null) {
if(courseDTO.finishGate != null && legOfLeadingCompetitor == numberOfLegs) {
LatLng[] finishGatePoints = new LatLng[2];
finishGatePoints[0] = LatLng.newInstance(courseDTO.finishGate.getA().position.latDeg, courseDTO.finishGate.getA().position.lngDeg);
finishGatePoints[1] = LatLng.newInstance(courseDTO.finishGate.getB().position.latDeg, courseDTO.finishGate.getB().position.lngDeg);