Merge branch 'design2015' into design2015-races

This commit is contained in:
Steffen Schaefer committed 2015-07-16 11:34:14 +02:00
commit d865123cea
5 files changed
+143 -49

No files matched your search

@@ -1,7 +1,10 @@
package com.sap.sailing.domain.base.impl; package com.sap.sailing.domain.base.impl;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Set;
import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Competitor;
@@ -13,6 +16,7 @@ public class RaceDefinitionImpl extends NamedImpl implements RaceDefinition {
private static final long serialVersionUID = -1900955198751393727L; private static final long serialVersionUID = -1900955198751393727L;
private final Course course; private final Course course;
private final LinkedHashMap<Serializable, Competitor> competitorsById; private final LinkedHashMap<Serializable, Competitor> competitorsById;
private final Set<Competitor> competitors;
private final BoatClass boatClass; private final BoatClass boatClass;
private final Serializable id; private final Serializable id;
@@ -23,11 +27,12 @@ public class RaceDefinitionImpl extends NamedImpl implements RaceDefinition {
public RaceDefinitionImpl(String name, Course course, BoatClass boatClass, Iterable<? extends Competitor> competitors, Serializable id) { public RaceDefinitionImpl(String name, Course course, BoatClass boatClass, Iterable<? extends Competitor> competitors, Serializable id) {
super(name); super(name);
assert name != null; assert name != null;
this.course = course; this.course = course;
this.competitors = new HashSet<>();
this.competitorsById = new LinkedHashMap<>(); this.competitorsById = new LinkedHashMap<>();
for (Competitor competitor : competitors) { for (Competitor competitor : competitors) {
Competitor competitorWithEqualID = competitorsById.put(competitor.getId(), competitor); Competitor competitorWithEqualID = competitorsById.put(competitor.getId(), competitor);
this.competitors.add(competitor);
if (competitorWithEqualID != null && competitorWithEqualID != competitor) { if (competitorWithEqualID != null && competitorWithEqualID != competitor) {
throw new IllegalArgumentException("Two distinct competitors with equal ID "+competitor.getId()+" are not allowed within the single race "+name); throw new IllegalArgumentException("Two distinct competitors with equal ID "+competitor.getId()+" are not allowed within the single race "+name);
} }
@@ -48,7 +53,7 @@ public class RaceDefinitionImpl extends NamedImpl implements RaceDefinition {
@Override @Override
public Iterable<Competitor> getCompetitors() { public Iterable<Competitor> getCompetitors() {
return competitorsById.values(); return Collections.unmodifiableSet(competitors);
} }
@Override @Override
@@ -99,6 +99,14 @@ public interface ScoreCorrection extends Serializable {
*/ */
boolean hasCorrectionFor(RaceColumn raceInLeaderboard); boolean hasCorrectionFor(RaceColumn raceInLeaderboard);
/**
* Similar to {@link #hasCorrectionFor(RaceColumn)}, but returns <code>true</code> only if score corrections are found
* for any competitor who in <code>raceInLeaderboard</code> is not in a tracked race and hence the fleet assignment
* cannot be determined. This is helpful, e.g., for progress detection. If score corrections are present for such
* untracked competitors then all untracked fleets need to be assumed as finished.
*/
boolean hasCorrectionForNonTrackedFleet(RaceColumn raceInLeaderboard);
/** /**
* @return all race columns for which this score corrections object has at least one correction; note that this * @return all race columns for which this score corrections object has at least one correction; note that this
* object may hold corrections also for competitors that are not currently returned by * object may hold corrections also for competitors that are not currently returned by
@@ -472,19 +472,30 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
@Override @Override
public boolean hasCorrectionFor(RaceColumn raceInLeaderboard) { public boolean hasCorrectionFor(RaceColumn raceInLeaderboard) {
return internalHasScoreCorrectionFor(raceInLeaderboard, /* considerOnlyUntrackedRaces */ false);
}
private boolean internalHasScoreCorrectionFor(RaceColumn raceInLeaderboard, boolean considerOnlyUntrackedRaces) {
for (com.sap.sse.common.Util.Pair<Competitor, RaceColumn> correctedScoresKey : correctedScores.keySet()) { for (com.sap.sse.common.Util.Pair<Competitor, RaceColumn> correctedScoresKey : correctedScores.keySet()) {
if (correctedScoresKey.getB() == raceInLeaderboard) { if (correctedScoresKey.getB() == raceInLeaderboard &&
(!considerOnlyUntrackedRaces || raceInLeaderboard.getTrackedRace(correctedScoresKey.getA()) == null)) {
return true; return true;
} }
} }
for (com.sap.sse.common.Util.Pair<Competitor, RaceColumn> maxPointsReasonsKey : maxPointsReasons.keySet()) { for (com.sap.sse.common.Util.Pair<Competitor, RaceColumn> maxPointsReasonsKey : maxPointsReasons.keySet()) {
if (maxPointsReasonsKey.getB() == raceInLeaderboard) { if (maxPointsReasonsKey.getB() == raceInLeaderboard &&
(!considerOnlyUntrackedRaces || raceInLeaderboard.getTrackedRace(maxPointsReasonsKey.getA()) == null)) {
return true; return true;
} }
} }
return false; return false;
} }
@Override
public boolean hasCorrectionForNonTrackedFleet(RaceColumn raceInLeaderboard) {
return internalHasScoreCorrectionFor(raceInLeaderboard, /* considerOnlyUntrackedRaces */ true);
}
@Override @Override
public TimePoint getTimePointOfLastCorrectionsValidity() { public TimePoint getTimePointOfLastCorrectionsValidity() {
return timePointOfLastCorrectionsValidity; return timePointOfLastCorrectionsValidity;
@@ -41,7 +41,7 @@ import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
import com.sap.sailing.domain.leaderboard.SettableScoreCorrection; import com.sap.sailing.domain.leaderboard.ScoreCorrection;
import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.WindTrack; import com.sap.sailing.domain.tracking.WindTrack;
import com.sap.sailing.domain.tracking.WindWithConfidence; import com.sap.sailing.domain.tracking.WindWithConfidence;
@@ -517,8 +517,8 @@ public class RaceContext {
} }
} }
} }
SettableScoreCorrection scoreCorrection = leaderboard.getScoreCorrection(); ScoreCorrection scoreCorrection = leaderboard.getScoreCorrection();
if(!hasTrackingForRaceColumn() && scoreCorrection != null && scoreCorrection.hasCorrectionFor(raceColumn)) { if(trackedRace == null && scoreCorrection != null && scoreCorrection.hasCorrectionForNonTrackedFleet(raceColumn)) {
return RaceViewState.FINISHED; return RaceViewState.FINISHED;
} }
if(startTime != null) { if(startTime != null) {
@@ -527,15 +527,6 @@ public class RaceContext {
return RaceViewState.PLANNED; return RaceViewState.PLANNED;
} }
private boolean hasTrackingForRaceColumn() {
for(Fleet fleetOfRaceColumn : raceColumn.getFleets()) {
if(raceColumn.getTrackedRace(fleetOfRaceColumn) != null) {
return true;
}
}
return false;
}
private Wind checkForWindFixesFromRaceLog() { private Wind checkForWindFixesFromRaceLog() {
WindFixesFinder windFixesFinder = new WindFixesFinder(raceLog); WindFixesFinder windFixesFinder = new WindFixesFinder(raceLog);
List<Wind> windList = windFixesFinder.analyze(); List<Wind> windList = windFixesFinder.analyze();
@@ -34,8 +34,11 @@ import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.Speed; import com.sap.sailing.domain.common.Speed;
import com.sap.sailing.domain.common.Tack; import com.sap.sailing.domain.common.Tack;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.WindSourceType;
import com.sap.sailing.domain.common.impl.KnotSpeedImpl; import com.sap.sailing.domain.common.impl.KnotSpeedImpl;
import com.sap.sailing.domain.common.impl.MeterDistance; import com.sap.sailing.domain.common.impl.MeterDistance;
import com.sap.sailing.domain.common.impl.WindSourceImpl;
import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo; import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
@@ -46,6 +49,8 @@ import com.sap.sailing.domain.tracking.TrackedLeg;
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sailing.domain.tracking.WindPositionMode;
import com.sap.sailing.domain.tracking.WindTrack;
import com.sap.sailing.domain.tracking.WindWithConfidence;
import com.sap.sailing.server.RacingEventService; import com.sap.sailing.server.RacingEventService;
import com.sap.sse.common.Duration; import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint; import com.sap.sse.common.TimePoint;
@@ -97,7 +102,7 @@ public class LeaderboardData extends ExportAction {
* </competitor> * </competitor>
* </pre> * </pre>
*/ */
private Element createLeaderboardXML(Leaderboard leaderboard, List<Element> competitors, List<Element> races, Util.Pair<Double, Vector<String>> leaderboardConfidenceAndErrorMessages) { private Element createLeaderboardXML(Leaderboard leaderboard, List<Element> windData, List<Element> competitors, List<Element> races, Util.Pair<Double, Vector<String>> leaderboardConfidenceAndErrorMessages) {
Element leaderboardElement = new Element("leaderboard"); Element leaderboardElement = new Element("leaderboard");
addNamedElementWithValue(leaderboardElement, "name", leaderboard.getName()); addNamedElementWithValue(leaderboardElement, "name", leaderboard.getName());
addNamedElementWithValue(leaderboardElement, "display_name", leaderboard.getDisplayName()); addNamedElementWithValue(leaderboardElement, "display_name", leaderboard.getDisplayName());
@@ -106,6 +111,9 @@ public class LeaderboardData extends ExportAction {
addNamedElementWithValue(leaderboardElement, "boat_class", getBoatClassName(leaderboard)); addNamedElementWithValue(leaderboardElement, "boat_class", getBoatClassName(leaderboard));
leaderboardElement.addContent(createTimedXML("last_modification_", leaderboard.getTimePointOfLatestModification())); leaderboardElement.addContent(createTimedXML("last_modification_", leaderboard.getTimePointOfLatestModification()));
leaderboardElement.addContent(createDataConfidenceXML(leaderboardConfidenceAndErrorMessages)); leaderboardElement.addContent(createDataConfidenceXML(leaderboardConfidenceAndErrorMessages));
Element windContainer = new Element("wind");
windContainer.addContent(windData);
leaderboardElement.addContent(windContainer);
leaderboardElement.addContent(competitors); leaderboardElement.addContent(competitors);
leaderboardElement.addContent(races); leaderboardElement.addContent(races);
return leaderboardElement; return leaderboardElement;
@@ -202,6 +210,35 @@ public class LeaderboardData extends ExportAction {
return windElements; return windElements;
} }
private Element createRaceXMLWithoutRaceData(final Fleet fleet, final RaceColumn column, final Leaderboard leaderboard, int sameDayGroupIndex, int raceCounter, Util.Pair<Double, Vector<String>> raceConfidenceAndErrorMessages) throws NoWindException, IOException, ServletException {
Element raceElement = new Element("race");
addNamedElementWithValue(raceElement, "name", column.getName()+'-'+fleet.getName());
addNamedElementWithValue(raceElement, "race_index_in_leaderboard", raceCounter);
addNamedElementWithValue(raceElement, "fleet_name", fleet.getName());
addNamedElementWithValue(raceElement, "same_day_index", sameDayGroupIndex);
addNamedElementWithValue(raceElement, "is_live", "false");
TimePoint timepointToBeUsed = MillisecondsTimePoint.now();
List<Competitor> competitors = leaderboard.getCompetitorsFromBestToWorst(column, timepointToBeUsed);
for (Competitor competitorInLeaderboard : competitors) {
MaxPointsReason mpr = leaderboard.getScoreCorrection().getMaxPointsReason(competitorInLeaderboard, column, timepointToBeUsed);
if (mpr != null && !mpr.equals(MaxPointsReason.NONE)) {
// add this competitor to the list to have him evaluated
Element competitorElement = createCompetitorXML(competitorInLeaderboard, leaderboard, /*shortVersion*/ true, null);
Element competitorRaceDataElement = new Element("competitor_race_data");
MaxPointsReason maxPointsReason = leaderboard.getMaxPointsReason(competitorInLeaderboard, column, timepointToBeUsed);
addNamedElementWithValue(competitorRaceDataElement, "max_points_reason", maxPointsReason.toString());
boolean isDiscardedForCompetitor = leaderboard.isDiscarded(competitorInLeaderboard, column, timepointToBeUsed);
addNamedElementWithValue(competitorRaceDataElement, "is_discarded", isDiscardedForCompetitor == true ? "true" : "false");
Double finalRaceScore = leaderboard.getTotalPoints(competitorInLeaderboard, column, timepointToBeUsed);
addNamedElementWithValue(competitorRaceDataElement, "final_race_score", finalRaceScore);
competitorElement.addContent(competitorRaceDataElement);
raceElement.addContent(competitorElement);
raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitorInLeaderboard.getName() + " has no valid data for this race!", 0.2, raceConfidenceAndErrorMessages);
}
}
return raceElement;
}
/** /**
* Creates elements containing information about a race * Creates elements containing information about a race
*/ */
@@ -233,7 +270,7 @@ public class LeaderboardData extends ExportAction {
addNamedElementWithValue(raceElement, "start_of_tracking_time_as_millis", handleValue(race.getStartOfTracking())); addNamedElementWithValue(raceElement, "start_of_tracking_time_as_millis", handleValue(race.getStartOfTracking()));
addNamedElementWithValue(raceElement, "end_of_tracking_time_as_millis", handleValue(race.getEndOfTracking())); addNamedElementWithValue(raceElement, "end_of_tracking_time_as_millis", handleValue(race.getEndOfTracking()));
LineDetails start = race.getStartLine(race.getStartOfTracking()); LineDetails start = race.getStartLine(race.getStartOfRace());
if (start != null) { if (start != null) {
if (start.getLength() != null) { if (start.getLength() != null) {
addNamedElementWithValue(raceElement, "start_line_length_in_meters", start.getLength().getMeters()); addNamedElementWithValue(raceElement, "start_line_length_in_meters", start.getLength().getMeters());
@@ -568,13 +605,16 @@ public class LeaderboardData extends ExportAction {
// will kick in // will kick in
} }
} }
if (endOfRaceForLastTrackedRaceInLeaderboard != null) { // first look for latest modification of leaderboard
timePointOfLatestModification = endOfRaceForLastTrackedRaceInLeaderboard; // if there is no latest modification then take the last races time
if (leaderboard.getTimePointOfLatestModification() != null) {
timePointOfLatestModification = leaderboard.getTimePointOfLatestModification();
} else { } else {
if (leaderboard.getTimePointOfLatestModification() != null) { if (endOfRaceForLastTrackedRaceInLeaderboard != null) {
timePointOfLatestModification = leaderboard.getTimePointOfLatestModification(); timePointOfLatestModification = endOfRaceForLastTrackedRaceInLeaderboard;
} else { } else {
timePointOfLatestModification = MillisecondsTimePoint.now(); // make sure that the timepoint is far in the future - could be that the export is called too early
timePointOfLatestModification = MillisecondsTimePoint.now().plus(Duration.ONE_YEAR);
} }
} }
Duration totalTimeSailed = leaderboard.getTotalTimeSailed(competitor, timePointOfLatestModification); Duration totalTimeSailed = leaderboard.getTotalTimeSailed(competitor, timePointOfLatestModification);
@@ -708,6 +748,36 @@ public class LeaderboardData extends ExportAction {
return legElement; return legElement;
} }
private List<Element> createFullWindDataXML(TrackedRace race, Fleet fleet, int sameDayIndex) {
List<Element> windElements = new ArrayList<>();
List<WindSource> windSourcesToDeliver = new ArrayList<WindSource>();
WindSourceImpl windSource = new WindSourceImpl(WindSourceType.COMBINED);
windSourcesToDeliver.add(windSource);
TimePoint fromTimePoint = race.getStartOfRace();
TimePoint toTimePoint = race.getEndOfRace();
int numberOfFixes = (int) ((toTimePoint.asMillis() - fromTimePoint.asMillis()) / /*resolutionInMillis*/ 1000*60*5);
WindTrack windTrack = race.getOrCreateWindTrack(windSource);
TimePoint timePoint = fromTimePoint;
for (int i = 0; i < numberOfFixes && toTimePoint != null && timePoint.compareTo(toTimePoint) < 0; i++) {
WindWithConfidence<com.sap.sse.common.Util.Pair<Position, TimePoint>> averagedWindWithConfidence = windTrack
.getAveragedWindWithConfidence(null, timePoint);
if (averagedWindWithConfidence != null) {
Element windElement = new Element("windFix");
addNamedElementWithValue(windElement, "same_day_index", sameDayIndex);
addNamedElementWithValue(windElement, "race_name", race.getRace().getName());
addNamedElementWithValue(windElement, "fleet_name", fleet.getName());
windElement.addContent(createTimedXML("", averagedWindWithConfidence.getObject().getTimePoint()));
addNamedElementWithValue(windElement, "bearingInDegrees", averagedWindWithConfidence.getObject().getBearing().getDegrees());
addNamedElementWithValue(windElement, "directionFromInDegrees", averagedWindWithConfidence.getObject().getBearing().reverse().getDegrees());
windElement.addContent(createWindXML("", new SpeedWithConfidenceImpl<TimePoint>(new KnotSpeedImpl(averagedWindWithConfidence.getObject().getKnots()),
averagedWindWithConfidence.getConfidence(), toTimePoint)));
windElements.add(windElement);
}
timePoint = new MillisecondsTimePoint(timePoint.asMillis() + 1000*60*5);
}
return windElements;
}
/** /**
* Creates xml elements that indicate confidence. * Creates xml elements that indicate confidence.
*/ */
@@ -784,24 +854,29 @@ public class LeaderboardData extends ExportAction {
private Util.Pair<Double, Vector<String>> checkData(TrackedRace race) throws Exception { private Util.Pair<Double, Vector<String>> checkData(TrackedRace race) throws Exception {
double simpleConfidence = 1.0; Vector<String> messages = new Vector<String>(); double simpleConfidence = 1.0; Vector<String> messages = new Vector<String>();
TimePoint dateAtYear2000 = new MillisecondsTimePoint(946681200000l); TimePoint dateAtYear2000 = new MillisecondsTimePoint(946681200000l);
if (race.getStartOfRace() == null || race.getStartOfRace().before(dateAtYear2000)) { if (race == null) {
messages.add("Start time of race " + race.getRaceIdentifier().getRaceName() + " is either null or not valid!"); messages.add("Tracked race is null - no race seems to be connected!");
simpleConfidence -= 1; simpleConfidence -= 1;
} } else {
if (race.getEndOfRace() == null || race.getEndOfRace().before(dateAtYear2000)) { if (race.getStartOfRace() == null || race.getStartOfRace().before(dateAtYear2000)) {
messages.add("End time of race " + race.getRaceIdentifier().getRaceName() + " is either null or not valid!"); messages.add("Start time of race " + race.getRaceIdentifier().getRaceName() + " is either null or not valid!");
simpleConfidence -= 1; simpleConfidence -= 1;
} }
if (race.getStartOfTracking() == null || race.getStartOfTracking().before(dateAtYear2000)) { if (race.getEndOfRace() == null || race.getEndOfRace().before(dateAtYear2000)) {
messages.add("Start tracking time of race " + race.getRaceIdentifier().getRaceName() + " is either null or not valid!"); messages.add("End time of race " + race.getRaceIdentifier().getRaceName() + " is either null or not valid!");
simpleConfidence -= 0.2; simpleConfidence -= 1;
} }
if (race.getEndOfTracking() == null || race.getEndOfTracking().before(dateAtYear2000)) { if (race.getStartOfTracking() == null || race.getStartOfTracking().before(dateAtYear2000)) {
messages.add("End tracking time of race " + race.getRaceIdentifier().getRaceName() + " is either null or not valid!"); messages.add("Start tracking time of race " + race.getRaceIdentifier().getRaceName() + " is either null or not valid!");
simpleConfidence -= 0.2; simpleConfidence -= 0.2;
} }
if (race.isLive(MillisecondsTimePoint.now())) { if (race.getEndOfTracking() == null || race.getEndOfTracking().before(dateAtYear2000)) {
messages.add("This race is live - data for this race will not be available until the race has been finished!"); messages.add("End tracking time of race " + race.getRaceIdentifier().getRaceName() + " is either null or not valid!");
simpleConfidence -= 0.2;
}
if (race.isLive(MillisecondsTimePoint.now())) {
messages.add("This race is live - data for this race will not be available until the race has been finished!");
}
} }
return new Util.Pair<Double, Vector<String>>(simpleConfidence, messages); return new Util.Pair<Double, Vector<String>>(simpleConfidence, messages);
} }
@@ -886,24 +961,25 @@ public class LeaderboardData extends ExportAction {
TimePoint timeSpent = MillisecondsTimePoint.now(); TimePoint timeSpent = MillisecondsTimePoint.now();
log.info("Starting XML export of " + leaderboard.getName()); log.info("Starting XML export of " + leaderboard.getName());
Util.Pair<Double, Vector<String>> leaderboardConfidenceAndErrorMessages = checkData(leaderboard); Util.Pair<Double, Vector<String>> leaderboardConfidenceAndErrorMessages = checkData(leaderboard);
final List<Element> racesElements = new ArrayList<Element>(); final List<Element> racesElements = new ArrayList<Element>();
final List<Element> competitorElements = new ArrayList<Element>(); final List<Element> competitorElements = new ArrayList<Element>();
for (Competitor competitor : leaderboard.getAllCompetitors()) { for (Competitor competitor : leaderboard.getAllCompetitors()) {
Util.Pair<Double, Vector<String>> competitorConfidenceAndErrorMessages = checkData(competitor); Util.Pair<Double, Vector<String>> competitorConfidenceAndErrorMessages = checkData(competitor);
competitorElements.add(createCompetitorXML(competitor, leaderboard, /*shortVersion*/ false, competitorConfidenceAndErrorMessages)); competitorElements.add(createCompetitorXML(competitor, leaderboard, /*shortVersion*/ false, competitorConfidenceAndErrorMessages));
} }
List<Element> windData = new ArrayList<Element>();
TrackedRace raceBefore = null; int sameDayGroupIndex = 0; int raceCounter = 0; TrackedRace raceBefore = null; int sameDayGroupIndex = 0; int raceCounter = 0;
for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { for (RaceColumn raceColumn : leaderboard.getRaceColumns()) {
for (Fleet fleet : raceColumn.getFleets()) { for (Fleet fleet : raceColumn.getFleets()) {
TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); TrackedRace trackedRace = raceColumn.getTrackedRace(fleet);
if (trackedRace != null && trackedRace.hasGPSData()) { if (trackedRace != null) {
sameDayGroupIndex += getSameDayGroupIndex(raceColumn.getTrackedRace(fleet), raceBefore); sameDayGroupIndex += getSameDayGroupIndex(raceColumn.getTrackedRace(fleet), raceBefore);
TimePoint timeSpentForRace = MillisecondsTimePoint.now(); }
Util.Pair<Double, Vector<String>> raceConfidenceAndErrorMessages = checkData(trackedRace); TimePoint timeSpentForRace = MillisecondsTimePoint.now();
final List<Element> legs = new ArrayList<Element>(); Util.Pair<Double, Vector<String>> raceConfidenceAndErrorMessages = checkData(trackedRace);
final List<Element> legs = new ArrayList<Element>();
if (trackedRace != null && trackedRace.hasGPSData()) {
windData.addAll(createFullWindDataXML(trackedRace, fleet, sameDayGroupIndex));
int legCounter = 0; int legCounter = 0;
for (TrackedLeg leg : trackedRace.getTrackedLegs()) { for (TrackedLeg leg : trackedRace.getTrackedLegs()) {
Util.Pair<Double, Vector<String>> legConfidenceAndErrorMessages = checkData(leg); Util.Pair<Double, Vector<String>> legConfidenceAndErrorMessages = checkData(leg);
@@ -914,12 +990,15 @@ public class LeaderboardData extends ExportAction {
addNamedElementWithValue(raceElement, "generation_time_in_milliseconds", elapsedTimeForRace.asMillis()); addNamedElementWithValue(raceElement, "generation_time_in_milliseconds", elapsedTimeForRace.asMillis());
racesElements.add(raceElement); racesElements.add(raceElement);
log.info("Exported complete race " + trackedRace.getRace().getName() + " in " + elapsedTimeForRace.asMillis() + " milliseconds!"); log.info("Exported complete race " + trackedRace.getRace().getName() + " in " + elapsedTimeForRace.asMillis() + " milliseconds!");
raceBefore = trackedRace; } else {
racesElements.add(createRaceXMLWithoutRaceData(fleet, raceColumn, leaderboard, sameDayGroupIndex, ++raceCounter, raceConfidenceAndErrorMessages));
log.info("Exported empty race in race column " + raceColumn.getName() + " with fleet " + fleet.getName());
} }
raceBefore = trackedRace;
} }
} }
log.info("Finished XML export of leaderboard " + leaderboard.getName() + " in " + MillisecondsTimePoint.now().minus(timeSpent.asMillis()).asMillis() + " milliseconds"); log.info("Finished XML export of leaderboard " + leaderboard.getName() + " in " + MillisecondsTimePoint.now().minus(timeSpent.asMillis()).asMillis() + " milliseconds");
Element dataToExport = createLeaderboardXML(leaderboard, competitorElements, racesElements, leaderboardConfidenceAndErrorMessages); Element dataToExport = createLeaderboardXML(leaderboard, windData, competitorElements, racesElements, leaderboardConfidenceAndErrorMessages);
sendDocument(dataToExport, leaderboard.getName() + ".xml"); sendDocument(dataToExport, leaderboard.getName() + ".xml");
} }
} }