diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/DetailType.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/DetailType.java index e2640851b9a..8fd63cec796 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/DetailType.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/DetailType.java @@ -216,7 +216,8 @@ public enum DetailType implements Serializable, SecuredEnum { EXPEDITION_LEG_MAST_BUTT(2, ASCENDING, null, ValueSpreader.CUBIC_ROOT), BRAVO_RACE_HEEL_IN_DEGREES(2, DESCENDING, null, ValueSpreader.CUBIC_ROOT), BRAVO_RACE_PITCH_IN_DEGREES(2, DESCENDING, null, ValueSpreader.CUBIC_ROOT), - PERCENT_TARGET_BOAT_SPEED(2, DESCENDING, PREMIUM_LEADERBOARD_INFORMATION, ValueSpreader.CUBIC_ROOT); + PERCENT_TARGET_BOAT_SPEED(2, DESCENDING, PREMIUM_LEADERBOARD_INFORMATION, ValueSpreader.CUBIC_ROOT), + EXPEDITION_RACE_KICKER_TENSION(2, ASCENDING, null, ValueSpreader.CUBIC_ROOT); private int precision; diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LegEntryDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LegEntryDTO.java index 8f650b0c49d..7978a03eb1d 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LegEntryDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LegEntryDTO.java @@ -531,6 +531,13 @@ public class LegEntryDTO implements Serializable { } } + public void setExpeditionKickerTensionIfAvailable(Double expeditionKickerTension) { + if (expeditionKickerTension != null) { + ensureExpeditionHolder(); + expeditionHolder.expeditionKickerTension = expeditionKickerTension; + } + } + public Double getExpeditionAWA() { return expeditionHolder == null ? null : expeditionHolder.expeditionAWA; } @@ -729,6 +736,7 @@ public class LegEntryDTO implements Serializable { public Double expeditionCourseDetail; public Double expeditionDistanceToPinDetail; public Double expeditionVMGTargVMGDelta; + public Double expeditionKickerTension; @Override public int hashCode() { @@ -784,6 +792,7 @@ public class LegEntryDTO implements Serializable { + ((expeditionTimeToStbLayline == null) ? 0 : expeditionTimeToStbLayline.hashCode()); result = prime * result + ((expeditionVMG == null) ? 0 : expeditionVMG.hashCode()); result = prime * result + ((expeditionVMGTargVMGDelta == null) ? 0 : expeditionVMGTargVMGDelta.hashCode()); + result = prime * result + ((expeditionKickerTension == null) ? 0 : expeditionKickerTension.hashCode()); return result; } @@ -991,6 +1000,11 @@ public class LegEntryDTO implements Serializable { return false; } else if (!expeditionVMGTargVMGDelta.equals(other.expeditionVMGTargVMGDelta)) return false; + if (expeditionKickerTension == null) { + if (other.expeditionKickerTension != null) + return false; + } else if (!expeditionKickerTension.equals(other.expeditionKickerTension)) + return false; return true; } } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/sensordata/BravoExtendedSensorDataMetadata.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/sensordata/BravoExtendedSensorDataMetadata.java index f90487c61ed..cb0064b4d1d 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/sensordata/BravoExtendedSensorDataMetadata.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/sensordata/BravoExtendedSensorDataMetadata.java @@ -73,6 +73,7 @@ public enum BravoExtendedSensorDataMetadata implements ColumnMetadata { EXPEDITION_JIB_CAR_STBD(null, /* expectedInLogfile */ false), // EXPEDITION_MAST_BUTT(null, /* expectedInLogfile */ false), // EXPEDITION_RATE_OF_TURN(null, /* expectedInLogfile */ false), // + EXPEDITION_KICKER_TENSION(null, /* expecedInLogfile */ false), // ; private final String columnName; diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/sensordata/ExpeditionExtendedSensorDataMetadata.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/sensordata/ExpeditionExtendedSensorDataMetadata.java index b578c759a66..3f7f0bfeea2 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/sensordata/ExpeditionExtendedSensorDataMetadata.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/sensordata/ExpeditionExtendedSensorDataMetadata.java @@ -54,6 +54,7 @@ public enum ExpeditionExtendedSensorDataMetadata { EXPEDITION_JIB_CAR_PORT("jibcarport", BravoExtendedSensorDataMetadata.EXPEDITION_JIB_CAR_PORT), // EXPEDITION_JIB_CAR_STBD("jibcarstbd", BravoExtendedSensorDataMetadata.EXPEDITION_JIB_CAR_STBD), // EXPEDITION_MAST_BUTT("mastbutt", BravoExtendedSensorDataMetadata.EXPEDITION_MAST_BUTT), // + EXPEDITION_KICKER_TENSION("kickertension", BravoExtendedSensorDataMetadata.EXPEDITION_KICKER_TENSION), // ; private String columnName; diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/BravoExtendedFix.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/BravoExtendedFix.java index 17b248254ee..39a2a4dfc3f 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/BravoExtendedFix.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/BravoExtendedFix.java @@ -39,6 +39,7 @@ public interface BravoExtendedFix extends BravoFix { Double getExpeditionHDG(); Double getExpeditionHeel(); Double getExpeditionTG_Heell(); + Double getExpeditionKickerTension(); /** * The time to gun in seconds; the value is converted from the Expedition-internal time format based on days */ diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BravoExtendedFixImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BravoExtendedFixImpl.java index 1921e5c3d1c..712d9b33f3c 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BravoExtendedFixImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BravoExtendedFixImpl.java @@ -255,4 +255,9 @@ public class BravoExtendedFixImpl extends BravoFixImpl implements BravoExtendedF } return null; } + + @Override + public Double getExpeditionKickerTension() { + return fix.get(BravoExtendedSensorDataMetadata.EXPEDITION_KICKER_TENSION.getColumnIndex()); + } } diff --git a/java/com.sap.sailing.domain.expeditionadapter/src/com/sap/sailing/domain/expeditionadapter/impl/ExpeditionGPSFixImporter.java b/java/com.sap.sailing.domain.expeditionadapter/src/com/sap/sailing/domain/expeditionadapter/impl/ExpeditionGPSFixImporter.java index 1124cde734c..8228250a511 100755 --- a/java/com.sap.sailing.domain.expeditionadapter/src/com/sap/sailing/domain/expeditionadapter/impl/ExpeditionGPSFixImporter.java +++ b/java/com.sap.sailing.domain.expeditionadapter/src/com/sap/sailing/domain/expeditionadapter/impl/ExpeditionGPSFixImporter.java @@ -49,12 +49,12 @@ public class ExpeditionGPSFixImporter implements GPSFixImporter { protected void handleExpeditionFile(String fileName, InputStream stream, Charset charset) throws IOException { final BufferedReader br = new BufferedReader(new InputStreamReader(stream, charset)); final String headerLine = br.readLine(); - final Map columnDefinitions = ExpeditionExtendedDataImporterImpl - .parseHeader(headerLine); + final ExpeditionExtendedDataImporterImpl importer = new ExpeditionExtendedDataImporterImpl(); + final Map columnDefinitions = importer.parseHeader(headerLine); final AtomicInteger lineNr = new AtomicInteger(0); br.lines().forEach(line -> { if (!line.trim().isEmpty()) { - ExpeditionExtendedDataImporterImpl.parseLine(lineNr.incrementAndGet(), fileName, line, + importer.parseLine(lineNr.incrementAndGet(), fileName, line, columnDefinitions, (timePoint, columnValues, columns) -> { final double latDeg = Double .parseDouble(columnValues[columns.get(LAT_COLUMN_HEADING)]); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/ExpeditionExtendedDataFixMapper.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/ExpeditionExtendedDataFixMapper.java index e1aa45aad0c..24937c22543 100755 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/ExpeditionExtendedDataFixMapper.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/ExpeditionExtendedDataFixMapper.java @@ -15,7 +15,7 @@ import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.impl.CompetitorBravoFixTrackImpl; /** - * {@link SensorFixMapper} implementation to product {@link BravoExtendedFix}es from {@link DoubleVectorFix}es + * {@link SensorFixMapper} implementation to produce {@link BravoExtendedFix}es from {@link DoubleVectorFix}es * interpreted as "Expedition" data. The data has significant overlap with what we typically receive from the * "Bravo" devices. Ultimately, the naming may need to be adjusted, better reflecting that the "Bravo" extended * tracks now assume general responsibility for a broader set of sensor values that may be assigned to a diff --git a/java/com.sap.sailing.domain.vakarosadapter.test/.classpath b/java/com.sap.sailing.domain.vakarosadapter.test/.classpath new file mode 100644 index 00000000000..5383c2c9e48 --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter.test/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/java/com.sap.sailing.domain.vakarosadapter.test/.project b/java/com.sap.sailing.domain.vakarosadapter.test/.project new file mode 100644 index 00000000000..f4d40d49a40 --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter.test/.project @@ -0,0 +1,28 @@ + + + com.sap.sailing.domain.vakarosadapter.test + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/java/com.sap.sailing.domain.vakarosadapter.test/.settings/org.eclipse.core.resources.prefs b/java/com.sap.sailing.domain.vakarosadapter.test/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000000..99f26c0203a --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter.test/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/java/com.sap.sailing.domain.vakarosadapter.test/.settings/org.eclipse.jdt.core.prefs b/java/com.sap.sailing.domain.vakarosadapter.test/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..0869a9baf86 --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter.test/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +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.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/java/com.sap.sailing.domain.vakarosadapter.test/.settings/org.eclipse.pde.core.prefs b/java/com.sap.sailing.domain.vakarosadapter.test/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 00000000000..f29e940a005 --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter.test/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/java/com.sap.sailing.domain.vakarosadapter.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.vakarosadapter.test/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..5b8c2ae3513 --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter.test/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Test +Bundle-SymbolicName: com.sap.sailing.domain.vakarosadapter.test +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Fragment-Host: com.sap.sailing.domain.vakarosadapter +Automatic-Module-Name: com.sap.sailing.domain.vakarosadapter.test +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Import-Package: com.sap.sailing.domain.common, + com.sap.sse.common, + org.junit;version="[4.13.0,5.0.0)" +Require-Bundle: org.hamcrest;bundle-version="2.2.0" diff --git a/java/com.sap.sailing.domain.vakarosadapter.test/build.properties b/java/com.sap.sailing.domain.vakarosadapter.test/build.properties new file mode 100644 index 00000000000..f11210d3f2c --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter.test/build.properties @@ -0,0 +1,5 @@ +source.. = src/,\ + resources/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/java/com.sap.sailing.domain.vakarosadapter.test/pom.xml b/java/com.sap.sailing.domain.vakarosadapter.test/pom.xml new file mode 100644 index 00000000000..d903309ac27 --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter.test/pom.xml @@ -0,0 +1,12 @@ + + + 4.0.0 + + root + com.sap.sailing + 1.0.0-SNAPSHOT + + com.sap.sailing.domain.vakarosadapter.test + eclipse-test-plugin + diff --git a/java/com.sap.sailing.domain.vakarosadapter.test/resources/GDF-13-12-2024.csv.zip b/java/com.sap.sailing.domain.vakarosadapter.test/resources/GDF-13-12-2024.csv.zip new file mode 100644 index 00000000000..0b9d60d526b Binary files /dev/null and b/java/com.sap.sailing.domain.vakarosadapter.test/resources/GDF-13-12-2024.csv.zip differ diff --git a/java/com.sap.sailing.domain.vakarosadapter.test/resources/GDF-8-11-2024.csv.gz b/java/com.sap.sailing.domain.vakarosadapter.test/resources/GDF-8-11-2024.csv.gz new file mode 100644 index 00000000000..f9ad419f292 Binary files /dev/null and b/java/com.sap.sailing.domain.vakarosadapter.test/resources/GDF-8-11-2024.csv.gz differ diff --git a/java/com.sap.sailing.domain.vakarosadapter.test/src/com/sap/sailing/domain/vakarosadapter/test/TestReadingVakarosFiles.java b/java/com.sap.sailing.domain.vakarosadapter.test/src/com/sap/sailing/domain/vakarosadapter/test/TestReadingVakarosFiles.java new file mode 100644 index 00000000000..3727497eb4b --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter.test/src/com/sap/sailing/domain/vakarosadapter/test/TestReadingVakarosFiles.java @@ -0,0 +1,109 @@ +package com.sap.sailing.domain.vakarosadapter.test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.domain.common.sensordata.BravoExtendedSensorDataMetadata; +import com.sap.sailing.domain.common.tracking.DoubleVectorFix; +import com.sap.sailing.domain.common.tracking.GPSFix; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier; +import com.sap.sailing.domain.trackimport.FormatNotSupportedException; +import com.sap.sailing.domain.trackimport.GPSFixImporter.Callback; +import com.sap.sailing.domain.vakarosadapter.VakarosGPSFixImporter; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util; + +public class TestReadingVakarosFiles { + private final static double EPSILON = 0.000000001; + private VakarosGPSFixImporter importer; + + @Before + public void setUp() { + importer = new VakarosGPSFixImporter(); + } + + @Test + public void testReadFileWithLoadValues() throws FormatNotSupportedException, IOException, ParseException { + final String sourceName = "/GDF-8-11-2024.csv.gz"; + final Map> gpsFixes = new HashMap<>(); + final Map> sensorFixes = new HashMap<>(); + readAndAssertNotEmpty(sourceName, gpsFixes, sensorFixes); + // check for presence of fixes corresponding to line: + // timestamp,latitude,longitude,sog_kts,cog,hdg_true,roll,pitch,load_GDF2,load_GDF1 + // 2024-11-08T08:38:56.077,41.7387700,12.2457483,0.000,113.1,125.4,-1.7,4.6,1.40,141.20 + final TimePoint timePoint = TimePoint.of(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX").parse("2024-11-08T08:38:56.077"+"Z")); + boolean foundGPSFix = false; + for (final GPSFix fix : gpsFixes.values().iterator().next()) { + final GPSFixMoving fixMoving = (GPSFixMoving) fix; + if (fix.getTimePoint().equals(timePoint) && + Math.abs(fix.getPosition().getLatDeg() - 41.7387700) < EPSILON && + Math.abs(fix.getPosition().getLngDeg() - 12.2457483) < EPSILON && + Math.abs(fixMoving.getSpeed().getKnots() - 0.000) < EPSILON && + Math.abs(fixMoving.getSpeed().getBearing().getDegrees() - 113.1) < EPSILON && + Math.abs(fixMoving.getOptionalTrueHeading().getDegrees() - 125.4) < EPSILON) { + foundGPSFix = true; + break; + } + } + assertTrue(foundGPSFix); + boolean foundSensorFix = false; + for (final DoubleVectorFix sensorFix : sensorFixes.values().iterator().next()) { + if (sensorFix.getTimePoint().equals(timePoint) && + Math.abs(sensorFix.get(BravoExtendedSensorDataMetadata.HEEL.getColumnIndex()) - -1.7) < EPSILON && + Math.abs(sensorFix.get(BravoExtendedSensorDataMetadata.PITCH.getColumnIndex()) - 4.6) < EPSILON && + Math.abs(sensorFix.get(BravoExtendedSensorDataMetadata.EXPEDITION_KICKER_TENSION.getColumnIndex()) - 1.4) < EPSILON && + Math.abs(sensorFix.get(BravoExtendedSensorDataMetadata.FORESTAY_LOAD.getColumnIndex()) - 141.2) < EPSILON) { + foundSensorFix = true; + break; + } + } + assertTrue(foundSensorFix); + } + + private void readAndAssertNotEmpty(final String sourceName, + final Map> gpsFixes, + final Map> sensorFixes) + throws FormatNotSupportedException, IOException { + final Callback callback = new Callback() { + @Override + public void addFix(GPSFix newFix, TrackFileImportDeviceIdentifier device) { + gpsFixes.computeIfAbsent(device, d->new ArrayList<>()).add(newFix); + } + + @Override + public void addSensorFixes(Iterable newSensorFixes, TrackFileImportDeviceIdentifier device) { + Util.addAll(newSensorFixes, sensorFixes.computeIfAbsent(device, d->new ArrayList<>())); + } + }; + importer.importFixes(getClass().getResourceAsStream(sourceName), Charset.forName("UTF-8"), callback, /* inferSpeedAndBearing */ false, sourceName); + assertFalse(gpsFixes.isEmpty()); + assertFalse(sensorFixes.isEmpty()); + for (final List gpsFixList : gpsFixes.values()) { + assertFalse(gpsFixList.isEmpty()); + } + for (final List sensorFixList : sensorFixes.values()) { + assertFalse(sensorFixList.isEmpty()); + } + } + + @Test + public void testReadFileWithoutLoadValues() throws FormatNotSupportedException, IOException { + final String sourceName = "/GDF-13-12-2024.csv.zip"; + final Map> gpsFixes = new HashMap<>(); + final Map> sensorFixes = new HashMap<>(); + readAndAssertNotEmpty(sourceName, gpsFixes, sensorFixes); + } +} diff --git a/java/com.sap.sailing.domain.vakarosadapter/.classpath b/java/com.sap.sailing.domain.vakarosadapter/.classpath new file mode 100644 index 00000000000..eca7bdba8f0 --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/java/com.sap.sailing.domain.vakarosadapter/.project b/java/com.sap.sailing.domain.vakarosadapter/.project new file mode 100644 index 00000000000..4407c09c3aa --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter/.project @@ -0,0 +1,28 @@ + + + com.sap.sailing.domain.vakarosadapter + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/java/com.sap.sailing.domain.vakarosadapter/.settings/org.eclipse.core.resources.prefs b/java/com.sap.sailing.domain.vakarosadapter/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000000..99f26c0203a --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/java/com.sap.sailing.domain.vakarosadapter/.settings/org.eclipse.jdt.core.prefs b/java/com.sap.sailing.domain.vakarosadapter/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..0869a9baf86 --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +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.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/java/com.sap.sailing.domain.vakarosadapter/.settings/org.eclipse.pde.core.prefs b/java/com.sap.sailing.domain.vakarosadapter/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 00000000000..f29e940a005 --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/java/com.sap.sailing.domain.vakarosadapter/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.vakarosadapter/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..54f55ef3752 --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter/META-INF/MANIFEST.MF @@ -0,0 +1,22 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Vakarosadapter +Bundle-SymbolicName: com.sap.sailing.domain.vakarosadapter +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: com.sap.sailing.domain.vakarosadapter.Activator +Bundle-Vendor: SAP +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Automatic-Module-Name: com.sap.sailing.domain.vakarosadapter +Import-Package: com.sap.sailing.domain.common.impl, + com.sap.sailing.domain.common.sensordata, + com.sap.sailing.domain.common.tracking, + com.sap.sailing.domain.common.tracking.impl, + com.sap.sailing.domain.trackfiles, + com.sap.sailing.domain.trackimport, + com.sap.sailing.server.trackfiles.common, + com.sap.sailing.server.trackfiles.impl, + com.sap.sse.common, + com.sap.sse.common.impl, + org.osgi.framework;version="1.3.0" +Bundle-ActivationPolicy: lazy +Export-Package: com.sap.sailing.domain.vakarosadapter diff --git a/java/com.sap.sailing.domain.vakarosadapter/build.properties b/java/com.sap.sailing.domain.vakarosadapter/build.properties new file mode 100644 index 00000000000..34d2e4d2dad --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/java/com.sap.sailing.domain.vakarosadapter/pom.xml b/java/com.sap.sailing.domain.vakarosadapter/pom.xml new file mode 100644 index 00000000000..286efdbffc1 --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter/pom.xml @@ -0,0 +1,12 @@ + + + 4.0.0 + + root + com.sap.sailing + 1.0.0-SNAPSHOT + + com.sap.sailing.domain.vakarosadapter + eclipse-plugin + diff --git a/java/com.sap.sailing.domain.vakarosadapter/src/com/sap/sailing/domain/vakarosadapter/Activator.java b/java/com.sap.sailing.domain.vakarosadapter/src/com/sap/sailing/domain/vakarosadapter/Activator.java new file mode 100644 index 00000000000..8e3c8d66028 --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter/src/com/sap/sailing/domain/vakarosadapter/Activator.java @@ -0,0 +1,26 @@ +package com.sap.sailing.domain.vakarosadapter; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +import com.sap.sailing.server.trackfiles.common.GPSFixImporterRegistration; +import com.sap.sailing.server.trackfiles.common.SensorDataImporterRegistration; + +public class Activator implements BundleActivator { + private static BundleContext context; + + static BundleContext getContext() { + return context; + } + + public void start(BundleContext bundleContext) throws Exception { + GPSFixImporterRegistration.register(new VakarosGPSFixImporter(), context); + SensorDataImporterRegistration.register(new VakarosExtendedDataImporterImpl(), context); + + + } + + public void stop(BundleContext bundleContext) throws Exception { + Activator.context = null; + } +} diff --git a/java/com.sap.sailing.domain.vakarosadapter/src/com/sap/sailing/domain/vakarosadapter/VakarosExtendedDataImporterImpl.java b/java/com.sap.sailing.domain.vakarosadapter/src/com/sap/sailing/domain/vakarosadapter/VakarosExtendedDataImporterImpl.java new file mode 100644 index 00000000000..d1ba62a551f --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter/src/com/sap/sailing/domain/vakarosadapter/VakarosExtendedDataImporterImpl.java @@ -0,0 +1,25 @@ +package com.sap.sailing.domain.vakarosadapter; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Map; + +import com.sap.sailing.server.trackfiles.impl.ExpeditionExtendedDataImporterImpl; +import com.sap.sse.common.TimePoint; + +public class VakarosExtendedDataImporterImpl extends ExpeditionExtendedDataImporterImpl { + private static final DateFormat timestampFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX"); + private static final String VAKAROS_EXTENDED = "VAKAROS_EXTENDED"; + + public VakarosExtendedDataImporterImpl() { + super(VAKAROS_EXTENDED); + } + + @Override + public TimePoint getTimePointFromLine(Map columnsInFileFromHeader, String[] lineContentTokens) + throws ParseException { + return TimePoint.of(timestampFormat + .parse(lineContentTokens[columnsInFileFromHeader.get(VakarosGPSFixImporter.TIMESTAMP_COLUMN_HEADING)]+"Z")); + } +} diff --git a/java/com.sap.sailing.domain.vakarosadapter/src/com/sap/sailing/domain/vakarosadapter/VakarosGPSFixImporter.java b/java/com.sap.sailing.domain.vakarosadapter/src/com/sap/sailing/domain/vakarosadapter/VakarosGPSFixImporter.java new file mode 100644 index 00000000000..f1257348144 --- /dev/null +++ b/java/com.sap.sailing.domain.vakarosadapter/src/com/sap/sailing/domain/vakarosadapter/VakarosGPSFixImporter.java @@ -0,0 +1,139 @@ +package com.sap.sailing.domain.vakarosadapter; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.sap.sailing.domain.common.impl.DegreePosition; +import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; +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.common.tracking.impl.GPSFixMovingImpl; +import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier; +import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifierImpl; +import com.sap.sailing.domain.trackimport.FormatNotSupportedException; +import com.sap.sailing.domain.trackimport.GPSFixImporter; +import com.sap.sailing.server.trackfiles.impl.CompressedStreamsUtil; +import com.sap.sailing.server.trackfiles.impl.ExpeditionImportFileHandler; +import com.sap.sse.common.Bearing; +import com.sap.sse.common.Util; +import com.sap.sse.common.impl.DegreeBearingImpl; + +public class VakarosGPSFixImporter implements GPSFixImporter { + + private static final Logger logger = Logger.getLogger(VakarosGPSFixImporter.class.getName()); + + static final String TIMESTAMP_COLUMN_HEADING = "timestamp"; + private static final String LAT_COLUMN_HEADING = "latitude"; + private static final String LON_COLUMN_HEADING = "longitude"; + private static final String SOG_COLUMN_HEADING = "sog_kts"; + private static final String COG_COLUMN_HEADING = "cog"; + private static final String HDG_COLUMN_HEADING = "hdg_true"; + private static final String HEEL_COLUMN_HEADING = "roll"; + private static final String PITCH_COLUMN_HEADING = "pitch"; + private static final String LOAD_GDF1_COLUMN_HEADING = "load_gdf1"; + private static final String LOAD_GDF2_COLUMN_HEADING = "load_gdf2"; + + private static final int MAX_EXPEDITION_COLUMN_INDEX = Collections.max(Arrays.asList( + ExpeditionExtendedSensorDataMetadata.HEEL.getColumnIndex(), + ExpeditionExtendedSensorDataMetadata.TRIM.getColumnIndex(), + ExpeditionExtendedSensorDataMetadata.FORESTAY_LOAD.getColumnIndex(), + ExpeditionExtendedSensorDataMetadata.EXPEDITION_KICKER_TENSION.getColumnIndex()))+1; + + private static final String VAKAROS_TYPE = "Vakaros"; + + @Override + public boolean importFixes(InputStream inputStream, Charset charset, Callback callback, + boolean inferSpeedAndBearing, final String sourceName) + throws FormatNotSupportedException, IOException { + final TrackFileImportDeviceIdentifier gpsDevice = new TrackFileImportDeviceIdentifierImpl(sourceName, getType() + "@" + new Date()); + final TrackFileImportDeviceIdentifier sensorDevice = new TrackFileImportDeviceIdentifierImpl(sourceName+"-SENSORS", getType() + "@" + new Date()); + final AtomicBoolean importedFixes = new AtomicBoolean(false); + CompressedStreamsUtil.handlePotentiallyCompressedFiles(sourceName, inputStream, + charset, new ExpeditionImportFileHandler() { + @Override + protected void handleExpeditionFile(String fileName, InputStream stream, Charset charset) throws IOException { + final BufferedReader br = new BufferedReader(new InputStreamReader(stream, charset)); + final String headerLine = br.readLine(); + final VakarosExtendedDataImporterImpl importer = new VakarosExtendedDataImporterImpl(); + final Map columnDefinitions = importer.parseHeader(headerLine); + final AtomicInteger lineNr = new AtomicInteger(0); + br.lines().forEach(line -> { + if (!line.trim().isEmpty()) { + importer.parseLine(lineNr.incrementAndGet(), fileName, line, + columnDefinitions, (timePoint, columnValues, columns) -> { + final double latDeg = Double + .parseDouble(columnValues[columns.get(LAT_COLUMN_HEADING)]); + final double lonDeg = Double + .parseDouble(columnValues[columns.get(LON_COLUMN_HEADING)]); + final double cogDeg = Double + .parseDouble(columnValues[columns.get(COG_COLUMN_HEADING)]); + final double sogKnots = Double + .parseDouble(columnValues[columns.get(SOG_COLUMN_HEADING)]); + final DegreePosition position = new DegreePosition(latDeg, lonDeg); + Bearing optionalTrueHeading; + if (columns.containsKey(HDG_COLUMN_HEADING)) { + try { + optionalTrueHeading = new DegreeBearingImpl(Double.parseDouble(columnValues[columns.get(HDG_COLUMN_HEADING)])); + } catch (NumberFormatException e) { + logger.log(Level.WARNING, "Problem obtaining declination for Expedition fix heading", e); + optionalTrueHeading = null; + } + } else { + optionalTrueHeading = null; + } + final GPSFixMoving fix = new GPSFixMovingImpl( + position, timePoint, + new KnotSpeedWithBearingImpl(sogKnots, + new DegreeBearingImpl(cogDeg)), optionalTrueHeading); + callback.addFix(fix, gpsDevice); + final Double[] fixData = new Double[MAX_EXPEDITION_COLUMN_INDEX]; + fixData[ExpeditionExtendedSensorDataMetadata.HEEL.getColumnIndex()] = parseOptionalValue(HEEL_COLUMN_HEADING, columnValues, columns); + fixData[ExpeditionExtendedSensorDataMetadata.TRIM.getColumnIndex()] = parseOptionalValue(PITCH_COLUMN_HEADING, columnValues, columns); + fixData[ExpeditionExtendedSensorDataMetadata.FORESTAY_LOAD.getColumnIndex()] = parseOptionalValue(LOAD_GDF1_COLUMN_HEADING, columnValues, columns); + fixData[ExpeditionExtendedSensorDataMetadata.EXPEDITION_KICKER_TENSION.getColumnIndex()] = parseOptionalValue(LOAD_GDF2_COLUMN_HEADING, columnValues, columns); + final DoubleVectorFix sensorFix = new DoubleVectorFixImpl(timePoint, fixData); + callback.addSensorFixes(Collections.singleton(sensorFix), sensorDevice); + importedFixes.set(true); + }); + } + }); + } + }); + return importedFixes.get(); + } + + private Double parseOptionalValue(final String columnName, String[] columns, Map header) { + final Integer columnIndex = header.get(columnName); + final Double result; + if (columnIndex != null && columns.length > columnIndex) { + final String columnContent = columns[columnIndex]; + result = Util.hasLength(columnContent) ? Double.parseDouble(columnContent) : null; + } else { + result = null; + } + return result; + } + + @Override + public Iterable getSupportedFileExtensions() { + return ExpeditionImportFileHandler.supportedExpeditionLogFileExtensions; + } + + @Override + public String getType() { + return VAKAROS_TYPE; + } +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java index 6ad821e905e..0058ea3fc2a 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java @@ -1165,6 +1165,7 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard { result.setExpeditionJibCarPortIfAvailable(extractDoubleValue.apply(TrackedLegOfCompetitor::getExpeditionJibCarPortIfAvailable, TrackedLegOfCompetitor::getAverageExpeditionJibCarPortIfAvailable)); result.setExpeditionJibCarStbdIfAvailable(extractDoubleValue.apply(TrackedLegOfCompetitor::getExpeditionJibCarStbdIfAvailable, TrackedLegOfCompetitor::getAverageExpeditionJibCarStbdIfAvailable)); result.setExpeditionMastButtIfAvailable(extractDoubleValue.apply(TrackedLegOfCompetitor::getExpeditionMastButtIfAvailable, TrackedLegOfCompetitor::getAverageExpeditionMastButtIfAvailable)); + result.setExpeditionKickerTensionIfAvailable(extractDoubleValue.apply(TrackedLegOfCompetitor::getExpeditionKickerTensionIfAvailable, TrackedLegOfCompetitor::getAverageExpeditionKickerTensionIfAvailable)); } return result; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/trackimport/GPSFixImporter.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/trackimport/GPSFixImporter.java index 54f894ce1e0..b3d23155996 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/trackimport/GPSFixImporter.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/trackimport/GPSFixImporter.java @@ -5,6 +5,7 @@ import java.nio.charset.Charset; import java.util.Map; import com.sap.sailing.domain.common.DeviceIdentifier; +import com.sap.sailing.domain.common.tracking.DoubleVectorFix; import com.sap.sailing.domain.common.tracking.GPSFix; import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier; @@ -49,6 +50,8 @@ public interface GPSFixImporter { default void addFixes(Iterable fixes, TrackFileImportDeviceIdentifier device) { fixes.forEach(fix->addFix(fix, device)); } + + default void addSensorFixes(Iterable sensorFixes, TrackFileImportDeviceIdentifier device) {} } /** diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/BravoFixTrack.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/BravoFixTrack.java index 45f164784d5..284dc6ea1cd 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/BravoFixTrack.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/BravoFixTrack.java @@ -137,6 +137,7 @@ public interface BravoFixTrack extends S Double getExpeditionJibCarPortIfAvailable(TimePoint at); Double getExpeditionJibCarStbdIfAvailable(TimePoint at); Double getExpeditionMastButtIfAvailable(TimePoint at); + Double getExpeditionKickerTensionIfAvailable(TimePoint at); Double getAverageExpeditionAWAIfAvailable(TimePoint start, TimePoint endTimePoint); Double getAverageExpeditionAWSIfAvailable(TimePoint start, TimePoint endTimePoint); Double getAverageExpeditionTWAIfAvailable(TimePoint start, TimePoint endTimePoint); @@ -176,4 +177,5 @@ public interface BravoFixTrack extends S Double getAverageExpeditionJibCarPortIfAvailable(TimePoint start, TimePoint endTimePoint); Double getAverageExpeditionJibCarStbdIfAvailable(TimePoint start, TimePoint endTimePoint); Double getAverageExpeditionMastButtIfAvailable(TimePoint start, TimePoint endTimePoint); + Double getAverageExpeditionKickerTensionIfAvailable(TimePoint start, TimePoint endTimePoint); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java index 173ec25513d..07742a0d168 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java @@ -413,6 +413,7 @@ public interface TrackedLegOfCompetitor extends Serializable { Double getExpeditionJibCarPortIfAvailable(TimePoint at); Double getExpeditionJibCarStbdIfAvailable(TimePoint at); Double getExpeditionMastButtIfAvailable(TimePoint at); + Double getExpeditionKickerTensionIfAvailable(TimePoint at); Double getAverageExpeditionAWA(TimePoint at); Double getAverageExpeditionAWS(TimePoint at); Double getAverageExpeditionTWA(TimePoint at); @@ -452,4 +453,5 @@ public interface TrackedLegOfCompetitor extends Serializable { Double getAverageExpeditionJibCarPortIfAvailable(TimePoint at); Double getAverageExpeditionJibCarStbdIfAvailable(TimePoint at); Double getAverageExpeditionMastButtIfAvailable(TimePoint at); + Double getAverageExpeditionKickerTensionIfAvailable(TimePoint at); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackImpl.java index ca8ea66fd16..7049001f907 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackImpl.java @@ -71,6 +71,7 @@ public class BravoFixTrackImpl extends S private transient TimeRangeCache> expeditionRateOfTurnCache; private transient TimeRangeCache> expeditionTimeToBurnToLineCache; private transient TimeRangeCache> expeditionDistanceBelowLineInMetersCache; + private transient TimeRangeCache> expeditionKickerTensionCache; /** * If a GPS track was provided at construction time, remember it non-transiently. It is needed when restoring @@ -489,6 +490,17 @@ public class BravoFixTrackImpl extends S ScalableDouble::new); } + @Override + public Double getExpeditionKickerTensionIfAvailable(TimePoint timePoint) { + return getValueFromExtendedFixSkippingNullValues(timePoint, BravoExtendedFix::getExpeditionKickerTension, + ScalableDouble::new); + } + + @Override + public Double getAverageExpeditionKickerTensionIfAvailable(TimePoint start, TimePoint endTimePoint) { + return getAverageOfBravoExtenededFixValueWithCachingForDouble(start, endTimePoint, BravoExtendedFix::getExpeditionKickerTension, expeditionKickerTensionCache); + } + @Override public Double getAverageExpeditionAWAIfAvailable(TimePoint start, TimePoint endTimePoint){ return getAverageOfBravoExtenededFixValueWithCachingForDouble(start, endTimePoint, BravoExtendedFix::getExpeditionAWA, expeditionAWACache); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegOfCompetitorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegOfCompetitorImpl.java index 4ce976c7392..3a4f8fe2e65 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegOfCompetitorImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegOfCompetitorImpl.java @@ -1029,6 +1029,11 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { return getExpeditionValueFromBravoFixTrackIfLegIsStarted(at, BravoFixTrack::getExpeditionMastButtIfAvailable); } + @Override + public Double getExpeditionKickerTensionIfAvailable(TimePoint at) { + return getExpeditionValueFromBravoFixTrackIfLegIsStarted(at, BravoFixTrack::getExpeditionKickerTensionIfAvailable); + } + @Override public Double getAverageExpeditionAWA(TimePoint at) { return getAverageExpeditionValueWithTimeRangeFromBravoFixTrackIfLegIsStarted(at, BravoFixTrack::getAverageExpeditionAWAIfAvailable); @@ -1224,6 +1229,11 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { return getAverageExpeditionValueWithTimeRangeFromBravoFixTrackIfLegIsStarted(at, BravoFixTrack::getAverageExpeditionMastButtIfAvailable); } + @Override + public Double getAverageExpeditionKickerTensionIfAvailable(TimePoint at) { + return getAverageExpeditionValueWithTimeRangeFromBravoFixTrackIfLegIsStarted(at, BravoFixTrack::getAverageExpeditionKickerTensionIfAvailable); + } + private R getExpeditionValueFromBravoFixTrackIfLegIsStarted(TimePoint at, BiFunction, TimePoint, R> valueExtractor) { final R result; if (hasStartedLeg(at)) { diff --git a/java/com.sap.sailing.feature.p2build/raceanalysis.product b/java/com.sap.sailing.feature.p2build/raceanalysis.product index 38aa72c5e55..788b713684c 100755 --- a/java/com.sap.sailing.feature.p2build/raceanalysis.product +++ b/java/com.sap.sailing.feature.p2build/raceanalysis.product @@ -49,6 +49,7 @@ + diff --git a/java/com.sap.sailing.feature/feature.xml b/java/com.sap.sailing.feature/feature.xml index ffb4c43feca..f61d03f5c38 100755 --- a/java/com.sap.sailing.feature/feature.xml +++ b/java/com.sap.sailing.feature/feature.xml @@ -49,6 +49,10 @@ Computes leaderboard information for sailing races and offers RESTful APIs to al id="com.sap.sailing.expeditionconnector" version="0.0.0"/> + + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DetailTypeFormatter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DetailTypeFormatter.java index b37c78f3264..6aa503d4186 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DetailTypeFormatter.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DetailTypeFormatter.java @@ -382,6 +382,8 @@ public class DetailTypeFormatter { return AVERAGE_SYMBOL + stringMessages.expeditionRaceJibCarStbd(); case EXPEDITION_LEG_MAST_BUTT: return AVERAGE_SYMBOL + stringMessages.expeditionRaceMastButt(); + case EXPEDITION_RACE_KICKER_TENSION: + return stringMessages.expeditionRaceKickerTension(); case BRAVO_RACE_HEEL_IN_DEGREES: return stringMessages.currentHeelInDegree(); case BRAVO_RACE_PITCH_IN_DEGREES: @@ -609,6 +611,7 @@ public class DetailTypeFormatter { case EXPEDITION_LEG_JIB_CAR_PORT: case EXPEDITION_LEG_JIB_CAR_STBD: case EXPEDITION_LEG_MAST_BUTT: + case EXPEDITION_RACE_KICKER_TENSION: return ""; } // Throwing an exception to get notified if an implementation of @@ -914,6 +917,7 @@ public class DetailTypeFormatter { case EXPEDITION_RACE_LOAD_P: case EXPEDITION_RACE_LOAD_S: case EXPEDITION_RACE_MAST_BUTT: + case EXPEDITION_RACE_KICKER_TENSION: return ""; case LEG_TACKTYPE_LONGTACK_SHORTTACK: return stringMessages.tackTypeTooltip(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index 4c46938bda3..8475c89430b 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -2020,6 +2020,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String expeditionRaceJibCarPort(); String expeditionRaceJibCarStbd(); String expeditionRaceMastButt(); + String expeditionRaceKickerTension(); String milliBarUnits(); String newExpeditionRace(); String newExpeditionCompetitor(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index d801ccd25e7..eceff0e01b3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -2059,6 +2059,7 @@ expeditionRaceLoadP=eFShroudP expeditionRaceJibCarPort=eaJibCarPFromBow expeditionRaceJibCarStbd=eaJibCarSFromBow expeditionRaceMastButt=exMastButt +expeditionRaceKickerTension=eKicker Tension milliBarUnits=mbar newExpeditionRace=Create a new race newExpeditionCompetitor=Add a new Competitor diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index ea43d169cd0..e10811b2abd 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -2046,6 +2046,7 @@ expeditionRaceLoadP=eFShroudP expeditionRaceJibCarPort=eaJibCarPFromBow expeditionRaceJibCarStbd=eaJibCarSFromBow expeditionRaceMastButt=exMastButt +expeditionRaceKickerTension=eKicker-Spannung newExpeditionRace=Neues Rennen anlegen newExpeditionCompetitor=Neuen Teilnehmer hinzufügen selectOneCompetitorToMapTheImportedData=Bitte einen Teilnehmer auf der linken Seite auswählen. Die importierten Daten werden dem ausgewählten Teinehmer zugeordnet. diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionCourseInferrer.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionCourseInferrer.java index 58bada2468e..3855940871f 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionCourseInferrer.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionCourseInferrer.java @@ -84,13 +84,14 @@ public class ExpeditionCourseInferrer { String headerLine = buffer.readLine(); lineNr.incrementAndGet(); logger.fine("Validate and parse header columns"); - final Map colIndices = ExpeditionExtendedDataImporterImpl.parseHeader(headerLine); - ExpeditionExtendedDataImporterImpl.validateHeader(colIndices); + final ExpeditionExtendedDataImporterImpl importer = new ExpeditionExtendedDataImporterImpl(); + final Map colIndices = importer.parseHeader(headerLine); + importer.validateHeader(colIndices); final Double lastTimeToGunValue[] = new Double[1]; buffer.lines().forEach(line -> { lineNr.incrementAndGet(); if (!line.trim().isEmpty()) { - ExpeditionExtendedDataImporterImpl.parseLine(lineNr.get(), filenameWithSuffix, line, colIndices, + importer.parseLine(lineNr.get(), filenameWithSuffix, line, colIndices, (timePoint, lineContentTokens, columnsInFileFromHeader) -> { // look for a start time based on the time to gun turning negative final Double timeToGunValue = getColumnValue(lineContentTokens, columnsInFileFromHeader, diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/TrackFilesImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/TrackFilesImporter.java index 6273c7c21e7..9401ae51730 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/TrackFilesImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/TrackFilesImporter.java @@ -20,6 +20,7 @@ import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import com.sap.sailing.domain.common.DeviceIdentifier; +import com.sap.sailing.domain.common.tracking.DoubleVectorFix; import com.sap.sailing.domain.common.tracking.GPSFix; import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier; import com.sap.sailing.domain.trackimport.GPSFixImporter; @@ -28,6 +29,7 @@ import com.sap.sailing.server.gateway.trackfiles.impl.ImportResult.TrackImportDT import com.sap.sailing.server.interfaces.RacingEventService; import com.sap.sse.common.NoCorrespondingServiceRegisteredException; import com.sap.sse.common.TimeRange; +import com.sap.sse.common.Timed; import com.sap.sse.common.TransformationException; import com.sap.sse.common.TypeBasedServiceFinderFactory; import com.sap.sse.common.Util.Pair; @@ -91,6 +93,13 @@ public class TrackFilesImporter { storeFixes(fixes, device); deviceIds.add(device); } + + @Override + public void addSensorFixes(Iterable sensorFixes, + TrackFileImportDeviceIdentifier device) { + storeFixes(sensorFixes, device); + deviceIds.add(device); + } }, true, fileName); if (ok) { succeeded.set(ok); @@ -136,7 +145,7 @@ public class TrackFilesImporter { } } - void storeFixes(Iterable fixes, DeviceIdentifier deviceIdentifier) { + void storeFixes(Iterable fixes, DeviceIdentifier deviceIdentifier) { try { service.getSensorFixStore().storeFixes(deviceIdentifier, fixes, /* returnManeuverUpdate */ false, /* returnLiveDelay */ false); } catch (NoCorrespondingServiceRegisteredException e) { diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/windimport/expedition/WindLogParser.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/windimport/expedition/WindLogParser.java index 0a62ecb1cc7..9a63e4512f4 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/windimport/expedition/WindLogParser.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/windimport/expedition/WindLogParser.java @@ -86,13 +86,14 @@ public class WindLogParser { public static Iterable importWind(InputStream windStream) throws IOException { BufferedReader csvReader = new BufferedReader(new InputStreamReader(windStream)); String headerLine = csvReader.readLine(); - final Map headers = ExpeditionExtendedDataImporterImpl.parseHeader(headerLine); + final ExpeditionExtendedDataImporterImpl importer = new ExpeditionExtendedDataImporterImpl(); + final Map headers = importer.parseHeader(headerLine); List result = new ArrayList(); WindBuffer windBuffer = new WindBuffer(); final AtomicInteger lineNr = new AtomicInteger(1); csvReader.lines().forEach(line->{ if (!line.trim().isEmpty()) { - ExpeditionExtendedDataImporterImpl.parseLine(lineNr.incrementAndGet(), "Expedition Wind Import", + importer.parseLine(lineNr.incrementAndGet(), "Expedition Wind Import", line, headers, (timePoint, columnValues, headerDefinitions)->{ windBuffer.updateTime(timePoint); final String trueWindSpeedData = headerDefinitions.containsKey(COL_NAME_TRUE_WIND_SPEED) && diff --git a/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/common/SensorDataImporterRegistration.java b/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/common/SensorDataImporterRegistration.java index 9d569be5960..87eeafb8ff9 100644 --- a/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/common/SensorDataImporterRegistration.java +++ b/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/common/SensorDataImporterRegistration.java @@ -19,12 +19,9 @@ public class SensorDataImporterRegistration { return properties; } - public static Collection> - register(DoubleVectorFixImporter importer, BundleContext context) { + public static Collection> register(DoubleVectorFixImporter importer, BundleContext context) { List> registrations = new ArrayList<>(); - - registrations - .add(context.registerService(DoubleVectorFixImporter.class, importer, getDict(importer.getType()))); + registrations.add(context.registerService(DoubleVectorFixImporter.class, importer, getDict(importer.getType()))); return registrations; } } diff --git a/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/ExpeditionExtendedDataImporterImpl.java b/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/ExpeditionExtendedDataImporterImpl.java index 728ff657850..04c2e1a6204 100755 --- a/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/ExpeditionExtendedDataImporterImpl.java +++ b/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/ExpeditionExtendedDataImporterImpl.java @@ -71,7 +71,11 @@ public class ExpeditionExtendedDataImporterImpl extends AbstractDoubleVectorFixI private final int trackColumnCount; public ExpeditionExtendedDataImporterImpl() { - super(DoubleVectorFixImporter.EXPEDITION_EXTENDED_TYPE); + this(DoubleVectorFixImporter.EXPEDITION_EXTENDED_TYPE); + } + + protected ExpeditionExtendedDataImporterImpl(String fixType) { + super(fixType); columnNamesInFileAndTheirValueIndexInResultingDoubleVectorFix = ExpeditionExtendedSensorDataMetadata .getColumnNamesToIndexInDoubleFix(); trackColumnCount = columnNamesInFileAndTheirValueIndexInResultingDoubleVectorFix.values().stream() @@ -149,7 +153,7 @@ public class ExpeditionExtendedDataImporterImpl extends AbstractDoubleVectorFixI * * All header column names will be stored in the resulting map's key set as lowercase. */ - public static Map parseHeader(String headerLine) { + public Map parseHeader(String headerLine) { final String[] headerTokens = split(headerLine); Map colIndicesInFile = new HashMap<>(); int columnInResultingHeader = 0; @@ -171,7 +175,7 @@ public class ExpeditionExtendedDataImporterImpl extends AbstractDoubleVectorFixI * key set are present in {@code colIndicesInFile}'s key set. If not, an * exception is thrown that reports the columns missing. */ - public static void validateHeader(Map colIndicesInFile) throws FormatNotSupportedException { + public void validateHeader(Map colIndicesInFile) throws FormatNotSupportedException { final boolean dateTimeFormatOk; if (colIndicesInFile.containsKey(UTC_COLUMN)) { dateTimeFormatOk = true; @@ -191,7 +195,7 @@ public class ExpeditionExtendedDataImporterImpl extends AbstractDoubleVectorFixI } } - public static String[] split(String line) { + public String[] split(String line) { return line.split("\\s*,\\s*"); } @@ -215,7 +219,7 @@ public class ExpeditionExtendedDataImporterImpl extends AbstractDoubleVectorFixI * Parses the CSV line and reads the double data values in the order defined * by the col enums. */ - public static void parseLine(long lineNr, String filename, String line, + public void parseLine(long lineNr, String filename, String line, Map columnsInFileFromHeader, LineParserCallback callback) { try { String[] lineContentTokens = split(line); @@ -252,7 +256,7 @@ public class ExpeditionExtendedDataImporterImpl extends AbstractDoubleVectorFixI * * If none of the above is found, {@link null} is returned. */ - public static TimePoint getTimePointFromLine(Map columnsInFileFromHeader, + public TimePoint getTimePointFromLine(Map columnsInFileFromHeader, String[] lineContentTokens) throws ParseException { final TimePoint timePoint; final String date; diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java index 484aa4e1d4d..4eb093a1cc5 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java @@ -5885,6 +5885,10 @@ Replicator { result = getBravoDoubleValue(BravoFixTrack::getExpeditionVMGTargVMGDeltaIfAvailable, trackedRace, competitor, timePoint); break; } + case EXPEDITION_RACE_KICKER_TENSION: { + result = getBravoDoubleValue(BravoFixTrack::getExpeditionKickerTensionIfAvailable, trackedRace, competitor, timePoint); + break; + } case PERCENT_TARGET_BOAT_SPEED: { final PolarDataService polarDataService = getPolarDataService(); final GPSFixTrack competitorTrack = trackedRace.getTrack(competitor); diff --git a/java/pom.xml b/java/pom.xml index d806ed90b66..5ee260d11a2 100755 --- a/java/pom.xml +++ b/java/pom.xml @@ -147,6 +147,8 @@ com.sap.sailing.domain.expeditionadapter com.sap.sailing.domain.tractracadapter com.sap.sailing.domain.tractracadapter.persistence + com.sap.sailing.domain.vakarosadapter + com.sap.sailing.domain.vakarosadapter.test com.sap.sailing.domain.windfinderadapter com.sap.sailing.domain.windfinderadapter.test com.sap.sailing.domain.igtimiadapter