diff --git a/java/com.sap.sailing.domain.swisstimingreplayadapter.test/src/com/sap/sailing/domain/swisstimingreplayadapter/test/SwissTimingReplayAdapterServiceTest.java b/java/com.sap.sailing.domain.swisstimingreplayadapter.test/src/com/sap/sailing/domain/swisstimingreplayadapter/test/SwissTimingReplayAdapterServiceTest.java
index a0608a2f5b4..c835cbc700b 100644
--- a/java/com.sap.sailing.domain.swisstimingreplayadapter.test/src/com/sap/sailing/domain/swisstimingreplayadapter/test/SwissTimingReplayAdapterServiceTest.java
+++ b/java/com.sap.sailing.domain.swisstimingreplayadapter.test/src/com/sap/sailing/domain/swisstimingreplayadapter/test/SwissTimingReplayAdapterServiceTest.java
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.swisstimingreplayadapter.test;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -15,6 +16,7 @@ import org.junit.Ignore;
import org.junit.Test;
import com.sap.sailing.domain.base.Competitor;
+import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.swisstimingadapter.DomainFactory;
import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayRace;
@@ -185,6 +187,20 @@ public class SwissTimingReplayAdapterServiceTest {
}
}
+ @Test
+ public void testStartPerformanceDetection() throws Exception {
+ SwissTimingReplayToDomainAdapter replayListener = new SwissTimingReplayToDomainAdapter(null, DomainFactory.INSTANCE,
+ new DummyTrackedRegattaRegistry());
+ new SwissTimingReplayParserImpl().readData(getClass().getResourceAsStream("/SAW005906.20120805.replay"), replayListener);
+ Iterable extends TrackedRace> trackedRaces = replayListener.getTrackedRaces();
+ TrackedRace trackedRace = trackedRaces.iterator().next();
+ for (Competitor competitor : trackedRace.getRace().getCompetitors()) {
+ Distance distanceToLineAtStart = trackedRace.getDistanceToStartLine(competitor, trackedRace.getStartOfRace());
+ assertTrue(distanceToLineAtStart.getMeters() > 0);
+ assertTrue(distanceToLineAtStart.getMeters() < 8.5);
+ }
+ }
+
@Test
@Ignore
public void printRaceData_SAW005906_20120805() throws Exception {
diff --git a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/SwissTimingReplayService.java b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/SwissTimingReplayService.java
index b55ac39273c..9c7abac8697 100755
--- a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/SwissTimingReplayService.java
+++ b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/SwissTimingReplayService.java
@@ -26,7 +26,8 @@ public interface SwissTimingReplayService {
/**
* @param link
* the URL without the implicit "http://" prefix, as obtained, e.g., from
- * {@link SwissTimingReplayRace#getLink()}.
+ * {@link SwissTimingReplayRace#getLink()}, or with an explicit protocol specification
+ * as in "file:///..."
* @param replayListener
* the listener to receive all persing events
*/
diff --git a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayServiceImpl.java b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayServiceImpl.java
index 940ab7eb221..70415d33e0a 100644
--- a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayServiceImpl.java
+++ b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayServiceImpl.java
@@ -121,9 +121,13 @@ public class SwissTimingReplayServiceImpl implements SwissTimingReplayService {
@Override
public void loadRaceData(String link, SwissTimingReplayListener replayListener) {
- URL raceDataUrl;
+ final URL raceDataUrl;
try {
- raceDataUrl = new URL("http://" + link);
+ if (link.contains("://")) {
+ raceDataUrl = new URL(link);
+ } else {
+ raceDataUrl = new URL("http://" + link);
+ }
InputStream urlInputStream = (InputStream) raceDataUrl.getContent();
ByteArrayOutputStreamWithVisibleBuffer bos = new ByteArrayOutputStreamWithVisibleBuffer();
byte[] buf = new byte[8192];
diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java
index 3ebf547d4f0..f42bf20736e 100755
--- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java
+++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java
@@ -764,4 +764,10 @@ public class MockedTrackedRace implements DynamicTrackedRace {
// TODO Auto-generated method stub
}
+
+ @Override
+ public Distance getDistanceToStartLine(Competitor competitor, TimePoint timePoint) {
+ // TODO Auto-generated method stub
+ return null;
+ }
}
diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java
index 4838b452619..e278ef96f27 100755
--- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java
+++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java
@@ -507,4 +507,10 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace {
}
+ @Override
+ public Distance getDistanceToStartLine(Competitor competitor, TimePoint timePoint) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java
index 66d5f01fa69..147a58d42f4 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java
@@ -499,4 +499,20 @@ public interface TrackedRace extends Serializable {
*/
void setCourseDesignChangedListener(CourseDesignChangedListener listener);
+ /**
+ * Tells how far the given competitor was from the start line at the given timePoint.
+ * Using the {@link #getStartOfRace() race start time} for timePoint, this tells the competitor's
+ * distance to the line when the race was started.
+ *
+ * + * The distance to the line is calculated by projecting the competitor's position onto the line orthogonally and + * computing the distance of the projected position and the competitor's position. + *
null is returned. If the course's first waypoint is not a line or gate,
+ * the geometric distance between the first waypoint and the competitor's position at timePoint is
+ * returned. If the competitor's position cannot be determined, null is returned.
+ */
+ Distance getDistanceToStartLine(Competitor competitor, TimePoint timePoint);
}
diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java
index a56a8dd20de..a19f2e3379f 100755
--- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java
+++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java
@@ -2316,5 +2316,34 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
public void setCourseDesignChangedListener(CourseDesignChangedListener listener) {
this.courseDesignChangedListener = listener;
}
-
+
+ @Override
+ public Distance getDistanceToStartLine(Competitor competitor, TimePoint timePoint) {
+ Waypoint startWaypoint = getRace().getCourse().getFirstWaypoint();
+ final Distance result;
+ if (startWaypoint == null) {
+ result = null;
+ } else {
+ Position competitorPosition = getTrack(competitor).getEstimatedPosition(timePoint, /* extrapolate */ false);
+ if (competitorPosition == null) {
+ result = null;
+ } else {
+ Iterable marks = startWaypoint.getControlPoint().getMarks();
+ Iterator marksIterator = marks.iterator();
+ Mark first = marksIterator.next();
+ Position firstPosition = getOrCreateTrack(first).getEstimatedPosition(timePoint, /* extrapolate */ false);
+ if (marksIterator.hasNext()) {
+ // it's a line / gate
+ Mark second = marksIterator.next();
+ Position secondPosition = getOrCreateTrack(second).getEstimatedPosition(timePoint, /* extrapolate */ false);
+ Position competitorProjectedOntoStartLine = competitorPosition.projectToLineThrough(firstPosition,
+ firstPosition.getBearingGreatCircle(secondPosition));
+ result = competitorPosition.getDistance(competitorProjectedOntoStartLine);
+ } else {
+ result = competitorPosition.getDistance(firstPosition);
+ }
+ }
+ }
+ return result;
+ }
}