mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-25 06:58:39 +00:00
Merge branch 'master' into bug4312
This commit is contained in:
+2
@@ -39,6 +39,8 @@
|
||||
<inherits name='com.google.gwt.maps.Maps' />
|
||||
|
||||
<inherits name="com.sap.sailing.domain.SailingDomain" />
|
||||
<inherits name="com.sap.sailing.ExpeditionConnectorCommon" />
|
||||
|
||||
<!-- module containing locale configuration -->
|
||||
<inherits name='com.sap.sailing.gwt.common.SailingLocalesAllPermutations' />
|
||||
<inherits name="com.sap.sailing.gwt.ui.NoUI" />
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.sap.sailing.domain.common.scalablevalue.impl;
|
||||
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.impl.MeterDistance;
|
||||
import com.sap.sse.common.scalablevalue.ScalableValue;
|
||||
import com.sap.sse.common.scalablevalue.ScalableValueWithDistance;
|
||||
|
||||
public class ScalableDistance implements ScalableValueWithDistance<Double, Distance> {
|
||||
private final double meters;
|
||||
|
||||
public ScalableDistance(Distance distance) {
|
||||
this.meters = distance.getMeters();
|
||||
}
|
||||
|
||||
private ScalableDistance(double meters) {
|
||||
this.meters = meters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalableDistance multiply(double factor) {
|
||||
return new ScalableDistance(factor*meters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalableDistance add(ScalableValue<Double, Distance> t) {
|
||||
return new ScalableDistance(meters+t.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance divide(double divisor) {
|
||||
return new MeterDistance(meters / divisor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getValue() {
|
||||
return meters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDistance(Distance other) {
|
||||
return Math.abs(meters-other.getMeters());
|
||||
}
|
||||
|
||||
}
|
||||
+1
@@ -14,6 +14,7 @@ public enum Permission implements com.sap.sse.security.shared.Permission {
|
||||
MANAGE_COURSE_LAYOUT,
|
||||
MANAGE_WIND,
|
||||
MANAGE_IGTIMI_ACCOUNTS,
|
||||
MANAGE_EXPEDITION_DEVICE_CONFIGURATIONS,
|
||||
MANAGE_LEADERBOARDS,
|
||||
MANAGE_LEADERBOARD_RESULTS,
|
||||
MANAGE_LEADERBOARD_GROUPS,
|
||||
|
||||
+3
@@ -42,6 +42,9 @@ public enum BravoExtendedSensorDataMetadata implements ColumnMetadata {
|
||||
return columnName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The index in the {@link DoubleVectorFix} where this data item will be stored
|
||||
*/
|
||||
public int getColumnIndex() {
|
||||
return this.ordinal();
|
||||
}
|
||||
|
||||
+3
@@ -40,6 +40,9 @@ public enum ExpeditionExtendedSensorDataMetadata {
|
||||
return columnName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The index in the {@link DoubleVectorFix} where this data item will be stored
|
||||
*/
|
||||
public int getColumnIndex() {
|
||||
return mappedToBravoField.getColumnIndex();
|
||||
}
|
||||
|
||||
+4
-4
@@ -6,9 +6,9 @@ import com.sap.sailing.domain.common.Bearing;
|
||||
* Extended version of {@link BravoFix} that provides access to more measures found in the extended data format.
|
||||
*/
|
||||
public interface BravoExtendedFix extends BravoFix {
|
||||
double getPortDaggerboardRake();
|
||||
double getStbdDaggerboardRake();
|
||||
double getPortRudderRake();
|
||||
double getStbdRudderRake();
|
||||
Double getPortDaggerboardRake();
|
||||
Double getStbdDaggerboardRake();
|
||||
Double getPortRudderRake();
|
||||
Double getStbdRudderRake();
|
||||
Bearing getMastRotation();
|
||||
}
|
||||
|
||||
+9
-4
@@ -3,10 +3,15 @@ package com.sap.sailing.domain.common.tracking;
|
||||
import com.sap.sse.common.Timed;
|
||||
|
||||
/**
|
||||
* A fix that simply holds an array of double values. The interpretation of the data depends on the concrete mapping in
|
||||
* the RegattaLog.
|
||||
* A fix that simply holds an array of {@link Double} values. The interpretation of the data depends on the concrete
|
||||
* mapping in the RegattaLog. Asking beyond the end of the vector using {@link #get(int)} will return {@code null} but
|
||||
* not throw an exception.
|
||||
*/
|
||||
public interface DoubleVectorFix extends Timed {
|
||||
double[] get();
|
||||
double get(int index);
|
||||
Double[] get();
|
||||
Double get(int index);
|
||||
/**
|
||||
* Tells whether at least one component is not {@code null}
|
||||
*/
|
||||
boolean hasValidData();
|
||||
}
|
||||
|
||||
+6
-5
@@ -24,28 +24,29 @@ public class BravoExtendedFixImpl extends BravoFixImpl implements BravoExtendedF
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPortDaggerboardRake() {
|
||||
public Double getPortDaggerboardRake() {
|
||||
return fix.get(BravoExtendedSensorDataMetadata.DB_RAKE_PORT.getColumnIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getStbdDaggerboardRake() {
|
||||
public Double getStbdDaggerboardRake() {
|
||||
return fix.get(BravoExtendedSensorDataMetadata.DB_RAKE_STBD.getColumnIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPortRudderRake() {
|
||||
public Double getPortRudderRake() {
|
||||
return fix.get(BravoExtendedSensorDataMetadata.RUDDER_RAKE_PORT.getColumnIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getStbdRudderRake() {
|
||||
public Double getStbdRudderRake() {
|
||||
return fix.get(BravoExtendedSensorDataMetadata.RUDDER_RAKE_STBD.getColumnIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing getMastRotation() {
|
||||
return new DegreeBearingImpl(fix.get(BravoExtendedSensorDataMetadata.MAST_ROTATION.getColumnIndex()));
|
||||
final Double bearingDeg = fix.get(BravoExtendedSensorDataMetadata.MAST_ROTATION.getColumnIndex());
|
||||
return bearingDeg == null ? null : new DegreeBearingImpl(bearingDeg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-2
@@ -58,11 +58,13 @@ public class BravoFixImpl extends SensorFixImpl implements BravoFix {
|
||||
|
||||
@Override
|
||||
public Bearing getPitch() {
|
||||
return new DegreeBearingImpl(fix.get(BravoSensorDataMetadata.PITCH.getColumnIndex()));
|
||||
final Double bearingDeg = fix.get(BravoSensorDataMetadata.PITCH.getColumnIndex());
|
||||
return bearingDeg == null ? null : new DegreeBearingImpl(bearingDeg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing getHeel() {
|
||||
return new DegreeBearingImpl(fix.get(BravoSensorDataMetadata.HEEL.getColumnIndex()));
|
||||
final Double bearingDeg = fix.get(BravoSensorDataMetadata.HEEL.getColumnIndex());
|
||||
return bearingDeg == null ? null : new DegreeBearingImpl(bearingDeg);
|
||||
}
|
||||
}
|
||||
|
||||
+41
-8
@@ -1,12 +1,16 @@
|
||||
package com.sap.sailing.domain.common.tracking.impl;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
|
||||
import com.sap.sailing.domain.common.tracking.DoubleVectorFix;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
/**
|
||||
* Implementation of {@link DoubleVectorFix}.
|
||||
* Implementation of {@link DoubleVectorFix}. In order to save some space and reduce the number of object headers,
|
||||
* instead of storing {@link Double} objects the structure internally uses an array of {@code double} values and
|
||||
* additionally remembers in a {@link BitSet} which components are {@code null}. The {@link #get()} and {@link #get(int)}
|
||||
* methods then translate back to a {@link Double} representation accordingly.
|
||||
*/
|
||||
public class DoubleVectorFixImpl implements DoubleVectorFix {
|
||||
|
||||
@@ -14,10 +18,25 @@ public class DoubleVectorFixImpl implements DoubleVectorFix {
|
||||
|
||||
private final double[] fixData;
|
||||
private final TimePoint timePoint;
|
||||
|
||||
/**
|
||||
* The constructor accepts a {@code Double[]} for the data components, allowing for {@code null}
|
||||
* values to be used. To save space, internally a {@code double[]} is used to represent the data.
|
||||
* In order to encode the {@code null} values, this bit set stores which array components had
|
||||
* valid, non-{@code null} data.
|
||||
*/
|
||||
private final BitSet validComponents;
|
||||
|
||||
public DoubleVectorFixImpl(TimePoint timePoint, double[] fixData) {
|
||||
public DoubleVectorFixImpl(TimePoint timePoint, Double[] fixData) {
|
||||
this.timePoint = timePoint;
|
||||
this.fixData = fixData;
|
||||
this.fixData = new double[fixData.length];
|
||||
this.validComponents = new BitSet(fixData.length);
|
||||
for (int i=0; i<fixData.length; i++) {
|
||||
if (fixData[i] != null) {
|
||||
this.validComponents.set(i);
|
||||
this.fixData[i] = fixData[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -26,14 +45,22 @@ public class DoubleVectorFixImpl implements DoubleVectorFix {
|
||||
}
|
||||
|
||||
@Override
|
||||
public double get(int index) {
|
||||
return fixData[index];
|
||||
public Double get(int index) {
|
||||
return index<fixData.length && validComponents.get(index) ? fixData[index] : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] get() {
|
||||
// TODO defensive copy?
|
||||
return fixData;
|
||||
public Double[] get() {
|
||||
final Double[] result = new Double[fixData.length];
|
||||
for (int i=0; i<fixData.length; i++) {
|
||||
result[i] = validComponents.get(i) ? fixData[i] : null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasValidData() {
|
||||
return !validComponents.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,6 +69,7 @@ public class DoubleVectorFixImpl implements DoubleVectorFix {
|
||||
int result = 1;
|
||||
result = prime * result + Arrays.hashCode(fixData);
|
||||
result = prime * result + ((timePoint == null) ? 0 : timePoint.hashCode());
|
||||
result = prime * result + ((validComponents == null) ? 0 : validComponents.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -61,6 +89,11 @@ public class DoubleVectorFixImpl implements DoubleVectorFix {
|
||||
return false;
|
||||
} else if (!timePoint.equals(other.timePoint))
|
||||
return false;
|
||||
if (validComponents == null) {
|
||||
if (other.validComponents != null)
|
||||
return false;
|
||||
} else if (!validComponents.equals(other.validComponents))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
package com.sap.sailing.domain.expeditionadapter.impl;
|
||||
|
||||
public enum FieldType {
|
||||
date, race_name, leg_name, leg_score, boat_speed, heel, leeway, rudder, heading, course, depth,
|
||||
tws, twa, twd, aws, awa, latitude, longitude, sog, cog, abstwa, absawa, absheel, absleeway, absrudder,
|
||||
foresail, staysail, mainsail, forestay, rake, vmg, status, starboard_port, rudder2, keelang, absrudder2, abskeelang;
|
||||
}
|
||||
+6
-6
@@ -38,20 +38,20 @@ public class DoubleVectorFixMongoHandlerImpl implements FixMongoHandler<DoubleVe
|
||||
return new DoubleVectorFixImpl(timePoint, fromDBObject((DBObject) dbObject.get(FieldNames.FIX.name())));
|
||||
}
|
||||
|
||||
private DBObject toDBObject(double[] data) {
|
||||
private DBObject toDBObject(Double[] data) {
|
||||
BasicDBList result = new BasicDBList();
|
||||
for (double value : data) {
|
||||
for (Double value : data) {
|
||||
result.add(value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private double[] fromDBObject(DBObject dbObject) {
|
||||
private Double[] fromDBObject(DBObject dbObject) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Number> dbValues = (List<Number>) dbObject;
|
||||
double[] result = new double[dbValues.size()];
|
||||
for(int i = 0 ; i < dbValues.size() ; i++) {
|
||||
result[i] = dbValues.get(i).doubleValue();
|
||||
Double[] result = new Double[dbValues.size()];
|
||||
for (int i = 0 ; i < dbValues.size() ; i++) {
|
||||
result[i] = dbValues.get(i) == null ? null : dbValues.get(i).doubleValue();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@ public class DeviceMappingsAndSensorFixStoreLockingTest extends AbstractGPSFixSt
|
||||
};
|
||||
}.start();
|
||||
|
||||
store.storeFix(device, new DoubleVectorFixImpl(new MillisecondsTimePoint(1), new double[]{0.0}));
|
||||
store.storeFix(device, new DoubleVectorFixImpl(new MillisecondsTimePoint(1), new Double[]{0.0}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -542,7 +542,7 @@ public class SensorFixStoreAndLoadTest {
|
||||
}
|
||||
|
||||
private DoubleVectorFix createBravoDoubleVectorFixWithRideHeight(long timestamp, double rideHeight) {
|
||||
double[] fixData = new double[BravoSensorDataMetadata.getTrackColumnCount()];
|
||||
Double[] fixData = new Double[BravoSensorDataMetadata.getTrackColumnCount()];
|
||||
// fill the port/starboard columns as well because their minimum defines the true ride height
|
||||
fixData[BravoSensorDataMetadata.RIDE_HEIGHT_PORT_HULL.getColumnIndex()] = rideHeight;
|
||||
fixData[BravoSensorDataMetadata.RIDE_HEIGHT_STBD_HULL.getColumnIndex()] = rideHeight;
|
||||
@@ -554,7 +554,7 @@ public class SensorFixStoreAndLoadTest {
|
||||
}
|
||||
|
||||
private DoubleVectorFix createTestDoubleVectorFixWithTestValue(long timestamp, double testValue) {
|
||||
double[] fixData = new double[TestFixImpl.COLUMNS.size()];
|
||||
Double[] fixData = new Double[TestFixImpl.COLUMNS.size()];
|
||||
fixData[TestFixImpl.TEST_COLUMN_INDEX] = testValue;
|
||||
return new DoubleVectorFixImpl(new MillisecondsTimePoint(timestamp), fixData);
|
||||
}
|
||||
|
||||
+1
-1
@@ -384,7 +384,7 @@ public class SensorFixStoreTest {
|
||||
}
|
||||
|
||||
private DoubleVectorFix createBravoDoubleVectorFixWithRideHeight(long timestamp, double rideHeight) {
|
||||
double[] fixData = new double[BravoSensorDataMetadata.getTrackColumnCount()];
|
||||
Double[] fixData = new Double[BravoSensorDataMetadata.getTrackColumnCount()];
|
||||
fixData[BravoSensorDataMetadata.RIDE_HEIGHT_PORT_HULL.getColumnIndex()] = rideHeight;
|
||||
fixData[BravoSensorDataMetadata.RIDE_HEIGHT_STBD_HULL.getColumnIndex()] = rideHeight;
|
||||
return new DoubleVectorFixImpl(new MillisecondsTimePoint(timestamp), fixData);
|
||||
|
||||
-2
@@ -4,8 +4,6 @@ import java.util.UUID;
|
||||
|
||||
public class PingDeviceIdentifierImpl implements PingDeviceIdentifier {
|
||||
private static final long serialVersionUID = -4049961972156611640L;
|
||||
|
||||
|
||||
private final UUID id;
|
||||
|
||||
public PingDeviceIdentifierImpl() {
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.sap.sailing.domain.tracking;
|
||||
|
||||
/**
|
||||
* A predicate for a fix, for use in
|
||||
* {@link Track#getInterpolatedValue(com.sap.sse.common.TimePoint, com.sap.sse.common.Util.Function)}, used, e.g., to
|
||||
* provide a rule for when a fix shall be accepted during the search for surrounding fixes.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
* @param <FixType>
|
||||
*/
|
||||
public interface FixAcceptancePredicate<FixType> {
|
||||
boolean isAcceptFix(FixType fix);
|
||||
}
|
||||
+44
-8
@@ -6,6 +6,7 @@ import java.util.ConcurrentModificationException;
|
||||
import java.util.Iterator;
|
||||
import java.util.NavigableSet;
|
||||
|
||||
import com.sap.sailing.domain.tracking.FixAcceptancePredicate;
|
||||
import com.sap.sailing.domain.tracking.Track;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
@@ -148,14 +149,25 @@ public class TrackImpl<FixType extends Timed> implements Track<FixType> {
|
||||
|
||||
@Override
|
||||
public FixType getLastFixAtOrBefore(TimePoint timePoint) {
|
||||
return getLastFixAtOrBefore(timePoint, /* fixAcceptancePredicate == null means accept all */ null);
|
||||
}
|
||||
|
||||
private FixType getLastFixAtOrBefore(TimePoint timePoint, FixAcceptancePredicate<FixType> fixAcceptancePredicate) {
|
||||
lockForRead();
|
||||
try {
|
||||
return (FixType) getInternalFixes().floor(getDummyFix(timePoint));
|
||||
final NavigableSet<FixType> headSet = getInternalFixes().headSet(getDummyFix(timePoint), /* inclusive */ true);
|
||||
for (final Iterator<FixType> i=headSet.descendingIterator(); i.hasNext(); ) {
|
||||
final FixType next = i.next();
|
||||
if (fixAcceptancePredicate == null || fixAcceptancePredicate.isAcceptFix(next)) {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} finally {
|
||||
unlockAfterRead();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FixType getLastFixBefore(TimePoint timePoint) {
|
||||
lockForRead();
|
||||
@@ -188,9 +200,20 @@ public class TrackImpl<FixType extends Timed> implements Track<FixType> {
|
||||
|
||||
@Override
|
||||
public FixType getFirstFixAtOrAfter(TimePoint timePoint) {
|
||||
return getFirstFixAtOrAfter(timePoint, /* fixAcceptancePredicate==null means accept all fixes */ null);
|
||||
}
|
||||
|
||||
private FixType getFirstFixAtOrAfter(TimePoint timePoint, FixAcceptancePredicate<FixType> fixAcceptancePredicate) {
|
||||
lockForRead();
|
||||
try {
|
||||
return (FixType) getInternalFixes().ceiling(getDummyFix(timePoint));
|
||||
final NavigableSet<FixType> tailSet = getInternalFixes().tailSet(getDummyFix(timePoint), /* inclusive */ true);
|
||||
for (final Iterator<FixType> i=tailSet.iterator(); i.hasNext(); ) {
|
||||
final FixType next = i.next();
|
||||
if (fixAcceptancePredicate == null || fixAcceptancePredicate.isAcceptFix(next)) {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} finally {
|
||||
unlockAfterRead();
|
||||
}
|
||||
@@ -254,9 +277,16 @@ public class TrackImpl<FixType extends Timed> implements Track<FixType> {
|
||||
}
|
||||
}
|
||||
|
||||
private Pair<FixType, FixType> getSurroundingFixes(TimePoint timePoint) {
|
||||
FixType left = getLastFixAtOrBefore(timePoint);
|
||||
FixType right = getFirstFixAtOrAfter(timePoint);
|
||||
/**
|
||||
* @param fixAcceptancePredicate
|
||||
* if not {@code null}, adjacent fixes will be skipped as long as this predicate does not
|
||||
* {@link FixAcceptancePredicate#isAcceptFix(Object) accept} the fix. This can, e.g., be used to skip
|
||||
* fixes that don't have values in a dimension required. If {@code null}, the next fixes left and right
|
||||
* (including the exact {@code timePoint} if a fix exists there) will be used without further check.
|
||||
*/
|
||||
private Pair<FixType, FixType> getSurroundingFixes(TimePoint timePoint, FixAcceptancePredicate<FixType> fixAcceptancePredicate) {
|
||||
FixType left = getLastFixAtOrBefore(timePoint, fixAcceptancePredicate);
|
||||
FixType right = getFirstFixAtOrAfter(timePoint, fixAcceptancePredicate);
|
||||
com.sap.sse.common.Util.Pair<FixType, FixType> result = new com.sap.sse.common.Util.Pair<>(left, right);
|
||||
return result;
|
||||
}
|
||||
@@ -274,9 +304,15 @@ public class TrackImpl<FixType extends Timed> implements Track<FixType> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <InternalType, ValueType> ValueType getInterpolatedValue(TimePoint timePoint, Function<FixType, ScalableValue<InternalType, ValueType>> converter) {
|
||||
public <InternalType, ValueType> ValueType getInterpolatedValue(TimePoint timePoint,
|
||||
Function<FixType, ScalableValue<InternalType, ValueType>> converter) {
|
||||
return getInterpolatedValue(timePoint, converter, /* fixAcceptancePredicate==null means accept all */ null);
|
||||
}
|
||||
|
||||
protected <InternalType, ValueType> ValueType getInterpolatedValue(TimePoint timePoint,
|
||||
Function<FixType, ScalableValue<InternalType, ValueType>> converter, FixAcceptancePredicate<FixType> fixAcceptancePredicate) {
|
||||
final ValueType result;
|
||||
Pair<FixType, FixType> fixPair = getSurroundingFixes(timePoint);
|
||||
Pair<FixType, FixType> fixPair = getSurroundingFixes(timePoint, fixAcceptancePredicate);
|
||||
if (fixPair.getA() == null) {
|
||||
if (fixPair.getB() == null) {
|
||||
result = null;
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package com.sap.sailing.domain.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.base.CourseArea;
|
||||
import com.sap.sailing.domain.base.impl.CourseAreaImpl;
|
||||
import com.sap.sailing.domain.common.sensordata.BravoExtendedSensorDataMetadata;
|
||||
import com.sap.sailing.domain.common.tracking.impl.BravoExtendedFixImpl;
|
||||
import com.sap.sailing.domain.common.tracking.impl.DoubleVectorFixImpl;
|
||||
import com.sap.sailing.domain.tracking.DynamicBravoFixTrack;
|
||||
import com.sap.sailing.domain.tracking.impl.BravoFixTrackImpl;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class BravoFixTrackInterpolationWithNullTest {
|
||||
@Test
|
||||
public void testFixesWithNonNullFieldsAreSelected() {
|
||||
DynamicBravoFixTrack<CourseArea> track = new BravoFixTrackImpl<>(new CourseAreaImpl("Test", UUID.randomUUID()),
|
||||
"test", /* hasExtendedFixes */ true);
|
||||
track.add(createFix(10l, 5., null));
|
||||
track.add(createFix(20l, null, 7.));
|
||||
track.add(createFix(30l, 7., null));
|
||||
assertEquals(6., track.getHeel(new MillisecondsTimePoint(20l)).getDegrees(), 0.00001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFixesWithNonNullFieldsAreSelectedForMultipleNullsInARow() {
|
||||
DynamicBravoFixTrack<CourseArea> track = new BravoFixTrackImpl<>(new CourseAreaImpl("Test", UUID.randomUUID()),
|
||||
"test", /* hasExtendedFixes */ true);
|
||||
track.add(createFix(10l, 5., null));
|
||||
track.add(createFix(20l, null, 7.));
|
||||
track.add(createFix(30l, null, 7.));
|
||||
track.add(createFix(40l, null, 7.));
|
||||
track.add(createFix(50l, 7., null));
|
||||
assertEquals(6., track.getHeel(new MillisecondsTimePoint(30l)).getDegrees(), 0.00001);
|
||||
assertEquals(5., track.getHeel(new MillisecondsTimePoint(10l)).getDegrees(), 0.00001);
|
||||
}
|
||||
|
||||
private BravoExtendedFixImpl createFix(long timePointAsMillis, Double heel, Double pitch) {
|
||||
final Double[] fixData = new Double[Math.max(BravoExtendedSensorDataMetadata.HEEL.getColumnIndex(),
|
||||
BravoExtendedSensorDataMetadata.PITCH.getColumnIndex())+1];
|
||||
fixData[BravoExtendedSensorDataMetadata.HEEL.getColumnIndex()] = heel;
|
||||
fixData[BravoExtendedSensorDataMetadata.PITCH.getColumnIndex()] = pitch;
|
||||
return new BravoExtendedFixImpl(new DoubleVectorFixImpl(new MillisecondsTimePoint(timePointAsMillis), fixData));
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -67,7 +67,7 @@ public class MarkPassingCalculatorPerformanceTest extends AbstractMockedRaceMark
|
||||
time = System.currentTimeMillis() - time;
|
||||
result.put("FinderPerformance", time);
|
||||
System.out.println(time);
|
||||
Assert.assertTrue("Time expected to be less than 5000ms but was "+time+"ms", time < 5000);
|
||||
Assert.assertTrue("Time expected to be less than 7000ms but was "+time+"ms", time < 7000);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+1
-1
@@ -116,7 +116,7 @@ public class BravoFixTrackSerializationTest {
|
||||
}
|
||||
|
||||
private void addOrReplaceBravoFixToTrack(boolean replace) {
|
||||
double[] fixData = new double[BravoSensorDataMetadata.getTrackColumnCount()];
|
||||
Double[] fixData = new Double[BravoSensorDataMetadata.getTrackColumnCount()];
|
||||
// fill the port/starboard columns as well because their minimum defines the true ride height
|
||||
fixData[BravoSensorDataMetadata.RIDE_HEIGHT_PORT_HULL.getColumnIndex()] = rideHeight;
|
||||
fixData[BravoSensorDataMetadata.RIDE_HEIGHT_STBD_HULL.getColumnIndex()] = rideHeight;
|
||||
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
package com.sap.sailing.domain.racelog.tracking;
|
||||
|
||||
/**
|
||||
* Some object that can supply a {@link SensorFixStore} can be registered with the OSGi
|
||||
* registry using this interface, so it can be discovered by others, and the sensor fix
|
||||
* store can then be obtained.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public interface SensorFixStoreSupplier {
|
||||
SensorFixStore getSensorFixStore();
|
||||
}
|
||||
+32
-59
@@ -8,6 +8,8 @@ import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.confidence.impl.ScalableDouble;
|
||||
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
|
||||
import com.sap.sailing.domain.common.scalablevalue.impl.ScalableBearing;
|
||||
import com.sap.sailing.domain.common.scalablevalue.impl.ScalableDistance;
|
||||
import com.sap.sailing.domain.common.tracking.BravoExtendedFix;
|
||||
import com.sap.sailing.domain.common.tracking.BravoFix;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
@@ -44,62 +46,20 @@ public class BravoFixTrackImpl<ItemType extends WithID & Serializable> extends S
|
||||
|
||||
@Override
|
||||
public Distance getRideHeight(TimePoint timePoint) {
|
||||
BravoFix fixAfter = getFirstFixAtOrAfter(timePoint);
|
||||
if (fixAfter != null && fixAfter.getTimePoint().compareTo(timePoint) == 0) {
|
||||
// exact match of timepoint -> no interpolation necessary
|
||||
return fixAfter.getRideHeight();
|
||||
}
|
||||
BravoFix fixBefore = getLastFixAtOrBefore(timePoint);
|
||||
if (fixBefore != null && fixBefore.getTimePoint().compareTo(timePoint) == 0) {
|
||||
// exact match of timepoint -> no interpolation necessary
|
||||
return fixBefore.getRideHeight();
|
||||
}
|
||||
if (fixAfter == null || fixBefore == null) {
|
||||
// the fix is out of the TimeRange where we have fixes
|
||||
return null;
|
||||
}
|
||||
// TODO interpolate if necessary
|
||||
return fixBefore.getRideHeight();
|
||||
return getValueFromExtendedFixSkippingNullValues(timePoint, BravoFix::getRideHeight,
|
||||
ScalableDistance::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing getHeel(TimePoint timePoint) {
|
||||
BravoFix fixAfter = getFirstFixAtOrAfter(timePoint);
|
||||
if (fixAfter != null && fixAfter.getTimePoint().compareTo(timePoint) == 0) {
|
||||
// exact match of timepoint -> no interpolation necessary
|
||||
return fixAfter.getHeel();
|
||||
}
|
||||
BravoFix fixBefore = getLastFixAtOrBefore(timePoint);
|
||||
if (fixBefore != null && fixBefore.getTimePoint().compareTo(timePoint) == 0) {
|
||||
// exact match of timepoint -> no interpolation necessary
|
||||
return fixBefore.getHeel();
|
||||
}
|
||||
if (fixAfter == null || fixBefore == null) {
|
||||
// the fix is out of the TimeRange where we have fixes
|
||||
return null;
|
||||
}
|
||||
// TODO interpolate if necessary
|
||||
return fixBefore.getHeel();
|
||||
return getValueFromExtendedFixSkippingNullValues(timePoint, BravoFix::getHeel,
|
||||
ScalableBearing::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing getPitch(TimePoint timePoint) {
|
||||
BravoFix fixAfter = getFirstFixAtOrAfter(timePoint);
|
||||
if (fixAfter != null && fixAfter.getTimePoint().compareTo(timePoint) == 0) {
|
||||
// exact match of timepoint -> no interpolation necessary
|
||||
return fixAfter.getPitch();
|
||||
}
|
||||
BravoFix fixBefore = getLastFixAtOrBefore(timePoint);
|
||||
if (fixBefore != null && fixBefore.getTimePoint().compareTo(timePoint) == 0) {
|
||||
// exact match of timepoint -> no interpolation necessary
|
||||
return fixBefore.getPitch();
|
||||
}
|
||||
if (fixAfter == null || fixBefore == null) {
|
||||
// the fix is out of the TimeRange where we have fixes
|
||||
return null;
|
||||
}
|
||||
// TODO interpolate if necessary
|
||||
return fixBefore.getPitch();
|
||||
return getValueFromExtendedFixSkippingNullValues(timePoint, BravoFix::getPitch,
|
||||
ScalableBearing::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -185,18 +145,31 @@ public class BravoFixTrackImpl<ItemType extends WithID & Serializable> extends S
|
||||
* Generic implementation to get values from extended fixes. The implementation ensured that in case of simple
|
||||
* {@link BravoFix} instances, just {@code null} is returned. If valid {@link BravoExtendedFix BravoExtendedFixes}
|
||||
* are found, the provided getter is used to extract the value from the identified fix.
|
||||
* <p>
|
||||
*
|
||||
* In case of a mix of {@link BravoFix} and {@link BravoExtendedFix} instances, this method may return null values
|
||||
* for specific {@link TimePoint TimePoints}.
|
||||
* <p>
|
||||
*
|
||||
* If the value extracted by the {@code getter} is {@code null}, the next fix will be probed, until no more fix
|
||||
* exists in that direction or a fix is found that delivers a non-{@code null} value for the {@code getter} result.
|
||||
* This way it is possible to skip fixes that don't make a statement with regard to the attribute extracted by the
|
||||
* {@code getter}.
|
||||
*/
|
||||
private <T, I> T getValueFromExtendedFix(final TimePoint timePoint, final Function<BravoExtendedFix, T> getter,
|
||||
private <T, I, BravoFixType extends BravoFix> T getValueFromExtendedFixSkippingNullValues(
|
||||
final TimePoint timePoint, final Function<BravoFixType, T> getter,
|
||||
Function<T, ScalableValue<I, T>> converterToScalableValue) {
|
||||
if (!hasExtendedFixes) {
|
||||
return null;
|
||||
}
|
||||
final com.sap.sse.common.Util.Function<BravoFix, ScalableValue<I, T>> converter =
|
||||
fix -> converterToScalableValue.apply(getter.apply((BravoExtendedFix) fix));
|
||||
return getInterpolatedValue(timePoint, converter);
|
||||
fix -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
final BravoFixType castFix = (BravoFixType) fix;
|
||||
return converterToScalableValue.apply(getter.apply(castFix));
|
||||
};
|
||||
return getInterpolatedValue(timePoint, converter, fix->{
|
||||
@SuppressWarnings("unchecked")
|
||||
final BravoFixType castFix = (BravoFixType) fix;
|
||||
return getter.apply(castFix) != null;
|
||||
});
|
||||
}
|
||||
|
||||
public BravoExtendedFix getFirstFixAtOrAfterIfExtended(TimePoint timePoint) {
|
||||
@@ -211,31 +184,31 @@ public class BravoFixTrackImpl<ItemType extends WithID & Serializable> extends S
|
||||
|
||||
@Override
|
||||
public Double getPortDaggerboardRakeIfAvailable(TimePoint timePoint) {
|
||||
return getValueFromExtendedFix(timePoint, BravoExtendedFix::getPortDaggerboardRake,
|
||||
return getValueFromExtendedFixSkippingNullValues(timePoint, BravoExtendedFix::getPortDaggerboardRake,
|
||||
ScalableDouble::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getStbdDaggerboardRakeStbdIfAvailable(TimePoint timePoint) {
|
||||
return getValueFromExtendedFix(timePoint, BravoExtendedFix::getStbdDaggerboardRake,
|
||||
return getValueFromExtendedFixSkippingNullValues(timePoint, BravoExtendedFix::getStbdDaggerboardRake,
|
||||
ScalableDouble::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getPortRudderRakeIfAvailable(TimePoint timePoint) {
|
||||
return getValueFromExtendedFix(timePoint, BravoExtendedFix::getPortRudderRake,
|
||||
return getValueFromExtendedFixSkippingNullValues(timePoint, BravoExtendedFix::getPortRudderRake,
|
||||
ScalableDouble::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getStbdRudderRakeIfAvailable(TimePoint timePoint) {
|
||||
return getValueFromExtendedFix(timePoint, BravoExtendedFix::getStbdRudderRake,
|
||||
return getValueFromExtendedFixSkippingNullValues(timePoint, BravoExtendedFix::getStbdRudderRake,
|
||||
ScalableDouble::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing getMastRotationIfAvailable(TimePoint timePoint) {
|
||||
return getValueFromExtendedFix(timePoint, BravoExtendedFix::getMastRotation,
|
||||
return getValueFromExtendedFixSkippingNullValues(timePoint, BravoExtendedFix::getMastRotation,
|
||||
NaivelyScalableBearing::new);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.7"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="com.google.gwt.eclipse.core.GWT_CONTAINER"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.sap.sailing.expeditionconnector.common</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>
|
||||
<buildCommand>
|
||||
<name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>com.google.gwt.eclipse.core.gwtNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
+12
@@ -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.7
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||
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.7
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
eclipse.preferences.version=1
|
||||
pluginProject.extensions=false
|
||||
resolve.requirebundle=false
|
||||
@@ -0,0 +1,10 @@
|
||||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Common
|
||||
Bundle-SymbolicName: com.sap.sailing.expeditionconnector.common
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Export-Package: com.sap.sailing.expeditionconnector
|
||||
Require-Bundle: com.sap.sse.gwt
|
||||
@@ -0,0 +1,4 @@
|
||||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
<?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.expeditionconnector.common</artifactId>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.tycho</groupId>
|
||||
<artifactId>tycho-compiler-plugin</artifactId>
|
||||
<version>${tycho-version}</version>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.tycho</groupId>
|
||||
<artifactId>tycho-source-plugin</artifactId>
|
||||
<version>${tycho-version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>plugin-source</id>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>plugin-source</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.7.0//EN" "http://gwtproject.org/doctype/2.7.0/gwt-module.dtd">
|
||||
<module>
|
||||
<inherits name="com.sap.sse.SSECommon" />
|
||||
<source path='expeditionconnector'/>
|
||||
</module>
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
package com.sap.sailing.expeditionconnector;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.sap.sse.common.impl.NamedImpl;
|
||||
|
||||
public class ExpeditionDeviceConfiguration extends NamedImpl implements Serializable {
|
||||
private static final long serialVersionUID = -7819154195403387909L;
|
||||
|
||||
private final UUID deviceUuid;
|
||||
|
||||
/**
|
||||
* The ID listed as first element in a UDP message coming from Expedition, prefixed by a '#'
|
||||
* character. If {@code null}, no mapping currently exists for the device.
|
||||
*/
|
||||
private final Integer expeditionBoatId;
|
||||
|
||||
public ExpeditionDeviceConfiguration(String name, UUID deviceUuid, Integer expeditionBoatId) {
|
||||
super(name);
|
||||
this.deviceUuid = deviceUuid;
|
||||
this.expeditionBoatId = expeditionBoatId;
|
||||
}
|
||||
|
||||
public UUID getDeviceUuid() {
|
||||
return deviceUuid;
|
||||
}
|
||||
|
||||
public Integer getExpeditionBoatId() {
|
||||
return expeditionBoatId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
|
||||
result = prime * result + ((deviceUuid == null) ? 0 : deviceUuid.hashCode());
|
||||
result = prime * result + ((expeditionBoatId == null) ? 0 : expeditionBoatId.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ExpeditionDeviceConfiguration other = (ExpeditionDeviceConfiguration) obj;
|
||||
if (getName() == null) {
|
||||
if (other.getName() != null)
|
||||
return false;
|
||||
} else if (!getName().equals(other.getName()))
|
||||
return false;
|
||||
if (deviceUuid == null) {
|
||||
if (other.deviceUuid != null)
|
||||
return false;
|
||||
} else if (!deviceUuid.equals(other.deviceUuid))
|
||||
return false;
|
||||
if (expeditionBoatId == null) {
|
||||
if (other.expeditionBoatId != null)
|
||||
return false;
|
||||
} else if (!expeditionBoatId.equals(other.expeditionBoatId))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ExpeditionDeviceConfiguration [deviceUuid=" + deviceUuid + ", expeditionBoatId=" + expeditionBoatId
|
||||
+ ", getName()=" + getName() + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?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="output" path="bin"/>
|
||||
</classpath>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.sap.sailing.expeditionconnector.persistence</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>
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
eclipse.preferences.version=1
|
||||
pluginProject.extensions=false
|
||||
resolve.requirebundle=false
|
||||
@@ -0,0 +1,18 @@
|
||||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Persistence
|
||||
Bundle-SymbolicName: com.sap.sailing.expeditionconnector.persistence
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Activator: com.sap.sailing.expeditionconnector.persistence.impl.Activator
|
||||
Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Import-Package: org.osgi.framework;version="1.3.0"
|
||||
Require-Bundle: com.sap.sailing.domain.persistence,
|
||||
com.sap.sailing.domain.shared.android,
|
||||
com.sap.sailing.domain.common,
|
||||
com.sap.sse.common,
|
||||
com.sap.sse.mongodb,
|
||||
org.mongodb.mongo-java-driver;bundle-version="2.13.0",
|
||||
com.sap.sailing.expeditionconnector.common,
|
||||
com.sap.sailing.server.gateway.serialization.shared.android
|
||||
Export-Package: com.sap.sailing.expeditionconnector.persistence
|
||||
@@ -0,0 +1,4 @@
|
||||
source.. = src/
|
||||
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.expeditionconnector.persistence</artifactId>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
</project>
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence;
|
||||
|
||||
import com.sap.sailing.expeditionconnector.ExpeditionDeviceConfiguration;
|
||||
|
||||
public interface DomainObjectFactory {
|
||||
Iterable<ExpeditionDeviceConfiguration> getExpeditionDeviceConfigurations();
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sailing.expeditionconnector.ExpeditionDeviceConfiguration;
|
||||
|
||||
public interface ExpeditionDeviceIdentifier extends DeviceIdentifier {
|
||||
/**
|
||||
* Derived from an {@link ExpeditionDeviceConfiguration#getDeviceUuid()}.
|
||||
*/
|
||||
UUID getId();
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence;
|
||||
|
||||
/**
|
||||
* A device identifier used to identify an installation of the regatta tool "Expedition"
|
||||
* regarding its basic GPS information.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public interface ExpeditionGpsDeviceIdentifier extends ExpeditionDeviceIdentifier {
|
||||
public static final String TYPE = "EXPEDITION_GPS";
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.sap.sailing.expeditionconnector.persistence.impl.AbstractExpeditionDeviceIdentifierImpl;
|
||||
|
||||
public class ExpeditionGpsDeviceIdentifierImpl extends AbstractExpeditionDeviceIdentifierImpl implements ExpeditionGpsDeviceIdentifier {
|
||||
private static final long serialVersionUID = -4049961972156611640L;
|
||||
|
||||
public ExpeditionGpsDeviceIdentifierImpl(UUID id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifierType() {
|
||||
return ExpeditionGpsDeviceIdentifier.TYPE;
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence;
|
||||
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sailing.server.gateway.serialization.racelog.tracking.DeviceIdentifierJsonHandler;
|
||||
|
||||
public class ExpeditionGpsDeviceIdentifierJsonHandler extends ExpeditionGpsDeviceIdentifierSerializationHandler
|
||||
implements DeviceIdentifierJsonHandler {
|
||||
|
||||
@Override
|
||||
public DeviceIdentifier deserialize(Object serialized, String type, String stringRepresentation)
|
||||
throws TransformationException {
|
||||
return deserialize((String) serialized, type, stringRepresentation);
|
||||
}
|
||||
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class ExpeditionGpsDeviceIdentifierSerializationHandler {
|
||||
private ExpeditionGpsDeviceIdentifier castIdentifier(DeviceIdentifier identifier) throws TransformationException {
|
||||
if (!(identifier instanceof ExpeditionGpsDeviceIdentifier))
|
||||
throw new TransformationException("Expected a ExpeditionGpsDeviceIdentifier, got instead: " + identifier);
|
||||
return (ExpeditionGpsDeviceIdentifier) identifier;
|
||||
}
|
||||
|
||||
public Util.Pair<String, String> serialize(DeviceIdentifier deviceIdentifier) throws TransformationException {
|
||||
return new Util.Pair<String, String>(ExpeditionGpsDeviceIdentifier.TYPE, castIdentifier(deviceIdentifier).getId().toString());
|
||||
}
|
||||
|
||||
public DeviceIdentifier deserialize(String input, String type, String stringRep) throws TransformationException {
|
||||
try {
|
||||
return new ExpeditionGpsDeviceIdentifierImpl(UUID.fromString(input));
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new TransformationException("Invalid string representation of smartphone UUID", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence;
|
||||
|
||||
/**
|
||||
* A device identifier used to identify an installation of the regatta tool "Expedition"
|
||||
* regarding its sensor data beyond the basic GPS and wind information.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public interface ExpeditionSensorDeviceIdentifier extends ExpeditionDeviceIdentifier {
|
||||
public static final String TYPE = "EXPEDITION_SENSOR";
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.sap.sailing.expeditionconnector.persistence.impl.AbstractExpeditionDeviceIdentifierImpl;
|
||||
|
||||
public class ExpeditionSensorDeviceIdentifierImpl extends AbstractExpeditionDeviceIdentifierImpl implements ExpeditionSensorDeviceIdentifier {
|
||||
private static final long serialVersionUID = -4049961972156611640L;
|
||||
|
||||
public ExpeditionSensorDeviceIdentifierImpl(UUID id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifierType() {
|
||||
return ExpeditionSensorDeviceIdentifier.TYPE;
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class ExpeditionSensorDeviceIdentifierSerializationHandler {
|
||||
private ExpeditionSensorDeviceIdentifier castIdentifier(DeviceIdentifier identifier) throws TransformationException {
|
||||
if (!(identifier instanceof ExpeditionSensorDeviceIdentifier))
|
||||
throw new TransformationException("Expected a ExpeditionSensorDeviceIdentifier, got instead: " + identifier);
|
||||
return (ExpeditionSensorDeviceIdentifier) identifier;
|
||||
}
|
||||
|
||||
public Util.Pair<String, String> serialize(DeviceIdentifier deviceIdentifier) throws TransformationException {
|
||||
return new Util.Pair<String, String>(ExpeditionSensorDeviceIdentifier.TYPE, castIdentifier(deviceIdentifier).getId().toString());
|
||||
}
|
||||
|
||||
public DeviceIdentifier deserialize(String input, String type, String stringRep) throws TransformationException {
|
||||
try {
|
||||
return new ExpeditionSensorDeviceIdentifierImpl(UUID.fromString(input));
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new TransformationException("Invalid string representation of smartphone UUID", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence;
|
||||
|
||||
import com.sap.sailing.expeditionconnector.ExpeditionDeviceConfiguration;
|
||||
|
||||
public interface MongoObjectFactory {
|
||||
void storeExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration expeditionDeviceConfiguration);
|
||||
|
||||
void removeExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration expeditionDeviceConfiguration);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence;
|
||||
|
||||
import com.sap.sailing.expeditionconnector.persistence.impl.PersistenceFactoryImpl;
|
||||
import com.sap.sse.mongodb.MongoDBConfiguration;
|
||||
import com.sap.sse.mongodb.MongoDBService;
|
||||
|
||||
public interface PersistenceFactory {
|
||||
PersistenceFactory INSTANCE = new PersistenceFactoryImpl();
|
||||
|
||||
/**
|
||||
* Obtains the domain object factory using the default persistence settings from {@link MongoDBConfiguration#getDefaultConfiguration()}.
|
||||
*/
|
||||
DomainObjectFactory getDefaultDomainObjectFactory();
|
||||
|
||||
DomainObjectFactory getDomainObjectFactory(MongoDBService mongoDbService);
|
||||
|
||||
/**
|
||||
* Obtains the Mongo object factory using the default persistence settings from {@link MongoDBConfiguration#getDefaultConfiguration()}.
|
||||
*/
|
||||
MongoObjectFactory getDefaultMongoObjectFactory();
|
||||
|
||||
MongoObjectFactory getMongoObjectFactory(MongoDBService mongoDbService);
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence.impl;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionDeviceIdentifier;
|
||||
|
||||
public abstract class AbstractExpeditionDeviceIdentifierImpl implements ExpeditionDeviceIdentifier {
|
||||
private static final long serialVersionUID = -6605059302775505785L;
|
||||
private final UUID id;
|
||||
|
||||
public AbstractExpeditionDeviceIdentifierImpl(UUID id) {
|
||||
super();
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStringRepresentation() {
|
||||
return id.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (obj instanceof ExpeditionDeviceIdentifier) &&
|
||||
((ExpeditionDeviceIdentifier) obj).getIdentifierType().equals(getIdentifierType()) &&
|
||||
((ExpeditionDeviceIdentifier) obj).getId().equals(getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 9478 ^ getIdentifierType().hashCode() ^ getId().hashCode();
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence.impl;
|
||||
|
||||
import java.util.Dictionary;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Set;
|
||||
|
||||
import org.osgi.framework.BundleActivator;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceRegistration;
|
||||
|
||||
import com.sap.sailing.domain.persistence.racelog.tracking.DeviceIdentifierMongoHandler;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionGpsDeviceIdentifier;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionSensorDeviceIdentifier;
|
||||
import com.sap.sse.common.TypeBasedServiceFinder;
|
||||
import com.sap.sse.mongodb.MongoDBService;
|
||||
|
||||
public class Activator implements BundleActivator {
|
||||
|
||||
private static BundleContext context;
|
||||
|
||||
/**
|
||||
* Registrations of OSGi services to be de-registered when the bundle shuts down
|
||||
*/
|
||||
private Set<ServiceRegistration<?>> registrations = new HashSet<>();
|
||||
|
||||
static BundleContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
|
||||
*/
|
||||
public void start(BundleContext bundleContext) throws Exception {
|
||||
Activator.context = bundleContext;
|
||||
registrations.add(context.registerService(DeviceIdentifierMongoHandler.class, new ExpeditionGpsDeviceIdentifierMongoHandler(), getDict(ExpeditionGpsDeviceIdentifier.TYPE)));
|
||||
registrations.add(context.registerService(DeviceIdentifierMongoHandler.class, new ExpeditionSensorDeviceIdentifierMongoHandler(), getDict(ExpeditionSensorDeviceIdentifier.TYPE)));
|
||||
for (CollectionNames name : CollectionNames.values()) {
|
||||
MongoDBService.INSTANCE.registerExclusively(CollectionNames.class, name.name());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
|
||||
*/
|
||||
public void stop(BundleContext bundleContext) throws Exception {
|
||||
Activator.context = null;
|
||||
for (ServiceRegistration<?> reg : registrations) {
|
||||
reg.unregister();
|
||||
}
|
||||
registrations.clear();
|
||||
}
|
||||
|
||||
private Dictionary<String, String> getDict(String type) {
|
||||
Dictionary<String, String> properties = new Hashtable<String, String>();
|
||||
properties.put(TypeBasedServiceFinder.TYPE, type);
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence.impl;
|
||||
|
||||
public enum CollectionNames {
|
||||
EXPEDITION_DEVICE_CONFIGURATIONS;
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.sap.sailing.expeditionconnector.ExpeditionDeviceConfiguration;
|
||||
import com.sap.sailing.expeditionconnector.persistence.DomainObjectFactory;
|
||||
|
||||
public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
private final DB db;
|
||||
|
||||
public DomainObjectFactoryImpl(DB db) {
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<ExpeditionDeviceConfiguration> getExpeditionDeviceConfigurations() {
|
||||
final List<ExpeditionDeviceConfiguration> result = new ArrayList<>();
|
||||
final DBCollection expeditionDeviceConfigurationsCollection = db.getCollection(CollectionNames.EXPEDITION_DEVICE_CONFIGURATIONS.name());
|
||||
for (final Object o : expeditionDeviceConfigurationsCollection.find()) {
|
||||
final DBObject dbo = (DBObject) o;
|
||||
final UUID uuid = (UUID) dbo.get(FieldNames.EXPEDITION_DEVICE_CONFIGURATION_UUID.name());
|
||||
final String name = (String) dbo.get(FieldNames.EXPEDITION_DEVICE_CONFIGURATION_NAME.name());
|
||||
final Number boatIdAsNumber = (Number) dbo.get(FieldNames.EXPEDITION_DEVICE_CONFIGURATION_BOAT_ID.name());
|
||||
final Integer boatId = boatIdAsNumber == null ? null : boatIdAsNumber.intValue();
|
||||
result.add(new ExpeditionDeviceConfiguration(name, uuid, boatId));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence.impl;
|
||||
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.persistence.racelog.tracking.DeviceIdentifierMongoHandler;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionGpsDeviceIdentifierSerializationHandler;
|
||||
|
||||
public class ExpeditionGpsDeviceIdentifierMongoHandler extends ExpeditionGpsDeviceIdentifierSerializationHandler
|
||||
implements DeviceIdentifierMongoHandler {
|
||||
@Override
|
||||
public DeviceIdentifier deserialize(Object serialized, String type, String stringRepresentation)
|
||||
throws TransformationException {
|
||||
return deserialize((String) serialized, type, stringRepresentation);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence.impl;
|
||||
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.persistence.racelog.tracking.DeviceIdentifierMongoHandler;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionSensorDeviceIdentifierSerializationHandler;
|
||||
|
||||
public class ExpeditionSensorDeviceIdentifierMongoHandler extends ExpeditionSensorDeviceIdentifierSerializationHandler
|
||||
implements DeviceIdentifierMongoHandler {
|
||||
@Override
|
||||
public DeviceIdentifier deserialize(Object serialized, String type, String stringRepresentation)
|
||||
throws TransformationException {
|
||||
return deserialize((String) serialized, type, stringRepresentation);
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence.impl;
|
||||
|
||||
public enum FieldNames {
|
||||
EXPEDITION_DEVICE_CONFIGURATION_NAME, EXPEDITION_DEVICE_CONFIGURATION_UUID, EXPEDITION_DEVICE_CONFIGURATION_BOAT_ID;
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence.impl;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.WriteConcern;
|
||||
import com.sap.sailing.expeditionconnector.ExpeditionDeviceConfiguration;
|
||||
import com.sap.sailing.expeditionconnector.persistence.MongoObjectFactory;
|
||||
|
||||
public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
private static final Logger logger = Logger.getLogger(MongoObjectFactoryImpl.class.getName());
|
||||
private final DBCollection expeditionDeviceConfigurationsCollection;
|
||||
|
||||
public MongoObjectFactoryImpl(DB db) {
|
||||
this.expeditionDeviceConfigurationsCollection = db.getCollection(CollectionNames.EXPEDITION_DEVICE_CONFIGURATIONS.name());
|
||||
DBObject index = new BasicDBObject();
|
||||
index.put(FieldNames.EXPEDITION_DEVICE_CONFIGURATION_UUID.name(), 1);
|
||||
expeditionDeviceConfigurationsCollection.createIndex(index, new BasicDBObject("unique", true));
|
||||
}
|
||||
|
||||
private BasicDBObject getExpeditionDeviceConfigurationDBKey(ExpeditionDeviceConfiguration expeditionDeviceConfiguration) {
|
||||
final BasicDBObject basicDBObject = new BasicDBObject(FieldNames.EXPEDITION_DEVICE_CONFIGURATION_UUID.name(), expeditionDeviceConfiguration.getDeviceUuid());
|
||||
return basicDBObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration expeditionDeviceConfiguration) {
|
||||
final BasicDBObject key = getExpeditionDeviceConfigurationDBKey(expeditionDeviceConfiguration);
|
||||
final DBObject expeditionDeviceConfigurationDBObject = new BasicDBObject();
|
||||
expeditionDeviceConfigurationDBObject.put(FieldNames.EXPEDITION_DEVICE_CONFIGURATION_UUID.name(), expeditionDeviceConfiguration.getDeviceUuid());
|
||||
expeditionDeviceConfigurationDBObject.put(FieldNames.EXPEDITION_DEVICE_CONFIGURATION_NAME.name(), expeditionDeviceConfiguration.getName());
|
||||
expeditionDeviceConfigurationDBObject.put(FieldNames.EXPEDITION_DEVICE_CONFIGURATION_BOAT_ID.name(), expeditionDeviceConfiguration.getExpeditionBoatId());
|
||||
boolean success = false;
|
||||
int attempt = 0;
|
||||
Exception lastException = null;
|
||||
while (attempt < 5 && !success) {
|
||||
try {
|
||||
expeditionDeviceConfigurationsCollection.update(key, expeditionDeviceConfigurationDBObject, /* upsert */ true, /* multi */ false, WriteConcern.SAFE);
|
||||
success = true;
|
||||
attempt++;
|
||||
} catch (Exception e) {
|
||||
lastException = e;
|
||||
logger.log(Level.WARNING, "Exception trying to write Expedition device configuration. Trying again", e);
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
throw new RuntimeException("Couldn't store Expedition device configuration "+expeditionDeviceConfiguration, lastException);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration expeditionDeviceConfiguration) {
|
||||
expeditionDeviceConfigurationsCollection.remove(getExpeditionDeviceConfigurationDBKey(expeditionDeviceConfiguration), WriteConcern.SAFE);
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.sap.sailing.expeditionconnector.persistence.impl;
|
||||
|
||||
import com.sap.sailing.expeditionconnector.persistence.DomainObjectFactory;
|
||||
import com.sap.sailing.expeditionconnector.persistence.MongoObjectFactory;
|
||||
import com.sap.sailing.expeditionconnector.persistence.PersistenceFactory;
|
||||
import com.sap.sse.mongodb.MongoDBConfiguration;
|
||||
import com.sap.sse.mongodb.MongoDBService;
|
||||
|
||||
public class PersistenceFactoryImpl implements PersistenceFactory {
|
||||
|
||||
@Override
|
||||
public DomainObjectFactory getDomainObjectFactory(MongoDBService mongoDbService) {
|
||||
return new DomainObjectFactoryImpl(mongoDbService.getDB());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MongoObjectFactory getMongoObjectFactory(MongoDBService mongoDbService) {
|
||||
return new MongoObjectFactoryImpl(mongoDbService.getDB());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainObjectFactory getDefaultDomainObjectFactory() {
|
||||
return getDomainObjectFactory(MongoDBConfiguration.getDefaultConfiguration().getService());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MongoObjectFactory getDefaultMongoObjectFactory() {
|
||||
return getMongoObjectFactory(MongoDBConfiguration.getDefaultConfiguration().getService());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="resources"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
source.. = src/
|
||||
source.. = src/,\
|
||||
resources/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
||||
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
#0,1,0.000,2,-129.8,3,2.64,4,-125.4,5,2.54,6,42.8,9,153.4,10,0.00,11,0.0,12,0.12,13,153.4,17,-3.00,18,0.50,19,0.28,20,18.41,22,1.193,48,-33.907350,49,18.419951,50,0.0,51,0.126,146,0.347763,152,109.8,172,1.872,173,2.0,175,1.185,176,294.957,238,3.256*0E
|
||||
#0,1,0.000,2,-130.2,3,2.65,4,-125.7,5,2.54,6,42.7,9,153.4,10,0.00,11,0.0,12,0.13,13,153.4,17,-3.00,18,0.50,19,0.28,20,18.42,22,1.193,48,-33.907350,49,18.419951,50,0.0,51,0.136,146,0.347766,152,109.2,172,1.872,173,2.0,175,1.185,176,294.959,238,3.256*03
|
||||
#0,1,0.000,2,-130.7,3,2.65,4,-126.0,5,2.54,6,42.5,9,153.4,10,0.00,11,0.0,12,0.14,13,153.4,17,-3.00,18,0.50,19,0.28,20,18.42,22,1.193,48,-33.907350,49,18.419951,50,0.0,51,0.146,146,0.347766,152,108.6,172,1.872,173,2.0,175,1.185,176,294.960,238,3.256*0F
|
||||
#0,9,153.4,11,0.0,12,0.15,152,107.9,238,3.256*32
|
||||
#0,1,0.000,2,-131.2,3,2.65,4,-126.4,5,2.54,6,42.3,9,153.4,10,0.00,11,0.0,12,0.16,13,153.4,17,-3.00,18,0.50,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419951,50,0.0,51,0.155,146,0.347769,152,107.1,172,1.872,173,2.0,175,1.184,176,294.959,238,3.256*04
|
||||
#0,1,0.000,2,-132.4,3,2.65,4,-127.4,5,2.54,6,41.9,9,153.4,10,0.00,11,0.0,12,0.18,13,153.4,17,-3.00,18,0.50,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419951,50,0.0,51,0.176,146,0.347769,152,105.3,172,1.872,173,2.0,175,1.184,176,294.954,238,3.255*08
|
||||
#0,1,0.000,2,-133.1,3,2.65,4,-127.9,5,2.54,6,41.7,9,153.4,10,0.00,11,0.0,12,0.18,13,153.4,17,-3.00,18,0.50,19,0.28,20,18.42,22,1.193,48,-33.907350,49,18.419951,50,0.0,51,0.176,146,0.347772,152,104.3,172,1.872,173,2.0,175,1.183,176,294.956,238,3.254*01
|
||||
#0,1,0.000,2,-133.8,3,2.66,4,-128.4,5,2.54,6,41.5,9,153.4,10,0.00,11,0.0,12,0.17,13,153.4,17,-3.00,18,0.50,19,0.28,20,18.42,22,1.193,48,-33.907350,49,18.419951,50,0.0,51,0.173,146,0.347772,152,103.2,172,1.872,173,2.0,175,1.184,176,294.956,238,3.254*00
|
||||
#0,1,0.000,2,-134.5,3,2.66,4,-128.9,5,2.54,6,41.3,9,153.4,10,0.00,11,0.0,12,0.17,13,153.4,17,-3.00,18,0.50,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419951,50,0.0,51,0.167,146,0.347775,172,1.872,173,2.0,175,1.184,176,294.954*0F
|
||||
#0,1,0.000,2,-135.1,3,2.66,4,-129.5,5,2.54,6,41.1,9,153.4,10,0.00,11,0.0,12,0.16,13,153.4,17,-3.00,18,0.50,19,0.28,20,18.42,22,1.193,48,-33.907350,49,18.419951,50,0.0,51,0.159,146,0.347775,152,102.1,172,1.872,173,2.0,175,1.184,176,294.956,238,3.253*00
|
||||
#0,1,0.000,2,-135.8,3,2.66,4,-130.0,5,2.54,6,40.9,9,153.4,10,0.00,11,0.0,12,0.15,13,153.4,17,-3.00,18,0.50,19,0.28,20,18.42,22,1.193,48,-33.907350,49,18.419951,50,0.0,51,0.152,146,0.347775,152,101.0,172,1.872,173,2.0,175,1.184,176,294.957,238,3.252*07
|
||||
#0,1,0.000,2,-136.3,3,2.66,4,-130.6,5,2.54,6,40.6,9,153.4,10,0.00,11,0.0,12,0.15,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.193,48,-33.907350,49,18.419951,50,0.0,51,0.145,146,0.347778,152,99.9,172,1.872,173,2.0,175,1.184,176,294.958,238,3.252*3A
|
||||
#0,1,0.000,2,-136.8,3,2.66,4,-131.0,5,2.54,6,40.4,9,153.4,10,0.00,11,0.0,12,0.14,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.193,48,-33.907350,49,18.419951,50,0.0,51,0.138,146,0.347778,152,98.9,172,1.872,173,2.0,175,1.184,176,294.956,238,3.251*33
|
||||
#0,1,0.000,2,-137.2,3,2.66,4,-131.5,5,2.54,6,40.3,9,153.4,10,0.00,11,0.0,12,0.14,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.193,48,-33.907350,49,18.419951,50,0.0,51,0.131,146,0.347781,152,97.9,172,1.872,173,2.0,175,1.183,176,294.957,238,3.251*3C
|
||||
#0,9,153.4,11,0.0,12,0.13,152,97.0,238,3.250*03
|
||||
#0,1,0.000,2,-137.8,3,2.66,4,-132.2,5,2.54,6,39.9,9,153.4,10,0.00,11,0.0,12,0.16,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419951,50,0.0,51,0.160,146,0.347781,152,95.6,172,1.872,173,2.0,175,1.184,176,294.956,238,3.250*38
|
||||
#0,1,0.000,2,-137.8,3,2.66,4,-132.2,5,2.54,6,39.9,9,153.4,10,0.00,11,0.0,12,0.16,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419951,50,0.0,51,0.160,146,0.347781,152,95.6,172,1.872,173,2.0,175,1.184,176,294.956,238,3.249*30
|
||||
#0,1,0.000,2,-138.0,3,2.67,4,-132.6,5,2.54,6,39.6,9,153.4,10,0.00,11,0.0,12,0.19,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419951,50,0.0,51,0.193,146,0.347784,152,94.7,172,1.872,173,2.0,175,1.184,176,294.954,238,3.249*39
|
||||
#0,1,0.000,2,-138.0,3,2.67,4,-132.8,5,2.54,6,39.5,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.193,48,-33.907350,49,18.419951,50,0.0,51,0.209,146,0.347786,152,94.4,172,1.872,173,2.0,175,1.184,176,294.954,238,3.250*36
|
||||
#0,1,0.000,2,-138.0,3,2.67,4,-132.9,5,2.54,6,39.4,9,153.4,10,0.00,11,0.0,12,0.22,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.193,48,-33.907350,49,18.419951,50,0.0,51,0.223,146,0.347786,152,94.2,172,1.872,173,2.0,175,1.184,176,294.955,238,3.251*3B
|
||||
#0,1,0.000,2,-138.0,3,2.67,4,-133.0,5,2.54,6,39.3,9,153.4,10,0.00,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.192,48,-33.907350,49,18.419951,50,0.0,51,0.233,146,0.347786,152,94.2,172,1.872,173,2.0,175,1.184,176,294.954,238,3.252*05
|
||||
#0,1,0.000,2,-138.0,3,2.67,4,-133.1,5,2.54,6,39.1,9,153.4,10,0.00,11,0.0,12,0.23,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.192,48,-33.907350,49,18.419951,50,0.0,51,0.233,146,0.347789,152,94.0,172,1.872,173,2.0,175,1.184,176,294.951,238,3.254*3A
|
||||
#0,1,0.000,2,-138.0,3,2.67,4,-133.2,5,2.54,6,39.0,9,153.4,10,0.00,11,0.0,12,0.23,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.193,48,-33.907350,49,18.419951,50,0.0,51,0.230,146,0.347789,152,93.8,172,1.872,173,2.0,175,1.184,176,294.951,238,3.254*35
|
||||
#0,1,0.000,2,-138.1,3,2.67,4,-133.3,5,2.55,6,38.9,9,153.4,10,0.00,11,0.0,12,0.23,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.193,48,-33.907350,49,18.419951,50,0.0,51,0.223,146,0.347792,152,93.6,172,1.872,173,2.0,175,1.185,176,294.951,238,3.255*3B
|
||||
#0,1,0.000,2,-138.2,3,2.68,4,-133.5,5,2.55,6,38.7,9,153.4,10,0.00,11,0.0,12,0.22,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.192,48,-33.907350,49,18.419951,50,0.0,51,0.217,146,0.347792,152,93.3,172,1.872,173,2.0,175,1.184,176,294.952,238,3.257*3C
|
||||
#0,1,0.000,2,-138.4,3,2.68,4,-133.7,5,2.55,6,38.6,9,153.4,10,0.00,11,0.0,12,0.22,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.193,48,-33.907350,49,18.419951,50,0.0,51,0.210,146,0.347792,152,93.0,172,1.872,173,2.0,175,1.184,176,294.954,238,3.259*34
|
||||
#0,1,0.000,2,-138.9,3,2.68,4,-134.1,5,2.55,6,38.2,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419951,50,0.0,51,0.210,146,0.347795,152,92.7,172,1.872,173,2.0,175,1.184,176,294.954,238,3.261*35
|
||||
#0,9,153.4,11,0.0,12,0.21,152,91.7,238,3.264*04
|
||||
#0,1,0.000,2,-139.1,3,2.69,4,-134.4,5,2.56,6,38.1,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.193,48,-33.907350,49,18.419951,50,0.0,51,0.210,146,0.347798,152,91.2,172,1.872,173,2.0,175,1.185,176,294.958,238,3.270*3F
|
||||
#0,1,0.000,2,-139.4,3,2.69,4,-134.7,5,2.56,6,37.9,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.193,48,-33.907350,49,18.419951,50,0.0,51,0.207,146,0.347798,152,90.7,172,1.872,173,2.0,175,1.185,176,294.958,238,3.274*3B
|
||||
#0,1,0.000,2,-139.6,3,2.69,4,-134.9,5,2.56,6,37.8,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419951,50,0.0,51,0.207,146,0.347798,152,90.2,172,1.872,173,2.0,175,1.185,176,294.960,238,3.278*35
|
||||
#0,1,0.000,2,-139.8,3,2.70,4,-135.1,5,2.57,6,37.6,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419951,50,0.0,51,0.207,146,0.347801,152,89.7,172,1.872,173,2.0,175,1.185,176,294.961,238,3.282*30
|
||||
#0,1,0.000,2,-139.9,3,2.70,4,-135.4,5,2.57,6,37.5,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419951,50,0.0,51,0.207,146,0.347801,152,89.3,172,1.872,173,2.0,175,1.185,176,294.960,238,3.287*34
|
||||
#0,1,0.000,2,-140.0,3,2.70,4,-135.5,5,2.58,6,37.3,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.207,146,0.347804,152,89.0,172,1.872,173,2.0,175,1.185,176,294.962,238,3.292*39
|
||||
#0,1,0.000,2,-140.0,3,2.71,4,-135.7,5,2.58,6,37.2,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.193,48,-33.907350,49,18.419950,50,0.0,51,0.207,146,0.347804,152,88.7,172,1.872,173,2.0,175,1.185,176,294.958,238,3.297*30
|
||||
#0,1,0.000,2,-140.0,3,2.71,4,-135.8,5,2.58,6,37.1,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.193,48,-33.907350,49,18.419950,50,0.0,51,0.207,146,0.347804,152,88.4,172,1.872,173,2.0,175,1.185,176,294.956,238,3.302*3F
|
||||
#0,1,0.000,2,-140.0,3,2.72,4,-135.9,5,2.59,6,36.9,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.207,146,0.347807,152,88.3,172,1.872,173,2.0,175,1.185,176,294.956,238,3.308*3A
|
||||
#0,1,0.000,2,-140.0,3,2.72,4,-136.0,5,2.59,6,36.8,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.207,146,0.347807,152,88.1,172,1.872,173,2.0,175,1.185,176,294.956,238,3.313*39
|
||||
#0,1,0.000,2,-140.2,3,2.73,4,-136.2,5,2.60,6,36.5,9,153.4,10,0.00,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.207,146,0.347810,172,1.872,173,2.0,175,1.184,176,294.951*33
|
||||
#0,9,153.4,11,0.0,12,0.21,152,87.6,238,3.318*08
|
||||
#0,1,0.000,2,-140.4,3,2.73,4,-136.3,5,2.60,6,36.4,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.207,146,0.347810,152,87.3,172,1.872,173,2.0,175,1.184,176,294.949,238,3.328*35
|
||||
#0,1,0.000,2,-140.6,3,2.73,4,-136.5,5,2.61,6,36.2,9,153.4,10,0.00,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.214,146,0.347813,152,87.3,172,1.872,173,2.0,175,1.184,176,294.950,238,3.333*05
|
||||
#0,1,0.000,2,-141.0,3,2.74,4,-136.8,5,2.61,6,36.0,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.222,146,0.347813,152,86.9,172,1.872,173,2.0,175,1.184,176,294.951,238,3.337*31
|
||||
#0,1,0.000,2,-141.4,3,2.74,4,-137.1,5,2.61,6,35.9,9,153.4,10,0.00,11,0.0,12,0.22,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.193,48,-33.907350,49,18.419950,50,0.0,51,0.229,146,0.347815,152,86.4,172,1.872,173,2.0,175,1.184,176,294.951,238,3.337*36
|
||||
#0,1,0.000,2,-141.8,3,2.74,4,-137.4,5,2.62,6,35.7,9,153.4,10,0.00,11,0.0,12,0.23,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.212,146,0.347815,152,85.8,172,1.872,173,2.0,175,1.184,176,294.953,238,3.341*35
|
||||
#0,1,0.000,2,-142.3,3,2.75,4,-137.8,5,2.62,6,35.5,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.193,48,-33.907350,49,18.419950,50,0.0,51,0.195,146,0.347815,152,85.1,172,1.872,173,2.0,175,1.185,176,294.954,238,3.345*35
|
||||
#0,1,0.000,2,-142.8,3,2.75,4,-138.2,5,2.62,6,35.3,9,153.4,10,0.00,11,0.0,12,0.20,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.178,146,0.347818,152,84.4,172,1.872,173,2.0,175,1.185,176,294.954,238,3.349*3B
|
||||
#0,1,0.000,2,-143.3,3,2.75,4,-138.6,5,2.63,6,35.0,9,153.4,10,0.00,11,0.0,12,0.18,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.193,48,-33.907350,49,18.419950,50,0.0,51,0.161,146,0.347818,152,83.6,172,1.872,173,2.0,175,1.185,176,294.954,238,3.353*3B
|
||||
#0,1,0.000,2,-143.8,3,2.75,4,-139.1,5,2.63,6,34.8,9,153.4,10,0.00,11,0.0,12,0.16,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.144,146,0.347821,152,82.7,172,1.872,173,2.0,175,1.186,176,294.955,238,3.357*3B
|
||||
#0,1,0.000,2,-144.6,3,2.76,4,-139.9,5,2.63,6,34.4,9,153.4,10,0.00,11,0.0,12,0.14,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.193,48,-33.907350,49,18.419950,50,0.0,51,0.158,146,0.347821,152,81.9,172,1.872,173,2.0,175,1.186,176,294.962,238,3.360*37
|
||||
#0,1,0.000,2,-144.6,3,2.76,4,-139.9,5,2.63,6,34.4,9,153.4,10,0.00,11,0.0,12,0.16,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.193,48,-33.907350,49,18.419950,50,0.0,51,0.158,146,0.347821,152,80.3,172,1.872,173,2.0,175,1.186,176,294.962,238,3.364*3A
|
||||
#0,9,153.4,11,0.0,12,0.16,152,80.3,238,3.370*00
|
||||
#0,1,0.000,2,-145.3,3,2.76,4,-140.5,5,2.64,6,34.1,9,153.4,10,0.00,11,0.0,12,0.15,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.193,48,-33.907350,49,18.419950,50,0.0,51,0.146,146,0.347824,152,78.9,172,1.872,173,2.0,175,1.185,176,294.964,238,3.370*3B
|
||||
#0,1,0.000,2,-145.5,3,2.76,4,-140.8,5,2.64,6,33.9,9,153.4,10,0.00,11,0.0,12,0.15,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.193,48,-33.907350,49,18.419950,50,0.0,51,0.146,146,0.347827,152,78.4,172,1.872,173,2.0,175,1.185,176,294.962,238,3.375*32
|
||||
#0,1,0.000,2,-145.6,3,2.76,4,-141.0,5,2.64,6,33.7,9,153.4,10,0.00,11,0.0,12,0.15,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.145,146,0.347827,152,77.9,172,1.872,173,2.0,175,1.185,176,294.965,238,3.377*30
|
||||
#0,1,0.000,2,-145.7,3,2.76,4,-141.2,5,2.64,6,33.6,9,153.4,10,0.00,11,0.0,12,0.14,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.144,146,0.347827,152,77.5,172,1.872,173,2.0,175,1.184,176,294.964,238,3.379*33
|
||||
#0,1,0.000,2,-145.7,3,2.76,4,-141.4,5,2.64,6,33.5,9,153.4,10,0.00,11,0.0,12,0.17,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.168,146,0.347830,152,77.3,172,1.872,173,2.0,175,1.184,176,294.962,238,3.381*3A
|
||||
#0,1,0.000,2,-145.7,3,2.76,4,-141.5,5,2.64,6,33.3,9,153.4,10,0.00,11,0.0,12,0.19,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.188,146,0.347830,152,77.0,172,1.872,173,2.0,175,1.183,176,294.963,238,3.383*3A
|
||||
#0,1,0.000,2,-145.7,3,2.76,4,-141.6,5,2.65,6,33.2,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.205,146,0.347833,152,76.9,172,1.872,173,2.0,175,1.183,176,294.963,238,3.385*3A
|
||||
#0,1,0.000,2,-145.6,3,2.76,4,-141.6,5,2.65,6,33.1,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.212,146,0.347833,152,76.8,172,1.872,173,2.0,175,1.183,176,294.963,238,3.387*3D
|
||||
#0,1,0.000,2,-145.6,3,2.76,4,-141.7,5,2.65,6,32.9,9,153.4,10,0.00,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.218,146,0.347833,152,76.8,172,1.872,173,2.0,175,1.183,176,294.959,238,3.388*09
|
||||
#0,1,0.000,2,-145.5,3,2.76,4,-141.7,5,2.65,6,32.8,9,153.4,10,0.00,11,0.0,12,0.22,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.222,146,0.347836,152,76.7,172,1.872,173,2.0,175,1.184,176,294.958,238,3.390*37
|
||||
#0,1,0.000,2,-145.4,3,2.77,4,-141.8,5,2.65,6,32.6,9,153.4,10,0.00,11,0.0,12,0.22,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.218,146,0.347839,152,76.6,172,1.872,173,2.0,175,1.184,176,294.961,238,3.390*3B
|
||||
#0,9,153.4,11,0.0,12,0.22,152,76.4,238,3.392*05
|
||||
#0,1,0.000,2,-145.3,3,2.77,4,-141.8,5,2.65,6,32.4,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.208,146,0.347839,152,76.3,172,1.872,173,2.0,175,1.184,176,294.959,238,3.395*34
|
||||
#0,1,0.000,2,-145.3,3,2.77,4,-141.9,5,2.65,6,32.3,9,153.4,10,0.00,11,0.0,12,0.20,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.197,146,0.347839,152,76.2,172,1.872,173,2.0,175,1.184,176,294.960,238,3.396*3E
|
||||
#0,1,0.000,2,-145.2,3,2.77,4,-141.9,5,2.66,6,32.2,9,153.4,10,0.00,11,0.0,12,0.20,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.43,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.197,146,0.347841,152,76.2,172,1.872,173,2.0,175,1.184,176,294.959,238,3.398*37
|
||||
#0,1,0.000,2,-145.1,3,2.77,4,-141.9,5,2.66,6,32.1,9,153.4,10,0.00,11,0.0,12,0.20,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.43,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.201,146,0.347841,152,76.2,172,1.872,173,2.0,175,1.184,176,294.959,238,3.400*3D
|
||||
#0,1,0.000,2,-144.9,3,2.77,4,-141.9,5,2.66,6,32.0,9,153.4,10,0.00,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.43,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.207,146,0.347844,172,1.872,173,2.0,175,1.184,176,294.958*3D
|
||||
#0,1,0.000,2,-144.8,3,2.78,4,-141.9,5,2.66,6,31.9,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.43,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.207,146,0.347844,152,76.2,172,1.872,173,2.0,175,1.184,176,294.958,238,3.402*30
|
||||
#0,1,0.000,2,-144.6,3,2.78,4,-141.8,5,2.66,6,31.8,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.207,146,0.347844,152,76.3,172,1.872,173,2.0,175,1.184,176,294.958,238,3.404*38
|
||||
#0,1,0.000,2,-144.4,3,2.78,4,-141.8,5,2.66,6,31.7,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.214,146,0.347847,152,76.4,172,1.872,173,2.0,175,1.184,176,294.957,238,3.406*3E
|
||||
#0,1,0.000,2,-144.2,3,2.78,4,-141.7,5,2.67,6,31.6,9,153.4,10,0.00,11,0.0,12,0.22,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.220,146,0.347847,152,76.5,172,1.872,173,2.0,175,1.184,176,294.958,238,3.408*33
|
||||
#0,1,0.000,2,-144.0,3,2.79,4,-141.6,5,2.67,6,31.5,9,153.4,10,0.00,11,0.0,12,0.22,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.226,146,0.347850,152,76.6,172,1.872,173,2.0,175,1.185,176,294.958,238,3.410*3A
|
||||
#0,1,0.000,2,-143.8,3,2.79,4,-141.5,5,2.67,6,31.4,9,153.4,10,0.00,11,0.0,12,0.24,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419950,50,0.0,51,0.244,146,0.347850,152,76.8,172,1.872,173,2.0,175,1.184,176,294.957,238,3.413*36
|
||||
#0,1,0.000,2,-143.7,3,2.79,4,-141.5,5,2.67,6,31.3,9,153.4,10,0.00,11,0.0,12,0.24,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.244,146,0.347853,152,77.0,172,1.872,173,2.0,175,1.185,176,294.959,238,3.413*33
|
||||
#0,9,153.4,11,0.0,12,0.24,152,77.1,238,3.416*0C
|
||||
#0,1,0.000,2,-143.6,3,2.79,4,-141.5,5,2.67,6,31.1,9,153.4,10,0.00,11,0.0,12,0.24,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.244,146,0.347853,152,77.1,172,1.872,173,2.0,175,1.185,176,294.960,238,3.417*3E
|
||||
#0,1,0.000,2,-143.6,3,2.80,4,-141.5,5,2.67,6,31.0,9,153.4,10,0.00,11,0.0,12,0.24,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.193,48,-33.907350,49,18.419949,50,0.0,51,0.244,146,0.347856,152,77.0,172,1.872,173,2.0,175,1.184,176,294.959,238,3.418*38
|
||||
#0,1,0.000,2,-143.7,3,2.80,4,-141.5,5,2.67,6,30.9,9,153.4,10,0.00,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.193,48,-33.907350,49,18.419949,50,0.0,51,0.237,146,0.347856,152,77.0,172,1.872,173,2.0,175,1.184,176,294.959,238,3.419*01
|
||||
#0,1,0.000,2,-143.8,3,2.80,4,-141.6,5,2.67,6,30.8,9,153.4,10,0.00,11,0.0,12,0.24,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.231,146,0.347856,152,77.0,172,1.872,173,2.0,175,1.184,176,294.959,238,3.420*34
|
||||
#0,1,0.000,2,-143.9,3,2.80,4,-141.7,5,2.67,6,30.7,9,153.4,10,0.00,11,0.0,12,0.23,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.231,146,0.347859,152,76.8,172,1.872,173,2.0,175,1.185,176,294.961,238,3.420*30
|
||||
#0,1,0.000,2,-144.0,3,2.80,4,-141.8,5,2.67,6,30.5,9,153.4,10,0.00,11,0.0,12,0.23,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.231,146,0.347859,152,76.6,172,1.872,173,2.0,175,1.185,176,294.961,238,3.421*3C
|
||||
#0,1,0.000,2,-144.1,3,2.81,4,-141.9,5,2.67,6,30.4,9,153.4,10,0.00,11,0.0,12,0.23,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.231,146,0.347862,152,76.4,172,1.872,173,2.0,175,1.184,176,294.959,238,3.421*3C
|
||||
#0,1,0.000,2,-144.3,3,2.81,4,-142.1,5,2.67,6,30.2,9,153.4,10,0.00,11,0.0,12,0.23,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.251,146,0.347862,152,76.1,172,1.872,173,2.0,175,1.185,176,294.962,238,3.422*3A
|
||||
#0,1,0.000,2,-144.4,3,2.81,4,-142.2,5,2.67,6,30.1,9,153.4,10,0.00,11,0.0,12,0.25,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.271,146,0.347862,152,75.9,172,1.872,173,2.0,175,1.185,176,294.963,238,3.422*33
|
||||
#0,1,0.000,2,-144.7,3,2.82,4,-142.5,5,2.67,6,29.8,9,153.4,10,0.00,11,0.0,12,0.27,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.258,146,0.347865,152,75.6,172,1.872,173,2.0,175,1.185,176,294.961,238,3.422*37
|
||||
#0,1,0.000,2,-144.8,3,2.82,4,-142.6,5,2.67,6,29.7,9,153.4,10,0.00,11,0.0,12,0.26,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.193,48,-33.907350,49,18.419949,50,0.0,51,0.252,146,0.347867,152,75.1,172,1.872,173,2.0,175,1.185,176,294.962,238,3.423*39
|
||||
#0,9,153.4,11,0.0,12,0.25,152,74.8,238,3.423*01
|
||||
#0,1,0.000,2,-144.8,3,2.82,4,-142.7,5,2.67,6,29.6,9,153.4,10,0.00,11,0.0,12,0.25,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.193,48,-33.907350,49,18.419949,50,0.0,51,0.245,146,0.347867,152,74.6,172,1.872,173,2.0,175,1.185,176,294.962,238,3.422*3B
|
||||
#0,1,0.000,2,-144.9,3,2.82,4,-142.8,5,2.67,6,29.5,9,153.4,10,0.00,11,0.0,12,0.24,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.238,146,0.347867,152,74.4,172,1.872,173,2.0,175,1.185,176,294.964,238,3.422*39
|
||||
#0,1,0.000,2,-145.0,3,2.83,4,-142.9,5,2.67,6,29.3,9,153.4,10,0.00,11,0.0,12,0.23,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.232,146,0.347870,152,74.2,172,1.872,173,2.0,175,1.184,176,294.963,238,3.422*3D
|
||||
#0,1,0.000,2,-145.0,3,2.83,4,-143.0,5,2.67,6,29.2,9,153.4,10,0.00,11,0.0,12,0.23,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.225,146,0.347870,152,74.1,172,1.872,173,2.0,175,1.185,176,294.962,238,3.421*32
|
||||
#0,1,0.000,2,-145.0,3,2.83,4,-143.0,5,2.67,6,29.1,9,153.4,10,0.00,11,0.0,12,0.22,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.219,146,0.347873,152,73.9,172,1.872,173,2.0,175,1.185,176,294.964,238,3.421*35
|
||||
#0,1,0.000,2,-145.0,3,2.83,4,-143.1,5,2.67,6,29.0,9,153.4,10,0.00,11,0.0,12,0.22,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.193,48,-33.907350,49,18.419949,50,0.0,51,0.219,146,0.347873,152,73.8,172,1.872,173,2.0,175,1.185,176,294.961,238,3.420*32
|
||||
#0,1,0.000,2,-145.0,3,2.83,4,-143.1,5,2.67,6,28.9,9,153.4,10,0.00,11,0.0,12,0.22,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.219,146,0.347873,152,73.8,172,1.872,173,2.0,175,1.185,176,294.962,238,3.418*30
|
||||
#0,1,0.000,2,-145.0,3,2.83,4,-143.1,5,2.67,6,28.8,9,153.4,10,0.00,11,0.0,12,0.22,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.219,146,0.347876,152,73.7,172,1.872,173,2.0,175,1.185,176,294.961,238,3.417*37
|
||||
#0,1,0.000,2,-144.9,3,2.83,4,-143.2,5,2.67,6,28.7,9,153.4,10,0.00,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.219,146,0.347876,152,73.7,172,1.872,173,2.0,175,1.184,176,294.961,238,3.416*03
|
||||
#0,1,0.000,2,-144.8,3,2.82,4,-143.2,5,2.66,6,28.5,9,153.4,10,0.00,11,0.0,12,0.23,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907349,49,18.419949,50,0.0,51,0.226,146,0.347879,172,1.872,173,2.0,175,1.185,176,294.962*07
|
||||
#0,1,0.000,2,-144.7,3,2.82,4,-143.2,5,2.66,6,28.4,9,153.4,10,0.00,11,0.0,12,0.23,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907349,49,18.419949,50,0.0,51,0.233,146,0.347879,152,73.6,172,1.872,173,2.0,175,1.185,176,294.960,238,3.414*30
|
||||
#0,9,153.4,11,0.0,12,0.23,152,73.7,238,3.411*0E
|
||||
#0,1,0.000,2,-144.7,3,2.82,4,-143.1,5,2.66,6,28.3,9,153.4,10,0.00,11,0.0,12,0.23,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907349,49,18.419949,50,0.0,51,0.227,146,0.347882,152,73.7,172,1.872,173,2.0,175,1.185,176,294.960,238,3.409*38
|
||||
#0,1,0.000,2,-144.6,3,2.81,4,-143.1,5,2.66,6,28.2,9,153.4,10,0.00,11,0.0,12,0.22,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907349,49,18.419949,50,0.0,51,0.220,146,0.347882,152,73.7,172,1.872,173,2.0,175,1.185,176,294.958,238,3.406*39
|
||||
#0,1,0.000,2,-144.5,3,2.81,4,-143.1,5,2.66,6,28.1,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907349,49,18.419949,50,0.0,51,0.214,146,0.347885,152,73.7,172,1.872,173,2.0,175,1.185,176,294.955,238,3.406*34
|
||||
#0,1,0.000,2,-144.4,3,2.81,4,-143.1,5,2.66,6,28.0,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907349,49,18.419949,50,0.0,51,0.207,146,0.347885,152,73.9,172,1.872,173,2.0,175,1.185,176,294.955,238,3.402*3C
|
||||
#0,1,0.000,2,-144.3,3,2.80,4,-143.0,5,2.65,6,28.0,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907349,49,18.419949,50,0.0,51,0.201,146,0.347885,152,73.9,172,1.872,173,2.0,175,1.185,176,294.955,238,3.402*3E
|
||||
#0,1,0.000,2,-144.2,3,2.80,4,-143.0,5,2.65,6,27.9,9,153.4,10,0.00,11,0.0,12,0.20,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907349,49,18.419949,50,0.0,51,0.201,146,0.347888,152,73.9,172,1.872,173,2.0,175,1.185,176,294.955,238,3.399*30
|
||||
#0,1,0.000,2,-144.0,3,2.79,4,-142.9,5,2.65,6,27.8,9,153.4,10,0.00,11,0.0,12,0.20,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907349,49,18.419949,50,0.0,51,0.202,146,0.347888,152,74.0,172,1.872,173,2.0,175,1.185,176,294.957,238,3.397*3C
|
||||
#0,1,0.000,2,-143.9,3,2.78,4,-142.9,5,2.65,6,27.7,9,153.4,10,0.00,11,0.0,12,0.20,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907349,49,18.419949,50,0.0,51,0.202,146,0.347891,152,74.1,172,1.872,173,2.0,175,1.185,176,294.955,238,3.394*34
|
||||
#0,1,0.000,2,-143.5,3,2.77,4,-142.7,5,2.64,6,27.6,9,153.4,10,0.00,11,0.0,12,0.20,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.193,48,-33.907349,49,18.419949,50,0.0,51,0.178,146,0.347891,152,74.2,172,1.872,173,2.0,175,1.185,176,294.957,238,3.391*32
|
||||
#0,1,0.000,2,-143.3,3,2.76,4,-142.6,5,2.64,6,27.5,9,153.4,10,0.00,11,0.0,12,0.18,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907349,49,18.419949,50,0.0,51,0.185,146,0.347894,152,74.6,172,1.872,173,2.0,175,1.185,176,294.958,238,3.388*39
|
||||
#0,1,0.000,2,-143.0,3,2.75,4,-142.5,5,2.64,6,27.5,9,153.4,10,0.00,11,0.0,12,0.19,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.193,48,-33.907349,49,18.419949,50,0.0,51,0.193,146,0.347894,152,74.8,172,1.872,173,2.0,175,1.185,176,294.960,238,3.382*32
|
||||
#0,9,153.4,11,0.0,12,0.19,152,75.1,238,3.379*0E
|
||||
#0,1,0.000,2,-142.8,3,2.74,4,-142.3,5,2.63,6,27.4,9,153.4,10,0.00,11,0.0,12,0.20,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.192,48,-33.907349,49,18.419949,50,0.0,51,0.200,146,0.347896,152,75.4,172,1.872,173,2.0,175,1.185,176,294.961,238,3.375*3F
|
||||
#0,1,0.000,2,-142.4,3,2.73,4,-142.1,5,2.63,6,27.4,9,153.4,10,0.00,11,0.0,12,0.18,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907349,49,18.419949,50,0.0,51,0.180,146,0.347896,152,75.7,172,1.872,173,2.0,175,1.185,176,294.960,238,3.372*32
|
||||
#0,1,0.000,2,-142.1,3,2.72,4,-141.9,5,2.63,6,27.4,9,153.4,10,0.00,11,0.0,12,0.16,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907349,49,18.419949,50,0.0,51,0.159,146,0.347896,152,76.1,172,1.872,173,2.0,175,1.185,176,294.961,238,3.368*38
|
||||
#0,1,0.000,2,-141.7,3,2.71,4,-141.7,5,2.63,6,27.4,9,153.4,10,0.00,11,0.0,12,0.16,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907349,49,18.419949,50,0.0,51,0.156,146,0.347899,152,76.6,172,1.872,173,2.0,175,1.184,176,294.962,238,3.365*38
|
||||
#0,1,0.000,2,-141.3,3,2.70,4,-141.5,5,2.62,6,27.4,9,153.4,10,0.00,11,0.0,12,0.16,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907349,49,18.419949,50,0.0,51,0.156,146,0.347899,152,77.1,172,1.872,173,2.0,175,1.184,176,294.960,238,3.361*3E
|
||||
#0,1,0.000,2,-141.0,3,2.69,4,-141.2,5,2.62,6,27.3,9,153.4,10,0.00,11,0.0,12,0.16,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.159,146,0.347902,152,77.6,172,1.872,173,2.0,175,1.184,176,294.960,238,3.358*3C
|
||||
#0,1,0.000,2,-140.6,3,2.68,4,-141.0,5,2.62,6,27.3,9,153.4,10,0.00,11,0.0,12,0.15,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.149,146,0.347902,152,78.1,172,1.872,173,2.0,175,1.185,176,294.961,238,3.355*3F
|
||||
#0,1,0.000,2,-140.2,3,2.67,4,-140.7,5,2.62,6,27.3,9,153.4,10,0.00,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.193,48,-33.907350,49,18.419949,50,0.0,51,0.138,146,0.347902,152,78.1,172,1.872,173,2.0,175,1.184,176,294.959,238,3.351*0C
|
||||
#0,1,0.000,2,-139.4,3,2.65,4,-140.2,5,2.61,6,27.3,9,153.4,10,0.00,11,0.0,12,0.15,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419949,50,0.0,51,0.155,146,0.347905,172,1.872,173,2.0,175,1.184,176,294.957*01
|
||||
#0,1,0.000,2,-139.1,3,2.64,4,-139.9,5,2.61,6,27.3,9,153.4,10,0.00,11,0.0,12,0.17,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.193,48,-33.907350,49,18.419948,50,0.0,51,0.168,146,0.347908,152,79.7,172,1.872,173,2.0,175,1.185,176,294.959,238,3.341*3E
|
||||
#0,9,153.4,11,0.0,12,0.17,152,80.2,238,3.341*02
|
||||
#0,1,0.000,2,-138.7,3,2.63,4,-139.7,5,2.61,6,27.3,9,153.4,10,0.00,11,0.0,12,0.17,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.168,146,0.347908,152,80.2,172,1.872,173,2.0,175,1.184,176,294.959,238,3.338*3D
|
||||
#0,1,0.000,2,-138.4,3,2.62,4,-139.4,5,2.60,6,27.3,9,153.4,10,0.00,11,0.0,12,0.17,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.168,146,0.347908,152,80.7,172,1.872,173,2.0,175,1.185,176,294.959,238,3.335*34
|
||||
#0,1,0.000,2,-138.1,3,2.62,4,-139.2,5,2.60,6,27.3,9,153.4,10,0.00,11,0.0,12,0.16,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.161,146,0.347911,152,81.6,172,1.872,173,2.0,175,1.185,176,294.957,238,3.335*39
|
||||
#0,1,0.000,2,-137.9,3,2.61,4,-139.0,5,2.60,6,27.2,9,153.4,10,0.00,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.153,146,0.347911,152,81.6,172,1.872,173,2.0,175,1.185,176,294.956,238,3.328*05
|
||||
#0,1,0.000,2,-137.6,3,2.60,4,-138.8,5,2.60,6,27.2,9,153.4,10,0.00,11,0.0,12,0.15,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.146,146,0.347914,152,82.0,172,1.872,173,2.0,175,1.185,176,294.956,238,3.325*3F
|
||||
#0,1,0.000,2,-137.4,3,2.59,4,-138.6,5,2.59,6,27.2,9,153.4,10,0.00,11,0.0,12,0.15,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.159,146,0.347914,152,82.4,172,1.872,173,2.0,175,1.185,176,294.955,238,3.325*3A
|
||||
#0,1,0.000,2,-137.2,3,2.58,4,-138.5,5,2.59,6,27.2,9,153.4,10,0.00,11,0.0,12,0.16,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.169,146,0.347914,152,82.7,172,1.872,173,2.0,175,1.185,176,294.955,238,3.322*3A
|
||||
#0,1,0.000,2,-137.0,3,2.58,4,-138.3,5,2.59,6,27.1,9,153.4,10,0.00,11,0.0,12,0.17,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.193,48,-33.907350,49,18.419948,50,0.0,51,0.179,146,0.347917,152,83.1,172,1.872,173,2.0,175,1.185,176,294.957,238,3.319*32
|
||||
#0,1,0.000,2,-136.8,3,2.56,4,-138.1,5,2.58,6,27.1,9,153.4,10,0.00,11,0.0,12,0.18,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.43,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.199,146,0.347920,152,83.4,172,1.872,173,2.0,175,1.184,176,294.953,238,3.316*3C
|
||||
#0,1,0.000,2,-136.7,3,2.55,4,-138.0,5,2.58,6,27.0,9,153.4,10,0.00,11,0.0,12,0.20,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.43,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.208,146,0.347920,152,83.9,172,1.872,173,2.0,175,1.184,176,294.953,238,3.312*39
|
||||
#0,1,0.000,2,-136.7,3,2.55,4,-137.9,5,2.58,6,27.0,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.43,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.218,146,0.347920,152,84.1,172,1.872,173,2.0,175,1.184,176,294.953,238,3.306*35
|
||||
#0,1,0.000,2,-136.7,3,2.54,4,-137.9,5,2.57,6,26.9,9,153.4,10,0.00,11,0.0,12,0.22,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.225,146,0.347922,152,84.2,172,1.872,173,2.0,175,1.185,176,294.956,238,3.303*3F
|
||||
#0,9,153.4,11,0.0,12,0.22,152,84.3,238,3.299*05
|
||||
#0,1,0.000,2,-136.8,3,2.53,4,-137.9,5,2.57,6,26.9,9,153.4,10,0.00,11,0.0,12,0.23,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.193,48,-33.907350,49,18.419948,50,0.0,51,0.228,146,0.347922,152,84.3,172,1.872,173,2.0,175,1.184,176,294.958,238,3.296*39
|
||||
#0,1,0.000,2,-137.0,3,2.52,4,-137.9,5,2.57,6,26.8,9,153.4,10,0.00,11,0.0,12,0.23,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.228,146,0.347925,152,84.2,172,1.872,173,2.0,175,1.185,176,294.957,238,3.292*3E
|
||||
#0,1,0.000,2,-137.1,3,2.52,4,-138.0,5,2.57,6,26.7,9,153.4,10,0.00,11,0.0,12,0.23,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.229,146,0.347925,152,84.1,172,1.872,173,2.0,175,1.185,176,294.957,238,3.288*3E
|
||||
#0,1,0.000,2,-137.4,3,2.51,4,-138.1,5,2.56,6,26.6,9,153.4,10,0.00,11,0.0,12,0.23,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.229,146,0.347925,152,83.9,172,1.872,173,2.0,175,1.184,176,294.957,238,3.284*3A
|
||||
#0,1,0.000,2,-137.7,3,2.50,4,-138.2,5,2.56,6,26.5,9,153.4,10,0.00,11,0.0,12,0.22,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.223,146,0.347928,152,83.6,172,1.872,173,2.0,175,1.185,176,294.958,238,3.280*3B
|
||||
#0,1,0.000,2,-138.0,3,2.49,4,-138.4,5,2.56,6,26.4,9,153.4,10,0.00,11,0.0,12,0.22,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.216,146,0.347928,152,83.3,172,1.872,173,2.0,175,1.185,176,294.958,238,3.276*36
|
||||
#0,1,0.000,2,-138.3,3,2.48,4,-138.6,5,2.55,6,26.3,9,153.4,10,0.00,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.210,146,0.347931,152,83.3,172,1.872,173,2.0,175,1.185,176,294.959,238,3.272*0A
|
||||
#0,1,0.000,2,-138.6,3,2.47,4,-138.8,5,2.55,6,26.1,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.210,146,0.347931,152,82.5,172,1.872,173,2.0,175,1.184,176,294.959,238,3.267*3E
|
||||
#0,1,0.000,2,-138.9,3,2.46,4,-139.0,5,2.55,6,26.0,9,153.4,10,0.00,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.211,146,0.347931,152,82.5,172,1.872,173,2.0,175,1.184,176,294.957,238,3.263*03
|
||||
#0,1,0.000,2,-139.6,3,2.45,4,-139.4,5,2.54,6,25.8,9,153.4,10,0.00,11,0.0,12,0.21,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.193,48,-33.907350,49,18.419948,50,0.0,51,0.185,146,0.347934,152,82.1,172,1.872,173,2.0,175,1.184,176,294.955,238,3.258*34
|
||||
#0,1,0.000,2,-139.8,3,2.44,4,-139.6,5,2.53,6,25.7,9,153.4,10,0.00,11,0.0,12,0.18,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.193,48,-33.907350,49,18.419948,50,0.0,51,0.172,146,0.347937,152,81.2,172,1.872,173,2.0,175,1.184,176,294.955,238,3.258*30
|
||||
#0,9,153.4,11,0.0,12,0.17,152,80.8,238,3.249*01
|
||||
#0,1,0.000,2,-140.1,3,2.43,4,-139.8,5,2.53,6,25.6,9,153.4,10,0.00,11,0.0,12,0.17,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.193,48,-33.907350,49,18.419948,50,0.0,51,0.172,146,0.347937,152,80.5,172,1.872,173,2.0,175,1.184,176,294.956,238,3.244*39
|
||||
#0,1,0.000,2,-140.3,3,2.42,4,-139.9,5,2.53,6,25.5,9,153.4,10,0.00,11,0.0,12,0.17,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.40,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.173,146,0.347937,152,80.1,172,1.872,173,2.0,175,1.184,176,294.955,238,3.240*3B
|
||||
#0,1,0.000,2,-140.5,3,2.41,4,-140.1,5,2.52,6,25.4,9,153.4,10,0.00,11,0.0,12,0.16,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.160,146,0.347940,152,79.8,172,1.872,173,2.0,175,1.184,176,294.956,238,3.235*34
|
||||
#0,1,0.000,2,-140.7,3,2.40,4,-140.3,5,2.52,6,25.3,9,153.4,10,0.00,11,0.0,12,0.15,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.147,146,0.347940,152,79.5,172,1.872,173,2.0,175,1.184,176,294.959,238,3.231*32
|
||||
#0,1,0.000,2,-140.9,3,2.39,4,-140.4,5,2.52,6,25.2,9,153.4,10,0.00,11,0.0,12,0.13,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.134,146,0.347943,152,79.2,172,1.872,173,2.0,175,1.185,176,294.960,238,3.227*3E
|
||||
#0,1,0.000,2,-141.1,3,2.38,4,-140.5,5,2.51,6,25.1,9,153.4,10,0.00,11,0.0,12,0.13,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.135,146,0.347943,152,78.9,172,1.872,173,2.0,175,1.185,176,294.962,238,3.222*3B
|
||||
#0,1,0.000,2,-141.3,3,2.37,4,-140.7,5,2.51,6,25.0,9,153.4,10,0.00,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.41,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.135,146,0.347943,172,1.872,173,2.0,175,1.185,176,294.964*3A
|
||||
#0,1,0.000,2,-141.5,3,2.36,4,-140.8,5,2.51,6,24.9,9,153.4,10,0.00,11,0.0,12,0.14,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.136,146,0.347946,152,78.7,172,1.872,173,2.0,175,1.185,176,294.963,238,3.218*31
|
||||
#0,1,0.000,2,-141.8,3,2.35,4,-141.0,5,2.50,6,24.7,9,153.4,10,0.00,11,0.0,12,0.14,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.137,146,0.347948,152,78.4,172,1.872,173,2.0,175,1.185,176,294.969,238,3.214*33
|
||||
#0,1,0.000,2,-141.9,3,2.34,4,-141.2,5,2.50,6,24.6,9,153.4,10,0.00,11,0.0,12,0.14,13,153.4,17,-3.00,18,0.51,19,0.28,20,18.42,22,1.192,48,-33.907350,49,18.419948,50,0.0,51,0.117,146,0.347948,152,77.9,172,1.872,173,2.0,175,1.185,176,294.969,238,3.209*3C
|
||||
@@ -0,0 +1,393 @@
|
||||
#pragma once
|
||||
|
||||
// All directions in magnetic
|
||||
|
||||
// multiboat channels
|
||||
|
||||
enum ExChannels
|
||||
{
|
||||
ExUtc, // Microsoft DATE type,utc system time
|
||||
ExBsp,
|
||||
ExAwa,
|
||||
ExAws,
|
||||
ExTwa, // #4
|
||||
ExTws, // #5
|
||||
ExTwd, // #6
|
||||
|
||||
ExRudderFwd,
|
||||
ExDeltaTargBsp,
|
||||
ExCourse,
|
||||
|
||||
ExLwy, // #10
|
||||
ExSet,
|
||||
ExDrift,
|
||||
ExHdg, // #13
|
||||
ExAirTemp,
|
||||
ExSeaTemp,
|
||||
ExBaro,
|
||||
ExDepth, // metres
|
||||
ExRoll,
|
||||
ExPitch,
|
||||
ExRudder, // #20
|
||||
ExTab,
|
||||
ExForestayLoad,
|
||||
ExDownhaulLoad,
|
||||
ExMastAngle,
|
||||
ExForestayLen,
|
||||
ExMast,
|
||||
ExStbdLoadCell,
|
||||
ExPortLoadCell,
|
||||
ExRake,
|
||||
ExVolts, // #30
|
||||
ExVmg,
|
||||
ExROT,
|
||||
ExLayDistOnStrb,
|
||||
ExLayTimeOnStrb,
|
||||
ExLayPortBear,
|
||||
ExLayDistOnPort,
|
||||
ExLayTimeOnPort,
|
||||
ExLayStrbBear,
|
||||
ExGpsQuality, // 0 Bad, 1 Autonomous, 2 Differential, 3 p-code, 4,5 Rtk, 6 dr, if change this, need to change CPort::NmeaAPB()
|
||||
ExGpsHDOP, // #40
|
||||
ExGpsPDOP,
|
||||
ExGpsVDOP,
|
||||
ExGpsNumber, // Number of satellites in active constellation
|
||||
ExGpsAge, // Age of differential data
|
||||
ExGpsAltitude, // antenna height
|
||||
ExGpsGeoidSeparation,
|
||||
ExGpsMode, // 0 = 1D, 1 = 2D, 2 = 3D, 3 = Auto, 6 = error
|
||||
|
||||
ExLat, // #48 // if add GPS vars, extend CCore::IsGPSvar()
|
||||
ExLon, // #49
|
||||
ExCog, // #50
|
||||
ExSog, // #51
|
||||
|
||||
ExDiffRefStn,
|
||||
|
||||
ExTargTwaN,
|
||||
ExTargBspN,
|
||||
ExTargVmg,
|
||||
ExTargRoll,
|
||||
ExPolarBsp,
|
||||
ExPolarBspPercent,
|
||||
ExPolarRoll,
|
||||
|
||||
ExErrorCode, // #60
|
||||
|
||||
ExStrbRunner,
|
||||
ExPortRunner,
|
||||
|
||||
ExPolarBspN,
|
||||
ExPolarBspPercentN,
|
||||
|
||||
ExTargTwaLwy, // target twa without leeway
|
||||
|
||||
ExVmgPercent,
|
||||
|
||||
ExVang,
|
||||
ExTraveller,
|
||||
ExMainSheet,
|
||||
|
||||
ExPolVmcToMark, // #70 // vmc if headed at mark
|
||||
|
||||
ExKeelAngle,
|
||||
ExKeelHeight,
|
||||
ExBoard,
|
||||
ExOilPressure,
|
||||
ExRPM1,
|
||||
ExRPM2,
|
||||
|
||||
ExBoardP,
|
||||
ExBoardS,
|
||||
|
||||
ExOppTrack,
|
||||
ExDistFinish, // #80
|
||||
|
||||
ExStartTimeToPort,
|
||||
ExStartTimeToStrb,
|
||||
ExLineSquareWind,
|
||||
ExStartDistToLine,
|
||||
ExStartRchTimeToLine, // time to reach into line
|
||||
ExStartRchDistToLine,
|
||||
ExStartRchBspToLine,
|
||||
|
||||
ExMarkTime,
|
||||
ExNextMarkTimeOnPort,
|
||||
ExNextMarkTimeOnStrb, // #90
|
||||
|
||||
ExXte,
|
||||
ExVmc,
|
||||
|
||||
ExMagVar,
|
||||
|
||||
ExGwd, // #94
|
||||
ExGws, // #95
|
||||
|
||||
ExLayDist, // distance to layline we are heading to
|
||||
ExLayTime, // time to layline
|
||||
ExLayBear, // bearing of that layline
|
||||
|
||||
ExVmcPercent,
|
||||
ExPolVmc, // #100
|
||||
ExOptVmc,
|
||||
ExOptVmcHdg,
|
||||
ExOptVmcTwa,
|
||||
ExDeltaTargTwa,
|
||||
|
||||
ExMarkRng,
|
||||
ExMarkBrg,
|
||||
ExMarkGpsTime,
|
||||
ExMarkTwa,
|
||||
|
||||
ExPredSet,
|
||||
ExPredDrift, // #110
|
||||
|
||||
ExNextMarkRng,
|
||||
ExNextMarkBrg,
|
||||
ExNextMarkTwa,
|
||||
|
||||
ExRadarRng,
|
||||
ExRadarBrg,
|
||||
ExStartDistBelowLineStern,
|
||||
|
||||
ExAlt0, // alternating number channels must be consecutive
|
||||
ExAlt1,
|
||||
ExAlt2,
|
||||
ExAlt3, // #120
|
||||
ExAlt4,
|
||||
ExAlt5,
|
||||
ExAlt6,
|
||||
ExAlt7,
|
||||
ExAlt8,
|
||||
ExAlt9,
|
||||
// ExAltNum = ExAlt9 - ExAlt0 + 1 // defined in CoreMem.h
|
||||
ExAltMaxId = ExAlt9, // alternating channels must be consecutive
|
||||
|
||||
ExNextMarkPolTime,
|
||||
|
||||
ExStartLineBiasDeg,
|
||||
ExStartLineBiasLen,
|
||||
|
||||
ExStartLayPortBear, // #130 // laylines for start line
|
||||
ExStartLayStrbBear,
|
||||
|
||||
ExNextMarkAwa,
|
||||
ExNextMarkAws,
|
||||
|
||||
ExStartRSTime, // turning to right, ending up on starboard
|
||||
ExStartRPTime, // turning to right, ending up on port
|
||||
ExStartLSTime, // turning to left, ending up on starboard
|
||||
ExStartLPTime, // turning to left, ending up on port
|
||||
|
||||
ExGpsDistToRaceNote,
|
||||
ExGpsTimeToRaceNote,
|
||||
|
||||
ExLogBsp, // #140
|
||||
ExLogSog,
|
||||
ExStartGpsTimeToLine,
|
||||
ExStartGpsTimeToBurn,
|
||||
ExTargTwaS, // Start
|
||||
ExTargBspS, // Start
|
||||
|
||||
ExGpsTime, // #146
|
||||
|
||||
ExTwdPlus90, // Twd + 90
|
||||
ExTwdLess90, // Twd - 90
|
||||
|
||||
ExShadow,
|
||||
ExShadowOppTack, // #150
|
||||
|
||||
ExDownhaulLoad2,
|
||||
|
||||
ExTackAngle,
|
||||
ExTackAnglePolar,
|
||||
|
||||
ExTargAwa,
|
||||
|
||||
ExStartTimeBurnStrbX, // time to burn when tack onto starboard end starboard layline and sail to 20s from line
|
||||
ExStartTimeBurnPortX, // offset for the start stbd layline to the pin
|
||||
ExStartLayTimeP,
|
||||
ExStartLayTimeS,
|
||||
|
||||
ExMarkSet,
|
||||
ExMarkDrift, // #160
|
||||
|
||||
ExMarkLat,
|
||||
ExMarkLon,
|
||||
ExStartPortEndLat, // ends of line
|
||||
ExStartPortEndLon,
|
||||
ExStartStrbEndLat,
|
||||
ExStartStrbEndLon,
|
||||
|
||||
ExGpsHPE,
|
||||
ExHumidity,
|
||||
ExLeadPort,
|
||||
ExLeadStbd, // #170
|
||||
ExBackstay,
|
||||
|
||||
ExUser0, // user channels must be consecutive
|
||||
ExUser1,
|
||||
ExUser2,
|
||||
ExUser3,
|
||||
ExUser4,
|
||||
ExUser5,
|
||||
ExUser6,
|
||||
ExUser7,
|
||||
ExUser8, // #180
|
||||
ExUser9,
|
||||
ExUser10,
|
||||
ExUser11,
|
||||
ExUser12,
|
||||
ExUser13,
|
||||
ExUser14,
|
||||
ExUser15,
|
||||
ExUser16,
|
||||
ExUser17,
|
||||
ExUser18, // #190
|
||||
ExUser19,
|
||||
ExUser20,
|
||||
ExUser21,
|
||||
ExUser22,
|
||||
ExUser23,
|
||||
ExUser24,
|
||||
ExUser25,
|
||||
ExUser26,
|
||||
ExUser27,
|
||||
ExUser28, // #200
|
||||
ExUser29,
|
||||
ExUser30,
|
||||
ExUser31,
|
||||
ExUserMax = ExUser31, // user channels must be consecutive
|
||||
|
||||
ExStartTimeToGun,
|
||||
ExStartTimeToLine,
|
||||
ExStartTimeToBurn,
|
||||
ExStartDistBelowLine,
|
||||
ExStartDistBelowLineGun,
|
||||
|
||||
ExGateTimeOnPort, // this is to the gate mark
|
||||
ExGateDistOnStrb, // #210
|
||||
ExGateTimeOnStrb,
|
||||
ExGateDistOnPort,
|
||||
|
||||
ExGateSpotTimeOnStrb,
|
||||
ExGateSpotTimeOnPort,
|
||||
|
||||
ExLayPortBearUp,
|
||||
ExLayStrbBearUp,
|
||||
ExLayPortBearDn,
|
||||
ExLayStrbBearDn,
|
||||
|
||||
ExTideLayPortTimeOnPort,
|
||||
ExTideLayPortTimeOnStbd, // #220
|
||||
ExTideLayStbdTimeOnPort,
|
||||
ExTideLayStbdTimeOnStbd,
|
||||
ExTideLayPortTime,
|
||||
ExTideLayStbdTime,
|
||||
|
||||
ExMaxLayPortBear,
|
||||
ExMinLayPortBear,
|
||||
ExMaxLayStrbBear,
|
||||
ExMinLayStrbBear,
|
||||
|
||||
ExTwdLayMark,
|
||||
ExTwdLayMarkOpp, // #230 // lay on other board
|
||||
|
||||
ExDeltaBspSog,
|
||||
ExDeltaHdgCog,
|
||||
|
||||
ExLayPortRatio,
|
||||
ExLayStrbRatio,
|
||||
|
||||
ExFourierTwd,
|
||||
ExFourierTws,
|
||||
|
||||
ExTargTwaP,
|
||||
ExTargBspP,
|
||||
|
||||
ExTwdTarg,
|
||||
|
||||
ExPolCustom1, // #240 // these need to be in this order : see CCore::DerivedPolarNumbers()
|
||||
ExPolCustom2,
|
||||
ExPolCustom3,
|
||||
ExPolCustom4,
|
||||
ExPolCustom1PC,
|
||||
ExPolCustom2PC,
|
||||
ExPolCustom3PC,
|
||||
ExPolCustom4PC,
|
||||
ExPolCustom1Targ,
|
||||
ExPolCustom2Targ,
|
||||
ExPolCustom3Targ, // #250
|
||||
ExPolCustom4Targ,
|
||||
|
||||
ExWaveSigHeight, // XDR from Volvo wave sensor
|
||||
ExWaveSigPeriod,
|
||||
ExWaveMaxHeight,
|
||||
ExWaveMaxPeriod,
|
||||
|
||||
ExSlam,
|
||||
ExMotion,
|
||||
|
||||
ExMwa,
|
||||
ExMws,
|
||||
ExBoom, // #260
|
||||
|
||||
ExTargBspPercent,
|
||||
ExHeadingToSteer,
|
||||
ExHeadingToSteerPol,
|
||||
|
||||
ExStartBspToPort,
|
||||
ExStartBspToStrb,
|
||||
ExStartBspOnPort,
|
||||
ExStartBspOnStrb,
|
||||
|
||||
ExTwdTwist,
|
||||
|
||||
ExSailNow,
|
||||
ExSailMark, // #270
|
||||
ExSailNext,
|
||||
|
||||
ExTackLossVMGSec,
|
||||
ExTackLossVMGMetres,
|
||||
|
||||
ExNearestTide,
|
||||
|
||||
ExTripLog,
|
||||
ExTurnToMark, // delta of cog and bearing to mark
|
||||
|
||||
ExPitchRate,
|
||||
ExRollRate,
|
||||
|
||||
ExDeltaPolBsp,
|
||||
ExDeltaTargRoll, // #280
|
||||
|
||||
ExDeflectorP,
|
||||
ExRudderP,
|
||||
ExRudderS,
|
||||
ExRudderToe,
|
||||
ExBspTransverse,
|
||||
ExForestayInner,
|
||||
ExGateTime, // this is to the gate mark
|
||||
|
||||
ExZeroAhead,
|
||||
ExBrgFromBoat0,
|
||||
ExRngFromBoat0, // #290
|
||||
|
||||
ExDeflectorS,
|
||||
ExBobstay,
|
||||
ExOuthaul,
|
||||
|
||||
ExD0port,
|
||||
ExD0starboard,
|
||||
ExD1port,
|
||||
ExD1starbboard,
|
||||
ExV0port,
|
||||
ExV0starbboard,
|
||||
ExV1port, // #300
|
||||
ExV1starbboard,
|
||||
|
||||
ExStartTimeToPortSimple,
|
||||
ExStartTimeToStrbSimple,
|
||||
|
||||
ExNumChannels
|
||||
};
|
||||
+165
-7
@@ -5,7 +5,9 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
@@ -17,16 +19,19 @@ import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.Timeout;
|
||||
|
||||
import com.sap.sailing.declination.Declination;
|
||||
import com.sap.sailing.declination.DeclinationService;
|
||||
@@ -34,19 +39,31 @@ import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.impl.DegreePosition;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||
import com.sap.sailing.domain.racelog.tracking.FixReceivedListener;
|
||||
import com.sap.sailing.domain.racelog.tracking.SensorFixStore;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.test.mock.MockedTrackedRace;
|
||||
import com.sap.sailing.expeditionconnector.DeviceRegistry;
|
||||
import com.sap.sailing.expeditionconnector.ExpeditionListener;
|
||||
import com.sap.sailing.expeditionconnector.ExpeditionMessage;
|
||||
import com.sap.sailing.expeditionconnector.ExpeditionTrackerFactory;
|
||||
import com.sap.sailing.expeditionconnector.ExpeditionWindTracker;
|
||||
import com.sap.sailing.expeditionconnector.ExpeditionWindTrackerFactory;
|
||||
import com.sap.sailing.expeditionconnector.UDPExpeditionReceiver;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionGpsDeviceIdentifier;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionGpsDeviceIdentifierImpl;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionSensorDeviceIdentifier;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionSensorDeviceIdentifierImpl;
|
||||
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.TimeRange;
|
||||
import com.sap.sse.common.Timed;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class UDPExpeditionReceiverTest {
|
||||
@Rule public Timeout TestTimeout = new Timeout(60 * 1000);
|
||||
// @Rule public Timeout TestTimeout = new Timeout(60 * 1000);
|
||||
|
||||
private String[] validLines;
|
||||
private String[] someValidWithFourInvalidLines;
|
||||
@@ -58,9 +75,126 @@ public class UDPExpeditionReceiverTest {
|
||||
private UDPExpeditionReceiver receiver;
|
||||
private ExpeditionListener listener;
|
||||
private Thread receiverThread;
|
||||
private DynamicDeviceRegistry deviceRegistry;
|
||||
private TestSensorFixStore sensorFixStore;
|
||||
|
||||
private class DynamicDeviceRegistry implements DeviceRegistry {
|
||||
private final Map<Integer, ExpeditionGpsDeviceIdentifier> gpsDeviceIdentifiers;
|
||||
private final Map<Integer, ExpeditionSensorDeviceIdentifier> sensorDeviceIdentifiers;
|
||||
|
||||
public DynamicDeviceRegistry() {
|
||||
gpsDeviceIdentifiers = new HashMap<>();
|
||||
sensorDeviceIdentifiers = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpeditionGpsDeviceIdentifier getGpsDeviceIdentifier(int boatId) {
|
||||
ExpeditionGpsDeviceIdentifier result = gpsDeviceIdentifiers.get(boatId);
|
||||
if (result == null) {
|
||||
result = new ExpeditionGpsDeviceIdentifierImpl(UUID.randomUUID());
|
||||
gpsDeviceIdentifiers.put(boatId, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpeditionSensorDeviceIdentifier getSensorDeviceIdentifier(int boatId) {
|
||||
ExpeditionSensorDeviceIdentifier result = sensorDeviceIdentifiers.get(boatId);
|
||||
if (result == null) {
|
||||
result = new ExpeditionSensorDeviceIdentifierImpl(UUID.randomUUID());
|
||||
sensorDeviceIdentifiers.put(boatId, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SensorFixStore getSensorFixStore() {
|
||||
return sensorFixStore;
|
||||
}
|
||||
}
|
||||
|
||||
private class TestSensorFixStore implements SensorFixStore {
|
||||
private Map<DeviceIdentifier, List<Timed>> fixesReceived;
|
||||
|
||||
public TestSensorFixStore() {
|
||||
fixesReceived = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <FixT extends Timed> void loadFixes(Consumer<FixT> consumer, DeviceIdentifier deviceIdentifier,
|
||||
TimePoint start, TimePoint end, boolean toIsInclusive)
|
||||
throws NoCorrespondingServiceRegisteredException, TransformationException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <FixT extends Timed> void loadFixes(Consumer<FixT> consumer, DeviceIdentifier deviceIdentifier,
|
||||
TimePoint start, TimePoint end, boolean inclusive, BooleanSupplier isPreemptiveStopped,
|
||||
Consumer<Double> progressReporter)
|
||||
throws NoCorrespondingServiceRegisteredException, TransformationException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <FixT extends Timed> void storeFix(DeviceIdentifier device, FixT fix) {
|
||||
List<Timed> fixesReceivedFromDevice = fixesReceived.get(device);
|
||||
if (fixesReceivedFromDevice == null) {
|
||||
fixesReceivedFromDevice = new ArrayList<>();
|
||||
fixesReceived.put(device, fixesReceivedFromDevice);
|
||||
}
|
||||
fixesReceivedFromDevice.add(fix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <FixT extends Timed> void storeFixes(DeviceIdentifier device, Iterable<FixT> fixes) {
|
||||
for (final FixT fix : fixes) {
|
||||
storeFix(device, fix);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(FixReceivedListener<? extends Timed> listener, DeviceIdentifier device) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(FixReceivedListener<? extends Timed> listener) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(FixReceivedListener<? extends Timed> listener, DeviceIdentifier device) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeRange getTimeRangeCoveredByFixes(DeviceIdentifier device)
|
||||
throws TransformationException, NoCorrespondingServiceRegisteredException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getNumberOfFixes(DeviceIdentifier device)
|
||||
throws TransformationException, NoCorrespondingServiceRegisteredException {
|
||||
return fixesReceived.get(device) == null ? 0 : fixesReceived.get(device).size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <FixT extends Timed> Map<DeviceIdentifier, FixT> getLastFix(Iterable<DeviceIdentifier> forDevices)
|
||||
throws TransformationException, NoCorrespondingServiceRegisteredException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <FixT extends Timed> boolean loadOldestFix(Consumer<FixT> consumer, DeviceIdentifier device,
|
||||
TimeRange timeRangetoLoad) throws NoCorrespondingServiceRegisteredException, TransformationException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <FixT extends Timed> boolean loadYoungestFix(Consumer<FixT> consumer, DeviceIdentifier device,
|
||||
TimeRange timeRangetoLoad) throws NoCorrespondingServiceRegisteredException, TransformationException {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws UnknownHostException, SocketException {
|
||||
public void setUp() throws UnknownHostException, SocketException, InterruptedException {
|
||||
validLines = new String[] {
|
||||
"#0,1,7.700,2,-39.0,3,23.00,9,319.0,12,1.17,146,40348.390035*37",
|
||||
"#0,4,-54.9,5,17.69,6,263.1,9,318.0*0D",
|
||||
@@ -114,9 +248,12 @@ public class UDPExpeditionReceiverTest {
|
||||
buf = new byte[512];
|
||||
packet = new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), PORT);
|
||||
socket = new DatagramSocket();
|
||||
receiver = new UDPExpeditionReceiver(PORT);
|
||||
sensorFixStore = new TestSensorFixStore();
|
||||
deviceRegistry = new DynamicDeviceRegistry();
|
||||
receiver = new UDPExpeditionReceiver(PORT, deviceRegistry);
|
||||
receiverThread = new Thread(receiver, "Expedition Receiver");
|
||||
receiverThread.start();
|
||||
Thread.sleep(10); // to give receiver enough time to start listening on UDP socket
|
||||
listener = new ExpeditionListener() {
|
||||
@Override
|
||||
public void received(ExpeditionMessage message) {
|
||||
@@ -175,6 +312,27 @@ public class UDPExpeditionReceiverTest {
|
||||
assertEquals(windFixes.get(0).getPosition(), windFixes.get(2).getPosition());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicPhoenixUDPProperties() throws IOException, InterruptedException {
|
||||
receiver.addListener(listener, /* validMessagesOnly */ true);
|
||||
final InputStreamReader reader = new InputStreamReader(getClass().getResourceAsStream("/Expedition_28Oct17_0820.txt"));
|
||||
final BufferedReader br = new BufferedReader(reader);
|
||||
final List<String> lines = new ArrayList<>();
|
||||
String line;
|
||||
while ((line=br.readLine()) != null) {
|
||||
if (!line.trim().isEmpty()) {
|
||||
lines.add(line.trim());
|
||||
}
|
||||
}
|
||||
br.close();
|
||||
sendAndWaitABit(lines.toArray(new String[0]));
|
||||
assertEquals(159, lines.size());
|
||||
assertEquals(159, messages.size());
|
||||
final ExpeditionGpsDeviceIdentifier gpsDevice = deviceRegistry.getGpsDeviceIdentifier(0);
|
||||
final ExpeditionSensorDeviceIdentifier sensorDevice = deviceRegistry.getSensorDeviceIdentifier(0);
|
||||
assertTrue(sensorFixStore.getNumberOfFixes(gpsDevice) > 0);
|
||||
assertTrue(sensorFixStore.getNumberOfFixes(sensorDevice) > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeStampConversion() throws IOException, InterruptedException {
|
||||
@@ -261,7 +419,7 @@ public class UDPExpeditionReceiverTest {
|
||||
MockedTrackedRace race = new MockedTrackedRace();
|
||||
DeclinationService declinationService = DeclinationService.INSTANCE;
|
||||
ExpeditionWindTracker windTracker = new ExpeditionWindTracker(race, declinationService, receiver,
|
||||
(ExpeditionWindTrackerFactory) ExpeditionWindTrackerFactory.getInstance());
|
||||
(ExpeditionTrackerFactory) ExpeditionTrackerFactory.getInstance());
|
||||
receiver.addListener(listener, /* validMessagesOnly */ true);
|
||||
receiver.addListener(windTracker, /* validMessagesOnly */ true);
|
||||
String[] lines = new String[validLines.length+1];
|
||||
|
||||
@@ -6,13 +6,18 @@ Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Export-Package: com.sap.sailing.expeditionconnector,
|
||||
com.sap.sailing.expeditionconnector.impl;x-friends:="com.sap.sailing.server.test"
|
||||
com.sap.sailing.expeditionconnector.impl;x-friends:="com.sap.sailing.server.test,com.sap.sailing.expeditionconnector.persistence"
|
||||
Require-Bundle: com.sap.sailing.domain,
|
||||
com.sap.sailing.declination,
|
||||
com.sap.sailing.udpconnector,
|
||||
com.sap.sailing.domain.common,
|
||||
com.sap.sse.common,
|
||||
com.sap.sse
|
||||
com.sap.sse,
|
||||
com.sap.sailing.domain.shared.android,
|
||||
com.sap.sailing.server.gateway.serialization.shared.android,
|
||||
com.sap.sailing.expeditionconnector.common,
|
||||
com.sap.sailing.expeditionconnector.persistence
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Import-Package: org.osgi.framework
|
||||
Import-Package: org.osgi.framework,
|
||||
org.osgi.util.tracker;version="1.5.1"
|
||||
Bundle-Activator: com.sap.sailing.expeditionconnector.impl.Activator
|
||||
|
||||
java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/DeviceRegistry.java
Executable
+28
@@ -0,0 +1,28 @@
|
||||
package com.sap.sailing.expeditionconnector;
|
||||
|
||||
import com.sap.sailing.domain.racelog.tracking.SensorFixStore;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionGpsDeviceIdentifier;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionSensorDeviceIdentifier;
|
||||
|
||||
/**
|
||||
* Makes accessible a mapping from "Expedition" boat IDs to device UUIDs.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public interface DeviceRegistry {
|
||||
/**
|
||||
* If a device is registered for the boat ID {@code boatId}, a non-{@code null} device identifier is returned that
|
||||
* represents a virtual device for the GPS data received from that boat ID. Otherwise, {@code null} is returned.
|
||||
*/
|
||||
ExpeditionGpsDeviceIdentifier getGpsDeviceIdentifier(int boatId);
|
||||
|
||||
/**
|
||||
* If a device is registered for the boat ID {@code boatId}, a non-{@code null} device identifier is returned that
|
||||
* represents a virtual device for the additional non-GPS and non-wind sensor data received from that boat ID.
|
||||
* Otherwise, {@code null} is returned.
|
||||
*/
|
||||
ExpeditionSensorDeviceIdentifier getSensorDeviceIdentifier(int boatId);
|
||||
|
||||
SensorFixStore getSensorFixStore();
|
||||
}
|
||||
+99
-29
@@ -49,6 +49,89 @@ public interface ExpeditionMessage extends UDPMessage {
|
||||
#0,6,344.2,40,2.10,94,350.8,95,2.35*28
|
||||
#0,4,135.0,5,2.06,6,345.5,94,350.8,95,2.35*05
|
||||
*/
|
||||
/**
|
||||
* variable ID for boat speed
|
||||
*/
|
||||
final int ID_BSP = 1;
|
||||
|
||||
/**
|
||||
* variable ID for apparent wind angle (probably in decimal degrees)
|
||||
*/
|
||||
final int ID_AWA = 2;
|
||||
|
||||
/**
|
||||
* variable ID for apparent wind speed (probably in decimal knots)
|
||||
*/
|
||||
final int ID_AWS = 3;
|
||||
|
||||
/**
|
||||
* variable ID for true wind angle, relative to keel, in decimal degrees
|
||||
*/
|
||||
final int ID_TWA = 4;
|
||||
|
||||
/**
|
||||
* variable ID for true wind speed in decimal knots
|
||||
*/
|
||||
final int ID_TWS = 5;
|
||||
|
||||
/**
|
||||
* Variable ID for what Expedition thinks is the true wind direction ("from"), in decimal degrees. Some
|
||||
* users prefer to not enter the current declination for a time / place into their Expedition
|
||||
* client. In this case, the values presented for this key are the magnetic wind direction instead.
|
||||
* They should then be corrected by adding the current declination.
|
||||
*/
|
||||
final int ID_TWD = 6;
|
||||
|
||||
/**
|
||||
* variable ID for course
|
||||
*/
|
||||
final int ID_COURSE = 9;
|
||||
|
||||
/**
|
||||
* variable ID for leeway
|
||||
*/
|
||||
final int ID_LWY = 10;
|
||||
|
||||
/**
|
||||
* variable ID for "set" (?)
|
||||
*/
|
||||
final int ID_SET = 11;
|
||||
|
||||
/**
|
||||
* variable ID for drift
|
||||
*/
|
||||
final int ID_DRIFT = 12;
|
||||
|
||||
/**
|
||||
* variable ID for magnetic heading, meaning the keel's direction, in decimal degrees
|
||||
*/
|
||||
final int ID_HEADING = 13;
|
||||
|
||||
/**
|
||||
* variable ID for depth in meters
|
||||
*/
|
||||
final int ID_DEPTH = 17;
|
||||
|
||||
/**
|
||||
* variable ID for roll (heel), probably in degrees
|
||||
*/
|
||||
final int ID_ROLL = 18;
|
||||
|
||||
/**
|
||||
* variable ID for pitch, probably in degrees
|
||||
*/
|
||||
final int ID_PITCH = 19;
|
||||
|
||||
/**
|
||||
* variable ID for rudder, probably in degrees
|
||||
*/
|
||||
final int ID_RUDDER = 20;
|
||||
|
||||
/**
|
||||
* variable ID for forestay load (unit unknown yet)
|
||||
*/
|
||||
final int ID_FORESTAY_LOAD = 22;
|
||||
|
||||
/**
|
||||
* variable ID for the GPS-measured latitude, in decimal degrees
|
||||
*/
|
||||
@@ -69,34 +152,6 @@ public interface ExpeditionMessage extends UDPMessage {
|
||||
*/
|
||||
final int ID_GPS_SOG = 51;
|
||||
|
||||
/**
|
||||
* variable ID for the GPS-measured time as days since 31.12.1899 UTC, meaning 1.0 is 1.1.1900 0:00:00 UTC
|
||||
*/
|
||||
final int ID_GPS_TIME = 146;
|
||||
|
||||
/**
|
||||
* variable ID for magnetic heading, meaning the keel's direction, in decimal degrees
|
||||
*/
|
||||
final int ID_HEADING = 13;
|
||||
|
||||
/**
|
||||
* variable ID for true wind angle, relative to keel, in decimal degrees
|
||||
*/
|
||||
final int ID_TWA = 4;
|
||||
|
||||
/**
|
||||
* Variable ID for what Expedition thinks is the true wind direction ("from"), in decimal degrees. Some
|
||||
* users prefer to not enter the current declination for a time / place into their Expedition
|
||||
* client. In this case, the values presented for this key are the magnetic wind direction instead.
|
||||
* They should then be corrected by adding the current declination.
|
||||
*/
|
||||
final int ID_TWD = 6;
|
||||
|
||||
/**
|
||||
* variable ID for true wind speed in decimal knots
|
||||
*/
|
||||
final int ID_TWS = 5;
|
||||
|
||||
/**
|
||||
* True wind direction over ground ("from") in decimal degrees, cleansed using the GPS device
|
||||
*/
|
||||
@@ -106,7 +161,22 @@ public interface ExpeditionMessage extends UDPMessage {
|
||||
* True wind speed over ground, cleansed using the GPS device
|
||||
*/
|
||||
final int ID_GWS = 95;
|
||||
|
||||
|
||||
/**
|
||||
* variable ID for the GPS-measured time as days since 31.12.1899 UTC, meaning 1.0 is 1.1.1900 0:00:00 UTC
|
||||
*/
|
||||
final int ID_GPS_TIME = 146;
|
||||
|
||||
/**
|
||||
* variable ID for tack angle, probably in degrees
|
||||
*/
|
||||
final int ID_TACK_ANGLE = 152;
|
||||
|
||||
/**
|
||||
* variable ID for target boat speed (P?), presumably in knots
|
||||
*/
|
||||
final int ID_TARG_BSP_P = 238;
|
||||
|
||||
/**
|
||||
* A message's checksum determines whether the package is to be considered valid.
|
||||
*/
|
||||
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
package com.sap.sailing.expeditionconnector;
|
||||
|
||||
import java.net.SocketException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
import org.osgi.util.tracker.ServiceTrackerCustomizer;
|
||||
|
||||
import com.sap.sailing.declination.DeclinationService;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.common.tracking.DoubleVectorFix;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.racelog.tracking.SensorFixStore;
|
||||
import com.sap.sailing.domain.racelog.tracking.SensorFixStoreSupplier;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.WindTracker;
|
||||
import com.sap.sailing.domain.tracking.WindTrackerFactory;
|
||||
import com.sap.sailing.expeditionconnector.impl.Activator;
|
||||
import com.sap.sailing.expeditionconnector.persistence.DomainObjectFactory;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionGpsDeviceIdentifier;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionGpsDeviceIdentifierImpl;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionSensorDeviceIdentifier;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionSensorDeviceIdentifierImpl;
|
||||
import com.sap.sailing.expeditionconnector.persistence.MongoObjectFactory;
|
||||
import com.sap.sailing.expeditionconnector.persistence.PersistenceFactory;
|
||||
|
||||
public class ExpeditionTrackerFactory implements WindTrackerFactory, DeviceRegistry {
|
||||
private static Logger logger = Logger.getLogger(ExpeditionTrackerFactory.class.getName());
|
||||
|
||||
private static ExpeditionTrackerFactory defaultInstance;
|
||||
|
||||
/**
|
||||
* Remembers the wind tracker and the port on which the UDP receiver with which the wind tracker is
|
||||
* registers is listening for incoming Expedition messages.
|
||||
*/
|
||||
private final Map<RaceDefinition, WindTracker> windTrackers;
|
||||
|
||||
private final Map<Integer, UDPExpeditionReceiver> windReceivers;
|
||||
|
||||
/**
|
||||
* When one or more device configurations exist then each {@link UDPExpeditionReceiver} created by this factory will
|
||||
* also produce {@link GPSFixMoving} and {@link DoubleVectorFix} fixes and send them to the {@link SensorFixStore},
|
||||
* using device identifiers of type {@link ExpeditionGpsDeviceIdentifier} and
|
||||
* {@link ExpeditionSensorDeviceIdentifier}, respectively, whose inner ID is the
|
||||
* {@link ExpeditionDeviceConfiguration#getDeviceUuid() UUID} of the device configuration.
|
||||
*/
|
||||
private final ConcurrentHashMap<UUID, ExpeditionDeviceConfiguration> deviceConfigurations;
|
||||
|
||||
/**
|
||||
* Holds the mappings from Expedition boat IDs (default being 0, counting upwards) to the
|
||||
* {@link ExpeditionDeviceConfiguration} that {@link ExpeditionDeviceConfiguration#getExpeditionBoatId() has this
|
||||
* boat ID}.
|
||||
*/
|
||||
private final ConcurrentHashMap<Integer, ExpeditionDeviceConfiguration> devicesPerBoatId;
|
||||
|
||||
private final int defaultPort;
|
||||
|
||||
/**
|
||||
* Cached result from calling {@link SensorFixStoreSupplier#getSensorFixStore()} on any supplier discovered
|
||||
* in the OSGi registry. Refreshed when the sensor fix store supplier changes in the OSGi registry.
|
||||
*/
|
||||
private SensorFixStore sensorFixStore;
|
||||
|
||||
private ServiceTracker<SensorFixStoreSupplier, SensorFixStoreSupplier> sensorFixServiceTracker;
|
||||
|
||||
private final MongoObjectFactory mongoObjectFactory;
|
||||
|
||||
public ExpeditionTrackerFactory(SensorFixStore sensorFixStore, DomainObjectFactory domainObjectFactory, MongoObjectFactory mongoObjectFactory) {
|
||||
this.windTrackers = new HashMap<RaceDefinition, WindTracker>();
|
||||
this.sensorFixStore = sensorFixStore;
|
||||
windReceivers = new HashMap<Integer, UDPExpeditionReceiver>();
|
||||
final Activator activator = Activator.getInstance();
|
||||
defaultPort = activator.getExpeditionUDPPort();
|
||||
deviceConfigurations = new ConcurrentHashMap<>();
|
||||
devicesPerBoatId = new ConcurrentHashMap<>();
|
||||
final BundleContext context = activator.getContext();
|
||||
this.mongoObjectFactory = mongoObjectFactory;
|
||||
for (final ExpeditionDeviceConfiguration expeditionDeviceConfigurationLoadedFromDB : domainObjectFactory.getExpeditionDeviceConfigurations()) {
|
||||
addOrReplaceDeviceConfigurationNoPersistence(expeditionDeviceConfigurationLoadedFromDB);
|
||||
}
|
||||
if (context != null) {
|
||||
sensorFixServiceTracker = startListeningForSensorFixStoreSuppliers(context);
|
||||
} else {
|
||||
sensorFixServiceTracker = null;
|
||||
}
|
||||
logger.info("Created "+getClass().getName()+" with default UDP port "+defaultPort);
|
||||
}
|
||||
|
||||
private ServiceTracker<SensorFixStoreSupplier, SensorFixStoreSupplier> startListeningForSensorFixStoreSuppliers(BundleContext context) {
|
||||
final ServiceTracker<SensorFixStoreSupplier, SensorFixStoreSupplier> result = new ServiceTracker<>(context, SensorFixStoreSupplier.class,
|
||||
new ServiceTrackerCustomizer<SensorFixStoreSupplier, SensorFixStoreSupplier>() {
|
||||
@Override
|
||||
public SensorFixStoreSupplier addingService(ServiceReference<SensorFixStoreSupplier> reference) {
|
||||
final SensorFixStoreSupplier service = Activator.getInstance().getContext().getService(reference);
|
||||
sensorFixStore = service.getSensorFixStore();
|
||||
return service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifiedService(ServiceReference<SensorFixStoreSupplier> reference,
|
||||
SensorFixStoreSupplier service) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removedService(ServiceReference<SensorFixStoreSupplier> reference,
|
||||
SensorFixStoreSupplier service) {
|
||||
// check if there is still a supplier left:
|
||||
final SensorFixStoreSupplier nextService = sensorFixServiceTracker.getService();
|
||||
if (nextService != null) {
|
||||
sensorFixStore = nextService.getSensorFixStore();
|
||||
}
|
||||
}
|
||||
});
|
||||
result.open();
|
||||
return result;
|
||||
}
|
||||
|
||||
public synchronized static ExpeditionTrackerFactory getInstance() {
|
||||
return getInstance(/* sensorFixStore */ null, PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory(),
|
||||
PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this constructor in non-OSGi scenarios such as plain JUnit test environments where the
|
||||
* {@link SensorFixStoreSupplier} cannot be discovered through the registry.
|
||||
*/
|
||||
public static ExpeditionTrackerFactory getInstance(SensorFixStore sensorFixStore, DomainObjectFactory domainObjectFactory, MongoObjectFactory mongoObjectFactory) {
|
||||
if (defaultInstance == null) {
|
||||
defaultInstance = new ExpeditionTrackerFactory(sensorFixStore, domainObjectFactory, mongoObjectFactory);
|
||||
}
|
||||
return defaultInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindTracker createWindTracker(DynamicTrackedRegatta trackedRegatta, RaceDefinition race,
|
||||
boolean correctByDeclination) throws SocketException {
|
||||
WindTracker result = getExistingWindTracker(race);
|
||||
if (result == null) {
|
||||
DynamicTrackedRace trackedRace = trackedRegatta.getTrackedRace(race);
|
||||
UDPExpeditionReceiver receiver = getOrCreateWindReceiverOnDefaultPort();
|
||||
result = new ExpeditionWindTracker(trackedRace,
|
||||
correctByDeclination ? DeclinationService.INSTANCE : null, receiver, this);
|
||||
windTrackers.put(race, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindTracker getExistingWindTracker(RaceDefinition race) {
|
||||
return windTrackers.get(race);
|
||||
}
|
||||
|
||||
public UDPExpeditionReceiver getOrCreateWindReceiverOnDefaultPort() throws SocketException {
|
||||
return getOrCreateWindReceiverForPort(defaultPort);
|
||||
}
|
||||
|
||||
private synchronized UDPExpeditionReceiver getOrCreateWindReceiverForPort(int port) throws SocketException {
|
||||
UDPExpeditionReceiver receiver = windReceivers.get(port);
|
||||
if (receiver == null) {
|
||||
receiver = new UDPExpeditionReceiver(port, this);
|
||||
windReceivers.put(port, receiver);
|
||||
Thread t = new Thread(receiver, "Expedition Wind Receiver on port "+port);
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
}
|
||||
return receiver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the factory that the wind tracker has stopped tracking wind for <code>race</code>. This
|
||||
* will remove the tracker from the respective caches.
|
||||
*/
|
||||
synchronized void trackerStopped(RaceDefinition race, ExpeditionWindTracker windTracker) {
|
||||
if (windTrackers.get(race) != windTracker) {
|
||||
throw new IllegalArgumentException("Intenral error: expected to remove wind tracker "+windTracker+
|
||||
", but another wind tracker "+windTrackers.get(race)+" was registered.");
|
||||
}
|
||||
windTrackers.remove(race);
|
||||
if (windTracker.getReceiver().isStopped()) {
|
||||
UDPExpeditionReceiver receiver = windReceivers.get(windTracker.getReceiver().getPort());
|
||||
if (receiver != windTracker.getReceiver()) {
|
||||
throw new IllegalArgumentException("Internal error: expected to remove wind receiver "+
|
||||
windTracker.getReceiver()+" but found receiver "+receiver);
|
||||
}
|
||||
windReceivers.remove(windTracker.getReceiver().getPort());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ExpeditionWindTrackerFactory [defaultPort=" + defaultPort + "]";
|
||||
}
|
||||
|
||||
public Iterable<? extends ExpeditionDeviceConfiguration> getDeviceConfigurations() {
|
||||
return Collections.unmodifiableCollection(deviceConfigurations.values());
|
||||
}
|
||||
|
||||
public void addOrReplaceDeviceConfiguration(ExpeditionDeviceConfiguration deviceConfiguration) {
|
||||
addOrReplaceDeviceConfigurationNoPersistence(deviceConfiguration);
|
||||
mongoObjectFactory.storeExpeditionDeviceConfiguration(deviceConfiguration);
|
||||
}
|
||||
|
||||
private void addOrReplaceDeviceConfigurationNoPersistence(ExpeditionDeviceConfiguration deviceConfiguration) {
|
||||
if (deviceConfiguration.getExpeditionBoatId() != null &&
|
||||
devicesPerBoatId.containsKey(deviceConfiguration.getExpeditionBoatId()) &&
|
||||
!devicesPerBoatId.get(deviceConfiguration.getExpeditionBoatId()).equals(deviceConfiguration)) {
|
||||
throw new IllegalStateException("Trying to create an ambiguous Expedition Boat ID mapping: established is "+
|
||||
devicesPerBoatId.get(deviceConfiguration.getExpeditionBoatId())+
|
||||
" and boat ID #"+deviceConfiguration.getExpeditionBoatId()+" therefore cannot be mapped to "+deviceConfiguration+
|
||||
" at the same time.");
|
||||
}
|
||||
final ExpeditionDeviceConfiguration old = deviceConfigurations.put(deviceConfiguration.getDeviceUuid(), deviceConfiguration);
|
||||
if (old != null && old.getExpeditionBoatId() != null) {
|
||||
devicesPerBoatId.remove(old.getExpeditionBoatId());
|
||||
}
|
||||
if (deviceConfiguration.getExpeditionBoatId() != null) {
|
||||
devicesPerBoatId.put(deviceConfiguration.getExpeditionBoatId(), deviceConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeDeviceConfiguration(ExpeditionDeviceConfiguration deviceConfiguration) {
|
||||
deviceConfigurations.remove(deviceConfiguration.getDeviceUuid());
|
||||
if (deviceConfiguration.getExpeditionBoatId() != null) {
|
||||
devicesPerBoatId.remove(deviceConfiguration.getExpeditionBoatId());
|
||||
}
|
||||
mongoObjectFactory.removeExpeditionDeviceConfiguration(deviceConfiguration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpeditionGpsDeviceIdentifier getGpsDeviceIdentifier(int boatId) {
|
||||
final ExpeditionDeviceConfiguration deviceConfig = devicesPerBoatId.get(boatId);
|
||||
final ExpeditionGpsDeviceIdentifier result;
|
||||
if (deviceConfig == null) {
|
||||
result = null;
|
||||
} else {
|
||||
result = new ExpeditionGpsDeviceIdentifierImpl(deviceConfig.getDeviceUuid());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpeditionSensorDeviceIdentifier getSensorDeviceIdentifier(int boatId) {
|
||||
final ExpeditionDeviceConfiguration deviceConfig = devicesPerBoatId.get(boatId);
|
||||
final ExpeditionSensorDeviceIdentifier result;
|
||||
if (deviceConfig == null) {
|
||||
result = null;
|
||||
} else {
|
||||
result = new ExpeditionSensorDeviceIdentifierImpl(deviceConfig.getDeviceUuid());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SensorFixStore getSensorFixStore() {
|
||||
return sensorFixStore;
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -20,7 +20,7 @@ import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.WindTracker;
|
||||
|
||||
/**
|
||||
* Can be subscribed to a {@link UDPExpeditionReceiver} and forwards the wind information
|
||||
* Can be subscribed to a {@link UDPExpeditionReceiver} and forwards wind information
|
||||
* received to the {@link DynamicTrackedRace} passed to the constructor.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
@@ -35,7 +35,7 @@ public class ExpeditionWindTracker extends AbstractWindTracker implements Expedi
|
||||
|
||||
private final UDPExpeditionReceiver receiver;
|
||||
|
||||
private final ExpeditionWindTrackerFactory factory;
|
||||
private final ExpeditionTrackerFactory factory;
|
||||
|
||||
/**
|
||||
* @param declinationService
|
||||
@@ -47,7 +47,7 @@ public class ExpeditionWindTracker extends AbstractWindTracker implements Expedi
|
||||
* calling {@link #stop}, this subscription will be removed again.
|
||||
*/
|
||||
public ExpeditionWindTracker(DynamicTrackedRace race, DeclinationService declinationService,
|
||||
UDPExpeditionReceiver receiver, ExpeditionWindTrackerFactory factory) {
|
||||
UDPExpeditionReceiver receiver, ExpeditionTrackerFactory factory) {
|
||||
super(race);
|
||||
this.lastKnownPositionPerBoatID = new HashMap<Integer, Position>();
|
||||
this.declinationService = declinationService;
|
||||
@@ -60,7 +60,7 @@ public class ExpeditionWindTracker extends AbstractWindTracker implements Expedi
|
||||
public void stop() {
|
||||
synchronized (factory) {
|
||||
receiver.removeListener(this);
|
||||
factory.windTrackerStopped(getTrackedRace().getRace(), this);
|
||||
factory.trackerStopped(getTrackedRace().getRace(), this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-104
@@ -1,104 +0,0 @@
|
||||
package com.sap.sailing.expeditionconnector;
|
||||
|
||||
import java.net.SocketException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.declination.DeclinationService;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.WindTracker;
|
||||
import com.sap.sailing.domain.tracking.WindTrackerFactory;
|
||||
import com.sap.sailing.expeditionconnector.impl.Activator;
|
||||
|
||||
public class ExpeditionWindTrackerFactory implements WindTrackerFactory {
|
||||
private static Logger logger = Logger.getLogger(ExpeditionWindTrackerFactory.class.getName());
|
||||
|
||||
private static ExpeditionWindTrackerFactory defaultInstance;
|
||||
|
||||
/**
|
||||
* Remembers the wind tracker and the port on which the UDP receiver with which the wind tracker is
|
||||
* registers is listening for incoming Expedition messages.
|
||||
*/
|
||||
private final Map<RaceDefinition, WindTracker> windTrackers;
|
||||
|
||||
private final Map<Integer, UDPExpeditionReceiver> windReceivers;
|
||||
|
||||
private final int defaultPort;
|
||||
|
||||
public ExpeditionWindTrackerFactory() {
|
||||
this.windTrackers = new HashMap<RaceDefinition, WindTracker>();
|
||||
windReceivers = new HashMap<Integer, UDPExpeditionReceiver>();
|
||||
defaultPort = Activator.getInstance().getExpeditionUDPPort();
|
||||
logger.info("Created "+getClass().getName()+" with default UDP port "+defaultPort);
|
||||
}
|
||||
|
||||
public synchronized static ExpeditionWindTrackerFactory getInstance() {
|
||||
if (defaultInstance == null) {
|
||||
defaultInstance = new ExpeditionWindTrackerFactory();
|
||||
}
|
||||
return defaultInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindTracker createWindTracker(DynamicTrackedRegatta trackedRegatta, RaceDefinition race,
|
||||
boolean correctByDeclination) throws SocketException {
|
||||
WindTracker result = getExistingWindTracker(race);
|
||||
if (result == null) {
|
||||
DynamicTrackedRace trackedRace = trackedRegatta.getTrackedRace(race);
|
||||
UDPExpeditionReceiver receiver = getOrCreateWindReceiverOnDefaultPort();
|
||||
result = new ExpeditionWindTracker(trackedRace,
|
||||
correctByDeclination ? DeclinationService.INSTANCE : null, receiver, this);
|
||||
windTrackers.put(race, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindTracker getExistingWindTracker(RaceDefinition race) {
|
||||
return windTrackers.get(race);
|
||||
}
|
||||
|
||||
public UDPExpeditionReceiver getOrCreateWindReceiverOnDefaultPort() throws SocketException {
|
||||
return getOrCreateWindReceiverForPort(defaultPort);
|
||||
}
|
||||
|
||||
private synchronized UDPExpeditionReceiver getOrCreateWindReceiverForPort(int port) throws SocketException {
|
||||
UDPExpeditionReceiver receiver = windReceivers.get(port);
|
||||
if (receiver == null) {
|
||||
receiver = new UDPExpeditionReceiver(port);
|
||||
windReceivers.put(port, receiver);
|
||||
Thread t = new Thread(receiver, "Expedition Wind Receiver on port "+port);
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
}
|
||||
return receiver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the factory that the wind tracker has stopped tracking wind for <code>race</code>. This
|
||||
* will remove the tracker from the respective caches.
|
||||
*/
|
||||
synchronized void windTrackerStopped(RaceDefinition race, ExpeditionWindTracker windTracker) {
|
||||
if (windTrackers.get(race) != windTracker) {
|
||||
throw new IllegalArgumentException("Intenral error: expected to remove wind tracker "+windTracker+
|
||||
", but another wind tracker "+windTrackers.get(race)+" was registered.");
|
||||
}
|
||||
windTrackers.remove(race);
|
||||
if (windTracker.getReceiver().isStopped()) {
|
||||
UDPExpeditionReceiver receiver = windReceivers.get(windTracker.getReceiver().getPort());
|
||||
if (receiver != windTracker.getReceiver()) {
|
||||
throw new IllegalArgumentException("Internal error: expected to remove wind receiver "+
|
||||
windTracker.getReceiver()+" but found receiver "+receiver);
|
||||
}
|
||||
windReceivers.remove(windTracker.getReceiver().getPort());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ExpeditionWindTrackerFactory [defaultPort=" + defaultPort + "]";
|
||||
}
|
||||
}
|
||||
+82
-6
@@ -5,7 +5,14 @@ import java.net.SocketException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sap.sailing.domain.common.sensordata.ExpeditionExtendedSensorDataMetadata;
|
||||
import com.sap.sailing.domain.common.tracking.DoubleVectorFix;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.common.tracking.impl.DoubleVectorFixImpl;
|
||||
import com.sap.sailing.domain.racelog.tracking.SensorFixStore;
|
||||
import com.sap.sailing.expeditionconnector.impl.ExpeditionMessageParser;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionGpsDeviceIdentifier;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionSensorDeviceIdentifier;
|
||||
import com.sap.sailing.udpconnector.UDPReceiver;
|
||||
|
||||
/**
|
||||
@@ -20,10 +27,18 @@ public class UDPExpeditionReceiver extends UDPReceiver<ExpeditionMessage, Expedi
|
||||
* Remembers, per boat ID, the milliseconds difference between the time the message was received
|
||||
* and the GPS time stamp provided by the message.
|
||||
*/
|
||||
private final Map<Integer, Long> timeStampOfLastMessageReceived;
|
||||
private final Map<Integer, Long> delayBetweenMessageTimestampAndTimepointReceived;
|
||||
|
||||
private final ExpeditionMessageParser parser;
|
||||
|
||||
/**
|
||||
* An optional lookup facility for device identifiers for a {@link ExpeditionMessage#getBoatID() boat ID} as
|
||||
* received in an Expedition UDP stream; if device identifiers are returned by a non-{@code null} registry, GPS /
|
||||
* sensor fixes will be assembled upon receiving them, and they will be submitted to the {@link SensorFixStore}.
|
||||
* Otherwise, only wind data will be forwarded.
|
||||
*/
|
||||
private final DeviceRegistry deviceRegistry;
|
||||
|
||||
/**
|
||||
* Launches a listener and dumps messages received to the console
|
||||
* @param args 0: port to listen on
|
||||
@@ -46,13 +61,74 @@ public class UDPExpeditionReceiver extends UDPReceiver<ExpeditionMessage, Expedi
|
||||
* start this object in a new thread.
|
||||
*/
|
||||
public UDPExpeditionReceiver(int listeningOnPort) throws SocketException {
|
||||
super(listeningOnPort);
|
||||
this.timeStampOfLastMessageReceived = new HashMap<Integer, Long>();
|
||||
parser = new ExpeditionMessageParser(this);
|
||||
this(listeningOnPort, /* DeviceRegistry */ null);
|
||||
}
|
||||
|
||||
public Map<Integer, Long> getTimeStampOfLastMessageReceived() {
|
||||
return timeStampOfLastMessageReceived;
|
||||
/**
|
||||
* You need call {@link #run} to actually start receiving events. To do this asynchronously, start this object in a
|
||||
* new thread.
|
||||
*
|
||||
* @param deviceRegistry
|
||||
* if not {@code null}, a look-up for each message's {@link ExpeditionMessage#getBoatID() boat ID} will
|
||||
* be performed; if valid device identifiers for GPS and sensor tracks are returned, this receiver will
|
||||
* produce GPS and sensor fixes, respectively, with the device identifiers produced by the
|
||||
* {@link DeviceRegistry} and submit them to the {@link SensorFixStore}.
|
||||
*/
|
||||
public UDPExpeditionReceiver(int listeningOnPort, DeviceRegistry deviceRegistry) throws SocketException {
|
||||
super(listeningOnPort);
|
||||
this.deviceRegistry = deviceRegistry;
|
||||
this.delayBetweenMessageTimestampAndTimepointReceived = new HashMap<Integer, Long>();
|
||||
parser = new ExpeditionMessageParser(this);
|
||||
addListener(msg->produceAndStoreOptionalFixes(msg), /* validMessagesOnly */ true);
|
||||
}
|
||||
|
||||
private void produceAndStoreOptionalFixes(ExpeditionMessage msg) {
|
||||
if (deviceRegistry != null) {
|
||||
final ExpeditionGpsDeviceIdentifier gpsDeviceIdentifier = deviceRegistry.getGpsDeviceIdentifier(msg.getBoatID());
|
||||
if (gpsDeviceIdentifier != null) {
|
||||
tryToProduceAndStoreGpsFix(msg, gpsDeviceIdentifier);
|
||||
}
|
||||
final ExpeditionSensorDeviceIdentifier sensorDeviceIdentifier = deviceRegistry.getSensorDeviceIdentifier(msg.getBoatID());
|
||||
if (sensorDeviceIdentifier != null) {
|
||||
tryToProduceAndStoreSensorFix(msg, sensorDeviceIdentifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If this message completes the set of data required to produce a sensor fix, do so and
|
||||
* store in the {@link DeviceRegistry#getSensorFixStore() sensor fix store}.
|
||||
*/
|
||||
private void tryToProduceAndStoreSensorFix(ExpeditionMessage msg, ExpeditionSensorDeviceIdentifier sensorDeviceIdentifier) {
|
||||
final Double heelInDegrees = msg.hasValue(ExpeditionMessage.ID_ROLL) ? msg.getValue(ExpeditionMessage.ID_ROLL) : null;
|
||||
final Double trimInDegrees = msg.hasValue(ExpeditionMessage.ID_PITCH) ? msg.getValue(ExpeditionMessage.ID_PITCH) : null;
|
||||
final Double[] vector = new Double[Math.max(ExpeditionExtendedSensorDataMetadata.HEEL.getColumnIndex(),
|
||||
ExpeditionExtendedSensorDataMetadata.TRIM.getColumnIndex())+1];
|
||||
vector[ExpeditionExtendedSensorDataMetadata.HEEL.getColumnIndex()] = heelInDegrees;
|
||||
vector[ExpeditionExtendedSensorDataMetadata.TRIM.getColumnIndex()] = trimInDegrees;
|
||||
final DoubleVectorFix fix = new DoubleVectorFixImpl(msg.getTimePoint(), vector);
|
||||
if (fix != null && fix.hasValidData()) {
|
||||
deviceRegistry.getSensorFixStore().storeFix(sensorDeviceIdentifier, fix);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If this message completes the set of data required to produce a GPS fix, do so and
|
||||
* store in the {@link DeviceRegistry#getSensorFixStore() sensor fix store}.
|
||||
*/
|
||||
private void tryToProduceAndStoreGpsFix(ExpeditionMessage msg, ExpeditionGpsDeviceIdentifier gpsDeviceIdentifier) {
|
||||
final GPSFixMoving fix = msg.getGPSFixMoving();
|
||||
if (fix != null) {
|
||||
deviceRegistry.getSensorFixStore().storeFix(gpsDeviceIdentifier, fix);
|
||||
}
|
||||
}
|
||||
|
||||
public Long getLastKnownMessageDelayInMillis(int boatID) {
|
||||
return delayBetweenMessageTimestampAndTimepointReceived.get(boatID);
|
||||
}
|
||||
|
||||
public void updateLastKnownMessageDelay(int boatID, long timestampAsMillis) {
|
||||
delayBetweenMessageTimestampAndTimepointReceived.put(boatID, timestampAsMillis);
|
||||
}
|
||||
|
||||
protected ExpeditionMessageParser getParser() {
|
||||
|
||||
+61
-3
@@ -1,13 +1,30 @@
|
||||
package com.sap.sailing.expeditionconnector.impl;
|
||||
|
||||
import java.util.Dictionary;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.osgi.framework.BundleActivator;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceRegistration;
|
||||
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifierStringSerializationHandler;
|
||||
import com.sap.sailing.domain.tracking.WindTrackerFactory;
|
||||
import com.sap.sailing.expeditionconnector.ExpeditionWindTrackerFactory;
|
||||
import com.sap.sailing.expeditionconnector.ExpeditionTrackerFactory;
|
||||
import com.sap.sailing.expeditionconnector.persistence.DomainObjectFactory;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionGpsDeviceIdentifier;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionGpsDeviceIdentifierJsonHandler;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionSensorDeviceIdentifier;
|
||||
import com.sap.sailing.expeditionconnector.persistence.MongoObjectFactory;
|
||||
import com.sap.sailing.expeditionconnector.persistence.PersistenceFactory;
|
||||
import com.sap.sailing.server.gateway.serialization.racelog.tracking.DeviceIdentifierJsonHandler;
|
||||
import com.sap.sse.common.TypeBasedServiceFinder;
|
||||
import com.sap.sse.util.impl.ThreadFactoryWithPriority;
|
||||
|
||||
public class Activator implements BundleActivator {
|
||||
private static Logger logger = Logger.getLogger(Activator.class.getName());
|
||||
@@ -16,17 +33,33 @@ public class Activator implements BundleActivator {
|
||||
|
||||
private static Activator instance;
|
||||
|
||||
/**
|
||||
* Registrations of OSGi services to be de-registered when the bundle shuts down
|
||||
*/
|
||||
private Set<ServiceRegistration<?>> registrations = new HashSet<>();
|
||||
|
||||
private static final int DEFAULT_PORT = 2013;
|
||||
|
||||
private int port;
|
||||
|
||||
private BundleContext context;
|
||||
|
||||
private final ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactoryWithPriority(Thread.NORM_PRIORITY, /* daemon */ true));
|
||||
|
||||
public Activator() {
|
||||
port = Integer.valueOf(System.getProperty(EXPEDITION_UDP_PORT_PROPERTY_NAME, ""+DEFAULT_PORT));
|
||||
logger.log(Level.INFO, "setting default for "+EXPEDITION_UDP_PORT_PROPERTY_NAME+" to "+port);
|
||||
}
|
||||
|
||||
private Dictionary<String, String> getDict(String type) {
|
||||
Dictionary<String, String> properties = new Hashtable<String, String>();
|
||||
properties.put(TypeBasedServiceFinder.TYPE, type);
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(BundleContext context) throws Exception {
|
||||
this.context = context;
|
||||
if (instance == null) {
|
||||
instance = this;
|
||||
}
|
||||
@@ -35,8 +68,20 @@ public class Activator implements BundleActivator {
|
||||
logger.log(Level.INFO, "found "+EXPEDITION_UDP_PORT_PROPERTY_NAME+"="+port+" in OSGi context");
|
||||
}
|
||||
// register the Expedition wind tracker factory as an OSGi service
|
||||
context.registerService(ExpeditionWindTrackerFactory.class, ExpeditionWindTrackerFactory.getInstance(), /* properties */null);
|
||||
context.registerService(WindTrackerFactory.class, ExpeditionWindTrackerFactory.getInstance(), /* properties */null);
|
||||
final DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory();
|
||||
final MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory();
|
||||
executor.execute(()->{
|
||||
logger.info("Creating ExpeditionTrackerFactory");
|
||||
final ExpeditionTrackerFactory expeditionTrackerFactory = new ExpeditionTrackerFactory(
|
||||
/* sensorFixStore will be discovered by tracker factory through OSGi */ null, domainObjectFactory, mongoObjectFactory);
|
||||
registrations.add(context.registerService(ExpeditionTrackerFactory.class, expeditionTrackerFactory, /* properties */null));
|
||||
registrations.add(context.registerService(WindTrackerFactory.class, expeditionTrackerFactory, /* properties */null));
|
||||
|
||||
registrations.add(context.registerService(DeviceIdentifierJsonHandler.class, new ExpeditionGpsDeviceIdentifierJsonHandler(), getDict(ExpeditionGpsDeviceIdentifier.TYPE)));
|
||||
registrations.add(context.registerService(DeviceIdentifierStringSerializationHandler.class, new ExpeditionGpsStringSerializationHandler(), getDict(ExpeditionGpsDeviceIdentifier.TYPE)));
|
||||
registrations.add(context.registerService(DeviceIdentifierJsonHandler.class, new ExpeditionSensorDeviceIdentifierJsonHandler(), getDict(ExpeditionSensorDeviceIdentifier.TYPE)));
|
||||
registrations.add(context.registerService(DeviceIdentifierStringSerializationHandler.class, new ExpeditionSensorStringSerializationHandler(), getDict(ExpeditionSensorDeviceIdentifier.TYPE)));
|
||||
});
|
||||
}
|
||||
|
||||
public static Activator getInstance() {
|
||||
@@ -46,8 +91,21 @@ public class Activator implements BundleActivator {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public BundleContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public void setContext(BundleContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
for (ServiceRegistration<?> reg : registrations) {
|
||||
reg.unregister();
|
||||
}
|
||||
registrations.clear();
|
||||
this.context = null;
|
||||
}
|
||||
|
||||
public int getExpeditionUDPPort() {
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.sap.sailing.expeditionconnector.impl;
|
||||
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifierStringSerializationHandler;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionGpsDeviceIdentifierSerializationHandler;
|
||||
|
||||
public class ExpeditionGpsStringSerializationHandler extends ExpeditionGpsDeviceIdentifierSerializationHandler
|
||||
implements DeviceIdentifierStringSerializationHandler {
|
||||
|
||||
}
|
||||
+8
-14
@@ -42,19 +42,7 @@ public class ExpeditionMessageImpl implements ExpeditionMessage {
|
||||
* {@link #getTimePoint() time point}.
|
||||
*/
|
||||
public ExpeditionMessageImpl(int boatID, Map<Integer, Double> values, boolean valid, String originalMessage) {
|
||||
this.boatID = boatID;
|
||||
// ensure that nobody can manipulate the map used by this message object from outside
|
||||
this.values = new HashMap<Integer, Double>(values);
|
||||
this.valid = valid;
|
||||
this.originalMessage = originalMessage;
|
||||
this.createdAtMillis = System.currentTimeMillis();
|
||||
if (hasValue(ID_GPS_TIME)) {
|
||||
timePoint = new MillisecondsTimePoint((long)
|
||||
(getValue(ID_GPS_TIME)*24*3600*1000) + // this is the milliseconds since 31.12.1899 0:00:00 UTC
|
||||
cal.getTimeInMillis());
|
||||
} else {
|
||||
timePoint = new MillisecondsTimePoint(createdAtMillis);
|
||||
}
|
||||
this(boatID, values, valid, /* defaultTimePoint */ null, originalMessage, /* unused */ true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,9 +51,13 @@ public class ExpeditionMessageImpl implements ExpeditionMessage {
|
||||
* stamp
|
||||
*/
|
||||
public ExpeditionMessageImpl(int boatID, Map<Integer, Double> values, boolean valid, TimePoint defaultTimePoint, String originalMessage) {
|
||||
this(boatID, values, valid, defaultTimePoint, originalMessage, /* unused */ true);
|
||||
if (defaultTimePoint == null) {
|
||||
throw new IllegalArgumentException("defaultTimePoint for ExpeditionMessageImpl constructor must not be null");
|
||||
throw new IllegalArgumentException("defaultTimePoint for this ExpeditionMessageImpl constructor must not be null");
|
||||
}
|
||||
}
|
||||
|
||||
private ExpeditionMessageImpl(int boatID, Map<Integer, Double> values, boolean valid, TimePoint defaultTimePoint, String originalMessage, boolean unused) {
|
||||
this.boatID = boatID;
|
||||
// ensure that nobody can manipulate the map used by this message object from outside
|
||||
this.values = new HashMap<Integer, Double>(values);
|
||||
@@ -76,6 +68,8 @@ public class ExpeditionMessageImpl implements ExpeditionMessage {
|
||||
timePoint = new MillisecondsTimePoint((long)
|
||||
(getValue(ID_GPS_TIME)*24*3600*1000) + // this is the milliseconds since 31.12.1899 0:00:00 UTC
|
||||
cal.getTimeInMillis());
|
||||
} else if (defaultTimePoint == null) {
|
||||
timePoint = new MillisecondsTimePoint(createdAtMillis);
|
||||
} else {
|
||||
timePoint = defaultTimePoint;
|
||||
}
|
||||
|
||||
+2
-2
@@ -36,7 +36,7 @@ public class ExpeditionMessageParser implements UDPMessageParser<ExpeditionMessa
|
||||
Map<Integer, Double> values = new HashMap<Integer, Double>();
|
||||
String[] variablesAndValuesInterleaved = variableValuePairs.split(",");
|
||||
long now = System.currentTimeMillis();
|
||||
Long diff = receiver.getTimeStampOfLastMessageReceived().get(boatID);
|
||||
Long diff = receiver.getLastKnownMessageDelayInMillis(boatID);
|
||||
TimePoint defaultForMessageTimePoint;
|
||||
if (diff != null) {
|
||||
// compute a reasonable default for a time stamp in case message doesn't provide one
|
||||
@@ -60,7 +60,7 @@ public class ExpeditionMessageParser implements UDPMessageParser<ExpeditionMessa
|
||||
}
|
||||
if (result.hasValue(ExpeditionMessage.ID_GPS_TIME)) {
|
||||
// an original GPS time stamp; then remember the difference between now and the time stamp
|
||||
receiver.getTimeStampOfLastMessageReceived().put(boatID, now - result.getTimePoint().asMillis());
|
||||
receiver.updateLastKnownMessageDelay(boatID, now - result.getTimePoint().asMillis());
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.sap.sailing.expeditionconnector.impl;
|
||||
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionSensorDeviceIdentifierSerializationHandler;
|
||||
import com.sap.sailing.server.gateway.serialization.racelog.tracking.DeviceIdentifierJsonHandler;
|
||||
|
||||
public class ExpeditionSensorDeviceIdentifierJsonHandler extends ExpeditionSensorDeviceIdentifierSerializationHandler
|
||||
implements DeviceIdentifierJsonHandler {
|
||||
|
||||
@Override
|
||||
public DeviceIdentifier deserialize(Object serialized, String type, String stringRepresentation)
|
||||
throws TransformationException {
|
||||
return deserialize((String) serialized, type, stringRepresentation);
|
||||
}
|
||||
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.sap.sailing.expeditionconnector.impl;
|
||||
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifierStringSerializationHandler;
|
||||
import com.sap.sailing.expeditionconnector.persistence.ExpeditionSensorDeviceIdentifierSerializationHandler;
|
||||
|
||||
public class ExpeditionSensorStringSerializationHandler extends ExpeditionSensorDeviceIdentifierSerializationHandler
|
||||
implements DeviceIdentifierStringSerializationHandler {
|
||||
|
||||
}
|
||||
@@ -47,6 +47,7 @@
|
||||
<plugin id="com.sap.sailing.domain.tractracadapter" autoStart="false" startLevel="4" />
|
||||
<plugin id="com.sap.sailing.domain.tractracadapter.persistence" autoStart="true" startLevel="3" />
|
||||
<plugin id="com.sap.sailing.ess40.resultimport" autoStart="true" startLevel="3" />
|
||||
<plugin id="com.sap.sailing.expeditionconnector.persistence" autoStart="true" startLevel="3" />
|
||||
<plugin id="com.sap.sailing.freg.resultimport" autoStart="true" startLevel="3" />
|
||||
<plugin id="com.sap.sailing.gwt.ui" autoStart="true" startLevel="5" />
|
||||
<plugin id="com.sap.sailing.kiworesultimport" autoStart="true" startLevel="3" />
|
||||
|
||||
@@ -402,4 +402,18 @@ Computes leaderboard information for sailing races and offers RESTful APIs to al
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.sap.sailing.expeditionconnector.persistence"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.sap.sailing.expeditionconnector.common"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
</feature>
|
||||
|
||||
@@ -3,6 +3,7 @@ encoding//src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/S
|
||||
encoding//src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaRaceStatesComponent.java=utf-8
|
||||
encoding//src/main/java/com/sap/sailing/gwt/server/HomeServiceUtil.java=utf-8
|
||||
encoding//src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDetailsComposite.java=utf-8
|
||||
encoding//src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionDeviceConfigurationsPanel.java=utf-8
|
||||
encoding//src/main/java/com/sap/sailing/gwt/ui/adminconsole/IgtimiAccountsPanel.java=utf-8
|
||||
encoding//src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java=utf-8
|
||||
encoding//src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties=UTF-8
|
||||
|
||||
@@ -53,7 +53,9 @@ Require-Bundle: com.sap.sailing.domain,
|
||||
com.sap.sailing.polars.datamining,
|
||||
com.sap.sse.datamining.annotations,
|
||||
com.sap.sse.shared.android,
|
||||
com.sap.sailing.competitorimport
|
||||
com.sap.sailing.competitorimport,
|
||||
com.sap.sailing.expeditionconnector,
|
||||
com.sap.sailing.expeditionconnector.common
|
||||
Bundle-Activator: com.sap.sailing.gwt.ui.server.Activator
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Import-Package: javax.servlet;version="3.1.0",
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.security.common/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.polars.datamining.shared/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.datamining.annotations/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.expeditionconnector.common/src" path="3" type="2"/> "/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/>
|
||||
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
|
||||
|
||||
@@ -50,6 +50,12 @@
|
||||
<version>1.6.0-SNAPSHOT</version>
|
||||
<classifier>sources</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sap.sailing</groupId>
|
||||
<artifactId>com.sap.sailing.expeditionconnector.common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>sources</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sap.sailing</groupId>
|
||||
<artifactId>com.sap.sailing.domain.common</artifactId>
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package com.google.gwt.user.client.rpc.core.com.sap.sailing.expeditionconnector;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.google.gwt.user.client.rpc.CustomFieldSerializer;
|
||||
import com.google.gwt.user.client.rpc.SerializationException;
|
||||
import com.google.gwt.user.client.rpc.SerializationStreamReader;
|
||||
import com.google.gwt.user.client.rpc.SerializationStreamWriter;
|
||||
import com.sap.sailing.expeditionconnector.ExpeditionDeviceConfiguration;
|
||||
|
||||
public class ExpeditionDeviceConfiguration_CustomFieldSerializer extends CustomFieldSerializer<ExpeditionDeviceConfiguration> {
|
||||
|
||||
@Override
|
||||
public void serializeInstance(SerializationStreamWriter streamWriter, ExpeditionDeviceConfiguration instance)
|
||||
throws SerializationException {
|
||||
serialize(streamWriter, instance);
|
||||
}
|
||||
|
||||
public static void serialize(SerializationStreamWriter streamWriter, ExpeditionDeviceConfiguration instance)
|
||||
throws SerializationException {
|
||||
streamWriter.writeString(instance.getName());
|
||||
streamWriter.writeObject(instance.getDeviceUuid());
|
||||
streamWriter.writeObject(instance.getExpeditionBoatId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCustomInstantiateInstance() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpeditionDeviceConfiguration instantiateInstance(SerializationStreamReader streamReader)
|
||||
throws SerializationException {
|
||||
return instantiate(streamReader);
|
||||
}
|
||||
|
||||
public static ExpeditionDeviceConfiguration instantiate(SerializationStreamReader streamReader)
|
||||
throws SerializationException {
|
||||
return new ExpeditionDeviceConfiguration(streamReader.readString(), (UUID) streamReader.readObject(), (Integer) streamReader.readObject());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeInstance(SerializationStreamReader streamReader, ExpeditionDeviceConfiguration instance)
|
||||
throws SerializationException {
|
||||
deserialize(streamReader, instance);
|
||||
}
|
||||
|
||||
public static void deserialize(SerializationStreamReader streamReader, ExpeditionDeviceConfiguration instance) {
|
||||
// Done by instantiateInstance
|
||||
}
|
||||
|
||||
}
|
||||
+7
@@ -67,6 +67,13 @@ public class GetEventViewAction implements SailingAction<EventViewDTO>, IsClient
|
||||
dto.setState(HomeServiceUtil.calculateEventState(event));
|
||||
// bug2982: always show leaderboard and competitor analytics
|
||||
dto.setHasAnalytics(true);
|
||||
|
||||
String description = event.getDescription();
|
||||
if (description == null || description.trim().isEmpty() || event.getName().equalsIgnoreCase(description)) {
|
||||
// If a description isn't useful, it should not be shown in the UI
|
||||
description = null;
|
||||
}
|
||||
dto.setDescription(description);
|
||||
|
||||
final EventType eventType = EventUtil.getEventType(event);
|
||||
dto.setType(eventType);
|
||||
|
||||
+9
@@ -23,6 +23,7 @@ public class EventViewDTO extends EventMetadataDTO implements Result, HasLogo {
|
||||
private ImageDTO logoImage;
|
||||
private String officialWebsiteURL;
|
||||
private String sailorsInfoWebsiteURL;
|
||||
private String description;
|
||||
|
||||
public EventType getType() {
|
||||
return type;
|
||||
@@ -116,4 +117,12 @@ public class EventViewDTO extends EventMetadataDTO implements Result, HasLogo {
|
||||
}
|
||||
return venue;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
.box {
|
||||
font-size: 1rem;
|
||||
border: 1px solid #dedede;
|
||||
border-radius: 0.333333333333333em;
|
||||
overflow: hidden;
|
||||
}
|
||||
.box_header {
|
||||
color: #333;
|
||||
font-size: 1.2em;
|
||||
font-weight: 700;
|
||||
background: #f2f2f2;
|
||||
padding: 1.111111111111111em;
|
||||
border-bottom: 1px solid #dedede;
|
||||
}
|
||||
.box_content {
|
||||
margin: 0;
|
||||
padding: 1em;
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.sap.sailing.gwt.home.desktop.partials.eventdescription;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.DivElement;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
|
||||
public class EventDescription extends Composite {
|
||||
|
||||
private static StatisticsBoxUiBinder uiBinder = GWT.create(StatisticsBoxUiBinder.class);
|
||||
|
||||
interface StatisticsBoxUiBinder extends UiBinder<Widget, EventDescription> {
|
||||
}
|
||||
|
||||
@UiField DivElement descriptionUi;
|
||||
|
||||
public EventDescription(String description) {
|
||||
EventDescriptionResources.INSTANCE.css().ensureInjected();
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
descriptionUi.setInnerText(description);
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
|
||||
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
|
||||
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared">
|
||||
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:with field="local_res" type="com.sap.sailing.gwt.home.desktop.partials.eventdescription.EventDescriptionResources" />
|
||||
<g:HTMLPanel addStyleNames="{local_res.css.box}">
|
||||
<div class="{local_res.css.box_header}" ui:field="titleUi"><ui:text from="{i18n.description}" /></div>
|
||||
<div class="{local_res.css.box_content}" ui:field="descriptionUi"></div>
|
||||
</g:HTMLPanel>
|
||||
</ui:UiBinder>
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package com.sap.sailing.gwt.home.desktop.partials.eventdescription;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.resources.client.ClientBundle;
|
||||
import com.google.gwt.resources.client.CssResource;
|
||||
|
||||
public interface EventDescriptionResources extends ClientBundle {
|
||||
public static final EventDescriptionResources INSTANCE = GWT.create(EventDescriptionResources.class);
|
||||
|
||||
@Source("EventDescription.gss")
|
||||
LocalCss css();
|
||||
|
||||
public interface LocalCss extends CssResource {
|
||||
String box();
|
||||
String box_header();
|
||||
String box_content();
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -94,7 +94,12 @@ public class MultiRegattaListStepsBody extends UIObject implements RequiresResiz
|
||||
}
|
||||
|
||||
private String caculateSeriesName(RegattaProgressSeriesDTO seriesProgress) {
|
||||
return DEFAULT_SERIES_NAME.equals(seriesProgress.getName()) ? I18N.races() : seriesProgress.getName();
|
||||
if (seriesProgress.getName() == null || seriesProgress.getName().isEmpty()
|
||||
|| DEFAULT_SERIES_NAME.equals(seriesProgress.getName())) {
|
||||
return I18N.races();
|
||||
} else {
|
||||
return seriesProgress.getName();
|
||||
}
|
||||
}
|
||||
|
||||
private String caculateSeriesNameMedium() {
|
||||
|
||||
+18
-46
@@ -1,6 +1,7 @@
|
||||
package com.sap.sailing.gwt.home.desktop.partials.old.leaderboard;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.DivElement;
|
||||
@@ -10,8 +11,6 @@ import com.google.gwt.dom.client.Style.Unit;
|
||||
import com.google.gwt.dom.client.Style.Visibility;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.event.logical.shared.AttachEvent;
|
||||
import com.google.gwt.event.logical.shared.AttachEvent.Handler;
|
||||
import com.google.gwt.event.logical.shared.CloseEvent;
|
||||
import com.google.gwt.event.logical.shared.CloseHandler;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
@@ -24,14 +23,11 @@ import com.google.gwt.user.client.ui.FocusWidget;
|
||||
import com.google.gwt.user.client.ui.HTMLPanel;
|
||||
import com.google.gwt.user.client.ui.PopupPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.domain.common.RaceIdentifier;
|
||||
import com.sap.sailing.domain.common.dto.LeaderboardDTO;
|
||||
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
|
||||
import com.sap.sailing.gwt.home.desktop.partials.old.EventRegattaLeaderboardResources;
|
||||
import com.sap.sailing.gwt.home.desktop.partials.old.LeaderboardDelegate;
|
||||
import com.sap.sailing.gwt.settings.client.leaderboard.MultiRaceLeaderboardSettings;
|
||||
import com.sap.sailing.gwt.ui.client.DebugIdHelper;
|
||||
import com.sap.sailing.gwt.ui.client.LeaderboardUpdateListener;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil;
|
||||
import com.sap.sailing.gwt.ui.leaderboard.MultiRaceLeaderboardPanel;
|
||||
@@ -81,28 +77,6 @@ public class OldLeaderboard extends Composite implements BusyStateChangeListener
|
||||
fullscreenAnchor.setTitle(StringMessages.INSTANCE.openFullscreenView());
|
||||
this.delegate = delegate;
|
||||
this.setupFullscreenDelegate();
|
||||
|
||||
// adding handler on page loading
|
||||
this.addAttachHandler(new Handler() {
|
||||
@Override
|
||||
public void onAttachOrDetach(AttachEvent event) {
|
||||
if (event.isAttached() && leaderboardPanel != null) {
|
||||
// waiting while leaderboard is loaded
|
||||
leaderboardPanel.addLeaderboardUpdateListener(new LeaderboardUpdateListener() {
|
||||
@Override
|
||||
public void updatedLeaderboard(LeaderboardDTO leaderboard) {
|
||||
// If race or regatta is live then check button by default
|
||||
if (leaderboard.hasLiveRace(autoRefreshTimer.getLiveTimePointInMillis())) {
|
||||
turnOnAutoPlay();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void currentRaceSelected(RaceIdentifier raceIdentifier, RaceColumnDTO raceColumn) { }
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupFullscreenDelegate() {
|
||||
@@ -142,14 +116,19 @@ public class OldLeaderboard extends Composite implements BusyStateChangeListener
|
||||
if (autoRefreshTimer.getPlayState() != PlayStates.Playing) {
|
||||
autoRefreshTimer.setPlayMode(PlayModes.Live);
|
||||
}
|
||||
|
||||
// Styles applied each time because of tabs switching. In this case play mode stays as Playing but styling is lost
|
||||
autoRefreshAnchor.addStyleName(local_res.css().regattaleaderboard_meta_reload_live());
|
||||
if (delegate != null) {
|
||||
delegate.getAutoRefreshControl().addStyleName(local_res.css().regattaleaderboard_meta_reload_live());
|
||||
}
|
||||
// Styles applied each time because of tabs switching. In this case play mode stays as Playing but style is lost
|
||||
this.updateAutoRefreshStylesDependingOnPlayState();
|
||||
}
|
||||
|
||||
private void updateAutoRefreshStylesDependingOnPlayState() {
|
||||
final boolean isPlaying = autoRefreshTimer != null && autoRefreshTimer.getPlayState() == PlayStates.Playing;
|
||||
final String isPlayingStyleName = local_res.css().regattaleaderboard_meta_reload_live();
|
||||
this.autoRefreshAnchor.setStyleName(isPlayingStyleName, isPlaying);
|
||||
if (Objects.nonNull(delegate)) {
|
||||
this.delegate.getAutoRefreshControl().setStyleName(isPlayingStyleName, isPlaying);
|
||||
}
|
||||
}
|
||||
|
||||
@UiHandler("autoRefreshAnchor")
|
||||
void toogleAutoRefreshClicked(ClickEvent event) {
|
||||
autoRefreshAnchor.removeStyleName(local_res.css().regattaleaderboard_meta_reload_live());
|
||||
@@ -161,21 +140,10 @@ public class OldLeaderboard extends Composite implements BusyStateChangeListener
|
||||
if (autoRefreshTimer != null) {
|
||||
if (autoRefreshTimer.getPlayState() == PlayStates.Playing) {
|
||||
autoRefreshTimer.pause();
|
||||
// autoRefreshAnchor.getElement().getStyle().setBackgroundColor("#8ab54e");
|
||||
// autoRefreshAnchor.addStyleName(local_res.css().regattaleaderboard_meta_reload_playing());
|
||||
// if (delegate != null) {
|
||||
// delegate.getAutoRefreshControl().getElement().getStyle().setBackgroundColor("#8ab54e");
|
||||
// delegate.getAutoRefreshControl().addStyleName(local_res.css().regattaleaderboard_meta_reload_playing());
|
||||
// }
|
||||
} else {
|
||||
// playing the standalone leaderboard means putting it into live mode
|
||||
autoRefreshTimer.setPlayMode(PlayModes.Live);
|
||||
// autoRefreshAnchor.getElement().getStyle().setBackgroundColor("red");
|
||||
autoRefreshAnchor.addStyleName(local_res.css().regattaleaderboard_meta_reload_live());
|
||||
if (delegate != null) {
|
||||
// delegate.getAutoRefreshControl().getElement().getStyle().setBackgroundColor("red");
|
||||
delegate.getAutoRefreshControl().addStyleName(local_res.css().regattaleaderboard_meta_reload_live());
|
||||
}
|
||||
this.updateAutoRefreshStylesDependingOnPlayState();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,12 +201,13 @@ public class OldLeaderboard extends Composite implements BusyStateChangeListener
|
||||
if (leaderboardPanel.getComponentContext() == null) {
|
||||
throw new IllegalStateException("Leaderboard Component with null Context");
|
||||
}
|
||||
this.updateAutoRefreshStylesDependingOnPlayState();
|
||||
oldLeaderboardPanel.add(leaderboardPanel);
|
||||
leaderboardPanel.addBusyStateChangeListener(this);
|
||||
}
|
||||
|
||||
public void updatedLeaderboard(LeaderboardDTO leaderboard) {
|
||||
boolean hasLiveRace = leaderboardPanel.hasLiveRace();
|
||||
final boolean hasLiveRace = leaderboardPanel.hasLiveRace();
|
||||
if (leaderboard != null) {
|
||||
String comment = leaderboard.getComment() != null ? leaderboard.getComment() : "";
|
||||
String scoringScheme = leaderboard.scoringScheme != null ? ScoringSchemeTypeFormatter.getDescription(leaderboard.scoringScheme, StringMessages.INSTANCE) : "";
|
||||
@@ -276,6 +245,9 @@ public class OldLeaderboard extends Composite implements BusyStateChangeListener
|
||||
setVisible(delegate.getLastScoringUpdateTimeElement(), !hasLiveRace);
|
||||
setVisible(delegate.getScoringSchemeElement(), true);
|
||||
}
|
||||
if (hasLiveRace) {
|
||||
turnOnAutoPlay();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ public class StandingsListCompetitor extends UIObject {
|
||||
teamIdUi.setInnerText(competitor.getSailID());
|
||||
teamNameUi.setInnerText(competitor.getName());
|
||||
String pointsString = i18n.pointsValue(item.getNetPoints());
|
||||
if(showRaceCounts) {
|
||||
if (showRaceCounts) {
|
||||
pointsString += " (" + i18n.racesCount(item.getRaceCount()) + ")";
|
||||
}
|
||||
pointsUi.setInnerText(pointsString);
|
||||
|
||||
+12
@@ -8,11 +8,13 @@ import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.ui.AcceptsOneWidget;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.HTMLPanel;
|
||||
import com.google.gwt.user.client.ui.SimplePanel;
|
||||
import com.sap.sailing.gwt.common.client.controls.tabbar.TabView;
|
||||
import com.sap.sailing.gwt.home.communication.event.GetLiveRacesForEventAction;
|
||||
import com.sap.sailing.gwt.home.communication.event.GetRegattaListViewAction;
|
||||
import com.sap.sailing.gwt.home.communication.event.statistics.GetEventStatisticsAction;
|
||||
import com.sap.sailing.gwt.home.communication.regatta.RegattaWithProgressDTO;
|
||||
import com.sap.sailing.gwt.home.desktop.partials.eventdescription.EventDescription;
|
||||
import com.sap.sailing.gwt.home.desktop.partials.eventstage.EventOverviewStage;
|
||||
import com.sap.sailing.gwt.home.desktop.partials.liveraces.LiveRacesList;
|
||||
import com.sap.sailing.gwt.home.desktop.partials.multiregattalist.MultiRegattaList;
|
||||
@@ -41,6 +43,7 @@ public class MultiregattaOverviewTabView extends Composite implements Multiregat
|
||||
private static MyBinder ourUiBinder = GWT.create(MyBinder.class);
|
||||
|
||||
@UiField(provided = true) EventOverviewStage stageUi;
|
||||
@UiField SimplePanel descriptionUi;
|
||||
@UiField(provided = true) LiveRacesList liveRacesListUi;
|
||||
@UiField(provided = true) DropdownFilter<String> boatCategoryFilterUi;
|
||||
@UiField(provided = true) MultiRegattaList regattaListUi;
|
||||
@@ -71,7 +74,16 @@ public class MultiregattaOverviewTabView extends Composite implements Multiregat
|
||||
boatCategoryFilterUi = new DropdownFilter<String>(StringMessages.INSTANCE.all(), regattaFilterList);
|
||||
regattaListUi = new MultiRegattaList(currentPresenter, false);
|
||||
statisticsBoxUi = new EventStatisticsBox(true, new DesktopStatisticsBoxView());
|
||||
|
||||
initWidget(ourUiBinder.createAndBindUi(this));
|
||||
|
||||
final String description = currentPresenter.getEventDTO().getDescription();
|
||||
if (description != null) {
|
||||
descriptionUi.add(new EventDescription(description));
|
||||
} else {
|
||||
descriptionUi.removeFromParent();
|
||||
}
|
||||
|
||||
raceOfficeSectionUi.addLink(StringMessages.INSTANCE.racesOverview(), currentPresenter.getRegattaOverviewLink());
|
||||
|
||||
RefreshManager refreshManager = new RefreshManagerWithErrorAndBusy(this, contentArea, currentPresenter.getDispatch(), currentPresenter.getErrorAndBusyClientFactory());
|
||||
|
||||
+6
-5
@@ -1,17 +1,18 @@
|
||||
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'
|
||||
xmlns:dp='urn:import:com.sap.sailing.gwt.home.desktop.partials'
|
||||
xmlns:sp='urn:import:com.sap.sailing.gwt.home.shared.partials'>
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
|
||||
<g:HTMLPanel>
|
||||
<dp:eventstage.EventOverviewStage ui:field="stageUi" />
|
||||
<div class="{res.mediaCss.grid}">
|
||||
<div class="{res.mediaCss.small12} {res.mediaCss.columns} {res.mainCss.spacermarginbottommedium}">
|
||||
<g:SimplePanel ui:field="descriptionUi" addStyleNames="{res.mainCss.spacermargin} {res.mainCss.spacermargintopmedium}" />
|
||||
<dp:liveraces.LiveRacesList ui:field="liveRacesListUi" addStyleNames="{res.mainCss.spacermargin} {res.mainCss.spacermargintopmedium}" />
|
||||
<dp:regattanavigation.DropdownFilter ui:field="boatCategoryFilterUi"
|
||||
addStyleNames="{res.mainCss.spacermargintopmedium} {res.mainCss.spacermarginbottombig}"/>
|
||||
<dp:multiregattalist.MultiRegattaList ui:field="regattaListUi" />
|
||||
<sp:statistics.EventStatisticsBox addStyleNames="{res.mainCss.spacermargin} {res.mainCss.spacermargintopmedium}" ui:field="statisticsBoxUi"/>
|
||||
addStyleNames="{res.mainCss.spacermargintopmedium} {res.mainCss.spacermarginbottombig}"/>
|
||||
<dp:multiregattalist.MultiRegattaList ui:field="regattaListUi" />
|
||||
<sp:statistics.EventStatisticsBox addStyleNames="{res.mainCss.spacermargin} {res.mainCss.spacermargintopmedium}" ui:field="statisticsBoxUi"/>
|
||||
</div>
|
||||
</div>
|
||||
<dp:raceoffice.RaceOfficeSection ui:field="raceOfficeSectionUi" />
|
||||
|
||||
+1
@@ -131,6 +131,7 @@ public class RegattaLeaderboardTabView extends SharedLeaderboardRegattaTabView<R
|
||||
}
|
||||
});
|
||||
} else {
|
||||
leaderboardPanel.loadCompleteLeaderboard(false);
|
||||
leaderboardConsumer.consume(leaderboardPanel);
|
||||
}
|
||||
} else {
|
||||
|
||||
+13
-1
@@ -17,6 +17,7 @@ import com.sap.sailing.gwt.home.communication.event.statistics.GetEventStatistic
|
||||
import com.sap.sailing.gwt.home.communication.eventview.HasRegattaMetadata;
|
||||
import com.sap.sailing.gwt.home.communication.eventview.HasRegattaMetadata.RegattaState;
|
||||
import com.sap.sailing.gwt.home.communication.regatta.RegattaWithProgressDTO;
|
||||
import com.sap.sailing.gwt.home.desktop.partials.eventdescription.EventDescription;
|
||||
import com.sap.sailing.gwt.home.desktop.partials.eventstage.EventOverviewStage;
|
||||
import com.sap.sailing.gwt.home.desktop.partials.liveraces.LiveRacesList;
|
||||
import com.sap.sailing.gwt.home.desktop.partials.multiregattalist.MultiRegattaListItem;
|
||||
@@ -42,10 +43,11 @@ public class RegattaOverviewTabView extends Composite implements RegattaTabView<
|
||||
|
||||
private static MyBinder ourUiBinder = GWT.create(MyBinder.class);
|
||||
private Presenter currentPresenter;
|
||||
|
||||
|
||||
@UiField SimplePanel regattaInfoContainerUi;
|
||||
@UiField(provided = true) LiveRacesList liveRacesListUi;
|
||||
@UiField(provided = true) EventOverviewStage stageUi;
|
||||
@UiField SimplePanel descriptionUi;
|
||||
@UiField(provided = true) StandingsList standingsUi;
|
||||
@UiField(provided = true) EventStatisticsBox statisticsBoxUi;
|
||||
@UiField RaceOfficeSection raceOfficeSectionUi;
|
||||
@@ -71,6 +73,16 @@ public class RegattaOverviewTabView extends Composite implements RegattaTabView<
|
||||
final HasRegattaMetadata regattaMetadata = currentPresenter.getRegattaMetadata();
|
||||
standingsUi = new StandingsList(regattaMetadata != null && regattaMetadata.getState() == RegattaState.FINISHED, currentPresenter.getRegattaLeaderboardNavigation(currentPresenter.getRegattaId()));
|
||||
initWidget(ourUiBinder.createAndBindUi(this));
|
||||
|
||||
if (!currentPresenter.showRegattaMetadata()) {
|
||||
final String description = currentPresenter.getEventDTO().getDescription();
|
||||
if (description != null) {
|
||||
descriptionUi.add(new EventDescription(description));
|
||||
} else {
|
||||
descriptionUi.removeFromParent();
|
||||
}
|
||||
}
|
||||
|
||||
raceOfficeSectionUi.addLink(StringMessages.INSTANCE.racesOverview(), currentPresenter.getRegattaOverviewLink());
|
||||
|
||||
RefreshManager refreshManager = new RefreshManagerWithErrorAndBusy(this, contentArea, currentPresenter.getDispatch(), currentPresenter.getErrorAndBusyClientFactory());
|
||||
|
||||
+4
-3
@@ -1,15 +1,16 @@
|
||||
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'
|
||||
xmlns:dp='urn:import:com.sap.sailing.gwt.home.desktop.partials'
|
||||
xmlns:sp='urn:import:com.sap.sailing.gwt.home.shared.partials'>
|
||||
xmlns:dp='urn:import:com.sap.sailing.gwt.home.desktop.partials'
|
||||
xmlns:sp='urn:import:com.sap.sailing.gwt.home.shared.partials'>
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<g:HTMLPanel>
|
||||
<div class="{res.mediaCss.grid}">
|
||||
<g:SimplePanel addStyleNames="{res.mediaCss.small12} {res.mediaCss.columns}" ui:field="regattaInfoContainerUi"/>
|
||||
<dp:liveraces.LiveRacesList ui:field="liveRacesListUi" addStyleNames="{res.mediaCss.small12} {res.mediaCss.columns} {res.mainCss.spacermargintopmedium}" />
|
||||
<dp:liveraces.LiveRacesList ui:field="liveRacesListUi" addStyleNames="{res.mediaCss.small12} {res.mediaCss.columns} {res.mainCss.spacermargintopmedium}" />
|
||||
</div>
|
||||
<dp:eventstage.EventOverviewStage ui:field="stageUi" addStyleNames="{res.mainCss.spacermargin} {res.mainCss.spacermargintopsmall}" />
|
||||
<div class="{res.mediaCss.grid}">
|
||||
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
|
||||
<g:SimplePanel ui:field="descriptionUi" addStyleNames="{res.mainCss.spacermargin} {res.mainCss.spacermargintopmedium}" />
|
||||
<dp:standings.StandingsList ui:field="standingsUi" addStyleNames="{res.mainCss.spacermargin} {res.mainCss.spacermargintopmedium}" />
|
||||
<sp:statistics.EventStatisticsBox addStyleNames="{res.mainCss.spacermargin} {res.mainCss.spacermargintopmedium} {res.mainCss.spacermarginbottommedium}" ui:field="statisticsBoxUi" />
|
||||
</div>
|
||||
|
||||
+2
@@ -22,6 +22,8 @@
|
||||
state of the currently opened page to get lost.
|
||||
After a sign out (and another page reload) the language preference will stop to take effect.
|
||||
</li>
|
||||
<li>If available, an event description is now shown on event overview pages.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h5 class="articleSubheadline">September 2017</h5>
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.sap.sailing.gwt.home.mobile.partials.eventdescription;
|
||||
|
||||
import com.google.gwt.dom.client.Style.Unit;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.sap.sailing.gwt.home.mobile.partials.section.MobileSection;
|
||||
import com.sap.sailing.gwt.home.mobile.partials.sectionHeader.SectionHeaderContent;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
|
||||
public class EventDescription extends Composite {
|
||||
|
||||
public EventDescription(String description) {
|
||||
final MobileSection section = new MobileSection();
|
||||
SectionHeaderContent header = new SectionHeaderContent();
|
||||
header.setSectionTitle(StringMessages.INSTANCE.description());
|
||||
section.addHeader(header);
|
||||
final Label content = new Label(description);
|
||||
content.getElement().getStyle().setPaddingTop(0.5, Unit.EM);
|
||||
content.getElement().getStyle().setPaddingBottom(0.75, Unit.EM);
|
||||
section.addContent(content);
|
||||
initWidget(section);
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user