Merge branch 'racecommittee_app' into racecommittee_wind

Conflicts:
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties
This commit is contained in:
Armin Zamani committed 2013-07-04 14:25:05 +02:00
commit 4b40d90fd0
73 files changed
+1593 -270

No files matched your search

@@ -0,0 +1,13 @@
package com.sap.sailing.domain.base;
import com.sap.sailing.domain.common.Named;
import com.sap.sailing.domain.common.WithID;
/**
* A side line in a race course
* @author Frank (C5163874)
*
*/
public interface Sideline extends Named, WithID {
Iterable<Mark> getMarks();
}
@@ -0,0 +1,40 @@
package com.sap.sailing.domain.base.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.common.impl.NamedImpl;
import com.sap.sailing.domain.common.impl.Util;
public class SidelineImpl extends NamedImpl implements Sideline {
private static final long serialVersionUID = -8145721464971358691L;
private final List<Mark> marks;
private static int idCounter = 1;
private final int id;
public SidelineImpl(String name, Iterable<Mark> marks) {
super(name);
List<Mark> myMarks = new ArrayList<Mark>();
Util.addAll(marks, myMarks);
this.marks = Collections.unmodifiableList(myMarks);
id = idCounter++;
}
@Override
public String toString() {
return getName();
}
@Override
public Iterable<Mark> getMarks() {
return marks;
}
@Override
public Integer getId() {
return id;
}
}
@@ -17,6 +17,7 @@ import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.Distance;
@@ -347,7 +348,7 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl implemen
// now we can create the RaceDefinition and most other things
Race swissTimingRace = messageLoader.getRace(raceID);
race = domainFactory.createRaceDefinition(regatta, swissTimingRace, startList, course);
trackedRace = getTrackedRegatta().createTrackedRace(race, windStore, delayToLiveInMillis,
trackedRace = getTrackedRegatta().createTrackedRace(race, Collections.<Sideline> emptyList(), windStore, delayToLiveInMillis,
WindTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_WIND,
/* time over which to average speed */ race.getBoatClass().getApproximateManeuverDurationInMilliseconds(),
new DynamicRaceDefinitionSet() {
@@ -21,6 +21,7 @@ import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.SpeedWithBearing;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl;
@@ -313,7 +314,7 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter {
currentRaceID, competitorsPerRaceID.get(currentRaceID), currentCourseDefinition);
racePerRaceID.put(currentRaceID, race);
DynamicTrackedRace trackedRace = trackedRegattaRegistry.getOrCreateTrackedRegatta(myRegatta).
createTrackedRace(race, EmptyWindStore.INSTANCE, TrackedRace.DEFAULT_LIVE_DELAY_IN_MILLISECONDS,
createTrackedRace(race, Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE, TrackedRace.DEFAULT_LIVE_DELAY_IN_MILLISECONDS,
WindTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_WIND,
/* time over which to average speed: */ race.getBoatClass().getApproximateManeuverDurationInMilliseconds(),
/* raceDefinitionSetToUpdate */ null);
@@ -18,6 +18,7 @@ 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;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.CompetitorImpl;
@@ -246,7 +247,7 @@ public class CourseTest {
final Set<CompetitorImpl> hasso = Collections.singleton(AbstractLeaderboardTest.createCompetitor("Hasso"));
DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(/* trackedRegatta */ null,
new RaceDefinitionImpl("Test Race", course, new BoatClassImpl("49er", /* upwind start */ true),
hasso),
hasso), Collections.<Sideline> emptyList(),
EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 3000,
/* millisecondsOverWhichToAverageWind */ 30000,
/* millisecondsOverWhichToAverageSpeed */ 8000);
@@ -276,7 +277,7 @@ public class CourseTest {
final Set<CompetitorImpl> hasso = Collections.singleton(AbstractLeaderboardTest.createCompetitor("Hasso"));
DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(/* trackedRegatta */ null,
new RaceDefinitionImpl("Test Race", course, new BoatClassImpl("49er", /* upwind start */ true),
hasso),
hasso), Collections.<Sideline> emptyList(),
EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 3000,
/* millisecondsOverWhichToAverageWind */ 30000,
/* millisecondsOverWhichToAverageSpeed */ 8000);
@@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
@@ -18,6 +19,7 @@ import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.CompetitorImpl;
@@ -99,7 +101,7 @@ public class ReachingLegTest extends TrackBasedTest {
waypoints.add(new WaypointImpl(leeGate));
Course course = new CourseImpl(raceName, waypoints);
RaceDefinition race = new RaceDefinitionImpl(raceName, course, boatClass, competitors);
DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(trackedRegatta, race, EmptyWindStore.INSTANCE,
DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(trackedRegatta, race, Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE,
/* delayToLiveInMillis */ 0,
/* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 30000,
/* delay for wind estimation cache invalidation */ 0);
@@ -6,6 +6,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
@@ -13,6 +14,7 @@ import org.junit.Test;
import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.CourseImpl;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
@@ -79,7 +81,7 @@ public class StarbordSideOfStartLineRecognitionTest {
private static final long serialVersionUID = -8007932232555073829L;
public MockedTrackedRaceImpl() {
super(null, null, null, 0, 0, 0, 0);
super(null, null, Collections.<Sideline> emptyList(), null, 0, 0, 0, 0);
}
@Override
@@ -12,6 +12,7 @@ import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.BoatImpl;
@@ -109,7 +110,7 @@ public abstract class TrackBasedTest {
waypoints.add(new WaypointImpl(leeGate));
Course course = new CourseImpl(raceName, waypoints);
RaceDefinition race = new RaceDefinitionImpl(raceName, course, boatClass, competitors);
DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(trackedRegatta, race, EmptyWindStore.INSTANCE,
DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(trackedRegatta, race, Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE,
/* delayToLiveInMillis */ 0,
/* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 30000,
/* delay for wind estimation cache invalidation */ 0);
@@ -11,6 +11,7 @@ import org.junit.Test;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.CourseImpl;
@@ -36,7 +37,7 @@ public class UpdateMarkPassingTest {
when(race.getBoatClass()).thenReturn(new BoatClassImpl("49er", /* typicallyStartsUpwind */ true));
when(race.getCompetitors()).thenReturn(Collections.singleton(competitor));
DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(
/* trackedRegatta */ null, race, EmptyWindStore.INSTANCE,
/* trackedRegatta */ null, race, Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE,
/* delayToLiveInMillis */ 1000, /* millisecondsOverWhichToAverageWind */ 30000,
/* millisecondsOverWhichToAverageSpeed */ 30000);
TimePoint now = MillisecondsTimePoint.now();
@@ -19,6 +19,7 @@ import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.ControlPoint;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.BoatImpl;
@@ -266,7 +267,7 @@ public class WindTest {
/* trackedRegattaRegistry */ null, domainFactory.createScoringScheme(ScoringSchemeType.LOW_POINT), "123", null)),
new RaceDefinitionImpl("Test Race",
new CourseImpl("Test Course", Arrays.asList(new Waypoint[] { w1, w2, w3 })),
boatClass, Collections.singleton(competitor)),
boatClass, Collections.singleton(competitor)), Collections.<Sideline> emptyList(),
EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 1000,
/* millisecondsOverWhichToAverageWind */ 30000,
/* millisecondsOverWhichToAverageSpeed */ 30000);
@@ -16,6 +16,7 @@ import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.RegattaListener;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.NoWindException;
@@ -469,7 +470,7 @@ public class MockedTrackedRace implements DynamicTrackedRace {
}
@Override
public DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, WindStore windStore,
public DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, Iterable<Sideline> sidelines, WindStore windStore,
long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed,
DynamicRaceDefinitionSet raceDefinitionSetToUpdate) {
// TODO Auto-generated method stub
@@ -811,4 +812,10 @@ public class MockedTrackedRace implements DynamicTrackedRace {
// TODO Auto-generated method stub
return false;
}
@Override
public Iterable<Sideline> getCourseSidelines() {
// TODO Auto-generated method stub
return null;
}
}
@@ -10,6 +10,7 @@ import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Leg;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.CourseImpl;
import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
@@ -525,4 +526,10 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace {
return false;
}
@Override
public Iterable<Sideline> getCourseSidelines() {
// TODO Auto-generated method stub
return null;
}
}
@@ -20,6 +20,7 @@ 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.Sideline;
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.common.NauticalSide;
@@ -63,6 +64,8 @@ public interface DomainFactory {
Course createCourse(String name, Iterable<Pair<TracTracControlPoint, NauticalSide>> controlPoints);
Sideline createSideline(String name, Iterable<TracTracControlPoint> controlPoints);
com.sap.sailing.domain.base.Competitor getOrCreateCompetitor(Competitor competitor);
/**
@@ -189,7 +192,7 @@ public interface DomainFactory {
* {@link DynamicRaceDefinitionSet#addRaceDefinition(RaceDefinition, DynamicTrackedRace) added} to that object.
*/
DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(TrackedRegatta trackedRegatta, Race race,
Course course, WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind,
Course course, Iterable<Sideline> sidelines, WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind,
DynamicRaceDefinitionSet raceDefinitionSetToUpdate, URI courseDesignUpdateURI, UUID tracTracEventUuid, String tracTracUsername, String tracTracPassword);
/**
@@ -390,6 +390,10 @@ public class ClientParamsPHP {
return HandicapSystem.valueOf(properties.get("RaceHandicapSystem"));
}
public String getRaceMetadata() {
return properties.get("RaceDataSheet");
}
/**
* Determines all control points listed in the document, regardless of whether they are part of a route/course or not
*/
@@ -24,12 +24,14 @@ import java.util.logging.Logger;
import com.sap.sailing.domain.base.Boat;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.ControlPoint;
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.Sideline;
import com.sap.sailing.domain.base.Team;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.BoatImpl;
@@ -39,6 +41,7 @@ import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
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.SidelineImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.common.MarkType;
import com.sap.sailing.domain.common.NauticalSide;
@@ -224,6 +227,18 @@ public class DomainFactoryImpl implements DomainFactory {
return new CourseImpl(name, waypointList);
}
@Override
public Sideline createSideline(String name, Iterable<TracTracControlPoint> controlPoints) {
List<Mark> marks = new ArrayList<Mark>();
for (TracTracControlPoint controlPoint : controlPoints) {
ControlPoint cp = getOrCreateControlPoint(controlPoint);
for (Mark mark : cp.getMarks()) {
marks.add(mark);
}
}
return new SidelineImpl(name, marks);
}
@Override
public Competitor getOrCreateCompetitor(com.tractrac.clientmodule.Competitor competitor) {
// TODO see bug 596; consider allowing for a new competitor (check for use of == throughout the code) or update existing one
@@ -463,7 +478,7 @@ public class DomainFactoryImpl implements DomainFactory {
@Override
public DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(TrackedRegatta trackedRegatta,
Race race, Course course, WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind,
Race race, Course course, Iterable<Sideline> sidelines, WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind,
DynamicRaceDefinitionSet raceDefinitionSetToUpdate, URI courseDesignUpdateURI, UUID tracTracEventUuid, String tracTracUsername, String tracTracPassword) {
synchronized (raceCache) {
RaceDefinition raceDefinition = raceCache.get(race);
@@ -475,7 +490,7 @@ public class DomainFactoryImpl implements DomainFactory {
// add to existing regatta only if boat class matches
if (raceDefinition.getBoatClass() == trackedRegatta.getRegatta().getBoatClass()) {
trackedRegatta.getRegatta().addRace(raceDefinition);
DynamicTrackedRace trackedRace = createTrackedRace(trackedRegatta, raceDefinition, windStore,
DynamicTrackedRace trackedRace = createTrackedRace(trackedRegatta, raceDefinition, sidelines, windStore,
delayToLiveInMillis, millisecondsOverWhichToAverageWind, raceDefinitionSetToUpdate);
logger.info("Added race "+raceDefinition+" to regatta "+trackedRegatta.getRegatta());
@@ -501,9 +516,9 @@ public class DomainFactoryImpl implements DomainFactory {
}
}
private DynamicTrackedRace createTrackedRace(TrackedRegatta trackedRegatta, RaceDefinition race, WindStore windStore,
private DynamicTrackedRace createTrackedRace(TrackedRegatta trackedRegatta, RaceDefinition race, Iterable<Sideline> sidelines, WindStore windStore,
long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate) {
return trackedRegatta.createTrackedRace(race,
return trackedRegatta.createTrackedRace(race, sidelines,
windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind,
/* time over which to average speed: */ race.getBoatClass().getApproximateManeuverDurationInMilliseconds(),
raceDefinitionSetToUpdate);
@@ -4,9 +4,11 @@ import java.io.IOException;
import java.io.StringReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -16,6 +18,7 @@ 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.base.Sideline;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
@@ -96,9 +99,7 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<Route, RouteDa
@Override
protected void handleEvent(Triple<Route, RouteData, Race> event) {
System.out.print("R");
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()) {
@@ -107,7 +108,15 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<Route, RouteDa
i++;
}
Course course = getDomainFactory().createCourse(event.getA().getName(), ttControlPoints);
List<Sideline> sidelines = new ArrayList<Sideline>();
Map<String, Iterable<TracTracControlPoint>> sidelinesMetadata = parseSidelinesFromRaceMetadata(event.getC(),
event.getC().getEvent().getControlPointList());
for (Entry<String, Iterable<TracTracControlPoint>> sidelineEntry : sidelinesMetadata.entrySet()) {
if (Util.size(sidelineEntry.getValue()) > 0) {
sidelines.add(getDomainFactory().createSideline(sidelineEntry.getKey(), sidelineEntry.getValue()));
}
}
RaceDefinition existingRaceDefinitionForRace = getDomainFactory().getExistingRaceDefinitionForRace(event.getC());
if (existingRaceDefinitionForRace != null) {
logger.log(Level.INFO, "Received course update for existing race "+event.getC().getName()+": "+
@@ -117,7 +126,7 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<Route, RouteDa
try {
getDomainFactory().updateCourseWaypoints(existingRaceDefinitionForRace.getCourse(), ttControlPoints);
if (getTrackedRegatta().getExistingTrackedRace(existingRaceDefinitionForRace) == null) {
createTrackedRace(existingRaceDefinitionForRace);
createTrackedRace(existingRaceDefinitionForRace, sidelines);
}
} catch (PatchFailedException e) {
logger.log(Level.SEVERE, "Internal error updating race course "+course+": "+e.getMessage());
@@ -127,10 +136,9 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<Route, RouteDa
logger.log(Level.INFO, "Received course for non-existing race "+event.getC().getName()+". Creating RaceDefinition.");
// create race definition and add to event
DynamicTrackedRace trackedRace = getDomainFactory().getOrCreateRaceDefinitionAndTrackedRace(
getTrackedRegatta(), event.getC(), course, windStore, delayToLiveInMillis,
getTrackedRegatta(), event.getC(), course, sidelines, windStore, delayToLiveInMillis,
millisecondsOverWhichToAverageWind, raceDefinitionSetToUpdate, courseDesignUpdateURI,
getTracTracEvent().getId(), tracTracUsername, tracTracPassword);
if (getSimulator() != null) {
getSimulator().setTrackedRace(trackedRace);
}
@@ -140,10 +148,12 @@ 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
* <pre>
* Seq.1=GATE
* Seq.2=PORT
* Seq.3=GATE
* Seq.4=STARBOARD
* </pre>
*/
private Map<Integer, NauticalSide> parseAdditionalCourseDataFromMetadata(Route route,
List<com.tractrac.clientmodule.ControlPoint> controlPoints) {
@@ -151,7 +161,7 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<Route, RouteDa
int controlPointsCount = controlPoints.size();
String routeMetadataString = route.getMetadata() != null ? route.getMetadata().getText() : null;
if(routeMetadataString != null) {
Map<String, String> routeMetadata = parseRouteMetadata(routeMetadataString);
Map<String, String> routeMetadata = parseMetadata(routeMetadataString);
for(int i = 1; i <= controlPointsCount; i++) {
String seqValue = routeMetadata.get("Seq." + i);
com.tractrac.clientmodule.ControlPoint controlPoint = controlPoints.get(i-1);
@@ -167,12 +177,43 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<Route, RouteDa
return result;
}
/**
* Parses the race metadata for sideline information
* The sidelines of a race (course) are encoded like this...
* <pre>
* SIDELINE1=(TR-A) 3
* SIDELINE2=(TR-A) Start
* </pre>
* Each sideline is defined right now through a simple gate, but this might change in the future
*/
private Map<String, Iterable<TracTracControlPoint>> parseSidelinesFromRaceMetadata(Race race,
Collection<com.tractrac.clientmodule.ControlPoint> controlPoints) {
Map<String, Iterable<TracTracControlPoint>> result = new HashMap<String, Iterable<TracTracControlPoint>>();
String raceMetadataString = race.getMetadata() != null ? race.getMetadata().getText() : null;
if (raceMetadataString != null) {
Map<String, String> sidelineMetadata = parseMetadata(raceMetadataString);
for (Entry<String, String> entry : sidelineMetadata.entrySet()) {
if (entry.getKey().startsWith("SIDELINE")) {
List<TracTracControlPoint> sidelineCPs = new ArrayList<>();
result.put(entry.getKey(), sidelineCPs);
for (com.tractrac.clientmodule.ControlPoint cp : controlPoints) {
String cpName = cp.getName().trim();
if (cpName.equals(entry.getValue())) {
sidelineCPs.add(new ControlPointAdapter(cp));
}
}
}
}
}
return result;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private Map<String, String> parseRouteMetadata(String routeMetadata) {
private Map<String, String> parseMetadata(String metadata) {
Map<String, String> metadataMap = new HashMap<String, String>();
try {
Properties p = new Properties();
p.load(new StringReader(routeMetadata));
p.load(new StringReader(metadata));
metadataMap = new HashMap<String, String>((Map) p);
} catch (IOException e) {
// do nothing
@@ -180,8 +221,8 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<Route, RouteDa
return metadataMap;
}
private void createTrackedRace(RaceDefinition race) {
DynamicTrackedRace trackedRace = getTrackedRegatta().createTrackedRace(race,
private void createTrackedRace(RaceDefinition race, Iterable<Sideline> sidelines) {
DynamicTrackedRace trackedRace = getTrackedRegatta().createTrackedRace(race, sidelines,
windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind,
/* time over which to average speed: */ race.getBoatClass().getApproximateManeuverDurationInMilliseconds(),
raceDefinitionSetToUpdate);
@@ -24,7 +24,6 @@ import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.maptrack.client.io.TypeController;
import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.Fleet;
@@ -338,7 +337,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
int controlPointsCount = controlPoints.size();
String routeMetadataString = route.getMetadata();
if(routeMetadataString != null) {
Map<String, String> routeMetadata = parseRouteMetadata(routeMetadataString);
Map<String, String> routeMetadata = parseMetadata(routeMetadataString);
for(int i = 1; i <= controlPointsCount; i++) {
String seqValue = routeMetadata.get("Seq." + i);
TracTracControlPoint controlPoint = controlPoints.get(i-1);
@@ -355,17 +354,18 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private Map<String, String> parseRouteMetadata(String routeMetadata) {
private Map<String, String> parseMetadata(String metadata) {
Map<String, String> metadataMap = new HashMap<String, String>();
try {
Properties p = new Properties();
p.load(new StringReader(routeMetadata));
p.load(new StringReader(metadata));
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();
@@ -1,6 +1,7 @@
package com.sap.sailing.domain.tracking;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Sideline;
public interface DynamicTrackedRegatta extends TrackedRegatta {
@@ -17,7 +18,7 @@ public interface DynamicTrackedRegatta extends TrackedRegatta {
* may be <code>null</code> which means that no update will be fired to any
* {@link DynamicRaceDefinitionSet}.
*/
DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, WindStore windStore,
DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, Iterable<Sideline> sidelines, WindStore windStore,
long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed,
DynamicRaceDefinitionSet raceDefinitionSetToUpdate);
@@ -10,6 +10,7 @@ import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.Leg;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.DouglasPeucker;
import com.sap.sailing.domain.common.Distance;
@@ -19,9 +20,11 @@ import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.Tack;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.TimingConstants;
import com.sap.sailing.domain.common.TrackedRaceStatusEnum;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.WindSourceType;
import com.sap.sailing.domain.common.dto.TrackedRaceDTO;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.racelog.RaceLog;
@@ -218,6 +221,11 @@ public interface TrackedRace extends Serializable {
*/
Iterable<Mark> getMarks();
/**
* Retrieves all course side lines assigned to the race.
*/
Iterable<Sideline> getCourseSidelines();
/**
* If the <code>waypoint</code> only has one {@link #getMarks() mark}, its position at time <code>timePoint</code>
* is returned. Otherwise, the center of gravity between the mark positions is computed and returned.
@@ -6,6 +6,7 @@ import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.TimePoint;
@@ -39,7 +40,7 @@ public interface TrackedRegatta extends Serializable {
* if not <code>null</code>, after creating the {@link TrackedRace}, the <code>raceDefinition</code> is
* {@link DynamicRaceDefinitionSet#addRaceDefinition(RaceDefinition, DynamicTrackedRace) added} to that object.
*/
DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, WindStore windStore,
DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, Iterable<Sideline> sidelines, WindStore windStore,
long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed,
DynamicRaceDefinitionSet raceDefinitionSetToUpdate);
@@ -20,6 +20,7 @@ import com.sap.sailing.domain.base.CourseBase;
import com.sap.sailing.domain.base.Leg;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.TimePoint;
@@ -63,10 +64,10 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
private transient Set<CourseDesignChangedListener> courseDesignChangedListeners;
public DynamicTrackedRaceImpl(TrackedRegatta trackedRegatta, RaceDefinition race,
public DynamicTrackedRaceImpl(TrackedRegatta trackedRegatta, RaceDefinition race, Iterable<Sideline> sidelines,
WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed,
long delayForCacheInvalidationOfWindEstimation) {
super(trackedRegatta, race, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed,
super(trackedRegatta, race, sidelines, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed,
delayForCacheInvalidationOfWindEstimation);
this.logListener = new DynamicTrackedRaceLogListener(this);
this.courseDesignChangedListeners = new HashSet<>();
@@ -106,10 +107,10 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
* the caller cannot assume that all wind tracks have yet been loaded completely. The caller may call {@link #waitUntilWindLoadingComplete()}
* to wait until all persistent wind sources have been successfully and completely loaded.
*/
public DynamicTrackedRaceImpl(TrackedRegatta trackedRegatta, RaceDefinition race,
public DynamicTrackedRaceImpl(TrackedRegatta trackedRegatta, RaceDefinition race, Iterable<Sideline> sidelines,
WindStore windStore, long delayToLiveInMillis,
long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed) {
this(trackedRegatta, race, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed,
this(trackedRegatta, race, sidelines, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed,
millisecondsOverWhichToAverageWind/2);
}
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.tracking.impl;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
@@ -25,10 +26,10 @@ public class DynamicTrackedRegattaImpl extends TrackedRegattaImpl implements Dyn
}
@Override
public DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, WindStore windStore,
public DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, Iterable<Sideline> sidelines, WindStore windStore,
long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed,
DynamicRaceDefinitionSet raceDefinitionSetToUpdate) {
return (DynamicTrackedRace) super.createTrackedRace(raceDefinition, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind,
return (DynamicTrackedRace) super.createTrackedRace(raceDefinition, sidelines, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind,
millisecondsOverWhichToAverageSpeed, raceDefinitionSetToUpdate);
}
}
@@ -38,6 +38,7 @@ import com.sap.sailing.domain.base.CourseListener;
import com.sap.sailing.domain.base.Leg;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.SpeedWithBearing;
import com.sap.sailing.domain.base.SpeedWithBearingWithConfidence;
import com.sap.sailing.domain.base.Timed;
@@ -209,6 +210,8 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
private transient Map<TimePoint, Future<Wind>> directionFromStartToNextMarkCache;
private final ConcurrentHashMap<Mark, GPSFixTrack<Mark, GPSFix>> markTracks;
private final Map<String, Sideline> courseSidelines;
protected long millisecondsOverWhichToAverageSpeed;
@@ -254,7 +257,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
private final Map<Iterable<MarkPassing>, NamedReentrantReadWriteLock> locksForMarkPassings;
public TrackedRaceImpl(final TrackedRegatta trackedRegatta, RaceDefinition race, final WindStore windStore,
public TrackedRaceImpl(final TrackedRegatta trackedRegatta, RaceDefinition race, final Iterable<Sideline> sidelines, final WindStore windStore,
long delayToLiveInMillis, final long millisecondsOverWhichToAverageWind,
long millisecondsOverWhichToAverageSpeed, long delayForWindEstimationCacheInvalidation) {
super();
@@ -289,6 +292,14 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
}
i++;
}
courseSidelines = new LinkedHashMap<String, Sideline>();
for (Sideline sideline : sidelines) {
courseSidelines.put(sideline.getName(), sideline);
for (Mark mark : sideline.getMarks()) {
getOrCreateTrack(mark);
}
}
trackedLegs = new LinkedHashMap<Leg, TrackedLeg>();
race.getCourse().lockForRead();
try {
@@ -2305,6 +2316,11 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
}
}
@Override
public Iterable<Sideline> getCourseSidelines() {
return new ArrayList<Sideline>(courseSidelines.values());
}
@Override
public long getDelayToLiveInMillis() {
return delayToLiveInMillis;
@@ -16,6 +16,7 @@ import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet;
@@ -167,11 +168,11 @@ public class TrackedRegattaImpl implements TrackedRegatta {
}
@Override
public DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, WindStore windStore, long delayToLiveInMillis,
public DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, Iterable<Sideline> sidelines, WindStore windStore, long delayToLiveInMillis,
long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed,
DynamicRaceDefinitionSet raceDefinitionSetToUpdate) {
logger.log(Level.INFO, "Creating DynamicTrackedRaceImpl for RaceDefinition " + raceDefinition.getName());
DynamicTrackedRaceImpl result = new DynamicTrackedRaceImpl(this, raceDefinition,
DynamicTrackedRaceImpl result = new DynamicTrackedRaceImpl(this, raceDefinition, sidelines,
windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed);
// adding the raceDefinition to the raceDefinitionSetToUpdate BEFORE calling addTrackedRace helps those who
// are called back by RaceListener.raceAdded(TrackedRace) and who then expect the update to have happened
@@ -42,6 +42,7 @@
<plugin id="com.sap.sailing.manage2sail.resultimport" autoStart="true" startLevel="3" />
<plugin id="com.sap.sailing.monitoring" autoStart="true" startLevel="5" />
<plugin id="com.sap.sailing.resultimport" autoStart="true" startLevel="3" />
<plugin id="com.sap.sailing.sailwave.resultimport" autoStart="true" startLevel="3" />
<plugin id="com.sap.sailing.server" autoStart="true" startLevel="4" />
<plugin id="com.sap.sailing.server.gateway" autoStart="true" startLevel="4" />
<plugin id="com.sap.sailing.server.gateway.ess40" autoStart="true" startLevel="4" />
@@ -15,6 +15,7 @@ import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.RegattaListener;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.NoWindException;
@@ -470,7 +471,7 @@ public class MockedTrackedRace implements DynamicTrackedRace {
}
@Override
public DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, WindStore windStore,
public DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, Iterable<Sideline> sidelines, WindStore windStore,
long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed,
DynamicRaceDefinitionSet raceDefinitionSetToUpdate) {
// TODO Auto-generated method stub
@@ -813,4 +814,10 @@ public class MockedTrackedRace implements DynamicTrackedRace {
return false;
}
@Override
public Iterable<Sideline> getCourseSidelines() {
// TODO Auto-generated method stub
return null;
}
}
@@ -120,7 +120,7 @@ public class AdminConsoleEntryPoint extends AbstractEntryPoint implements Regatt
final MediaPanel mediaPanel = new MediaPanel(mediaService, this, stringMessages);
tabPanel.add(mediaPanel, stringMessages.mediaPanel(), /* asHTML */ false);
final MasterDataImportPanel masterDataImportPanel = new MasterDataImportPanel(stringMessages, sailingService);
final MasterDataImportPanel masterDataImportPanel = new MasterDataImportPanel(stringMessages, sailingService, this, sailingEventManagementPanel, leaderboardGroupConfigPanel);
tabPanel.add(masterDataImportPanel, stringMessages.masterDataImportPanel(), /* asHTML */ false);
tabPanel.selectTab(0);
@@ -41,6 +41,7 @@ import com.sap.sailing.gwt.ui.adminconsole.LeaderboardGroupDialog.LeaderboardGro
import com.sap.sailing.gwt.ui.client.AbstractRegattaPanel;
import com.sap.sailing.gwt.ui.client.DataEntryDialog.DialogCallback;
import com.sap.sailing.gwt.ui.client.ErrorReporter;
import com.sap.sailing.gwt.ui.client.LeaderboardGroupRefresher;
import com.sap.sailing.gwt.ui.client.RegattaRefresher;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
@@ -51,7 +52,7 @@ import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel {
public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel implements LeaderboardGroupRefresher {
interface AnchorTemplates extends SafeHtmlTemplates {
@SafeHtmlTemplates.Template("<a href=\"{0}\">{1}</a>")
@@ -119,7 +120,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel {
splitPanel.add(createLeaderboardsGUI(tableRes));
//Load Data
loadGroups();
fillLeaderboardGroups();
loadLeaderboards();
}
@@ -494,7 +495,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel {
return leaderboardGroupsCaptionPanel;
}
private void loadGroups() {
public void fillLeaderboardGroups() {
sailingService.getLeaderboardGroups(false /*withGeoLocationData*/, new AsyncCallback<List<LeaderboardGroupDTO>>() {
@Override
public void onSuccess(List<LeaderboardGroupDTO> groups) {
@@ -664,7 +665,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel {
//Check if the removed group was the selected one
LeaderboardGroupDTO selectedGroup = groupsSelectionModel.getSelectedObject();
if (selectedGroup != null && selectedGroup.getName().equals(group.getName())) {
groupsSelectionModel.setSelected(null, true);
groupsSelectionModel.setSelected(selectedGroup, false);
}
}
});
@@ -686,34 +687,21 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel {
final LeaderboardGroupDTO selectedGroup = groupsSelectionModel.getSelectedObject();
splitPanel.setVisible(selectedGroup != null);
if (selectedGroup != null) {
sailingService.getLeaderboardGroupByName(selectedGroup.getName(), false /*withGeoLocationData*/, new AsyncCallback<LeaderboardGroupDTO>() {
@Override
public void onFailure(Throwable t) {
errorReporter.reportError("Error trying to obtain the leaderboard group " + selectedGroup.getName() + ": " + t.getMessage());
}
@Override
public void onSuccess(LeaderboardGroupDTO result) {
//Updating the data lists
availableLeaderboardGroups.set(availableLeaderboardGroups.indexOf(selectedGroup), result);
groupsSelectionModel.setSelected(result, true);
//Display details of the group
groupDetailsCaptionPanel.setCaptionText(stringMessages.detailsOfLeaderboardGroup() + " '" + selectedGroup.getName() + "'");
descriptionTextArea.setText(selectedGroup.description);
setDescriptionEditable(false);
//Display details of the group
groupDetailsCaptionPanel.setCaptionText(stringMessages.detailsOfLeaderboardGroup() + " '" + result.getName() + "'");
descriptionTextArea.setText(result.description);
setDescriptionEditable(false);
groupDetailsSelectionModel.clear();
groupDetailsProvider.getList().clear();
groupDetailsProvider.getList().addAll(selectedGroup.leaderboards);
groupDetailsSelectionModel.clear();
groupDetailsProvider.getList().clear();
groupDetailsProvider.getList().addAll(result.leaderboards);
//Reload available leaderboards and remove leaderboards of the group from the list
leaderboardsSelectionModel.clear();
leaderboardsFilterTextBox.setText("");
leaderboardsProvider.getList().clear();
leaderboardsProvider.getList().addAll(availableLeaderboards);
leaderboardsProvider.getList().removeAll(result.leaderboards);
}
});
//Reload available leaderboards and remove leaderboards of the group from the list
leaderboardsSelectionModel.clear();
leaderboardsFilterTextBox.setText("");
leaderboardsProvider.getList().clear();
leaderboardsProvider.getList().addAll(availableLeaderboards);
leaderboardsProvider.getList().removeAll(selectedGroup.leaderboards);
}
}
@@ -27,6 +27,7 @@ import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
import com.sap.sailing.gwt.ui.client.DataEntryDialog.DialogCallback;
import com.sap.sailing.gwt.ui.client.ErrorReporter;
import com.sap.sailing.gwt.ui.client.EventRefresher;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.URLEncoder;
@@ -39,7 +40,7 @@ import com.sap.sailing.gwt.ui.shared.EventDTO;
* @author Frank Mittag (C5163974)
*
*/
public class SailingEventManagementPanel extends SimplePanel {
public class SailingEventManagementPanel extends SimplePanel implements EventRefresher {
private final SailingServiceAsync sailingService;
private final ErrorReporter errorReporter;
private final StringMessages stringMessages;
@@ -321,7 +322,7 @@ public class SailingEventManagementPanel extends SimplePanel {
});
}
private void fillEvents() {
public void fillEvents() {
sailingService.getEvents(new AsyncCallback<List<EventDTO>>() {
@Override
public void onFailure(Throwable caught) {
@@ -0,0 +1,7 @@
package com.sap.sailing.gwt.ui.client;
public interface EventRefresher {
void fillEvents();
}
@@ -0,0 +1,7 @@
package com.sap.sailing.gwt.ui.client;
public interface LeaderboardGroupRefresher {
void fillLeaderboardGroups();
}
@@ -321,5 +321,5 @@ public interface SailingService extends RemoteService {
void reloadRaceLog(String selectedLeaderboardName, RaceColumnDTO raceColumnDTO, FleetDTO fleet);
MasterDataImportObjectCreationCount importMasterData(String host, String[] groupNames);
MasterDataImportObjectCreationCount importMasterData(String host, String[] groupNames, boolean override);
}
@@ -441,8 +441,9 @@ public interface SailingServiceAsync {
void reloadRaceLog(String selectedLeaderboardName, RaceColumnDTO raceColumnDTO, FleetDTO fleet,
AsyncCallback<Void> asyncCallback);
void importMasterData(String host, String[] names, AsyncCallback<MasterDataImportObjectCreationCount> asyncCallback);
void importMasterData(String host, String[] names, boolean override, AsyncCallback<MasterDataImportObjectCreationCount> asyncCallback);
}
@@ -700,6 +700,7 @@ public interface StringMessages extends Messages {
String refreshRaceLog();
String raceLogReloaded();
String reloadAllRaceLogs();
String sideline();
String classAndGolfUp();
String classDisplayed();
String papaDisplayed();
@@ -694,6 +694,7 @@ earlyStarters=Early starters
refreshRaceLog=Refresh race log
raceLogReloaded=RaceLog successfully reloaded from database
reloadAllRaceLogs=Reload all race logs
sideline=Sideline
classAndGolfUp=Flag displayed - eight minutes till start - the startprocedure is a gate start
classDisplayed=Flag displayed - five minutes till start
papaDisplayed=Start mode flag - four minutes till start
@@ -690,6 +690,7 @@ earlyStarters=Frühstarter
refreshRaceLog=RaceLog neu laden
raceLogReloaded=RaceLog wurde neu geladen
reloadAllRaceLogs=Alle RaceLogs neu laden
sideline=Seitenlinie
classAndGolfUp=Flagge angezeigt - acht Minuten bis zum Start - die Startprozedur ist der Gate Start
classDisplayed=Flagge angezeigt - fünf Minuten bis zum Start
papaDisplayed=Startmodusflagge - vier Minuten bis zum Start
@@ -30,6 +30,8 @@ import com.google.gwt.maps.client.control.ScaleControl;
import com.google.gwt.maps.client.event.MapDragEndHandler;
import com.google.gwt.maps.client.event.MapMouseMoveHandler;
import com.google.gwt.maps.client.event.MapZoomEndHandler;
import com.google.gwt.maps.client.event.PolygonMouseOutHandler;
import com.google.gwt.maps.client.event.PolygonMouseOverHandler;
import com.google.gwt.maps.client.event.PolylineClickHandler;
import com.google.gwt.maps.client.event.PolylineMouseOutHandler;
import com.google.gwt.maps.client.event.PolylineMouseOverHandler;
@@ -37,6 +39,8 @@ import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.geom.LatLngBounds;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.maps.client.overlay.MarkerOptions;
import com.google.gwt.maps.client.overlay.Polygon;
import com.google.gwt.maps.client.overlay.PolygonOptions;
import com.google.gwt.maps.client.overlay.Polyline;
import com.google.gwt.maps.client.overlay.PolylineOptions;
import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -85,6 +89,7 @@ import com.sap.sailing.gwt.ui.shared.MarkDTO;
import com.sap.sailing.gwt.ui.shared.QuickRankDTO;
import com.sap.sailing.gwt.ui.shared.RaceMapDataDTO;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
import com.sap.sailing.gwt.ui.shared.SidelineDTO;
import com.sap.sailing.gwt.ui.shared.WindDTO;
import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO;
import com.sap.sailing.gwt.ui.shared.WindTrackInfoDTO;
@@ -115,12 +120,14 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
* Polyline for the advantage line (the leading line for the boats, orthogonal to the wind direction; touching the leading boat).
*/
private Polyline advantageLine;
/**
* Polyline for the course middle line.
*/
private Polyline courseMiddleLine;
private Map<SidelineDTO, Polygon> courseSidelines;
private WindTrackInfoDTO lastCombinedWindTrackInfoDTO;
/**
@@ -248,6 +255,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
firstShownFix = new HashMap<CompetitorDTO, Integer>();
lastShownFix = new HashMap<CompetitorDTO, Integer>();
markDTOs = new HashMap<String, MarkDTO>();
courseSidelines = new HashMap<SidelineDTO, Polygon>();
boatOverlays = new HashMap<CompetitorDTO, BoatOverlay>();
competitorInfoOverlays = new HashMap<CompetitorDTO, CompetitorInfoOverlay>();
windSensorOverlays = new HashMap<WindSource, WindSensorOverlay>();
@@ -385,6 +393,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
// Do mark specific actions
showCourseMarksOnMap(raceMapDataDTO.coursePositions);
showCourseSidelinesOnMap(raceMapDataDTO.courseSidelines);
showStartAndFinishLines(raceMapDataDTO.coursePositions);
showAdvantageLine(competitorsToShow, date);
@@ -550,6 +559,52 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
}
}
private void showCourseSidelinesOnMap(List<SidelineDTO> sidelinesDTOs) {
if (map != null && sidelinesDTOs != null ) {
Map<SidelineDTO, Polygon> toRemoveSidelines = new HashMap<SidelineDTO, Polygon>(courseSidelines);
for (SidelineDTO sidelineDTO : sidelinesDTOs) {
if (sidelineDTO.getMarks().size() == 2) { // right now we only support sidelines with 2 marks
Polygon sideline = courseSidelines.get(sidelineDTO);
LatLng[] sidelinePoints = new LatLng[sidelineDTO.getMarks().size()];
int i=0;
for (MarkDTO sidelineMark : sidelineDTO.getMarks()) {
sidelinePoints[i] = LatLng.newInstance(sidelineMark.position.latDeg, sidelineMark.position.lngDeg);
i++;
}
if (sideline == null) {
PolygonOptions options = PolygonOptions.newInstance(/* clickable must be true for hover sensititivy*/ true);
sideline = new Polygon(sidelinePoints, /* color */"#0000FF", /* width */1, /* opacity */1.0, /* fillColor */
null, /* fillOpacity */1.0, options);
sideline.addPolygonMouseOverHandler(new PolygonMouseOverHandler() {
@Override
public void onMouseOver(PolygonMouseOverEvent event) {
map.setTitle(stringMessages.sideline());
}
});
sideline.addPolygonMouseOutHandler(new PolygonMouseOutHandler() {
@Override
public void onMouseOut(PolygonMouseOutEvent event) {
map.setTitle("");
}
});
courseSidelines.put(sidelineDTO, sideline);
map.addOverlay(sideline);
} else {
sideline.deleteVertex(1);
sideline.deleteVertex(0);
sideline.insertVertex(0, sidelinePoints[0]);
sideline.insertVertex(1, sidelinePoints[1]);
toRemoveSidelines.remove(sidelineDTO);
}
}
}
for (SidelineDTO toRemoveSideline : toRemoveSidelines.keySet()) {
Polygon polygon = courseSidelines.remove(toRemoveSideline);
map.removeOverlay(polygon);
}
}
}
protected void showCourseMarksOnMap(CoursePositionsDTO courseDTO) {
if (map != null && courseDTO != null) {
Map<String, CourseMarkOverlay> toRemoveCourseMarks = new HashMap<String, CourseMarkOverlay>(courseMarkOverlays);
@@ -20,6 +20,7 @@ import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
@@ -27,6 +28,9 @@ import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.sap.sailing.domain.common.MasterDataImportObjectCreationCount;
import com.sap.sailing.gwt.ui.client.EventRefresher;
import com.sap.sailing.gwt.ui.client.LeaderboardGroupRefresher;
import com.sap.sailing.gwt.ui.client.RegattaRefresher;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
@@ -46,10 +50,19 @@ public class MasterDataImportPanel extends VerticalPanel {
private final StringMessages stringMessages;
private String currentHost;
private SailingServiceAsync sailingService;
private CheckBox overrideSwitch;
private final RegattaRefresher regattaRefresher;
private final EventRefresher eventRefresher;
private final LeaderboardGroupRefresher leaderboardGroupRefresher;
public MasterDataImportPanel(StringMessages stringMessages, SailingServiceAsync sailingService) {
public MasterDataImportPanel(StringMessages stringMessages, SailingServiceAsync sailingService,
RegattaRefresher regattaRefresher, EventRefresher eventRefresher,
LeaderboardGroupRefresher leaderboardGroupRefresher) {
this.sailingService = sailingService;
this.stringMessages = stringMessages;
this.regattaRefresher = regattaRefresher;
this.eventRefresher = eventRefresher;
this.leaderboardGroupRefresher = leaderboardGroupRefresher;
HorizontalPanel serverAddressPanel = new HorizontalPanel();
serverAddressPanel.add(new Label("Remote host:"));
@@ -102,22 +115,33 @@ public class MasterDataImportPanel extends VerticalPanel {
protected void importLeaderboardGroups() {
String[] groupNames = createLeaderBoardGroupNamesFromListBox();
sailingService.importMasterData(currentHost, groupNames, new AsyncCallback<MasterDataImportObjectCreationCount>() {
@Override
public void onSuccess(MasterDataImportObjectCreationCount result) {
int leaderboardsCreated = result.getLeaderboardCount();
int leaderboardGroupsCreated = result.getLeaderboardGroupCount();
int eventsCreated = result.getEventCount();
int regattasCreated = result.getRegattaCount();
showSuccessAlert(leaderboardsCreated, leaderboardGroupsCreated, eventsCreated, regattasCreated);
}
@Override
public void onFailure(Throwable caught) {
showErrorAlert(caught.getLocalizedMessage());
}
});
boolean override = overrideSwitch.getValue();
sailingService.importMasterData(currentHost, groupNames, override,
new AsyncCallback<MasterDataImportObjectCreationCount>() {
@Override
public void onSuccess(MasterDataImportObjectCreationCount result) {
int leaderboardsCreated = result.getLeaderboardCount();
int leaderboardGroupsCreated = result.getLeaderboardGroupCount();
int eventsCreated = result.getEventCount();
int regattasCreated = result.getRegattaCount();
if (regattasCreated > 0) {
regattaRefresher.fillRegattas();
}
if (eventsCreated > 0) {
eventRefresher.fillEvents();
}
if (leaderboardGroupsCreated > 0) {
leaderboardGroupRefresher.fillLeaderboardGroups();
}
showSuccessAlert(leaderboardsCreated, leaderboardGroupsCreated, eventsCreated, regattasCreated);
}
@Override
public void onFailure(Throwable caught) {
showErrorAlert(caught.getLocalizedMessage());
}
});
}
@@ -226,6 +250,10 @@ public class MasterDataImportPanel extends VerticalPanel {
leaderboardgroupListBox = new ListBox(true);
contentPanel.add(leaderboardgroupListBox);
overrideSwitch = new CheckBox("Override existing data if names and ids match");
overrideSwitch.setValue(false);
contentPanel.add(overrideSwitch);
importLeaderboardGroupsButton = new Button("Import selected Leaderboard Groups");
contentPanel.add(importLeaderboardGroupsButton);
@@ -45,9 +45,6 @@ import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
@@ -67,6 +64,7 @@ import com.sap.sailing.domain.base.RaceColumnInSeries;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.SpeedWithBearing;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.FleetImpl;
@@ -123,7 +121,6 @@ import com.sap.sailing.domain.common.dto.TrackedRaceDTO;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.domain.common.impl.KilometersPerHourSpeedImpl;
import com.sap.sailing.domain.common.impl.MasterDataImportObjectCreationCountImpl;
import com.sap.sailing.domain.common.impl.MeterDistance;
import com.sap.sailing.domain.common.impl.PolarSheetGenerationTriggerResponseImpl;
import com.sap.sailing.domain.common.impl.PolarSheetsHistogramDataImpl;
@@ -141,7 +138,6 @@ import com.sap.sailing.domain.leaderboard.MetaLeaderboard;
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
import com.sap.sailing.domain.leaderboard.caching.LiveLeaderboardUpdater;
import com.sap.sailing.domain.masterdataimport.LeaderboardGroupMasterData;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
import com.sap.sailing.domain.persistence.MongoFactory;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
@@ -229,6 +225,7 @@ import com.sap.sailing.gwt.ui.shared.ReplicationMasterDTO;
import com.sap.sailing.gwt.ui.shared.ReplicationStateDTO;
import com.sap.sailing.gwt.ui.shared.ScoreCorrectionProviderDTO;
import com.sap.sailing.gwt.ui.shared.SeriesDTO;
import com.sap.sailing.gwt.ui.shared.SidelineDTO;
import com.sap.sailing.gwt.ui.shared.SpeedWithBearingDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationDTO;
@@ -246,9 +243,7 @@ import com.sap.sailing.resultimport.ResultUrlProvider;
import com.sap.sailing.resultimport.ResultUrlRegistry;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.masterdata.impl.LeaderboardGroupMasterDataJsonDeserializer;
import com.sap.sailing.server.masterdata.MasterDataImporter;
import com.sap.sailing.server.operationaltransformation.AddColumnToLeaderboard;
import com.sap.sailing.server.operationaltransformation.AddColumnToSeries;
import com.sap.sailing.server.operationaltransformation.AddCourseArea;
@@ -259,7 +254,6 @@ import com.sap.sailing.server.operationaltransformation.CreateFlexibleLeaderboar
import com.sap.sailing.server.operationaltransformation.CreateLeaderboardGroup;
import com.sap.sailing.server.operationaltransformation.CreateRegattaLeaderboard;
import com.sap.sailing.server.operationaltransformation.DisconnectLeaderboardColumnFromTrackedRace;
import com.sap.sailing.server.operationaltransformation.ImportMasterDataOperation;
import com.sap.sailing.server.operationaltransformation.MoveColumnInSeriesDown;
import com.sap.sailing.server.operationaltransformation.MoveColumnInSeriesUp;
import com.sap.sailing.server.operationaltransformation.MoveLeaderboardColumnDown;
@@ -1186,7 +1180,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
Map<String, Date> fromPerCompetitorIdAsString, Map<String, Date> toPerCompetitorIdAsString,
boolean extrapolate) throws NoWindException {
return new CompactRaceMapDataDTO(getBoatPositions(raceIdentifier, fromPerCompetitorIdAsString,
toPerCompetitorIdAsString, extrapolate), getCoursePositions(raceIdentifier, date), getQuickRanks(
toPerCompetitorIdAsString, extrapolate), getCoursePositions(raceIdentifier, date), getCourseSidelines(raceIdentifier, date), getQuickRanks(
raceIdentifier, date));
}
@@ -1382,6 +1376,28 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
return raceTimesInfos;
}
private List<SidelineDTO> getCourseSidelines(RegattaAndRaceIdentifier raceIdentifier, Date date) {
List<SidelineDTO> result = new ArrayList<SidelineDTO>();
if (date != null) {
TimePoint dateAsTimePoint = new MillisecondsTimePoint(date);
TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier);
if (trackedRace != null) {
for (Sideline sideline : trackedRace.getCourseSidelines()) {
List<MarkDTO> markDTOs = new ArrayList<MarkDTO>();
for (Mark mark : sideline.getMarks()) {
GPSFixTrack<Mark, GPSFix> track = trackedRace.getOrCreateTrack(mark);
Position positionAtDate = track.getEstimatedPosition(dateAsTimePoint, /* extrapolate */false);
if (positionAtDate != null) {
markDTOs.add(convertToMarkDTO(mark, positionAtDate));
}
}
result.add(new SidelineDTO(sideline.getName(), markDTOs));
}
}
}
return result;
}
@Override
public CoursePositionsDTO getCoursePositions(RegattaAndRaceIdentifier raceIdentifier, Date date) {
CoursePositionsDTO result = new CoursePositionsDTO();
@@ -3161,7 +3177,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
@Override
public MasterDataImportObjectCreationCount importMasterData(String host, String[] groupNames) {
public MasterDataImportObjectCreationCount importMasterData(String host, String[] groupNames, boolean override) {
String getMasterDataUrl = createGetMasterDataForLgsUrl(host);
if (!isValidUrl(getMasterDataUrl, false)) {
throw new RuntimeException("Not a valid URL for fetching leaderboardgroups masterdata: " + getMasterDataUrl);
@@ -3195,7 +3211,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
sb.append(line);
}
return importFromHttpResponse(sb.toString());
return importFromHttpResponse(sb.toString(), override);
} catch (Exception e) {
throw new RuntimeException(e);
@@ -3219,27 +3235,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
toURL();
}
protected MasterDataImportObjectCreationCountImpl importFromHttpResponse(String response) {
MasterDataImportObjectCreationCountImpl creationCount = new MasterDataImportObjectCreationCountImpl();
JsonDeserializer<LeaderboardGroupMasterData> leaderboardGroupMasterDataDeserializer = LeaderboardGroupMasterDataJsonDeserializer
.create(baseDomainFactory);
JSONParser parser = new JSONParser();
try {
JSONArray leaderboardGroupsMasterDataJsonArray = (JSONArray) parser.parse(response);
for (Object leaderBoardGroupMasterData : leaderboardGroupsMasterDataJsonArray) {
JSONObject leaderBoardGroupMasterDataJson = (JSONObject) leaderBoardGroupMasterData;
LeaderboardGroupMasterData masterData = leaderboardGroupMasterDataDeserializer
.deserialize(leaderBoardGroupMasterDataJson);
ImportMasterDataOperation op = new ImportMasterDataOperation(masterData);
creationCount.add(getService().apply(op));
}
} catch (org.json.simple.parser.ParseException e) {
throw new RuntimeException(e);
} catch (JsonDeserializationException e) {
throw new RuntimeException(e);
}
return creationCount;
protected MasterDataImportObjectCreationCount importFromHttpResponse(String response, boolean override) {
MasterDataImporter importer = new MasterDataImporter(baseDomainFactory, getService());
return importer.importMasterData(response, override);
}
private String createLeaderboardQuery(String[] groupNames) {
@@ -22,12 +22,13 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
public class CompactRaceMapDataDTO implements IsSerializable {
private Map<String, List<GPSFixDTO>> boatPositionsByCompetitorIdAsString;
private CoursePositionsDTO coursePositions;
private List<SidelineDTO> courseSidelines;
private List<CompactQuickRankDTO> quickRanks;
CompactRaceMapDataDTO() {}
public CompactRaceMapDataDTO(Map<CompetitorDTO, List<GPSFixDTO>> boatPositions, CoursePositionsDTO coursePositions,
List<QuickRankDTO> quickRanks) {
List<SidelineDTO> courseSidelines, List<QuickRankDTO> quickRanks) {
this.boatPositionsByCompetitorIdAsString = new HashMap<String, List<GPSFixDTO>>();
for (Map.Entry<CompetitorDTO, List<GPSFixDTO>> e : boatPositions.entrySet()) {
this.boatPositionsByCompetitorIdAsString.put(e.getKey().getIdAsString(), e.getValue());
@@ -36,6 +37,7 @@ public class CompactRaceMapDataDTO implements IsSerializable {
for (QuickRankDTO quickRank : quickRanks) {
this.quickRanks.add(new CompactQuickRankDTO(quickRank.competitor.getIdAsString(), quickRank.rank, quickRank.legNumber));
}
this.courseSidelines = courseSidelines;
this.coursePositions = coursePositions;
}
@@ -52,6 +54,7 @@ public class CompactRaceMapDataDTO implements IsSerializable {
result.quickRanks.add(new QuickRankDTO(competitorDTO, compactQuickRank.getRank(), compactQuickRank.getLegNumber()));
}
}
result.courseSidelines = courseSidelines;
result.coursePositions = coursePositions;
result.boatPositions = new HashMap<CompetitorDTO, List<GPSFixDTO>>();
for (Map.Entry<String, List<GPSFixDTO>> e : boatPositionsByCompetitorIdAsString.entrySet()) {
@@ -9,5 +9,6 @@ import com.sap.sailing.domain.common.dto.CompetitorDTO;
public class RaceMapDataDTO implements IsSerializable {
public Map<CompetitorDTO, List<GPSFixDTO>> boatPositions;
public CoursePositionsDTO coursePositions;
public List<SidelineDTO> courseSidelines;
public List<QuickRankDTO> quickRanks;
}
@@ -0,0 +1,21 @@
package com.sap.sailing.gwt.ui.shared;
import java.util.List;
import com.sap.sailing.domain.common.dto.NamedDTO;
@SuppressWarnings("serial")
public class SidelineDTO extends NamedDTO {
private List<MarkDTO> marks;
SidelineDTO() {}
public SidelineDTO(String name, List<MarkDTO> marks) {
super(name);
this.marks = marks;
}
public List<MarkDTO> getMarks() {
return marks;
}
}
@@ -7,6 +7,7 @@ import static org.junit.Assert.assertTrue;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
@@ -17,6 +18,7 @@ import com.mongodb.Mongo;
import com.mongodb.MongoException;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.Position;
@@ -84,7 +86,7 @@ public class TestStoringAndRetrievingWindTracksTest extends AbstractTracTracLive
}, /* trackedRegattaRegistry */ null, /*courseDesignUpdateURI*/ null, /*tracTracUsername*/ null, /*tracTracPassword*/ null, ReceiverType.RACECOURSE);
addListenersForStoredDataAndStartController(typeControllers);
RaceDefinition race = domainFactory.getAndWaitForRaceDefinition(getTracTracEvent().getRaceList().iterator().next());
DynamicTrackedRace trackedRace = trackedRegatta.createTrackedRace(race, EmptyWindStore.INSTANCE,
DynamicTrackedRace trackedRace = trackedRegatta.createTrackedRace(race, Collections.<Sideline> emptyList(), EmptyWindStore.INSTANCE,
/* delayToLiveInMillis */ 0l, /* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 10000, new DynamicRaceDefinitionSet() {
@Override
public void addRaceDefinition(RaceDefinition race, DynamicTrackedRace trackedRace) {
@@ -3,5 +3,6 @@
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="resources"/>
<classpathentry kind="output" path="bin"/>
</classpath>
@@ -7,8 +7,5 @@ Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Import-Package: org.osgi.framework;version="1.5.0"
Bundle-ActivationPolicy: lazy
Require-Bundle: org.junit4;bundle-version="4.8.2",
com.sap.sailing.sailwave.resultimport,
com.sap.sailing.domain.common,
com.sap.sailing.domain,
com.sap.sailing.resultimport
Fragment-Host: com.sap.sailing.sailwave.resultimport
Require-Bundle: org.junit4;bundle-version="4.8.2"
@@ -1,4 +1,5 @@
source.. = src/
source.. = src/,\
resources/
output.. = bin/
bin.includes = META-INF/,\
.
@@ -0,0 +1,38 @@
Rank;Nat;SailNo;Club;HelmName;CrewName;Q1;Q2;Q3;Q4;Q5;Q6;Q7;Q8;Q9;F1;F2;F3;F4;F5;F6;F7;F8;F9;F10;F11;F12;F13;F14;F15;F16;F17;F18;F19;F20;Total;Nett;
1;DEN;241;Aarhus Sejlklub;Ida Marie Baad Nielsen;Marie Thusgaard Olsen;1;7;(27);1;1;2;;;;;;;;;;;;;;;;;;;;;;;;39;12;
5;NZL;111;Murrays Bay Sailing Club, Akarana Yacht;Alexandra Maloney;Molly Meech;(10);9;6;2;10;3;;;;;;;;;;;;;;;;;;;;;;;;40;30;
4;BRA;321;Marinha do Brasil;Martine Soffiatti Grael;Kattena Larsen Kunze;3;19;3;3;2;(29);;;;;;;;;;;;;;;;;;;;;;;;59;30;
10;AUS;848;Middle Harbour Yacht Club, Fremantle Sai;Olivia Price;Caitlin Elks;(36);15;7;4;5;20;;;;;;;;;;;;;;;;;;;;;;;;87;51;
3;GBR;808;RNCYC;Charlotte Dobson;Sophie Ainsworth;2;(30);1;5;9;9;;;;;;;;;;;;;;;;;;;;;;;;56;26;
24;AUS;117;F..S.C R.F.B.Y.C M.B.S.C;Tessa Parkinson;Chelsea Hall;5;(31);31;6;24;30;;;;;;;;;;;;;;;;;;;;;;;;127;96;
6;DEN;136;Yachtklubben Furesøen;Jena Mai Hansen;Katja Salskov-Iversen;8;(28);10;7;6;6;;;;;;;;;;;;;;;;;;;;;;;;65;37;
16;DEN;104;KDY/Horsens Sejlklub;Maiken Foght Schütt;Anne-Julie Foght Schütt;(26);22;16;8;15;17;;;;;;;;;;;;;;;;;;;;;;;;104;78;
8;NED;131;Delta Lloyd Kernploeg;Annemiek Bekkering;Claire Blom;6;8;(28);9;14;10;;;;;;;;;;;;;;;;;;;;;;;;75;47;
7;GER;712;Verein Seglerhaus am Wannsee;Victoria Jurczok;Anika Lorenz;4;(24);4;10;13;7;;;;;;;;;;;;;;;;;;;;;;;;62;38;
22;GBR;370;Poole YC and Royal Thames YC;Kate Macgregor;Mary Rook;23;21;17;11;20;(33);;;;;;;;;;;;;;;;;;;;;;;;125;92;
12;GBR;121;HISC;Frances Peters;Nicola Groves;14;10;12;12;(22);18;;;;;;;;;;;;;;;;;;;;;;;;88;66;
13;GER;810;Kieler Yacht Club;Jule Görge;Lotta Görge;28;1;(33);13;23;5;;;;;;;;;;;;;;;;;;;;;;;;103;70;
23;USA;816;NCYC/NYYC;Anna Tunnicliffe;Molly Vandemoer;20;13;20;14;(36);27;;;;;;;;;;;;;;;;;;;;;;;;130;94;
17;ESP;989;Real Club Náutico de Gran Canaria;María Cantero;Ana Hernández;19;12;19;15;(26);13;;;;;;;;;;;;;;;;;;;;;;;;104;78;
9;ITA;747;C.C.Aniene/Aeronautica Militare;Giulia Conti;Francesca Clapcich;13;5;15;(16);4;11;;;;;;;;;;;;;;;;;;;;;;;;64;48;
21;DEN;112;Aarhus Sejlklub/Kaløvig Bådelaug;Lin Ea Cenholt;Line Just;11;(29);26;17;25;12;;;;;;;;;;;;;;;;;;;;;;;;120;91;
26;NOR;123;Tønsberg Seilforening;Helene Næss;Marie Rønningen;22;27;(38,DNC);18;16;14;;;;;;;;;;;;;;;;;;;;;;;;135;97;
36;SWE;116;Sweden;Julia Gross;Cecilia Jonsson;(35);34;34;19;27;34;;;;;;;;;;;;;;;;;;;;;;;;183;148;
19;NED;110;Delta Lloyd Kernploeg;Nina Keijzer;Annette Duetz;(30);25;29;20;7;8;;;;;;;;;;;;;;;;;;;;;;;;119;89;
35;BRA;198;Marinha do Brasil / Iate Clube Brasileir;Juliana Senfft;Gabriela Nicolino;32;(38,DNF);38,DNC;21;19;35;;;;;;;;;;;;;;;;;;;;;;;;183;145;
14;GER;777;NRV;Leonie Meyer;Maren Hahlbrode;15;6;18;(22);17;15;;;;;;;;;;;;;;;;;;;;;;;;93;71;
18;FIN;701;Nyländska Jaktklubben, NJK;Silja Kanerva;Miikka Pennanen;16;11;(35);23;18;16;;;;;;;;;;;;;;;;;;;;;;;;119;84;
32;FIN;101;NJK;Noora Ruskola;Camilla Cedercreutz;(31);23;21;24;30;28;;;;;;;;;;;;;;;;;;;;;;;;157;126;
37;IRL;997;National Yacht Club;Andrea Brewster;Claudine Murphy;33;36;32;25;31;(38,DNC);;;;;;;;;;;;;;;;;;;;;;;;195;157;
11;AUS;708;RFBYC;Ella Giudice;Kate Lathouras;9;14;5;(26);11;23;;;;;;;;;;;;;;;;;;;;;;;;88;62;
25;SWE;113;RoyalSwedishYachtClub;Johanna Sommarlund;Kevin Reisenaver;27;4;8;27;(33);31;;;;;;;;;;;;;;;;;;;;;;;;130;97;
34;IRL;727;Royal Irish Yacht Club, Royal North Yach;Tiffany Brien;Saskia Tidey;25;(33);30;28;28;32;;;;;;;;;;;;;;;;;;;;;;;;176;143;
29;SIN;396;SAFYC;Griselda Khng;Sara Tan;17;20;25;29;(34);24;;;;;;;;;;;;;;;;;;;;;;;;149;115;
2;GER;161;Chiemsee-Yacht-Club;Tina Lutz;Susann Beucke;7;3;2;(30);8;4;;;;;;;;;;;;;;;;;;;;;;;;54;24;
33;ITA;143;S.C.G.SALO;TEZZA LAVINIA;PAOLA BERGAMASCHI;(34);18;23;31;32;25;;;;;;;;;;;;;;;;;;;;;;;;163;129;
28;FIN;707;NJK;Sinem Kurtbay;Edward Lehtinen;(38,DNF);2;22;32;29;19;;;;;;;;;;;;;;;;;;;;;;;;142;104;
30;USA;216;Richmond Yacht Club;Kristen Lane;Christine Neville;21;35;11;33;(38,DNC);22;;;;;;;;;;;;;;;;;;;;;;;;160;122;
15;ESP;323;Real Club Naútico de Vigo;Tamara Echegoyen Domínguez;Berta Betanzos Moro;29;17;24;(38,BFD);3;1;;;;;;;;;;;;;;;;;;;;;;;;112;74;
27;FRA;222;YCPR/CVSAE;Lili Sebesi;Caroline Vandame;12;32;9;(38,BFD);12;36;;;;;;;;;;;;;;;;;;;;;;;;139;101;
31;FRA;871;CN Chateillalon;Sarah STEYAERT;Julie BOSSARD;24;26;13;(38,BFD);35;26;;;;;;;;;;;;;;;;;;;;;;;;162;124;
20;AUS;999;Wangi Wangi Amateur Sailing Club;Haylee Outteridge;Nina Curtis;18;16;14;(38,DNF);21;21;;;;;;;;;;;;;;;;;;;;;;;;128;90;
1 Rank Nat SailNo Club HelmName CrewName Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 Total Nett
2 1 DEN 241 Aarhus Sejlklub Ida Marie Baad Nielsen Marie Thusgaard Olsen 1 7 (27) 1 1 2 39 12
3 5 NZL 111 Murrays Bay Sailing Club, Akarana Yacht Alexandra Maloney Molly Meech (10) 9 6 2 10 3 40 30
4 4 BRA 321 Marinha do Brasil Martine Soffiatti Grael Kattena Larsen Kunze 3 19 3 3 2 (29) 59 30
5 10 AUS 848 Middle Harbour Yacht Club, Fremantle Sai Olivia Price Caitlin Elks (36) 15 7 4 5 20 87 51
6 3 GBR 808 RNCYC Charlotte Dobson Sophie Ainsworth 2 (30) 1 5 9 9 56 26
7 24 AUS 117 F..S.C R.F.B.Y.C M.B.S.C Tessa Parkinson Chelsea Hall 5 (31) 31 6 24 30 127 96
8 6 DEN 136 Yachtklubben Furesøen Jena Mai Hansen Katja Salskov-Iversen 8 (28) 10 7 6 6 65 37
9 16 DEN 104 KDY/Horsens Sejlklub Maiken Foght Schütt Anne-Julie Foght Schütt (26) 22 16 8 15 17 104 78
10 8 NED 131 Delta Lloyd Kernploeg Annemiek Bekkering Claire Blom 6 8 (28) 9 14 10 75 47
11 7 GER 712 Verein Seglerhaus am Wannsee Victoria Jurczok Anika Lorenz 4 (24) 4 10 13 7 62 38
12 22 GBR 370 Poole YC and Royal Thames YC Kate Macgregor Mary Rook 23 21 17 11 20 (33) 125 92
13 12 GBR 121 HISC Frances Peters Nicola Groves 14 10 12 12 (22) 18 88 66
14 13 GER 810 Kieler Yacht Club Jule Görge Lotta Görge 28 1 (33) 13 23 5 103 70
15 23 USA 816 NCYC/NYYC Anna Tunnicliffe Molly Vandemoer 20 13 20 14 (36) 27 130 94
16 17 ESP 989 Real Club Náutico de Gran Canaria María Cantero Ana Hernández 19 12 19 15 (26) 13 104 78
17 9 ITA 747 C.C.Aniene/Aeronautica Militare Giulia Conti Francesca Clapcich 13 5 15 (16) 4 11 64 48
18 21 DEN 112 Aarhus Sejlklub/Kaløvig Bådelaug Lin Ea Cenholt Line Just 11 (29) 26 17 25 12 120 91
19 26 NOR 123 Tønsberg Seilforening Helene Næss Marie Rønningen 22 27 (38,DNC) 18 16 14 135 97
20 36 SWE 116 Sweden Julia Gross Cecilia Jonsson (35) 34 34 19 27 34 183 148
21 19 NED 110 Delta Lloyd Kernploeg Nina Keijzer Annette Duetz (30) 25 29 20 7 8 119 89
22 35 BRA 198 Marinha do Brasil / Iate Clube Brasileir Juliana Senfft Gabriela Nicolino 32 (38,DNF) 38,DNC 21 19 35 183 145
23 14 GER 777 NRV Leonie Meyer Maren Hahlbrode 15 6 18 (22) 17 15 93 71
24 18 FIN 701 Nyländska Jaktklubben, NJK Silja Kanerva Miikka Pennanen 16 11 (35) 23 18 16 119 84
25 32 FIN 101 NJK Noora Ruskola Camilla Cedercreutz (31) 23 21 24 30 28 157 126
26 37 IRL 997 National Yacht Club Andrea Brewster Claudine Murphy 33 36 32 25 31 (38,DNC) 195 157
27 11 AUS 708 RFBYC Ella Giudice Kate Lathouras 9 14 5 (26) 11 23 88 62
28 25 SWE 113 RoyalSwedishYachtClub Johanna Sommarlund Kevin Reisenaver 27 4 8 27 (33) 31 130 97
29 34 IRL 727 Royal Irish Yacht Club, Royal North Yach Tiffany Brien Saskia Tidey 25 (33) 30 28 28 32 176 143
30 29 SIN 396 SAFYC Griselda Khng Sara Tan 17 20 25 29 (34) 24 149 115
31 2 GER 161 Chiemsee-Yacht-Club Tina Lutz Susann Beucke 7 3 2 (30) 8 4 54 24
32 33 ITA 143 S.C.G.SALO TEZZA LAVINIA PAOLA BERGAMASCHI (34) 18 23 31 32 25 163 129
33 28 FIN 707 NJK Sinem Kurtbay Edward Lehtinen (38,DNF) 2 22 32 29 19 142 104
34 30 USA 216 Richmond Yacht Club Kristen Lane Christine Neville 21 35 11 33 (38,DNC) 22 160 122
35 15 ESP 323 Real Club Naútico de Vigo Tamara Echegoyen Domínguez Berta Betanzos Moro 29 17 24 (38,BFD) 3 1 112 74
36 27 FRA 222 YCPR/CVSAE Lili Sebesi Caroline Vandame 12 32 9 (38,BFD) 12 36 139 101
37 31 FRA 871 CN Chateillalon Sarah STEYAERT Julie BOSSARD 24 26 13 (38,BFD) 35 26 162 124
38 20 AUS 999 Wangi Wangi Amateur Sailing Club Haylee Outteridge Nina Curtis 18 16 14 (38,DNF) 21 21 128 90
@@ -0,0 +1,92 @@
Rank;Nat;SailNo;Club;HelmName;CrewName;Q1;Q2;Q3;Q4;Q5;Q6;F1;F2;F3;F4;F5;F6;F7;F8;F9;Total;Nett;
1;NZL;6;Victoria Cruising Club;Marcus Hansen;Josh Porebski;4;(22);2;1;1;2;;;;;;;;;;32;10;
2;GER;7;NRV;Erik Heil;Thomas Ploessel;1;(13);6;1;1;7;;;;;;;;;;29;16;
3;GBR;96;Silverline;Dylan Fletcher;Alain Sign;5;4;2;3;(6);4;;;;;;;;;;24;18;
4;FRA;14;S.R.Calédonienne/CNSeiez;Mathiev Frei;Yenn Rocherieux;(14);11;6;1;2;1;;;;;;;;;;35;21;
5;NZL;2;Tauranga & Kerikeri;Peter Burling;Blair Tuke;(18);9;1;9;6;1;;;;;;;;;;44;26;
6;AUT;84;KYK/YCV;Nico Luca Marc Delle-Karth;Nikolaus Leopold Resch;17;(23);1;2;5;2;;;;;;;;;;50;27;
7;ESP;9;RCAR;Federico Alonso Tellechea;Arturo Alonso Tellechea;6;(17);7;9;1;6;;;;;;;;;;46;29;
8;ESP;900;RCMSantander;DIEGO BOTIN;PABLO TURRADO;1;4;(17);11;6;8;;;;;;;;;;47;30;
9;GER;216;Flensburg13er Segel-Club;Jan Hauke Erichsen;Max Lutz;(16);3;7;2;7;11;;;;;;;;;;46;30;
10;GBR;77;Exe. S. C;Stevie Morrison;Ben Rhodes;3;(19);3;16;4;5;;;;;;;;;;50;31;
11;DEN;3;Kolding Sejlklub;Allan Nørregaard;Anders Thomsen;(24);5;3;4;11;9;;;;;;;;;;56;32;
12;DEN;30;KDY / Kongelig Dansk Yachtclub;Jonas Warrer;Peter Lang;5;7;8;(13);13;1;;;;;;;;;;47;34;
13;GBR;999;HISC;james peters;ed FitzGerald;11;12;(18);3;2;6;;;;;;;;;;52;34;
14;GER;55;Kieler Yacht Club;Justus Schmidt;Max Boehme;6;8;10;(19);2;8;;;;;;;;;;53;34;
15;GBR;98;Tata steel sailing club;David Evans;Edward Powys;(20);4;9;15;3;3;;;;;;;;;;54;34;
16;ITA;22;Cluc canottieri roggero di lauria;giuseppe angilella;pietro zucchetti;12;2;5;(13);12;4;;;;;;;;;;48;35;
17;SWE;717;GKSS;Carl P Sylvan;Otto Hamel;(16);3;8;16;7;2;;;;;;;;;;52;36;
18;POR;127;FPV-CNC/Lusodiete;Jorge Lima;Jose Luis Costa;4;2;(22);10;8;12;;;;;;;;;;58;36;
19;POL;42;AZS AWFis Gdansk;Lukasz Przybytek;Pawel Kolodzinski;8;(13);5;4;10;9;;;;;;;;;;49;36;
20;AUS;66;BYS;Will Phillips;Rhys Mara;10;1;3;12;(19);11;;;;;;;;;;56;37;
21;FRA;8;YCPR-EMD-Banque Populaire French sailing;Julien d Ortoli;Noé Delpech;18;9;2;(22);5;3;;;;;;;;;;59;37;
22;IRL;99;ballyholme/carrick/royal ulster;Ryan Seaton;Matt McGovern;4;(27);4;3;13;13;;;;;;;;;;64;37;
23;DEN;132;Kongelig Dansk Yachtklub;Mads Emil Lübeck;Christian Peter Lübeck;3;(14);9;7;4;14;;;;;;;;;;51;37;
24;FIN;49;NJK;Lauri Lehtinen;Kalle Bask;10,RDGa;(20);8;14;3;3;;;;;;;;;;58;38;
25;JPN;81;EYC;YUKIO MAKINO;KENJI TAKAHASHI;(32,BFD);10;4;16;5;5;;;;;;;;;;72;40;
26;GBR;114;WOBYC;Nic Asher;Fynn Sterritt;1;10;12;5;14;(24);;;;;;;;;;66;42;
27;CRO;13;JK USKOK;PAVLE KOSTOV;PETAR CUPAC;12;6;1;13;11;(18);;;;;;;;;;61;43;
28;SWE;21;KSSS;Charlie Ekberg;Niclas Düring;(17);15;6;5;10;7;;;;;;;;;;60;43;
29;AUT;192;YCB;Benjamin Bildstein;David Hussl;2;12;9;17;(23);9;;;;;;;;;;72;49;
30;POR;15;FPV-CNC;Bernardo Freitas;Francisco Andrade;19;10;(20);7;8;5;;;;;;;;;;69;49;
31;AUS;400;SYC;Joel Turner;Lewis Brake;(22);6;11;9;18;6;;;;;;;;;;72;50;
32;GBR;118;lymington town sailing club;henry lloyd williams;sam batten;11;1;14;17;(18);8;;;;;;;;;;69;51;
33;RUS;178;Hercules;Artem Basalkin;Nikita Rusakov;2;(24);24;8;4;15;;;;;;;;;;77;53;
34;POL;52;AZS UWM OLSZTYN;Tomasz Januszewski;Jacek Nowak;9;(26);4;8;12;22;;;;;;;;;;81;55;
35;SWE;500;GKSS;Victor Bergström;Victor Västernäs;5;5;(26);12;15;19;;;;;;;;;;82;56;
36;DEN;11;KDY/HS;Jonathan Bay;Christopher Thorsell;10;16;16;5;9;(17);;;;;;;;;;73;56;
37;GBR;101;WPNSA;Stuart Bithell;Chris Grube;9;7;13;12;15;(32,DNF);;;;;;;;;;88;56;
38;AUS;91;RFBYC;David Gilmour;Sam Phillips;(15);15;14;14;10;4;;;;;;;;;;72;57;
39;USA;122;US Sailing Team Sperry Top-Sider;Ryan Pesch;Trevor Burd;14;13;11;10;9;(21);;;;;;;;;;78;57;
40;SWE;131;KSSS;gustav Petterson;Marcus Anjemark;(19);19;7;11;7;14;;;;;;;;;;77;58;
41;ITA;969;Yacht Club Porto San Rocco;Stefano Cherin;Andrea Tesei;9;(27);13;10;14;15;;;;;;;;;;88;61;
42;GBR;19;Hill Head SC/Parkstone YC;John Pink;Simon Wheeler;14;16;12;(18);8;12;;;;;;;;;;80;62;
43;ITA;23;FVRiva;Jacopo Plazzi;Umberto Molineris;12;21;10;4;17;(23);;;;;;;;;;87;64;
44;ESP;800;Real Club Maritimo de Santander;Victor Paya;Alvaro del Arco;15;14;(17);8;16;13;;;;;;;;;;83;66;
45;FRA;144;cnbpp;Kevin Fischer;Marc Mallaret;10;19;13;(21);12;12;;;;;;;;;;87;66;
46;AUS;119;Fremantle Sailing Club;Luke Parkinson;Fang Warren;21;23;(26);6;3;14;;;;;;;;;;93;67;
47;GER;115;SVOS;Philipp Kramer;Thilo Kramer;3;2;21;21;22;(27);;;;;;;;;;96;69;
48;ITA;140;STV - SVMM;Andrea Savio;Alessandro Savio;8;6;19;19;18;(25);;;;;;;;;;95;70;
49;ESP;32;LC VILAGARCIA;Carlos Paz Blanco;Anton Paz Blanco;7;16;(18);15;16;16;;;;;;;;;;88;70;
50;USA;150;Lauderdale yacht club;Brad Funk;zach Brown;13;18;10;(20);19;10;;;;;;;;;;90;70;
51;NZL;117;Napier Sailing Club;Ben Goodwin;Sam Bullock;6;8;15;22;(25);20;;;;;;;;;;96;71;
52;GER;211;VSaW;Tim Elsner;Marco Grasse;(22);18;20;6;9;18;;;;;;;;;;93;71;
53;CAN;905;Royal Canadian Yacht Club;David Mori;Justin Barnes;(32,RET);1;15;18;21;19;;;;;;;;;;106;74;
54;AUS;112;Woolahara Sailing Club;Peter Kendall;Harry Bethwaite;(26);26;14;7;11;16;;;;;;;;;;100;74;
55;CAN;709;RNYC;Jon Ladha;Dan Inkpen;(27);3;15;20;22;15;;;;;;;;;;102;75;
56;BRA;332;Rio Yacht Club;Marlo Soffiatti Grael;Gabriel Portilho Borges;13;21;11;11;20;(30);;;;;;;;;;106;76;
57;SWE;181;KSSS;Sebastian Östling;Kalle torlen;20;8;21;(28);16;13;;;;;;;;;;106;78;
58;ITA;444;s.v. marina militare- s.c.g. salò;luca dubbini;roberto dubbini;(32,DNC);17;16;15;13;17;;;;;;;;;;110;78;
59;DEN;747;Royal Norwegian Yacht Club/HS/KDY;Anders Hylen Klippenberg;Christian Christfort Gormsen;(26);11;25;2;15;26;;;;;;;;;;105;79;
60;SWE;116;GKSS;Fritiof Hedström;Jonatan Bergström;22;(32,BFD);5;23;22;7;;;;;;;;;;111;79;
61;FRA;18;YCPR;Thomas Ribeaud;sébastien Scotto di Fasano;(23);22;12;14;21;11;;;;;;;;;;103;80;
62;BEL;171;RBSC;Yannick Lefebvre;Matthieu Janssens de Bisthoven;7;(29);20;17;19;18;;;;;;;;;;110;81;
63;AUS;222;SSCBC, SYC;George Davies;Jack Lloyd;18;7;19;(23);17;23;;;;;;;;;;107;84;
64;RUS;281;SHVSM Voronez;Pavel Kalinchev;Pavel Karachov;21;22;19;6;17;(32,DNC);;;;;;;;;;117;85;
65;GBR;321;HISC;Tim Gratton;Chris Taylor;15;11;17;(27);20;24;;;;;;;;;;114;87;
66;GER;779;Herrschinger Segelclub;Philipp Müller;Moritz Janich;32,DNE;(21);18;18;14;10;;;;;;;;;;113;92;
67;ARG;113;CNSI;Gonzalo Pollitzer Ramos;Federico Villambrosa;24;12;16;20;(25);20;;;;;;;;;;117;92;
68;SWE;121;Royal Swedish yacht club;Nils Åkervall;David Jonsson;7;17;27;21;23;(32,DNF);;;;;;;;;;127;95;
69;FIN;350;EPS;Joonas Lindahl;Joel Tykkyläinen;8;14;27;24;(29);24;;;;;;;;;;126;97;
70;GER;110;HYC;Kim Niclas Holste;Yannik Holste;23;9;23;(24);24;21;;;;;;;;;;124;100;
71;BRA;300;Iate Clube Rio de Janeiro;Dante Bianchi;Thomas Lowbeer;21;(23);23;19;21;16;;;;;;;;;;123;100;
72;GBR;360;RESTRONGUET SAILING CLUB;JACK HAWKINS;CHRISTOPHER THOMAS;(29);20;23;25;24;10;;;;;;;;;;131;102;
73;DEN;711;KBL;Tobias Hemdorff;Søren W. Kristensen;13;18;29;23;(32,BFD);19;;;;;;;;;;134;102;
74;GER;911;PYC / StSC;Frithjof Schwerdt;Sebastian Wiedemann;11;(30);22;27;26;17;;;;;;;;;;133;103;
75;GBR;333;Brightlingsea SC;David Conlon;Finbar Anderson;2;26;25;(29);24;29;;;;;;;;;;135;106;
76;RUS;686;Druzba;Artemev Yurii;Bubnov Viacheslav;16;25;21;26;(27);22;;;;;;;;;;137;110;
77;SUI;257;Club Nautique de Versoix;Victor Casas;Bryan Mettraux;25;5;24;(32,DNF);25;32,DNF;;;;;;;;;;143;111;
78;GER;220;Flensburger Segelclub;Nils Carstensen;Jan Frigge;23;15;(28);28;23;25;;;;;;;;;;142;114;
79;CRO;102;JK USKOK;DUJE FRZOP;jure frzop;17;(27);24;26;27;21;;;;;;;;;;142;115;
80;RUS;125;SFYC, SHVSM, PGUOR;Konstantin Nosov;Alexander Gaydaenko;20;25;25;25;(26);25;;;;;;;;;;146;120;
81;GBR;494;Grafham Water;Tom Bucktrout;Dominick Burke;19;24;(32,DNF);26;29;23;;;;;;;;;;153;121;
82;CAN;311;Royal Canadian Yacht Club;John Ferguson;Arthur Ferguson;26;24;27;24;20;(28);;;;;;;;;;149;121;
83;FIN;280;EPS;Pekka Saijonmaa;Henri Paatela;27;(30);26;22;27;20;;;;;;;;;;152;122;
84;NOR;888;Asker Seilforening;Bror Føyen With;Ludvig Lilleby Johansson;(29);25;22;25;28;26;;;;;;;;;;155;126;
85;FIN;100;EPS;Erik Lindahl;Max Hasselblatt;24;20;28;(29);28;27;;;;;;;;;;156;127;
86;GBR;600;Arran Yacht Club;Rory Hunter;Neil Hunter;28;29;(32,DNF);32,DNC;26;22;;;;;;;;;;169;137;
87;FIN;290;Espoon pursiseura;Teemu Rantanen;Jukka Saarikorpi;25;28;(32,DNF);27;30;28;;;;;;;;;;170;138;
88;BEL;314;RBSC;Levi Slap;Tom Pelsmaekers;28;28;28;(29);28;26;;;;;;;;;;167;138;
89;FIN;313;BS;Niclas Borenius;Arthur Therman;25;28;(30);28;29;29;;;;;;;;;;169;139;
90;ISR;180;Hapoel Tel-Aviv;Omer Brand;Bar Halevy;30;29;29;30;(32,DNS);30;;;;;;;;;;180;148;
DNQ;ESP;1344;Club Nàutic El Balís;Carlos Robles Lorente;Dani Codina Serra;(32,DNC);32,DNC;32,DNC;32,DNC;32,DNC;32,DNC;;;;;;;;;;192;160;
1 Rank Nat SailNo Club HelmName CrewName Q1 Q2 Q3 Q4 Q5 Q6 F1 F2 F3 F4 F5 F6 F7 F8 F9 Total Nett
2 1 NZL 6 Victoria Cruising Club Marcus Hansen Josh Porebski 4 (22) 2 1 1 2 32 10
3 2 GER 7 NRV Erik Heil Thomas Ploessel 1 (13) 6 1 1 7 29 16
4 3 GBR 96 Silverline Dylan Fletcher Alain Sign 5 4 2 3 (6) 4 24 18
5 4 FRA 14 S.R.Calédonienne/CNSeiez Mathiev Frei Yenn Rocherieux (14) 11 6 1 2 1 35 21
6 5 NZL 2 Tauranga & Kerikeri Peter Burling Blair Tuke (18) 9 1 9 6 1 44 26
7 6 AUT 84 KYK/YCV Nico Luca Marc Delle-Karth Nikolaus Leopold Resch 17 (23) 1 2 5 2 50 27
8 7 ESP 9 RCAR Federico Alonso Tellechea Arturo Alonso Tellechea 6 (17) 7 9 1 6 46 29
9 8 ESP 900 RCMSantander DIEGO BOTIN PABLO TURRADO 1 4 (17) 11 6 8 47 30
10 9 GER 216 Flensburg13er Segel-Club Jan Hauke Erichsen Max Lutz (16) 3 7 2 7 11 46 30
11 10 GBR 77 Exe. S. C Stevie Morrison Ben Rhodes 3 (19) 3 16 4 5 50 31
12 11 DEN 3 Kolding Sejlklub Allan Nørregaard Anders Thomsen (24) 5 3 4 11 9 56 32
13 12 DEN 30 KDY / Kongelig Dansk Yachtclub Jonas Warrer Peter Lang 5 7 8 (13) 13 1 47 34
14 13 GBR 999 HISC james peters ed FitzGerald 11 12 (18) 3 2 6 52 34
15 14 GER 55 Kieler Yacht Club Justus Schmidt Max Boehme 6 8 10 (19) 2 8 53 34
16 15 GBR 98 Tata steel sailing club David Evans Edward Powys (20) 4 9 15 3 3 54 34
17 16 ITA 22 Cluc canottieri roggero di lauria giuseppe angilella pietro zucchetti 12 2 5 (13) 12 4 48 35
18 17 SWE 717 GKSS Carl P Sylvan Otto Hamel (16) 3 8 16 7 2 52 36
19 18 POR 127 FPV-CNC/Lusodiete Jorge Lima Jose Luis Costa 4 2 (22) 10 8 12 58 36
20 19 POL 42 AZS AWFis Gdansk Lukasz Przybytek Pawel Kolodzinski 8 (13) 5 4 10 9 49 36
21 20 AUS 66 BYS Will Phillips Rhys Mara 10 1 3 12 (19) 11 56 37
22 21 FRA 8 YCPR-EMD-Banque Populaire French sailing Julien d Ortoli Noé Delpech 18 9 2 (22) 5 3 59 37
23 22 IRL 99 ballyholme/carrick/royal ulster Ryan Seaton Matt McGovern 4 (27) 4 3 13 13 64 37
24 23 DEN 132 Kongelig Dansk Yachtklub Mads Emil Lübeck Christian Peter Lübeck 3 (14) 9 7 4 14 51 37
25 24 FIN 49 NJK Lauri Lehtinen Kalle Bask 10,RDGa (20) 8 14 3 3 58 38
26 25 JPN 81 EYC YUKIO MAKINO KENJI TAKAHASHI (32,BFD) 10 4 16 5 5 72 40
27 26 GBR 114 WOBYC Nic Asher Fynn Sterritt 1 10 12 5 14 (24) 66 42
28 27 CRO 13 JK USKOK PAVLE KOSTOV PETAR CUPAC 12 6 1 13 11 (18) 61 43
29 28 SWE 21 KSSS Charlie Ekberg Niclas Düring (17) 15 6 5 10 7 60 43
30 29 AUT 192 YCB Benjamin Bildstein David Hussl 2 12 9 17 (23) 9 72 49
31 30 POR 15 FPV-CNC Bernardo Freitas Francisco Andrade 19 10 (20) 7 8 5 69 49
32 31 AUS 400 SYC Joel Turner Lewis Brake (22) 6 11 9 18 6 72 50
33 32 GBR 118 lymington town sailing club henry lloyd williams sam batten 11 1 14 17 (18) 8 69 51
34 33 RUS 178 Hercules Artem Basalkin Nikita Rusakov 2 (24) 24 8 4 15 77 53
35 34 POL 52 AZS UWM OLSZTYN Tomasz Januszewski Jacek Nowak 9 (26) 4 8 12 22 81 55
36 35 SWE 500 GKSS Victor Bergström Victor Västernäs 5 5 (26) 12 15 19 82 56
37 36 DEN 11 KDY/HS Jonathan Bay Christopher Thorsell 10 16 16 5 9 (17) 73 56
38 37 GBR 101 WPNSA Stuart Bithell Chris Grube 9 7 13 12 15 (32,DNF) 88 56
39 38 AUS 91 RFBYC David Gilmour Sam Phillips (15) 15 14 14 10 4 72 57
40 39 USA 122 US Sailing Team Sperry Top-Sider Ryan Pesch Trevor Burd 14 13 11 10 9 (21) 78 57
41 40 SWE 131 KSSS gustav Petterson Marcus Anjemark (19) 19 7 11 7 14 77 58
42 41 ITA 969 Yacht Club Porto San Rocco Stefano Cherin Andrea Tesei 9 (27) 13 10 14 15 88 61
43 42 GBR 19 Hill Head SC/Parkstone YC John Pink Simon Wheeler 14 16 12 (18) 8 12 80 62
44 43 ITA 23 FVRiva Jacopo Plazzi Umberto Molineris 12 21 10 4 17 (23) 87 64
45 44 ESP 800 Real Club Maritimo de Santander Victor Paya Alvaro del Arco 15 14 (17) 8 16 13 83 66
46 45 FRA 144 cnbpp Kevin Fischer Marc Mallaret 10 19 13 (21) 12 12 87 66
47 46 AUS 119 Fremantle Sailing Club Luke Parkinson Fang Warren 21 23 (26) 6 3 14 93 67
48 47 GER 115 SVOS Philipp Kramer Thilo Kramer 3 2 21 21 22 (27) 96 69
49 48 ITA 140 STV - SVMM Andrea Savio Alessandro Savio 8 6 19 19 18 (25) 95 70
50 49 ESP 32 LC VILAGARCIA Carlos Paz Blanco Anton Paz Blanco 7 16 (18) 15 16 16 88 70
51 50 USA 150 Lauderdale yacht club Brad Funk zach Brown 13 18 10 (20) 19 10 90 70
52 51 NZL 117 Napier Sailing Club Ben Goodwin Sam Bullock 6 8 15 22 (25) 20 96 71
53 52 GER 211 VSaW Tim Elsner Marco Grasse (22) 18 20 6 9 18 93 71
54 53 CAN 905 Royal Canadian Yacht Club David Mori Justin Barnes (32,RET) 1 15 18 21 19 106 74
55 54 AUS 112 Woolahara Sailing Club Peter Kendall Harry Bethwaite (26) 26 14 7 11 16 100 74
56 55 CAN 709 RNYC Jon Ladha Dan Inkpen (27) 3 15 20 22 15 102 75
57 56 BRA 332 Rio Yacht Club Marlo Soffiatti Grael Gabriel Portilho Borges 13 21 11 11 20 (30) 106 76
58 57 SWE 181 KSSS Sebastian Östling Kalle torlen 20 8 21 (28) 16 13 106 78
59 58 ITA 444 s.v. marina militare- s.c.g. salò luca dubbini roberto dubbini (32,DNC) 17 16 15 13 17 110 78
60 59 DEN 747 Royal Norwegian Yacht Club/HS/KDY Anders Hylen Klippenberg Christian Christfort Gormsen (26) 11 25 2 15 26 105 79
61 60 SWE 116 GKSS Fritiof Hedström Jonatan Bergström 22 (32,BFD) 5 23 22 7 111 79
62 61 FRA 18 YCPR Thomas Ribeaud sébastien Scotto di Fasano (23) 22 12 14 21 11 103 80
63 62 BEL 171 RBSC Yannick Lefebvre Matthieu Janssens de Bisthoven 7 (29) 20 17 19 18 110 81
64 63 AUS 222 SSCBC, SYC George Davies Jack Lloyd 18 7 19 (23) 17 23 107 84
65 64 RUS 281 SHVSM Voronez Pavel Kalinchev Pavel Karachov 21 22 19 6 17 (32,DNC) 117 85
66 65 GBR 321 HISC Tim Gratton Chris Taylor 15 11 17 (27) 20 24 114 87
67 66 GER 779 Herrschinger Segelclub Philipp Müller Moritz Janich 32,DNE (21) 18 18 14 10 113 92
68 67 ARG 113 CNSI Gonzalo Pollitzer Ramos Federico Villambrosa 24 12 16 20 (25) 20 117 92
69 68 SWE 121 Royal Swedish yacht club Nils Åkervall David Jonsson 7 17 27 21 23 (32,DNF) 127 95
70 69 FIN 350 EPS Joonas Lindahl Joel Tykkyläinen 8 14 27 24 (29) 24 126 97
71 70 GER 110 HYC Kim Niclas Holste Yannik Holste 23 9 23 (24) 24 21 124 100
72 71 BRA 300 Iate Clube Rio de Janeiro Dante Bianchi Thomas Lowbeer 21 (23) 23 19 21 16 123 100
73 72 GBR 360 RESTRONGUET SAILING CLUB JACK HAWKINS CHRISTOPHER THOMAS (29) 20 23 25 24 10 131 102
74 73 DEN 711 KBL Tobias Hemdorff Søren W. Kristensen 13 18 29 23 (32,BFD) 19 134 102
75 74 GER 911 PYC / StSC Frithjof Schwerdt Sebastian Wiedemann 11 (30) 22 27 26 17 133 103
76 75 GBR 333 Brightlingsea SC David Conlon Finbar Anderson 2 26 25 (29) 24 29 135 106
77 76 RUS 686 Druzba Artemev Yurii Bubnov Viacheslav 16 25 21 26 (27) 22 137 110
78 77 SUI 257 Club Nautique de Versoix Victor Casas Bryan Mettraux 25 5 24 (32,DNF) 25 32,DNF 143 111
79 78 GER 220 Flensburger Segelclub Nils Carstensen Jan Frigge 23 15 (28) 28 23 25 142 114
80 79 CRO 102 JK USKOK DUJE FRZOP jure frzop 17 (27) 24 26 27 21 142 115
81 80 RUS 125 SFYC, SHVSM, PGUOR Konstantin Nosov Alexander Gaydaenko 20 25 25 25 (26) 25 146 120
82 81 GBR 494 Grafham Water Tom Bucktrout Dominick Burke 19 24 (32,DNF) 26 29 23 153 121
83 82 CAN 311 Royal Canadian Yacht Club John Ferguson Arthur Ferguson 26 24 27 24 20 (28) 149 121
84 83 FIN 280 EPS Pekka Saijonmaa Henri Paatela 27 (30) 26 22 27 20 152 122
85 84 NOR 888 Asker Seilforening Bror Føyen With Ludvig Lilleby Johansson (29) 25 22 25 28 26 155 126
86 85 FIN 100 EPS Erik Lindahl Max Hasselblatt 24 20 28 (29) 28 27 156 127
87 86 GBR 600 Arran Yacht Club Rory Hunter Neil Hunter 28 29 (32,DNF) 32,DNC 26 22 169 137
88 87 FIN 290 Espoon pursiseura Teemu Rantanen Jukka Saarikorpi 25 28 (32,DNF) 27 30 28 170 138
89 88 BEL 314 RBSC Levi Slap Tom Pelsmaekers 28 28 28 (29) 28 26 167 138
90 89 FIN 313 BS Niclas Borenius Arthur Therman 25 28 (30) 28 29 29 169 139
91 90 ISR 180 Hapoel Tel-Aviv Omer Brand Bar Halevy 30 29 29 30 (32,DNS) 30 180 148
92 DNQ ESP 1344 Club Nàutic El Balís Carlos Robles Lorente Dani Codina Serra (32,DNC) 32,DNC 32,DNC 32,DNC 32,DNC 32,DNC 192 160
@@ -0,0 +1,93 @@
package com.sap.sailing.sailwave.resultimport.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.RegattaScoreCorrections;
import com.sap.sailing.domain.common.RegattaScoreCorrections.ScoreCorrectionsForRace;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.resultimport.RegattaResults;
import com.sap.sailing.resultimport.ResultDocumentDescriptor;
import com.sap.sailing.resultimport.ResultDocumentProvider;
import com.sap.sailing.resultimport.impl.ResultDocumentDescriptorImpl;
import com.sap.sailing.sailwave.resultimport.CsvParserFactory;
import com.sap.sailing.sailwave.resultimport.impl.ScoreCorrectionProviderImpl;
public class ParserTest {
private static final String SAMPLE_INPUT_NAME_49er = "49er_R1-6.csv";
private static final String SAMPLE_INPUT_NAME_49erFX = "49erFX_R1-6.csv";
private static final String RESOURCES = "resources/";
private InputStream getInputStream(String filename) throws FileNotFoundException, IOException {
return new FileInputStream(getFile(filename));
}
private File getFile(String filename) {
return new File(RESOURCES + filename);
}
private ResultDocumentProvider getTestDocumentProvider() {
return new ResultDocumentProvider() {
@Override
public Iterable<ResultDocumentDescriptor> getResultDocumentDescriptors() throws IOException {
try {
List<ResultDocumentDescriptor> result = new ArrayList<>();
TimePoint now = MillisecondsTimePoint.now();
result.add(new ResultDocumentDescriptorImpl(getInputStream(SAMPLE_INPUT_NAME_49er), SAMPLE_INPUT_NAME_49er, now));
result.add(new ResultDocumentDescriptorImpl(getInputStream(SAMPLE_INPUT_NAME_49erFX), SAMPLE_INPUT_NAME_49erFX, now));
return result;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
};
}
@Test
public void testParsingSomeDocuments() throws Exception {
RegattaResults parseResults49er = CsvParserFactory.INSTANCE.createParser(getInputStream(SAMPLE_INPUT_NAME_49er),
SAMPLE_INPUT_NAME_49er, MillisecondsTimePoint.now()).parseResults();
assertNotNull(parseResults49er);
RegattaResults parseResults49erFX = CsvParserFactory.INSTANCE.createParser(getInputStream(SAMPLE_INPUT_NAME_49erFX),
SAMPLE_INPUT_NAME_49erFX, MillisecondsTimePoint.now()).parseResults();
assertNotNull(parseResults49erFX);
}
@Test
public void testScoreCorrectionProvider49er() throws Exception {
ScoreCorrectionProviderImpl scoreCorrectionProvider = new ScoreCorrectionProviderImpl(getTestDocumentProvider(),
CsvParserFactory.INSTANCE);
Map<String, Set<Pair<String, TimePoint>>> hasResultsFor = scoreCorrectionProvider.getHasResultsForBoatClassFromDateByEventName();
RegattaScoreCorrections result49er = scoreCorrectionProvider.getScoreCorrections(SAMPLE_INPUT_NAME_49er,
"49er", hasResultsFor.get(SAMPLE_INPUT_NAME_49er).iterator().next().getB());
assertNotNull(result49er);
Iterable<ScoreCorrectionsForRace> scoreCorrectionsForRaces = result49er.getScoreCorrectionsForRaces();
assertNotNull(scoreCorrectionsForRaces);
assertEquals(6, Util.size(scoreCorrectionsForRaces)); // 6 races
{
final ScoreCorrectionsForRace resultsForR2 = Util.get(scoreCorrectionsForRaces, 1);
assertEquals(32, resultsForR2.getScoreCorrectionForCompetitor("SWE 116").getPoints(), 0.00000001);
assertSame(MaxPointsReason.BFD, resultsForR2.getScoreCorrectionForCompetitor("SWE 116").getMaxPointsReason());
assertEquals("Fritiof Hedström+Jonatan Bergström",
resultsForR2.getScoreCorrectionForCompetitor("SWE 116").getCompetitorName());
}
}
}
@@ -1,9 +0,0 @@
package com.sap.sailing.sailwave.resultimport.test;
import org.junit.Test;
public class PlaceHolderTest {
@Test
public void testNothing() {
}
}
@@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: SailWave result import
Bundle-SymbolicName: com.sap.sailing.sailwave.resultimport
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.sap.sailing.sailwave.resultimport.Activator
Bundle-Activator: com.sap.sailing.sailwave.resultimport.impl.Activator
Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Import-Package: org.osgi.framework;version="1.5.0"
@@ -1,12 +0,0 @@
package com.sap.sailing.sailwave.resultimport;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class Activator implements BundleActivator {
public void start(BundleContext bundleContext) throws Exception {
}
public void stop(BundleContext bundleContext) throws Exception {
}
}
@@ -0,0 +1,14 @@
package com.sap.sailing.sailwave.resultimport;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.resultimport.RegattaResults;
public interface CsvParser {
RegattaResults parseResults() throws Exception;
String getBoatClass();
String getFilename();
TimePoint getLastModified();
}
@@ -0,0 +1,11 @@
package com.sap.sailing.sailwave.resultimport;
import java.io.InputStream;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.sailwave.resultimport.impl.CsvParserFactoryImpl;
public interface CsvParserFactory {
CsvParserFactory INSTANCE = new CsvParserFactoryImpl();
CsvParser createParser(InputStream is, String name, TimePoint lastModified);
}
@@ -0,0 +1,28 @@
package com.sap.sailing.sailwave.resultimport.impl;
import java.io.File;
import org.osgi.framework.BundleContext;
import com.sap.sailing.domain.common.ScoreCorrectionProvider;
import com.sap.sailing.resultimport.impl.AbstractFileBasedScoreCorrectionProviderActivator;
import com.sap.sailing.resultimport.impl.FileBasedResultDocumentProvider;
import com.sap.sailing.sailwave.resultimport.CsvParserFactory;
public class Activator extends AbstractFileBasedScoreCorrectionProviderActivator {
private static final String SCAN_DIR_PATH_PROPERTY_NAME = "sailwave.results";
private static final String DEFAULT_SCAN_DIR = "sailwave";
public Activator() {
super(SCAN_DIR_PATH_PROPERTY_NAME, DEFAULT_SCAN_DIR);
}
@Override
public void stop(BundleContext context) throws Exception {
}
@Override
protected ScoreCorrectionProvider create(File scanDir) {
return new ScoreCorrectionProviderImpl(new FileBasedResultDocumentProvider(scanDir), CsvParserFactory.INSTANCE);
}
}
@@ -0,0 +1,14 @@
package com.sap.sailing.sailwave.resultimport.impl;
import java.io.InputStream;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.sailwave.resultimport.CsvParser;
import com.sap.sailing.sailwave.resultimport.CsvParserFactory;
public class CsvParserFactoryImpl implements CsvParserFactory {
@Override
public CsvParser createParser(InputStream is, String name, TimePoint lastModified) {
return new CsvParserImpl(is, name, lastModified);
}
}
@@ -0,0 +1,157 @@
package com.sap.sailing.sailwave.resultimport.impl;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.resultimport.CompetitorEntry;
import com.sap.sailing.resultimport.CompetitorRow;
import com.sap.sailing.resultimport.RegattaResults;
import com.sap.sailing.resultimport.impl.CompetitorRowImpl;
import com.sap.sailing.resultimport.impl.DefaultCompetitorEntryImpl;
import com.sap.sailing.sailwave.resultimport.CsvParser;
public class CsvParserImpl implements CsvParser {
private final InputStream inputStream;
private final String filename;
private final TimePoint lastModified;
private final String SEPARATOR = ";";
public CsvParserImpl(InputStream inputStream, String filename, TimePoint lastModified) {
this.inputStream = inputStream;
this.filename = filename;
this.lastModified = lastModified;
}
@Override
public String getFilename() {
return filename;
}
@Override
public String getBoatClass() {
String result = "Unknown Boatclass";
// we assume the boat class name is in the filename
int underScoreIndex = filename.lastIndexOf("_");
if(underScoreIndex > 0) {
result = filename.substring(0, underScoreIndex);
}
return result;
}
@Override
public RegattaResults parseResults() throws Exception {
final List<CompetitorRow> competitorRows = new ArrayList<>();
// Sample line for a couple of races
// Rank;Nat;SailNo;Club;HelmName;CrewName;Q1;Q2;Q3;Q4;Q5;Q6;F1;F2;F3;F4;F5;F6;F7;F8;F9;Total;Nett;
// 1;NZL;6;Victoria Cruising Club;Marcus Hansen;Josh Porebski;4;(22);2;1;1;2;;;;;;;;;;32;10;
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "cp1252"));
String line = br.readLine();
int startIndexForRacePoints = -1;
int endIndexForRacePoints = -1;
while (line != null) {
int firstSeparator = line.indexOf(SEPARATOR);
if(line.startsWith("DNQ")) {
// ignore line
} else if (firstSeparator > 0) {
String firstEntry = line.substring(0, firstSeparator);
if(firstEntry.startsWith("Rank")) {
// header line
// scan the number of races
String[] splittedHeadline = line.split(SEPARATOR);
for(int i = 0; i < splittedHeadline.length; i++) {
// find index of 'CrewName'
if(splittedHeadline[i].equals("CrewName")) {
startIndexForRacePoints = i+1;
} else if (splittedHeadline[i].equals("Total")) {
endIndexForRacePoints = i-1;
}
}
} else {
try {
// check for valid race row
Integer.parseInt(firstEntry);
String[] splittedRow = line.split(SEPARATOR);
String sailID = splittedRow[1] + " " + splittedRow[2];
Integer totalRank = Integer.parseInt(splittedRow[0]);
List<String> names = new ArrayList<String>();
List<CompetitorEntry> rankAndMaxPointsReasonAndPointsAndDiscarded = new ArrayList<>();
names.add(splittedRow[4]);
names.add(splittedRow[5]);
int index = startIndexForRacePoints;
while(index <= endIndexForRacePoints) {
String pointsAndMaxPointsReasonAndDiscard = splittedRow[index];
if(pointsAndMaxPointsReasonAndDiscard != null && !pointsAndMaxPointsReasonAndDiscard.isEmpty()) {
Integer rank = null;
String maxPointsReason;
Double points;
boolean discarded = false;
// sample for points and maxPointReason and discard in one field: (32,DNF)
if(pointsAndMaxPointsReasonAndDiscard.startsWith("(") && pointsAndMaxPointsReasonAndDiscard.endsWith(")")) {
pointsAndMaxPointsReasonAndDiscard = pointsAndMaxPointsReasonAndDiscard.substring(1, pointsAndMaxPointsReasonAndDiscard.length() - 1);
discarded = true;
}
if(pointsAndMaxPointsReasonAndDiscard.contains(",")) {
String[] splittedPointsAndMaxPointReason = pointsAndMaxPointsReasonAndDiscard.split(",");
points = Double.valueOf(splittedPointsAndMaxPointReason[0]);
maxPointsReason = splittedPointsAndMaxPointReason[1];
} else {
points = Double.valueOf(pointsAndMaxPointsReasonAndDiscard);
maxPointsReason = null;
}
if (points != 0.0) {
CompetitorEntry entry = new DefaultCompetitorEntryImpl(rank,
maxPointsReason, points, discarded);
rankAndMaxPointsReasonAndPointsAndDiscarded.add(entry);
} else {
rankAndMaxPointsReasonAndPointsAndDiscarded.add(null);
}
}
index++;
}
CompetitorRow competitorRow = new CompetitorRowImpl(totalRank, sailID, names, null,
null, rankAndMaxPointsReasonAndPointsAndDiscarded);
competitorRows.add(competitorRow);
} catch (NumberFormatException e) {
// ignore lines with no rank at the beginning
}
}
} else {
// probably last line
}
line = br.readLine();
}
return new RegattaResults() {
@Override
public Map<String, String> getMetadata() {
Map<String, String> result = new HashMap<>();
return result;
}
@Override
public List<CompetitorRow> getCompetitorResults() {
return competitorRows;
}
};
}
public TimePoint getLastModified() {
return lastModified;
}
}
@@ -0,0 +1,85 @@
package com.sap.sailing.sailwave.resultimport.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import com.sap.sailing.domain.common.RegattaScoreCorrections;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.resultimport.RegattaResults;
import com.sap.sailing.resultimport.ResultDocumentDescriptor;
import com.sap.sailing.resultimport.ResultDocumentProvider;
import com.sap.sailing.resultimport.impl.AbstractDocumentBasedScoreCorrectionProvider;
import com.sap.sailing.resultimport.impl.RegattaScoreCorrectionsImpl;
import com.sap.sailing.sailwave.resultimport.CsvParser;
import com.sap.sailing.sailwave.resultimport.CsvParserFactory;
public class ScoreCorrectionProviderImpl extends AbstractDocumentBasedScoreCorrectionProvider {
private static final long serialVersionUID = 4767200739966995306L;
private static final String NAME = "Sailwave CSV result importer";
private static final Logger logger = Logger.getLogger(ScoreCorrectionProviderImpl.class.getName());
private final CsvParserFactory parserFactory;
public ScoreCorrectionProviderImpl(ResultDocumentProvider documentProvider, CsvParserFactory parserFactory) {
super(documentProvider);
this.parserFactory = parserFactory;
}
@Override
public String getName() {
return NAME;
}
@Override
public Map<String, Set<Pair<String, TimePoint>>> getHasResultsForBoatClassFromDateByEventName() throws Exception {
Map<String, Set<Pair<String, TimePoint>>> result = new HashMap<String, Set<Pair<String, TimePoint>>>();
for (CsvParser parser : getAllRegattaResults()) {
try {
parser.parseResults();
String boatClass = parser.getBoatClass();
result.put(/* use document name as "event" name */ parser.getFilename(),
Collections.singleton(new Pair<String, TimePoint>(boatClass, parser.getLastModified())));
} catch (Exception e) {
logger.info("Parse error during CSV import. Ignoring document " + parser.toString());
logger.throwing(ScoreCorrectionProviderImpl.class.getName(), "getHasResultsForBoatClassFromDateByEventName", e);
}
}
return result;
}
@Override
public RegattaScoreCorrections getScoreCorrections(String eventName, String boatClassName,
TimePoint timePointPublished) throws Exception {
for (CsvParser parser : getAllRegattaResults()) {
try {
if(parser.getFilename().equals(eventName)) {
RegattaResults regattaResult = parser.parseResults();
return new RegattaScoreCorrectionsImpl(this, regattaResult);
}
} catch (Exception e) {
logger.info("Parse error during CSV import. Ignoring document " + parser.toString());
logger.throwing(ScoreCorrectionProviderImpl.class.getName(), "getScoreCorrections", e);
}
}
return null;
}
private Iterable<CsvParser> getAllRegattaResults() throws Exception {
List<CsvParser> result = new ArrayList<>();
for (ResultDocumentDescriptor resultDocDescr : getResultDocumentProvider().getResultDocumentDescriptors()) {
CsvParser parser = parserFactory.createParser(resultDocDescr.getInputStream(), resultDocDescr.getDocumentName(), resultDocDescr.getLastModified());
result.add(parser);
}
return result;
}
}
@@ -241,7 +241,7 @@ public class LeaderboardMasterDataJsonDeserializer implements JsonDeserializer<L
}
int[] result = new int[indeces.size()];
for (int i = 0; i < result.length; i++) {
result[i] = (Integer) indeces.get(i);
result[i] = ((Long) indeces.get(i)).intValue();
}
return result;
}
@@ -0,0 +1,31 @@
package com.sap.sailing.server.gateway.deserialization.masterdata.impl;
import java.util.Date;
import org.json.simple.JSONObject;
import com.sap.sailing.domain.common.media.MediaTrack;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.serialization.masterdata.impl.MediaTrackJsonSerializer;
public class MediaTrackJsonDeserializer implements JsonDeserializer<MediaTrack> {
@Override
public MediaTrack deserialize(JSONObject object) throws JsonDeserializationException {
String dbId = (String) object.get(MediaTrackJsonSerializer.FIELD_DB_ID);
int durationInMillis = ((Long) object.get(MediaTrackJsonSerializer.FIELD_DURATION)).intValue();
MediaTrack.MimeType mimeType = MediaTrack.MimeType.valueOf((String) object
.get(MediaTrackJsonSerializer.FIELD_MIME_TYPE));
long startTimeInMillis = (Long) object.get(MediaTrackJsonSerializer.FIELD_START_TIME);
Date startTime = new Date(startTimeInMillis);
MediaTrack.Status status = MediaTrack.Status
.valueOf((String) object.get(MediaTrackJsonSerializer.FIELD_STATUS));
String title = (String) object.get(MediaTrackJsonSerializer.FIELD_TITLE);
String url = (String) object.get(MediaTrackJsonSerializer.FIELD_URL);
MediaTrack mediaTrack = new MediaTrack(dbId, title, url, startTime, durationInMillis, mimeType);
mediaTrack.status = status;
return mediaTrack;
}
}
@@ -0,0 +1,31 @@
package com.sap.sailing.server.gateway.serialization.masterdata.impl;
import org.json.simple.JSONObject;
import com.sap.sailing.domain.common.media.MediaTrack;
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
public class MediaTrackJsonSerializer implements JsonSerializer<MediaTrack> {
public static final String FIELD_DB_ID = "dbId";
public static final String FIELD_DURATION = "duration";
public static final String FIELD_MIME_TYPE = "mimeType";
public static final String FIELD_START_TIME = "startTime";
public static final String FIELD_STATUS = "status";
public static final String FIELD_TITLE = "title";
public static final String FIELD_URL = "url";
@Override
public JSONObject serialize(MediaTrack mediaTrack) {
JSONObject result = new JSONObject();
result.put(FIELD_DB_ID, mediaTrack.dbId);
result.put(FIELD_DURATION, mediaTrack.durationInMillis);
result.put(FIELD_MIME_TYPE, mediaTrack.mimeType.name());
result.put(FIELD_START_TIME, mediaTrack.startTime.getTime());
result.put(FIELD_STATUS, mediaTrack.status.name());
result.put(FIELD_TITLE, mediaTrack.title);
result.put(FIELD_URL, mediaTrack.url);
return result;
}
}
@@ -1,13 +1,16 @@
package com.sap.sailing.server.gateway.serialization.masterdata.impl;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.media.MediaTrack;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
@@ -21,19 +24,28 @@ import com.sap.sailing.server.gateway.serialization.JsonSerializer;
*/
public class TopLevelMasterDataSerializer {
public static final String FIELD_PER_LG = "perLg";
public static final String FIELD_MEDIA = "media";
private final Map<String, LeaderboardGroup> allLeaderboardGroups;
private final Iterable<Event> allEvents;
private final ConcurrentHashMap<String, Regatta> regattaForRaceIdStrings;
private final Collection<MediaTrack> allMediaTracks;
private final JsonSerializer<MediaTrack> mediaTrackSerializer;
public TopLevelMasterDataSerializer(Map<String, LeaderboardGroup> allLeaderboardGroups, Iterable<Event> allEvents, ConcurrentHashMap<String, Regatta> regattaForRaceIdString) {
public TopLevelMasterDataSerializer(Map<String, LeaderboardGroup> allLeaderboardGroups, Iterable<Event> allEvents,
ConcurrentHashMap<String, Regatta> regattaForRaceIdString, Collection<MediaTrack> allMediaTracks) {
this.allLeaderboardGroups = allLeaderboardGroups;
this.allEvents = allEvents;
this.regattaForRaceIdStrings = regattaForRaceIdString;
this.allMediaTracks = allMediaTracks;
mediaTrackSerializer = new MediaTrackJsonSerializer();
}
public JSONArray serialize(Set<String> requestedLeaderboardGroupNames) {
JSONArray masterData = new JSONArray();
public JSONObject serialize(Set<String> requestedLeaderboardGroupNames) {
JSONObject masterData = new JSONObject();
JSONArray masterDataPerLg = new JSONArray();
for (String name : requestedLeaderboardGroupNames) {
LeaderboardGroup leaderboardGroup = allLeaderboardGroups.get(name);
@@ -41,10 +53,20 @@ public class TopLevelMasterDataSerializer {
continue;
}
JsonSerializer<LeaderboardGroup> serializer = new LeaderboardGroupMasterDataJsonSerializer(allEvents, regattaForRaceIdStrings);
masterData.add(serializer.serialize(leaderboardGroup));
masterDataPerLg.add(serializer.serialize(leaderboardGroup));
}
masterData.put(FIELD_PER_LG, masterDataPerLg);
masterData.put(FIELD_MEDIA, createJsonArrayForMediaTracks());
return masterData;
}
private JSONArray createJsonArrayForMediaTracks() {
JSONArray array = new JSONArray();
for (MediaTrack mediaTrack : allMediaTracks) {
array.add(mediaTrackSerializer.serialize(mediaTrack));
}
return array;
}
}
@@ -13,7 +13,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sailing.server.gateway.AbstractJsonHttpServlet;
@@ -40,9 +40,9 @@ public class MasterDataByLeaderboardGroupJsonGetServlet extends AbstractJsonHttp
}
TopLevelMasterDataSerializer masterSerializer = new TopLevelMasterDataSerializer(leaderboardGroups,
getService().getAllEvents(), getService().getPersistentRegattasForRaceIDs());
getService().getAllEvents(), getService().getPersistentRegattasForRaceIDs(), getService().getAllMediaTracks());
JSONArray masterData = masterSerializer.serialize(requestedLeaderboardGroupNames);
JSONObject masterData = masterSerializer.serialize(requestedLeaderboardGroupNames);
setJsonResponseHeader(resp);
masterData.writeJSONString(resp.getWriter());
@@ -4,6 +4,7 @@ import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
@@ -14,7 +15,6 @@ import java.util.concurrent.ConcurrentHashMap;
import junit.framework.Assert;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.junit.After;
import org.junit.Test;
@@ -43,25 +43,23 @@ import com.sap.sailing.domain.base.impl.NationalityImpl;
import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.SeriesImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.common.MasterDataImportObjectCreationCount;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.MasterDataImportObjectCreationCountImpl;
import com.sap.sailing.domain.common.media.MediaTrack;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
import com.sap.sailing.domain.masterdataimport.LeaderboardGroupMasterData;
import com.sap.sailing.domain.racelog.RaceLogEventFactory;
import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent;
import com.sap.sailing.domain.racelog.impl.RaceLogEventFactoryImpl;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.mongodb.MongoDBService;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.masterdata.impl.LeaderboardGroupMasterDataJsonDeserializer;
import com.sap.sailing.server.gateway.serialization.masterdata.impl.TopLevelMasterDataSerializer;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sailing.server.masterdata.MasterDataImporter;
import com.sap.sailing.server.operationaltransformation.DummyTrackedRace;
import com.sap.sailing.server.operationaltransformation.ImportMasterDataOperation;
public class MasterDataImportTest {
@@ -119,6 +117,12 @@ public class MasterDataImportTest {
// raceLogCollection.remove(result.next());
// }
// }
//Remove all media tracks
Collection<MediaTrack> tracks = service.getAllMediaTracks();
for (MediaTrack track : tracks) {
service.mediaTrackDeleted(track);
}
}
@Test
@@ -209,11 +213,11 @@ public class MasterDataImportTest {
// Serialize
TopLevelMasterDataSerializer serializer = new TopLevelMasterDataSerializer(
sourceService.getLeaderboardGroups(), sourceService.getAllEvents(),
sourceService.getPersistentRegattasForRaceIDs());
sourceService.getPersistentRegattasForRaceIDs(), sourceService.getAllMediaTracks());
Set<String> names = new HashSet<String>();
names.add(TEST_GROUP_NAME);
JSONArray masterDataOverallArray = serializer.serialize(names);
Assert.assertNotNull(masterDataOverallArray);
JSONObject masterDataOverallObject = serializer.serialize(names);
Assert.assertNotNull(masterDataOverallObject);
// Delete all data above from the database, to allow recreating all of it on target server
deleteCreatedDataFromDatabase();
@@ -221,18 +225,9 @@ public class MasterDataImportTest {
// Deserialization copied from doPost in MasterDataByLeaderboardGroupJsonPostServlet
RacingEventService destService = new RacingEventServiceImplMock();
DomainFactory domainFactory = DomainFactory.INSTANCE;
MasterDataImportObjectCreationCountImpl creationCount = new MasterDataImportObjectCreationCountImpl();
JsonDeserializer<LeaderboardGroupMasterData> leaderboardGroupMasterDataDeserializer = LeaderboardGroupMasterDataJsonDeserializer
.create(domainFactory);
JSONArray leaderboardGroupsMasterDataJsonArray = masterDataOverallArray;
// Actual import. Roughly copied from doPost in MasterDataByLeaderboardGroupJsonPostServlet
for (Object leaderBoardGroupMasterData : leaderboardGroupsMasterDataJsonArray) {
JSONObject leaderBoardGroupMasterDataJson = (JSONObject) leaderBoardGroupMasterData;
LeaderboardGroupMasterData masterData = leaderboardGroupMasterDataDeserializer
.deserialize(leaderBoardGroupMasterDataJson);
ImportMasterDataOperation op = new ImportMasterDataOperation(masterData);
creationCount.add(destService.apply(op));
}
MasterDataImporter importer = new MasterDataImporter(domainFactory, destService);
MasterDataImportObjectCreationCount creationCount = importer.importMasterData(
masterDataOverallObject.toString(), false);
Assert.assertNotNull(creationCount);
Event eventOnTarget = destService.getEvent(eventUUID);
@@ -375,11 +370,12 @@ public class MasterDataImportTest {
// Serialize
TopLevelMasterDataSerializer serializer = new TopLevelMasterDataSerializer(
sourceService.getLeaderboardGroups(), sourceService.getAllEvents(), sourceService.getPersistentRegattasForRaceIDs());
sourceService.getLeaderboardGroups(), sourceService.getAllEvents(),
sourceService.getPersistentRegattasForRaceIDs(), sourceService.getAllMediaTracks());
Set<String> names = new HashSet<String>();
names.add(TEST_GROUP_NAME);
JSONArray masterDataOverallArray = serializer.serialize(names);
Assert.assertNotNull(masterDataOverallArray);
JSONObject masterDataOverallObject = serializer.serialize(names);
Assert.assertNotNull(masterDataOverallObject);
// Delete all data above from the database, to allow recreating all of it on target server
deleteCreatedDataFromDatabase();
@@ -414,18 +410,10 @@ public class MasterDataImportTest {
// Deserialization copied from SailingServiceImpl
DomainFactory domainFactory = DomainFactory.INSTANCE;
MasterDataImportObjectCreationCountImpl creationCount = new MasterDataImportObjectCreationCountImpl();
JsonDeserializer<LeaderboardGroupMasterData> leaderboardGroupMasterDataDeserializer = LeaderboardGroupMasterDataJsonDeserializer
.create(domainFactory);
JSONArray leaderboardGroupsMasterDataJsonArray = masterDataOverallArray;
// Actual import. Roughly copied from SailingServiceImpl
for (Object leaderBoardGroupMasterData : leaderboardGroupsMasterDataJsonArray) {
JSONObject leaderBoardGroupMasterDataJson = (JSONObject) leaderBoardGroupMasterData;
LeaderboardGroupMasterData masterData = leaderboardGroupMasterDataDeserializer
.deserialize(leaderBoardGroupMasterDataJson);
ImportMasterDataOperation op = new ImportMasterDataOperation(masterData);
creationCount.add(destService.apply(op));
}
MasterDataImporter importer = new MasterDataImporter(domainFactory, destService);
MasterDataImportObjectCreationCount creationCount = importer.importMasterData(
masterDataOverallObject.toString(), false);
//---Asserts---
@@ -455,6 +443,282 @@ public class MasterDataImportTest {
Assert.assertEquals(leaderboardNotToOverride.getDisplayName(), leaderboardOnTarget.getDisplayName());
Assert.assertFalse(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget));
}
@Test
public void testMasterDataImportWithOverrideWithoutHttpStack() throws MalformedURLException, IOException, InterruptedException {
// Setup source service
RacingEventService sourceService = new RacingEventServiceImpl();
Event event = sourceService.addEvent(TEST_EVENT_NAME, "testVenue", "", false, eventUUID,
new ArrayList<String>());
UUID courseAreaUUID = UUID.randomUUID();
CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID);
event.getVenue().addCourseArea(courseArea);
List<String> raceColumnNames = new ArrayList<String>();
String raceColumnName = "T1";
raceColumnNames.add(raceColumnName);
raceColumnNames.add("T2");
List<Series> series = new ArrayList<Series>();
List<Fleet> fleets = new ArrayList<Fleet>();
FleetImpl testFleet1 = new FleetImpl("testFleet1");
fleets.add(testFleet1);
fleets.add(new FleetImpl("testFleet2"));
series.add(new SeriesImpl("testSeries", false, fleets, raceColumnNames, sourceService));
UUID regattaUUID = UUID.randomUUID();
Regatta regatta = sourceService.createRegatta("testRegatta", "29er", regattaUUID, series, true, new LowPoint(),
courseAreaUUID);
event.addRegatta(regatta);
int[] discardRule = { 1, 2, 3, 4 };
Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(),
"testDisplayName", discardRule);
List<String> leaderboardNames = new ArrayList<String>();
leaderboardNames.add(leaderboard.getName());
LeaderboardGroup group = sourceService.addLeaderboardGroup(TEST_GROUP_NAME, "testGroupDesc", false,
leaderboardNames, null, null);
// Set tracked Race with competitors
Set<Competitor> competitors = new HashSet<Competitor>();
UUID competitorUUID = UUID.randomUUID();
Set<Person> sailors = new HashSet<Person>();
sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L),
"Oberhoschy"));
Person coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L),
"Der Lennart halt");
Team team = new TeamImpl("Pros", sailors, coach);
BoatClass boatClass = new BoatClassImpl("H16", true);
Boat boat = new BoatImpl("Wingy", boatClass, "GER70133");
CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", team, boat);
competitors.add(competitor);
UUID competitorToSuppressUUID = UUID.randomUUID();
Set<Person> sailors2 = new HashSet<Person>();
sailors2.add(new PersonImpl("Angela Merkel", new NationalityImpl("GER"), new Date(645487200000L),
"segelt auch mit"));
Person coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L),
"Bester Coach");
Team team2 = new TeamImpl("Noobs", sailors2, coach2);
Boat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337");
CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", team2, boat2);
competitors.add(competitorToSuppress);
TrackedRace trackedRace = new DummyTrackedRace(competitors, regatta);
RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName);
raceColumn.setTrackedRace(testFleet1, trackedRace);
// Set log event
RaceLogEventFactory factory = new RaceLogEventFactoryImpl();
TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L);
RaceLogStartTimeEvent logEvent = factory.createStartTimeEvent(logTimePoint, 1,
logTimePoint);
raceColumn.getRaceLog(testFleet1).add(logEvent);
storedLogUUIDs.add(logEvent.getId());
// Set score correction
double scoreCorrection = 12.0;
leaderboard.getScoreCorrection().correctScore(competitor, raceColumn, scoreCorrection);
MaxPointsReason maxPointsReason = MaxPointsReason.DNS;
leaderboard.getScoreCorrection().setMaxPointsReason(competitor, raceColumn, maxPointsReason);
// Set carried Points
double carriedPoints = 2.0;
leaderboard.setCarriedPoints(competitor, carriedPoints);
// Set suppressed competitor
leaderboard.setSuppressed(competitorToSuppress, true);
// Set display name
String nickName = "Angie";
leaderboard.setDisplayName(competitorToSuppress, nickName);
// Serialize
TopLevelMasterDataSerializer serializer = new TopLevelMasterDataSerializer(
sourceService.getLeaderboardGroups(), sourceService.getAllEvents(), sourceService.getPersistentRegattasForRaceIDs(),
sourceService.getAllMediaTracks());
Set<String> names = new HashSet<String>();
names.add(TEST_GROUP_NAME);
JSONObject masterDataOverallObject = serializer.serialize(names);
Assert.assertNotNull(masterDataOverallObject);
// Delete all data above from the database, to allow recreating all of it on target server
deleteCreatedDataFromDatabase();
// Create existing data on target
RacingEventService destService = new RacingEventServiceImplMock();
String venueNameToOverride = "Override";
Event eventToOverride = destService.addEvent(TEST_EVENT_NAME, venueNameToOverride, "", false, eventUUID,
new ArrayList<String>());
CourseArea courseAreaToOverride = new CourseAreaImpl("testAreaToOverride", courseAreaUUID);
eventToOverride.getVenue().addCourseArea(courseAreaToOverride);
List<String> raceColumnNamesToOverride = new ArrayList<String>();
String raceColumnNameToOveride = "T1tooverride";
raceColumnNamesToOverride.add(raceColumnNameToOveride);
List<Series> seriesToOverride = new ArrayList<Series>();
List<Fleet> fleetsToOverride = new ArrayList<Fleet>();
FleetImpl testFleet1ToOverride = new FleetImpl("testFleet1");
fleetsToOverride.add(testFleet1ToOverride);
seriesToOverride.add(new SeriesImpl("testSeries", false, fleetsToOverride, raceColumnNamesToOverride, destService));
Regatta regattaToOverride = destService.createRegatta("testRegatta", "29er", regattaUUID, seriesToOverride, true, new LowPoint(),
courseAreaUUID);
event.addRegatta(regattaToOverride);
Leaderboard leaderboardToOverride = destService.addRegattaLeaderboard(regattaToOverride.getRegattaIdentifier(),
"testDisplayNameNotToOverride", discardRule);
List<String> leaderboardNamesToOverride = new ArrayList<String>();
leaderboardNamesToOverride.add(leaderboardToOverride.getName());
destService.addLeaderboardGroup(TEST_GROUP_NAME,
"testGroupDescNotToOverride", false, leaderboardNamesToOverride, null, null);
// Deserialization copied from SailingServiceImpl
DomainFactory domainFactory = DomainFactory.INSTANCE;
MasterDataImporter importer = new MasterDataImporter(domainFactory, destService);
MasterDataImportObjectCreationCount creationCount = importer.importMasterData(
masterDataOverallObject.toString(), true);
//---Asserts---
Assert.assertNotNull(creationCount);
Event eventOnTarget = destService.getEvent(eventUUID);
Assert.assertNotNull(eventOnTarget);
//Check if existing event didn't survive import
Assert.assertEquals(event.getVenue().getName(), eventOnTarget.getVenue().getName());
//Check if existing course area survive import
Assert.assertEquals(courseArea.getName(), eventOnTarget.getVenue().getCourseAreas().iterator().next().getName());
LeaderboardGroup leaderboardGroupOnTarget = destService.getLeaderboardGroupByName(TEST_GROUP_NAME);
Assert.assertNotNull(leaderboardGroupOnTarget);
//Check if existing leaderboard group didn't survive import
Assert.assertEquals(group.getDescription(), leaderboardGroupOnTarget.getDescription());
Leaderboard leaderboardOnTarget = destService.getLeaderboardByName(TEST_LEADERBOARD_NAME);
Assert.assertNotNull(leaderboardOnTarget);
Regatta regattaOnTarget = destService.getRegattaByName(TEST_LEADERBOARD_NAME);
Assert.assertNotNull(regattaOnTarget);
Assert.assertEquals(courseAreaUUID, eventOnTarget.getVenue().getCourseAreas().iterator().next().getId());
RaceColumn raceColumnOnTarget = leaderboardOnTarget.getRaceColumnByName(raceColumnName);
Assert.assertNotNull(raceColumnOnTarget);
//Check if existing leaderboard didn't survive import
Assert.assertEquals(leaderboard.getDisplayName(), leaderboardOnTarget.getDisplayName());
Assert.assertTrue(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget));
}
@Test
public void testMasterDataImportForRegattaWithoutCourseArea() throws MalformedURLException, IOException, InterruptedException {
// Setup source service
RacingEventService sourceService = new RacingEventServiceImpl();
List<String> raceColumnNames = new ArrayList<String>();
String raceColumnName = "T1";
raceColumnNames.add(raceColumnName);
raceColumnNames.add("T2");
List<Series> series = new ArrayList<Series>();
List<Fleet> fleets = new ArrayList<Fleet>();
FleetImpl testFleet1 = new FleetImpl("testFleet1");
fleets.add(testFleet1);
fleets.add(new FleetImpl("testFleet2"));
series.add(new SeriesImpl("testSeries", false, fleets, raceColumnNames, sourceService));
UUID regattaUUID = UUID.randomUUID();
Regatta regatta = sourceService.createRegatta("testRegatta", "29er", regattaUUID, series, true, new LowPoint(),
null);
int[] discardRule = { 1, 2, 3, 4 };
Leaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(),
"testDisplayName", discardRule);
List<String> leaderboardNames = new ArrayList<String>();
leaderboardNames.add(leaderboard.getName());
sourceService.addLeaderboardGroup(TEST_GROUP_NAME, "testGroupDesc", false, leaderboardNames, null, null);
// Set tracked Race with competitors
Set<Competitor> competitors = new HashSet<Competitor>();
UUID competitorUUID = UUID.randomUUID();
Set<Person> sailors = new HashSet<Person>();
sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L),
"Oberhoschy"));
Person coach = new PersonImpl("Lennart Hensler", new NationalityImpl("GER"), new Date(645487200000L),
"Der Lennart halt");
Team team = new TeamImpl("Pros", sailors, coach);
BoatClass boatClass = new BoatClassImpl("H16", true);
Boat boat = new BoatImpl("Wingy", boatClass, "GER70133");
CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", team, boat);
competitors.add(competitor);
UUID competitorToSuppressUUID = UUID.randomUUID();
Set<Person> sailors2 = new HashSet<Person>();
sailors2.add(new PersonImpl("Angela Merkel", new NationalityImpl("GER"), new Date(645487200000L),
"segelt auch mit"));
Person coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L),
"Bester Coach");
Team team2 = new TeamImpl("Noobs", sailors2, coach2);
Boat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337");
CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", team2, boat2);
competitors.add(competitorToSuppress);
TrackedRace trackedRace = new DummyTrackedRace(competitors, regatta);
RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName);
raceColumn.setTrackedRace(testFleet1, trackedRace);
// Set log event
RaceLogEventFactory factory = new RaceLogEventFactoryImpl();
TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L);
RaceLogStartTimeEvent logEvent = factory.createStartTimeEvent(logTimePoint, 1,
logTimePoint);
raceColumn.getRaceLog(testFleet1).add(logEvent);
storedLogUUIDs.add(logEvent.getId());
// Set score correction
double scoreCorrection = 12.0;
leaderboard.getScoreCorrection().correctScore(competitor, raceColumn, scoreCorrection);
MaxPointsReason maxPointsReason = MaxPointsReason.DNS;
leaderboard.getScoreCorrection().setMaxPointsReason(competitor, raceColumn, maxPointsReason);
// Set carried Points
double carriedPoints = 2.0;
leaderboard.setCarriedPoints(competitor, carriedPoints);
// Set suppressed competitor
leaderboard.setSuppressed(competitorToSuppress, true);
// Set display name
String nickName = "Angie";
leaderboard.setDisplayName(competitorToSuppress, nickName);
// Serialize
TopLevelMasterDataSerializer serializer = new TopLevelMasterDataSerializer(
sourceService.getLeaderboardGroups(), sourceService.getAllEvents(), sourceService.getPersistentRegattasForRaceIDs(),
sourceService.getAllMediaTracks());
Set<String> names = new HashSet<String>();
names.add(TEST_GROUP_NAME);
JSONObject masterDataOverallObject = serializer.serialize(names);
Assert.assertNotNull(masterDataOverallObject);
// Delete all data above from the database, to allow recreating all of it on target server
deleteCreatedDataFromDatabase();
RacingEventService destService = new RacingEventServiceImplMock();
// Deserialization copied from SailingServiceImpl
DomainFactory domainFactory = DomainFactory.INSTANCE;
MasterDataImporter importer = new MasterDataImporter(domainFactory, destService);
MasterDataImportObjectCreationCount creationCount = importer.importMasterData(
masterDataOverallObject.toString(), false);
//---Asserts---
Assert.assertNotNull(creationCount);
//Check if existing event survived import
Assert.assertNotNull(destService.getRegattaByName(regatta.getName()));
}
@Test
@@ -549,11 +813,11 @@ public class MasterDataImportTest {
// Serialize
TopLevelMasterDataSerializer serializer = new TopLevelMasterDataSerializer(
sourceService.getLeaderboardGroups(), sourceService.getAllEvents(),
sourceService.getPersistentRegattasForRaceIDs());
sourceService.getPersistentRegattasForRaceIDs(), sourceService.getAllMediaTracks());
Set<String> names = new HashSet<String>();
names.add(TEST_GROUP_NAME);
JSONArray masterDataOverallArray = serializer.serialize(names);
Assert.assertNotNull(masterDataOverallArray);
JSONObject masterDataOverallObject = serializer.serialize(names);
Assert.assertNotNull(masterDataOverallObject);
// Delete all data above from the database, to allow recreating all of it on target server
deleteCreatedDataFromDatabase();
@@ -562,18 +826,10 @@ public class MasterDataImportTest {
RacingEventService destService = new RacingEventServiceImplMock();
DomainFactory domainFactory = DomainFactory.INSTANCE;
MasterDataImportObjectCreationCountImpl creationCount = new MasterDataImportObjectCreationCountImpl();
JsonDeserializer<LeaderboardGroupMasterData> leaderboardGroupMasterDataDeserializer = LeaderboardGroupMasterDataJsonDeserializer
.create(domainFactory);
JSONArray leaderboardGroupsMasterDataJsonArray = masterDataOverallArray;
// Actual import. Roughly copied from SailingServiceImpl
for (Object leaderBoardGroupMasterData : leaderboardGroupsMasterDataJsonArray) {
JSONObject leaderBoardGroupMasterDataJson = (JSONObject) leaderBoardGroupMasterData;
LeaderboardGroupMasterData masterData = leaderboardGroupMasterDataDeserializer
.deserialize(leaderBoardGroupMasterDataJson);
ImportMasterDataOperation op = new ImportMasterDataOperation(masterData);
creationCount.add(destService.apply(op));
}
MasterDataImporter importer = new MasterDataImporter(domainFactory, destService);
MasterDataImportObjectCreationCount creationCount = importer.importMasterData(
masterDataOverallObject.toString(), false);
// ---Asserts---
@@ -589,4 +845,49 @@ public class MasterDataImportTest {
Assert.assertEquals(regattaOnTarget, map.get("dummy"));
}
@Test
public void testMasterDataImportForMediaTracks() throws MalformedURLException,
IOException, InterruptedException {
// Setup source service
RacingEventService sourceService = new RacingEventServiceImpl();
MediaTrack trackOnSource = new MediaTrack("test", "testTitle", "http://test/test.mp4", new Date(0),
2000, MediaTrack.MimeType.mp4);
sourceService.mediaTrackAdded(trackOnSource);
// Serialize
TopLevelMasterDataSerializer serializer = new TopLevelMasterDataSerializer(
sourceService.getLeaderboardGroups(), sourceService.getAllEvents(),
sourceService.getPersistentRegattasForRaceIDs(), sourceService.getAllMediaTracks());
Set<String> names = new HashSet<String>();
JSONObject masterDataOverallObject = serializer.serialize(names);
Assert.assertNotNull(masterDataOverallObject);
// Delete all data above from the database, to allow recreating all of it on target server
deleteCreatedDataFromDatabase();
// Deserialization copied from SailingServiceImpl
RacingEventService destService = new RacingEventServiceImplMock();
DomainFactory domainFactory = DomainFactory.INSTANCE;
MasterDataImporter importer = new MasterDataImporter(domainFactory, destService);
MasterDataImportObjectCreationCount creationCount = importer.importMasterData(
masterDataOverallObject.toString(), false);
// ---Asserts---
Assert.assertNotNull(creationCount);
Collection<MediaTrack> targetTracks = destService.getAllMediaTracks();
Assert.assertEquals(1, targetTracks.size());
MediaTrack trackOnTarget = targetTracks.iterator().next();
Assert.assertEquals(trackOnSource.dbId, trackOnTarget.dbId);
Assert.assertEquals(trackOnSource.url, trackOnTarget.url);
}
}
@@ -10,6 +10,7 @@ import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
@@ -23,6 +24,7 @@ import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.CourseImpl;
@@ -71,13 +73,13 @@ public class RaceTrackerStartStopTest {
raceDef2 = new RaceDefinitionImpl(RACENAME2, new CourseImpl("Course2", new ArrayList<Waypoint>()), boatClass, new ArrayList<Competitor>());
raceDef3 = new RaceDefinitionImpl(RACENAME3, new CourseImpl("Course3", new ArrayList<Waypoint>()), boatClass, new ArrayList<Competitor>());
regatta.addRace(raceDef1);
trackedRegatta1.createTrackedRace(raceDef1, /* windStore */ EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 0l, /* millisecondsOverWhichToAverageWind */ 0l,
trackedRegatta1.createTrackedRace(raceDef1, Collections.<Sideline> emptyList(), /* windStore */ EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 0l, /* millisecondsOverWhichToAverageWind */ 0l,
/* millisecondsOverWhichToAverageSpeed */ 0l, /* raceDefinitionSetToUpdate */ null);
regatta.addRace(raceDef2);
trackedRegatta1.createTrackedRace(raceDef2, /* windStore */ EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 0l, /* millisecondsOverWhichToAverageWind */ 0l,
trackedRegatta1.createTrackedRace(raceDef2, Collections.<Sideline> emptyList(), /* windStore */ EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 0l, /* millisecondsOverWhichToAverageWind */ 0l,
/* millisecondsOverWhichToAverageSpeed */ 0l, /* raceDefinitionSetToUpdate */ null);
regatta.addRace(raceDef3);
trackedRegatta1.createTrackedRace(raceDef3, /* windStore */ EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 0l, /* millisecondsOverWhichToAverageWind */ 0l,
trackedRegatta1.createTrackedRace(raceDef3, Collections.<Sideline> emptyList(), /* windStore */ EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 0l, /* millisecondsOverWhichToAverageWind */ 0l,
/* millisecondsOverWhichToAverageSpeed */ 0l, /* raceDefinitionSetToUpdate */ null);
Set<RaceDefinition> raceDefinitionSetRace1 = new HashSet<RaceDefinition>();
raceDefinitionSetRace1.add(raceDef1);
@@ -6,7 +6,10 @@ Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.sap.sailing.server.impl.Activator
Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Import-Package: org.json.simple,
Import-Package: com.sap.sailing.server.gateway.deserialization,
com.sap.sailing.server.gateway.deserialization.masterdata.impl,
com.sap.sailing.server.gateway.serialization.masterdata.impl,
org.json.simple,
org.json.simple.parser,
org.osgi.framework;version="1.3.0",
org.osgi.util.tracker;version="1.3.1"
@@ -32,5 +35,6 @@ Export-Package: com.sap.sailing.server,
com.sap.sailing.domain.swisstimingadapter.test,
com.sap.sailing.gwt.ui.test,
com.sap.sailing.server.replication.test",
com.sap.sailing.server.masterdata,
com.sap.sailing.server.operationaltransformation
@@ -42,6 +42,7 @@ import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.RegattaListener;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.EventImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
@@ -949,7 +950,7 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed) {
DynamicTrackedRegatta trackedRegatta = getOrCreateTrackedRegatta(getRegatta(raceIdentifier));
RaceDefinition race = getRace(raceIdentifier);
return trackedRegatta.createTrackedRace(race, windStore, delayToLiveInMillis,
return trackedRegatta.createTrackedRace(race, Collections.<Sideline> emptyList(), windStore, delayToLiveInMillis,
millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed,
/* raceDefinitionSetToUpdate */null);
}
@@ -0,0 +1,85 @@
package com.sap.sailing.server.masterdata;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import com.sap.sailing.domain.base.DomainFactory;
import com.sap.sailing.domain.common.MasterDataImportObjectCreationCount;
import com.sap.sailing.domain.common.impl.MasterDataImportObjectCreationCountImpl;
import com.sap.sailing.domain.common.media.MediaTrack;
import com.sap.sailing.domain.masterdataimport.LeaderboardGroupMasterData;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.masterdata.impl.LeaderboardGroupMasterDataJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.masterdata.impl.MediaTrackJsonDeserializer;
import com.sap.sailing.server.gateway.serialization.masterdata.impl.TopLevelMasterDataSerializer;
import com.sap.sailing.server.operationaltransformation.ImportMasterDataOperation;
public class MasterDataImporter {
private final DomainFactory baseDomainFactory;
private final RacingEventService racingEventService;
public MasterDataImporter(DomainFactory baseDomainFactory, RacingEventService racingEventService) {
this.baseDomainFactory = baseDomainFactory;
this.racingEventService = racingEventService;
}
public MasterDataImportObjectCreationCount importMasterData(String response, boolean override) {
MasterDataImportObjectCreationCountImpl creationCount = new MasterDataImportObjectCreationCountImpl();
JsonDeserializer<LeaderboardGroupMasterData> leaderboardGroupMasterDataDeserializer = LeaderboardGroupMasterDataJsonDeserializer
.create(baseDomainFactory);
JSONParser parser = new JSONParser();
try {
JSONObject masterDataOverall = (JSONObject) parser.parse(response);
JSONArray leaderboardGroupsMasterDataJsonArray = (JSONArray) masterDataOverall.get(TopLevelMasterDataSerializer.FIELD_PER_LG);
for (Object leaderBoardGroupMasterData : leaderboardGroupsMasterDataJsonArray) {
JSONObject leaderBoardGroupMasterDataJson = (JSONObject) leaderBoardGroupMasterData;
LeaderboardGroupMasterData masterData = leaderboardGroupMasterDataDeserializer
.deserialize(leaderBoardGroupMasterDataJson);
ImportMasterDataOperation op = new ImportMasterDataOperation(masterData, override);
creationCount.add(racingEventService.apply(op));
}
JsonDeserializer<MediaTrack> mediaTrackDeserializer = new MediaTrackJsonDeserializer();
JSONArray mediaTracks = (JSONArray) masterDataOverall.get(TopLevelMasterDataSerializer.FIELD_MEDIA);
List<MediaTrack> tracks = new ArrayList<MediaTrack>();
for (Object obj : mediaTracks) {
tracks.add(mediaTrackDeserializer.deserialize((JSONObject) obj));
}
Collection<MediaTrack> existingMediaTracks = racingEventService.getAllMediaTracks();
Map<String, MediaTrack> existingMap = new HashMap<String, MediaTrack>();
for (MediaTrack oneTrack : existingMediaTracks) {
existingMap.put(oneTrack.dbId, oneTrack);
}
for (MediaTrack oneNewTrack : tracks) {
if (existingMap.containsKey(oneNewTrack.dbId)) {
if (override) {
racingEventService.mediaTrackDeleted(existingMap.get(oneNewTrack));
} else {
continue;
}
}
racingEventService.mediaTrackAdded(oneNewTrack);
}
} catch (org.json.simple.parser.ParseException e) {
throw new RuntimeException(e);
} catch (JsonDeserializationException e) {
throw new RuntimeException(e);
}
return creationCount;
}
}
@@ -9,6 +9,7 @@ import com.sap.sailing.domain.base.Leg;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Sideline;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
import com.sap.sailing.domain.common.Distance;
@@ -40,7 +41,6 @@ import com.sap.sailing.domain.tracking.WindWithConfidence;
import com.sap.sailing.domain.tracking.impl.TrackedRegattaImpl;
public class DummyTrackedRace implements TrackedRace {
private static final long serialVersionUID = -11522605089325440L;
private Iterable<? extends Competitor> competitors;
private Regatta regatta;
@@ -487,4 +487,10 @@ public class DummyTrackedRace implements TrackedRace {
// TODO Auto-generated method stub
return false;
}
@Override
public Iterable<Sideline> getCourseSidelines() {
// TODO Auto-generated method stub
return null;
}
}
@@ -1,5 +1,6 @@
package com.sap.sailing.server.operationaltransformation;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -29,6 +30,7 @@ import com.sap.sailing.domain.common.ScoringSchemeType;
import com.sap.sailing.domain.common.impl.MasterDataImportObjectCreationCountImpl;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
import com.sap.sailing.domain.leaderboard.SettableScoreCorrection;
import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl;
@@ -59,8 +61,11 @@ public class ImportMasterDataOperation extends
private DomainFactory domainFactory = DomainFactory.INSTANCE;
public ImportMasterDataOperation(LeaderboardGroupMasterData masterData) {
private final boolean override;
public ImportMasterDataOperation(LeaderboardGroupMasterData masterData, boolean override) {
this.masterData = masterData;
this.override = override;
}
@Override
@@ -72,14 +77,20 @@ public class ImportMasterDataOperation extends
private void createLeaderboardGroupWithAllRelatedObjects(LeaderboardGroupMasterData masterData,
RacingEventService toState) {
List<String> leaderboardNames = new ArrayList<String>();
Map<String, Leaderboard> existingLeaderboards = toState.getLeaderboards();
createCourseAreasAndEvents(masterData, toState);
createRegattas(masterData, toState);
Map<String, Leaderboard> existingLeaderboards = toState.getLeaderboards();
for (LeaderboardMasterData board : masterData.getLeaderboards()) {
if (existingLeaderboards.containsKey(board.getName())) {
logger.info(String.format("Leaderboard with name %1$s already exists and hasn't been overridden.",
board.getName()));
continue;
if (override) {
toState.removeLeaderboard(board.getName());
logger.info(String.format("Leaderboard with name %1$s already existed and has been overridden.",
board.getName()));
} else {
logger.info(String.format("Leaderboard with name %1$s already exists and hasn't been overridden.",
board.getName()));
continue;
}
}
setCourseAreaIfNecessary(board, toState);
setRegattaIfNecessary(board, toState);
@@ -116,7 +127,14 @@ public class ImportMasterDataOperation extends
.getDiscardIndexResultsStartingWithHowManyRaces();
overallLeaderboardScoringSchemeType = flex.getScoringScheme().getType();
}
if (toState.getLeaderboardGroupByName(masterData.getName()) == null) {
LeaderboardGroup existingLeaderboardGroup = toState.getLeaderboardGroupByName(masterData.getName());
if (existingLeaderboardGroup != null && override) {
logger.info(String.format("Leaderboard Group with name %1$s already existed and will be overridden.",
masterData.getName()));
toState.removeLeaderboardGroup(masterData.getName());
existingLeaderboardGroup = null;
}
if (existingLeaderboardGroup == null) {
toState.addLeaderboardGroup(masterData.getName(), masterData.getDescription(),
masterData.isDisplayGroupsRevese(), leaderboardNames, overallLeaderboardDiscardThresholds,
overallLeaderboardScoringSchemeType);
@@ -225,10 +243,6 @@ public class ImportMasterDataOperation extends
singleCorrection.getExplicitScoreCorrection());
}
}
} else {
logger.info(String
.format("Race Column with name %1$s for leaderboard with name %2$s already exists and hasn't been overridden.",
masterData.getName(), leaderboard.getName()));
}
}
@@ -251,11 +265,24 @@ public class ImportMasterDataOperation extends
private void createRegattas(LeaderboardGroupMasterData masterData, RacingEventService toState) {
Iterable<RegattaMasterData> regattaData = masterData.getRegattas();
for (RegattaMasterData singleRegattaData : regattaData) {
if (toState.getRegatta(new RegattaName(singleRegattaData.getRegattaName())) != null) {
logger.info(String
.format("Regatta with name %1$s already exists and hasn't been overridden.",
Regatta existingRegatta = toState.getRegatta(new RegattaName(singleRegattaData.getRegattaName()));
if (existingRegatta != null) {
if (override) {
logger.info(String.format("Regatta with name %1$s already existed and has been overridden.",
singleRegattaData.getRegattaName()));
try {
toState.removeRegatta(existingRegatta);
} catch (IOException | InterruptedException e) {
logger.info(String.format("Regatta with name %1$s could not be deleted due to an error.",
singleRegattaData.getRegattaName()));
continue;
e.printStackTrace();
continue;
}
} else {
logger.info(String.format("Regatta with name %1$s already exists and hasn't been overridden.",
singleRegattaData.getRegattaName()));
continue;
}
}
String id = singleRegattaData.getId();
Iterable<Series> series = createSeries(singleRegattaData.getSeries(), toState);
@@ -269,8 +296,7 @@ public class ImportMasterDataOperation extends
UUID.fromString(id), series, isPersistent,
domainFactory.createScoringScheme(ScoringSchemeType.valueOf(scoringSchemeType)),
courseAreaUUID).getA();
//TODO adjust boolean according to override mode
toState.setPersistentRegattaForRaceIDs(createdRegatta, singleRegattaData.getRaceIds(), false);
toState.setPersistentRegattaForRaceIDs(createdRegatta, singleRegattaData.getRaceIds(), override);
creationCount.addOneRegatta();
}
@@ -312,6 +338,12 @@ public class ImportMasterDataOperation extends
for (EventMasterData event : events) {
String id = event.getId();
Event existingEvent = toState.getEvent(UUID.fromString(id));
if (existingEvent != null && override) {
logger.info(String.format("Event with name %1$s already existed and will be overridden.",
event.getName()));
toState.removeEvent(existingEvent.getId());
existingEvent = null;
}
if (existingEvent == null) {
String name = event.getName();
String pubString = event.getPubUrl();
@@ -22,7 +22,7 @@ import com.sap.sailing.velum.resultimport.CsvParserFactory;
public class ScoreCorrectionProviderImpl extends AbstractDocumentBasedScoreCorrectionProvider {
private static final long serialVersionUID = 4767200739966995306L;
private static final String NAME = "Scores from Velum CSV exports";
private static final String NAME = "Velum CSV result importer";
private static final Logger logger = Logger.getLogger(ScoreCorrectionProviderImpl.class.getName());
+31 -25
View File
@@ -17,9 +17,7 @@
<img alt='SAP Website' src='images/sap-logo.png' />
</a>
<ul class="headNavigation">
<li> <a href="http://www.sapsailing.com/postrace/post-race-analytics-info.html">Post Race Information</a>
</li>
<li><a href="http://www.sapsailing.com/postrace/post-race-analytics-info.html">Post Race Information</a></li>
</ul>
</div>
<div id='contentWrapper'>
@@ -27,7 +25,6 @@
<img alt='Sailer' src='images/key-visual.jpg' />
<div id='infoBox'>
<h1 id='pageHeadline'>SAP Sailing Analytics</h1>
<p>Understanding what happens out on the race course isn't always easy. To help solve this challenge and bring the excitement of sailing to the fans, we have developed the SAP sailing analytics.</p>
</div>
</div>
@@ -40,16 +37,24 @@
<div class='timeBar'>
<div class='raceSection'>
<h5 class='date'>
July 3 - 7
</h5>
<div class='raceTimepoint'></div>
<a href='http://kielerwoche2013.sapsailing.com' target='_blank'>
<a href='http://49er-euros2013.sapsailing.com' target='_blank'>
<ul class='racePanel'>
<li class='raceName'>Kieler Woche 2013</li>
<li class='raceLocation'>Germany, Kiel</li>
</ul>
<li class='raceName'>
49er European Championship 2013
</li>
<li class='raceLocation'>
Aarhus, Denmark
</li>
</ul>
</a>
<div class='raceDescription'>
<p>Kieler Woche 2013</p> <a href='http://livecenter.kieler-woche.de/' target='_blank'>Official website</a>
<p>49er European Championship 2013</p>
<a href='http://49er-euros2013.sapsailing.com' target='_blank'>SAP Sailing Analytics</a><br/>
<a href='http://www.sportaarhusevents.dk/en/events/2013/49er-european-championship' target='_blank'>Official website</a>
</div>
</div>
</div>
@@ -72,6 +77,7 @@
</a>
<div class='raceDescription'>
<p>Extreme Sailing Series 2013</p>
<a href='http://ess40-2013.sapsailing.com' target='_blank'>SAP Sailing Analytics</a><br/>
<a href='http://www.extremesailingseries.com' target='_blank'>Official website</a>
</div>
</div>
@@ -92,27 +98,25 @@
</a>
<div class='raceDescription'>
<p>Travem&uuml;nder Week</p>
<a href='http://tw2013.sapsailing.com' target='_blank'>SAP Sailing Analytics</a><br/>
<a href='http://www.travemuender-woche.com/' target='_blank'>Official website</a>
</div>
</div>
<div class='raceSection'>
<h5 class='date'>
June 29 - July 7
June 21 - 30
</h5>
<div class='raceTimepoint'></div>
<a href='http://49er-euros2013.sapsailing.com' target='_blank'>
<a href='http://kielerwoche2013.sapsailing.com' target='_blank'>
<ul class='racePanel'>
<li class='raceName'>
49er European Championship 2013
</li>
<li class='raceLocation'>
Aarhus, Denmark
</li>
</ul>
<li class='raceName'>Kieler Woche 2013</li>
<li class='raceLocation'>Germany, Kiel</li>
</ul>
</a>
<div class='raceDescription'>
<p>49er European Championship 2013</p>
<a href='http://www.sportaarhusevents.dk/en/events/2013/49er-european-championship' target='_blank'>Official website</a>
<p>Kieler Woche 2013</p>
<a href='http://kielerwoche2013.sapsailing.com' target='_blank'>SAP Sailing Analytics</a><br/>
<a href='http://livecenter.kieler-woche.de/' target='_blank'>Official website</a>
</div>
</div>
<div class='raceSection'>
@@ -128,8 +132,9 @@
</ul>
</a>
<div class='raceDescription'>
<p>Star IDM 2013</p> <a href='http://www.starclass.de/termine-detail/events/int-deutsche-meisterschaft-2013.html' target='_blank'>Official website</a>
<p>Star IDM 2013</p>
<a href='http://staridm2013.sapsailing.com' target='_blank'>SAP Sailing Analytics</a><br/>
<a href='http://www.starclass.de/termine-detail/events/int-deutsche-meisterschaft-2013.html' target='_blank'>Official website</a>
</div>
</div>
<div class='raceSection'>
@@ -145,8 +150,9 @@
</ul>
</a>
<div class='raceDescription'>
<p>505 World Champinships 2013</p> <a href='http://www.sap505worlds.com/' target='_blank'>Official website</a>
<p>505 World Championship 2013</p>
<a href='http://505worlds2013.sapsailing.com' target='_blank'>SAP Sailing Analytics</a><br/>
<a href='http://www.sap505worlds.com/' target='_blank'>Official website</a>
</div>
</div>
</div>