mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-25 06:58:39 +00:00
progress towards creating a RaceDefinition and TrackedRace from the archived swiss timing data
This commit is contained in:
+13
-1
@@ -1,7 +1,10 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
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.Nationality;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
@@ -24,9 +27,11 @@ public interface DomainFactory {
|
||||
|
||||
Regatta getOrCreateRegatta(String raceID, TrackedRegattaRegistry trackedRegattaRegistry);
|
||||
|
||||
Nationality getOrCreateNationality(String nationalityName);
|
||||
Nationality getOrCreateNationality(String threeLetterIOCCode);
|
||||
|
||||
Competitor getOrCreateCompetitor(com.sap.sailing.domain.swisstimingadapter.Competitor competitor, BoatClass boatClass);
|
||||
|
||||
Competitor getOrCreateCompetitor(String boatID, String threeLetterIOCCode, String name, BoatClass boatClass);
|
||||
|
||||
RaceDefinition createRaceDefinition(Regatta regatta, Race race, StartList startList, com.sap.sailing.domain.swisstimingadapter.Course course);
|
||||
|
||||
@@ -46,4 +51,11 @@ public interface DomainFactory {
|
||||
boolean canSendRequests, long delayToLiveInMillis,
|
||||
SwissTimingFactory swissTimingFactory, DomainFactory domainFactory, WindStore windStore,
|
||||
RaceSpecificMessageLoader messageLoader);
|
||||
|
||||
BoatClass getOrCreateBoatClassFromRaceID(String raceID);
|
||||
|
||||
ControlPoint getOrCreateControlPoint(Iterable<String> devices);
|
||||
|
||||
RaceDefinition createRaceDefinition(Regatta regatta, String raceID, Iterable<Competitor> competitors,
|
||||
List<ControlPoint> courseDefinition);
|
||||
}
|
||||
|
||||
+34
-10
@@ -132,6 +132,28 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Competitor getOrCreateCompetitor(String boatID, String threeLetterIOCCode, String name,
|
||||
BoatClass boatClass) {
|
||||
return getOrCreateCompetitor(new CompetitorImpl(boatID, threeLetterIOCCode, name), boatClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RaceDefinition createRaceDefinition(Regatta regatta, String raceID, Iterable<Competitor> competitors,
|
||||
List<ControlPoint> courseDefinition) {
|
||||
List<Waypoint> waypoints = new ArrayList<>();
|
||||
for (ControlPoint controlPoint : courseDefinition) {
|
||||
Waypoint waypoint = baseDomainFactory.createWaypoint(controlPoint);
|
||||
waypoints.add(waypoint);
|
||||
}
|
||||
com.sap.sailing.domain.base.Course domainCourse = new CourseImpl("Course", waypoints);
|
||||
BoatClass boatClass = getOrCreateBoatClassFromRaceID(raceID);
|
||||
logger.info("Creating RaceDefinitionImpl for race "+raceID);
|
||||
RaceDefinition result = new RaceDefinitionImpl(raceID, domainCourse, boatClass, competitors);
|
||||
regatta.addRace(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RaceDefinition createRaceDefinition(Regatta regatta, Race race, StartList startList, Course course) {
|
||||
com.sap.sailing.domain.base.Course domainCourse = createCourse(race.getDescription(), course);
|
||||
@@ -144,18 +166,19 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
return result;
|
||||
}
|
||||
|
||||
private BoatClass getOrCreateBoatClassFromRaceID(String raceID) {
|
||||
@Override
|
||||
public BoatClass getOrCreateBoatClassFromRaceID(String raceID) {
|
||||
BoatClass result;
|
||||
/*
|
||||
SAM102000 Men's Windsurfer = Windsufer M�nner RS:X
|
||||
SAM102000 Men's Windsurfer = Windsurfer Maenner RS:X
|
||||
SAW102000 Women's Windsurfer = Windsurfer Damen RS:X
|
||||
SAM004000 Men's One Person Dinghy = Laser M�nner
|
||||
SAM004000 Men's One Person Dinghy = Laser Maenner
|
||||
SAW103000 Women's One Person Dinghy = Laser Damen Laser Radial
|
||||
SAM002000 Men's One Person Dinghy Heavy = Finn Dinghy M�nner
|
||||
SAM005000 Men's Two Person Dinghy = 470er M�nner
|
||||
SAM002000 Men's One Person Dinghy Heavy = Finn Dinghy Maenner
|
||||
SAM005000 Men's Two Person Dinghy = 470er Maenner
|
||||
SAW005000 Women's Two Person Dinghy = 470er Damen
|
||||
SAM009000 Men's Skiff = 49er M�nner
|
||||
SAM007000 Men's Keelboat = Starboot M�nner
|
||||
SAM009000 Men's Skiff = 49er Maenner
|
||||
SAM007000 Men's Keelboat = Starboot Maenner
|
||||
SAW010000 Women's Match Racing = Matchrace Damen Elliott 6M (modified)
|
||||
*/
|
||||
if (raceID.toUpperCase().startsWith("SA") && raceID.length() == 9) {
|
||||
@@ -191,7 +214,8 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
return result;
|
||||
}
|
||||
|
||||
private ControlPoint getOrCreateControlPoint(Iterable<String> devices) {
|
||||
@Override
|
||||
public ControlPoint getOrCreateControlPoint(Iterable<String> devices) {
|
||||
ControlPoint result;
|
||||
synchronized (controlPointCache) {
|
||||
result = controlPointCache.get(devices);
|
||||
@@ -270,8 +294,8 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nationality getOrCreateNationality(String nationalityName) {
|
||||
return baseDomainFactory.getOrCreateNationality(nationalityName);
|
||||
public Nationality getOrCreateNationality(String threeLetterIOCCode) {
|
||||
return baseDomainFactory.getOrCreateNationality(threeLetterIOCCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,3 +9,4 @@ Fragment-Host: com.sap.sailing.domain.swisstimingreplayadapter
|
||||
Import-Package: org.json.simple,
|
||||
org.json.simple.parser,
|
||||
org.junit;version="4.8.2"
|
||||
Require-Bundle: com.sap.sailing.domain.test
|
||||
|
||||
+13
-1
@@ -8,9 +8,12 @@ import java.util.List;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.swisstimingadapter.DomainFactory;
|
||||
import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayRace;
|
||||
import com.sap.sailing.domain.swisstimingreplayadapter.impl.SwissTimingReplayParserImpl;
|
||||
import com.sap.sailing.domain.swisstimingreplayadapter.impl.SwissTimingReplayServiceImpl;
|
||||
import com.sap.sailing.domain.swisstimingreplayadapter.impl.SwissTimingReplayToDomainAdapter;
|
||||
import com.sap.sailing.domain.test.DummyTrackedRegattaRegistry;
|
||||
|
||||
public class SwissTimingReplayAdapterServiceTest {
|
||||
|
||||
@@ -76,10 +79,19 @@ public class SwissTimingReplayAdapterServiceTest {
|
||||
assertEquals(2418, replayCountListener.rankingMarkCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRaceData_SAW010955_20120802_WithDomainAdapter() throws Exception {
|
||||
SwissTimingReplayToDomainAdapter replayListener = new SwissTimingReplayToDomainAdapter(null, DomainFactory.INSTANCE,
|
||||
new DummyTrackedRegattaRegistry());
|
||||
new SwissTimingReplayParserImpl().readData(getClass().getResourceAsStream("/SAW005906.20120805.replay"), replayListener);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void printRaceData_SAW005906_20120805() throws Exception {
|
||||
new SwissTimingReplayParserImpl().readData(getClass().getResourceAsStream("/SAW005906.20120805.replay"), new SwissTimingReplayPrintListener());
|
||||
new SwissTimingReplayParserImpl().readData(getClass().getResourceAsStream("/SAW005906.20120805.replay"),
|
||||
new SwissTimingReplayPrintListener());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -8,6 +8,8 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: com.sap.sailing.domain.common,
|
||||
com.sap.sailing.domain,
|
||||
org.json.simple;bundle-version="1.1.0"
|
||||
org.json.simple;bundle-version="1.1.0",
|
||||
com.sap.sailing.domain.swisstimingadapter,
|
||||
com.googlecode.java-diff-utils;bundle-version="1.3.0"
|
||||
Export-Package: com.sap.sailing.domain.swisstimingreplayadapter,
|
||||
com.sap.sailing.domain.swisstimingreplayadapter.impl;x-friends:="com.sap.sailing.domain.swisstimingreplayadapter.test"
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ public interface SwissTimingReplayListener {
|
||||
|
||||
void competitorsCount(short competitorsCount);
|
||||
|
||||
void competitor(int hashValue, String nation, String sailNumber, String name, CompetitorStatus competitorStatus, BoatType boatType,
|
||||
void competitor(int hashValue, String nation, String sailNumberOrTrackerID, String name, CompetitorStatus competitorStatus, BoatType boatType,
|
||||
short cRank_Bracket, short cnPoints_x10_Bracket, short ctPoints_x10_Winner);
|
||||
|
||||
/**
|
||||
|
||||
+225
-24
@@ -1,22 +1,50 @@
|
||||
package com.sap.sailing.domain.swisstimingreplayadapter.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
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.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.base.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl;
|
||||
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.DegreePosition;
|
||||
import com.sap.sailing.domain.common.impl.Util;
|
||||
import com.sap.sailing.domain.common.impl.WindSourceWithAdditionalID;
|
||||
import com.sap.sailing.domain.swisstimingadapter.DomainFactory;
|
||||
import com.sap.sailing.domain.swisstimingreplayadapter.CompetitorStatus;
|
||||
import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayListener;
|
||||
import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayParser;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
|
||||
import com.sap.sailing.domain.tracking.WindTrack;
|
||||
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
|
||||
import com.sap.sailing.domain.tracking.impl.GPSFixMovingImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.MarkPassingImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.WindImpl;
|
||||
|
||||
import difflib.PatchFailedException;
|
||||
|
||||
/**
|
||||
* Turns the data received through the {@link SwissTimingReplayListener} callback interface into domain objects, creating
|
||||
@@ -30,6 +58,10 @@ import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
*
|
||||
*/
|
||||
public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter {
|
||||
private static final Logger logger = Logger.getLogger(SwissTimingReplayToDomainAdapter.class.getName());
|
||||
|
||||
private final DomainFactory domainFactory;
|
||||
|
||||
private final Map<String, RaceDefinition> racePerRaceID;
|
||||
private final Map<String, DynamicTrackedRace> trackedRacePerRaceID;
|
||||
|
||||
@@ -49,11 +81,68 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter {
|
||||
*/
|
||||
private Position referenceLocation;
|
||||
|
||||
public SwissTimingReplayToDomainAdapter() {
|
||||
private final Map<String, Set<Competitor>> competitorsPerRaceID;
|
||||
|
||||
private final Map<String, Map<String, Mark>> marksPerRaceIDPerMarkID;
|
||||
|
||||
private final Map<String, TimePoint> bestStartTimePerRaceID;
|
||||
|
||||
private final Map<String, TimePoint> raceTimePerRaceID;
|
||||
|
||||
/**
|
||||
* When the first mark definition of a course sequence is received, this member holds <code>null</code> and is then
|
||||
* initialized with a valid list. The list then accumulates the marks until the tracker count is received which marks
|
||||
* the end of the course sequence and the beginning of the tracker messages. The course is then compared to the current
|
||||
* course. If the race hasn't even been created, this can be done now. Otherwise, the new course definition is compared
|
||||
* to the current race's course definition, and if necessary, a course change is performed. Then, this member is set
|
||||
* to <code>null</code> again to show that the course has been consumed and updated to the race definition if necessary.
|
||||
*/
|
||||
private List<ControlPoint> currentCourseDefinition;
|
||||
|
||||
private final Regatta regatta;
|
||||
|
||||
private final TrackedRegattaRegistry trackedRegattaRegistry;
|
||||
|
||||
private final Map<Integer, Mark> markByHashValue;
|
||||
|
||||
private final Map<Integer, Competitor> competitorByHashValue;
|
||||
|
||||
/**
|
||||
* If a wind speed and direction was transmitted with the last mark message, it is recorded for the mark. When the next
|
||||
* mark position tracker message is received, a look up in this map is performed. If a wind speed/direction is found, it is
|
||||
* added to the tracked race's {@link WindSourceType#EXPEDITION} wind track.
|
||||
*/
|
||||
private final Map<ControlPoint, SpeedWithBearing> windAtControlPoint;
|
||||
|
||||
/**
|
||||
* Records the next mark for each competitor numerically
|
||||
*/
|
||||
private final Map<Competitor, Short> lastNextMark;
|
||||
|
||||
/**
|
||||
* @param regatta
|
||||
* the regatta to associate the race(s) received by the listener with, or <code>null</code> to force the
|
||||
* use / creation of a default regatta per race
|
||||
*/
|
||||
public SwissTimingReplayToDomainAdapter(Regatta regatta, DomainFactory domainFactory, TrackedRegattaRegistry trackedRegattaRegistry) {
|
||||
this.regatta = null;
|
||||
this.trackedRegattaRegistry = trackedRegattaRegistry;
|
||||
racePerRaceID = new HashMap<>();
|
||||
trackedRacePerRaceID = new HashMap<>();
|
||||
bestStartTimePerRaceID = new HashMap<>();
|
||||
raceTimePerRaceID = new HashMap<>();
|
||||
competitorsPerRaceID = new HashMap<>();
|
||||
marksPerRaceIDPerMarkID = new HashMap<>();
|
||||
markByHashValue = new HashMap<>();
|
||||
competitorByHashValue = new HashMap<>();
|
||||
windAtControlPoint = new HashMap<>();
|
||||
lastNextMark = new HashMap<>();
|
||||
this.domainFactory = domainFactory;
|
||||
}
|
||||
|
||||
private BoatClass getCurrentBoatClass() {
|
||||
return domainFactory.getOrCreateBoatClassFromRaceID(currentRaceID);
|
||||
}
|
||||
@Override
|
||||
public void referenceTimestamp(long referenceTimestampMillis) {
|
||||
referenceTimePoint = new MillisecondsTimePoint(referenceTimestampMillis);
|
||||
@@ -68,49 +157,161 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter {
|
||||
public void raceID(String raceID) {
|
||||
currentRaceID = raceID;
|
||||
}
|
||||
|
||||
private boolean isValid(int threeByteValue) {
|
||||
return threeByteValue == 2<<24 - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frameMetaData(byte cid, int raceTime, int startTime, int estimatedStartTime, RaceStatus raceStatus,
|
||||
short distanceToNextMark, Weather weather, short humidity, short temperature, String messageText,
|
||||
byte cFlag, byte rFlag, byte duration, short nm) {
|
||||
// TODO Auto-generated method stub
|
||||
super.frameMetaData(cid, raceTime, startTime, estimatedStartTime, raceStatus, distanceToNextMark, weather, humidity,
|
||||
temperature, messageText, cFlag, rFlag, duration, nm);
|
||||
if (isValid(startTime)) {
|
||||
bestStartTimePerRaceID.put(currentRaceID, getTimePoint(startTime));
|
||||
} else if (isValid(estimatedStartTime)) {
|
||||
bestStartTimePerRaceID.put(currentRaceID, getTimePoint(estimatedStartTime));
|
||||
}
|
||||
if (bestStartTimePerRaceID.containsKey(currentRaceID)) {
|
||||
raceTimePerRaceID.put(currentRaceID, bestStartTimePerRaceID.get(currentRaceID).plus(1000*raceTime));
|
||||
}
|
||||
}
|
||||
|
||||
private TimePoint getTimePoint(int threeByteTimeSpecInSecondsSinceMidnight) {
|
||||
assert isValid(threeByteTimeSpecInSecondsSinceMidnight);
|
||||
return getMidnight(referenceTimePoint).plus(1000 * threeByteTimeSpecInSecondsSinceMidnight);
|
||||
}
|
||||
|
||||
private TimePoint getMidnight(TimePoint referenceTimePoint) {
|
||||
GregorianCalendar cal = new GregorianCalendar();
|
||||
cal.setTimeInMillis(referenceTimePoint.asMillis());
|
||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
||||
cal.set(Calendar.MINUTE, 0);
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
return new MillisecondsTimePoint(cal.getTimeInMillis());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void competitor(int hashValue, String nation, String sailNumber, String name,
|
||||
public void competitor(int hashValue, String threeLetterIOCCode, String sailNumberOrTrackerID, String name,
|
||||
CompetitorStatus competitorStatus, BoatType boatType, short cRank_Bracket, short cnPoints_x10_Bracket,
|
||||
short ctPoints_x10_Winner) {
|
||||
// TODO distinguish between competitors and non-competitors; all non-competitors are considered marks
|
||||
// TODO Auto-generated method stub
|
||||
super.competitor(hashValue, nation, sailNumber, name, competitorStatus, boatType, cRank_Bracket, cnPoints_x10_Bracket,
|
||||
ctPoints_x10_Winner);
|
||||
if (boatType == BoatType.Competitor) {
|
||||
Competitor competitor = domainFactory.getOrCreateCompetitor(sailNumberOrTrackerID, threeLetterIOCCode, name,
|
||||
getCurrentBoatClass());
|
||||
Set<Competitor> competitorsOfCurrentRace = competitorsPerRaceID.get(currentRaceID);
|
||||
if (competitorsOfCurrentRace == null) {
|
||||
competitorsOfCurrentRace = new HashSet<>();
|
||||
competitorsPerRaceID.put(currentRaceID, competitorsOfCurrentRace);
|
||||
}
|
||||
competitorsOfCurrentRace.add(competitor);
|
||||
competitorByHashValue.put(hashValue, competitor);
|
||||
} else {
|
||||
// consider it a mark
|
||||
Mark mark = domainFactory.getOrCreateMark(sailNumberOrTrackerID);
|
||||
Map<String, Mark> marksOfCurrentRace = marksPerRaceIDPerMarkID.get(currentRaceID);
|
||||
if (marksOfCurrentRace == null) {
|
||||
marksOfCurrentRace = new HashMap<>();
|
||||
marksPerRaceIDPerMarkID.put(currentRaceID, marksOfCurrentRace);
|
||||
}
|
||||
marksOfCurrentRace.put(sailNumberOrTrackerID, mark);
|
||||
markByHashValue.put(hashValue, mark);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void mark(MarkType markType, String name, byte index, String id1, String id2, short windSpeedInKnots,
|
||||
short trueWindDirectionInDegrees) {
|
||||
// TODO Auto-generated method stub
|
||||
super.mark(markType, name, index, id1, id2, windSpeedInKnots, trueWindDirectionInDegrees);
|
||||
final List<String> markNames = new ArrayList<>();
|
||||
markNames.add(id1);
|
||||
if (id2 != null) {
|
||||
markNames.add(id2);
|
||||
}
|
||||
final ControlPoint controlPoint = domainFactory.getOrCreateControlPoint(markNames);
|
||||
if (index == 0) {
|
||||
currentCourseDefinition = new ArrayList<>();
|
||||
}
|
||||
while (currentCourseDefinition.size() < index+1) {
|
||||
currentCourseDefinition.add(null); // pad course
|
||||
}
|
||||
currentCourseDefinition.set(index, controlPoint);
|
||||
if (windSpeedInKnots != -1 && trueWindDirectionInDegrees != -1) {
|
||||
SpeedWithBearing windSpeedWithBearing = new KnotSpeedWithBearingImpl(windSpeedInKnots,
|
||||
new DegreeBearingImpl(trueWindDirectionInDegrees));
|
||||
windAtControlPoint.put(controlPoint, windSpeedWithBearing);
|
||||
} else {
|
||||
windAtControlPoint.remove(controlPoint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trackersCount(short trackersCount) {
|
||||
try {
|
||||
RaceDefinition race = racePerRaceID.get(currentRaceID);
|
||||
if (race == null) {
|
||||
createRace();
|
||||
} else {
|
||||
Course course = race.getCourse();
|
||||
try {
|
||||
course.update(currentCourseDefinition, domainFactory.getBaseDomainFactory());
|
||||
} catch (PatchFailedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
currentCourseDefinition = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void createRace() {
|
||||
final Regatta myRegatta = regatta != null ? regatta : domainFactory.getOrCreateRegatta(currentRaceID, trackedRegattaRegistry);
|
||||
RaceDefinition race = domainFactory.createRaceDefinition(
|
||||
myRegatta,
|
||||
currentRaceID, competitorsPerRaceID.get(currentRaceID), currentCourseDefinition);
|
||||
racePerRaceID.put(currentRaceID, race);
|
||||
DynamicTrackedRace trackedRace = trackedRegattaRegistry.getOrCreateTrackedRegatta(myRegatta).
|
||||
createTrackedRace(race, 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);
|
||||
trackedRacePerRaceID.put(currentRaceID, trackedRace);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trackers(int hashValue, int latitude, int longitude, short cog, short sog_Knots_x10, short average_sog,
|
||||
short vmg_Knots_x10, CompetitorStatus competitorStatus, short rank, short distanceToLeader_meters,
|
||||
short distanceToNextMark_meters, short nextMark, short pRank, short ptPoints, short pnPoints) {
|
||||
// TODO Auto-generated method stub
|
||||
super.trackers(hashValue, latitude, longitude, cog, sog_Knots_x10, average_sog, vmg_Knots_x10, competitorStatus, rank,
|
||||
distanceToLeader_meters, distanceToNextMark_meters, nextMark, pRank, ptPoints, pnPoints);
|
||||
DynamicTrackedRace trackedRace = trackedRacePerRaceID.get(currentRaceID);
|
||||
Position position = new DegreePosition(referenceLocation.getLatDeg() + ((double) latitude) / 10000000.,
|
||||
referenceLocation.getLngDeg() + ((double) longitude) / 10000000.);
|
||||
TimePoint raceTimePoint = raceTimePerRaceID.get(currentRaceID);
|
||||
Bearing bearing = new DegreeBearingImpl(cog);
|
||||
SpeedWithBearing speed = new KnotSpeedWithBearingImpl(((double) sog_Knots_x10) / 10., bearing);
|
||||
GPSFixMoving fix = new GPSFixMovingImpl(position, raceTimePoint, speed);
|
||||
Mark mark = markByHashValue.get(hashValue);
|
||||
if (mark != null) {
|
||||
for (Map.Entry<ControlPoint, SpeedWithBearing> controlPointWithWind : windAtControlPoint.entrySet()) {
|
||||
if (Util.contains(controlPointWithWind.getKey().getMarks(), mark)) {
|
||||
trackedRace.recordWind(new WindImpl(position, raceTimePoint, controlPointWithWind.getValue()),
|
||||
new WindSourceWithAdditionalID(WindSourceType.EXPEDITION, mark.getName()));
|
||||
}
|
||||
}
|
||||
trackedRace.recordFix(mark, fix);
|
||||
} else {
|
||||
Competitor competitor = competitorByHashValue.get(hashValue);
|
||||
if (competitor != null) {
|
||||
trackedRace.recordFix(competitor, fix);
|
||||
if (lastNextMark.get(competitor) != nextMark) {
|
||||
List<MarkPassing> newMarkPassings = new ArrayList<>();
|
||||
Util.addAll(trackedRace.getMarkPassings(competitor), newMarkPassings);
|
||||
newMarkPassings.add(new MarkPassingImpl(raceTimePoint,
|
||||
Util.get(trackedRace.getRace().getCourse().getWaypoints(), nextMark), competitor));
|
||||
trackedRace.updateMarkPassings(competitor, newMarkPassings);
|
||||
lastNextMark.put(competitor, nextMark);
|
||||
}
|
||||
} else {
|
||||
logger.warning("Couldn't find hash value "+hashValue+" in either the mark or the competitor map");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ranking(int hashValue, short rank, short rankIndex, short racePoints,
|
||||
CompetitorStatus competitorStatus, short finishRank, short finishRankIndex, int gap_seconds,
|
||||
int raceTime_seconds) {
|
||||
// TODO Auto-generated method stub
|
||||
super.ranking(hashValue, rank, rankIndex, racePoints, competitorStatus, finishRank, finishRankIndex, gap_seconds,
|
||||
raceTime_seconds);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user