mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-16 09:11:02 +00:00
Merge remote-tracking branch 'origin/master' into ribdashboard
This commit is contained in:
commit
5bbb80891e
18 files changed
+1065
-75
No files matched your search
@@ -602,8 +602,6 @@ if [[ "$@" == "build" ]] || [[ "$@" == "all" ]]; then
|
|||||||
TRACKING_APP_VERSION=`grep "android:versionCode=" mobile/com.sap.$PROJECT_TYPE.android.tracking.app/AndroidManifest.xml | cut -d "\"" -f 2`
|
TRACKING_APP_VERSION=`grep "android:versionCode=" mobile/com.sap.$PROJECT_TYPE.android.tracking.app/AndroidManifest.xml | cut -d "\"" -f 2`
|
||||||
echo "TRACKING_APP_VERSION=$TRACKING_APP_VERSION"
|
echo "TRACKING_APP_VERSION=$TRACKING_APP_VERSION"
|
||||||
extra="$extra -Dtracking-app-version=$TRACKING_APP_VERSION"
|
extra="$extra -Dtracking-app-version=$TRACKING_APP_VERSION"
|
||||||
|
|
||||||
|
|
||||||
else
|
else
|
||||||
echo "INFO: Deactivating mobile modules"
|
echo "INFO: Deactivating mobile modules"
|
||||||
extra="$extra -P !with-mobile"
|
extra="$extra -P !with-mobile"
|
||||||
|
|||||||
+14
-4
@@ -17,14 +17,12 @@ import com.sap.sse.common.TimePoint;
|
|||||||
public class TracTracStartTimeUpdateHandler extends UpdateHandler implements StartTimeChangedListener {
|
public class TracTracStartTimeUpdateHandler extends UpdateHandler implements StartTimeChangedListener {
|
||||||
|
|
||||||
private static final String ACTION = "update_race_start_time";
|
private static final String ACTION = "update_race_start_time";
|
||||||
private final TracTracStartTimeResetHandler resetHandler;
|
|
||||||
|
|
||||||
private final static Logger logger = Logger.getLogger(TracTracStartTimeUpdateHandler.class.getName());
|
private final static Logger logger = Logger.getLogger(TracTracStartTimeUpdateHandler.class.getName());
|
||||||
private final static String FIELD_RACE_START_TIME = "race_start_time";
|
private final static String FIELD_RACE_START_TIME = "race_start_time";
|
||||||
|
|
||||||
public TracTracStartTimeUpdateHandler(URI updateURI, String tracTracUsername, String tracTracPassword, Serializable tracTracEventId, Serializable raceId) {
|
public TracTracStartTimeUpdateHandler(URI updateURI, String tracTracUsername, String tracTracPassword, Serializable tracTracEventId, Serializable raceId) {
|
||||||
super(updateURI, ACTION, tracTracUsername, tracTracPassword, tracTracEventId, raceId);
|
super(updateURI, ACTION, tracTracUsername, tracTracPassword, tracTracEventId, raceId);
|
||||||
resetHandler = new TracTracStartTimeResetHandler(updateURI, tracTracUsername, tracTracPassword, tracTracEventId, raceId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -34,8 +32,20 @@ public class TracTracStartTimeUpdateHandler extends UpdateHandler implements Sta
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (newStartTime == null) {
|
if (newStartTime == null) {
|
||||||
// reset start time with TracTrac
|
/*
|
||||||
resetHandler.startTimeChanged(null);
|
* Do not reset start time based on request by Jorge from TracTrac:
|
||||||
|
*
|
||||||
|
* """
|
||||||
|
* We have detected that when you want to update the race start time your
|
||||||
|
* system sends before a message to reset the race start time. When your
|
||||||
|
* system invokes the first service our system changes the race start time
|
||||||
|
* to null and this value causes some secondary effects in our side.
|
||||||
|
*
|
||||||
|
* Can you just send the update_race_start_time without the
|
||||||
|
* reset_race_start_time? The reset_race_start_time service has to be used
|
||||||
|
* if you want to set the value to null.
|
||||||
|
* """
|
||||||
|
*/
|
||||||
} else {
|
} else {
|
||||||
HashMap<String, String> additionalParameters = new HashMap<String, String>();
|
HashMap<String, String> additionalParameters = new HashMap<String, String>();
|
||||||
additionalParameters.put(FIELD_RACE_START_TIME, String.valueOf(newStartTime.asMillis()));
|
additionalParameters.put(FIELD_RACE_START_TIME, String.valueOf(newStartTime.asMillis()));
|
||||||
|
|||||||
+1
-1
@@ -674,7 +674,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
|
|||||||
WindTrackInfoDTO windTrackInfoDTO = windInfo.windTrackInfoByWindSource.get(windSource);
|
WindTrackInfoDTO windTrackInfoDTO = windInfo.windTrackInfoByWindSource.get(windSource);
|
||||||
switch (windSource.getType()) {
|
switch (windSource.getType()) {
|
||||||
case EXPEDITION:
|
case EXPEDITION:
|
||||||
// we filter out measured wind sources with a very little confidence
|
// we filter out measured wind sources with vary low confidence
|
||||||
if (windTrackInfoDTO.minWindConfidence > 0.0001) {
|
if (windTrackInfoDTO.minWindConfidence > 0.0001) {
|
||||||
windSourcesToShow.add(new com.sap.sse.common.Util.Pair<WindSource, WindTrackInfoDTO>(windSource, windTrackInfoDTO));
|
windSourcesToShow.add(new com.sap.sse.common.Util.Pair<WindSource, WindTrackInfoDTO>(windSource, windTrackInfoDTO));
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-6
@@ -82,7 +82,7 @@ public class TestWindEstimationFromManeuversOnAFew505Races extends OnlineTracTra
|
|||||||
CreateModelException, NotEnoughDataHasBeenAddedException {
|
CreateModelException, NotEnoughDataHasBeenAddedException {
|
||||||
setUp("OBMR 2012", "event_20121031_OBMR-OBMR_2012_VR_Fr_Fleet_1_2");
|
setUp("OBMR 2012", "event_20121031_OBMR-OBMR_2012_VR_Fr_Fleet_1_2");
|
||||||
Wind average = getManeuverBasedAverageWind();
|
Wind average = getManeuverBasedAverageWind();
|
||||||
assertEquals(222, average.getFrom().getDegrees(), 5.0); // wind in this race was from 075deg on average
|
assertEquals(222, average.getFrom().getDegrees(), 5.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -91,7 +91,7 @@ public class TestWindEstimationFromManeuversOnAFew505Races extends OnlineTracTra
|
|||||||
CreateModelException, NotEnoughDataHasBeenAddedException {
|
CreateModelException, NotEnoughDataHasBeenAddedException {
|
||||||
setUp("event_20110609_KielerWoch-505_Race_2");
|
setUp("event_20110609_KielerWoch-505_Race_2");
|
||||||
Wind average = getManeuverBasedAverageWind();
|
Wind average = getManeuverBasedAverageWind();
|
||||||
assertEquals(235, average.getFrom().getDegrees(), 5.0); // wind in this race was from 075deg on average
|
assertEquals(235, average.getFrom().getDegrees(), 5.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -100,7 +100,7 @@ public class TestWindEstimationFromManeuversOnAFew505Races extends OnlineTracTra
|
|||||||
CreateModelException, NotEnoughDataHasBeenAddedException {
|
CreateModelException, NotEnoughDataHasBeenAddedException {
|
||||||
setUp("event_20110609_KielerWoch-505_Race_3");
|
setUp("event_20110609_KielerWoch-505_Race_3");
|
||||||
Wind average = getManeuverBasedAverageWind();
|
Wind average = getManeuverBasedAverageWind();
|
||||||
assertEquals(245, average.getFrom().getDegrees(), 5.0); // wind in this race was from 075deg on average
|
assertEquals(245, average.getFrom().getDegrees(), 5.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -109,7 +109,7 @@ public class TestWindEstimationFromManeuversOnAFew505Races extends OnlineTracTra
|
|||||||
CreateModelException, NotEnoughDataHasBeenAddedException {
|
CreateModelException, NotEnoughDataHasBeenAddedException {
|
||||||
setUp("event_20110609_KielerWoch-505_race_4");
|
setUp("event_20110609_KielerWoch-505_race_4");
|
||||||
Wind average = getManeuverBasedAverageWind();
|
Wind average = getManeuverBasedAverageWind();
|
||||||
assertEquals(275, average.getFrom().getDegrees(), 5.0); // wind in this race was from 075deg on average
|
assertEquals(270, average.getFrom().getDegrees(), 5.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -139,8 +139,11 @@ public class TestWindEstimationFromManeuversOnAFew505Races extends OnlineTracTra
|
|||||||
.sorted((c1, c2) -> (int) -Math.signum(getAverageLikelihood(c1, ManeuverType.TACK)
|
.sorted((c1, c2) -> (int) -Math.signum(getAverageLikelihood(c1, ManeuverType.TACK)
|
||||||
- getAverageLikelihood(c2, ManeuverType.TACK))).collect(Collectors.toList());
|
- getAverageLikelihood(c2, ManeuverType.TACK))).collect(Collectors.toList());
|
||||||
// expecting a wind direction that is from around 245deg, +/- 10deg
|
// expecting a wind direction that is from around 245deg, +/- 10deg
|
||||||
assertEquals(245., windTrack.getWeightedAverageMiddleManeuverCOGDeg(clustersSortedByAverageTackLikelihood.get(0), ManeuverType.TACK).getDegrees(), 10.);
|
assertEquals(
|
||||||
assertEquals(245., windTrack.getWeightedAverageMiddleManeuverCOGDeg(clustersSortedByAverageTackLikelihood.get(1), ManeuverType.TACK).getDegrees(), 10.);
|
245., windTrack.getWeightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg(
|
||||||
|
clustersSortedByAverageTackLikelihood.get(0), ManeuverType.TACK).getA().getDegrees(), 10.);
|
||||||
|
assertEquals(245., windTrack.getWeightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg(
|
||||||
|
clustersSortedByAverageTackLikelihood.get(1), ManeuverType.TACK).getA().getDegrees(), 10.);
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getAverageLikelihood(
|
private double getAverageLikelihood(
|
||||||
|
|||||||
+207
-59
@@ -70,26 +70,59 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl {
|
|||||||
* for another cluster to be a cluster's opposite tack cluster is determined by first computing the
|
* for another cluster to be a cluster's opposite tack cluster is determined by first computing the
|
||||||
* {@link #getClusterDistanceBasedOnAverageManeuverLikelihoodAndWeightedAverageMiddleCOG(Cluster, double, Bearing) angular
|
* {@link #getClusterDistanceBasedOnAverageManeuverLikelihoodAndWeightedAverageMiddleCOG(Cluster, double, Bearing) angular
|
||||||
* distance}. For each so many degrees of distance as specified by this constant, the likelihood of the cluster to be the
|
* distance}. For each so many degrees of distance as specified by this constant, the likelihood of the cluster to be the
|
||||||
* opposite tack cluster is halved.
|
* opposite tack cluster is halved. This constant can also be used to assign likelihoods for other cluster types
|
||||||
|
* based on their distance from an expected configuration of maneuver angle and middle COG.
|
||||||
*/
|
*/
|
||||||
private static final double ANGULAR_DISTANCE_FOR_HALF_CONFIDENCE_FOR_OPPOSITE_TACK_CLUSTER_DEG = 20.;
|
private static final double ANGULAR_DISTANCE_FOR_HALF_CONFIDENCE_FOR_OPPOSITE_TACK_CLUSTER_DEG = 20.;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When one or two jibe clusters have been found whose
|
||||||
|
* {@link #getLikelihoodOfBeingJibeCluster(Speed, Stream, BoatClass, Set) likelihood of being a jibe cluster} is 100%,
|
||||||
|
* this is the boost factor by which the base likelihood for the tack cluster candidate will be increased (up to a
|
||||||
|
* maximum of 1.0).
|
||||||
|
*/
|
||||||
|
private static final double BOOST_FACTOR_FOR_FULL_JIBE_CLUSTER_LIKELIHOOD = 0.2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When one or two head-up / bear-away clusters on the two tacks adjacent to the middle upwind COG have been found
|
||||||
|
* whose {@link #getLikelihoodOfClusterBasedOnDistanceFromExpected(double, Bearing, Cluster) likelihood of being
|
||||||
|
* such a cluster} is 100%, this is the boost factor by which the base likelihood for the tack cluster candidate
|
||||||
|
* will be increased (up to a maximum of 1.0).
|
||||||
|
*/
|
||||||
|
private static final double BOOST_FACTOR_FOR_FULL_HEAD_UP_BEAR_AWAY_CLUSTER_LIKELIHOOD = 0.1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When looking for the head-up/bear-away clusters, which average maneuver angle should be expected? This is a bit
|
||||||
|
* fuzzy because in some cases the head-up and bear-away maneuvers may be grouped into one cluster, resulting in an
|
||||||
|
* average maneuver angle that is close to zero whereas in other cases they may form two clusters, one with positive
|
||||||
|
* and the other with negative maneuver angles of somewhere between 10-20deg, typically.
|
||||||
|
*/
|
||||||
|
private static final double EXPECTED_AVERAGE_HEAD_UP_AND_BEAR_AWAY_MANEUVER_ANGLE_DEG = 10.;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We're trying to find the jibe cluster based on a candidate for the tack cluster. This constant tells how many degrees
|
* We're trying to find the jibe cluster based on a candidate for the tack cluster. This constant tells how many degrees
|
||||||
* the jibe cluster may be off from the reversed tack cluster's centroid in order to be accepted as jibe cluster candidate.
|
* the jibe cluster may be off from the reversed tack cluster's centroid in order to be accepted as jibe cluster candidate.
|
||||||
*/
|
*/
|
||||||
private static final double THRESHOLD_JIBE_CLUSTER_DIFFERENCE_DEGREES = 20;
|
private static final double THRESHOLD_JIBE_CLUSTER_DIFFERENCE_DEGREES = 20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For judging the likelihood of a cluster being a speed cluster, the speed ratio of the tack cluster candidate and
|
||||||
|
* the jibe cluster candidate is computed and compared to what the polar service predicts. The basic likelihood of the
|
||||||
|
* jibe cluster candidate (based on the maneuver angles relative to their speeds) is boosted by this factor for a perfect
|
||||||
|
* speed ratio match.
|
||||||
|
*/
|
||||||
|
private static final double BOOST_FACTOR_FOR_JIBE_TACK_SPEED_RATIO_LIKELIHOOD = 0;
|
||||||
|
|
||||||
private final PolarDataService polarService;
|
private final PolarDataService polarService;
|
||||||
|
|
||||||
private final TrackedRace trackedRace;
|
private final TrackedRace trackedRace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Caches the {@link #getWeightedAverageMiddleManeuverCOGDeg(Cluster, ManeuverType)} results because these values are required several times to
|
* Caches the {@link #getWeightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg(Cluster, ManeuverType)} results because these values are required several times to
|
||||||
* determine the likelihood with which a cluster is a cluster of tacks or a cluster of jibes. Note that the un-weighted averages can simply be obtained
|
* determine the likelihood with which a cluster is a cluster of tacks or a cluster of jibes. Note that the un-weighted averages can simply be obtained
|
||||||
* by asking the cluster for its {@link Cluster#getCentroid() centroid}.
|
* by asking the cluster for its {@link Cluster#getCentroid() centroid}.
|
||||||
*/
|
*/
|
||||||
private final Map<Pair<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>, ManeuverType>, Bearing>
|
private final Map<Pair<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>, ManeuverType>, Pair<Bearing, Double>>
|
||||||
weightedAverageMiddleCOGForManeuverType;
|
weightedAverageMiddleCOGForManeuverType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -308,17 +341,16 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl {
|
|||||||
* There are usually no other maneuvers with similar middle COG because boats can't sail straight against the wind.
|
* There are usually no other maneuvers with similar middle COG because boats can't sail straight against the wind.
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* We evaluate each cluster's likelihood of being the tack cluster by for each of its maneuvers adding up the
|
* We evaluate each cluster's likelihood of being the tack cluster by computing the average across all its maneuvers
|
||||||
* likelihood of that maneuver being a tack, solely based on its maneuver angle, as judged by the polar service. If
|
* for that maneuver being a tack, solely based on its speed and maneuver angle, as
|
||||||
* a cluster exists that has approximately the opposite average middle COG (the jibe cluster candidate), the
|
* {@link PolarDataService#getManeuverLikelihoodAndTwsTwa(BoatClass, Speed, double, ManeuverType) judged by the
|
||||||
* likelihoods for its maneuvers being a jibe are added. (TODO adding is statistically not adequate here; however,
|
* polar service}. If a cluster exists that has approximately the opposite average middle COG (the jibe cluster
|
||||||
* multiplying hundreds if not thousands of probability values would easily lead to a double value going to 0.0
|
* candidate), the {@link #getLikelihoodOfBeingJibeCluster(Speed, Stream, BoatClass, Set) likelihood for its maneuvers
|
||||||
* quickly. But is adding adequate to estimate the cluster having the maximum likelihood of being the tack cluster?
|
* being jibes} are determined and may result in a "boost" for the basic probability of up to 20%. Finally, the
|
||||||
* We'd only need a monotonous function.) Finally, the resulting likelihood is multiplied by how likely the speed
|
* resulting likelihood is multiplied by how likely the speed ratio between the tack and jibe cluster candidates is,
|
||||||
* ratio between the tack and jibe cluster candidates is, based on the polar diagram. For this task, the cluster's
|
* based on the polar diagram. For this task, the cluster's maneuvers' average speed (weighted by each maneuver's
|
||||||
* maneuvers' average speed (weighted by each maneuver's likelihood of being a tack) is divided by that of the jibe
|
* likelihood of being a tack) is divided by that of the jibe cluster's maneuvers' average speed (weighted by each
|
||||||
* cluster's maneuvers' average speed (weighted by each maneuver's likelihood of being a jibe) and assigned a
|
* maneuver's likelihood of being a jibe) and assigned a likelihood by the polar service.
|
||||||
* likelihood by the polar service.
|
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* The cluster that has the highest likelihood of being the tack cluster is selected. The confidence of the choice
|
* The cluster that has the highest likelihood of being the tack cluster is selected. The confidence of the choice
|
||||||
@@ -361,21 +393,22 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl {
|
|||||||
final Map<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>, Double>
|
final Map<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>, Double>
|
||||||
likelihoodOfBeingTackCluster = new HashMap<>();
|
likelihoodOfBeingTackCluster = new HashMap<>();
|
||||||
for (Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble> c : clusters) {
|
for (Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble> c : clusters) {
|
||||||
likelihoodOfBeingTackCluster.put(c, getLikelihoodOfBeingTackCluster(c, clusters));
|
likelihoodOfBeingTackCluster.put(c,
|
||||||
|
getLikelihoodOfBeingTackCluster(c, clusters));
|
||||||
}
|
}
|
||||||
// The first two clusters in the resulting list are now our best bet for the tack clusters, assuming that the likelihood for the third element
|
// The first two clusters in the resulting list are now our best bet for the tack clusters, assuming that the likelihood for the third element
|
||||||
// in the list is already much lower. Should there be a significant degradation of likelihood between the first and the second cluster, we
|
// in the list is already much lower. Should there be a significant degradation of likelihood between the first and the second cluster, we
|
||||||
// will only use the first, particularly if the average middle COGs of the first two clusters differ significantly.
|
// will only use the first, particularly if the average middle COGs of the first two clusters differ significantly.
|
||||||
final List<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>> tackClusters =
|
final List<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>> tackClusters =
|
||||||
clusters.stream()
|
clusters.stream()
|
||||||
.sorted((c1, c2) -> (int) -Math.signum(likelihoodOfBeingTackCluster.get(c1) // TODO cache result of getLikelihoodOfBeingTackCluster
|
.sorted((c1, c2) -> (int) -Math.signum(likelihoodOfBeingTackCluster.get(c1)
|
||||||
- likelihoodOfBeingTackCluster.get(c2))).limit(2).collect(Collectors.toList());
|
- likelihoodOfBeingTackCluster.get(c2))).limit(2).collect(Collectors.toList());
|
||||||
addWindFixes(tackClusters.stream(), ManeuverType.TACK);
|
addWindFixes(tackClusters.stream(), ManeuverType.TACK);
|
||||||
Bearing estimatedJibeMiddleCOG =
|
Bearing estimatedJibeMiddleCOG =
|
||||||
tackClusters.isEmpty() ? null
|
tackClusters.isEmpty() ? null
|
||||||
: (tackClusters.size() == 1 ? getWeightedAverageMiddleManeuverCOGDeg(tackClusters.get(0), ManeuverType.TACK)
|
: (tackClusters.size() == 1 ? getWeightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg(tackClusters.get(0), ManeuverType.TACK).getA()
|
||||||
: new ScalableBearing(getWeightedAverageMiddleManeuverCOGDeg(tackClusters.get(0), ManeuverType.TACK)).add(
|
: new ScalableBearing(getWeightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg(tackClusters.get(0), ManeuverType.TACK).getA()).add(
|
||||||
new ScalableBearing(getWeightedAverageMiddleManeuverCOGDeg(tackClusters.get(1), ManeuverType.TACK))).
|
new ScalableBearing(getWeightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg(tackClusters.get(1), ManeuverType.TACK).getA())).
|
||||||
divide(2)).reverse();
|
divide(2)).reverse();
|
||||||
final List<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>> jibeClusters =
|
final List<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>> jibeClusters =
|
||||||
getJibeClusters(estimatedJibeMiddleCOG, clusters).collect(Collectors.toList());
|
getJibeClusters(estimatedJibeMiddleCOG, clusters).collect(Collectors.toList());
|
||||||
@@ -402,12 +435,14 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl {
|
|||||||
/**
|
/**
|
||||||
* Determines the likelihood of <code>cluster</code> being a cluster of tacks, based on the average likelihood of
|
* Determines the likelihood of <code>cluster</code> being a cluster of tacks, based on the average likelihood of
|
||||||
* the maneuver classifications in <code>cluster</code> to be maneuvers of type {@link ManeuverType#TACK TACK}, in
|
* the maneuver classifications in <code>cluster</code> to be maneuvers of type {@link ManeuverType#TACK TACK}, in
|
||||||
* turn based on what the {@link #polarService} thinks that this likelihood is and based on whether we find other
|
* turn based on what the {@link #polarService} thinks that this
|
||||||
* <code>clusters</code> that support this hypothesis. The likelihood is positively affected
|
* {@link PolarDataService#getManeuverLikelihoodAndTwsTwa(BoatClass, Speed, double, ManeuverType) likelihood} is and
|
||||||
|
* based on whether we find other <code>clusters</code> that support this hypothesis. The likelihood is positively
|
||||||
|
* affected
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>if a second cluster with similar average middle COG and a similar average maneuver angle with opposite sign
|
* <li>if a second cluster with similar average middle COG and a similar average maneuver angle with opposite sign
|
||||||
* is found that also has a high average likelihood of the maneuvers contained being tacks</li>
|
* is found that also has a high average likelihood of its maneuvers being tacks</li>
|
||||||
* <li>if other clusters are found that for the average true wind speed estimated from the maneuvers in
|
* <li>if other clusters are found that for the average true wind speed estimated from the maneuvers in
|
||||||
* <code>cluster</code> seem like head-up/bear-away clusters on port/starboard tack with an average middle COG that
|
* <code>cluster</code> seem like head-up/bear-away clusters on port/starboard tack with an average middle COG that
|
||||||
* is half the tacking angle for that wind speed away from the tack cluster's average middle COG</li>
|
* is half the tacking angle for that wind speed away from the tack cluster's average middle COG</li>
|
||||||
@@ -423,7 +458,14 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl {
|
|||||||
* apart from the tacks even if they have similar maneuver angles.</li>
|
* apart from the tacks even if they have similar maneuver angles.</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @return a likelihood between 0..1 (inclusive)
|
* @return a likelihood between 0..1 (inclusive), obtained by multiplying the based likelihood of the
|
||||||
|
* <code>cluster</code> to hold tacks, based on the maneuver angles and their speed and how likely the
|
||||||
|
* {@link #polarService} considers this to be a tack; with boost factors added for the likelihood of having
|
||||||
|
* found a good jibe cluster and boost factors for the likelihoods of having found starboard and port tack
|
||||||
|
* clusters that hold the head-up/bear-away maneuvers. These boosts can add as much as
|
||||||
|
* {@link #BOOST_FACTOR_FOR_FULL_JIBE_CLUSTER_LIKELIHOOD} + 2*
|
||||||
|
* {@link #BOOST_FACTOR_FOR_FULL_HEAD_UP_BEAR_AWAY_CLUSTER_LIKELIHOOD} of the original value but will be
|
||||||
|
* capped at the maximum likelihood of 1.0.
|
||||||
*
|
*
|
||||||
* @see ManeuverClassification#getLikelihoodAndTWSBasedOnSpeedAndAngle(ManeuverType)
|
* @see ManeuverClassification#getLikelihoodAndTWSBasedOnSpeedAndAngle(ManeuverType)
|
||||||
* @see PolarDataService#getManeuverLikelihoodAndTwsTwa(BoatClass, Speed, double, ManeuverType)
|
* @see PolarDataService#getManeuverLikelihoodAndTwsTwa(BoatClass, Speed, double, ManeuverType)
|
||||||
@@ -433,8 +475,7 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl {
|
|||||||
Set<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>> clusters) {
|
Set<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>> clusters) {
|
||||||
// start with the average of all of the cluster's maneuvers' likelihood to be a tack
|
// start with the average of all of the cluster's maneuvers' likelihood to be a tack
|
||||||
double averageTackLikelihood = getAverageLikelihoodOfBeingManeuver(ManeuverType.TACK, cluster.stream());
|
double averageTackLikelihood = getAverageLikelihoodOfBeingManeuver(ManeuverType.TACK, cluster.stream());
|
||||||
final Bearing approximateMiddleCOG = getWeightedAverageMiddleManeuverCOGDeg(cluster, ManeuverType.TACK);
|
final Bearing approximateMiddleCOG = getWeightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg(cluster, ManeuverType.TACK).getA();
|
||||||
final Bearing approximateMiddleCOGForJibes = approximateMiddleCOG.reverse();
|
|
||||||
// search for the opposite tack cluster by finding the one that has the smallest angular distance to the expected
|
// search for the opposite tack cluster by finding the one that has the smallest angular distance to the expected
|
||||||
// middle COG (same as for the candidate cluster) and expected maneuver angle (the cluster's average maneuver angle with inverted sign)
|
// middle COG (same as for the candidate cluster) and expected maneuver angle (the cluster's average maneuver angle with inverted sign)
|
||||||
final Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble> oppositeTackCluster =
|
final Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble> oppositeTackCluster =
|
||||||
@@ -442,11 +483,29 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl {
|
|||||||
getClusterDistanceBasedOnAverageManeuverLikelihoodAndWeightedAverageMiddleCOG(a, -cluster.getCentroid().getB(), approximateMiddleCOG)-
|
getClusterDistanceBasedOnAverageManeuverLikelihoodAndWeightedAverageMiddleCOG(a, -cluster.getCentroid().getB(), approximateMiddleCOG)-
|
||||||
getClusterDistanceBasedOnAverageManeuverLikelihoodAndWeightedAverageMiddleCOG(b, -cluster.getCentroid().getB(), approximateMiddleCOG))).
|
getClusterDistanceBasedOnAverageManeuverLikelihoodAndWeightedAverageMiddleCOG(b, -cluster.getCentroid().getB(), approximateMiddleCOG))).
|
||||||
orElse(null);
|
orElse(null);
|
||||||
final double likelihoodOfOppositeCluster = getLikelihoodOfOppositeTackCluster(-cluster.getCentroid().getB(), approximateMiddleCOG, oppositeTackCluster);
|
// if the opposite tack cluster is empty, it's pretty unlikely that it's a tack cluster; assign a low default probability of 10%
|
||||||
|
final double likelihoodOfOppositeCluster = oppositeTackCluster.isEmpty() ? 0.1 :
|
||||||
|
getLikelihoodOfClusterBasedOnDistanceFromExpected(-cluster.getCentroid().getB(), approximateMiddleCOG, oppositeTackCluster);
|
||||||
|
// compute weighted averages across the current candidate cluster and its supposed opposite tack cluster where the latter
|
||||||
|
// is weighted by the likelihoodOfOppositeCluster whereas the candidate cluster is always weighed as 1.0 for this purpose
|
||||||
|
final double averageTackingAngleDeg = (Math.abs(getWeightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg(cluster, ManeuverType.TACK).getB()) +
|
||||||
|
likelihoodOfOppositeCluster*Math.abs(getWeightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg(oppositeTackCluster, ManeuverType.TACK).getB()))
|
||||||
|
/ (1+likelihoodOfOppositeCluster);
|
||||||
|
final Bearing averageUpwindCOG = new ScalableBearing(
|
||||||
|
getWeightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg(cluster, ManeuverType.TACK).getA()).add(new ScalableBearing(
|
||||||
|
getWeightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg(oppositeTackCluster, ManeuverType.TACK).getA()).
|
||||||
|
multiply(likelihoodOfOppositeCluster)).divide(1+likelihoodOfOppositeCluster);
|
||||||
|
|
||||||
// TODO search for head-up/bear-away cluster(s) to port and to starboard of cluster's weighted middle COG
|
// Now search for head-up/bear-away cluster(s) to port and to starboard of cluster's weighted middle COG
|
||||||
|
final Bearing expectedUpwindStarboardTackCOG = averageUpwindCOG.add(new DegreeBearingImpl(-averageTackingAngleDeg/2.));
|
||||||
|
double starboardHeadUpBearAwayClusterLikelihood = getLikelihoodOfBestFittingHeadUpBearAwayCluster(
|
||||||
|
clusters.stream().filter(c->c!=cluster), expectedUpwindStarboardTackCOG);
|
||||||
|
final Bearing expectedUpwindPortTackCOG = averageUpwindCOG.add(new DegreeBearingImpl(averageTackingAngleDeg/2.));
|
||||||
|
double portHeadUpBearAwayClusterLikelihood = getLikelihoodOfBestFittingHeadUpBearAwayCluster(
|
||||||
|
clusters.stream().filter(c->c!=cluster), expectedUpwindPortTackCOG);
|
||||||
|
|
||||||
// under the assumption that cluster holds tacks, find the clusters that then most likely hold the jibes
|
// under the assumption that cluster holds tacks, find the clusters that then most likely hold the jibes
|
||||||
|
final Bearing approximateMiddleCOGForJibes = averageUpwindCOG.reverse();
|
||||||
Stream<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>> jibeClusters =
|
Stream<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>> jibeClusters =
|
||||||
getJibeClusters(approximateMiddleCOGForJibes, clusters);
|
getJibeClusters(approximateMiddleCOGForJibes, clusters);
|
||||||
// increase cluster's score if "good" jibe clusters are found; quality is defined by how well the angle matches and how well the speed ratio fits
|
// increase cluster's score if "good" jibe clusters are found; quality is defined by how well the angle matches and how well the speed ratio fits
|
||||||
@@ -455,12 +514,14 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl {
|
|||||||
if (tackClusterWeightedAverageSpeed != null) {
|
if (tackClusterWeightedAverageSpeed != null) {
|
||||||
// find out how likely the speed ratio is between the candidate tack cluster and the corresponding
|
// find out how likely the speed ratio is between the candidate tack cluster and the corresponding
|
||||||
// hypothetical jibe clusters
|
// hypothetical jibe clusters
|
||||||
double tackJibeLikelihoodBasedOnSpeedRatioAndAverageManeuverAngle = getLikelihoodOfBeingJibeCluster(
|
double jibeClusterLikelihood = getLikelihoodOfBeingJibeCluster(
|
||||||
tackClusterWeightedAverageSpeed, jibeClusters.map((jc) -> jc.stream()).reduce(Stream::concat)
|
tackClusterWeightedAverageSpeed, jibeClusters.map((jc) -> jc.stream()).reduce(Stream::concat)
|
||||||
.orElse(Stream.empty()), getBoatClass());
|
.orElse(Stream.empty()), getBoatClass(), clusters);
|
||||||
// Likely jibe clusters may raise the general likelihood by up to 20% of the value so far, but not to over 1.0
|
// Likely jibe clusters may raise the general likelihood by up to 20% of the value so far, but not to over 1.0
|
||||||
result = Math.min(1.0, averageTackLikelihood * likelihoodOfOppositeCluster *
|
result = Math.min(1.0, averageTackLikelihood * likelihoodOfOppositeCluster *
|
||||||
(1.0 + 0.2 * tackJibeLikelihoodBasedOnSpeedRatioAndAverageManeuverAngle));
|
(1.0 + BOOST_FACTOR_FOR_FULL_JIBE_CLUSTER_LIKELIHOOD * jibeClusterLikelihood +
|
||||||
|
BOOST_FACTOR_FOR_FULL_HEAD_UP_BEAR_AWAY_CLUSTER_LIKELIHOOD * starboardHeadUpBearAwayClusterLikelihood +
|
||||||
|
BOOST_FACTOR_FOR_FULL_HEAD_UP_BEAR_AWAY_CLUSTER_LIKELIHOOD * portHeadUpBearAwayClusterLikelihood));
|
||||||
} else {
|
} else {
|
||||||
result = .1; // no elements in the cluster, therefore no average speed; low propability that this would be a tack cluster
|
result = .1; // no elements in the cluster, therefore no average speed; low propability that this would be a tack cluster
|
||||||
}
|
}
|
||||||
@@ -468,28 +529,86 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells how likely it is that the two clusters are opposite tack clusters. This is determined by looking at the
|
* Determines a likelihood for <code>cluster</code> being a head-up/bear-away cluster for the
|
||||||
* {@link #getClusterDistanceBasedOnAverageManeuverLikelihoodAndWeightedAverageMiddleCOG(Cluster, double, Bearing) angular distance}
|
* <code>expectedMiddleCOG</code>.
|
||||||
* between the two clusters regarding their middle COG and their average maneuver angles. The likelihood decreases exponentially
|
*
|
||||||
* with increasing angle differences. It is 1.0 for an exact match and reaches 0.5 for an angular distance of 20deg.
|
* @return a value between 0..1 (exclusive)
|
||||||
|
* @see #getLikelihoodOfClusterBasedOnDistanceFromExpected(double, Bearing, Cluster)
|
||||||
*/
|
*/
|
||||||
private double getLikelihoodOfOppositeTackCluster(
|
private double getLikelihoodOfBestFittingHeadUpBearAwayCluster(
|
||||||
|
Stream<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>> clusters,
|
||||||
|
final Bearing expectedAverageMiddleCOG) {
|
||||||
|
final Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble> starboardTackHeadUpAndBearAwayCluster =
|
||||||
|
clusters.max((a, b)->(int) Math.signum(
|
||||||
|
getLikelihoodOfClusterBasedOnDistanceFromExpected(EXPECTED_AVERAGE_HEAD_UP_AND_BEAR_AWAY_MANEUVER_ANGLE_DEG, expectedAverageMiddleCOG, a)-
|
||||||
|
getLikelihoodOfClusterBasedOnDistanceFromExpected(EXPECTED_AVERAGE_HEAD_UP_AND_BEAR_AWAY_MANEUVER_ANGLE_DEG, expectedAverageMiddleCOG, b))).
|
||||||
|
orElse(null);
|
||||||
|
double starboardHeadUpBearAwayClusterLikelihood = starboardTackHeadUpAndBearAwayCluster == null ? 0.0 :
|
||||||
|
getLikelihoodOfClusterBasedOnDistanceFromExpected(
|
||||||
|
EXPECTED_AVERAGE_HEAD_UP_AND_BEAR_AWAY_MANEUVER_ANGLE_DEG, expectedAverageMiddleCOG, starboardTackHeadUpAndBearAwayCluster);
|
||||||
|
return starboardHeadUpBearAwayClusterLikelihood;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns a likelihood to a cluster based on its
|
||||||
|
* {@link #getClusterDistanceBasedOnAverageManeuverLikelihoodAndWeightedAverageMiddleCOG(Cluster, double, Bearing)
|
||||||
|
* "angular distance"} from an expected average middle COG and Tells how likely it is that the two clusters are opposite tack clusters. This is determined
|
||||||
|
* by looking at the
|
||||||
|
* {@link #getClusterDistanceBasedOnAverageManeuverLikelihoodAndWeightedAverageMiddleCOG(Cluster, double, Bearing)
|
||||||
|
* angular distance} between the two clusters regarding their middle COG and their average maneuver angles. The
|
||||||
|
* likelihood decreases exponentially with increasing angle differences. It is 1.0 for an exact match and reaches
|
||||||
|
* 0.5 for an angular distance of 20deg.
|
||||||
|
*/
|
||||||
|
private double getLikelihoodOfClusterBasedOnDistanceFromExpected(
|
||||||
double expectedManeuverAngleDeg, Bearing expectedApproximateMiddleCOG,
|
double expectedManeuverAngleDeg, Bearing expectedApproximateMiddleCOG,
|
||||||
Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble> oppositeTackCluster) {
|
Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble> oppositeTackCluster) {
|
||||||
return Math.exp(Math.log(0.5) * (getClusterDistanceBasedOnAverageManeuverLikelihoodAndWeightedAverageMiddleCOG(
|
final double clusterDistanceFromExpected = getClusterDistanceBasedOnAverageManeuverLikelihoodAndWeightedAverageMiddleCOG(
|
||||||
oppositeTackCluster, expectedManeuverAngleDeg, expectedApproximateMiddleCOG) / ANGULAR_DISTANCE_FOR_HALF_CONFIDENCE_FOR_OPPOSITE_TACK_CLUSTER_DEG));
|
oppositeTackCluster, expectedManeuverAngleDeg, expectedApproximateMiddleCOG);
|
||||||
|
return getLikelihoodOfClusterBasedOnDistanceFromExpected(clusterDistanceFromExpected);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns a likelihood to a cluster based on its
|
||||||
|
* {@link #getClusterDistanceBasedOnAverageManeuverLikelihoodAndWeightedAverageMiddleCOG(Cluster, double, Bearing)
|
||||||
|
* "angular distance"} from an expected average middle COG and Tells how likely it is that the two clusters are
|
||||||
|
* opposite tack clusters. This is determined by looking at the
|
||||||
|
* {@link #getClusterDistanceBasedOnAverageManeuverLikelihoodAndWeightedAverageMiddleCOG(Cluster, double, Bearing)
|
||||||
|
* angular distance} between the two clusters regarding their middle COG and their average maneuver angles. The
|
||||||
|
* likelihood decreases exponentially with increasing angle differences. It is 1.0 for an exact match and reaches
|
||||||
|
* 0.5 for an angular distance of 20deg (see
|
||||||
|
* {@link #ANGULAR_DISTANCE_FOR_HALF_CONFIDENCE_FOR_OPPOSITE_TACK_CLUSTER_DEG}).
|
||||||
|
*
|
||||||
|
* @param clusterDistanceFromExpected
|
||||||
|
* an angular distance as computed by {@link #getClusterDistance(double, Bearing, double, Bearing)} and
|
||||||
|
* {@link #getClusterDistanceBasedOnAverageManeuverLikelihoodAndWeightedAverageMiddleCOG(Cluster, double, Bearing)}
|
||||||
|
* .
|
||||||
|
*/
|
||||||
|
private double getLikelihoodOfClusterBasedOnDistanceFromExpected(final double clusterDistanceFromExpected) {
|
||||||
|
return Math.exp(Math.log(0.5) * (clusterDistanceFromExpected / ANGULAR_DISTANCE_FOR_HALF_CONFIDENCE_FOR_OPPOSITE_TACK_CLUSTER_DEG));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A euklidian degree distance based on the two degree distances between the maneuver angles and the
|
||||||
|
* middle COGs. The expected pair is passed as <code>expcetedManeuverAngleDeg</code> and <code>expectedApproximateMiddleCOG</code> whereas
|
||||||
|
* the actuals are determined by computing the {@link ManeuverType#TACK}-weighted average for those values from <code>cluster</code>.
|
||||||
|
*/
|
||||||
|
private double getClusterDistanceBasedOnAverageManeuverLikelihoodAndWeightedAverageMiddleCOG(
|
||||||
|
Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble> cluster,
|
||||||
|
double expectedManeuverAngleDeg, Bearing expectedApproximateMiddleCOG) {
|
||||||
|
final Pair<Bearing, Double> weightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg = getWeightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg(cluster, ManeuverType.TACK);
|
||||||
|
final Bearing weightedAverageMiddleCOG = weightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg.getA();
|
||||||
|
final Double weightedAverageManeuverAngle = weightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg.getB();
|
||||||
|
return getClusterDistance(expectedManeuverAngleDeg, expectedApproximateMiddleCOG, weightedAverageManeuverAngle, weightedAverageMiddleCOG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A euklidian degree distance based on the two degree distances between the maneuver angles and the
|
* A euklidian degree distance based on the two degree distances between the maneuver angles and the
|
||||||
* middle COGs.
|
* middle COGs.
|
||||||
*/
|
*/
|
||||||
private double getClusterDistanceBasedOnAverageManeuverLikelihoodAndWeightedAverageMiddleCOG(
|
private double getClusterDistance(double expectedManeuverAngleDeg, Bearing expectedApproximateMiddleCOG,
|
||||||
Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble> cluster,
|
final double weightedAverageManeuverAngle, final Bearing weightedAverageMiddleCOG) {
|
||||||
double expectedManeuverAngleDeg, Bearing expectedApproximateMiddleCOG) {
|
double middleCOGDiff = weightedAverageMiddleCOG.getDifferenceTo(expectedApproximateMiddleCOG).getDegrees();
|
||||||
final Bearing approximateMiddleCOG = getWeightedAverageMiddleManeuverCOGDeg(cluster, ManeuverType.TACK);
|
double maneuverAngleDiff = weightedAverageManeuverAngle - expectedManeuverAngleDeg;
|
||||||
double middleCOGDiff = approximateMiddleCOG.getDifferenceTo(expectedApproximateMiddleCOG).getDegrees();
|
|
||||||
double maneuverAngleDiff = cluster.getCentroid().getB() - expectedManeuverAngleDeg;
|
|
||||||
return Math.sqrt(middleCOGDiff*middleCOGDiff + maneuverAngleDiff*maneuverAngleDiff);
|
return Math.sqrt(middleCOGDiff*middleCOGDiff + maneuverAngleDiff*maneuverAngleDiff);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,7 +627,7 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns at most two clusters that hold maneuvers with the highest average probability of being a jibe and whose
|
* Returns at most two clusters that hold maneuvers with the highest average probability of being a jibe and whose
|
||||||
* {@link #getWeightedAverageMiddleManeuverCOGDeg(Cluster, ManeuverType) weighted average middle COG} fits that of
|
* {@link #getWeightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg(Cluster, ManeuverType) weighted average middle COG} fits that of
|
||||||
* the expected value (<code>approximateMiddleCOGForJibes</code>) within
|
* the expected value (<code>approximateMiddleCOGForJibes</code>) within
|
||||||
* {@link #THRESHOLD_JIBE_CLUSTER_DIFFERENCE_DEGREES} degrees.
|
* {@link #THRESHOLD_JIBE_CLUSTER_DIFFERENCE_DEGREES} degrees.
|
||||||
*/
|
*/
|
||||||
@@ -519,17 +638,17 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl {
|
|||||||
return clusters.stream().sorted((a, b)->
|
return clusters.stream().sorted((a, b)->
|
||||||
(int) -Math.signum(getAverageLikelihoodOfBeingManeuver(ManeuverType.JIBE, a.stream()) -
|
(int) -Math.signum(getAverageLikelihoodOfBeingManeuver(ManeuverType.JIBE, a.stream()) -
|
||||||
getAverageLikelihoodOfBeingManeuver(ManeuverType.JIBE, b.stream()))).filter(
|
getAverageLikelihoodOfBeingManeuver(ManeuverType.JIBE, b.stream()))).filter(
|
||||||
(jibeClusterCandidate)->Math.abs(getWeightedAverageMiddleManeuverCOGDeg(jibeClusterCandidate, ManeuverType.JIBE).
|
(jibeClusterCandidate)->Math.abs(getWeightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg(jibeClusterCandidate, ManeuverType.JIBE).getA().
|
||||||
getDifferenceTo(approximateMiddleCOGForJibes).getDegrees()) < THRESHOLD_JIBE_CLUSTER_DIFFERENCE_DEGREES).
|
getDifferenceTo(approximateMiddleCOGForJibes).getDegrees()) < THRESHOLD_JIBE_CLUSTER_DIFFERENCE_DEGREES).
|
||||||
limit(2);
|
limit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* By looking at the weighted speeds over ground averages, and based on the {@link #polarService} determines how
|
* By looking at the weighted speeds over ground averages, and based on the {@link #polarService} determines how
|
||||||
* likely it is that the jibe cluster contents are actually jibes. This is based on the idea that if for the most
|
* {@link PolarDataService#getManeuverLikelihoodAndTwsTwa(BoatClass, Speed, double, ManeuverType) likely} it is that
|
||||||
* likely wind speeds the jibes have a different (usually significantly higher) entry speed than the tacks then this
|
* the jibe cluster contents are actually jibes. This is based on the idea that if for the most likely wind speeds
|
||||||
* difference show show in the cluster elements. If they don't, then this should give a penalty for the cluster
|
* the jibes have a different (usually significantly higher) entry speed than the tacks then this difference should
|
||||||
* likelihoods.
|
* show in the cluster elements. If they don't, then this should give a penalty for the cluster likelihoods.
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* The weight of a maneuver for computing the weighted speed average is determined to be the
|
* The weight of a maneuver for computing the weighted speed average is determined to be the
|
||||||
@@ -539,26 +658,48 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl {
|
|||||||
private double getLikelihoodOfBeingJibeCluster(
|
private double getLikelihoodOfBeingJibeCluster(
|
||||||
Speed tackClusterWeightedAverageSpeed,
|
Speed tackClusterWeightedAverageSpeed,
|
||||||
Stream<ManeuverClassification> jibeClustersContent,
|
Stream<ManeuverClassification> jibeClustersContent,
|
||||||
BoatClass boatClass) {
|
BoatClass boatClass, Set<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>> clusters) {
|
||||||
final int[] count = new int[1];
|
final int[] count = new int[1];
|
||||||
final double[] likelihoodSum = new double[1];
|
final double[] likelihoodSum = new double[1];
|
||||||
|
final ScalableBearing[] scaledAverageDownwindCOG = new ScalableBearing[1];
|
||||||
|
final double[] scaledAbsJibingAngleSum = new double[1];
|
||||||
Stream<ManeuverClassification> jibeClustersContentPeeker = jibeClustersContent.peek((mc)->{
|
Stream<ManeuverClassification> jibeClustersContentPeeker = jibeClustersContent.peek((mc)->{
|
||||||
count[0]++;
|
count[0]++;
|
||||||
likelihoodSum[0] += mc.getLikelihoodAndTWSBasedOnSpeedAndAngle(ManeuverType.JIBE).getA();
|
final double likelihood = mc.getLikelihoodAndTWSBasedOnSpeedAndAngle(ManeuverType.JIBE).getA();
|
||||||
|
likelihoodSum[0] += likelihood;
|
||||||
|
final ScalableBearing scaledCOG = new ScalableBearing(mc.getMiddleManeuverCourse()).multiply(likelihood);
|
||||||
|
if (scaledAverageDownwindCOG[0] == null) {
|
||||||
|
scaledAverageDownwindCOG[0] = scaledCOG;
|
||||||
|
} else {
|
||||||
|
scaledAverageDownwindCOG[0] = scaledAverageDownwindCOG[0].add(scaledCOG);
|
||||||
|
}
|
||||||
|
scaledAbsJibingAngleSum[0] += likelihood * Math.abs(mc.getManeuverAngleDeg());
|
||||||
});
|
});
|
||||||
Speed jibeClusterWeightedAverageSpeed = getWeightedAverageSpeed(jibeClustersContentPeeker, ManeuverType.JIBE);
|
Speed jibeClusterWeightedAverageSpeed = getWeightedAverageSpeed(jibeClustersContentPeeker, ManeuverType.JIBE);
|
||||||
|
Bearing averageDownwindCOG = scaledAverageDownwindCOG[0] == null ? null : scaledAverageDownwindCOG[0].divide(likelihoodSum[0]);
|
||||||
|
double absWeightedAverageJibingAbgle = scaledAbsJibingAngleSum[0] / likelihoodSum[0];
|
||||||
final double result;
|
final double result;
|
||||||
if (jibeClusterWeightedAverageSpeed != null) {
|
if (jibeClusterWeightedAverageSpeed != null) {
|
||||||
double tackJibeSpeedRatioLikelihood = polarService.getConfidenceForTackJibeSpeedRatio(
|
double tackJibeSpeedRatioLikelihood = polarService.getConfidenceForTackJibeSpeedRatio(
|
||||||
tackClusterWeightedAverageSpeed, jibeClusterWeightedAverageSpeed, boatClass);
|
tackClusterWeightedAverageSpeed, jibeClusterWeightedAverageSpeed, boatClass);
|
||||||
if (count[0] > 0) {
|
if (count[0] > 0) {
|
||||||
double averageJibeLikelihood = likelihoodSum[0] / count[0];
|
double averageJibeLikelihood = likelihoodSum[0] / count[0];
|
||||||
result = averageJibeLikelihood * tackJibeSpeedRatioLikelihood;
|
// Now search for head-up/bear-away cluster(s) to port and to starboard of cluster's weighted middle COG
|
||||||
|
final Bearing expectedDownwindStarboardTackCOG = averageDownwindCOG.add(new DegreeBearingImpl(+absWeightedAverageJibingAbgle/2.));
|
||||||
|
double starboardHeadUpBearAwayClusterLikelihood = getLikelihoodOfBestFittingHeadUpBearAwayCluster(
|
||||||
|
clusters.stream(), expectedDownwindStarboardTackCOG);
|
||||||
|
final Bearing expectedDownwindPortTackCOG = averageDownwindCOG.add(new DegreeBearingImpl(-absWeightedAverageJibingAbgle/2.));
|
||||||
|
double portHeadUpBearAwayClusterLikelihood = getLikelihoodOfBestFittingHeadUpBearAwayCluster(
|
||||||
|
clusters.stream(), expectedDownwindPortTackCOG);
|
||||||
|
result = Math.min(1.0, averageJibeLikelihood
|
||||||
|
* (1.0 + BOOST_FACTOR_FOR_JIBE_TACK_SPEED_RATIO_LIKELIHOOD * tackJibeSpeedRatioLikelihood +
|
||||||
|
BOOST_FACTOR_FOR_FULL_HEAD_UP_BEAR_AWAY_CLUSTER_LIKELIHOOD * starboardHeadUpBearAwayClusterLikelihood +
|
||||||
|
BOOST_FACTOR_FOR_FULL_HEAD_UP_BEAR_AWAY_CLUSTER_LIKELIHOOD * portHeadUpBearAwayClusterLikelihood));
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Internal error: no maneuvers in jibe cluster candidate but still a valid weighted average speed "+jibeClusterWeightedAverageSpeed);
|
throw new RuntimeException("Internal error: no maneuvers in jibe cluster candidate but still a valid weighted average speed "+jibeClusterWeightedAverageSpeed);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = 0.5; // no maneuvers in the jibe clusters; could be but may also not be a jibe cluster
|
result = 0.1; // no maneuvers in the jibe clusters; could be but may also not be a jibe cluster
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -606,28 +747,35 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* For a cluster of maneuver classifications, clustered two-dimensionally by middle COG and maneuver angle, computes the
|
* For a cluster of maneuver classifications, clustered two-dimensionally by middle COG and maneuver angle, computes the
|
||||||
* weighted average of the middle COG where as the weight of each maneuver the likelihood that the maneuver was of type
|
* weighted average of the middle COG and maneuver angle where as the weight of each maneuver the likelihood that the maneuver was of type
|
||||||
* <code>maneuverType</code> is used.<p>
|
* <code>maneuverType</code> is used.<p>
|
||||||
*
|
*
|
||||||
* The method has default package scope to allow tests in the same package in the test fragment to use it.
|
* The method has default package scope to allow tests in the same package in the test fragment to use it.
|
||||||
*
|
*
|
||||||
* @return the weighted average middle COG
|
* @return the weighted average middle COG
|
||||||
*/
|
*/
|
||||||
Bearing getWeightedAverageMiddleManeuverCOGDeg(
|
Pair<Bearing, Double> getWeightedAverageMiddleManeuverCOGDegAndManeuverAngleDeg(
|
||||||
Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble> cluster,
|
Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble> cluster,
|
||||||
ManeuverType maneuverType) {
|
ManeuverType maneuverType) {
|
||||||
Pair<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>, ManeuverType> key = new Pair<>(
|
Pair<Cluster<ManeuverClassification, Pair<ScalableBearing, ScalableDouble>, Pair<Bearing, Double>, ScalableBearingAndScalableDouble>, ManeuverType> key = new Pair<>(
|
||||||
cluster, maneuverType);
|
cluster, maneuverType);
|
||||||
Bearing result = weightedAverageMiddleCOGForManeuverType.get(key);
|
Pair<Bearing, Double> result = weightedAverageMiddleCOGForManeuverType.get(key);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
ConfidenceBasedAverager<DoublePair, Bearing, Void> averager = ConfidenceFactory.INSTANCE
|
ConfidenceBasedAverager<DoublePair, Bearing, Void> middleCOGAverager = ConfidenceFactory.INSTANCE
|
||||||
.createAverager(/* weigher */null);
|
.createAverager(/* weigher */null);
|
||||||
HasConfidence<DoublePair, Bearing, Void> average = averager.getAverage(
|
HasConfidence<DoublePair, Bearing, Void> average = middleCOGAverager.getAverage(
|
||||||
cluster.stream()
|
cluster.stream()
|
||||||
.map(new ManeuverClassificationToHasConfidenceAndIsScalableAdapter<DoublePair, Bearing>(
|
.map(new ManeuverClassificationToHasConfidenceAndIsScalableAdapter<DoublePair, Bearing>(
|
||||||
maneuverType, (mc) -> new ScalableBearing(mc.getMiddleManeuverCourse()),
|
maneuverType, (mc) -> new ScalableBearing(mc.getMiddleManeuverCourse()),
|
||||||
polarService)).iterator(), /* at */null);
|
polarService)).iterator(), /* at */null);
|
||||||
result = average.getObject();
|
ConfidenceBasedAverager<Double, Double, Void> maneuverAngleAverager = ConfidenceFactory.INSTANCE
|
||||||
|
.createAverager(/* weigher */null);
|
||||||
|
HasConfidence<Double, Double, Void> maneuverAngleAverageDeg = maneuverAngleAverager.getAverage(
|
||||||
|
cluster.stream()
|
||||||
|
.map(new ManeuverClassificationToHasConfidenceAndIsScalableAdapter<Double, Double>(
|
||||||
|
maneuverType, (mc) -> new ScalableDouble(mc.getManeuverAngleDeg()),
|
||||||
|
polarService)).iterator(), /* at */null);
|
||||||
|
result = new Pair<>(average.getObject(), maneuverAngleAverageDeg.getObject());
|
||||||
weightedAverageMiddleCOGForManeuverType.put(key, result);
|
weightedAverageMiddleCOGForManeuverType.put(key, result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="src" path="resources"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
||||||
Executable
+28
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>com.sap.sailing.xmlexport.test</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.pde.PluginNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||||
|
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.8
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
pluginProject.extensions=false
|
||||||
|
resolve.requirebundle=false
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Bundle-ManifestVersion: 2
|
||||||
|
Bundle-Name: Test
|
||||||
|
Bundle-SymbolicName: com.sap.sailing.xmlexport.test
|
||||||
|
Bundle-Version: 1.0.0.qualifier
|
||||||
|
Bundle-Vendor: SAP
|
||||||
|
Fragment-Host: com.sap.sailing.xmlexport
|
||||||
|
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||||
|
Require-Bundle: org.junit4;bundle-version="4.8.2",
|
||||||
|
com.sap.sse.common,
|
||||||
|
com.sap.sailing.domain.test;bundle-version="1.0.0",
|
||||||
|
com.tractrac.clientmodule;bundle-version="3.0.7"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
source.. = src/,\
|
||||||
|
resources/
|
||||||
|
output.. = bin/
|
||||||
|
bin.includes = META-INF/,\
|
||||||
|
.
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<artifactId>root</artifactId>
|
||||||
|
<groupId>com.sap.sailing</groupId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>com.sap.sailing.xmlexport.test</artifactId>
|
||||||
|
<packaging>eclipse-test-plugin</packaging>
|
||||||
|
</project>
|
||||||
Binary file not shown.
@@ -0,0 +1,643 @@
|
|||||||
|
stored-uri:event_20141001_ESSNice-Race_1.mtb
|
||||||
|
StartReplay:1
|
||||||
|
|
||||||
|
// Input from params_static:
|
||||||
|
|
||||||
|
// Input from event_parameters:
|
||||||
|
|
||||||
|
DefaultPanel:
|
||||||
|
ReCalcDirAndSpeed:1
|
||||||
|
CompMarkerUUID:2dee0384-2c45-11e4-a9f6-14dae9614d7b
|
||||||
|
CodanIsSponsor:0
|
||||||
|
DefaultTailLength:60
|
||||||
|
APzoomChangeTime:2500
|
||||||
|
disableAutoProduce:0
|
||||||
|
autoProduce:0
|
||||||
|
APstartLineShowOfLeg:0.25
|
||||||
|
APsideOfStartLine:0.30
|
||||||
|
APstartSwitch:0.8
|
||||||
|
APwholeLegBehindMarks:0.15
|
||||||
|
APmarkSwitch:0.13
|
||||||
|
APmarkZoomBehindMarks:0.10
|
||||||
|
APmarkZoomInFrontOfMarks:0.20
|
||||||
|
PopupMarkerUUID:84199024-2c45-11e4-a9f6-14dae9614d7b
|
||||||
|
ManualUrl:http://www.tractrac.com/files/userguide_sailing.pdf
|
||||||
|
//live-uri:tcp://192.168.1.203:4400
|
||||||
|
//stored-uri:tcp://192.168.1.203:4401
|
||||||
|
Marker1UUID:2dee0384-2c45-11e4-a9f6-14dae9614d7b
|
||||||
|
Marker1Type:RGBMarkerFactory
|
||||||
|
Marker1Directional:1
|
||||||
|
Marker1Image:markers/boat_FF0000_big.png
|
||||||
|
Marker1Length:5
|
||||||
|
Marker1MinPixelSize:30
|
||||||
|
Startlocation:7.269026586914038,43.68669104379883
|
||||||
|
MaxDiffTime:1200
|
||||||
|
MaxMetersPerSecond:20
|
||||||
|
PrecisionMeters:20
|
||||||
|
ShortAvgTime:180
|
||||||
|
LongAvgTime:900
|
||||||
|
TimeZone:2
|
||||||
|
CompMarkerTimeout:60
|
||||||
|
FramesPerSecond:8
|
||||||
|
replayspeedup:5
|
||||||
|
MatchRaceClock:0
|
||||||
|
MatchRaceClockNo:3
|
||||||
|
MatchRaceClockSpacing:300
|
||||||
|
Minimap:1
|
||||||
|
MinimapUseLayers:2
|
||||||
|
Minimapgeorect:7.241326904296898,43.705766636035165,7.296516491699208,43.67209091170523
|
||||||
|
MinimapMarkerUUID:84199024-2c45-11e4-a9f6-14dae9614d7b
|
||||||
|
Marker4UUID:84199024-2c45-11e4-a9f6-14dae9614d7b
|
||||||
|
Marker4Type:RGBmarkerFactory
|
||||||
|
Marker4Directional:1
|
||||||
|
Marker4Image:markers/boat_FF0000_small.png
|
||||||
|
MetersPerPixel:18
|
||||||
|
MetersPerPixelMax:30
|
||||||
|
MetersPerPixelMin:0.2
|
||||||
|
isMatchRace:0
|
||||||
|
DefaultDistanceUnits:meters
|
||||||
|
weatherEnabled:0
|
||||||
|
DefaultSpeedUnits:KmH
|
||||||
|
showRaceClock:1
|
||||||
|
BackGroundImage:graphics/background.jpg
|
||||||
|
DisableRotation:0
|
||||||
|
ControlPointMarkerRadius:13
|
||||||
|
disableselection:0
|
||||||
|
disableleaderline:0
|
||||||
|
DisableChangeRace:0
|
||||||
|
PopUpRow1Name:
|
||||||
|
PopUpRow1Type:Name
|
||||||
|
PopUpRow2Name:Knots
|
||||||
|
PopUpRow2Type:BoatSpeed
|
||||||
|
PopUpRow3Name:Ranking
|
||||||
|
PopUpRow3Type:RowNumber
|
||||||
|
PopUpRow4Name:Sail
|
||||||
|
PopUpRow4Type:Ini
|
||||||
|
PopUpRow5Name:After
|
||||||
|
PopUpRow5Type:BoatAfter
|
||||||
|
WindEstimator:0
|
||||||
|
MapUrl:http://tile.traclive.dk/ttm
|
||||||
|
ResultColumn1Name:#
|
||||||
|
ResultColumn1Size:20
|
||||||
|
ResultColumn1Type:RowNumber
|
||||||
|
ResultColumn2Name:sail
|
||||||
|
ResultColumn2Size:45
|
||||||
|
ResultColumn2Type:Ini
|
||||||
|
ResultColumn3Name:name
|
||||||
|
ResultColumn3Size:110
|
||||||
|
ResultColumn3Type:Name
|
||||||
|
ResultColumn4Name:after
|
||||||
|
ResultColumn4Size:45
|
||||||
|
ResultColumn4Type:BoatAfter
|
||||||
|
ResultColumn5Name:kts
|
||||||
|
ResultColumn5Size:40
|
||||||
|
ResultColumn5Type:BoatSpeed
|
||||||
|
DisableLeaderboard:0
|
||||||
|
DisableAnalysis:0
|
||||||
|
TableFontSize:11
|
||||||
|
compInitialsFontSize:11
|
||||||
|
AutoRotate:0
|
||||||
|
MassStart:0
|
||||||
|
SegmentFile:segments.php
|
||||||
|
StartType:Mass
|
||||||
|
RaceHandicapSystem:NONE
|
||||||
|
TeamCompetitionType:NONE
|
||||||
|
LiveDelaySecs: 6
|
||||||
|
|
||||||
|
//-------- AUTO GENERATED PARAMETERS START ----------------
|
||||||
|
|
||||||
|
EventID:8638bc00-2aad-0132-18bc-448a5b8481d8
|
||||||
|
EventName:ESS Nice 2014
|
||||||
|
EventDB:event_20141001_ESSNice
|
||||||
|
EventStartTime:2014-09-30 22:00:00
|
||||||
|
EventEndTime:2014-10-05 21:00:00
|
||||||
|
EventType:a1b74ca0-fdd8-11dc-8811-005056c00008
|
||||||
|
|
||||||
|
RaceID:09f4b690-2bc6-0132-1eef-10b11c4ed8fd
|
||||||
|
RaceName:Race 1
|
||||||
|
RaceStartTime:2014-10-02 12:02:00
|
||||||
|
RaceEndTime:
|
||||||
|
RaceTrackingStartTime:2014-10-02 11:58:14
|
||||||
|
RaceTrackingEndTime:2014-10-02 12:17:02
|
||||||
|
RaceDefaultRouteUUID:09f125d0-2bc6-0132-1eee-10b11c4ed8fd
|
||||||
|
RaceHandicapSystem:NONE
|
||||||
|
|
||||||
|
Image1UUID:64a7b348-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Image1Type:Logo
|
||||||
|
Image1Description:http://germanmaster.traclive.dk/events/event_20100806_SailforGol/images/SUI.gif
|
||||||
|
Image1Image:http://germanmaster.traclive.dk/events/event_20100806_SailforGol/images/SUI.gif
|
||||||
|
|
||||||
|
Image2UUID:64c3a8fa-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Image2Type:Logo
|
||||||
|
Image2Description:http://germanmaster.traclive.dk/events/event_20100806_SailforGol/images/NZL.gif
|
||||||
|
Image2Image:http://germanmaster.traclive.dk/events/event_20100806_SailforGol/images/NZL.gif
|
||||||
|
|
||||||
|
Image3UUID:651130a2-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Image3Type:Logo
|
||||||
|
Image3Description:http://germanmaster.traclive.dk/events/event_20100806_SailforGol/images/KOR.gif
|
||||||
|
Image3Image:http://germanmaster.traclive.dk/events/event_20100806_SailforGol/images/KOR.gif
|
||||||
|
|
||||||
|
Image4UUID:653c1ab0-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Image4Type:Logo
|
||||||
|
Image4Description:http://germanmaster.traclive.dk/events/event_20100806_SailforGol/images/AUT.gif
|
||||||
|
Image4Image:http://germanmaster.traclive.dk/events/event_20100806_SailforGol/images/AUT.gif
|
||||||
|
|
||||||
|
Image5UUID:65637da8-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Image5Type:Logo
|
||||||
|
Image5Description:http://germanmaster.traclive.dk/events/event_20100806_SailforGol/images/DEN.gif
|
||||||
|
Image5Image:http://germanmaster.traclive.dk/events/event_20100806_SailforGol/images/DEN.gif
|
||||||
|
|
||||||
|
Image6UUID:65875138-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Image6Type:Logo
|
||||||
|
Image6Description:http://germanmaster.traclive.dk/events/event_20100806_SailforGol/images/OMN.gif
|
||||||
|
Image6Image:http://germanmaster.traclive.dk/events/event_20100806_SailforGol/images/OMN.gif
|
||||||
|
|
||||||
|
Class1UUID:648ee25a-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Class1Name:Extreme40
|
||||||
|
|
||||||
|
Team1UUID:649f1dbe-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Team1Name:TeamA
|
||||||
|
Team1Comp1UUID:648bd4f2-83db-11e2-88c0-10bf48d758ce
|
||||||
|
|
||||||
|
Team2UUID:64bf0854-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Team2Name:TeamB
|
||||||
|
Team2Comp1UUID:64bbff7e-83db-11e2-88c0-10bf48d758ce
|
||||||
|
|
||||||
|
Team3UUID:64dd7988-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Team3Name:TeamC
|
||||||
|
Team3Comp1UUID:64da7c24-83db-11e2-88c0-10bf48d758ce
|
||||||
|
|
||||||
|
Team4UUID:64ffc402-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Team4Name:TeamD
|
||||||
|
|
||||||
|
Team5UUID:65351d82-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Team5Name:TeamE
|
||||||
|
Team5Comp1UUID:65322500-83db-11e2-88c0-10bf48d758ce
|
||||||
|
|
||||||
|
Team6UUID:655ed82a-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Team6Name:TeamF
|
||||||
|
Team6Comp1UUID:655bd56c-83db-11e2-88c0-10bf48d758ce
|
||||||
|
|
||||||
|
Team7UUID:65829fa8-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Team7Name:TeamG
|
||||||
|
Team7Comp1UUID:657fa5a0-83db-11e2-88c0-10bf48d758ce
|
||||||
|
|
||||||
|
Team8UUID:e4459a20-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Team8Name:TeamH
|
||||||
|
|
||||||
|
Team9UUID:a73aabc0-d6d6-0130-8be2-60a44ce903c3
|
||||||
|
Team9Name:TeamI
|
||||||
|
Team9Comp1UUID:93085e80-7ad9-0131-e5b3-60a44ce903c3
|
||||||
|
|
||||||
|
Team10UUID:bbf81f60-d6d6-0130-8be3-60a44ce903c3
|
||||||
|
Team10Name:TeamJ
|
||||||
|
Team10Comp1UUID:f097f4f0-7ad9-0131-e5b4-60a44ce903c3
|
||||||
|
|
||||||
|
Team11UUID:65659280-eda3-0130-c5c0-10b11c4ed8fd
|
||||||
|
Team11Name:TeamK
|
||||||
|
Team11Comp1UUID:19dc3eb0-7ada-0131-e5b5-60a44ce903c3
|
||||||
|
|
||||||
|
Team12UUID:9ee14560-77af-0131-e5af-60a44ce903c3
|
||||||
|
Team12Name:TeamL
|
||||||
|
Team12Comp1UUID:5e15e7c0-7ada-0131-e5b6-60a44ce903c3
|
||||||
|
|
||||||
|
Team13UUID:b9677300-7ad7-0131-e5b0-60a44ce903c3
|
||||||
|
Team13Name:TeamM
|
||||||
|
Team13Comp1UUID:84e68b70-7ada-0131-e5b7-60a44ce903c3
|
||||||
|
|
||||||
|
Team14UUID:c9689a00-7ad7-0131-e5b1-60a44ce903c3
|
||||||
|
Team14Name:TeamN
|
||||||
|
|
||||||
|
Team15UUID:d5712f30-7ad7-0131-e5b2-60a44ce903c3
|
||||||
|
Team15Name:TeamO
|
||||||
|
|
||||||
|
Comp1UUID:648bd4f2-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp1Name:Alinghi
|
||||||
|
Comp1NameShort:Alinghi
|
||||||
|
Comp1Color:00FF00
|
||||||
|
Comp1Nationality:SUI
|
||||||
|
Comp1Description:
|
||||||
|
Comp1Handicap:1.0000000000
|
||||||
|
Comp1HandicapDistance:0.00000
|
||||||
|
Comp1StartTime:2014-10-02 12:02:00
|
||||||
|
Comp1PictureUUID:64a7b348-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp1ClassUUID:648ee25a-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp1RouteUUID:09f125d0-2bc6-0132-1eee-10b11c4ed8fd
|
||||||
|
|
||||||
|
Comp2UUID:64bbff7e-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp2Name:GAC Pindar
|
||||||
|
Comp2NameShort:GAC Pindar
|
||||||
|
Comp2Color:000080
|
||||||
|
Comp2Nationality:AUS
|
||||||
|
Comp2Description:
|
||||||
|
Comp2Handicap:1.0000000000
|
||||||
|
Comp2HandicapDistance:0.00000
|
||||||
|
Comp2StartTime:2014-10-02 12:02:00
|
||||||
|
Comp2PictureUUID:64c3a8fa-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp2ClassUUID:648ee25a-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp2RouteUUID:09f125d0-2bc6-0132-1eee-10b11c4ed8fd
|
||||||
|
|
||||||
|
Comp3UUID:64da7c24-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp3Name:Realteam by Realstone
|
||||||
|
Comp3NameShort:Realstone
|
||||||
|
Comp3Color:000000
|
||||||
|
Comp3Nationality:AFG
|
||||||
|
Comp3Description:
|
||||||
|
Comp3Handicap:1.0000000000
|
||||||
|
Comp3HandicapDistance:0.00000
|
||||||
|
Comp3StartTime:2014-10-02 12:02:00
|
||||||
|
Comp3PictureUUID:64a7b348-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp3ClassUUID:648ee25a-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp3RouteUUID:09f125d0-2bc6-0132-1eee-10b11c4ed8fd
|
||||||
|
|
||||||
|
Comp4UUID:65322500-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp4Name:Red Bull Sailing Team
|
||||||
|
Comp4NameShort:Red Bull
|
||||||
|
Comp4Color:008080
|
||||||
|
Comp4Nationality:AUT
|
||||||
|
Comp4Description:
|
||||||
|
Comp4Handicap:1.0000000000
|
||||||
|
Comp4HandicapDistance:0.00000
|
||||||
|
Comp4StartTime:2014-10-02 12:02:00
|
||||||
|
Comp4PictureUUID:653c1ab0-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp4ClassUUID:648ee25a-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp4RouteUUID:09f125d0-2bc6-0132-1eee-10b11c4ed8fd
|
||||||
|
|
||||||
|
Comp5UUID:655bd56c-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp5Name:SAP Extreme Sailing Team
|
||||||
|
Comp5NameShort:SAP
|
||||||
|
Comp5Color:FFFFFF
|
||||||
|
Comp5Nationality:DEN
|
||||||
|
Comp5Description:
|
||||||
|
Comp5Handicap:1.0000000000
|
||||||
|
Comp5HandicapDistance:0.00000
|
||||||
|
Comp5StartTime:2014-10-02 12:02:00
|
||||||
|
Comp5PictureUUID:65637da8-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp5ClassUUID:648ee25a-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp5RouteUUID:09f125d0-2bc6-0132-1eee-10b11c4ed8fd
|
||||||
|
|
||||||
|
Comp6UUID:657fa5a0-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp6Name:The Wave, Muscat
|
||||||
|
Comp6NameShort:The Wave
|
||||||
|
Comp6Color:800080
|
||||||
|
Comp6Nationality:OMA
|
||||||
|
Comp6Description:
|
||||||
|
Comp6Handicap:1.0000000000
|
||||||
|
Comp6HandicapDistance:0.00000
|
||||||
|
Comp6StartTime:2014-10-02 12:02:00
|
||||||
|
Comp6PictureUUID:65875138-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp6ClassUUID:648ee25a-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp6RouteUUID:09f125d0-2bc6-0132-1eee-10b11c4ed8fd
|
||||||
|
|
||||||
|
Comp7UUID:93085e80-7ad9-0131-e5b3-60a44ce903c3
|
||||||
|
Comp7Name:Emirates Team New Zealand
|
||||||
|
Comp7NameShort:Emirates NZ
|
||||||
|
Comp7Color:CC9900
|
||||||
|
Comp7Nationality:NZL
|
||||||
|
Comp7Description:
|
||||||
|
Comp7Handicap:1.0000000000
|
||||||
|
Comp7HandicapDistance:0.00000
|
||||||
|
Comp7StartTime:2014-10-02 12:02:00
|
||||||
|
Comp7PictureUUID:64c3a8fa-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp7ClassUUID:648ee25a-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp7RouteUUID:09f125d0-2bc6-0132-1eee-10b11c4ed8fd
|
||||||
|
|
||||||
|
Comp8UUID:f097f4f0-7ad9-0131-e5b4-60a44ce903c3
|
||||||
|
Comp8Name:Gazprom Team Russia
|
||||||
|
Comp8NameShort:Team Russia
|
||||||
|
Comp8Color:999900
|
||||||
|
Comp8Nationality:RUS
|
||||||
|
Comp8Description:
|
||||||
|
Comp8Handicap:1.0000000000
|
||||||
|
Comp8HandicapDistance:0.00000
|
||||||
|
Comp8StartTime:2014-10-02 12:02:00
|
||||||
|
Comp8ClassUUID:648ee25a-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp8RouteUUID:09f125d0-2bc6-0132-1eee-10b11c4ed8fd
|
||||||
|
|
||||||
|
Comp9UUID:19dc3eb0-7ada-0131-e5b5-60a44ce903c3
|
||||||
|
Comp9Name:Groupama sailing team
|
||||||
|
Comp9NameShort:Groupama
|
||||||
|
Comp9Color:33CC00
|
||||||
|
Comp9Nationality:AFG
|
||||||
|
Comp9Description:
|
||||||
|
Comp9Handicap:1.0000000000
|
||||||
|
Comp9HandicapDistance:0.00000
|
||||||
|
Comp9StartTime:2014-10-02 12:02:00
|
||||||
|
Comp9ClassUUID:648ee25a-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp9RouteUUID:09f125d0-2bc6-0132-1eee-10b11c4ed8fd
|
||||||
|
|
||||||
|
Comp10UUID:5e15e7c0-7ada-0131-e5b6-60a44ce903c3
|
||||||
|
Comp10Name:J.P. Morgan BAR
|
||||||
|
Comp10NameShort:J.P. Morgan
|
||||||
|
Comp10Color:CCFF00
|
||||||
|
Comp10Nationality:GBR
|
||||||
|
Comp10Description:
|
||||||
|
Comp10Handicap:1.0000000000
|
||||||
|
Comp10HandicapDistance:0.00000
|
||||||
|
Comp10StartTime:2014-10-02 12:02:00
|
||||||
|
Comp10ClassUUID:648ee25a-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp10RouteUUID:09f125d0-2bc6-0132-1eee-10b11c4ed8fd
|
||||||
|
|
||||||
|
Comp11UUID:84e68b70-7ada-0131-e5b7-60a44ce903c3
|
||||||
|
Comp11Name:Oman Air
|
||||||
|
Comp11NameShort:Oman Air
|
||||||
|
Comp11Color:CCFF99
|
||||||
|
Comp11Nationality:OMA
|
||||||
|
Comp11Description:
|
||||||
|
Comp11Handicap:1.0000000000
|
||||||
|
Comp11HandicapDistance:0.00000
|
||||||
|
Comp11StartTime:2014-10-02 12:02:00
|
||||||
|
Comp11PictureUUID:65875138-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp11ClassUUID:648ee25a-83db-11e2-88c0-10bf48d758ce
|
||||||
|
Comp11RouteUUID:09f125d0-2bc6-0132-1eee-10b11c4ed8fd
|
||||||
|
|
||||||
|
ControlPoint1UUID:1100ea60-7adb-0131-e5b8-60a44ce903c3
|
||||||
|
ControlPoint1Name:Red-Green
|
||||||
|
ControlPoint1HasTwoPoints:1
|
||||||
|
ControlPoint1ShortName:RG
|
||||||
|
ControlPoint1DataSheet:P1.Type=Buoy###BREAKLINE###P1.Color=Red###BREAKLINE###P1.Shape=Conical###BREAKLINE###P1.Name=Red###BREAKLINE###P1.UUID=5427c7d2-83be-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=Green###BREAKLINE###P2.Shape=Conical###BREAKLINE###P2.Name=Green###BREAKLINE###P2.UUID=785c3e44-83be-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint1Mark1Lon:7.273181
|
||||||
|
ControlPoint1Mark1Lat:43.688370
|
||||||
|
ControlPoint1Mark2Lon:7.272257
|
||||||
|
ControlPoint1Mark2Lat:43.687305
|
||||||
|
|
||||||
|
ControlPoint2UUID:1286f15e-83be-11e2-88c0-10bf48d758ce
|
||||||
|
ControlPoint2Name:Blue
|
||||||
|
ControlPoint2HasTwoPoints:0
|
||||||
|
ControlPoint2ShortName:Bl
|
||||||
|
ControlPoint2DataSheet:Name=Blue###BREAKLINE###Type=Buoy###BREAKLINE###Color=Blue###BREAKLINE###Shape=Conical
|
||||||
|
ControlPoint2Mark1Lon:7.269418
|
||||||
|
ControlPoint2Mark1Lat:43.687290
|
||||||
|
|
||||||
|
ControlPoint3UUID:1a94c6a0-7adc-0131-e5f4-60a44ce903c3
|
||||||
|
ControlPoint3Name:Black Conical-Blue
|
||||||
|
ControlPoint3HasTwoPoints:1
|
||||||
|
ControlPoint3ShortName:BB
|
||||||
|
ControlPoint3DataSheet:P1.Type=Buoy###BREAKLINE###P1.Color=Black###BREAKLINE###P1.Shape=Conical###BREAKLINE###P1.Pattern=Checkered###BREAKLINE###P1.Name=Black Conical###BREAKLINE###P1.UUID=d78695ea-83be-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=Blue###BREAKLINE###P2.Shape=Conical###BREAKLINE###P2.Name=Blue###BREAKLINE###P2.UUID=1286f15e-83be-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint3Mark1Lon:7.272432
|
||||||
|
ControlPoint3Mark1Lat:43.692131
|
||||||
|
ControlPoint3Mark2Lon:7.269418
|
||||||
|
ControlPoint3Mark2Lat:43.687290
|
||||||
|
|
||||||
|
ControlPoint4UUID:2ce99970-2c47-0132-20ce-10b11c4ed8fd
|
||||||
|
ControlPoint4Name:Black Conical-White P
|
||||||
|
ControlPoint4HasTwoPoints:1
|
||||||
|
ControlPoint4ShortName:F
|
||||||
|
ControlPoint4DataSheet:P1.Type=Buoy###BREAKLINE###P1.Color=Black###BREAKLINE###P1.Shape=Conical###BREAKLINE###P1.Pattern=Checkered###BREAKLINE###P1.Name=Black Conical###BREAKLINE###P1.UUID=d78695ea-83be-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=White###BREAKLINE###P2.Shape=Conical###BREAKLINE###P2.Name=White P###BREAKLINE###P2.UUID=e9ec42f8-83bd-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint4Mark1Lon:7.272432
|
||||||
|
ControlPoint4Mark1Lat:43.692131
|
||||||
|
ControlPoint4Mark2Lon:7.271063
|
||||||
|
ControlPoint4Mark2Lat:43.691803
|
||||||
|
|
||||||
|
ControlPoint5UUID:2dc7d9d0-7b84-0131-b9c3-10b11c4ed8fd
|
||||||
|
ControlPoint5Name:Black Cylinder - Black Conical
|
||||||
|
ControlPoint5HasTwoPoints:1
|
||||||
|
ControlPoint5ShortName:BB
|
||||||
|
ControlPoint5DataSheet:P1.Type=Buoy###BREAKLINE###P1.Color=Black###BREAKLINE###P1.Shape=Cylinder###BREAKLINE###P1.Pattern=Checkered###BREAKLINE###P1.Name=Black Cylinder###BREAKLINE###P1.UUID=b153dfd6-83be-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=Black###BREAKLINE###P2.Shape=Conical###BREAKLINE###P2.Pattern=Checkered###BREAKLINE###P2.Name=Black Conical###BREAKLINE###P2.UUID=d78695ea-83be-11e2-88c0-10bf48d758ce
|
||||||
|
ControlPoint5Mark1Lon:7.269445
|
||||||
|
ControlPoint5Mark1Lat:43.687302
|
||||||
|
ControlPoint5Mark2Lon:7.272432
|
||||||
|
ControlPoint5Mark2Lat:43.692131
|
||||||
|
|
||||||
|
ControlPoint6UUID:2e37b410-7adc-0131-e5fe-60a44ce903c3
|
||||||
|
ControlPoint6Name:Black Conical-Yellow (white S)
|
||||||
|
ControlPoint6HasTwoPoints:1
|
||||||
|
ControlPoint6ShortName:BY
|
||||||
|
ControlPoint6DataSheet:P1.Type=Buoy###BREAKLINE###P1.Color=Black###BREAKLINE###P1.Shape=Conical###BREAKLINE###P1.Pattern=Checkered###BREAKLINE###P1.Name=Black Conical###BREAKLINE###P1.UUID=d78695ea-83be-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=Yellow###BREAKLINE###P2.Shape=Conical###BREAKLINE###P2.Name=Yellow###BREAKLINE###P2.UUID=3fdd2402-83be-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint6Mark1Lon:7.272432
|
||||||
|
ControlPoint6Mark1Lat:43.692131
|
||||||
|
ControlPoint6Mark2Lon:7.269320
|
||||||
|
ControlPoint6Mark2Lat:43.687366
|
||||||
|
|
||||||
|
ControlPoint7UUID:3240586c-83c0-11e2-88c0-10bf48d758ce
|
||||||
|
ControlPoint7Name:Finish Pole
|
||||||
|
ControlPoint7HasTwoPoints:0
|
||||||
|
ControlPoint7ShortName:F
|
||||||
|
ControlPoint7DataSheet:Color=Black###BREAKLINE###Type=Landmark###BREAKLINE###Name=Finish Pole
|
||||||
|
ControlPoint7Mark1Lon:7.271467
|
||||||
|
ControlPoint7Mark1Lat:43.694897
|
||||||
|
|
||||||
|
ControlPoint8UUID:37cb36e0-7adb-0131-e5c2-60a44ce903c3
|
||||||
|
ControlPoint8Name:Red-Blue
|
||||||
|
ControlPoint8HasTwoPoints:1
|
||||||
|
ControlPoint8ShortName:RB
|
||||||
|
ControlPoint8DataSheet:P1.Type=Buoy###BREAKLINE###P1.Color=Red###BREAKLINE###P1.Shape=Conical###BREAKLINE###P1.Name=Red###BREAKLINE###P1.UUID=5427c7d2-83be-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=Blue###BREAKLINE###P2.Shape=Conical###BREAKLINE###P2.Name=Blue###BREAKLINE###P2.UUID=1286f15e-83be-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint8Mark1Lon:7.273181
|
||||||
|
ControlPoint8Mark1Lat:43.688370
|
||||||
|
ControlPoint8Mark2Lon:7.269418
|
||||||
|
ControlPoint8Mark2Lat:43.687290
|
||||||
|
|
||||||
|
ControlPoint9UUID:3e6c1c94-83bf-11e2-88c0-10bf48d758ce
|
||||||
|
ControlPoint9Name:Race Committee
|
||||||
|
ControlPoint9HasTwoPoints:0
|
||||||
|
ControlPoint9ShortName:RC
|
||||||
|
ControlPoint9DataSheet:Type=StartBoat###BREAKLINE###Name=Race Committee
|
||||||
|
ControlPoint9Mark1Lon:7.267022
|
||||||
|
ControlPoint9Mark1Lat:43.691895
|
||||||
|
|
||||||
|
ControlPoint10UUID:3fdd2402-83be-11e2-88c0-10bf48d758ce
|
||||||
|
ControlPoint10Name:Yellow
|
||||||
|
ControlPoint10HasTwoPoints:0
|
||||||
|
ControlPoint10ShortName:Y
|
||||||
|
ControlPoint10DataSheet:Type=Buoy###BREAKLINE###Color=Yellow###BREAKLINE###Shape=Conical###BREAKLINE###Name=Yellow
|
||||||
|
ControlPoint10Mark1Lon:7.269320
|
||||||
|
ControlPoint10Mark1Lat:43.687366
|
||||||
|
|
||||||
|
ControlPoint11UUID:4c304720-7adc-0131-e608-60a44ce903c3
|
||||||
|
ControlPoint11Name:Black Conical-Red
|
||||||
|
ControlPoint11HasTwoPoints:1
|
||||||
|
ControlPoint11ShortName:BR
|
||||||
|
ControlPoint11DataSheet:P1.Type=Buoy###BREAKLINE###P1.Color=Black###BREAKLINE###P1.Shape=Conical###BREAKLINE###P1.Pattern=Checkered###BREAKLINE###P1.Name=Black Conical###BREAKLINE###P1.UUID=d78695ea-83be-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=Red###BREAKLINE###P2.Shape=Conical###BREAKLINE###P2.Name=Red###BREAKLINE###P2.UUID=5427c7d2-83be-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint11Mark1Lon:7.272432
|
||||||
|
ControlPoint11Mark1Lat:43.692131
|
||||||
|
ControlPoint11Mark2Lon:7.273181
|
||||||
|
ControlPoint11Mark2Lat:43.688370
|
||||||
|
|
||||||
|
ControlPoint12UUID:4e0c2a90-7adb-0131-e5cc-60a44ce903c3
|
||||||
|
ControlPoint12Name:Red-Yellow
|
||||||
|
ControlPoint12HasTwoPoints:1
|
||||||
|
ControlPoint12ShortName:RY
|
||||||
|
ControlPoint12DataSheet:P1.Type=Buoy###BREAKLINE###P1.Color=Red###BREAKLINE###P1.Shape=Conical###BREAKLINE###P1.Name=Red###BREAKLINE###P1.UUID=5427c7d2-83be-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=Yellow###BREAKLINE###P2.Shape=Conical###BREAKLINE###P2.Name=Yellow###BREAKLINE###P2.UUID=3fdd2402-83be-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint12Mark1Lon:7.273181
|
||||||
|
ControlPoint12Mark1Lat:43.688370
|
||||||
|
ControlPoint12Mark2Lon:7.269320
|
||||||
|
ControlPoint12Mark2Lat:43.687366
|
||||||
|
|
||||||
|
ControlPoint13UUID:5427c7d2-83be-11e2-88c0-10bf48d758ce
|
||||||
|
ControlPoint13Name:Red
|
||||||
|
ControlPoint13HasTwoPoints:0
|
||||||
|
ControlPoint13ShortName:R
|
||||||
|
ControlPoint13DataSheet:Type=Buoy###BREAKLINE###Color=Red###BREAKLINE###Shape=Conical###BREAKLINE###Name=Red
|
||||||
|
ControlPoint13Mark1Lon:7.273181
|
||||||
|
ControlPoint13Mark1Lat:43.688370
|
||||||
|
|
||||||
|
ControlPoint14UUID:621831d0-7adc-0131-e612-60a44ce903c3
|
||||||
|
ControlPoint14Name:Black Conical-Green
|
||||||
|
ControlPoint14HasTwoPoints:1
|
||||||
|
ControlPoint14ShortName:BG
|
||||||
|
ControlPoint14DataSheet:P1.Type=Buoy###BREAKLINE###P1.Color=Black###BREAKLINE###P1.Shape=Conical###BREAKLINE###P1.Pattern=Checkered###BREAKLINE###P1.Name=Black Conical###BREAKLINE###P1.UUID=d78695ea-83be-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=Green###BREAKLINE###P2.Shape=Conical###BREAKLINE###P2.Name=Green###BREAKLINE###P2.UUID=785c3e44-83be-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint14Mark1Lon:7.272432
|
||||||
|
ControlPoint14Mark1Lat:43.692131
|
||||||
|
ControlPoint14Mark2Lon:7.272257
|
||||||
|
ControlPoint14Mark2Lat:43.687305
|
||||||
|
|
||||||
|
ControlPoint15UUID:77b9e620-7adb-0131-e5d6-60a44ce903c3
|
||||||
|
ControlPoint15Name:Green-Blue
|
||||||
|
ControlPoint15HasTwoPoints:1
|
||||||
|
ControlPoint15ShortName:GB
|
||||||
|
ControlPoint15DataSheet:P1.Type=Buoy###BREAKLINE###P1.Color=Green###BREAKLINE###P1.Shape=Conical###BREAKLINE###P1.Name=Green###BREAKLINE###P1.UUID=785c3e44-83be-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=Blue###BREAKLINE###P2.Shape=Conical###BREAKLINE###P2.Name=Blue###BREAKLINE###P2.UUID=1286f15e-83be-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint15Mark1Lon:7.272257
|
||||||
|
ControlPoint15Mark1Lat:43.687305
|
||||||
|
ControlPoint15Mark2Lon:7.269418
|
||||||
|
ControlPoint15Mark2Lat:43.687290
|
||||||
|
|
||||||
|
ControlPoint16UUID:785c3e44-83be-11e2-88c0-10bf48d758ce
|
||||||
|
ControlPoint16Name:Green
|
||||||
|
ControlPoint16HasTwoPoints:0
|
||||||
|
ControlPoint16ShortName:G
|
||||||
|
ControlPoint16DataSheet:Type=Buoy###BREAKLINE###Color=Green###BREAKLINE###Shape=Conical###BREAKLINE###Name=Green
|
||||||
|
ControlPoint16Mark1Lon:7.272257
|
||||||
|
ControlPoint16Mark1Lat:43.687305
|
||||||
|
|
||||||
|
ControlPoint17UUID:7d9d1730-b3e8-0131-1d10-10b11c4ed8fd
|
||||||
|
ControlPoint17Name:Race Committee - Finish Pole
|
||||||
|
ControlPoint17HasTwoPoints:1
|
||||||
|
ControlPoint17ShortName:RF
|
||||||
|
ControlPoint17DataSheet:P1.Type=StartBoat###BREAKLINE###P1.Name=Race Committee###BREAKLINE###P1.UUID=3e6c1c94-83bf-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Color=Black###BREAKLINE###P2.Type=Landmark###BREAKLINE###P2.Name=Finish Pole###BREAKLINE###P2.UUID=3240586c-83c0-11e2-88c0-10bf48d758ce
|
||||||
|
ControlPoint17Mark1Lon:7.267022
|
||||||
|
ControlPoint17Mark1Lat:43.691895
|
||||||
|
ControlPoint17Mark2Lon:7.271342
|
||||||
|
ControlPoint17Mark2Lat:43.694851
|
||||||
|
|
||||||
|
ControlPoint18UUID:88ef6d40-7adc-0131-e61c-60a44ce903c3
|
||||||
|
ControlPoint18Name:Finish Pole-Cylinder
|
||||||
|
ControlPoint18HasTwoPoints:1
|
||||||
|
ControlPoint18ShortName:F
|
||||||
|
ControlPoint18DataSheet:P1.Color=Black###BREAKLINE###P1.Type=Landmark###BREAKLINE###P1.Name=Finish Pole###BREAKLINE###P1.UUID=3240586c-83c0-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=Black###BREAKLINE###P2.Shape=Cylinder###BREAKLINE###P2.Pattern=Checkered###BREAKLINE###P2.Name=Black Cylinder###BREAKLINE###P2.UUID=b153dfd6-83be-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint18Mark1Lon:7.271342
|
||||||
|
ControlPoint18Mark1Lat:43.694851
|
||||||
|
ControlPoint18Mark2Lon:7.269445
|
||||||
|
ControlPoint18Mark2Lat:43.687302
|
||||||
|
|
||||||
|
ControlPoint19UUID:8f9a4ee0-7adb-0131-e5e0-60a44ce903c3
|
||||||
|
ControlPoint19Name:Green-Yellow
|
||||||
|
ControlPoint19HasTwoPoints:1
|
||||||
|
ControlPoint19ShortName:GY
|
||||||
|
ControlPoint19DataSheet:P1.Type=Buoy###BREAKLINE###P1.Color=Green###BREAKLINE###P1.Shape=Conical###BREAKLINE###P1.Name=Green###BREAKLINE###P1.UUID=785c3e44-83be-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=Yellow###BREAKLINE###P2.Shape=Conical###BREAKLINE###P2.Name=Yellow###BREAKLINE###P2.UUID=3fdd2402-83be-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint19Mark1Lon:7.272257
|
||||||
|
ControlPoint19Mark1Lat:43.687305
|
||||||
|
ControlPoint19Mark2Lon:7.269320
|
||||||
|
ControlPoint19Mark2Lat:43.687366
|
||||||
|
|
||||||
|
ControlPoint20UUID:a0f71190-7adb-0131-e5ea-60a44ce903c3
|
||||||
|
ControlPoint20Name:Blue-Yellow
|
||||||
|
ControlPoint20HasTwoPoints:1
|
||||||
|
ControlPoint20ShortName:BY
|
||||||
|
ControlPoint20DataSheet:P1.Type=Buoy###BREAKLINE###P1.Color=Blue###BREAKLINE###P1.Shape=Conical###BREAKLINE###P1.Name=Blue###BREAKLINE###P1.UUID=1286f15e-83be-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=Yellow###BREAKLINE###P2.Shape=Conical###BREAKLINE###P2.Name=Yellow###BREAKLINE###P2.UUID=3fdd2402-83be-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint20Mark1Lon:7.269418
|
||||||
|
ControlPoint20Mark1Lat:43.687290
|
||||||
|
ControlPoint20Mark2Lon:7.269320
|
||||||
|
ControlPoint20Mark2Lat:43.687366
|
||||||
|
|
||||||
|
ControlPoint21UUID:a68c6350-7adc-0131-e626-60a44ce903c3
|
||||||
|
ControlPoint21Name:RC-Black Conical
|
||||||
|
ControlPoint21HasTwoPoints:1
|
||||||
|
ControlPoint21ShortName:S
|
||||||
|
ControlPoint21DataSheet:P1.Type=StartBoat###BREAKLINE###P1.Name=Race Committee###BREAKLINE###P1.UUID=3e6c1c94-83bf-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=Black###BREAKLINE###P2.Shape=Conical###BREAKLINE###P2.Pattern=Checkered###BREAKLINE###P2.Name=Black Conical###BREAKLINE###P2.UUID=d78695ea-83be-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint21Mark1Lon:7.267022
|
||||||
|
ControlPoint21Mark1Lat:43.691895
|
||||||
|
ControlPoint21Mark2Lon:7.272432
|
||||||
|
ControlPoint21Mark2Lat:43.692131
|
||||||
|
|
||||||
|
ControlPoint22UUID:b153dfd6-83be-11e2-88c0-10bf48d758ce
|
||||||
|
ControlPoint22Name:Black Cylinder
|
||||||
|
ControlPoint22HasTwoPoints:0
|
||||||
|
ControlPoint22ShortName:B
|
||||||
|
ControlPoint22DataSheet:Type=Buoy###BREAKLINE###Color=Black###BREAKLINE###Shape=Cylinder###BREAKLINE###Pattern=Checkered###BREAKLINE###Name=Black Cylinder
|
||||||
|
ControlPoint22Mark1Lon:7.269445
|
||||||
|
ControlPoint22Mark1Lat:43.687302
|
||||||
|
|
||||||
|
ControlPoint23UUID:b62e0bf0-7adc-0131-e630-60a44ce903c3
|
||||||
|
ControlPoint23Name:RC-Black Cylinder
|
||||||
|
ControlPoint23HasTwoPoints:1
|
||||||
|
ControlPoint23ShortName:S
|
||||||
|
ControlPoint23DataSheet:P1.Type=StartBoat###BREAKLINE###P1.Name=Race Committee###BREAKLINE###P1.UUID=3e6c1c94-83bf-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=Black###BREAKLINE###P2.Shape=Cylinder###BREAKLINE###P2.Pattern=Checkered###BREAKLINE###P2.Name=Black Cylinder###BREAKLINE###P2.UUID=b153dfd6-83be-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint23Mark1Lon:7.267022
|
||||||
|
ControlPoint23Mark1Lat:43.691895
|
||||||
|
ControlPoint23Mark2Lon:7.269445
|
||||||
|
ControlPoint23Mark2Lat:43.687302
|
||||||
|
|
||||||
|
ControlPoint24UUID:bd1fc330-7c10-0131-9c24-10b11c4ed8fd
|
||||||
|
ControlPoint24Name:Black Cylinder-Yellow
|
||||||
|
ControlPoint24HasTwoPoints:1
|
||||||
|
ControlPoint24ShortName:S
|
||||||
|
ControlPoint24DataSheet:P1.Type=Buoy###BREAKLINE###P1.Color=Black###BREAKLINE###P1.Shape=Cylinder###BREAKLINE###P1.Pattern=Checkered###BREAKLINE###P1.Name=Black Cylinder###BREAKLINE###P1.UUID=b153dfd6-83be-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=Yellow###BREAKLINE###P2.Shape=Conical###BREAKLINE###P2.Name=Yellow###BREAKLINE###P2.UUID=3fdd2402-83be-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint24Mark1Lon:7.269445
|
||||||
|
ControlPoint24Mark1Lat:43.687302
|
||||||
|
ControlPoint24Mark2Lon:7.269320
|
||||||
|
ControlPoint24Mark2Lat:43.687366
|
||||||
|
|
||||||
|
ControlPoint25UUID:bf6777e6-83bd-11e2-88c0-10bf48d758ce
|
||||||
|
ControlPoint25Name:White S
|
||||||
|
ControlPoint25HasTwoPoints:0
|
||||||
|
ControlPoint25ShortName:W
|
||||||
|
ControlPoint25DataSheet:Type=Buoy###BREAKLINE###Color=White###BREAKLINE###Shape=Conical###BREAKLINE###Name=White S
|
||||||
|
ControlPoint25Mark1Lon:7.268352
|
||||||
|
ControlPoint25Mark1Lat:43.691936
|
||||||
|
|
||||||
|
ControlPoint26UUID:cd3c1dc0-7c11-0131-9c2e-10b11c4ed8fd
|
||||||
|
ControlPoint26Name:Finish Pole-Conical
|
||||||
|
ControlPoint26HasTwoPoints:1
|
||||||
|
ControlPoint26ShortName:S
|
||||||
|
ControlPoint26DataSheet:P1.Color=Black###BREAKLINE###P1.Type=Landmark###BREAKLINE###P1.Name=Finish Pole###BREAKLINE###P1.UUID=3240586c-83c0-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=Black###BREAKLINE###P2.Shape=Conical###BREAKLINE###P2.Pattern=Checkered###BREAKLINE###P2.Name=Black Conical###BREAKLINE###P2.UUID=d78695ea-83be-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint26Mark1Lon:7.271342
|
||||||
|
ControlPoint26Mark1Lat:43.694851
|
||||||
|
ControlPoint26Mark2Lon:7.272432
|
||||||
|
ControlPoint26Mark2Lat:43.692131
|
||||||
|
|
||||||
|
ControlPoint27UUID:d39a0d00-7adc-0131-e63a-60a44ce903c3
|
||||||
|
ControlPoint27Name:White Gate
|
||||||
|
ControlPoint27HasTwoPoints:1
|
||||||
|
ControlPoint27ShortName:W
|
||||||
|
ControlPoint27DataSheet:P1.Type=Buoy###BREAKLINE###P1.Color=White###BREAKLINE###P1.Shape=Conical###BREAKLINE###P1.Name=White S###BREAKLINE###P1.UUID=bf6777e6-83bd-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=White###BREAKLINE###P2.Shape=Conical###BREAKLINE###P2.Name=White P###BREAKLINE###P2.UUID=e9ec42f8-83bd-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint27Mark1Lon:7.268352
|
||||||
|
ControlPoint27Mark1Lat:43.691936
|
||||||
|
ControlPoint27Mark2Lon:7.271063
|
||||||
|
ControlPoint27Mark2Lat:43.691803
|
||||||
|
|
||||||
|
ControlPoint28UUID:d78695ea-83be-11e2-88c0-10bf48d758ce
|
||||||
|
ControlPoint28Name:Black Conical
|
||||||
|
ControlPoint28HasTwoPoints:0
|
||||||
|
ControlPoint28ShortName:B
|
||||||
|
ControlPoint28DataSheet:Type=Buoy###BREAKLINE###Color=Black###BREAKLINE###Shape=Conical###BREAKLINE###Pattern=Checkered###BREAKLINE###Name=Black Conical
|
||||||
|
ControlPoint28Mark1Lon:7.272432
|
||||||
|
ControlPoint28Mark1Lat:43.692131
|
||||||
|
|
||||||
|
ControlPoint29UUID:e9ec42f8-83bd-11e2-88c0-10bf48d758ce
|
||||||
|
ControlPoint29Name:White P
|
||||||
|
ControlPoint29HasTwoPoints:0
|
||||||
|
ControlPoint29ShortName:W
|
||||||
|
ControlPoint29DataSheet:Type=Buoy###BREAKLINE###Color=White###BREAKLINE###Shape=Conical###BREAKLINE###Name=White P
|
||||||
|
ControlPoint29Mark1Lon:7.271063
|
||||||
|
ControlPoint29Mark1Lat:43.691803
|
||||||
|
|
||||||
|
ControlPoint30UUID:eff23330-7b84-0131-b9d2-10b11c4ed8fd
|
||||||
|
ControlPoint30Name:RC-Red
|
||||||
|
ControlPoint30HasTwoPoints:1
|
||||||
|
ControlPoint30ShortName:S
|
||||||
|
ControlPoint30DataSheet:P1.Type=StartBoat###BREAKLINE###P1.Name=Race Committee###BREAKLINE###P1.UUID=3e6c1c94-83bf-11e2-88c0-10bf48d758ce###BREAKLINE###P2.Type=Buoy###BREAKLINE###P2.Color=Red###BREAKLINE###P2.Shape=Conical###BREAKLINE###P2.Name=Red###BREAKLINE###P2.UUID=5427c7d2-83be-11e2-88c0-10bf48d758ce###BREAKLINE###
|
||||||
|
ControlPoint30Mark1Lon:7.267022
|
||||||
|
ControlPoint30Mark1Lat:43.691895
|
||||||
|
ControlPoint30Mark2Lon:7.273181
|
||||||
|
ControlPoint30Mark2Lat:43.688370
|
||||||
|
|
||||||
|
SegmentFile:segments.php
|
||||||
|
Route1UUID:09f125d0-2bc6-0132-1eee-10b11c4ed8fd
|
||||||
|
Route1Description:Race 1
|
||||||
|
Route1Length:0
|
||||||
|
Route1DataSheet:CourseDiagram=Course###BREAKLINE###Seq.1=Line###BREAKLINE###Seq.2=Port###BREAKLINE###Seq.3=Gate###BREAKLINE###Seq.4=Port###BREAKLINE###Seq.5=Line###BREAKLINE###
|
||||||
|
Route1ControlPoint1UUID:d39a0d00-7adc-0131-e63a-60a44ce903c3
|
||||||
|
Route1ControlPoint2UUID:785c3e44-83be-11e2-88c0-10bf48d758ce
|
||||||
|
Route1ControlPoint3UUID:2ce99970-2c47-0132-20ce-10b11c4ed8fd
|
||||||
|
|
||||||
|
//-------- AUTO GENERATED PARAMETERS END ------------------
|
||||||
+76
@@ -0,0 +1,76 @@
|
|||||||
|
package com.sap.sailing.xmlexport.test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.sap.sailing.domain.common.WindSourceType;
|
||||||
|
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
|
||||||
|
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
|
||||||
|
import com.sap.sailing.domain.common.impl.WindSourceImpl;
|
||||||
|
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
|
||||||
|
import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
|
||||||
|
import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets10LastBreaksTie;
|
||||||
|
import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl;
|
||||||
|
import com.sap.sailing.domain.test.OnlineTracTracBasedTest;
|
||||||
|
import com.sap.sailing.domain.tracking.impl.WindImpl;
|
||||||
|
import com.sap.sailing.domain.tractracadapter.ReceiverType;
|
||||||
|
import com.sap.sailing.xmlexport.LeaderboardData;
|
||||||
|
|
||||||
|
public class XMLExportTest extends OnlineTracTracBasedTest {
|
||||||
|
|
||||||
|
public XMLExportTest() throws MalformedURLException, URISyntaxException {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpESS2014Nice(String raceNumber) {
|
||||||
|
URI storedUri;
|
||||||
|
try {
|
||||||
|
storedUri = new URI("file:///" + new File("resources/" + getFileName() + raceNumber + ".mtb").getCanonicalPath().replace('\\', '/'));
|
||||||
|
super.setUp(new URL("file:///" + new File("resources/" + getFileName() + raceNumber + ".txt").getCanonicalPath()),
|
||||||
|
/* liveUri */null, /* storedUri */storedUri,
|
||||||
|
new ReceiverType[] { ReceiverType.MARKPASSINGS, ReceiverType.RACECOURSE, ReceiverType.MARKPOSITIONS, ReceiverType.RAWPOSITIONS });
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
boolean result = getTrackedRace().recordWind(new WindImpl(/* position */null, getTrackedRace().getStartOfRace(), new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(65))),
|
||||||
|
new WindSourceImpl(WindSourceType.WEB));
|
||||||
|
assert result==true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getExpectedEventName() {
|
||||||
|
return "ESS Nice 2014";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getFileName() {
|
||||||
|
return "event_20141001_ESSNice-Race_";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExportingESSNice2014() {
|
||||||
|
setUpESS2014Nice("1");
|
||||||
|
FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("ESS 2014 Nice", new ThresholdBasedResultDiscardingRuleImpl(new int[] {0}), new HighPointFirstGets10LastBreaksTie(),
|
||||||
|
null);
|
||||||
|
leaderboard.addRace(getTrackedRace(), "R1", false);
|
||||||
|
LeaderboardData leaderboardData = new LeaderboardData(leaderboard);
|
||||||
|
try {
|
||||||
|
leaderboardData.perform();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
fail("No exception should occur");
|
||||||
|
}
|
||||||
|
String resultData = leaderboardData.getResultXML();
|
||||||
|
assertNotNull(resultData);
|
||||||
|
assertTrue(resultData.length()>261000);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.sap.sailing.xmlexport;
|
package com.sap.sailing.xmlexport;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.StringWriter;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.NavigableSet;
|
import java.util.NavigableSet;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
@@ -41,11 +42,21 @@ public abstract class ExportAction {
|
|||||||
private HttpServletResponse res;
|
private HttpServletResponse res;
|
||||||
|
|
||||||
private RacingEventService service;
|
private RacingEventService service;
|
||||||
|
private Leaderboard leaderboard;
|
||||||
|
protected final boolean useProvidedLeaderboard;
|
||||||
|
private String resultingXMLData;
|
||||||
|
|
||||||
public ExportAction(HttpServletRequest req, HttpServletResponse res, RacingEventService service) {
|
public ExportAction(HttpServletRequest req, HttpServletResponse res, RacingEventService service) {
|
||||||
this.req = req;
|
this.req = req;
|
||||||
this.res = res;
|
this.res = res;
|
||||||
this.service = service;
|
this.service = service;
|
||||||
|
this.leaderboard = null;
|
||||||
|
this.useProvidedLeaderboard = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExportAction(Leaderboard leaderboard) {
|
||||||
|
this.leaderboard = leaderboard;
|
||||||
|
this.useProvidedLeaderboard = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAttribute(String name) {
|
public String getAttribute(String name) {
|
||||||
@@ -56,15 +67,21 @@ public abstract class ExportAction {
|
|||||||
return service;
|
return service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getResultXML() {
|
||||||
|
return resultingXMLData;
|
||||||
|
}
|
||||||
|
|
||||||
public Leaderboard getLeaderboard() throws IOException, ServletException {
|
public Leaderboard getLeaderboard() throws IOException, ServletException {
|
||||||
|
if (!useProvidedLeaderboard) {
|
||||||
final String leaderboardName = getAttribute("name");
|
final String leaderboardName = getAttribute("name");
|
||||||
if (leaderboardName == null) {
|
if (leaderboardName == null) {
|
||||||
throw new ServletException("Use the name= parameter to specify the leaderboard");
|
throw new ServletException("Use the name= parameter to specify the leaderboard");
|
||||||
}
|
}
|
||||||
final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName);
|
leaderboard = getService().getLeaderboardByName(leaderboardName);
|
||||||
if (leaderboard == null) {
|
if (leaderboard == null) {
|
||||||
throw new ServletException("Leaderboard " + leaderboardName + " not found.");
|
throw new ServletException("Leaderboard " + leaderboardName + " not found.");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return leaderboard;
|
return leaderboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,14 +332,23 @@ public abstract class ExportAction {
|
|||||||
format.setEncoding("UTF-8");
|
format.setEncoding("UTF-8");
|
||||||
XMLOutputter xmlOutputter = new XMLOutputter(format);
|
XMLOutputter xmlOutputter = new XMLOutputter(format);
|
||||||
|
|
||||||
|
if (!useProvidedLeaderboard) {
|
||||||
res.setContentType("text/xml");
|
res.setContentType("text/xml");
|
||||||
res.addHeader("Content-Disposition", "attachment; filename=" + fileName);
|
res.addHeader("Content-Disposition", "attachment; filename=" + fileName);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
xmlOutputter.output(element, res.getOutputStream());
|
xmlOutputter.output(element, res.getOutputStream());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
StringWriter resultStringWriter = new StringWriter();
|
||||||
|
try {
|
||||||
|
xmlOutputter.output(element, resultStringWriter);
|
||||||
|
resultingXMLData = resultStringWriter.toString();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected long handleValue(TimePoint timepoint) {
|
protected long handleValue(TimePoint timepoint) {
|
||||||
|
|||||||
@@ -75,6 +75,10 @@ public class LeaderboardData extends ExportAction {
|
|||||||
super(req, res, service);
|
super(req, res, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LeaderboardData(Leaderboard leaderboard) {
|
||||||
|
super(leaderboard);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates XML for a leaderboard. Expects a list of generated competitors and races XML elements that are associated with the leaderboard.
|
* Creates XML for a leaderboard. Expects a list of generated competitors and races XML elements that are associated with the leaderboard.
|
||||||
* <pre>
|
* <pre>
|
||||||
@@ -907,6 +911,7 @@ public class LeaderboardData extends ExportAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.info("Finished XML export of leaderboard " + leaderboard.getName() + " in " + MillisecondsTimePoint.now().minus(timeSpent.asMillis()).asMillis() + " milliseconds");
|
log.info("Finished XML export of leaderboard " + leaderboard.getName() + " in " + MillisecondsTimePoint.now().minus(timeSpent.asMillis()).asMillis() + " milliseconds");
|
||||||
sendDocument(createLeaderboardXML(leaderboard, competitorElements, racesElements, leaderboardConfidenceAndErrorMessages), leaderboard.getName() + ".xml");
|
Element dataToExport = createLeaderboardXML(leaderboard, competitorElements, racesElements, leaderboardConfidenceAndErrorMessages);
|
||||||
|
sendDocument(dataToExport, leaderboard.getName() + ".xml");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,6 +67,7 @@
|
|||||||
<module>com.sap.sailing.www</module>
|
<module>com.sap.sailing.www</module>
|
||||||
<module>com.sap.sailing.www.events</module>
|
<module>com.sap.sailing.www.events</module>
|
||||||
<module>com.sap.sailing.xmlexport</module>
|
<module>com.sap.sailing.xmlexport</module>
|
||||||
|
<module>com.sap.sailing.xmlexport.test</module>
|
||||||
<module>com.google.gwt.osgi</module>
|
<module>com.google.gwt.osgi</module>
|
||||||
<module>com.tractrac.clientmodule</module>
|
<module>com.tractrac.clientmodule</module>
|
||||||
<module>org.json.simple</module>
|
<module>org.json.simple</module>
|
||||||
|
|||||||
Reference in new issue
Block a user