Merge remote-tracking branch 'origin/passingSide'

This commit is contained in:
fmittag committed 2013-03-01 10:33:05 +01:00
commit cd5121bf8f
33 files changed
+352 -182

No files matched your search

@@ -26,6 +26,8 @@ import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.common.Named;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.ScoringSchemeType;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.WithID;
@@ -150,7 +152,7 @@ public class DomainFactoryImpl implements DomainFactory {
List<ControlPoint> courseDefinition) {
List<Waypoint> waypoints = new ArrayList<>();
for (ControlPoint controlPoint : courseDefinition) {
Waypoint waypoint = baseDomainFactory.createWaypoint(controlPoint);
Waypoint waypoint = baseDomainFactory.createWaypoint(controlPoint, /* passingSide */ null);
waypoints.add(waypoint);
}
com.sap.sailing.domain.base.Course domainCourse = new CourseImpl("Course", waypoints);
@@ -214,7 +216,7 @@ public class DomainFactoryImpl implements DomainFactory {
List<Waypoint> waypoints = new ArrayList<Waypoint>();
for (Mark mark : course.getMarks()) {
ControlPoint controlPoint = getOrCreateControlPoint(mark.getDevices());
Waypoint waypoint = baseDomainFactory.createWaypoint(controlPoint);
Waypoint waypoint = baseDomainFactory.createWaypoint(controlPoint, /* passingSide */ null);
waypoints.add(waypoint);
}
com.sap.sailing.domain.base.Course result = new CourseImpl(courseName, waypoints);
@@ -267,11 +269,11 @@ public class DomainFactoryImpl implements DomainFactory {
@Override
public void updateCourseWaypoints(com.sap.sailing.domain.base.Course courseToUpdate, Iterable<Mark> marks) throws PatchFailedException {
List<com.sap.sailing.domain.base.ControlPoint> newDomainControlPoints = new ArrayList<ControlPoint>();
List<Pair<com.sap.sailing.domain.base.ControlPoint, NauticalSide>> newDomainControlPoints = new ArrayList<Pair<com.sap.sailing.domain.base.ControlPoint, NauticalSide>>();
for (Mark mark : marks) {
// TODO bug 1043: propagate the mark names to the waypoint names
com.sap.sailing.domain.base.ControlPoint domainControlPoint = getOrCreateControlPoint(mark.getDevices());
newDomainControlPoints.add(domainControlPoint);
newDomainControlPoints.add(new Pair<com.sap.sailing.domain.base.ControlPoint, NauticalSide>(domainControlPoint, null));
}
courseToUpdate.update(newDomainControlPoints, baseDomainFactory);
}
@@ -27,6 +27,7 @@ import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.Bearing;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.TrackedRaceStatusEnum;
@@ -34,6 +35,7 @@ import com.sap.sailing.domain.common.WindSourceType;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.common.impl.WindSourceWithAdditionalID;
import com.sap.sailing.domain.swisstimingadapter.DomainFactory;
import com.sap.sailing.domain.swisstimingreplayadapter.CompetitorStatus;
@@ -289,7 +291,12 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter {
} else {
Course course = race.getCourse();
try {
course.update(currentCourseDefinition, domainFactory.getBaseDomainFactory());
// TODO: Does SwissTiming also deliver the passing side for course marks?
List<Pair<ControlPoint, NauticalSide>> courseToUpdate = new ArrayList<Pair<ControlPoint, NauticalSide>>();
for(ControlPoint cp: currentCourseDefinition) {
courseToUpdate.add(new Pair<ControlPoint, NauticalSide>(cp, null));
}
course.update(courseToUpdate, domainFactory.getBaseDomainFactory());
} catch (PatchFailedException e) {
throw new RuntimeException(e);
}
@@ -19,6 +19,8 @@ import org.junit.Assert;
import org.junit.Before;
import com.maptrack.client.io.TypeController;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.tractracadapter.Receiver;
import com.sap.sailing.domain.tractracadapter.TracTracConnectionConstants;
import com.sap.sailing.domain.tractracadapter.TracTracControlPoint;
@@ -179,6 +181,14 @@ public abstract class AbstractTracTracLiveTest extends StoredTrackBasedTest impl
System.err.println("Error with live data "+arg0);
}
public static Iterable<Pair<TracTracControlPoint, NauticalSide>> getTracTracControlPointsWithPassingSide(Iterable<ControlPoint> controlPoints) {
List<Pair<TracTracControlPoint, NauticalSide>> ttControlPoints = new ArrayList<Pair<TracTracControlPoint, NauticalSide>>();
for (com.tractrac.clientmodule.ControlPoint cp : controlPoints) {
ttControlPoints.add(new Pair<TracTracControlPoint, NauticalSide>(new ControlPointAdapter(cp), null));
}
return ttControlPoints;
}
public static Iterable<TracTracControlPoint> getTracTracControlPoints(Iterable<ControlPoint> controlPoints) {
List<TracTracControlPoint> ttControlPoints = new ArrayList<>();
for (com.tractrac.clientmodule.ControlPoint cp : controlPoints) {
@@ -14,6 +14,7 @@ import java.util.Set;
import org.junit.Test;
import com.sap.sailing.domain.base.ControlPoint;
import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Leg;
@@ -24,7 +25,9 @@ import com.sap.sailing.domain.base.impl.CourseImpl;
import com.sap.sailing.domain.base.impl.MarkImpl;
import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
import com.sap.sailing.domain.base.impl.WaypointImpl;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.TrackedLeg;
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
@@ -171,8 +174,11 @@ public class CourseTest {
assertEquals(3, Util.size(course.getWaypoints()));
assertEquals(2, Util.size(course.getLegs()));
assertWaypointIndexes(course);
course.update(Arrays.asList(wp2.getMarks().iterator().next(), wp3.getMarks().iterator().next(), wp1.getMarks().iterator().next()),
DomainFactory.INSTANCE);
List<Pair<ControlPoint, NauticalSide>> courseToUpdate = new ArrayList<Pair<ControlPoint, NauticalSide>>();
courseToUpdate.add(new Pair<ControlPoint, NauticalSide>(wp2.getMarks().iterator().next(), wp2.getPassingSide()));
courseToUpdate.add(new Pair<ControlPoint, NauticalSide>(wp3.getMarks().iterator().next(), wp3.getPassingSide()));
courseToUpdate.add(new Pair<ControlPoint, NauticalSide>(wp1.getMarks().iterator().next(), wp1.getPassingSide()));
course.update(courseToUpdate, DomainFactory.INSTANCE);
assertWaypointIndexes(course);
}
@@ -177,7 +177,7 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest {
result[0] = zeroBasedIndex == controlPoints.size() && waypointThatGotRemoved.getControlPoint() == cp;
}
});
domainFactory.updateCourseWaypoints(course, getTracTracControlPoints(controlPoints));
domainFactory.updateCourseWaypoints(course, getTracTracControlPointsWithPassingSide(controlPoints));
assertTrue(result[0]);
testLegStructure(1);
}
@@ -202,7 +202,7 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest {
result[0] = zeroBasedIndex == 1 && waypointThatGotRemoved.getControlPoint() == cp;
}
});
domainFactory.updateCourseWaypoints(course, getTracTracControlPoints(controlPoints));
domainFactory.updateCourseWaypoints(course, getTracTracControlPointsWithPassingSide(controlPoints));
assertTrue(result[0]);
testLegStructure(1);
}
@@ -239,7 +239,7 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest {
});
((CourseImpl) course).lockForWrite(); // without the lock it's possible that another race course update removes the additional waypoint again
try {
domainFactory.updateCourseWaypoints(course, getTracTracControlPoints(controlPoints));
domainFactory.updateCourseWaypoints(course, getTracTracControlPointsWithPassingSide(controlPoints));
assertTrue(result[0]);
testLegStructure(3);
} finally {
@@ -269,7 +269,7 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest {
System.out.println("waypointRemoved " + zeroBasedIndex + " / " + waypointThatGotRemoved);
}
});
domainFactory.updateCourseWaypoints(course, getTracTracControlPoints(controlPoints));
domainFactory.updateCourseWaypoints(course, getTracTracControlPointsWithPassingSide(controlPoints));
assertTrue(result[0]);
testLegStructure(3);
}
@@ -102,7 +102,7 @@ public class OfflineSerializationTest extends AbstractSerializationTest {
DomainFactory senderDomainFactory = new DomainFactoryImpl();
DomainFactory receiverDomainFactory = new DomainFactoryImpl();
Mark sendersMark1 = senderDomainFactory.getOrCreateMark("TestBuoy1");
Waypoint sendersWaypoint1 = senderDomainFactory.createWaypoint(sendersMark1);
Waypoint sendersWaypoint1 = senderDomainFactory.createWaypoint(sendersMark1, /*passingSide*/null);
Waypoint receiversWaypoint1 = cloneBySerialization(sendersWaypoint1, receiverDomainFactory);
Waypoint receiversSecondCopyOfWaypoint1 = cloneBySerialization(sendersWaypoint1, receiverDomainFactory);
assertSame(receiversWaypoint1, receiversSecondCopyOfWaypoint1);
@@ -88,7 +88,7 @@ public class RouteAssemblyTest extends AbstractTracTracLiveTest {
}
assertNotNull(firstRoute[0]);
assertNotNull(firstData[0]);
Course course = DomainFactory.INSTANCE.createCourse(firstRoute[0].getName(), getTracTracControlPoints(firstData[0].getPoints()));
Course course = DomainFactory.INSTANCE.createCourse(firstRoute[0].getName(), getTracTracControlPointsWithPassingSide(firstData[0].getPoints()));
assertNotNull(course);
assertEquals("windward-leeward training", course.getName());
assertEquals(3, Util.size(course.getWaypoints()));
@@ -250,9 +250,9 @@ public class WindTest {
Mark startFinishRight = domainFactory.getOrCreateMark("Start/Finish right");
ControlPoint startFinish = domainFactory.createGate(startFinishLeft, startFinishRight, "Start/Finish");
ControlPoint top = domainFactory.getOrCreateMark("Top");
Waypoint w1 = domainFactory.createWaypoint(startFinish);
Waypoint w2 = domainFactory.createWaypoint(top);
Waypoint w3 = domainFactory.createWaypoint(startFinish);
Waypoint w1 = domainFactory.createWaypoint(startFinish, /*passingSide*/ null);
Waypoint w2 = domainFactory.createWaypoint(top, /*passingSide*/ null);
Waypoint w3 = domainFactory.createWaypoint(startFinish, /*passingSide*/ null);
Competitor competitor = new CompetitorImpl(123, "Test Competitor", new TeamImpl("STG", Collections.singleton(
new PersonImpl("Test Competitor", new NationalityImpl("GER"),
/* dateOfBirth */null, "This is famous " + "Test Competitor")), new PersonImpl("Rigo van Maas",
@@ -12,14 +12,15 @@ import java.util.List;
import com.maptrack.client.io.TypeController;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.base.Person;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet;
@@ -57,7 +58,7 @@ public interface DomainFactory {
com.sap.sailing.domain.common.TimePoint createTimePoint(long timestamp);
Course createCourse(String name, Iterable<TracTracControlPoint> controlPoints);
Course createCourse(String name, Iterable<Pair<TracTracControlPoint, NauticalSide>> controlPoints);
com.sap.sailing.domain.base.Competitor getOrCreateCompetitor(Competitor competitor);
@@ -215,7 +216,7 @@ public interface DomainFactory {
* of waypoints. The waypoints are created from the control points and represent usages of the control points
* in a course. A single control point may be used more than once in a course's list of waypoints.
*/
void updateCourseWaypoints(Course courseToUpdate, Iterable<? extends TracTracControlPoint> controlPoints) throws PatchFailedException;
void updateCourseWaypoints(Course courseToUpdate, Iterable<Pair<TracTracControlPoint, NauticalSide>> controlPoints) throws PatchFailedException;
TracTracConfiguration createTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI);
@@ -136,7 +136,11 @@ public class ClientParamsPHP {
return getProperty("Description");
}
public Iterable<ControlPoint> getControlPoints() {
public String getMetadata() {
return getProperty("DataSheet");
}
public List<ControlPoint> getControlPoints() {
List<ControlPoint> result = new ArrayList<>();
int i=1;
String controlPointUUID;
@@ -39,6 +39,7 @@ import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.common.MarkType;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.ScoringSchemeType;
import com.sap.sailing.domain.common.TimePoint;
@@ -129,11 +130,11 @@ public class DomainFactoryImpl implements DomainFactory {
}
@Override
public void updateCourseWaypoints(Course courseToUpdate, Iterable<? extends TracTracControlPoint> controlPoints) throws PatchFailedException {
List<com.sap.sailing.domain.base.ControlPoint> newDomainControlPoints = new ArrayList<com.sap.sailing.domain.base.ControlPoint>();
for (TracTracControlPoint tractracControlPoint : controlPoints) {
com.sap.sailing.domain.base.ControlPoint newDomainControlPoint = getOrCreateControlPoint(tractracControlPoint);
newDomainControlPoints.add(newDomainControlPoint);
public void updateCourseWaypoints(Course courseToUpdate, Iterable<Pair<TracTracControlPoint, NauticalSide>> controlPoints) throws PatchFailedException {
List<Pair<com.sap.sailing.domain.base.ControlPoint, NauticalSide>> newDomainControlPoints = new ArrayList<Pair<com.sap.sailing.domain.base.ControlPoint, NauticalSide>>();
for (Pair<TracTracControlPoint, NauticalSide> tractracControlPoint : controlPoints) {
com.sap.sailing.domain.base.ControlPoint newDomainControlPoint = getOrCreateControlPoint(tractracControlPoint.getA());
newDomainControlPoints.add(new Pair<com.sap.sailing.domain.base.ControlPoint, NauticalSide>(newDomainControlPoint, tractracControlPoint.getB()));
}
courseToUpdate.update(newDomainControlPoints, baseDomainFactory);
}
@@ -209,10 +210,10 @@ public class DomainFactoryImpl implements DomainFactory {
}
@Override
public Course createCourse(String name, Iterable<TracTracControlPoint> controlPoints) {
public Course createCourse(String name, Iterable<Pair<TracTracControlPoint, NauticalSide>> controlPoints) {
List<Waypoint> waypointList = new ArrayList<Waypoint>();
for (TracTracControlPoint controlPoint : controlPoints) {
Waypoint waypoint = baseDomainFactory.createWaypoint(getOrCreateControlPoint(controlPoint));
for (Pair<TracTracControlPoint, NauticalSide> controlPoint: controlPoints) {
Waypoint waypoint = baseDomainFactory.createWaypoint(getOrCreateControlPoint(controlPoint.getA()), controlPoint.getB());
waypointList.add(waypoint);
}
return new CourseImpl(name, waypointList);
@@ -1,7 +1,12 @@
package com.sap.sailing.domain.tractracadapter.impl;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -10,6 +15,9 @@ import com.sap.sailing.domain.base.ControlPoint;
import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
@@ -81,11 +89,18 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<Route, RouteDa
@Override
protected void handleEvent(Triple<Route, RouteData, Race> event) {
System.out.print("R");
List<TracTracControlPoint> ttControlPoints = new ArrayList<>();
Map<Integer, NauticalSide> courseWaypointPassingSides = parseAdditionalCourseDataFromMetadata(event.getA(), event.getB().getPoints());
List<Util.Pair<TracTracControlPoint, NauticalSide>> ttControlPoints = new ArrayList<>();
int i = 1;
for (com.tractrac.clientmodule.ControlPoint cp : event.getB().getPoints()) {
ttControlPoints.add(new ControlPointAdapter(cp));
NauticalSide nauticalSide = courseWaypointPassingSides.containsKey(i) ? courseWaypointPassingSides.get(i) : null;
ttControlPoints.add(new Pair<TracTracControlPoint, NauticalSide>(new ControlPointAdapter(cp), nauticalSide));
i++;
}
Course course = getDomainFactory().createCourse(event.getA().getName(), ttControlPoints);
RaceDefinition existingRaceDefinitionForRace = getDomainFactory().getExistingRaceDefinitionForRace(event.getC());
if (existingRaceDefinitionForRace != null) {
logger.log(Level.INFO, "Received course update for existing race "+event.getC().getName()+": "+
@@ -112,7 +127,50 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<Route, RouteDa
}
}
}
/**
* Parses the route metadata for additional course information
* The 'passing side' for each course waypoint is encoded like this...
* Seq.1=GATE
* Seq.2=PORT
* Seq.3=GATE
* Seq.4=STARBOARD
*/
private Map<Integer, NauticalSide> parseAdditionalCourseDataFromMetadata(Route route,
List<com.tractrac.clientmodule.ControlPoint> controlPoints) {
Map<Integer, NauticalSide> result = new HashMap<Integer, NauticalSide>();;
int controlPointsCount = controlPoints.size();
String routeMetadataString = route.getMetadata() != null ? route.getMetadata().getText() : null;
if(routeMetadataString != null) {
Map<String, String> routeMetadata = parseRouteMetadata(routeMetadataString);
for(int i = 1; i <= controlPointsCount; i++) {
String seqValue = routeMetadata.get("Seq." + i);
com.tractrac.clientmodule.ControlPoint controlPoint = controlPoints.get(i-1);
if(!controlPoint.getHasTwoPoints() && seqValue != null) {
if("PORT".equalsIgnoreCase(seqValue)) {
result.put(i, NauticalSide.PORT);
} else if("STARBOARD".equalsIgnoreCase(seqValue)) {
result.put(i, NauticalSide.STARBOARD);
}
}
}
}
return result;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private Map<String, String> parseRouteMetadata(String routeMetadata) {
Map<String, String> metadataMap = new HashMap<String, String>();
try {
Properties p = new Properties();
p.load(new StringReader(routeMetadata));
metadataMap = new HashMap<String, String>((Map) p);
} catch (IOException e) {
// do nothing
}
return metadataMap;
}
private void createTrackedRace(RaceDefinition race) {
getTrackedRegatta().createTrackedRace(race,
windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind,
@@ -4,14 +4,18 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -28,9 +32,11 @@ import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.TrackedRaceStatusEnum;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.tracking.AbstractRaceTrackerImpl;
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
@@ -256,10 +262,15 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
final ClientParamsPHP clientParams;
try {
clientParams = new ClientParamsPHP(new InputStreamReader(paramURL.openStream()));
List<com.sap.sailing.domain.base.ControlPoint> newCourseControlPoints = new ArrayList<>();
final Iterable<? extends TracTracControlPoint> newTracTracControlPoints = clientParams.getRaceDefaultRoute().getControlPoints();
List<Pair<com.sap.sailing.domain.base.ControlPoint, NauticalSide>> newCourseControlPoints = new ArrayList<>();
final List<? extends TracTracControlPoint> newTracTracControlPoints = clientParams.getRaceDefaultRoute().getControlPoints();
Map<Integer, NauticalSide> passingSideData = parsePassingSideData(clientParams.getRaceDefaultRoute(), newTracTracControlPoints);
int i = 1;
for (TracTracControlPoint newTracTracControlPoint : newTracTracControlPoints) {
newCourseControlPoints.add(domainFactory.getOrCreateControlPoint(newTracTracControlPoint));
NauticalSide nauticalSide = passingSideData.containsKey(i) ? passingSideData.get(i) : null;
newCourseControlPoints.add(new Pair<com.sap.sailing.domain.base.ControlPoint,
NauticalSide>(domainFactory.getOrCreateControlPoint(newTracTracControlPoint), nauticalSide));
i++;
}
List<com.sap.sailing.domain.base.ControlPoint> currentCourseControlPoints = new ArrayList<>();
final Course course = getRaces().iterator().next().getCourse();
@@ -302,6 +313,47 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
}
}
/**
* Parses the route metadata for additional course information
* The 'passing side' for each course waypoint is encoded like this...
* Seq.1=GATE
* Seq.2=PORT
* Seq.3=GATE
* Seq.4=STARBOARD
*/
private Map<Integer, NauticalSide> parsePassingSideData(ClientParamsPHP.Route route, List<? extends TracTracControlPoint> controlPoints) {
Map<Integer, NauticalSide> result = new HashMap<Integer, NauticalSide>();
int controlPointsCount = controlPoints.size();
String routeMetadataString = route.getMetadata();
if(routeMetadataString != null) {
Map<String, String> routeMetadata = parseRouteMetadata(routeMetadataString);
for(int i = 1; i <= controlPointsCount; i++) {
String seqValue = routeMetadata.get("Seq." + i);
TracTracControlPoint controlPoint = controlPoints.get(i-1);
if(!controlPoint.getHasTwoPoints() && seqValue != null) {
if("PORT".equalsIgnoreCase(seqValue)) {
result.put(i, NauticalSide.PORT);
} else if("STARBOARD".equalsIgnoreCase(seqValue)) {
result.put(i, NauticalSide.STARBOARD);
}
}
}
}
return result;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private Map<String, String> parseRouteMetadata(String routeMetadata) {
Map<String, String> metadataMap = new HashMap<String, String>();
try {
Properties p = new Properties();
p.load(new StringReader(routeMetadata));
metadataMap = new HashMap<String, String>((Map) p);
} catch (IOException e) {
// do nothing
}
return metadataMap;
}
private void updateStartStopTimesAndLiveDelay(ClientParamsPHP clientParams, Simulator simulator) {
RaceDefinition currentRace = null;
long delayInMillis = clientParams.getLiveDelayInMillis();
@@ -4,6 +4,8 @@ import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import com.sap.sailing.domain.common.Named;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.impl.Util.Pair;
import difflib.PatchFailedException;
@@ -74,7 +76,7 @@ public interface Course extends Named {
* to the registered {@link CourseListener}s as if {@link #addWaypoint(int, Waypoint)} and {@link #removeWaypoint(int)}
* had been used.
*/
void update(List<? extends ControlPoint> newControlPoints, DomainFactory baseDomainFactory) throws PatchFailedException;
void update(List<Pair<ControlPoint, NauticalSide>> newControlPoints, DomainFactory baseDomainFactory) throws PatchFailedException;
Iterable<Leg> getLegsAdjacentTo(Mark mark);
@@ -7,6 +7,7 @@ import java.util.UUID;
import com.sap.sailing.domain.base.impl.DomainFactoryImpl;
import com.sap.sailing.domain.common.MarkType;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.ScoringSchemeType;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.leaderboard.ScoringScheme;
@@ -61,7 +62,7 @@ public interface DomainFactory {
* The waypoint created is weakly cached so that when requested again by
* {@link #getExistingWaypointById(Waypoint)} it is found.
*/
Waypoint createWaypoint(ControlPoint controlPoint);
Waypoint createWaypoint(ControlPoint controlPoint, NauticalSide passingSide);
Waypoint getExistingWaypointById(Waypoint waypointPrototype);
@@ -21,7 +21,9 @@ import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Leg;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.impl.NamedImpl;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.util.CourseAsWaypointList;
import com.sap.sailing.util.impl.LockUtil;
import com.sap.sailing.util.impl.NamedReentrantReadWriteLock;
@@ -364,7 +366,7 @@ public class CourseImpl extends NamedImpl implements Course {
}
@Override
public void update(List<? extends ControlPoint> newControlPoints, DomainFactory baseDomainFactory) throws PatchFailedException {
public void update(List<Pair<ControlPoint, NauticalSide>> newControlPoints, DomainFactory baseDomainFactory) throws PatchFailedException {
LockUtil.lockForWrite(lock);
try {
Iterable<Waypoint> courseWaypoints = getWaypoints();
@@ -383,12 +385,12 @@ public class CourseImpl extends NamedImpl implements Course {
}
wpl.add(waypoint);
}
for (com.sap.sailing.domain.base.ControlPoint newDomainControlPoint : newControlPoints) {
List<Waypoint> waypoints = existingWaypointsByControlPoint.get(newDomainControlPoint);
for (Pair<ControlPoint, NauticalSide> newDomainControlPoint : newControlPoints) {
List<Waypoint> waypoints = existingWaypointsByControlPoint.get(newDomainControlPoint.getA());
Waypoint waypoint;
if (waypoints == null || waypoints.isEmpty()) {
// must be a new control point for which we don't have a waypoint yet
waypoint = baseDomainFactory.createWaypoint(newDomainControlPoint);
waypoint = baseDomainFactory.createWaypoint(newDomainControlPoint.getA(), newDomainControlPoint.getB());
} else {
waypoint = waypoints.remove(0); // take the first from the list
}
@@ -25,8 +25,10 @@ import com.sap.sailing.domain.base.ObjectInputStreamResolvingAgainstDomainFactor
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.common.MarkType;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.ScoringSchemeType;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.WithID;
import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.leaderboard.impl.HighPoint;
import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOverall;
@@ -169,10 +171,10 @@ public class DomainFactoryImpl implements DomainFactory {
}
@Override
public Waypoint createWaypoint(ControlPoint controlPoint) {
public Waypoint createWaypoint(ControlPoint controlPoint, NauticalSide passingSide) {
synchronized (waypointCache) {
expungeStaleWaypointCacheEntries();
Waypoint result = new WaypointImpl(controlPoint);
Waypoint result = new WaypointImpl(controlPoint, passingSide);
waypointCache.put(result.getId(), new WeakWaypointReference(result));
return result;
}
@@ -5,15 +5,15 @@ import java.util.Date;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.shared.CourseDTO;
import com.sap.sailing.gwt.ui.shared.CoursePositionsDTO;
public class GetCoursePositionsAction extends DefaultAsyncAction<CourseDTO> {
public class GetCoursePositionsAction extends DefaultAsyncAction<CoursePositionsDTO> {
private final SailingServiceAsync sailingService;
private final RegattaAndRaceIdentifier raceIdentifier;
private final Date date;
public GetCoursePositionsAction(SailingServiceAsync sailingService, RegattaAndRaceIdentifier raceIdentifier, Date date,
AsyncCallback<CourseDTO> callback) {
AsyncCallback<CoursePositionsDTO> callback) {
super(callback);
this.sailingService = sailingService;
this.raceIdentifier = raceIdentifier;
@@ -22,6 +22,6 @@ public class GetCoursePositionsAction extends DefaultAsyncAction<CourseDTO> {
@Override
public void execute(AsyncActionsExecutor asyncActionsExecutor) {
sailingService.getCoursePositions(raceIdentifier, date, (AsyncCallback<CourseDTO>) getWrapperCallback(asyncActionsExecutor));
sailingService.getCoursePositions(raceIdentifier, date, (AsyncCallback<CoursePositionsDTO>) getWrapperCallback(asyncActionsExecutor));
}
}
@@ -33,6 +33,8 @@ import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SelectionChangeEvent.Handler;
import com.google.gwt.view.client.SelectionModel;
import com.google.gwt.view.client.SingleSelectionModel;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.gwt.ui.client.DataEntryDialog;
import com.sap.sailing.gwt.ui.client.DataEntryDialog.DialogCallback;
import com.sap.sailing.gwt.ui.client.ErrorReporter;
@@ -42,7 +44,8 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.ControlPointDTO;
import com.sap.sailing.gwt.ui.shared.GateDTO;
import com.sap.sailing.gwt.ui.shared.MarkDTO;
import com.sap.sailing.gwt.ui.shared.RaceCourseMarksDTO;
import com.sap.sailing.gwt.ui.shared.RaceCourseDTO;
import com.sap.sailing.gwt.ui.shared.WaypointDTO;
/**
* A panel that has a race selection (inherited from {@link AbstractRaceManagementPanel}) and which adds a table
@@ -62,12 +65,17 @@ public class RaceCourseManagementPanel extends AbstractRaceManagementPanel {
private final ControlPointDTO controlPoint;
private final MarkDTO oldMark;
private MarkDTO newMark;
public ControlPointAndOldAndNewMark(ControlPointDTO controlPoint, MarkDTO oldMark) {
private NauticalSide passingSide;
public ControlPointAndOldAndNewMark(ControlPointDTO controlPoint, NauticalSide passingSide, MarkDTO oldMark) {
super();
this.controlPoint = controlPoint;
this.passingSide = passingSide;
this.oldMark = oldMark;
this.newMark = oldMark;
}
public NauticalSide getPassingSide() {
return passingSide;
}
public MarkDTO getNewMark() {
return newMark;
}
@@ -215,8 +223,19 @@ public class RaceCourseManagementPanel extends AbstractRaceManagementPanel {
public String getValue(ControlPointAndOldAndNewMark cpaoanb) {
return cpaoanb.getControlPoint().name;
}
};
};
controlPointsTable.addColumn(nameColumn, stringMessages.controlPoint());
TextColumn<ControlPointAndOldAndNewMark> passingSideColumn = new TextColumn<ControlPointAndOldAndNewMark>() {
@Override
public String getValue(ControlPointAndOldAndNewMark cpaoanb) {
String result = "";
if(cpaoanb.getPassingSide() != null) {
result = cpaoanb.getPassingSide().name();
}
return result;
}
};
controlPointsTable.addColumn(passingSideColumn, "Passing side");
TextColumn<ControlPointAndOldAndNewMark> oldMarkColumn = new TextColumn<ControlPointAndOldAndNewMark>() {
@Override
public String getValue(ControlPointAndOldAndNewMark cpaoanb) {
@@ -326,7 +345,7 @@ public class RaceCourseManagementPanel extends AbstractRaceManagementPanel {
private void saveCourse(SailingServiceAsync sailingService, final StringMessages stringMessages) {
Set<ControlPointDTO> oldControlPointsFromTableAlreadyHandled = new HashSet<ControlPointDTO>();
List<ControlPointDTO> controlPoints = new ArrayList<ControlPointDTO>();
List<Pair<ControlPointDTO, NauticalSide>> controlPoints = new ArrayList<Pair<ControlPointDTO, NauticalSide>>();
for (ControlPointAndOldAndNewMark cpaoanb : controlPointDataProvider.getList()) {
if (!oldControlPointsFromTableAlreadyHandled.contains(cpaoanb.getControlPoint())) {
oldControlPointsFromTableAlreadyHandled.add(cpaoanb.getControlPoint());
@@ -340,7 +359,7 @@ public class RaceCourseManagementPanel extends AbstractRaceManagementPanel {
} else {
controlPointToAdd = cpaoanb.getControlPoint();
}
controlPoints.add(controlPointToAdd);
controlPoints.add(new Pair<ControlPointDTO, NauticalSide>(controlPointToAdd, cpaoanb.passingSide));
}
}
sailingService.updateRaceCourse(singleSelectedRace, controlPoints, new AsyncCallback<Void>() {
@@ -396,7 +415,9 @@ public class RaceCourseManagementPanel extends AbstractRaceManagementPanel {
@Override
public SafeHtml getValue(MarkDTO mark) {
SafeHtmlBuilder builder = new SafeHtmlBuilder();
builder.appendEscaped(mark.position.toFormattedString());
if(mark.position != null) {
builder.appendEscaped(mark.position.toFormattedString());
}
return builder.toSafeHtml();
}
};
@@ -480,7 +501,7 @@ public class RaceCourseManagementPanel extends AbstractRaceManagementPanel {
ControlPointAndOldAndNewMark selectedElement = selectedElements.iterator().next();
int insertPos = controlPointDataProvider.getList().indexOf(selectedElement) + (beforeSelection?0:1);
for (MarkDTO markDTO : result.getMarks()) {
controlPointDataProvider.getList().add(insertPos++, new ControlPointAndOldAndNewMark(result, markDTO));
controlPointDataProvider.getList().add(insertPos++, new ControlPointAndOldAndNewMark(result, null, markDTO));
}
}
}
@@ -491,27 +512,17 @@ public class RaceCourseManagementPanel extends AbstractRaceManagementPanel {
void refreshSelectedRaceData() {
if (singleSelectedRace != null && selectedRaceDTO != null) {
courseActionsPanel.setVisible(true);
sailingService.getRaceCourse(singleSelectedRace, new Date(), new AsyncCallback<List<ControlPointDTO>>() {
sailingService.getRaceCourse(singleSelectedRace, new Date(), new AsyncCallback<RaceCourseDTO>() {
@Override
public void onSuccess(final List<ControlPointDTO> controlPoints) {
sailingService.getRaceCourseMarks(singleSelectedRace, new Date(), new AsyncCallback<RaceCourseMarksDTO>() {
@Override
public void onSuccess(RaceCourseMarksDTO raceCourseMarksDTO) {
updateCourseAndMarksInfo(controlPoints, raceCourseMarksDTO);
}
@Override
public void onFailure(Throwable caught) {
RaceCourseManagementPanel.this.errorReporter.reportError(
RaceCourseManagementPanel.this.stringMessages.errorTryingToObtainTheMarksOfTheRace(
caught.getMessage()));
}
});
public void onSuccess(RaceCourseDTO raceCourseDTO) {
updateCourseAndMarksInfo(raceCourseDTO);
}
@Override
public void onFailure(Throwable caught) {
RaceCourseManagementPanel.this.errorReporter.reportError(stringMessages.errorTryingToObtainRaceCourse(caught.getMessage()));
RaceCourseManagementPanel.this.errorReporter.reportError(
RaceCourseManagementPanel.this.stringMessages.errorTryingToObtainTheMarksOfTheRace(
caught.getMessage()));
}
});
} else {
@@ -519,11 +530,12 @@ public class RaceCourseManagementPanel extends AbstractRaceManagementPanel {
}
}
private void updateCourseAndMarksInfo(List<ControlPointDTO> controlPoints, RaceCourseMarksDTO marksDTO) {
private void updateCourseAndMarksInfo(RaceCourseDTO raceCourseDTO) {
List<ControlPointAndOldAndNewMark> waypointsAndOldAndNewMarks = new ArrayList<ControlPointAndOldAndNewMark>();
for (ControlPointDTO controlPointDTO : controlPoints) {
for (WaypointDTO waypointDTO : raceCourseDTO.waypoints) {
ControlPointDTO controlPointDTO = waypointDTO.controlPoint;
for (MarkDTO mark : controlPointDTO.getMarks()) {
ControlPointAndOldAndNewMark waypointAndOldAndNewMark = new ControlPointAndOldAndNewMark(controlPointDTO, mark);
ControlPointAndOldAndNewMark waypointAndOldAndNewMark = new ControlPointAndOldAndNewMark(controlPointDTO, waypointDTO.passingSide, mark);
waypointsAndOldAndNewMarks.add(waypointAndOldAndNewMark);
}
}
@@ -531,7 +543,7 @@ public class RaceCourseManagementPanel extends AbstractRaceManagementPanel {
controlPointDataProvider.getList().addAll(waypointsAndOldAndNewMarks);
controlPointsNeedingReplacement.clear();
markDataProvider.getList().clear();
markDataProvider.getList().addAll(marksDTO.marks);
markDataProvider.getList().addAll(raceCourseDTO.getMarks());
Collections.sort(markDataProvider.getList(), new Comparator<MarkDTO>() {
@Override
public int compare(MarkDTO o1, MarkDTO o2) {
@@ -41,7 +41,7 @@ import com.sap.sailing.gwt.ui.client.RegattaDisplayer;
import com.sap.sailing.gwt.ui.client.RegattaRefresher;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.CourseDTO;
import com.sap.sailing.gwt.ui.shared.CoursePositionsDTO;
import com.sap.sailing.gwt.ui.shared.RaceDTO;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.WindDTO;
@@ -109,14 +109,14 @@ public class WindPanel extends FormPanel implements RegattaDisplayer, WindShower
RegattaAndRaceIdentifier selectedRace = getSelectedRace();
if(selectedRace != null) {
final RaceDTO race = trackedRacesListComposite.getRaceByIdentifier(selectedRace);
sailingService.getCoursePositions(selectedRace, race.startOfRace, new AsyncCallback<CourseDTO>() {
sailingService.getCoursePositions(selectedRace, race.startOfRace, new AsyncCallback<CoursePositionsDTO>() {
@Override
public void onFailure(Throwable caught) {
showWindSettingDialog(race, null);
}
@Override
public void onSuccess(final CourseDTO result) {
public void onSuccess(final CoursePositionsDTO result) {
showWindSettingDialog(race, result);
}
});
@@ -214,7 +214,7 @@ public class WindPanel extends FormPanel implements RegattaDisplayer, WindShower
windFixesDisplayPanel.add(rawWindFixesTable);
}
private void showWindSettingDialog(RaceDTO race, CourseDTO course) {
private void showWindSettingDialog(RaceDTO race, CoursePositionsDTO course) {
WindSettingDialog windSettingDialog = new WindSettingDialog(race, course, stringMessages,
new DialogCallback<WindDTO>() {
@Override
@@ -8,7 +8,7 @@ import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.datepicker.client.DateBox;
import com.sap.sailing.gwt.ui.client.DataEntryDialog;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.CourseDTO;
import com.sap.sailing.gwt.ui.shared.CoursePositionsDTO;
import com.sap.sailing.gwt.ui.shared.PositionDTO;
import com.sap.sailing.gwt.ui.shared.RaceDTO;
import com.sap.sailing.gwt.ui.shared.WindDTO;
@@ -54,7 +54,7 @@ public class WindSettingDialog extends DataEntryDialog<WindDTO> {
}
}
public WindSettingDialog(RaceDTO race, CourseDTO courseDTO, StringMessages stringMessages, DialogCallback<WindDTO> callback) {
public WindSettingDialog(RaceDTO race, CoursePositionsDTO courseDTO, StringMessages stringMessages, DialogCallback<WindDTO> callback) {
super(stringMessages.actionAddWindData(), null, stringMessages.ok(), stringMessages.cancel(), new WindDataValidator(stringMessages), callback);
this.stringMessages = stringMessages;
speedInKnotsBox = createDoubleBox(5);
@@ -13,6 +13,7 @@ import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
import com.sap.sailing.domain.common.Color;
import com.sap.sailing.domain.common.DetailType;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.PolarSheetGenerationTriggerResponse;
import com.sap.sailing.domain.common.PolarSheetsData;
@@ -27,7 +28,7 @@ import com.sap.sailing.gwt.ui.shared.BulkScoreCorrectionDTO;
import com.sap.sailing.gwt.ui.shared.CompetitorDTO;
import com.sap.sailing.gwt.ui.shared.CompetitorsRaceDataDTO;
import com.sap.sailing.gwt.ui.shared.ControlPointDTO;
import com.sap.sailing.gwt.ui.shared.CourseDTO;
import com.sap.sailing.gwt.ui.shared.CoursePositionsDTO;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sailing.gwt.ui.shared.GPSFixDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
@@ -35,7 +36,7 @@ import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.ManeuverDTO;
import com.sap.sailing.gwt.ui.shared.QuickRankDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnInSeriesDTO;
import com.sap.sailing.gwt.ui.shared.RaceCourseMarksDTO;
import com.sap.sailing.gwt.ui.shared.RaceCourseDTO;
import com.sap.sailing.gwt.ui.shared.RaceDTO;
import com.sap.sailing.gwt.ui.shared.RaceMapDataDTO;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
@@ -108,9 +109,9 @@ public interface SailingService extends RemoteService {
List<RaceTimesInfoDTO> getRaceTimesInfos(Collection<RegattaAndRaceIdentifier> raceIdentifiers);
CourseDTO getCoursePositions(RegattaAndRaceIdentifier raceIdentifier, Date date);
CoursePositionsDTO getCoursePositions(RegattaAndRaceIdentifier raceIdentifier, Date date);
List<ControlPointDTO> getRaceCourse(RegattaAndRaceIdentifier raceIdentifier, Date date);
RaceCourseDTO getRaceCourse(RegattaAndRaceIdentifier raceIdentifier, Date date);
List<QuickRankDTO> getQuickRanks(RegattaAndRaceIdentifier raceIdentifier, Date date) throws NoWindException;
@@ -263,9 +264,7 @@ public interface SailingService extends RemoteService {
Void updateLeaderboardScoreCorrectionMetadata(String leaderboardName, Date timePointOfLastCorrectionValidity,
String comment);
RaceCourseMarksDTO getRaceCourseMarks(RegattaAndRaceIdentifier raceIdentifier, Date date);
void updateRaceCourse(RegattaAndRaceIdentifier raceIdentifier, List<ControlPointDTO> controlPoints);
void updateRaceCourse(RegattaAndRaceIdentifier raceIdentifier, List<Pair<ControlPointDTO, NauticalSide>> controlPoints);
void addColumnsToLeaderboard(String leaderboardName, List<Pair<String, Boolean>> columnsToAdd);
@@ -12,6 +12,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sailing.domain.common.Color;
import com.sap.sailing.domain.common.DetailType;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.PolarSheetGenerationTriggerResponse;
import com.sap.sailing.domain.common.PolarSheetsData;
import com.sap.sailing.domain.common.PolarSheetsHistogramData;
@@ -27,7 +28,7 @@ import com.sap.sailing.gwt.ui.shared.BulkScoreCorrectionDTO;
import com.sap.sailing.gwt.ui.shared.CompetitorDTO;
import com.sap.sailing.gwt.ui.shared.CompetitorsRaceDataDTO;
import com.sap.sailing.gwt.ui.shared.ControlPointDTO;
import com.sap.sailing.gwt.ui.shared.CourseDTO;
import com.sap.sailing.gwt.ui.shared.CoursePositionsDTO;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sailing.gwt.ui.shared.GPSFixDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
@@ -36,7 +37,7 @@ import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.ManeuverDTO;
import com.sap.sailing.gwt.ui.shared.QuickRankDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnInSeriesDTO;
import com.sap.sailing.gwt.ui.shared.RaceCourseMarksDTO;
import com.sap.sailing.gwt.ui.shared.RaceCourseDTO;
import com.sap.sailing.gwt.ui.shared.RaceDTO;
import com.sap.sailing.gwt.ui.shared.RaceMapDataDTO;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
@@ -174,7 +175,7 @@ public interface SailingServiceAsync {
void getRaceTimesInfos(Collection<RegattaAndRaceIdentifier> raceIdentifiers, AsyncCallback<List<RaceTimesInfoDTO>> callback);
void getCoursePositions(RegattaAndRaceIdentifier raceIdentifier, Date date, AsyncCallback<CourseDTO> asyncCallback);
void getCoursePositions(RegattaAndRaceIdentifier raceIdentifier, Date date, AsyncCallback<CoursePositionsDTO> asyncCallback);
void getQuickRanks(RegattaAndRaceIdentifier raceIdentifier, Date date, AsyncCallback<List<QuickRankDTO>> callback);
@@ -394,9 +395,9 @@ public interface SailingServiceAsync {
void getWindSourcesInfo(RegattaAndRaceIdentifier raceIdentifier, AsyncCallback<WindInfoForRaceDTO> callback);
void getRaceCourse(RegattaAndRaceIdentifier raceIdentifier, Date date, AsyncCallback<List<ControlPointDTO>> callback);
void getRaceCourse(RegattaAndRaceIdentifier raceIdentifier, Date date, AsyncCallback<RaceCourseDTO> callback);
void updateRaceCourse(RegattaAndRaceIdentifier raceIdentifier, List<ControlPointDTO> controlPoints, AsyncCallback<Void> callback);
void updateRaceCourse(RegattaAndRaceIdentifier raceIdentifier, List<Pair<ControlPointDTO, NauticalSide>> controlPoints, AsyncCallback<Void> callback);
void getFregResultUrls(AsyncCallback<List<String>> asyncCallback);
@@ -404,8 +405,6 @@ public interface SailingServiceAsync {
void addFragUrl(String result, AsyncCallback<Void> asyncCallback);
void getRaceCourseMarks(RegattaAndRaceIdentifier raceIdentifier, Date date, AsyncCallback<RaceCourseMarksDTO> callback);
void addColumnsToLeaderboard(String leaderboardName, List<Pair<String, Boolean>> columnsToAdd,
AsyncCallback<Void> callback);
@@ -444,4 +443,5 @@ public interface SailingServiceAsync {
void getPolarSheetsGenerationResults(String id, AsyncCallback<PolarSheetsData> asyncCallback);
void getPolarSheetData(String polarSheetId, int angle, int windSpeed, AsyncCallback<PolarSheetsHistogramData> wrapperCallback);
}
@@ -74,6 +74,7 @@ import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.LegType;
import com.sap.sailing.domain.common.ManeuverType;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.NoWindError;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.Placemark;
@@ -157,7 +158,7 @@ import com.sap.sailing.gwt.ui.shared.CompetitorDTO;
import com.sap.sailing.gwt.ui.shared.CompetitorRaceDataDTO;
import com.sap.sailing.gwt.ui.shared.CompetitorsRaceDataDTO;
import com.sap.sailing.gwt.ui.shared.ControlPointDTO;
import com.sap.sailing.gwt.ui.shared.CourseDTO;
import com.sap.sailing.gwt.ui.shared.CoursePositionsDTO;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sailing.gwt.ui.shared.FleetDTO;
import com.sap.sailing.gwt.ui.shared.GPSFixDTO;
@@ -178,7 +179,7 @@ import com.sap.sailing.gwt.ui.shared.PositionDTO;
import com.sap.sailing.gwt.ui.shared.QuickRankDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnInSeriesDTO;
import com.sap.sailing.gwt.ui.shared.RaceCourseMarksDTO;
import com.sap.sailing.gwt.ui.shared.RaceCourseDTO;
import com.sap.sailing.gwt.ui.shared.RaceDTO;
import com.sap.sailing.gwt.ui.shared.RaceMapDataDTO;
import com.sap.sailing.gwt.ui.shared.RaceStatusDTO;
@@ -202,6 +203,7 @@ import com.sap.sailing.gwt.ui.shared.TracTracConfigurationDTO;
import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDTO;
import com.sap.sailing.gwt.ui.shared.TrackedRaceDTO;
import com.sap.sailing.gwt.ui.shared.VenueDTO;
import com.sap.sailing.gwt.ui.shared.WaypointDTO;
import com.sap.sailing.gwt.ui.shared.WindDTO;
import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO;
import com.sap.sailing.gwt.ui.shared.WindTrackInfoDTO;
@@ -1020,7 +1022,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
private MarkDTO convertToMarkDTO(Mark mark, Position position) {
MarkDTO markDTO = new MarkDTO(mark.getId().toString(), mark.getName(), position.getLatDeg(), position.getLngDeg());
MarkDTO markDTO;
if(position != null) {
markDTO = new MarkDTO(mark.getId().toString(), mark.getName(), position.getLatDeg(), position.getLngDeg());
} else {
markDTO = new MarkDTO(mark.getId().toString(), mark.getName());
}
markDTO.color = mark.getColor();
markDTO.shape = mark.getShape();
markDTO.pattern = mark.getPattern();
@@ -1700,8 +1707,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
@Override
public CourseDTO getCoursePositions(RegattaAndRaceIdentifier raceIdentifier, Date date) {
CourseDTO result = new CourseDTO();
public CoursePositionsDTO getCoursePositions(RegattaAndRaceIdentifier raceIdentifier, Date date) {
CoursePositionsDTO result = new CoursePositionsDTO();
if (date != null) {
TimePoint dateAsTimePoint = new MillisecondsTimePoint(date);
TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier);
@@ -1740,43 +1747,33 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
return result;
}
@Override
public RaceCourseMarksDTO getRaceCourseMarks(RegattaAndRaceIdentifier raceIdentifier, Date date) {
RaceCourseMarksDTO raceMarksDTO = new RaceCourseMarksDTO();
TimePoint dateAsTimePoint = new MillisecondsTimePoint(date);
TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier);
if (trackedRace != null) {
raceMarksDTO.marks = new HashSet<MarkDTO>();
Iterable<Mark> marks = trackedRace.getMarks();
for (Mark mark : marks) {
GPSFixTrack<Mark, GPSFix> track = trackedRace.getOrCreateTrack(mark);
Position positionAtDate = track.getEstimatedPosition(dateAsTimePoint, /* extrapolate */false);
if (positionAtDate != null) {
raceMarksDTO.marks.add(convertToMarkDTO(mark, positionAtDate));
}
}
}
return raceMarksDTO;
}
@Override
public List<ControlPointDTO> getRaceCourse(RegattaAndRaceIdentifier raceIdentifier, Date date) {
List<ControlPointDTO> result = new ArrayList<ControlPointDTO>();
public RaceCourseDTO getRaceCourse(RegattaAndRaceIdentifier raceIdentifier, Date date) {
List<WaypointDTO> waypointDTOs = new ArrayList<WaypointDTO>();
RaceCourseDTO result = new RaceCourseDTO(waypointDTOs);
if (date != null) {
TimePoint dateAsTimePoint = new MillisecondsTimePoint(date);
TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier);
if (trackedRace != null) {
Course course = trackedRace.getRace().getCourse();
for (Waypoint waypoint : course.getWaypoints()) {
result.add(createControlPointDTO(waypoint.getControlPoint(), trackedRace, dateAsTimePoint));
List<MarkDTO> markDTOs = new ArrayList<MarkDTO>();
for (Mark mark : trackedRace.getMarks()) {
GPSFixTrack<Mark, GPSFix> track = trackedRace.getOrCreateTrack(mark);
Position positionAtDate = track.getEstimatedPosition(dateAsTimePoint, /* extrapolate */false);
markDTOs.add(convertToMarkDTO(mark, positionAtDate));
}
ControlPointDTO controlPointDTO = convertToControlPointDTO(waypoint.getControlPoint(), trackedRace, dateAsTimePoint);
WaypointDTO waypointDTO = new WaypointDTO(waypoint.getName(), controlPointDTO, markDTOs, waypoint.getPassingSide());
waypointDTOs.add(waypointDTO);
}
}
}
return result;
}
private ControlPointDTO createControlPointDTO(ControlPoint controlPoint, TrackedRace trackedRace, TimePoint timePoint) {
private ControlPointDTO convertToControlPointDTO(ControlPoint controlPoint, TrackedRace trackedRace, TimePoint timePoint) {
ControlPointDTO result;
if (controlPoint instanceof Gate) {
final Mark left = ((Gate) controlPoint).getLeft();
@@ -1801,21 +1798,22 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
* the course of the race identified by <code>raceIdentifier</code>.
*/
@Override
public void updateRaceCourse(RegattaAndRaceIdentifier raceIdentifier, List<ControlPointDTO> controlPoints) {
public void updateRaceCourse(RegattaAndRaceIdentifier raceIdentifier, List<Pair<ControlPointDTO, NauticalSide>> controlPoints) {
TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier);
if (trackedRace != null) {
Course course = trackedRace.getRace().getCourse();
Iterable<Waypoint> waypoints = course.getWaypoints();
List<ControlPoint> newControlPoints = new ArrayList<ControlPoint>();
List<Pair<ControlPoint, NauticalSide>> newControlPoints = new ArrayList<Pair<ControlPoint, NauticalSide>>();
int lastMatchPosition = -1;
for (ControlPointDTO controlPointDTO : controlPoints) {
for (Pair<ControlPointDTO, NauticalSide> controlPointAndPassingSide : controlPoints) {
ControlPointDTO controlPointDTO = controlPointAndPassingSide.getA();
ControlPoint matchFromOldCourse = null;
for (int i=lastMatchPosition+1; matchFromOldCourse == null && i<Util.size(waypoints); i++) {
Waypoint waypointAtI = Util.get(waypoints, i);
ControlPoint controlPointAtI = waypointAtI.getControlPoint();
if (controlPointAtI.getId().toString().equals(controlPointDTO.getIdAsString()) && markIDsMatch(controlPointAtI.getMarks(), controlPointDTO.getMarks())) {
matchFromOldCourse = controlPointAtI;
newControlPoints.add(matchFromOldCourse);
newControlPoints.add(new Pair<ControlPoint, NauticalSide>(matchFromOldCourse, null));
lastMatchPosition = i;
}
}
@@ -1833,10 +1831,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
Mark left = baseDomainFactory.getOrCreateMark(gateDTO.getLeft().getIdAsString(), gateDTO.getLeft().name);
Mark right = baseDomainFactory.getOrCreateMark(gateDTO.getRight().getIdAsString(), gateDTO.getRight().name);
newControlPoint = baseDomainFactory.createGate(id, left, right, gateDTO.name);
newControlPoints.add(new Pair<ControlPoint, NauticalSide>(newControlPoint, null));
} else {
newControlPoint = baseDomainFactory.getOrCreateMark(controlPointDTO.getIdAsString(), controlPointDTO.name);
NauticalSide nauticalSide = controlPointAndPassingSide.getB();
newControlPoints.add(new Pair<ControlPoint, NauticalSide>(newControlPoint, nauticalSide));
}
newControlPoints.add(newControlPoint);
}
}
try {
@@ -5,7 +5,7 @@ import java.util.Set;
import com.google.gwt.user.client.rpc.IsSerializable;
public class CourseDTO implements IsSerializable {
public class CoursePositionsDTO implements IsSerializable {
public List<PositionDTO> waypointPositions;
public List<PositionDTO> startMarkPositions;
public List<PositionDTO> finishMarkPositions;
@@ -18,6 +18,10 @@ public class MarkDTO extends ControlPointDTO {
this.position = new PositionDTO(latDeg, lngDeg);
}
public MarkDTO(String idAsString, String name) {
super(idAsString, name);
}
@Override
public Iterable<MarkDTO> getMarks() {
return Collections.singleton(this);
@@ -0,0 +1,39 @@
package com.sap.sailing.gwt.ui.shared;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gwt.user.client.rpc.IsSerializable;
public class RaceCourseDTO implements IsSerializable {
public List<WaypointDTO> waypoints;
RaceCourseDTO() {}
public RaceCourseDTO(List<WaypointDTO> waypoints) {
this.waypoints = waypoints;
}
public List<ControlPointDTO> getControlPoints() {
List<ControlPointDTO> controlPoints = new ArrayList<ControlPointDTO>();
for(WaypointDTO waypoint: waypoints) {
controlPoints.add(waypoint.controlPoint);
}
return controlPoints;
}
public Collection<MarkDTO> getMarks() {
Map<String, MarkDTO> marks = new HashMap<String, MarkDTO>();
for(WaypointDTO waypoint: waypoints) {
for(MarkDTO mark: waypoint.marks) {
if(!marks.containsKey(mark.name)) {
marks.put(mark.name, mark);
}
}
}
return marks.values();
}
}
@@ -1,9 +0,0 @@
package com.sap.sailing.gwt.ui.shared;
import java.util.Set;
import com.google.gwt.user.client.rpc.IsSerializable;
public class RaceCourseMarksDTO implements IsSerializable {
public Set<MarkDTO> marks;
}
@@ -7,7 +7,7 @@ import com.google.gwt.user.client.rpc.IsSerializable;
public class RaceMapDataDTO implements IsSerializable {
public Map<CompetitorDTO, List<GPSFixDTO>> boatPositions;
public CourseDTO coursePositions;
public CoursePositionsDTO coursePositions;
public List<QuickRankDTO> quickRanks;
public BoatClassDTO boatClass;
}
@@ -2,45 +2,22 @@ package com.sap.sailing.gwt.ui.shared;
import java.util.List;
import com.sap.sailing.domain.common.NauticalSide;
public class WaypointDTO extends NamedDTO {
public List<MarkDTO> marks;
public int courseIndex;
public int markPassingsCount;
public ControlPointDTO controlPoint;
public WaypointDTO() {}
public NauticalSide passingSide;
public WaypointDTO(String name, int courseIndex) {
WaypointDTO() {}
public WaypointDTO(String name, ControlPointDTO controlPoint, List<MarkDTO> marks, NauticalSide passingSide) {
super(name);
this.courseIndex = courseIndex;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + courseIndex;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
WaypointDTO other = (WaypointDTO) obj;
if (courseIndex != other.courseIndex)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
this.name = name;
this.marks = marks;
this.controlPoint = controlPoint;
this.passingSide = passingSide;
}
}
@@ -73,7 +73,7 @@ import com.sap.sailing.gwt.ui.client.Timer;
import com.sap.sailing.gwt.ui.client.Timer.PlayStates;
import com.sap.sailing.gwt.ui.client.WindSourceTypeFormatter;
import com.sap.sailing.gwt.ui.shared.CompetitorDTO;
import com.sap.sailing.gwt.ui.shared.CourseDTO;
import com.sap.sailing.gwt.ui.shared.CoursePositionsDTO;
import com.sap.sailing.gwt.ui.shared.GPSFixDTO;
import com.sap.sailing.gwt.ui.shared.LegInfoDTO;
import com.sap.sailing.gwt.ui.shared.ManeuverDTO;
@@ -549,7 +549,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
}
}
protected void showCourseMarksOnMap(CourseDTO courseDTO) {
protected void showCourseMarksOnMap(CoursePositionsDTO courseDTO) {
if (map != null && courseDTO != null) {
Map<String, CourseMarkOverlay> toRemoveCourseMarks = new HashMap<String, CourseMarkOverlay>(courseMarkOverlays);
if (courseDTO.marks != null) {
@@ -822,7 +822,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
}
}
private void showStartAndFinishLines(final CourseDTO courseDTO) {
private void showStartAndFinishLines(final CoursePositionsDTO courseDTO) {
if (map != null && courseDTO != null && lastRaceTimesInfo != null) {
Pair<Integer, CompetitorDTO> leadingVisibleCompetitorInfo = getLeadingVisibleCompetitorInfo(getCompetitorsToShow());
int legOfLeadingCompetitor = leadingVisibleCompetitorInfo == null ? -1 : leadingVisibleCompetitorInfo.getA();
@@ -88,9 +88,9 @@ public class ServerReplicationTest extends AbstractServerReplicationTest {
new ArrayList<Competitor>());
AddRaceDefinition addRaceOperation = new AddRaceDefinition(new RegattaName(regatta.getName()), race);
master.apply(addRaceOperation);
masterCourse.addWaypoint(0, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark1")));
masterCourse.addWaypoint(1, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark2")));
masterCourse.addWaypoint(2, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark3")));
masterCourse.addWaypoint(0, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark1"), /*passingSide*/ null));
masterCourse.addWaypoint(1, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark2"), /*passingSide*/ null));
masterCourse.addWaypoint(2, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark3"), /*passingSide*/ null));
masterCourse.removeWaypoint(1);
Thread.sleep(3000); // wait 1s for JMS to deliver the message and the message to be applied
Regatta replicaEvent = replica.getRegatta(new RegattaName(regatta.getName()));
@@ -81,9 +81,9 @@ public class TrackedRaceContentsReplicationTest extends AbstractServerReplicatio
RaceDefinition race = new RaceDefinitionImpl(raceName, masterCourse, boatClass, Collections.singletonList(competitor));
AddRaceDefinition addRaceOperation = new AddRaceDefinition(new RegattaName(regatta.getName()), race);
master.apply(addRaceOperation);
masterCourse.addWaypoint(0, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark1")));
masterCourse.addWaypoint(1, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark2")));
masterCourse.addWaypoint(2, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark3")));
masterCourse.addWaypoint(0, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark1"), /*passingSide*/ null));
masterCourse.addWaypoint(1, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark2"), /*passingSide*/ null));
masterCourse.addWaypoint(2, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark3"), /*passingSide*/ null));
masterCourse.removeWaypoint(1);
raceIdentifier = new RegattaNameAndRaceName(regatta.getName(), raceName);
trackedRegatta = master.apply(new TrackRegatta(raceIdentifier));