mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-26 23:46:36 +00:00
bug5217: unfinished (5) ; first version of the race comparison
This commit is contained in:
+52
-65
@@ -1,95 +1,82 @@
|
|||||||
package com.sap.sailing.domain.test.hash;
|
package com.sap.sailing.domain.test.hash;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotEquals;
|
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import com.sap.sailing.domain.base.Mark;
|
|
||||||
import com.sap.sailing.domain.base.Waypoint;
|
|
||||||
import com.sap.sailing.domain.common.Position;
|
|
||||||
import com.sap.sailing.domain.common.impl.DegreePosition;
|
|
||||||
import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl;
|
|
||||||
import com.sap.sailing.domain.test.OnlineTracTracBasedTest;
|
import com.sap.sailing.domain.test.OnlineTracTracBasedTest;
|
||||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
|
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
|
||||||
import com.sap.sailing.domain.tractracadapter.ReceiverType;
|
import com.sap.sailing.domain.tractracadapter.ReceiverType;
|
||||||
import com.sap.sse.common.TimePoint;
|
|
||||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
|
||||||
|
|
||||||
public class CalculatingHashTest extends OnlineTracTracBasedTest{
|
public class CalculatingHashTest extends OnlineTracTracBasedTest {
|
||||||
private static final Logger logger = Logger.getLogger(CalculatingHashTest.class.getName());
|
private static final Logger logger = Logger.getLogger(CalculatingHashTest.class.getName());
|
||||||
DynamicTrackedRaceImpl trackedRace1;
|
DynamicTrackedRaceImpl trackedRace1;
|
||||||
DynamicTrackedRaceImpl trackedRace2;
|
DynamicTrackedRaceImpl trackedRace2;
|
||||||
|
|
||||||
public CalculatingHashTest() throws MalformedURLException, URISyntaxException {
|
public CalculatingHashTest() throws MalformedURLException, URISyntaxException {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getExpectedEventName() {
|
protected String getExpectedEventName() {
|
||||||
return "Academy Tracking 2011";
|
return "Academy Tracking 2011";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception{
|
public void setUp() throws Exception {
|
||||||
super.setUp("event_20110505_SailingTea", // Semifinale
|
super.setUp("event_20110505_SailingTea", // Semifinale
|
||||||
/* raceId */ "01ea3604-02ef-11e1-9efc-406186cbf87c",
|
/* raceId */ "01ea3604-02ef-11e1-9efc-406186cbf87c", /* liveUri */ null, /* storedUri */ null,
|
||||||
/* liveUri */ null, /* storedUri */ null,
|
new ReceiverType[] { ReceiverType.MARKPASSINGS, ReceiverType.MARKPOSITIONS, ReceiverType.RACECOURSE,
|
||||||
new ReceiverType[] { ReceiverType.MARKPASSINGS, ReceiverType.MARKPOSITIONS, ReceiverType.RACECOURSE, ReceiverType.RACESTARTFINISH, ReceiverType.RAWPOSITIONS, ReceiverType.SENSORDATA});
|
ReceiverType.RACESTARTFINISH, ReceiverType.RAWPOSITIONS, ReceiverType.SENSORDATA });
|
||||||
trackedRace1 = getTrackedRace();
|
trackedRace1 = getTrackedRace();
|
||||||
super.setUp();
|
super.setUp();
|
||||||
super.setUp("event_20110505_SailingTea", // Semifinale
|
super.setUp("event_20110505_SailingTea", // Semifinale
|
||||||
/* raceId */ "01ea3604-02ef-11e1-9efc-406186cbf87c",
|
/* raceId */ "01ea3604-02ef-11e1-9efc-406186cbf87c", /* liveUri */ null, /* storedUri */ null,
|
||||||
/* liveUri */ null, /* storedUri */ null,
|
new ReceiverType[] { ReceiverType.MARKPASSINGS, ReceiverType.MARKPOSITIONS, ReceiverType.RACECOURSE,
|
||||||
new ReceiverType[] { ReceiverType.MARKPASSINGS, ReceiverType.MARKPOSITIONS, ReceiverType.RACECOURSE, ReceiverType.RACESTARTFINISH, ReceiverType.RAWPOSITIONS, ReceiverType.SENSORDATA});
|
ReceiverType.RACESTARTFINISH, ReceiverType.RAWPOSITIONS, ReceiverType.SENSORDATA });
|
||||||
trackedRace2 = getTrackedRace();
|
trackedRace2 = getTrackedRace();
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test
|
// @Test
|
||||||
// public void testWithoutChangesInRace() {
|
// public void testWithoutChangesInRace() {
|
||||||
// trackedRace1.calculateHash();
|
// trackedRace1.calculateHash();
|
||||||
// int[] hash1 = trackedRace1.getHashValue();
|
// int[] hash1 = trackedRace1.getHashValue();
|
||||||
// trackedRace2.calculateHash();
|
// trackedRace2.calculateHash();
|
||||||
// int[] hash2 = trackedRace2.getHashValue();
|
// int[] hash2 = trackedRace2.getHashValue();
|
||||||
//
|
//
|
||||||
// assertEquals("0: Hash1: " + hash1[0] + " Hash2: " + hash2[0], hash1[0], hash2[0]);
|
// assertEquals("0: Hash1: " + hash1[0] + " Hash2: " + hash2[0], hash1[0], hash2[0]);
|
||||||
// assertEquals("1: Hash1: " + hash1[1] + " Hash2: " + hash2[1], hash1[1], hash2[1]);
|
// assertEquals("1: Hash1: " + hash1[1] + " Hash2: " + hash2[1], hash1[1], hash2[1]);
|
||||||
// assertEquals("2: Hash1: " + hash1[2] + " Hash2: " + hash2[2], hash1[2], hash2[2]);
|
// assertEquals("2: Hash1: " + hash1[2] + " Hash2: " + hash2[2], hash1[2], hash2[2]);
|
||||||
// assertEquals("3: Hash1: " + hash1[3] + " Hash2: " + hash2[3], hash1[3], hash2[3]);
|
// assertEquals("3: Hash1: " + hash1[3] + " Hash2: " + hash2[3], hash1[3], hash2[3]);
|
||||||
// assertEquals("4: Hash1: " + hash1[4] + " Hash2: " + hash2[4], hash1[4], hash2[4]);
|
// assertEquals("4: Hash1: " + hash1[4] + " Hash2: " + hash2[4], hash1[4], hash2[4]);
|
||||||
// assertEquals("5: Hash1: " + hash1[5] + " Hash2: " + hash2[5], hash1[5], hash2[5]);
|
// assertEquals("5: Hash1: " + hash1[5] + " Hash2: " + hash2[5], hash1[5], hash2[5]);
|
||||||
// assertEquals("6: Hash1: " + hash1[6] + " Hash2: " + hash2[6], hash1[6], hash2[6]);
|
// assertEquals("6: Hash1: " + hash1[6] + " Hash2: " + hash2[6], hash1[6], hash2[6]);
|
||||||
// //assertEquals("7: Hash1: " + hash1[7] + " Hash2: " + hash2[7], hash1[7], hash2[7]);
|
// //assertEquals("7: Hash1: " + hash1[7] + " Hash2: " + hash2[7], hash1[7], hash2[7]);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// @Test
|
// @Test
|
||||||
// public void testWithChangesInRace() {
|
// public void testWithChangesInRace() {
|
||||||
// trackedRace1.calculateHash();
|
// trackedRace1.calculateHash();
|
||||||
// int[] hash1 = trackedRace1.getHashValue();
|
// int[] hash1 = trackedRace1.getHashValue();
|
||||||
//// Change of the race should result in a different hash
|
//// Change of the race should result in a different hash
|
||||||
// TimePoint epoch = new MillisecondsTimePoint(0l);
|
// TimePoint epoch = new MillisecondsTimePoint(0l);
|
||||||
// TimePoint now = MillisecondsTimePoint.now();
|
// TimePoint now = MillisecondsTimePoint.now();
|
||||||
// Map<String, Position> markPositions = new HashMap<String, Position>();
|
// Map<String, Position> markPositions = new HashMap<String, Position>();
|
||||||
// markPositions.put("CR Start (1)", new DegreePosition(53.562944999999985, 10.010104000000046));
|
// markPositions.put("CR Start (1)", new DegreePosition(53.562944999999985, 10.010104000000046));
|
||||||
// markPositions.put("CR Start (2)", new DegreePosition(53.562944999999985, 10.010104000000046));
|
// markPositions.put("CR Start (2)", new DegreePosition(53.562944999999985, 10.010104000000046));
|
||||||
// markPositions.put("Leeward mark", new DegreePosition(53.562145000000015, 10.009252));
|
// markPositions.put("Leeward mark", new DegreePosition(53.562145000000015, 10.009252));
|
||||||
// markPositions.put("Luvtonne", new DegreePosition(53.560581899999995, 10.005657));
|
// markPositions.put("Luvtonne", new DegreePosition(53.560581899999995, 10.005657));
|
||||||
// for (Waypoint w : getTrackedRace().getRace().getCourse().getWaypoints()) {
|
// for (Waypoint w : getTrackedRace().getRace().getCourse().getWaypoints()) {
|
||||||
// for (Mark mark : w.getMarks()) {
|
// for (Mark mark : w.getMarks()) {
|
||||||
// trackedRace2.getOrCreateTrack(mark).addGPSFix(new GPSFixImpl(markPositions.get(mark.getName()), epoch));
|
// trackedRace2.getOrCreateTrack(mark).addGPSFix(new GPSFixImpl(markPositions.get(mark.getName()), epoch));
|
||||||
// trackedRace2.getOrCreateTrack(mark).addGPSFix(new GPSFixImpl(markPositions.get(mark.getName()), now));
|
// trackedRace2.getOrCreateTrack(mark).addGPSFix(new GPSFixImpl(markPositions.get(mark.getName()), now));
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// trackedRace2.calculateHash();
|
// trackedRace2.calculateHash();
|
||||||
// int[] hash2 = trackedRace2.getHashValue();
|
// int[] hash2 = trackedRace2.getHashValue();
|
||||||
//
|
//
|
||||||
// assertNotEquals("Hash1 and Hash2 are equal", hash1, hash2);
|
// assertNotEquals("Hash1 and Hash2 are equal", hash1, hash2);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -50,6 +50,7 @@ import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
|||||||
import com.sap.sailing.domain.common.tracking.SensorFix;
|
import com.sap.sailing.domain.common.tracking.SensorFix;
|
||||||
import com.sap.sailing.domain.leaderboard.ScoringScheme;
|
import com.sap.sailing.domain.leaderboard.ScoringScheme;
|
||||||
import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike;
|
import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike;
|
||||||
|
import com.sap.sailing.domain.markpassinghash.impl.TrackedRaceHashForMarkPassingComparatorImpl.TypeOfHash;
|
||||||
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
||||||
import com.sap.sailing.domain.polars.PolarDataService;
|
import com.sap.sailing.domain.polars.PolarDataService;
|
||||||
import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver;
|
import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver;
|
||||||
@@ -89,7 +90,6 @@ import com.sap.sailing.domain.tracking.WindStore;
|
|||||||
import com.sap.sailing.domain.tracking.WindSummary;
|
import com.sap.sailing.domain.tracking.WindSummary;
|
||||||
import com.sap.sailing.domain.tracking.WindTrack;
|
import com.sap.sailing.domain.tracking.WindTrack;
|
||||||
import com.sap.sailing.domain.tracking.WindWithConfidence;
|
import com.sap.sailing.domain.tracking.WindWithConfidence;
|
||||||
import com.sap.sailing.domain.tracking.impl.TrackedRaceHashForMarkPassingComperatorImpl.typeOfHash;
|
|
||||||
import com.sap.sailing.domain.tracking.impl.WindTrackImpl;
|
import com.sap.sailing.domain.tracking.impl.WindTrackImpl;
|
||||||
import com.sap.sailing.domain.windestimation.IncrementalWindEstimation;
|
import com.sap.sailing.domain.windestimation.IncrementalWindEstimation;
|
||||||
import com.sap.sse.common.Bearing;
|
import com.sap.sse.common.Bearing;
|
||||||
@@ -1365,11 +1365,11 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setHashValuesForMarkPassingCalculation(Map<typeOfHash, Integer> hashValues) {
|
public void setHashValuesForMarkPassingCalculation(Map<TypeOfHash, Integer> hashValues) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<typeOfHash, Integer> getHashValuesForMarkPassingCalculation() {
|
public Map<TypeOfHash, Integer> getHashValuesForMarkPassingCalculation() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -41,6 +41,7 @@ import com.sap.sailing.domain.common.WindSourceType;
|
|||||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||||
import com.sap.sailing.domain.common.tracking.SensorFix;
|
import com.sap.sailing.domain.common.tracking.SensorFix;
|
||||||
|
import com.sap.sailing.domain.markpassinghash.impl.TrackedRaceHashForMarkPassingComparatorImpl.TypeOfHash;
|
||||||
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
||||||
import com.sap.sailing.domain.polars.PolarDataService;
|
import com.sap.sailing.domain.polars.PolarDataService;
|
||||||
import com.sap.sailing.domain.ranking.RankingMetric;
|
import com.sap.sailing.domain.ranking.RankingMetric;
|
||||||
@@ -69,7 +70,6 @@ import com.sap.sailing.domain.tracking.WindSummary;
|
|||||||
import com.sap.sailing.domain.tracking.WindTrack;
|
import com.sap.sailing.domain.tracking.WindTrack;
|
||||||
import com.sap.sailing.domain.tracking.WindWithConfidence;
|
import com.sap.sailing.domain.tracking.WindWithConfidence;
|
||||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl;
|
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl;
|
||||||
import com.sap.sailing.domain.tracking.impl.TrackedRaceHashForMarkPassingComperatorImpl.typeOfHash;
|
|
||||||
import com.sap.sailing.domain.windestimation.IncrementalWindEstimation;
|
import com.sap.sailing.domain.windestimation.IncrementalWindEstimation;
|
||||||
import com.sap.sse.common.Bearing;
|
import com.sap.sse.common.Bearing;
|
||||||
import com.sap.sse.common.Distance;
|
import com.sap.sse.common.Distance;
|
||||||
@@ -876,11 +876,11 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setHashValuesForMarkPassingCalculation(Map<typeOfHash, Integer> hashValues) {
|
public void setHashValuesForMarkPassingCalculation(Map<TypeOfHash, Integer> hashValues) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<typeOfHash, Integer> getHashValuesForMarkPassingCalculation() {
|
public Map<TypeOfHash, Integer> getHashValuesForMarkPassingCalculation() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ Export-Package: com.sap.sailing.domain.base,
|
|||||||
com.sap.sailing.domain.markpassingcalculation,
|
com.sap.sailing.domain.markpassingcalculation,
|
||||||
com.sap.sailing.domain.markpassingcalculation.impl,
|
com.sap.sailing.domain.markpassingcalculation.impl,
|
||||||
com.sap.sailing.domain.markpassingcalculation.splining,
|
com.sap.sailing.domain.markpassingcalculation.splining,
|
||||||
|
com.sap.sailing.domain.markpassinghash.impl;x-friends:="com.sap.sailing.domain.persistence",
|
||||||
com.sap.sailing.domain.masterdataimport,
|
com.sap.sailing.domain.masterdataimport,
|
||||||
com.sap.sailing.domain.orc,
|
com.sap.sailing.domain.orc,
|
||||||
com.sap.sailing.domain.orc.impl;x-friends:="com.sap.sailing.domain.test,com.sap.sailing.domain.test,com.sap.sailing.mongodb.test",
|
com.sap.sailing.domain.orc.impl;x-friends:="com.sap.sailing.domain.test,com.sap.sailing.domain.test,com.sap.sailing.mongodb.test",
|
||||||
|
|||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package com.sap.sailing.domain.markpassinghash;
|
||||||
|
|
||||||
|
import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl;
|
||||||
|
|
||||||
|
public interface TrackedRaceHashForMarkPassingCalculation {
|
||||||
|
|
||||||
|
boolean equals(TrackedRaceImpl trackedRace);
|
||||||
|
}
|
||||||
+29
-27
@@ -1,67 +1,69 @@
|
|||||||
package com.sap.sailing.domain.tracking;
|
package com.sap.sailing.domain.markpassinghash;
|
||||||
|
|
||||||
import com.sap.sailing.domain.base.Boat;
|
import com.sap.sailing.domain.base.Boat;
|
||||||
import com.sap.sailing.domain.base.Competitor;
|
import com.sap.sailing.domain.base.Competitor;
|
||||||
import com.sap.sailing.domain.common.Position;
|
import com.sap.sailing.domain.common.Position;
|
||||||
|
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||||
import com.sap.sse.common.TimePoint;
|
import com.sap.sse.common.TimePoint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This comperator is used to calculate a set of hashes for a {@link trackedRace}
|
* This comperator is used to calculate a set of hashes for a {@link trackedRace} in order to lay the foundation to
|
||||||
* in order to lay the foundation to decide if the {@link markpassings} are recalculated or
|
* decide if the {@link markpassings} are recalculated or loaded out of the database, when restarting a server.
|
||||||
* loaded out of the database, when restarting a server.
|
|
||||||
*
|
*
|
||||||
* @author Fabian Kallenbach (I550803)
|
* @author Fabian Kallenbach (I550803)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface TrackedRaceHashForMarkPassingComperator {
|
public interface TrackedRaceHashForMarkPassingComparator {
|
||||||
/**
|
/**
|
||||||
* This Method loads the individual hashes into the local hashmap and then {@link #setHashValuesForMarkPassingCalculation} in {@link TrackedRace}.
|
* This Method loads the individual hashes into the local hashmap and then
|
||||||
|
* {@link #setHashValuesForMarkPassingCalculation} in {@link TrackedRace}.
|
||||||
*/
|
*/
|
||||||
void CalculateHash();
|
void calculateHash();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the hash for the {@link competitor} on the basis of it's ID.
|
* Calculates the hash for the {@link competitor} on the basis of it's ID.
|
||||||
*/
|
*/
|
||||||
int CalculateHashForCompetitor (Competitor c);
|
int calculateHashForCompetitor(Competitor c);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the hash for the {@link boat} on the basis of it's ID.
|
* Calculates the hash for the {@link boat} on the basis of it's ID.
|
||||||
*/
|
*/
|
||||||
int CalculateHashForBoat (Boat b);
|
int calculateHashForBoat(Boat b);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the hash for the race start on the basis of {@link #getStartOfTracking} and if it isn't inferred also on the {@link #getStartOfRace}.
|
* Calculates the hash for the race start on the basis of {@link #getStartOfTracking} and if it isn't inferred also
|
||||||
|
* on the {@link #getStartOfRace}.
|
||||||
*/
|
*/
|
||||||
int CalculateHashForStart ();
|
int calculateHashForStart();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the hash for the race end on the basis of {@link #getEndOfTracking}.
|
* Calculates the hash for the race end on the basis of {@link #getEndOfTracking}.
|
||||||
*/
|
*/
|
||||||
int CalculateHashForEnd ();
|
int calculateHashForEnd();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the hash for the number of GPSFixes of the {@link trackedRace}.
|
* Calculates the hash for the number of GPSFixes of the {@link trackedRace}.
|
||||||
*/
|
*/
|
||||||
int CalculateHashForNumberOfGPSFixes ();
|
int calculateHashForNumberOfGPSFixes();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the hash for all {@link GPSFix} on the basis of theire {@link TimePoint}s and {@link Position}s.
|
* Calculates the hash for all {@link GPSFix} on the basis of theire {@link TimePoint}s and {@link Position}s.
|
||||||
*/
|
*/
|
||||||
int CalculateHashForGPSFixes ();
|
int calculateHashForGPSFixes();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the hash for a {@link TimePoint}.
|
* Calculates the hash for a {@link TimePoint}.
|
||||||
*/
|
*/
|
||||||
int CalculateHashForTimePoint (TimePoint tp);
|
int calculateHashForTimePoint(TimePoint tp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the hash for a {@link Position}.
|
* Calculates the hash for a {@link Position}.
|
||||||
*/
|
*/
|
||||||
int CalculateHashForPosition (Position p);
|
int calculateHashForPosition(Position p);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the hash for a {@link Waypoint}.
|
* Calculates the hash for a {@link Waypoint}.
|
||||||
*/
|
*/
|
||||||
int CalculateHashForWaypoints ();
|
int calculateHashForWaypoints();
|
||||||
}
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package com.sap.sailing.domain.markpassinghash;
|
||||||
|
|
||||||
|
import com.sap.sailing.domain.markpassinghash.impl.TrackedRaceHashForMarkPassingCalculationImpl;
|
||||||
|
import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl;
|
||||||
|
|
||||||
|
public interface TrackedRaceHashForMaskPassingCalculationFactory {
|
||||||
|
|
||||||
|
TrackedRaceHashForMarkPassingCalculationImpl create(TrackedRaceImpl trackedRace);
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package com.sap.sailing.domain.markpassinghash.impl;
|
||||||
|
|
||||||
|
import com.sap.sailing.domain.markpassinghash.TrackedRaceHashForMaskPassingCalculationFactory;
|
||||||
|
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||||
|
import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl;
|
||||||
|
|
||||||
|
public class TrackedRaceHashForMarkPassingCalculationFactoryImpl implements TrackedRaceHashForMaskPassingCalculationFactory{
|
||||||
|
private final TrackedRace trackedRace;
|
||||||
|
|
||||||
|
public TrackedRaceHashForMarkPassingCalculationFactoryImpl(TrackedRaceImpl trackedRace) {
|
||||||
|
this.trackedRace = trackedRace;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TrackedRaceHashForMarkPassingCalculationImpl create(TrackedRaceImpl trackedRace) {
|
||||||
|
|
||||||
|
TrackedRaceHashForMarkPassingCalculationImpl hashValues = new TrackedRaceHashForMarkPassingCalculationImpl(trackedRace.getHashValuesForMarkPassingCalculation());
|
||||||
|
return hashValues;
|
||||||
|
}
|
||||||
|
}
|
||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
package com.sap.sailing.domain.markpassinghash.impl;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.sap.sailing.domain.base.Competitor;
|
||||||
|
import com.sap.sailing.domain.markpassinghash.impl.TrackedRaceHashForMarkPassingComparatorImpl.TypeOfHash;
|
||||||
|
import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl;
|
||||||
|
|
||||||
|
public class TrackedRaceHashForMarkPassingCalculationImpl {
|
||||||
|
private final int competitor;
|
||||||
|
private final int start;
|
||||||
|
private final int end;
|
||||||
|
private final int waypoints;
|
||||||
|
private final int numberOfGPSFixes;
|
||||||
|
private final int gpsFixes;
|
||||||
|
|
||||||
|
public TrackedRaceHashForMarkPassingCalculationImpl(Map<TypeOfHash, Integer> hashValues) {
|
||||||
|
this.competitor = hashValues.get(TypeOfHash.COMPETITOR);
|
||||||
|
this.start = hashValues.get(TypeOfHash.START);
|
||||||
|
this.end = hashValues.get(TypeOfHash.END);
|
||||||
|
this.waypoints = hashValues.get(TypeOfHash.WAYPOINTS);
|
||||||
|
this.numberOfGPSFixes = hashValues.get(TypeOfHash.NUMBEROFGPSFIXES);
|
||||||
|
this.gpsFixes = hashValues.get(TypeOfHash.GPSFIXES);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(TrackedRaceImpl trackedRace) {
|
||||||
|
TrackedRaceHashForMarkPassingComparatorImpl hashCalculator = new TrackedRaceHashForMarkPassingComparatorImpl(
|
||||||
|
trackedRace);
|
||||||
|
int competitorHash = 0;
|
||||||
|
|
||||||
|
if (hashCalculator.calculateHashForWaypoints() != waypoints)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (Competitor c : trackedRace.getRace().getCompetitors()) {
|
||||||
|
competitorHash = competitorHash + hashCalculator.calculateHashForCompetitor(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (competitorHash != competitor)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (hashCalculator.calculateHashForStart() != start)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (hashCalculator.calculateHashForEnd() != end)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (hashCalculator.calculateHashForNumberOfGPSFixes() != numberOfGPSFixes)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (hashCalculator.calculateHashForGPSFixes() != gpsFixes)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
+70
-79
@@ -1,4 +1,4 @@
|
|||||||
package com.sap.sailing.domain.tracking.impl;
|
package com.sap.sailing.domain.markpassinghash.impl;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -10,54 +10,46 @@ import com.sap.sailing.domain.base.Mark;
|
|||||||
import com.sap.sailing.domain.base.Waypoint;
|
import com.sap.sailing.domain.base.Waypoint;
|
||||||
import com.sap.sailing.domain.common.Position;
|
import com.sap.sailing.domain.common.Position;
|
||||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||||
import com.sap.sailing.domain.tracking.TrackedRaceHashForMarkPassingComperator;
|
import com.sap.sailing.domain.markpassinghash.TrackedRaceHashForMarkPassingComparator;
|
||||||
|
import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl;
|
||||||
import com.sap.sse.common.TimePoint;
|
import com.sap.sse.common.TimePoint;
|
||||||
|
import com.sap.sse.common.Util;
|
||||||
|
|
||||||
public class TrackedRaceHashForMarkPassingComperatorImpl implements TrackedRaceHashForMarkPassingComperator{
|
public class TrackedRaceHashForMarkPassingComparatorImpl implements TrackedRaceHashForMarkPassingComparator {
|
||||||
|
|
||||||
|
public enum TypeOfHash {
|
||||||
|
COMPETITOR, START, END, WAYPOINTS, NUMBEROFGPSFIXES, GPSFIXES
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(TrackedRaceHashForMarkPassingComparatorImpl.class.getName());
|
||||||
|
|
||||||
public enum typeOfHash {
|
|
||||||
COMPETITOR,
|
|
||||||
BOAT,
|
|
||||||
START,
|
|
||||||
END,
|
|
||||||
WAYPOINTS,
|
|
||||||
NUMBEROFGPSFIXES,
|
|
||||||
GPSFIXES
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(TrackedRaceHashForMarkPassingComperatorImpl.class.getName());
|
|
||||||
|
|
||||||
private TrackedRaceImpl trackedRace;
|
private TrackedRaceImpl trackedRace;
|
||||||
private final Iterable<Waypoint> waypoints;
|
private final Iterable<Waypoint> waypoints;
|
||||||
private Map<typeOfHash, Integer> hashValues;
|
private Map<TypeOfHash, Integer> hashValues;
|
||||||
|
|
||||||
public TrackedRaceHashForMarkPassingComperatorImpl (TrackedRaceImpl trackedRace) {
|
public TrackedRaceHashForMarkPassingComparatorImpl(TrackedRaceImpl trackedRace) {
|
||||||
this.trackedRace = trackedRace;
|
this.trackedRace = trackedRace;
|
||||||
this.waypoints = trackedRace.getRace().getCourse().getWaypoints();
|
this.waypoints = trackedRace.getRace().getCourse().getWaypoints();
|
||||||
this.hashValues = new HashMap<>();
|
this.hashValues = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CalculateHash() {
|
public void calculateHash() {
|
||||||
int competitorHash = 0;
|
int competitorHash = 0;
|
||||||
int boatHash = 0;
|
hashValues.put(TypeOfHash.WAYPOINTS, calculateHashForWaypoints());
|
||||||
hashValues.put(typeOfHash.WAYPOINTS, CalculateHashForWaypoints());
|
|
||||||
for (Competitor c : trackedRace.getRace().getCompetitors()) {
|
for (Competitor c : trackedRace.getRace().getCompetitors()) {
|
||||||
competitorHash = competitorHash + CalculateHashForCompetitor(c);
|
competitorHash = competitorHash + calculateHashForCompetitor(c);
|
||||||
boatHash = boatHash + CalculateHashForBoat(trackedRace.getRace().getBoatOfCompetitor(c));
|
|
||||||
}
|
}
|
||||||
hashValues.put(typeOfHash.COMPETITOR, competitorHash);
|
hashValues.put(TypeOfHash.COMPETITOR, competitorHash);
|
||||||
hashValues.put(typeOfHash.BOAT, boatHash);
|
hashValues.put(TypeOfHash.START, calculateHashForStart());
|
||||||
hashValues.put(typeOfHash.START, CalculateHashForStart());
|
hashValues.put(TypeOfHash.END, calculateHashForEnd());
|
||||||
hashValues.put(typeOfHash.END, CalculateHashForEnd());
|
hashValues.put(TypeOfHash.NUMBEROFGPSFIXES, calculateHashForNumberOfGPSFixes());
|
||||||
|
hashValues.put(TypeOfHash.GPSFIXES, calculateHashForGPSFixes());
|
||||||
hashValues.put(typeOfHash.NUMBEROFGPSFIXES, CalculateHashForNumberOfGPSFixes());
|
|
||||||
hashValues.put(typeOfHash.GPSFIXES, CalculateHashForGPSFixes());
|
|
||||||
|
|
||||||
trackedRace.setHashValuesForMarkPassingCalculation(hashValues);
|
trackedRace.setHashValuesForMarkPassingCalculation(hashValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CalculateHashForCompetitor (Competitor c) {
|
public int calculateHashForCompetitor(Competitor c) {
|
||||||
int res = 0;
|
int res = 0;
|
||||||
try {
|
try {
|
||||||
res = res ^ c.getId().hashCode();
|
res = res ^ c.getId().hashCode();
|
||||||
res = (res << 5) - res;
|
res = (res << 5) - res;
|
||||||
@@ -66,50 +58,50 @@ public class TrackedRaceHashForMarkPassingComperatorImpl implements TrackedRaceH
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CalculateHashForBoat (Boat b) {
|
public int calculateHashForBoat(Boat b) {
|
||||||
int res = 0;
|
int res = 0;
|
||||||
try {
|
try {
|
||||||
res = res ^ b.getBoatClass().getName().hashCode();
|
res = res ^ b.getBoatClass().getName().hashCode();
|
||||||
res = (res << 5) - res;
|
res = (res << 5) - res;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.info("Hash calculation for competitor " + b + " failed: " + e);
|
logger.info("Hash calculation for competitor " + b + " failed: " + e);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CalculateHashForStart () {
|
public int calculateHashForStart() {
|
||||||
int res = 0;
|
int res = 0;
|
||||||
try {
|
try {
|
||||||
res = res ^ CalculateHashForTimePoint(trackedRace.getStartOfTracking());
|
res = res ^ calculateHashForTimePoint(trackedRace.getStartOfTracking());
|
||||||
res = (res << 5) - res;
|
res = (res << 5) - res;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.info("An error occured when getting the start of tracking: " + e);
|
logger.info("An error occured when getting the start of tracking: " + e);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
//Maybe that could be solved by using .getStartOfRace(boolean inferred)
|
// Maybe that could be solved by using .getStartOfRace(boolean inferred)
|
||||||
if( trackedRace.getTrackedRegatta().getRegatta().useStartTimeInference() == false) {
|
if (trackedRace.getTrackedRegatta().getRegatta().useStartTimeInference() == false) {
|
||||||
res = res ^ CalculateHashForTimePoint(trackedRace.getStartOfRace());
|
res = res ^ calculateHashForTimePoint(trackedRace.getStartOfRace());
|
||||||
res = (res << 5) - res;
|
res = (res << 5) - res;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.info("An error occured when getting the starttime: " + e);
|
logger.info("An error occured when getting the starttime: " + e);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CalculateHashForEnd () {
|
public int calculateHashForEnd() {
|
||||||
int res = 0;
|
int res = 0;
|
||||||
try {
|
try {
|
||||||
res = res ^ CalculateHashForTimePoint(trackedRace.getEndOfTracking());
|
res = res ^ calculateHashForTimePoint(trackedRace.getEndOfTracking());
|
||||||
res = (res << 5) - res;
|
res = (res << 5) - res;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.info("Hash calculation for end of Tracking failed: " + e);
|
logger.info("Hash calculation for end of Tracking failed: " + e);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CalculateHashForNumberOfGPSFixes () {
|
public int calculateHashForNumberOfGPSFixes() {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (Waypoint w : waypoints) {
|
for (Waypoint w : waypoints) {
|
||||||
for (Mark m : w.getMarks()) {
|
for (Mark m : w.getMarks()) {
|
||||||
@@ -117,8 +109,8 @@ public class TrackedRaceHashForMarkPassingComperatorImpl implements TrackedRaceH
|
|||||||
try {
|
try {
|
||||||
trackedRace.getTrack(m).lockForRead();
|
trackedRace.getTrack(m).lockForRead();
|
||||||
gpsTrack = trackedRace.getTrack(m).getFixes();
|
gpsTrack = trackedRace.getTrack(m).getFixes();
|
||||||
//Unused warning since we need the individual Fixes only to count
|
// Unused warning since we need the individual Fixes only to count
|
||||||
for (GPSFix gf : gpsTrack) {
|
for (int i = 0; i < Util.size(gpsTrack); i++) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -130,9 +122,8 @@ public class TrackedRaceHashForMarkPassingComperatorImpl implements TrackedRaceH
|
|||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int calculateHashForGPSFixes() {
|
||||||
public int CalculateHashForGPSFixes () {
|
|
||||||
int res = 0;
|
int res = 0;
|
||||||
for (Waypoint w : waypoints) {
|
for (Waypoint w : waypoints) {
|
||||||
for (Mark m : w.getMarks()) {
|
for (Mark m : w.getMarks()) {
|
||||||
@@ -141,9 +132,9 @@ public class TrackedRaceHashForMarkPassingComperatorImpl implements TrackedRaceH
|
|||||||
trackedRace.getTrack(m).lockForRead();
|
trackedRace.getTrack(m).lockForRead();
|
||||||
gpsTrack = trackedRace.getTrack(m).getFixes();
|
gpsTrack = trackedRace.getTrack(m).getFixes();
|
||||||
for (GPSFix gf : gpsTrack) {
|
for (GPSFix gf : gpsTrack) {
|
||||||
res = res ^ CalculateHashForTimePoint(gf.getTimePoint());
|
res = res ^ calculateHashForTimePoint(gf.getTimePoint());
|
||||||
res = (res << 5) - res;
|
res = (res << 5) - res;
|
||||||
res = res ^ CalculateHashForPosition(gf.getPosition());
|
res = res ^ calculateHashForPosition(gf.getPosition());
|
||||||
res = (res << 5) - res;
|
res = (res << 5) - res;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -155,31 +146,31 @@ public class TrackedRaceHashForMarkPassingComperatorImpl implements TrackedRaceH
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CalculateHashForTimePoint (TimePoint tp) {
|
public int calculateHashForTimePoint(TimePoint tp) {
|
||||||
int res = 0;
|
int res = 0;
|
||||||
//How problematic is this cast?
|
// How problematic is this cast?
|
||||||
try {
|
try {
|
||||||
res = res ^ (int) tp.asMillis();
|
res = res ^ (int) tp.asMillis();
|
||||||
res = (res << 5) - res;
|
res = (res << 5) - res;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.info("Ther");
|
logger.info("Ther");
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int CalculateHashForPosition (Position p) {
|
|
||||||
int res = 0;
|
|
||||||
res = res ^ (int) p.getLatDeg();
|
|
||||||
res = res ^ (int) p.getLngDeg();
|
|
||||||
res = (res << 5) - res;
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CalculateHashForWaypoints () {
|
public int calculateHashForPosition(Position p) {
|
||||||
int res = 0;
|
int res = 0;
|
||||||
for(Waypoint p : waypoints) {
|
res = res ^ (int) p.getLatDeg();
|
||||||
|
res = res ^ (int) p.getLngDeg();
|
||||||
|
res = (res << 5) - res;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int calculateHashForWaypoints() {
|
||||||
|
int res = 0;
|
||||||
|
for (Waypoint p : waypoints) {
|
||||||
res = res ^ p.getId().hashCode();
|
res = res ^ p.getId().hashCode();
|
||||||
try {
|
try {
|
||||||
res = res ^ p.getPassingInstructions().hashCode();
|
res = res ^ p.getPassingInstructions().hashCode();
|
||||||
@@ -187,6 +178,6 @@ public class TrackedRaceHashForMarkPassingComperatorImpl implements TrackedRaceH
|
|||||||
logger.info("Hash calculation for Waypoints failed: " + e);
|
logger.info("Hash calculation for Waypoints failed: " + e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-3
@@ -35,13 +35,13 @@ import com.sap.sailing.domain.common.WindSource;
|
|||||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||||
import com.sap.sailing.domain.common.tracking.SensorFix;
|
import com.sap.sailing.domain.common.tracking.SensorFix;
|
||||||
|
import com.sap.sailing.domain.markpassinghash.impl.TrackedRaceHashForMarkPassingComparatorImpl.TypeOfHash;
|
||||||
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
||||||
import com.sap.sailing.domain.polars.PolarDataService;
|
import com.sap.sailing.domain.polars.PolarDataService;
|
||||||
import com.sap.sailing.domain.ranking.RankingMetric;
|
import com.sap.sailing.domain.ranking.RankingMetric;
|
||||||
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
|
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
|
||||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl;
|
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl;
|
||||||
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
|
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
|
||||||
import com.sap.sailing.domain.tracking.impl.TrackedRaceHashForMarkPassingComperatorImpl.typeOfHash;
|
|
||||||
import com.sap.sailing.domain.windestimation.IncrementalWindEstimation;
|
import com.sap.sailing.domain.windestimation.IncrementalWindEstimation;
|
||||||
import com.sap.sse.common.Bearing;
|
import com.sap.sse.common.Bearing;
|
||||||
import com.sap.sse.common.Distance;
|
import com.sap.sse.common.Distance;
|
||||||
@@ -814,11 +814,11 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setHashValuesForMarkPassingCalculation(Map<typeOfHash, Integer> hashValues) {
|
public void setHashValuesForMarkPassingCalculation(Map<TypeOfHash, Integer> hashValues) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<typeOfHash, Integer> getHashValuesForMarkPassingCalculation() {
|
public Map<TypeOfHash, Integer> getHashValuesForMarkPassingCalculation() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+264
-224
@@ -52,6 +52,7 @@ import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
|||||||
import com.sap.sailing.domain.common.tracking.SensorFix;
|
import com.sap.sailing.domain.common.tracking.SensorFix;
|
||||||
import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCalculationReuseCache;
|
import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCalculationReuseCache;
|
||||||
import com.sap.sailing.domain.markpassingcalculation.MarkPassingCalculator;
|
import com.sap.sailing.domain.markpassingcalculation.MarkPassingCalculator;
|
||||||
|
import com.sap.sailing.domain.markpassinghash.impl.TrackedRaceHashForMarkPassingComparatorImpl.TypeOfHash;
|
||||||
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
||||||
import com.sap.sailing.domain.polars.PolarDataService;
|
import com.sap.sailing.domain.polars.PolarDataService;
|
||||||
import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver;
|
import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver;
|
||||||
@@ -60,7 +61,6 @@ import com.sap.sailing.domain.ranking.RankingMetric;
|
|||||||
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
|
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
|
||||||
import com.sap.sailing.domain.tracking.impl.NonCachingMarkPositionAtTimePointCache;
|
import com.sap.sailing.domain.tracking.impl.NonCachingMarkPositionAtTimePointCache;
|
||||||
import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl;
|
import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl;
|
||||||
import com.sap.sailing.domain.tracking.impl.TrackedRaceHashForMarkPassingComperatorImpl.typeOfHash;
|
|
||||||
import com.sap.sailing.domain.windestimation.IncrementalWindEstimation;
|
import com.sap.sailing.domain.windestimation.IncrementalWindEstimation;
|
||||||
import com.sap.sse.common.Bearing;
|
import com.sap.sse.common.Bearing;
|
||||||
import com.sap.sse.common.Distance;
|
import com.sap.sse.common.Distance;
|
||||||
@@ -74,6 +74,7 @@ import com.sap.sse.security.shared.HasPermissions;
|
|||||||
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
|
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
|
||||||
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
|
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
|
||||||
import com.sap.sse.security.shared.WithQualifiedObjectIdentifier;
|
import com.sap.sse.security.shared.WithQualifiedObjectIdentifier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Live tracking data of a single race. The race follows a defined {@link Course} with a sequence of {@link Leg}s. The
|
* Live tracking data of a single race. The race follows a defined {@link Course} with a sequence of {@link Leg}s. The
|
||||||
* course may change over time as the race committee decides to change it. Therefore, a {@link TrackedRace} instance
|
* course may change over time as the race committee decides to change it. Therefore, a {@link TrackedRace} instance
|
||||||
@@ -89,8 +90,7 @@ import com.sap.sse.security.shared.WithQualifiedObjectIdentifier;
|
|||||||
* @author Axel Uhl (d043530)
|
* @author Axel Uhl (d043530)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public interface TrackedRace
|
public interface TrackedRace extends Serializable, IsManagedByCache<DomainFactory>, WithQualifiedObjectIdentifier {
|
||||||
extends Serializable, IsManagedByCache<DomainFactory>, WithQualifiedObjectIdentifier {
|
|
||||||
final Duration START_TRACKING_THIS_MUCH_BEFORE_RACE_START = Duration.ONE_MINUTE.times(5);
|
final Duration START_TRACKING_THIS_MUCH_BEFORE_RACE_START = Duration.ONE_MINUTE.times(5);
|
||||||
final Duration STOP_TRACKING_THIS_MUCH_AFTER_RACE_FINISH = Duration.ONE_SECOND.times(30);
|
final Duration STOP_TRACKING_THIS_MUCH_AFTER_RACE_FINISH = Duration.ONE_SECOND.times(30);
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ public interface TrackedRace
|
|||||||
RaceDefinition getRace();
|
RaceDefinition getRace();
|
||||||
|
|
||||||
RegattaAndRaceIdentifier getRaceIdentifier();
|
RegattaAndRaceIdentifier getRaceIdentifier();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells how ranks are to be assigned to the competitors at any time during the race. For one-design boat classes
|
* Tells how ranks are to be assigned to the competitors at any time during the race. For one-design boat classes
|
||||||
* this will usually happen by projecting the competitors to the wind direction for upwind and downwind legs or to
|
* this will usually happen by projecting the competitors to the wind direction for upwind and downwind legs or to
|
||||||
@@ -116,17 +116,17 @@ public interface TrackedRace
|
|||||||
* Computes the estimated start time for this race (not to be confused with the {@link #getStartOfTracking()} time
|
* Computes the estimated start time for this race (not to be confused with the {@link #getStartOfTracking()} time
|
||||||
* point which is expected to be before the race start time). The highest precedence take the
|
* point which is expected to be before the race start time). The highest precedence take the
|
||||||
* {@link #attachedRaceLogs race logs} and their start time events, followed by the field {@link #startTimeReceived}
|
* {@link #attachedRaceLogs race logs} and their start time events, followed by the field {@link #startTimeReceived}
|
||||||
* which can explicitly be set using {@link #setStartTimeReceived(TimePoint)}. When there are no {@link MarkPassing}s
|
* which can explicitly be set using {@link #setStartTimeReceived(TimePoint)}. When there are no
|
||||||
* for the first mark, <code>null</code> is returned. If there are mark passings for the first mark and the start
|
* {@link MarkPassing}s for the first mark, <code>null</code> is returned. If there are mark passings for the first
|
||||||
* time is less than {@link #MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS} before the first mark
|
* mark and the start time is less than {@link #MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS}
|
||||||
* passing for the first mark. Otherwise, the first mark passing for the first mark minus
|
* before the first mark passing for the first mark. Otherwise, the first mark passing for the first mark minus
|
||||||
* {@link #MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS} is returned as the race start time.
|
* {@link #MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS} is returned as the race start time.
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* If no start time can be determined this way, <code>null</code> is returned.
|
* If no start time can be determined this way, <code>null</code> is returned.
|
||||||
*/
|
*/
|
||||||
TimePoint getStartOfRace();
|
TimePoint getStartOfRace();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Like {@link #getStartOfRace()}, but ignoring any inference from start mark passings in case {@code inferred} is
|
* Like {@link #getStartOfRace()}, but ignoring any inference from start mark passings in case {@code inferred} is
|
||||||
* {@code false}. In this case, if no official start time was set, e.g., in the {@link RaceLog} or explicitly using
|
* {@code false}. In this case, if no official start time was set, e.g., in the {@link RaceLog} or explicitly using
|
||||||
@@ -137,15 +137,15 @@ public interface TrackedRace
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the time point taken from a valid, non-revoked {@link RaceLogRaceStatusEvent} that transfers the race
|
* @return the time point taken from a valid, non-revoked {@link RaceLogRaceStatusEvent} that transfers the race
|
||||||
* into status {@link RaceLogRaceStatus#FINISHING} or {@code null} if no such event is found.
|
* into status {@link RaceLogRaceStatus#FINISHING} or {@code null} if no such event is found.
|
||||||
*/
|
*/
|
||||||
TimePoint getFinishingTime();
|
TimePoint getFinishingTime();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the time point taken from a valid, non-revoked {@link RaceLogRaceStatusEvent} that transfers the race
|
* @return the time point taken from a valid, non-revoked {@link RaceLogRaceStatusEvent} that transfers the race
|
||||||
* into status {@link RaceLogRaceStatus#FINISHED} from any of the {@link RaceLog}s attached to this race,
|
* into status {@link RaceLogRaceStatus#FINISHED} from any of the {@link RaceLog}s attached to this race, or
|
||||||
* or {@code null} if no such event is found.
|
* {@code null} if no such event is found.
|
||||||
*
|
*
|
||||||
* @see {@link RaceChangeListener#finishedTimeChanged(TimePoint, TimePoint)}
|
* @see {@link RaceChangeListener#finishedTimeChanged(TimePoint, TimePoint)}
|
||||||
*/
|
*/
|
||||||
TimePoint getFinishedTime();
|
TimePoint getFinishedTime();
|
||||||
@@ -172,18 +172,18 @@ public interface TrackedRace
|
|||||||
* Shorthand for <code>{@link #getStart()}.{@link TimePoint#compareTo(TimePoint) compareTo(at)} <= 0</code>
|
* Shorthand for <code>{@link #getStart()}.{@link TimePoint#compareTo(TimePoint) compareTo(at)} <= 0</code>
|
||||||
*/
|
*/
|
||||||
boolean hasStarted(TimePoint at);
|
boolean hasStarted(TimePoint at);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A race is considered "live" if it
|
* A race is considered "live" if it {@link TrackedRaceDTO#hasGPSData has GPS data} and
|
||||||
* {@link TrackedRaceDTO#hasGPSData has GPS data} and {@link TrackedRaceDTO#hasWindData wind data} and if the
|
* {@link TrackedRaceDTO#hasWindData wind data} and if the <code>at</code> time point is between the start and the
|
||||||
* <code>at</code> time point is between the start and the end of the race.
|
* end of the race.
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* The pre-start phase of a race is interesting also in live mode. Therefore, if a {@link TrackedRace#getStartOfRace start
|
* The pre-start phase of a race is interesting also in live mode. Therefore, if a {@link TrackedRace#getStartOfRace
|
||||||
* time} is available for the race, the {@link TimingConstants#PRE_START_PHASE_DURATION_IN_MILLIS} is subtracted
|
* start time} is available for the race, the {@link TimingConstants#PRE_START_PHASE_DURATION_IN_MILLIS} is
|
||||||
* from the actual start time so that the pre-start phase also counts as live. If no start time is known for the
|
* subtracted from the actual start time so that the pre-start phase also counts as live. If no start time is known
|
||||||
* race, but a {@link TrackedRace#getStartOfTracking start of tracking time} is known, it is used as the start of
|
* for the race, but a {@link TrackedRace#getStartOfTracking start of tracking time} is known, it is used as the
|
||||||
* the "live" interval.
|
* start of the "live" interval.
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* If an {@link TrackedRace#getEndOfRace end time} is already known for the race,
|
* If an {@link TrackedRace#getEndOfRace end time} is already known for the race,
|
||||||
@@ -193,8 +193,8 @@ public interface TrackedRace
|
|||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* @param at
|
* @param at
|
||||||
* the time point at which to determine whether the race for <code>fleet</code>
|
* the time point at which to determine whether the race for <code>fleet</code> is/was live. A
|
||||||
* is/was live. A <code>null</code> value will use the start time of the race.
|
* <code>null</code> value will use the start time of the race.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
boolean isLive(TimePoint at);
|
boolean isLive(TimePoint at);
|
||||||
@@ -222,12 +222,12 @@ public interface TrackedRace
|
|||||||
TrackedLeg getCurrentLeg(TimePoint timePoint);
|
TrackedLeg getCurrentLeg(TimePoint timePoint);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells the number of the last started leg at <code>timePoint</code>
|
* Tells the number of the last started leg at <code>timePoint</code> The leg number is 0 before the start, the
|
||||||
* The leg number is 0 before the start, the number of the current leg during the race
|
* number of the current leg during the race and the number of the last leg at the end of the race even if the race
|
||||||
* and the number of the last leg at the end of the race even if the race has finished.
|
* has finished.
|
||||||
*/
|
*/
|
||||||
int getLastLegStarted(TimePoint timePoint);
|
int getLastLegStarted(TimePoint timePoint);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Precondition: waypoint must still be part of {@link #getRace()}.{@link RaceDefinition#getCourse() getCourse()}.
|
* Precondition: waypoint must still be part of {@link #getRace()}.{@link RaceDefinition#getCourse() getCourse()}.
|
||||||
* Returns {@code null} for the first waypoint of the course. If the waypoint is not part of the course, an
|
* Returns {@code null} for the first waypoint of the course. If the waypoint is not part of the course, an
|
||||||
@@ -251,16 +251,21 @@ public interface TrackedRace
|
|||||||
* So every type of track has an associated name. With this construct you can have track implementations that
|
* So every type of track has an associated name. With this construct you can have track implementations that
|
||||||
* provide specific functionality based on the contained fix type.
|
* provide specific functionality based on the contained fix type.
|
||||||
*
|
*
|
||||||
* @param competitor the competitor to get the track for
|
* @param competitor
|
||||||
* @param trackName the name of the track to get
|
* the competitor to get the track for
|
||||||
|
* @param trackName
|
||||||
|
* the name of the track to get
|
||||||
* @return the track associated to the given Competitor and name or <code>null</code> if there is none.
|
* @return the track associated to the given Competitor and name or <code>null</code> if there is none.
|
||||||
*/
|
*/
|
||||||
<FixT extends SensorFix, TrackT extends SensorFixTrack<Competitor, FixT>> TrackT getSensorTrack(Competitor competitor, String trackName);
|
<FixT extends SensorFix, TrackT extends SensorFixTrack<Competitor, FixT>> TrackT getSensorTrack(
|
||||||
|
Competitor competitor, String trackName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all contained {@link SensorFixTrack SensorFixTracks} for the given trackName and associated to any competitor.
|
* Returns all contained {@link SensorFixTrack SensorFixTracks} for the given trackName and associated to any
|
||||||
|
* competitor.
|
||||||
*/
|
*/
|
||||||
<FixT extends SensorFix, TrackT extends SensorFixTrack<Competitor, FixT>> Iterable<TrackT> getSensorTracks(String trackName);
|
<FixT extends SensorFix, TrackT extends SensorFixTrack<Competitor, FixT>> Iterable<TrackT> getSensorTracks(
|
||||||
|
String trackName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells the leg on which the <code>competitor</code> was at time <code>at</code>. If the competitor hasn't passed
|
* Tells the leg on which the <code>competitor</code> was at time <code>at</code>. If the competitor hasn't passed
|
||||||
@@ -329,7 +334,7 @@ public interface TrackedRace
|
|||||||
* @see #getTrack(Mark)
|
* @see #getTrack(Mark)
|
||||||
*/
|
*/
|
||||||
GPSFixTrack<Mark, GPSFix> getOrCreateTrack(Mark mark);
|
GPSFixTrack<Mark, GPSFix> getOrCreateTrack(Mark mark);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Yields the track describing <code>mark</code>'s movement over time; <code>null</code> if no track exists for
|
* Yields the track describing <code>mark</code>'s movement over time; <code>null</code> if no track exists for
|
||||||
* <code>mark</code> so far.
|
* <code>mark</code> so far.
|
||||||
@@ -357,7 +362,7 @@ public interface TrackedRace
|
|||||||
default Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint) {
|
default Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint) {
|
||||||
return getApproximatePosition(waypoint, timePoint, new NonCachingMarkPositionAtTimePointCache(this, timePoint));
|
return getApproximatePosition(waypoint, timePoint, new NonCachingMarkPositionAtTimePointCache(this, timePoint));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link #getApproximatePosition(Waypoint, TimePoint)}, but giving the caller the possibility to pass a
|
* Same as {@link #getApproximatePosition(Waypoint, TimePoint)}, but giving the caller the possibility to pass a
|
||||||
* cache of mark positions and related information that can help speed up compound operations requiring frequent
|
* cache of mark positions and related information that can help speed up compound operations requiring frequent
|
||||||
@@ -411,18 +416,19 @@ public interface TrackedRace
|
|||||||
/**
|
/**
|
||||||
* Retrieves the wind sources used so far by this race that have the specified <code>type</code> as their
|
* Retrieves the wind sources used so far by this race that have the specified <code>type</code> as their
|
||||||
* {@link WindSource#getType() type}. Always returns a non-<code>null</code> iterable which may be empty in case the
|
* {@link WindSource#getType() type}. Always returns a non-<code>null</code> iterable which may be empty in case the
|
||||||
* race does not use any wind source of the specified type (yet).<p>
|
* race does not use any wind source of the specified type (yet).
|
||||||
|
* <p>
|
||||||
*
|
*
|
||||||
* It is possible to ask for the {@link WindSourceType#COMBINED} and {@link WindSourceType#LEG_MIDDLE} types and
|
* It is possible to ask for the {@link WindSourceType#COMBINED} and {@link WindSourceType#LEG_MIDDLE} types and get
|
||||||
* get a non-empty result although those sources are never returned by {@link #getWindSources()}.
|
* a non-empty result although those sources are never returned by {@link #getWindSources()}.
|
||||||
*/
|
*/
|
||||||
Set<WindSource> getWindSources(WindSourceType type);
|
Set<WindSource> getWindSources(WindSourceType type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves all wind sources known to this race, including those {@link #getWindSourcesToExclude() to exclude}.
|
* Retrieves all wind sources known to this race, including those {@link #getWindSourcesToExclude() to exclude}.
|
||||||
* Callers can freely iterate because the set returned is weakly-consistent and never throws a {@link ConcurrentModificationException}
|
* Callers can freely iterate because the set returned is weakly-consistent and never throws a
|
||||||
* upon iteration. The {@link WindSourceType#COMBINED} wind source
|
* {@link ConcurrentModificationException} upon iteration. The {@link WindSourceType#COMBINED} wind source as well
|
||||||
* as well as the {@link WindSourceType#LEG_MIDDLE} sources are never part of the result.
|
* as the {@link WindSourceType#LEG_MIDDLE} sources are never part of the result.
|
||||||
*/
|
*/
|
||||||
Set<WindSource> getWindSources();
|
Set<WindSource> getWindSources();
|
||||||
|
|
||||||
@@ -475,7 +481,7 @@ public interface TrackedRace
|
|||||||
* lock.
|
* lock.
|
||||||
*/
|
*/
|
||||||
NavigableSet<MarkPassing> getMarkPassings(Competitor competitor);
|
NavigableSet<MarkPassing> getMarkPassings(Competitor competitor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns competitor's mark passings.
|
* Returns competitor's mark passings.
|
||||||
*
|
*
|
||||||
@@ -490,18 +496,20 @@ public interface TrackedRace
|
|||||||
/**
|
/**
|
||||||
* This obtains the course's read lock before asking for the read lock for the <code>markPassings</code> structure.
|
* This obtains the course's read lock before asking for the read lock for the <code>markPassings</code> structure.
|
||||||
* See also bug 1370 (http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=1370). This is necessary because the
|
* See also bug 1370 (http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=1370). This is necessary because the
|
||||||
* code that executes a course update will first ask the course's write lock and then relay execution to the
|
* code that executes a course update will first ask the course's write lock and then relay execution to the course
|
||||||
* course change listeners among which there is a {@link TrackedRace} which will then update the mark passings
|
* change listeners among which there is a {@link TrackedRace} which will then update the mark passings for all
|
||||||
* for all competitors and therefore will need to ask the write lock for those. If the thread calling this method
|
* competitors and therefore will need to ask the write lock for those. If the thread calling this method first
|
||||||
* first obtains the mark passings read lock and later, while holding on to that lock, asks for the course's read
|
* obtains the mark passings read lock and later, while holding on to that lock, asks for the course's read lock, a
|
||||||
* lock, a deadlock may result.<p>
|
* deadlock may result.
|
||||||
|
* <p>
|
||||||
*
|
*
|
||||||
* Furthermore, when trying to acquire both, a lock for the {@link #getMarkPassings(Competitor) mark passings for a competitor}
|
* Furthermore, when trying to acquire both, a lock for the {@link #getMarkPassings(Competitor) mark passings for a
|
||||||
* and a lock for the {@link #getMarkPassingsInOrder(Waypoint) mark passings for a waypoint, this needs to happen in exactly
|
* competitor} and a lock for the {@link #getMarkPassingsInOrder(Waypoint) mark passings for a waypoint, this needs
|
||||||
* this order, or a deadlock may result.<p>
|
* to happen in exactly this order, or a deadlock may result.
|
||||||
|
* <p>
|
||||||
*
|
*
|
||||||
* The {@link #unlockAfterRead(Iterable)} method will symmetrically unlock the course's read lock after releasing the
|
* The {@link #unlockAfterRead(Iterable)} method will symmetrically unlock the course's read lock after releasing
|
||||||
* read lock for the mark passings.
|
* the read lock for the mark passings.
|
||||||
*/
|
*/
|
||||||
void lockForRead(Iterable<MarkPassing> markPassings);
|
void lockForRead(Iterable<MarkPassing> markPassings);
|
||||||
|
|
||||||
@@ -559,7 +567,7 @@ public interface TrackedRace
|
|||||||
* {@link WindSource#TRACK_BASED_ESTIMATION} source is used, also the monitors of the competitors' GPS tracks.
|
* {@link WindSource#TRACK_BASED_ESTIMATION} source is used, also the monitors of the competitors' GPS tracks.
|
||||||
*/
|
*/
|
||||||
Tack getTack(Competitor competitor, TimePoint timePoint) throws NoWindException;
|
Tack getTack(Competitor competitor, TimePoint timePoint) throws NoWindException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Based on the wind direction at <code>timePoint</code> and at position <code>where</code>, compares the
|
* Based on the wind direction at <code>timePoint</code> and at position <code>where</code>, compares the
|
||||||
* <code>boatBearing</code> to the wind's bearing at that time and place and determined the tack.
|
* <code>boatBearing</code> to the wind's bearing at that time and place and determined the tack.
|
||||||
@@ -585,8 +593,8 @@ public interface TrackedRace
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes a default wind direction based on the direction of the first leg at time <code>at</code>, with a default
|
* Computes a default wind direction based on the direction of the first leg at time <code>at</code>, with a default
|
||||||
* speed of zero knots. Note that this wind direction can only be used if {@link #raceIsKnownToStartUpwind()} returns
|
* speed of zero knots. Note that this wind direction can only be used if {@link #raceIsKnownToStartUpwind()}
|
||||||
* <code>true</code>.
|
* returns <code>true</code>.
|
||||||
*
|
*
|
||||||
* @param at
|
* @param at
|
||||||
* usually the {@link #getStart() start time} should be used; if no valid start time is provided, the
|
* usually the {@link #getStart() start time} should be used; if no valid start time is provided, the
|
||||||
@@ -618,7 +626,7 @@ public interface TrackedRace
|
|||||||
* for the <code>key</code> is still ongoing, the result of that ongoing re-calculation is returned.
|
* for the <code>key</code> is still ongoing, the result of that ongoing re-calculation is returned.
|
||||||
*/
|
*/
|
||||||
Iterable<Maneuver> getManeuvers(Competitor competitor, TimePoint from, TimePoint to, boolean waitForLatest);
|
Iterable<Maneuver> getManeuvers(Competitor competitor, TimePoint from, TimePoint to, boolean waitForLatest);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a non-<code>null</code> but perhaps empty list of the maneuvers that <code>competitor</code> performed in
|
* @return a non-<code>null</code> but perhaps empty list of the maneuvers that <code>competitor</code> performed in
|
||||||
* this race. Depending on <code>waitForLatest</code> the result is taken from the cache straight away
|
* this race. Depending on <code>waitForLatest</code> the result is taken from the cache straight away
|
||||||
@@ -659,7 +667,8 @@ public interface TrackedRace
|
|||||||
* tracked race. This runs synchronized with the otherwise asynchronous loading of wind tracks, triggered by the
|
* tracked race. This runs synchronized with the otherwise asynchronous loading of wind tracks, triggered by the
|
||||||
* constructor of the {@link TrackedRace} implementation classes. This procedure guarantees that eventually the
|
* constructor of the {@link TrackedRace} implementation classes. This procedure guarantees that eventually the
|
||||||
* listener will have received a notification for all wind fixes, regardless of whether they were already loaded at
|
* listener will have received a notification for all wind fixes, regardless of whether they were already loaded at
|
||||||
* the time the listener is registered or they are loaded after the registration has completed.<p>
|
* the time the listener is registered or they are loaded after the registration has completed.
|
||||||
|
* <p>
|
||||||
*
|
*
|
||||||
* The same is true for the GPS fixes for marks and competitors.
|
* The same is true for the GPS fixes for marks and competitors.
|
||||||
*/
|
*/
|
||||||
@@ -667,10 +676,10 @@ public interface TrackedRace
|
|||||||
boolean notifyAboutGPSFixesAlreadyLoaded);
|
boolean notifyAboutGPSFixesAlreadyLoaded);
|
||||||
|
|
||||||
void removeListener(RaceChangeListener listener);
|
void removeListener(RaceChangeListener listener);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return <code>null</code> if there are no mark passings for the <code>competitor</code> in this race
|
* @return <code>null</code> if there are no mark passings for the <code>competitor</code> in this race or if the
|
||||||
* or if the competitor has not finished one of the legs in the race.
|
* competitor has not finished one of the legs in the race.
|
||||||
*/
|
*/
|
||||||
Distance getDistanceTraveled(Competitor competitor, TimePoint timePoint);
|
Distance getDistanceTraveled(Competitor competitor, TimePoint timePoint);
|
||||||
|
|
||||||
@@ -680,32 +689,35 @@ public interface TrackedRace
|
|||||||
Distance getDistanceTraveledIncludingGateStart(Competitor competitor, TimePoint timePoint);
|
Distance getDistanceTraveledIncludingGateStart(Competitor competitor, TimePoint timePoint);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return <code>null</code> if there are no mark passings for the <code>competitor</code> in this race
|
* @return <code>null</code> if there are no mark passings for the <code>competitor</code> in this race or if the
|
||||||
* or if the competitor has not finished one of the legs in the race.
|
* competitor has not finished one of the legs in the race.
|
||||||
*/
|
*/
|
||||||
Distance getDistanceFoiled(Competitor competitor, TimePoint timePoint);
|
Distance getDistanceFoiled(Competitor competitor, TimePoint timePoint);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return <code>null</code> if there are no mark passings for the <code>competitor</code> in this race
|
* @return <code>null</code> if there are no mark passings for the <code>competitor</code> in this race or if the
|
||||||
* or if the competitor has not finished one of the legs in the race.
|
* competitor has not finished one of the legs in the race.
|
||||||
*/
|
*/
|
||||||
Duration getDurationFoiled(Competitor competitor, TimePoint timePoint);
|
Duration getDurationFoiled(Competitor competitor, TimePoint timePoint);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See {@link TrackedLegOfCompetitor#getWindwardDistanceToCompetitorFarthestAhead(TimePoint, WindPositionMode, RankingInfo)}
|
* See
|
||||||
|
* {@link TrackedLegOfCompetitor#getWindwardDistanceToCompetitorFarthestAhead(TimePoint, WindPositionMode, RankingInfo)}
|
||||||
*/
|
*/
|
||||||
Distance getWindwardDistanceToCompetitorFarthestAhead(Competitor competitor, TimePoint timePoint, WindPositionMode windPositionMode);
|
Distance getWindwardDistanceToCompetitorFarthestAhead(Competitor competitor, TimePoint timePoint,
|
||||||
|
WindPositionMode windPositionMode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link #getWindwardDistanceToCompetitorFarthestAhead(Competitor, TimePoint, WindPositionMode)}, only with an
|
* Same as {@link #getWindwardDistanceToCompetitorFarthestAhead(Competitor, TimePoint, WindPositionMode)}, only with
|
||||||
* additional cache to speed up wind and leg type and leg bearing calculations in case of multiple similar look-ups
|
* an additional cache to speed up wind and leg type and leg bearing calculations in case of multiple similar
|
||||||
* for the same time point.
|
* look-ups for the same time point.
|
||||||
*
|
*
|
||||||
* @param rankingInfo
|
* @param rankingInfo
|
||||||
* materialized ranking information that is expensive to calculate, avoiding redundant calculations
|
* materialized ranking information that is expensive to calculate, avoiding redundant calculations
|
||||||
*/
|
*/
|
||||||
Distance getWindwardDistanceToCompetitorFarthestAhead(Competitor competitor, TimePoint timePoint,
|
Distance getWindwardDistanceToCompetitorFarthestAhead(Competitor competitor, TimePoint timePoint,
|
||||||
WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache);
|
WindPositionMode windPositionMode, RankingInfo rankingInfo,
|
||||||
|
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls {@link #getWindWithConfidence(Position, TimePoint, Iterable)} and excludes those wind sources listed in
|
* Calls {@link #getWindWithConfidence(Position, TimePoint, Iterable)} and excludes those wind sources listed in
|
||||||
@@ -729,8 +741,8 @@ public interface TrackedRace
|
|||||||
Set<WindSource> windSourcesToExclude);
|
Set<WindSource> windSourcesToExclude);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link #getEstimatedWindDirection(TimePoint)}, but propagates the confidence of the wind
|
* Same as {@link #getEstimatedWindDirection(TimePoint)}, but propagates the confidence of the wind estimation,
|
||||||
* estimation, relative to the <code>timePoint</code> for which the request is made, in the result. The
|
* relative to the <code>timePoint</code> for which the request is made, in the result. The
|
||||||
* {@link Wind#getPosition() position} of all {@link Wind} fixes returned is <code>null</code>.
|
* {@link Wind#getPosition() position} of all {@link Wind} fixes returned is <code>null</code>.
|
||||||
*/
|
*/
|
||||||
WindWithConfidence<TimePoint> getEstimatedWindDirectionWithConfidence(TimePoint timePoint);
|
WindWithConfidence<TimePoint> getEstimatedWindDirectionWithConfidence(TimePoint timePoint);
|
||||||
@@ -748,16 +760,18 @@ public interface TrackedRace
|
|||||||
* if <code>true</code> and any cache update is currently going on, wait for the update to complete and
|
* if <code>true</code> and any cache update is currently going on, wait for the update to complete and
|
||||||
* then fetch the updated value; otherwise, serve this requests from whatever is currently in the cache
|
* then fetch the updated value; otherwise, serve this requests from whatever is currently in the cache
|
||||||
*/
|
*/
|
||||||
Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalysis);
|
Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint timePoint,
|
||||||
|
boolean waitForLatestAnalysis);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link #getAverageAbsoluteCrossTrackError(Competitor, TimePoint, boolean)}, only that a cache for leg type,
|
* Same as {@link #getAverageAbsoluteCrossTrackError(Competitor, TimePoint, boolean)}, only that a cache for leg
|
||||||
* wind on leg and leg bearing is provided.
|
* type, wind on leg and leg bearing is provided.
|
||||||
*/
|
*/
|
||||||
Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalyses,
|
Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint timePoint,
|
||||||
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache);
|
boolean waitForLatestAnalyses, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache);
|
||||||
|
|
||||||
Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint from, TimePoint to, boolean upwindOnly, boolean waitForLatestAnalyses);
|
Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint from, TimePoint to, boolean upwindOnly,
|
||||||
|
boolean waitForLatestAnalyses);
|
||||||
|
|
||||||
Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalysis);
|
Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalysis);
|
||||||
|
|
||||||
@@ -776,13 +790,13 @@ public interface TrackedRace
|
|||||||
WindStore getWindStore();
|
WindStore getWindStore();
|
||||||
|
|
||||||
Competitor getOverallLeader(TimePoint timePoint);
|
Competitor getOverallLeader(TimePoint timePoint);
|
||||||
|
|
||||||
Competitor getOverallLeader(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache);
|
Competitor getOverallLeader(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache);
|
||||||
|
|
||||||
Boat getBoatOfCompetitor(Competitor competitor);
|
Boat getBoatOfCompetitor(Competitor competitor);
|
||||||
|
|
||||||
Competitor getCompetitorOfBoat(Boat boat);
|
Competitor getCompetitorOfBoat(Boat boat);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the competitors of this tracked race, according to their ranking. Competitors whose
|
* Returns the competitors of this tracked race, according to their ranking. Competitors whose
|
||||||
* {@link #getRank(Competitor)} is 0 will be sorted "worst".
|
* {@link #getRank(Competitor)} is 0 will be sorted "worst".
|
||||||
@@ -790,34 +804,34 @@ public interface TrackedRace
|
|||||||
List<Competitor> getCompetitorsFromBestToWorst(TimePoint timePoint);
|
List<Competitor> getCompetitorsFromBestToWorst(TimePoint timePoint);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link #getCompetitorsFromBestToWorst(TimePoint)}, using a cache for wind, leg type and leg
|
* Same as {@link #getCompetitorsFromBestToWorst(TimePoint)}, using a cache for wind, leg type and leg bearing
|
||||||
* bearing values.
|
* values.
|
||||||
*/
|
*/
|
||||||
List<Competitor> getCompetitorsFromBestToWorst(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache);
|
List<Competitor> getCompetitorsFromBestToWorst(TimePoint timePoint,
|
||||||
|
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When provided with a {@link WindStore} during construction, the tracked race will
|
* When provided with a {@link WindStore} during construction, the tracked race will asynchronously load the wind
|
||||||
* asynchronously load the wind data for this tracked race from the wind store and the GPS store in a
|
* data for this tracked race from the wind store and the GPS store in a background thread and update this tracked
|
||||||
* background thread and update this tracked race with the results. Clients that want to wait for the wind
|
* race with the results. Clients that want to wait for the wind loading process to complete can do so by calling
|
||||||
* loading process to complete can do so by calling this method which will block until the wind loading has
|
* this method which will block until the wind loading has completed.
|
||||||
* completed.
|
|
||||||
*/
|
*/
|
||||||
void waitUntilLoadingFromWindStoreComplete() throws InterruptedException;
|
void waitUntilLoadingFromWindStoreComplete() throws InterruptedException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whenever a {@link RegattaLog} is attached, fixes are loaded from the {@link SensorFixStore} for all mappings
|
* Whenever a {@link RegattaLog} is attached, fixes are loaded from the {@link SensorFixStore} for all mappings
|
||||||
* found in the {@code RegattaLog} in a separate thread. This method blocks if there is such a thread loading
|
* found in the {@code RegattaLog} in a separate thread. This method blocks if there is such a thread loading fixes,
|
||||||
* fixes, until that thread is finished.
|
* until that thread is finished.
|
||||||
*/
|
*/
|
||||||
void waitForLoadingToFinish() throws InterruptedException;
|
void waitForLoadingToFinish() throws InterruptedException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current status of the {@link TrackedRace}. This consists of one of the {@link TrackedRaceStatusEnum}
|
* Returns the current status of the {@link TrackedRace}. This consists of one of the {@link TrackedRaceStatusEnum}
|
||||||
* values plus a progress for LOADING state.<br>
|
* values plus a progress for LOADING state.<br>
|
||||||
* Due to the fact that multiple loaders can exist that load data into the {@link TrackedRace}, the returned status
|
* Due to the fact that multiple loaders can exist that load data into the {@link TrackedRace}, the returned status
|
||||||
* is a composite of those loader statuses. When a loader is finished, its status isn't tracked anymore. This causes
|
* is a composite of those loader statuses. When a loader is finished, its status isn't tracked anymore. This causes
|
||||||
* the overall progress to not be guaranteed to be monotonic (progress may jump to a lower percentage when one loader
|
* the overall progress to not be guaranteed to be monotonic (progress may jump to a lower percentage when one
|
||||||
* that had a progress of 100% is finished and thus removed).
|
* loader that had a progress of 100% is finished and thus removed).
|
||||||
*
|
*
|
||||||
* @see TrackedRaceStatus
|
* @see TrackedRaceStatus
|
||||||
* @see DynamicTrackedRace#onStatusChanged(TrackingDataLoader, TrackedRaceStatus)
|
* @see DynamicTrackedRace#onStatusChanged(TrackingDataLoader, TrackedRaceStatus)
|
||||||
@@ -825,8 +839,8 @@ public interface TrackedRace
|
|||||||
TrackedRaceStatus getStatus();
|
TrackedRaceStatus getStatus();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the {@link #getStatus() status} is currently {@link TrackedRaceStatusEnum#LOADING}, blocks until the status changes to any
|
* If the {@link #getStatus() status} is currently {@link TrackedRaceStatusEnum#LOADING}, blocks until the status
|
||||||
* other status.
|
* changes to any other status.
|
||||||
*/
|
*/
|
||||||
void waitUntilNotLoading();
|
void waitUntilNotLoading();
|
||||||
|
|
||||||
@@ -836,64 +850,64 @@ public interface TrackedRace
|
|||||||
* @return the race log detached or {@code null} if no race log can be found by the {@code identifier}
|
* @return the race log detached or {@code null} if no race log can be found by the {@code identifier}
|
||||||
*/
|
*/
|
||||||
RaceLog detachRaceLog(Serializable identifier);
|
RaceLog detachRaceLog(Serializable identifier);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detaches the link {@link RaceExecutionOrderProvider}
|
* Detaches the link {@link RaceExecutionOrderProvider}
|
||||||
*/
|
*/
|
||||||
void detachRaceExecutionOrderProvider(RaceExecutionOrderProvider raceExecutionOrderProvider);
|
void detachRaceExecutionOrderProvider(RaceExecutionOrderProvider raceExecutionOrderProvider);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches the passed race log with this {@link TrackedRace}.
|
* Attaches the passed race log with this {@link TrackedRace}. This causes fixes from the {@link SensorFixStore} to
|
||||||
* This causes fixes from the {@link SensorFixStore} to be loaded for such {@link RegattaLogDeviceMappingEvent RegattaLogDeviceMappingEvents}
|
* be loaded for such {@link RegattaLogDeviceMappingEvent RegattaLogDeviceMappingEvents} that are present in the
|
||||||
* that are present in the {@link RaceLog raceLog}. This loading is offloaded into a separate thread, that blocks
|
* {@link RaceLog raceLog}. This loading is offloaded into a separate thread, that blocks serialization until it is
|
||||||
* serialization until it is finished. If multiple race logs are attached, the loading process is
|
* finished. If multiple race logs are attached, the loading process is forced to be serialized. To guarantee that a
|
||||||
* forced to be serialized.
|
* the fixes for a race log have been fully loaded before continuing, {@link #waitForLoadingToFinish()} can be used.
|
||||||
* To guarantee that a the fixes for a race log have been fully loaded before continuing,
|
*
|
||||||
* {@link #waitForLoadingToFinish()} can be used.
|
* @param raceLog
|
||||||
* @param raceLog to be attached.
|
* to be attached.
|
||||||
*/
|
*/
|
||||||
void attachRaceLog(RaceLog raceLog);
|
void attachRaceLog(RaceLog raceLog);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches the passed {@link RegattaLog} with this {@link TrackedRace}.
|
* Attaches the passed {@link RegattaLog} with this {@link TrackedRace}. This also causes fixes from the
|
||||||
* This also causes fixes from the {@link SensorFixStore} to be loaded (see {@link #attachRaceLog(RaceLog)} for details).
|
* {@link SensorFixStore} to be loaded (see {@link #attachRaceLog(RaceLog)} for details).
|
||||||
*/
|
*/
|
||||||
void attachRegattaLog(RegattaLog regattaLog);
|
void attachRegattaLog(RegattaLog regattaLog);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return all currently attached {@link RegattaLog}s or an empty Iterable if there aren't any
|
* @return all currently attached {@link RegattaLog}s or an empty Iterable if there aren't any
|
||||||
*/
|
*/
|
||||||
Iterable<RegattaLog> getAttachedRegattaLogs();
|
Iterable<RegattaLog> getAttachedRegattaLogs();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches a {@link RaceExecutionOrderProvider} to make a {@link TrackedRace} aware
|
* Attaches a {@link RaceExecutionOrderProvider} to make a {@link TrackedRace} aware which races are scheduled
|
||||||
* which races are scheduled around it in the execution order of a {@link Regatta}.
|
* around it in the execution order of a {@link Regatta}.
|
||||||
* */
|
*/
|
||||||
void attachRaceExecutionProvider(RaceExecutionOrderProvider raceExecutionOrderProvider);
|
void attachRaceExecutionProvider(RaceExecutionOrderProvider raceExecutionOrderProvider);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the attached race log event track for this race if any.
|
* Returns the attached race log event track for this race if any. Otherwise <code>null</code>.
|
||||||
* Otherwise <code>null</code>.
|
|
||||||
*/
|
*/
|
||||||
RaceLog getRaceLog(Serializable identifier);
|
RaceLog getRaceLog(Serializable identifier);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A setter for the listener on course design changes suggested by one of the {@link RaceLog RaceLog} attached to this
|
* A setter for the listener on course design changes suggested by one of the {@link RaceLog RaceLog} attached to
|
||||||
* race. The listener is mostly part of the tracking provider adapter.
|
* this race. The listener is mostly part of the tracking provider adapter.
|
||||||
*
|
*
|
||||||
* @param listener
|
* @param listener
|
||||||
* the listener to operate with.
|
* the listener to operate with.
|
||||||
*/
|
*/
|
||||||
void addCourseDesignChangedListener(CourseDesignChangedListener listener);
|
void addCourseDesignChangedListener(CourseDesignChangedListener listener);
|
||||||
|
|
||||||
void addStartTimeChangedListener(StartTimeChangedListener listener);
|
void addStartTimeChangedListener(StartTimeChangedListener listener);
|
||||||
|
|
||||||
void removeStartTimeChangedListener(StartTimeChangedListener listener);
|
void removeStartTimeChangedListener(StartTimeChangedListener listener);
|
||||||
|
|
||||||
void addRaceAbortedListener(RaceAbortedListener listener);
|
void addRaceAbortedListener(RaceAbortedListener listener);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells how far the given <code>competitor</code> was from the start line at the time point of the given seconds before the start.
|
* Tells how far the given <code>competitor</code> was from the start line at the time point of the given seconds
|
||||||
|
* before the start.
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* The distance to the line is calculated by projecting the competitor's position onto the line orthogonally and
|
* The distance to the line is calculated by projecting the competitor's position onto the line orthogonally and
|
||||||
@@ -938,8 +952,9 @@ public interface TrackedRace
|
|||||||
* Like {@link #getWindwardDistanceToFavoredSideOfStartLine(Competitor, long)}, but with a cache to accelerate
|
* Like {@link #getWindwardDistanceToFavoredSideOfStartLine(Competitor, long)}, but with a cache to accelerate
|
||||||
* repetitive requests for wind and leg types.
|
* repetitive requests for wind and leg types.
|
||||||
*/
|
*/
|
||||||
Distance getWindwardDistanceToFavoredSideOfStartLine(Competitor competitor, long millisecondsBeforeRaceStart, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache);
|
Distance getWindwardDistanceToFavoredSideOfStartLine(Competitor competitor, long millisecondsBeforeRaceStart,
|
||||||
|
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells how far, projected onto the wind for upwind/downwind and projected onto the course middle line for reaching
|
* Tells how far, projected onto the wind for upwind/downwind and projected onto the course middle line for reaching
|
||||||
* starts, the given <code>competitor</code> was from the favored end of the start line at the given
|
* starts, the given <code>competitor</code> was from the favored end of the start line at the given
|
||||||
@@ -952,7 +967,8 @@ public interface TrackedRace
|
|||||||
* returned. If the competitor's position cannot be determined, <code>null</code> is returned.
|
* returned. If the competitor's position cannot be determined, <code>null</code> is returned.
|
||||||
*/
|
*/
|
||||||
default Distance getWindwardDistanceToFavoredSideOfStartLine(Competitor competitor, TimePoint timePoint) {
|
default Distance getWindwardDistanceToFavoredSideOfStartLine(Competitor competitor, TimePoint timePoint) {
|
||||||
return getWindwardDistanceToFavoredSideOfStartLine(competitor, timePoint, new LeaderboardDTOCalculationReuseCache(timePoint));
|
return getWindwardDistanceToFavoredSideOfStartLine(competitor, timePoint,
|
||||||
|
new LeaderboardDTOCalculationReuseCache(timePoint));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -963,19 +979,19 @@ public interface TrackedRace
|
|||||||
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache);
|
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When the <code>competitor</code> has started, this method returns the distance to the starboard end of the start line
|
* When the <code>competitor</code> has started, this method returns the distance to the starboard end of the start
|
||||||
* or---if the start waypoint was a single mark---the distance to the single start mark at the time the competitor started.
|
* line or---if the start waypoint was a single mark---the distance to the single start mark at the time the
|
||||||
* If the competitor hasn't started yet, <code>null</code> is returned.
|
* competitor started. If the competitor hasn't started yet, <code>null</code> is returned.
|
||||||
*/
|
*/
|
||||||
Distance getDistanceFromStarboardSideOfStartLineWhenPassingStart(Competitor competitor);
|
Distance getDistanceFromStarboardSideOfStartLineWhenPassingStart(Competitor competitor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* At the given timepoint and for the competitor, this method returns the distance to the starboard end of the start line
|
* At the given timepoint and for the competitor, this method returns the distance to the starboard end of the start
|
||||||
* or---if the start waypoint was a single mark---the distance to the single start mark at the timepoint.
|
* line or---if the start waypoint was a single mark---the distance to the single start mark at the timepoint. If
|
||||||
* If the competitor hasn't started yet, <code>null</code> is returned.
|
* the competitor hasn't started yet, <code>null</code> is returned.
|
||||||
*/
|
*/
|
||||||
Distance getDistanceFromStarboardSideOfStartLine(Competitor competitor, TimePoint timePoint);
|
Distance getDistanceFromStarboardSideOfStartLine(Competitor competitor, TimePoint timePoint);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* At the given timepoint and for the competitor, this method returns the distance between the starboard end of the
|
* At the given timepoint and for the competitor, this method returns the distance between the starboard end of the
|
||||||
* start line and the competitor position projected perpendicularly onto the line. If the start waypoint was a
|
* start line and the competitor position projected perpendicularly onto the line. If the start waypoint was a
|
||||||
@@ -984,7 +1000,7 @@ public interface TrackedRace
|
|||||||
* hasn't started yet, <code>null</code> is returned.
|
* hasn't started yet, <code>null</code> is returned.
|
||||||
*/
|
*/
|
||||||
Distance getDistanceFromStarboardSideOfStartLineProjectedOntoLine(Competitor competitor, TimePoint timePoint);
|
Distance getDistanceFromStarboardSideOfStartLineProjectedOntoLine(Competitor competitor, TimePoint timePoint);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For all competitors in this race computes their
|
* For all competitors in this race computes their
|
||||||
* {@link #getDistanceFromStarboardSideOfStartLineProjectedOntoLine(Competitor, TimePoint)} and puts the results in
|
* {@link #getDistanceFromStarboardSideOfStartLineProjectedOntoLine(Competitor, TimePoint)} and puts the results in
|
||||||
@@ -992,50 +1008,62 @@ public interface TrackedRace
|
|||||||
* finding adjacent records, using {@link SortedMap#headMap(Object)} and {@link SortedMap#tailMap(Object)}.
|
* finding adjacent records, using {@link SortedMap#headMap(Object)} and {@link SortedMap#tailMap(Object)}.
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* Competitors who are part of this race but for which no such {@link Distance} can be calculated, a record is
|
* Competitors who are part of this race but for which no such {@link Distance} can be calculated, a record is put
|
||||||
* put to the resulting map with a {@code null} value associated. Those entries are sorted to the end of the map,
|
* to the resulting map with a {@code null} value associated. Those entries are sorted to the end of the map,
|
||||||
* meaning that "{@code null} is greater" than other values.</p>
|
* meaning that "{@code null} is greater" than other values.
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* Results are cached in a fixed-size LRU cache which is invalidated by competitor or mark positions within the
|
* Results are cached in a fixed-size LRU cache which is invalidated by competitor or mark positions within the
|
||||||
* averaging time range of {@code timePoint}. With this, repeated requests for equal {@code timePoint}s have a good
|
* averaging time range of {@code timePoint}. With this, repeated requests for equal {@code timePoint}s have a good
|
||||||
* chance of being fulfilled from a previous computation result.<p>
|
* chance of being fulfilled from a previous computation result.
|
||||||
|
* <p>
|
||||||
*
|
*
|
||||||
* Boats are not considered in this if they are {@link MaxPointsReason#DNC DNC} or {@link MaxPointsReason#DNC DNS}
|
* Boats are not considered in this if they are {@link MaxPointsReason#DNC DNC} or {@link MaxPointsReason#DNC DNS}
|
||||||
* which both suggest the boat may not have made a serious attempt to start.
|
* which both suggest the boat may not have made a serious attempt to start.
|
||||||
*/
|
*/
|
||||||
SortedMap<Competitor, Distance> getDistancesFromStarboardSideOfStartLineProjectedOntoLine(TimePoint timePoint,
|
SortedMap<Competitor, Distance> getDistancesFromStarboardSideOfStartLineProjectedOntoLine(TimePoint timePoint,
|
||||||
BiFunction<Competitor, TimePoint, MaxPointsReason> maxPointsReasonSupplier);
|
BiFunction<Competitor, TimePoint, MaxPointsReason> maxPointsReasonSupplier);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Based on the result of {@link #getDistancesFromStarboardSideOfStartLineProjectedOntoLine(TimePoint, Function<Triple<Competitor, RaceColumn, TimePoint>, MaxPointsReason>)}, finds the
|
* Based on the result of {@link #getDistancesFromStarboardSideOfStartLineProjectedOntoLine(TimePoint,
|
||||||
* next competitor to port regarding their start line projection at {@code timePoint}. Returns {@code null} if
|
* Function<Triple<Competitor, RaceColumn, TimePoint>, MaxPointsReason>)}, finds the next competitor to port
|
||||||
* the start line cannot be determined or if there is no competitor further to port.<p>
|
* regarding their start line projection at {@code timePoint}. Returns {@code null} if the start line cannot be
|
||||||
|
* determined or if there is no competitor further to port.
|
||||||
|
* <p>
|
||||||
*
|
*
|
||||||
* Boats are not considered in this if they are {@link MaxPointsReason#DNC DNC} or {@link MaxPointsReason#DNC DNS}
|
* Boats are not considered in this if they are {@link MaxPointsReason#DNC DNC} or {@link MaxPointsReason#DNC DNS}
|
||||||
* which both suggest the boat may not have made a serious attempt to start.
|
* which both suggest the boat may not have made a serious attempt to start.
|
||||||
* @param maxPointsReasonSupplier TODO
|
*
|
||||||
|
* @param maxPointsReasonSupplier
|
||||||
|
* TODO
|
||||||
*/
|
*/
|
||||||
Competitor getNextCompetitorToPortOnStartLine(Competitor relativeTo, TimePoint timePoint, BiFunction<Competitor, TimePoint, MaxPointsReason> maxPointsReasonSupplier);
|
Competitor getNextCompetitorToPortOnStartLine(Competitor relativeTo, TimePoint timePoint,
|
||||||
|
BiFunction<Competitor, TimePoint, MaxPointsReason> maxPointsReasonSupplier);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Based on the result of {@link #getDistancesFromStarboardSideOfStartLineProjectedOntoLine(TimePoint, Function<Triple<Competitor, RaceColumn, TimePoint>, MaxPointsReason>)}, finds the
|
* Based on the result of {@link #getDistancesFromStarboardSideOfStartLineProjectedOntoLine(TimePoint,
|
||||||
* next competitor to starboard regarding their start line projection at {@code timePoint}. Returns {@code null} if
|
* Function<Triple<Competitor, RaceColumn, TimePoint>, MaxPointsReason>)}, finds the next competitor to starboard
|
||||||
* the start line cannot be determined or if there is no competitor further to starboard.<p>
|
* regarding their start line projection at {@code timePoint}. Returns {@code null} if the start line cannot be
|
||||||
|
* determined or if there is no competitor further to starboard.
|
||||||
|
* <p>
|
||||||
*
|
*
|
||||||
* Boats are not considered in this if they are {@link MaxPointsReason#DNC DNC} or {@link MaxPointsReason#DNC DNS}
|
* Boats are not considered in this if they are {@link MaxPointsReason#DNC DNC} or {@link MaxPointsReason#DNC DNS}
|
||||||
* which both suggest the boat may not have made a serious attempt to start.
|
* which both suggest the boat may not have made a serious attempt to start.
|
||||||
* @param maxPointsReasonSupplier TODO
|
*
|
||||||
|
* @param maxPointsReasonSupplier
|
||||||
|
* TODO
|
||||||
*/
|
*/
|
||||||
Competitor getNextCompetitorToStarboardOnStartLine(Competitor relativeTo, TimePoint timePoint, BiFunction<Competitor, TimePoint, MaxPointsReason> maxPointsReasonSupplier);
|
Competitor getNextCompetitorToStarboardOnStartLine(Competitor relativeTo, TimePoint timePoint,
|
||||||
|
BiFunction<Competitor, TimePoint, MaxPointsReason> maxPointsReasonSupplier);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The estimated speed of the competitor at the time point of the given seconds before the start of race.
|
* The estimated speed of the competitor at the time point of the given seconds before the start of race.
|
||||||
*/
|
*/
|
||||||
Speed getSpeed(Competitor competitor, long millisecondsBeforeRaceStart);
|
Speed getSpeed(Competitor competitor, long millisecondsBeforeRaceStart);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The speed of the competitor when crossing the start line. It will return null if there are no recorded
|
* The speed of the competitor when crossing the start line. It will return null if there are no recorded mark
|
||||||
* mark passings for this competitor (competitor did not yet or never pass the start line).
|
* passings for this competitor (competitor did not yet or never pass the start line).
|
||||||
*/
|
*/
|
||||||
Speed getSpeedWhenCrossingStartLine(Competitor competitor);
|
Speed getSpeedWhenCrossingStartLine(Competitor competitor);
|
||||||
|
|
||||||
@@ -1043,56 +1071,58 @@ public interface TrackedRace
|
|||||||
* Start time received by the tracking infrastructure. To determine real start time use {@link #getStartOfRace()}.
|
* Start time received by the tracking infrastructure. To determine real start time use {@link #getStartOfRace()}.
|
||||||
*/
|
*/
|
||||||
TimePoint getStartTimeReceived();
|
TimePoint getStartTimeReceived();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return <code>null</code> if the start waypoint does not have two marks or the course
|
* @return <code>null</code> if the start waypoint does not have two marks or the course is empty or the start
|
||||||
* is empty or the start waypoint is the only waypoint
|
* waypoint is the only waypoint
|
||||||
*/
|
*/
|
||||||
LineDetails getStartLine(TimePoint at);
|
LineDetails getStartLine(TimePoint at);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return <code>null</code> if the finish waypoint does not have two marks or the course
|
* @return <code>null</code> if the finish waypoint does not have two marks or the course is empty or the finish
|
||||||
* is empty or the finish waypoint is the only waypoint
|
* waypoint is the only waypoint
|
||||||
*/
|
*/
|
||||||
LineDetails getFinishLine(TimePoint at);
|
LineDetails getFinishLine(TimePoint at);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Length of course if there are mark passings for competitors.
|
* Length of course if there are mark passings for competitors.
|
||||||
*/
|
*/
|
||||||
Distance getCourseLength();
|
Distance getCourseLength();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The average wind speed with confidence for this race. It uses the timepoint of the {@link #getEndOfRace race end} as
|
* The average wind speed with confidence for this race. It uses the timepoint of the {@link #getEndOfRace race end}
|
||||||
* a reference point, or, if that is {@code null}, the {@link #getTimePointOfNewestEvent()}.
|
* as a reference point, or, if that is {@code null}, the {@link #getTimePointOfNewestEvent()}.
|
||||||
*/
|
*/
|
||||||
SpeedWithConfidence<TimePoint> getAverageWindSpeedWithConfidence(long resolutionInMillis);
|
SpeedWithConfidence<TimePoint> getAverageWindSpeedWithConfidence(long resolutionInMillis);
|
||||||
|
|
||||||
SpeedWithConfidence<TimePoint> getAverageWindSpeedWithConfidenceWithNumberOfSamples(int numberOfSamples);
|
SpeedWithConfidence<TimePoint> getAverageWindSpeedWithConfidenceWithNumberOfSamples(int numberOfSamples);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The average wind speed with confidence for this race.
|
* The average wind speed with confidence for this race.
|
||||||
*/
|
*/
|
||||||
SpeedWithConfidence<TimePoint> getAverageWindSpeedWithConfidence(TimePoint fromTimePoint, TimePoint toTimePoint, int numberOfSamples);
|
SpeedWithConfidence<TimePoint> getAverageWindSpeedWithConfidence(TimePoint fromTimePoint, TimePoint toTimePoint,
|
||||||
|
int numberOfSamples);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the center point of the course's marks at the given time point.
|
* Computes the center point of the course's marks at the given time point.
|
||||||
*/
|
*/
|
||||||
Position getCenterOfCourse(TimePoint at);
|
Position getCenterOfCourse(TimePoint at);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the {@link RacingProcedure} defined by any of the {@link #attachedRaceLogs attached} {@link RaceLog}s
|
* If the {@link RacingProcedure} defined by any of the {@link #attachedRaceLogs attached} {@link RaceLog}s has type
|
||||||
* has type {@link RacingProcedureType#GateStart}, this method returns <code>true</code>, <code>false</code> for
|
* {@link RacingProcedureType#GateStart}, this method returns <code>true</code>, <code>false</code> for any other
|
||||||
* any other type found. If no type is found, e.g., because no race log is currently attached to this tracked race,
|
* type found. If no type is found, e.g., because no race log is currently attached to this tracked race,
|
||||||
* <code>null</code> is returned, meaning that the type is not known.
|
* <code>null</code> is returned, meaning that the type is not known.
|
||||||
*/
|
*/
|
||||||
Boolean isGateStart();
|
Boolean isGateStart();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the time in milliseconds when the line was closed with lowering flag {@link Flags#GOLF} if {@link #isGateStart()} is <code>true</code>.
|
* Returns the time in milliseconds when the line was closed with lowering flag {@link Flags#GOLF} if
|
||||||
* If flag was not raised or {@link #isGateStart()} is <code>false</code> it returns <code>null</code>.
|
* {@link #isGateStart()} is <code>true</code>. If flag was not raised or {@link #isGateStart()} is
|
||||||
|
* <code>false</code> it returns <code>null</code>.
|
||||||
*/
|
*/
|
||||||
long getGateStartGolfDownTime();
|
long getGateStartGolfDownTime();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the race was started with a gate start (see {@link #isGateStart()}, this method returns the distance between
|
* If the race was started with a gate start (see {@link #isGateStart()}, this method returns the distance between
|
||||||
* the competitor's starting position and the port side of the start line (pin end); otherwise, returns a zero
|
* the competitor's starting position and the port side of the start line (pin end); otherwise, returns a zero
|
||||||
@@ -1101,7 +1131,7 @@ public interface TrackedRace
|
|||||||
Distance getAdditionalGateStartDistance(Competitor competitor, TimePoint timePoint);
|
Distance getAdditionalGateStartDistance(Competitor competitor, TimePoint timePoint);
|
||||||
|
|
||||||
boolean isUsingMarkPassingCalculator();
|
boolean isUsingMarkPassingCalculator();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the estimated time it takes a competitor to sail the race, from start to finish.
|
* Calculates the estimated time it takes a competitor to sail the race, from start to finish.
|
||||||
*
|
*
|
||||||
@@ -1109,13 +1139,15 @@ public interface TrackedRace
|
|||||||
* Used for positions of marks and wind information; note that sometimes the marks are not in place yet
|
* Used for positions of marks and wind information; note that sometimes the marks are not in place yet
|
||||||
* when the race starts and that a windward mark may be collected already before the race finishes.
|
* when the race starts and that a windward mark may be collected already before the race finishes.
|
||||||
*
|
*
|
||||||
* @return estimated time it takes to complete the race, plus more useful information about how this result came about
|
* @return estimated time it takes to complete the race, plus more useful information about how this result came
|
||||||
|
* about
|
||||||
*
|
*
|
||||||
* @throws NotEnoughDataHasBeenAddedException
|
* @throws NotEnoughDataHasBeenAddedException
|
||||||
* thrown if not enough polar data has been added or polar data service is not available
|
* thrown if not enough polar data has been added or polar data service is not available
|
||||||
* @throws NoWindException
|
* @throws NoWindException
|
||||||
*/
|
*/
|
||||||
TargetTimeInfo getEstimatedTimeToComplete(TimePoint timepoint) throws NotEnoughDataHasBeenAddedException, NoWindException;
|
TargetTimeInfo getEstimatedTimeToComplete(TimePoint timepoint)
|
||||||
|
throws NotEnoughDataHasBeenAddedException, NoWindException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine the time sailed for the {@code competitor} at {@code timePoint} in this race. This ignores whether or
|
* Determine the time sailed for the {@code competitor} at {@code timePoint} in this race. This ignores whether or
|
||||||
@@ -1154,38 +1186,40 @@ public interface TrackedRace
|
|||||||
default Pair<TimePointSpecificationFoundInLog, TimePointSpecificationFoundInLog> getTrackingTimesFromRaceLogs() {
|
default Pair<TimePointSpecificationFoundInLog, TimePointSpecificationFoundInLog> getTrackingTimesFromRaceLogs() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
default Pair<TimePoint, TimePoint> getStartAndFinishedTimeFromRaceLogs() {
|
default Pair<TimePoint, TimePoint> getStartAndFinishedTimeFromRaceLogs() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all marks found in the {@link #markTracks} map and the mark device mappings and mark
|
* Returns all marks found in the {@link #markTracks} map and the mark device mappings and mark definition events in
|
||||||
* definition events in all attached race and regatta logs. Note that usually a device mapping should
|
* all attached race and regatta logs. Note that usually a device mapping should exist for a mark only if that mark
|
||||||
* exist for a mark only if that mark is also defined by a {@link RegattaLogDefineMarkEvent}, so for
|
* is also defined by a {@link RegattaLogDefineMarkEvent}, so for this standard case, adding the marks from the
|
||||||
* this standard case, adding the marks from the device mark mappings would be redundant.
|
* device mark mappings would be redundant.
|
||||||
*/
|
*/
|
||||||
default Iterable<Mark> getMarksFromRegattaLogs() {
|
default Iterable<Mark> getMarksFromRegattaLogs() {
|
||||||
return getMarks();
|
return getMarks();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the start and end of tracking in the following precedence order:
|
* Updates the start and end of tracking in the following precedence order:
|
||||||
*
|
*
|
||||||
* <ol>
|
* <ol>
|
||||||
* <li>start/end of tracking in Racelog</li>
|
* <li>start/end of tracking in Racelog</li>
|
||||||
* <li>manually set start/end of tracking via {@link #setStartOfTrackingReceived(TimePoint, boolean)} and {@link #setEndOfTrackingReceived(TimePoint, boolean)}</li>
|
* <li>manually set start/end of tracking via {@link #setStartOfTrackingReceived(TimePoint, boolean)} and
|
||||||
* <li>start/end of race in Racelog -/+ {@link #START_TRACKING_THIS_MUCH_BEFORE_RACE_START}/{@link #STOP_TRACKING_THIS_MUCH_AFTER_RACE_FINISH}</li>
|
* {@link #setEndOfTrackingReceived(TimePoint, boolean)}</li>
|
||||||
|
* <li>start/end of race in Racelog -/+
|
||||||
|
* {@link #START_TRACKING_THIS_MUCH_BEFORE_RACE_START}/{@link #STOP_TRACKING_THIS_MUCH_AFTER_RACE_FINISH}</li>
|
||||||
* </ol>
|
* </ol>
|
||||||
*/
|
*/
|
||||||
public void updateStartAndEndOfTracking(boolean waitForGPSFixesToLoad);
|
public void updateStartAndEndOfTracking(boolean waitForGPSFixesToLoad);
|
||||||
|
|
||||||
default void lockForSerializationRead() {
|
default void lockForSerializationRead() {
|
||||||
}
|
}
|
||||||
|
|
||||||
default void unlockAfterSerializationRead() {
|
default void unlockAfterSerializationRead() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return all currently attached {@link RaceLog}s or an empty Iterable if there aren't any
|
* @return all currently attached {@link RaceLog}s or an empty Iterable if there aren't any
|
||||||
*/
|
*/
|
||||||
@@ -1201,7 +1235,6 @@ public interface TrackedRace
|
|||||||
*/
|
*/
|
||||||
Speed getAverageSpeedOverGround(Competitor competitor, TimePoint timePoint);
|
Speed getAverageSpeedOverGround(Competitor competitor, TimePoint timePoint);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the competitor's speed projected onto the wind (if wind data is available and the competitor is not
|
* Computes the competitor's speed projected onto the wind (if wind data is available and the competitor is not
|
||||||
* between start and finish (not racing) or not on a {@link LegType#REACHING reaching} leg; if outside a race and no
|
* between start and finish (not racing) or not on a {@link LegType#REACHING reaching} leg; if outside a race and no
|
||||||
@@ -1214,21 +1247,25 @@ public interface TrackedRace
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Like {@link #getVelocityMadeGood(Competitor, TimePoint)}, but allowing callers to specify a {@link WindPositionMode}
|
* Like {@link #getVelocityMadeGood(Competitor, TimePoint)}, but allowing callers to specify a
|
||||||
* other than the default {@link WindPositionMode#EXACT}. If {@link WindPositionMode#LEG_MIDDLE} is used and the
|
* {@link WindPositionMode} other than the default {@link WindPositionMode#EXACT}. If
|
||||||
* competitor is not currently sailing on a leg (hasn't started or has already finished), {@code null} is returned.
|
* {@link WindPositionMode#LEG_MIDDLE} is used and the competitor is not currently sailing on a leg (hasn't started
|
||||||
|
* or has already finished), {@code null} is returned.
|
||||||
*/
|
*/
|
||||||
default SpeedWithBearing getVelocityMadeGood(Competitor competitor, TimePoint timePoint, WindPositionMode windPositionMode) {
|
default SpeedWithBearing getVelocityMadeGood(Competitor competitor, TimePoint timePoint,
|
||||||
return getVelocityMadeGood(competitor, timePoint, windPositionMode, new LeaderboardDTOCalculationReuseCache(timePoint));
|
WindPositionMode windPositionMode) {
|
||||||
|
return getVelocityMadeGood(competitor, timePoint, windPositionMode,
|
||||||
|
new LeaderboardDTOCalculationReuseCache(timePoint));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the angle between the competitors direction and the wind's "from" direction. The angle's direction is chosen such that
|
* Computes the angle between the competitors direction and the wind's "from" direction. The angle's direction is
|
||||||
* it can be added to the boat's course over ground to arrive at the wind's {@link Wind#getFrom() "from"} direction. Example: wind
|
* chosen such that it can be added to the boat's course over ground to arrive at the wind's {@link Wind#getFrom()
|
||||||
* from the north (0deg), boat's course over ground 90deg (moving east), then the bearing returned is -90deg.
|
* "from"} direction. Example: wind from the north (0deg), boat's course over ground 90deg (moving east), then the
|
||||||
|
* bearing returned is -90deg.
|
||||||
*/
|
*/
|
||||||
default Bearing getTWA(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) {
|
default Bearing getTWA(Competitor competitor, TimePoint timePoint,
|
||||||
|
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) {
|
||||||
Bearing twa = null;
|
Bearing twa = null;
|
||||||
final GPSFixTrack<Competitor, GPSFixMoving> sogTrack = this.getTrack(competitor);
|
final GPSFixTrack<Competitor, GPSFixMoving> sogTrack = this.getTrack(competitor);
|
||||||
if (sogTrack != null) {
|
if (sogTrack != null) {
|
||||||
@@ -1241,20 +1278,21 @@ public interface TrackedRace
|
|||||||
}
|
}
|
||||||
return twa;
|
return twa;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link #getTWA}, only that additionally a cache is provided that can allow the method to use
|
* Same as {@link #getTWA}, only that additionally a cache is provided that can allow the method to use cached wind
|
||||||
* cached wind and leg type values.
|
* and leg type values.
|
||||||
*/
|
*/
|
||||||
default Bearing getTWA(Competitor competitor, TimePoint at){
|
default Bearing getTWA(Competitor competitor, TimePoint at) {
|
||||||
return getTWA(competitor, at, new LeaderboardDTOCalculationReuseCache(at));
|
return getTWA(competitor, at, new LeaderboardDTOCalculationReuseCache(at));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Like {@link #getVelocityMadeGood(Competitor, TimePoint)}, but allowing callers to specify a cache that can
|
* Like {@link #getVelocityMadeGood(Competitor, TimePoint)}, but allowing callers to specify a cache that can
|
||||||
* accelerate requests for wind directions, the leg type and the competitor's current leg's bearing.
|
* accelerate requests for wind directions, the leg type and the competitor's current leg's bearing.
|
||||||
*/
|
*/
|
||||||
default SpeedWithBearing getVelocityMadeGood(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) {
|
default SpeedWithBearing getVelocityMadeGood(Competitor competitor, TimePoint timePoint,
|
||||||
|
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) {
|
||||||
return getVelocityMadeGood(competitor, timePoint, WindPositionMode.EXACT, cache);
|
return getVelocityMadeGood(competitor, timePoint, WindPositionMode.EXACT, cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1274,6 +1312,7 @@ public interface TrackedRace
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets polar service which is currently set in this tracked race instance.
|
* Gets polar service which is currently set in this tracked race instance.
|
||||||
|
*
|
||||||
* @see #setPolarDataService(PolarDataService)
|
* @see #setPolarDataService(PolarDataService)
|
||||||
*/
|
*/
|
||||||
PolarDataService getPolarDataService();
|
PolarDataService getPolarDataService();
|
||||||
@@ -1291,16 +1330,16 @@ public interface TrackedRace
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains a quick, rough summary of the wind conditions during this race, based on a few wind samples at the
|
* Obtains a quick, rough summary of the wind conditions during this race, based on a few wind samples at the
|
||||||
* beginning, in the middle and at the end of the race. This is summarized in a min and max wind speed as well
|
* beginning, in the middle and at the end of the race. This is summarized in a min and max wind speed as well as a
|
||||||
* as a single average wind direction.
|
* single average wind direction.
|
||||||
*/
|
*/
|
||||||
WindSummary getWindSummary();
|
WindSummary getWindSummary();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default QualifiedObjectIdentifier getIdentifier() {
|
default QualifiedObjectIdentifier getIdentifier() {
|
||||||
return getIdentifier(getRaceIdentifier());
|
return getIdentifier(getRaceIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static QualifiedObjectIdentifier getIdentifier(RegattaAndRaceIdentifier regattaAndRaceId) {
|
public static QualifiedObjectIdentifier getIdentifier(RegattaAndRaceIdentifier regattaAndRaceId) {
|
||||||
return getSecuredDomainType().getQualifiedObjectIdentifier(regattaAndRaceId.getTypeRelativeObjectIdentifier());
|
return getSecuredDomainType().getQualifiedObjectIdentifier(regattaAndRaceId.getTypeRelativeObjectIdentifier());
|
||||||
}
|
}
|
||||||
@@ -1318,7 +1357,7 @@ public interface TrackedRace
|
|||||||
default HasPermissions getPermissionType() {
|
default HasPermissions getPermissionType() {
|
||||||
return getSecuredDomainType();
|
return getSecuredDomainType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HasPermissions getSecuredDomainType() {
|
public static HasPermissions getSecuredDomainType() {
|
||||||
return SecuredDomainType.TRACKED_RACE;
|
return SecuredDomainType.TRACKED_RACE;
|
||||||
}
|
}
|
||||||
@@ -1341,13 +1380,14 @@ public interface TrackedRace
|
|||||||
* the maximum across their competitors' implied winds, or in case the implied wind was explicitly fixed by a
|
* the maximum across their competitors' implied winds, or in case the implied wind was explicitly fixed by a
|
||||||
* corresponding {@link RaceLogORCImpliedWindSourceEvent}, that fixed implied wind speed.
|
* corresponding {@link RaceLogORCImpliedWindSourceEvent}, that fixed implied wind speed.
|
||||||
*/
|
*/
|
||||||
default Speed getReferenceImpliedWind(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) {
|
default Speed getReferenceImpliedWind(TimePoint timePoint,
|
||||||
|
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) {
|
||||||
return getRankingMetric().getReferenceImpliedWind(timePoint, cache);
|
return getRankingMetric().getReferenceImpliedWind(timePoint, cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gets a {@link TrackingConnectorInfo}, which contains a String representation of the Tracking-Service used to Track the Race and a web-URL for the Event Event;
|
* gets a {@link TrackingConnectorInfo}, which contains a String representation of the Tracking-Service used to
|
||||||
* may be {@code null}, particularly in test set-ups
|
* Track the Race and a web-URL for the Event Event; may be {@code null}, particularly in test set-ups
|
||||||
*/
|
*/
|
||||||
TrackingConnectorInfo getTrackingConnectorInfo();
|
TrackingConnectorInfo getTrackingConnectorInfo();
|
||||||
|
|
||||||
@@ -1381,8 +1421,8 @@ public interface TrackedRace
|
|||||||
* hypothetical "line" perpendicular to the first leg's bearing.
|
* hypothetical "line" perpendicular to the first leg's bearing.
|
||||||
*/
|
*/
|
||||||
Pair<Bearing, Position> getStartLineBearingAndStarboardMarkPosition(TimePoint timePoint);
|
Pair<Bearing, Position> getStartLineBearingAndStarboardMarkPosition(TimePoint timePoint);
|
||||||
|
|
||||||
void setHashValuesForMarkPassingCalculation(Map<typeOfHash, Integer> hashValues);
|
void setHashValuesForMarkPassingCalculation(Map<TypeOfHash, Integer> hashValues);
|
||||||
|
|
||||||
Map<typeOfHash, Integer> getHashValuesForMarkPassingCalculation ();
|
Map<TypeOfHash, Integer> getHashValuesForMarkPassingCalculation();
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -123,6 +123,7 @@ import com.sap.sailing.domain.maneuverdetection.ManeuverDetector;
|
|||||||
import com.sap.sailing.domain.maneuverdetection.ShortTimeAfterLastHitCache;
|
import com.sap.sailing.domain.maneuverdetection.ShortTimeAfterLastHitCache;
|
||||||
import com.sap.sailing.domain.maneuverdetection.impl.IncrementalManeuverDetectorImpl;
|
import com.sap.sailing.domain.maneuverdetection.impl.IncrementalManeuverDetectorImpl;
|
||||||
import com.sap.sailing.domain.markpassingcalculation.MarkPassingCalculator;
|
import com.sap.sailing.domain.markpassingcalculation.MarkPassingCalculator;
|
||||||
|
import com.sap.sailing.domain.markpassinghash.impl.TrackedRaceHashForMarkPassingComparatorImpl.TypeOfHash;
|
||||||
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
||||||
import com.sap.sailing.domain.polars.PolarDataService;
|
import com.sap.sailing.domain.polars.PolarDataService;
|
||||||
import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver;
|
import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver;
|
||||||
@@ -158,7 +159,6 @@ import com.sap.sailing.domain.tracking.WindStore;
|
|||||||
import com.sap.sailing.domain.tracking.WindSummary;
|
import com.sap.sailing.domain.tracking.WindSummary;
|
||||||
import com.sap.sailing.domain.tracking.WindTrack;
|
import com.sap.sailing.domain.tracking.WindTrack;
|
||||||
import com.sap.sailing.domain.tracking.WindWithConfidence;
|
import com.sap.sailing.domain.tracking.WindWithConfidence;
|
||||||
import com.sap.sailing.domain.tracking.impl.TrackedRaceHashForMarkPassingComperatorImpl.typeOfHash;
|
|
||||||
import com.sap.sailing.domain.windestimation.IncrementalWindEstimation;
|
import com.sap.sailing.domain.windestimation.IncrementalWindEstimation;
|
||||||
import com.sap.sse.common.Bearing;
|
import com.sap.sse.common.Bearing;
|
||||||
import com.sap.sse.common.Distance;
|
import com.sap.sse.common.Distance;
|
||||||
@@ -444,7 +444,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
|||||||
private transient ConcurrentMap<TimePoint, SortedMap<Competitor, Distance>> distancesFromStarboardSideOfStartLineProjectedOntoLineCache;
|
private transient ConcurrentMap<TimePoint, SortedMap<Competitor, Distance>> distancesFromStarboardSideOfStartLineProjectedOntoLineCache;
|
||||||
private transient ConcurrentMap<TimePoint, TimePoint> distancesFromStarboardSideOfStartLineProjectedOntoLineCacheLastAccessTimes;
|
private transient ConcurrentMap<TimePoint, TimePoint> distancesFromStarboardSideOfStartLineProjectedOntoLineCacheLastAccessTimes;
|
||||||
|
|
||||||
private Map<typeOfHash, Integer> hashValuesForMarkPassingCalculation;
|
private Map<TypeOfHash, Integer> hashValuesForMarkPassingCalculation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When a regatta's {@link Regatta#useStartTimeInference()} or {@link Regatta#isControlTrackingFromStartAndFinishTimes()}
|
* When a regatta's {@link Regatta#useStartTimeInference()} or {@link Regatta#isControlTrackingFromStartAndFinishTimes()}
|
||||||
@@ -4307,11 +4307,11 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
|||||||
return trackingConnectorInfo;
|
return trackingConnectorInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHashValuesForMarkPassingCalculation(Map<typeOfHash, Integer> hashValues) {
|
public void setHashValuesForMarkPassingCalculation(Map<TypeOfHash, Integer> hashValues) {
|
||||||
this.hashValuesForMarkPassingCalculation = hashValues;
|
this.hashValuesForMarkPassingCalculation = hashValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<typeOfHash, Integer> getHashValuesForMarkPassingCalculation () {
|
public Map<TypeOfHash, Integer> getHashValuesForMarkPassingCalculation () {
|
||||||
return this.hashValuesForMarkPassingCalculation;
|
return this.hashValuesForMarkPassingCalculation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user