mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-09 13:50:57 +00:00
Merge remote-tracking branch 'origin/dataMining' into dataMining
This commit is contained in:
commit
400d8c9552
18 files changed
+182
-37
No files matched your search
@@ -7,6 +7,7 @@ Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
Fragment-Host: com.sap.sailing.datamining
|
||||
Import-Package: junit.framework;version="4.8.2",
|
||||
org.junit;version="4.8.2"
|
||||
org.junit;version="4.8.2",
|
||||
org.junit.runner;version="4.8.2"
|
||||
Require-Bundle: org.mockito.mockito-core;bundle-version="1.9.5",
|
||||
org.hamcrest;bundle-version="1.1.0"
|
||||
+8
-2
@@ -852,13 +852,13 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getDistanceToStartLine(Competitor competitor, double secondsBeforeRaceStart) {
|
||||
public Distance getDistanceToStartLine(Competitor competitor, long millisecondsBeforeRaceStart) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Speed getSpeed(Competitor competitor, double secondsBeforeRaceStart) {
|
||||
public Speed getSpeed(Competitor competitor, long millisecondsBeforeRaceStart) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
@@ -910,4 +910,10 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getDistanceFromStarboardSideOfStartLine(Competitor competitor, TimePoint timePoint) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+8
-2
@@ -543,13 +543,13 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getDistanceToStartLine(Competitor competitor, double secondsBeforeRaceStart) {
|
||||
public Distance getDistanceToStartLine(Competitor competitor, long millisecondsBeforeRaceStart) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Speed getSpeed(Competitor competitor, double secondsBeforeRaceStart) {
|
||||
public Speed getSpeed(Competitor competitor, long millisecondsBeforeRaceStart) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
@@ -595,4 +595,10 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getDistanceFromStarboardSideOfStartLine(Competitor competitor, TimePoint timePoint) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -1274,10 +1274,10 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
||||
if (!competitorMarkPassings.isEmpty()) {
|
||||
final MarkPassing firstMarkPassing = competitorMarkPassings.iterator().next();
|
||||
if (firstMarkPassing.getWaypoint() == startWaypoint) {
|
||||
Distance distanceToStartLineFiveSecondsBeforeStartOfRace = trackedRace.getDistanceToStartLine(competitor, 5);
|
||||
Distance distanceToStartLineFiveSecondsBeforeStartOfRace = trackedRace.getDistanceToStartLine(competitor, /*milliseconds before start*/ 5000);
|
||||
entryDTO.distanceToStartLineFiveSecondsBeforeStartInMeters = distanceToStartLineFiveSecondsBeforeStartOfRace == null ? null
|
||||
: distanceToStartLineFiveSecondsBeforeStartOfRace.getMeters();
|
||||
Speed speedFiveSecondsBeforeStartOfRace = trackedRace.getSpeed(competitor, 5);
|
||||
Speed speedFiveSecondsBeforeStartOfRace = trackedRace.getSpeed(competitor, /*milliseconds before start*/ 5000);
|
||||
entryDTO.speedOverGroundFiveSecondsBeforeStartInKnots = speedFiveSecondsBeforeStartOfRace == null ? null
|
||||
: speedFiveSecondsBeforeStartOfRace.getKnots();
|
||||
Distance distanceToStartLineAtStartOfRace = trackedRace.getDistanceToStartLine(
|
||||
|
||||
@@ -576,7 +576,7 @@ public interface TrackedRace extends Serializable {
|
||||
* the geometric distance between the first waypoint and the competitor's position at <code>timePoint</code> is
|
||||
* returned. If the competitor's position cannot be determined, <code>null</code> is returned.
|
||||
*/
|
||||
Distance getDistanceToStartLine(Competitor competitor, double secondsBeforeRaceStart);
|
||||
Distance getDistanceToStartLine(Competitor competitor, long millisecondsBeforeRaceStart);
|
||||
|
||||
/**
|
||||
* Tells how far the given <code>competitor</code> was from the start line at the given <code>timePoint</code>.
|
||||
@@ -600,12 +600,20 @@ public interface TrackedRace extends Serializable {
|
||||
* or---if the start waypoint was a single mark---the distance to the single start mark at the time the competitor started.
|
||||
* If the competitor hasn't started yet, <code>null</code> is returned.
|
||||
*/
|
||||
Distance getDistanceFromStarboardSideOfStartLineWhenPassingStart(Competitor competitor);
|
||||
Distance getDistanceFromStarboardSideOfStartLineWhenPassingStart(Competitor competitor);
|
||||
|
||||
/**
|
||||
* At the given timepoint and for the competitor, this method returns the distance to the starboard end of the start line
|
||||
* or---if the start waypoint was a single mark---the distance to the single start mark at the timepoint.
|
||||
* If the competitor hasn't started yet, <code>null</code> is returned.
|
||||
*
|
||||
*/
|
||||
Distance getDistanceFromStarboardSideOfStartLine(Competitor competitor, TimePoint timePoint);
|
||||
|
||||
/**
|
||||
* The estimated speed of the competitor at the time point of the given seconds before the start of race.
|
||||
*/
|
||||
Speed getSpeed(Competitor competitor, double secondsBeforeRaceStart);
|
||||
Speed getSpeed(Competitor competitor, long millisecondsBeforeRaceStart);
|
||||
|
||||
/**
|
||||
* The speed of the competitor when crossing the start line. It will return null if there are no recorded
|
||||
|
||||
+22
-4
@@ -2373,12 +2373,12 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getDistanceToStartLine(Competitor competitor, double secondsBeforeRaceStart) {
|
||||
public Distance getDistanceToStartLine(Competitor competitor, long millisecondsBeforeRaceStart) {
|
||||
if (getStartOfRace() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
TimePoint beforeStart = new MillisecondsTimePoint(getStartOfRace().asMillis() - (long) (secondsBeforeRaceStart * 1000));
|
||||
TimePoint beforeStart = new MillisecondsTimePoint(getStartOfRace().asMillis() - millisecondsBeforeRaceStart);
|
||||
return getDistanceToStartLine(competitor, beforeStart);
|
||||
}
|
||||
|
||||
@@ -2423,12 +2423,12 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
}
|
||||
|
||||
@Override
|
||||
public Speed getSpeed(Competitor competitor, double secondsBeforeRaceStart) {
|
||||
public Speed getSpeed(Competitor competitor, long millisecondsBeforeRaceStart) {
|
||||
if (getStartOfRace() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
TimePoint beforeStart = new MillisecondsTimePoint(getStartOfRace().asMillis() - (long) (secondsBeforeRaceStart * 1000));
|
||||
TimePoint beforeStart = new MillisecondsTimePoint(getStartOfRace().asMillis() - millisecondsBeforeRaceStart);
|
||||
return getTrack(competitor).getEstimatedSpeed(beforeStart);
|
||||
}
|
||||
|
||||
@@ -2452,6 +2452,24 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getDistanceFromStarboardSideOfStartLine(Competitor competitor, TimePoint timePoint) {
|
||||
final Distance result;
|
||||
if (timePoint != null) {
|
||||
Position competitorPositionWhenPassingStart = getTrack(competitor).getEstimatedPosition(
|
||||
timePoint, /* extrapolate */false);
|
||||
final Position starboardMarkPosition = getStarboardMarkOfStartlinePosition(timePoint);
|
||||
if (competitorPositionWhenPassingStart != null && starboardMarkPosition != null) {
|
||||
result = starboardMarkPosition == null ? null : competitorPositionWhenPassingStart.getDistance(starboardMarkPosition);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* The method has protected scope in order to allow for testing. Based on the bearing from the start waypoint to the
|
||||
* next mark, identifies which of the two marks of the start line is on starboard. If the start waypoint has only
|
||||
|
||||
+8
-2
@@ -853,13 +853,13 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getDistanceToStartLine(Competitor competitor, double secondsBeforeRaceStart) {
|
||||
public Distance getDistanceToStartLine(Competitor competitor, long millisecondsBeforeRaceStart) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Speed getSpeed(Competitor competitor, double secondsBeforeRaceStart) {
|
||||
public Speed getSpeed(Competitor competitor, long millisecondsBeforeRaceStart) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
@@ -911,4 +911,10 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getDistanceFromStarboardSideOfStartLine(Competitor competitor, TimePoint timePoint) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -62,7 +62,7 @@ public interface StringMessages extends Messages {
|
||||
String renameRace();
|
||||
String openSelectedLeaderboard();
|
||||
String rank();
|
||||
String totalRank();
|
||||
String totalRegattaRank();
|
||||
String collapse();
|
||||
String expand();
|
||||
String leg();
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ regattaRank=Regatta Rank
|
||||
regattaRankTooltip=Competitor''s rank in the regatta
|
||||
overallRank=Overall Rank
|
||||
overallRankTooltip=Competitor''s rank in the series
|
||||
totalRank=Total rank
|
||||
totalRegattaRank=Regatta Rank
|
||||
collapse=-
|
||||
expand=+
|
||||
leg=L
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ regattaRank=Platz in der Regatta
|
||||
regattaRankTooltip=Platzierung des Teilnehmers in der Regatta
|
||||
overallRank=Platz in der Serie
|
||||
overallRankTooltip=Platzierung des Teilnehmers in der Serie
|
||||
totalRank=Gesamtplatz
|
||||
totalRegattaRank=Gesamtplatz
|
||||
collapse=-
|
||||
expand=+
|
||||
leg=L
|
||||
|
||||
+2
-2
@@ -42,12 +42,12 @@ public class CompetitorTotalRankFilter extends AbstractNumberFilter<CompetitorDT
|
||||
|
||||
@Override
|
||||
public String getLocalizedName(StringMessages stringMessages) {
|
||||
return stringMessages.totalRank();
|
||||
return stringMessages.totalRegattaRank();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocalizedDescription(StringMessages stringMessages) {
|
||||
return stringMessages.totalRank();
|
||||
return stringMessages.totalRegattaRank();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -1304,7 +1304,7 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS
|
||||
|
||||
@Override
|
||||
public SafeHtmlHeader getHeader() {
|
||||
return new SafeHtmlHeaderWithTooltip(SafeHtmlUtils.fromString(stringMessages.totalRank()), stringMessages.rankColumnTooltip());
|
||||
return new SafeHtmlHeaderWithTooltip(SafeHtmlUtils.fromString(stringMessages.totalRegattaRank()), stringMessages.rankColumnTooltip());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+23
-1
@@ -3,9 +3,11 @@ package com.sap.sailing.server.replication.test;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -21,9 +23,11 @@ import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
|
||||
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.domain.common.impl.Util;
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
import com.sap.sailing.domain.leaderboard.DelayedLeaderboardCorrections;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.SettableScoreCorrection;
|
||||
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
|
||||
import com.sap.sailing.domain.persistence.PersistenceFactory;
|
||||
import com.sap.sailing.domain.persistence.media.MediaDBFactory;
|
||||
@@ -42,6 +46,8 @@ import com.sap.sailing.server.replication.ReplicationMasterDescriptor;
|
||||
import com.sap.sailing.server.replication.ReplicationService;
|
||||
|
||||
public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServerReplicationTest {
|
||||
private static final Logger logger = Logger.getLogger(DelayedLeaderboardCorrectionsReplicationTest.class.getName());
|
||||
|
||||
private static final String Q2 = "Q2";
|
||||
private ReplicationService replicaReplicator;
|
||||
private ReplicationMasterDescriptor masterDescriptor;
|
||||
@@ -68,7 +74,7 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer
|
||||
// then start initial load, wait until finished; then link a tracked race to leaderboard's RaceColumn on master and
|
||||
// verify that on the replica it is associated to the RaceColumn as well, and the DelayedLeaderboardCorrections are
|
||||
// resolved properly on the replica.
|
||||
final DomainFactory domainFactory = DomainFactory.INSTANCE;
|
||||
final DomainFactory domainFactory = new DomainFactoryImpl();
|
||||
BoatClass boatClass = domainFactory.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true);
|
||||
DynamicCompetitor hasso = AbstractLeaderboardTest.createCompetitor("Dr. Hasso Plattner"); // don't create competitor using CompetitorStore
|
||||
final DynamicTrackedRace q2YellowTrackedRace = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 1, /* started */ false, boatClass) {
|
||||
@@ -123,9 +129,25 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer
|
||||
assertEquals(MaxPointsReason.NONE, replicaLeaderboard.getMaxPointsReason(hasso,
|
||||
replicaLeaderboard.getRaceColumnByName(Q2), MillisecondsTimePoint.now()));
|
||||
|
||||
logger.info("hasso object ID hash: "+System.identityHashCode(hasso));
|
||||
Leaderboard newMasterLeaderboard = master.getLeaderboardByName(masterLeaderboard.getName());
|
||||
SettableScoreCorrection newMasterScoreCorrections = newMasterLeaderboard.getScoreCorrection();
|
||||
RaceColumn newMasterQ2 = newMasterLeaderboard.getRaceColumnByName(Q2);
|
||||
newMasterScoreCorrections.getCompetitorsThatHaveCorrectionsIn(newMasterQ2);
|
||||
StringBuilder unexpectedCompetitors = new StringBuilder();
|
||||
unexpectedCompetitors.append("Unexpected competitors having score corrections (expected no competitor to have a real score correction at this point: ");
|
||||
for (Competitor unexpectedCompetitor : newMasterScoreCorrections.getCompetitorsThatHaveCorrectionsIn(newMasterQ2)) {
|
||||
unexpectedCompetitors.append(unexpectedCompetitor);
|
||||
unexpectedCompetitors.append(" with object ID ");
|
||||
unexpectedCompetitors.append(System.identityHashCode(unexpectedCompetitor));
|
||||
unexpectedCompetitors.append(", ");
|
||||
}
|
||||
assertTrue(unexpectedCompetitors.toString(), Util.isEmpty(newMasterScoreCorrections.getCompetitorsThatHaveCorrectionsIn(newMasterQ2))); // no score corrections applied yet
|
||||
// now connect the tracked race again to the leaderboard column in the re-loaded environment
|
||||
master.apply(new ConnectTrackedRaceToLeaderboardColumn(masterLeaderboard.getName(), Q2, /* default fleet */
|
||||
masterLeaderboard.getFleet(null).getName(), q2YellowTrackedRace.getRaceIdentifier()));
|
||||
logger.info("got score correction for competitor "+System.identityHashCode(newMasterScoreCorrections.getCompetitorsThatHaveCorrectionsIn(newMasterQ2).iterator().next()));
|
||||
assertTrue(Util.contains(newMasterScoreCorrections.getCompetitorsThatHaveCorrectionsIn(newMasterQ2), hasso)); // now score corrections must have been applied from Delayed...
|
||||
// now the delayed corrections are expected to have been resolved:
|
||||
assertEquals(MaxPointsReason.DNF, master.getLeaderboardByName(leaderboardName).getMaxPointsReason(hasso,
|
||||
master.getLeaderboardByName(leaderboardName).getRaceColumnByName(Q2), MillisecondsTimePoint.now()));
|
||||
|
||||
+8
-2
@@ -492,13 +492,13 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getDistanceToStartLine(Competitor competitor, double secondsBeforeRaceStart) {
|
||||
public Distance getDistanceToStartLine(Competitor competitor, long millisecondsBeforeRaceStart) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Speed getSpeed(Competitor competitor, double secondsBeforeRaceStart) {
|
||||
public Speed getSpeed(Competitor competitor, long millisecondsBeforeRaceStart) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
@@ -543,4 +543,10 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getDistanceFromStarboardSideOfStartLine(Competitor competitor, TimePoint timePoint) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -193,6 +193,34 @@ public abstract class ExportAction {
|
||||
return result;
|
||||
}
|
||||
|
||||
public Speed getAverageSpeedOverGround(TrackedRace trackedRace, Competitor competitor, TimePoint timePoint, boolean alsoIncludeNonFinishedRaces) {
|
||||
Speed result = null;
|
||||
if (Util.contains(trackedRace.getRace().getCompetitors(), competitor)) {
|
||||
NavigableSet<MarkPassing> markPassings = trackedRace.getMarkPassings(competitor);
|
||||
if (!markPassings.isEmpty()) {
|
||||
TimePoint from = markPassings.first().getTimePoint();
|
||||
TimePoint to;
|
||||
if (timePoint.after(markPassings.last().getTimePoint()) &&
|
||||
markPassings.last().getWaypoint() == trackedRace.getRace().getCourse().getLastWaypoint()) {
|
||||
// stop counting when competitor finished the race
|
||||
to = markPassings.last().getTimePoint();
|
||||
} else {
|
||||
if (markPassings.last().getWaypoint() != trackedRace.getRace().getCourse().getLastWaypoint() &&
|
||||
timePoint.after(markPassings.last().getTimePoint()) &&
|
||||
!alsoIncludeNonFinishedRaces) {
|
||||
return null;
|
||||
}
|
||||
to = timePoint;
|
||||
}
|
||||
Distance distanceTraveled = trackedRace.getDistanceTraveled(competitor, timePoint);
|
||||
if (distanceTraveled != null) {
|
||||
result = distanceTraveled.inTime(to.asMillis()-from.asMillis());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected String cleanSailId(String sailId, Competitor competitor) {
|
||||
if (sailId.matches("^[A-Z]{3}\\s[0-9]*")) {
|
||||
Pattern regex = Pattern.compile("(^[A-Z]{3})\\s([0-9]*)");
|
||||
|
||||
@@ -4,10 +4,13 @@ import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -22,6 +25,7 @@ import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.SpeedWithConfidence;
|
||||
import com.sap.sailing.domain.base.impl.SpeedWithConfidenceImpl;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
@@ -161,7 +165,7 @@ public class LeaderboardData extends ExportAction {
|
||||
return windElements;
|
||||
}
|
||||
|
||||
private Element createRaceXML(TrackedRace race, Fleet fleet, List<Element> legs, RaceColumn column, Leaderboard leaderboard, int sameDayGroupIndex, int raceCounter, Pair<Double, Vector<String>> raceConfidenceAndErrorMessages) throws NoWindException, IOException, ServletException {
|
||||
private Element createRaceXML(final TrackedRace race, final Fleet fleet, final List<Element> legs, final RaceColumn column, final Leaderboard leaderboard, int sameDayGroupIndex, int raceCounter, Pair<Double, Vector<String>> raceConfidenceAndErrorMessages) throws NoWindException, IOException, ServletException {
|
||||
Element raceElement = new Element("race");
|
||||
addNamedElementWithValue(raceElement, "name", cleanRaceName(race.getRace().getName()));
|
||||
addNamedElementWithValue(raceElement, "race_index_in_leaderboard", raceCounter);
|
||||
@@ -190,27 +194,53 @@ public class LeaderboardData extends ExportAction {
|
||||
final List<Competitor> allCompetitors = race.getCompetitorsFromBestToWorst(/*timePoint*/ race.getEndOfRace());
|
||||
addNamedElementWithValue(raceElement, "race_participant_count", allCompetitors.size());
|
||||
|
||||
// sort competitors according to their distance to the starboard side of the start line
|
||||
List<Competitor> allCompetitorsSortedByDistanceToStarboardSide = new ArrayList<Competitor>(allCompetitors.size());
|
||||
allCompetitorsSortedByDistanceToStarboardSide.addAll(allCompetitors);
|
||||
Collections.sort(allCompetitorsSortedByDistanceToStarboardSide, new Comparator<Competitor>() {
|
||||
@Override
|
||||
public int compare(Competitor o1, Competitor o2) {
|
||||
return race.getDistanceFromStarboardSideOfStartLineWhenPassingStart(o1).compareTo(race.getDistanceFromStarboardSideOfStartLineWhenPassingStart(o2));
|
||||
}
|
||||
});
|
||||
|
||||
Map<Competitor, Integer> competitorToDistanceRank = new HashMap<Competitor, Integer>();
|
||||
int raceRankSorted = 0;
|
||||
for (Competitor competitorSorted : allCompetitorsSortedByDistanceToStarboardSide) {
|
||||
raceRankSorted += 1;
|
||||
competitorToDistanceRank.put(competitorSorted, raceRankSorted);
|
||||
}
|
||||
|
||||
int raceRank = 0;
|
||||
for (Competitor competitor : allCompetitors) {
|
||||
Element competitorElement = createCompetitorXML(competitor, leaderboard, /*shortVersion*/ true, null);
|
||||
Element competitorRaceDataElement = new Element("competitor_race_data");
|
||||
int[] timePointsInSecondsBeforeStart = new int[]{5, 10, 20, 30};
|
||||
for (int i : timePointsInSecondsBeforeStart) {
|
||||
addNamedElementWithValue(competitorRaceDataElement, "distance_to_start_line_"+i+"seconds_before_start_in_meters", race.getDistanceToStartLine(competitor, race.getStartOfRace().minus(i*1000)).getMeters());
|
||||
addNamedElementWithValue(competitorRaceDataElement, "speed_"+i+"seconds_before_start_of_race_in_knots", race.getTrack(competitor).getEstimatedSpeed(race.getStartOfRace().minus(i*1000)).getKnots());
|
||||
addNamedElementWithValue(competitorRaceDataElement, "distance_from_starboard_side_of_start_line_"+i+"seconds_before_start_in_meters", race.getDistanceFromStarboardSideOfStartLine(competitor, race.getStartOfRace().minus(i*1000)).getMeters());
|
||||
}
|
||||
addNamedElementWithValue(competitorRaceDataElement, "distance_to_start_line_on_race_start_in_meters", race.getDistanceToStartLine(competitor, race.getStartOfRace()).getMeters());
|
||||
addNamedElementWithValue(competitorRaceDataElement, "speed_on_start_signal_of_race_in_knots", race.getTrack(competitor).getEstimatedSpeed(race.getStartOfRace()).getKnots());
|
||||
addNamedElementWithValue(competitorRaceDataElement, "distance_from_starboard_side_of_start_line_when_passing_start_in_meters", race.getDistanceFromStarboardSideOfStartLineWhenPassingStart(competitor).getMeters());
|
||||
addNamedElementWithValue(competitorRaceDataElement, "rank_based_on_distance_from_starboard_side_of_start_line", competitorToDistanceRank.get(competitor));
|
||||
addNamedElementWithValue(competitorRaceDataElement, "speed_when_crossing_start_line_in_knots", race.getSpeedWhenCrossingStartLine(competitor).getKnots());
|
||||
addNamedElementWithValue(competitorRaceDataElement, "start_advantage_in_meters", start.getAdvantage().getMeters());
|
||||
addNamedElementWithValue(competitorRaceDataElement, "speed_on_start_signal_of_race_in_knots", race.getTrack(competitor).getEstimatedSpeed(race.getStartOfRace()).getKnots());
|
||||
addNamedElementWithValue(competitorRaceDataElement, "advantageous_side_while_approaching_start_line", start.getAdvantageousSideWhileApproachingLine().name());
|
||||
addNamedElementWithValue(competitorRaceDataElement, "distance_traveled_in_meters", race.getDistanceTraveled(competitor, race.getEndOfRace()).getMeters());
|
||||
addNamedElementWithValue(competitorRaceDataElement, "average_speed_over_ground_in_knots", getAverageSpeedOverGround(race, competitor, race.getEndOfRace(), true).getKnots());
|
||||
addNamedElementWithValue(competitorRaceDataElement, "final_race_rank", ++raceRank);
|
||||
addNamedElementWithValue(competitorRaceDataElement, "final_race_score", leaderboard.getScoringScheme().getScoreForRank(column, competitor, raceRank, new Callable<Integer>() {
|
||||
@Override
|
||||
public Integer call() throws Exception {
|
||||
return allCompetitors.size();
|
||||
}
|
||||
}));
|
||||
TrackedLegOfCompetitor trackedLegOfCompetitor = race.getTrackedLeg(competitor, race.getRace().getCourse().getFirstLeg());
|
||||
addNamedElementWithValue(competitorRaceDataElement, "rank_at_end_of_first_leg", trackedLegOfCompetitor.getRank(trackedLegOfCompetitor.getFinishTime()));
|
||||
|
||||
// error here - check with race 8 muscat
|
||||
MaxPointsReason maxPointsReason = leaderboard.getMaxPointsReason(competitor, column, race.getEndOfRace());
|
||||
Double finalRaceScore = leaderboard.getTotalPoints(competitor, column, race.getEndOfRace());
|
||||
addNamedElementWithValue(competitorRaceDataElement, "final_race_score", finalRaceScore);
|
||||
Distance averageCrossTrackError = race.getAverageCrossTrackError(competitor, race.getEndOfRace(), /*waitForLatestAnalysis*/ false);
|
||||
addNamedElementWithValue(competitorRaceDataElement, "average_cross_track_error_in_meters", averageCrossTrackError != null ? averageCrossTrackError.getMeters() : -1.0);
|
||||
addNamedElementWithValue(competitorRaceDataElement, "max_points_reason", leaderboard.getMaxPointsReason(competitor, column, race.getEndOfRace()).toString());
|
||||
addNamedElementWithValue(competitorRaceDataElement, "max_points_reason", maxPointsReason.toString());
|
||||
competitorElement.addContent(competitorRaceDataElement);
|
||||
raceElement.addContent(competitorElement);
|
||||
}
|
||||
@@ -311,6 +341,7 @@ public class LeaderboardData extends ExportAction {
|
||||
addNamedElementWithValue(competitorLegDataElement, "windward_distance_to_overall_leader_that_has_finished_this_leg_in_meters", competitorLeg.getWindwardDistanceToOverallLeader(legFinishTime).getMeters());
|
||||
addNamedElementWithValue(competitorLegDataElement, "distance_traveled_in_meters", competitorLeg.getDistanceTraveled(legFinishTime).getMeters());
|
||||
addNamedElementWithValue(competitorLegDataElement, "average_speed_over_ground_in_knots", competitorLeg.getAverageSpeedOverGround(legFinishTime).getKnots());
|
||||
|
||||
addNamedElementWithValue(competitorLegDataElement, "number_of_jibes", competitorLeg.getNumberOfJibes(legFinishTime));
|
||||
addNamedElementWithValue(competitorLegDataElement, "number_of_tacks", competitorLeg.getNumberOfTacks(legFinishTime));
|
||||
addNamedElementWithValue(competitorLegDataElement, "number_of_penalty_circles", competitorLeg.getNumberOfPenaltyCircles(legFinishTime));
|
||||
@@ -322,9 +353,12 @@ public class LeaderboardData extends ExportAction {
|
||||
List<Maneuver> maneuvers = competitorLeg.getManeuvers(legFinishTime, /*waitForLatest*/false);
|
||||
addNamedElementWithValue(competitorLegDataElement, "maneuver_count", maneuvers.size());
|
||||
Element maneuversElement = new Element("maneuvers");
|
||||
int maneuverCounter = 0;
|
||||
for (Maneuver man : maneuvers) {
|
||||
maneuverCounter += 1;
|
||||
Element maneuverInformation = new Element("maneuver");
|
||||
addNamedElementWithValue(maneuverInformation, "type", man.getType().toString());
|
||||
addNamedElementWithValue(maneuverInformation, "position", maneuverCounter);
|
||||
addNamedElementWithValue(maneuverInformation, "direction_change_in_degrees", man.getDirectionChangeInDegrees());
|
||||
Distance maneuverLoss = man.getManeuverLoss();
|
||||
addNamedElementWithValue(maneuverInformation, "loss_in_meters", maneuverLoss != null ? maneuverLoss.getMeters() : 0.0);
|
||||
@@ -374,6 +408,10 @@ public class LeaderboardData extends ExportAction {
|
||||
messages.add("Competitor " + competitorLeg.getCompetitor().getName() + " has no average cross track error for this leg!");
|
||||
simpleConfidence -= 0.02;
|
||||
}
|
||||
if (competitorLeg.getStartTime().before(leg.getTrackedRace().getStartOfRace())) {
|
||||
messages.add("Competitor " + competitorLeg.getCompetitor().getName() + " has a start time of " + competitorLeg.getStartTime() + " that is BEFORE start of race time!");
|
||||
simpleConfidence -= 0.01;
|
||||
}
|
||||
}
|
||||
return new Pair<Double, Vector<String>>(simpleConfidence, messages);
|
||||
}
|
||||
|
||||
+1
-2
@@ -123,8 +123,7 @@
|
||||
-Dmongo.host=localhost
|
||||
</parameters.mongodb>
|
||||
<parameters.debug>
|
||||
-Xdebug
|
||||
-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y
|
||||
-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y
|
||||
</parameters.debug>
|
||||
<!--
|
||||
"Forward declaration" for better readability. The actual value should be defined in the local settings.xml,
|
||||
|
||||
@@ -67,6 +67,13 @@ osgi> ss com.sap.sailing.monitoring
|
||||
osgi> start 71
|
||||
</pre>
|
||||
|
||||
### Debug Tests Running During Full Build
|
||||
|
||||
If you quickly want to run tests in an OSGi/Maven environment but debug locally, run a full build locally using `buildAndUpdateProduct.sh` with all other test bundles commented out in `java/pom.xml`. You may then go to the test bundle/fragment directory and use `mvn
|
||||
-s ../../settings.xml -P debug.with-proxy install`. This will build the test bundle again and launch the tests, waiting for your debugger to connect. Connect your Eclipse debugger's remote debug launch to port 8000 on localhost.
|
||||
|
||||
Don't forget to un-comment the test bundles in the `java/pom.xml` file when you're done.
|
||||
|
||||
### Display Line Endings for File
|
||||
|
||||
Sometimes different line endings get mixed. To display all lin endings for each line of a given file use the following command:
|
||||
|
||||
Reference in new issue
Block a user