mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-04 10:09:42 +00:00
bug6162: keep the last used fix to "hide" past buffered fixes
This commit is contained in:
1 parent
6d1074a628
commit
eb33bf0253
14 files changed
+45
-18
No files matched your search
+2
-2
@@ -53,9 +53,9 @@ import com.sap.sse.replication.Replicable;
|
||||
* can be registered with this server using the {@link #addListener(BulkFixReceiver)} method.
|
||||
* <p>
|
||||
*
|
||||
* When combined with {@link IgtimiWindReceiver} (which is such a {@link BulkFixReceiver},
|
||||
* When combined with {@link IgtimiWindReceiver} (which is such a {@link BulkFixReceiver}),
|
||||
* {@link IgtimiWindListener}s can be registered on the wind receiver, just as they can
|
||||
* for a websocket connection.
|
||||
* for a websocket connection.<p>
|
||||
*
|
||||
* The server uses <tt>java.nio</tt> and {@link ServerSocketChannel}s, avoiding the creation
|
||||
* of a thread per connection.<p>
|
||||
|
||||
+7
-5
@@ -188,8 +188,9 @@ public class IgtimiWindReceiver implements BulkFixReceiver {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a wind fix produced out of an AWS/AWA and other fixes, as well as the fixes used for this, including a {@link BatteryLevel}
|
||||
* fix, if any was found, although this did technically not contribute to the production of the {@link Wind} object.
|
||||
* Returns a wind fix produced out of an AWS/AWA and other fixes, as well as the fixes used for this (in case of
|
||||
* interpolation between two fixes, the older one of the two is returned), including a {@link BatteryLevel} fix, if
|
||||
* any was found, although this did technically not contribute to the production of the {@link Wind} object.
|
||||
*/
|
||||
private Pair<Wind, Set<Fix>> getWind(final TimePoint timePoint, String deviceSerialNumber) throws ClassNotFoundException, IOException, ParseException {
|
||||
final Wind result;
|
||||
@@ -213,7 +214,7 @@ public class IgtimiWindReceiver implements BulkFixReceiver {
|
||||
final SpeedWithBearing apparentWindSpeedWithDirection = new KnotSpeedWithBearingImpl(aws.getKnots(), apparentWindDirection);
|
||||
/*
|
||||
* Hint from Brent Russell from Igtimi, at 2013-12-05 on the question whether to use GpsLatLong to
|
||||
* improve precision of boat speed / coarse over SOG/COG measurements:
|
||||
* improve precision of boat speed / course over SOG/COG measurements:
|
||||
*
|
||||
* "Personally I would use COG/SOG exclusively, and if unhappy with the result add a small amount of
|
||||
* smoothing and consider dropping samples as outliers if they cause a SOG discontinuity. The latter
|
||||
@@ -260,7 +261,8 @@ public class IgtimiWindReceiver implements BulkFixReceiver {
|
||||
/**
|
||||
* Searches for the last fix at or before {@code timePoint} in the given {@link trackToCleanUp}. If such a fix is
|
||||
* found, adds the given fix to {@code fixesUsed} and clears all fixes from the {@code trackToCleanUp} that are
|
||||
* earlier than or at the {@code timePoint} given.
|
||||
* earlier than the {@code timePoint} given. This in particular preserves at least one live fix which will "hide"
|
||||
* older, e.g., buffered fixes that may be received when a WindBot device sends them out-of-order.
|
||||
* <p>
|
||||
*
|
||||
* This assumes that the {@code fix} passed has been "consumed" now, and earlier fixes will not be relevant anymore.
|
||||
@@ -270,7 +272,7 @@ public class IgtimiWindReceiver implements BulkFixReceiver {
|
||||
final FixType fix = trackToCleanUp.getLastFixAtOrBefore(timePoint);
|
||||
if (fix != null) {
|
||||
fixesUsed.add(fix);
|
||||
trackToCleanUp.removeAllUpToAndIncluding(fix);
|
||||
trackToCleanUp.removeAllUpToExcluding(fix);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -292,6 +292,11 @@ public class TrackImpl<FixType extends Timed> implements Track<FixType> {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates a linear interpolation of values based on their time points and a target time point that is expected
|
||||
* to be in between (inclusive) the two time points for the two values. If the two time points for the two values
|
||||
* are equal, the average of the two values is returned.
|
||||
*/
|
||||
private <V, T> T timeBasedAverage(TimePoint timePoint, ScalableValue<V, T> value1, TimePoint timePoint1, ScalableValue<V, T> value2, TimePoint timePoint2) {
|
||||
final T acc;
|
||||
if (timePoint1.equals(timePoint2)) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
|
||||
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
||||
<listEntry value="/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test"/>
|
||||
</listAttribute>
|
||||
@@ -10,7 +11,7 @@
|
||||
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
|
||||
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=com.sap.sailing.domain.test/src=/test=/true=/<com.sap.sailing.domain.test"/>
|
||||
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=com.sap.sailing.domain.test/src<com.sap.sailing.domain.test"/>
|
||||
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
|
||||
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
|
||||
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
|
||||
|
||||
+1
-1
@@ -26,5 +26,5 @@ public interface DynamicTrackWithRemove<FixType extends Timed> extends DynamicTr
|
||||
*/
|
||||
boolean remove(FixType fix);
|
||||
|
||||
void removeAllUpToAndIncluding(FixType fix);
|
||||
void removeAllUpToExcluding(FixType fix);
|
||||
}
|
||||
+2
-2
@@ -27,7 +27,7 @@ public class DynamicTrackWithRemoveImpl<FixType extends Timed> extends DynamicTr
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllUpToAndIncluding(FixType fix) {
|
||||
getInternalFixes().removeAllLessOrEqual(fix);
|
||||
public void removeAllUpToExcluding(FixType fix) {
|
||||
getInternalFixes().removeAllLessThan(fix);
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -341,6 +341,7 @@ public class WindPanel extends FormPanel implements FilterablePanelProvider<Race
|
||||
contentPanel.add(new Label(stringMessages.seeIgtimiTabForAccountSettings()));
|
||||
final CheckBox correctByDeclination = new CheckBox(stringMessages.declinationCheckbox());
|
||||
correctByDeclination.setValue(true); // by default this is desirable because the Igtimi connector reads uncorrected magnetic values
|
||||
final TextBox optionalBearerTokenBox = new TextBox();
|
||||
final Button importButton = new Button(stringMessages.importWindFromIgtimi());
|
||||
importButton.ensureDebugId("ImportWindFromIgtimi");
|
||||
final HTML resultReport = new HTML();
|
||||
@@ -357,7 +358,7 @@ public class WindPanel extends FormPanel implements FilterablePanelProvider<Race
|
||||
if (Window.confirm(warningMessage)) {
|
||||
resultReport.setText(stringMessages.loading());
|
||||
sailingServiceWrite.importWindFromIgtimi(new ArrayList<>(refreshableRaceSelectionModel.getSelectedSet()),
|
||||
correctByDeclination.getValue(), new AsyncCallback<Map<RegattaAndRaceIdentifier, Integer>>() {
|
||||
correctByDeclination.getValue(), optionalBearerTokenBox.getValue(), new AsyncCallback<Map<RegattaAndRaceIdentifier, Integer>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError(stringMessages.errorImportingIgtimiWind(caught.getMessage()));
|
||||
@@ -383,6 +384,11 @@ public class WindPanel extends FormPanel implements FilterablePanelProvider<Race
|
||||
}
|
||||
});
|
||||
contentPanel.add(correctByDeclination);
|
||||
final HorizontalPanel tokenPanel = new HorizontalPanel();
|
||||
tokenPanel.setSpacing(5);
|
||||
tokenPanel.add(new Label(stringMessages.optionalBearerTokenForWindImport()));
|
||||
tokenPanel.add(optionalBearerTokenBox);
|
||||
contentPanel.add(tokenPanel);
|
||||
contentPanel.add(importButton);
|
||||
contentPanel.add(resultReport);
|
||||
return igtimiWindImportRootPanel;
|
||||
|
||||
+1
-1
@@ -243,7 +243,7 @@ public interface SailingServiceWrite extends FileStorageManagementGwtService, Sa
|
||||
throws NotFoundException, NotDenotableForRaceLogTrackingException;
|
||||
|
||||
Map<RegattaAndRaceIdentifier, Integer> importWindFromIgtimi(List<RaceDTO> selectedRaces,
|
||||
boolean correctByDeclination)
|
||||
boolean correctByDeclination, String optionalBearerTokenOrNull)
|
||||
throws IllegalStateException, Exception;
|
||||
|
||||
IgtimiDataAccessWindowWithSecurityDTO addIgtimiDataAccessWindow(String deviceSerialNumber, Date from, Date to);
|
||||
|
||||
+1
-1
@@ -586,7 +586,7 @@ public interface SailingServiceWriteAsync extends FileStorageManagementGwtServic
|
||||
void removeIgtimiDevice(String deviceSerialNumber, AsyncCallback<Void> asyncCallback);
|
||||
|
||||
void importWindFromIgtimi(List<RaceDTO> selectedRaces, boolean correctByDeclination,
|
||||
AsyncCallback<Map<RegattaAndRaceIdentifier, Integer>> asyncCallback);
|
||||
String optionalBearerTokenOrNull, AsyncCallback<Map<RegattaAndRaceIdentifier, Integer>> asyncCallback);
|
||||
|
||||
/**
|
||||
* The boolean result reflects whether a connection to the device identified by {@code serialNumber}
|
||||
|
||||
+1
@@ -2563,4 +2563,5 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
|
||||
String selectToRaceColumn();
|
||||
String exportTWAHistogramToCsv();
|
||||
String exportWindSpeedHistogramToCsv();
|
||||
String optionalBearerTokenForWindImport();
|
||||
}
|
||||
+1
@@ -2601,3 +2601,4 @@ selectFromRaceColumn=Select race column from where to start copying pairings
|
||||
selectToRaceColumn=Select race colunm to where to copy pairings
|
||||
exportTWAHistogramToCsv=Export True Wind Angle histogram to CSV
|
||||
exportWindSpeedHistogramToCsv=Export Wind Speed histogram to CSV
|
||||
optionalBearerTokenForWindImport=Optional bearer token for wind import
|
||||
+1
@@ -2595,3 +2595,4 @@ selectFromRaceColumn=Spalte auswählen, ab der die Zuordnungen kopiert werden so
|
||||
selectToRaceColumn=Spalte auswählen, bis zu der die Zuordnungen kopiert werden sollen
|
||||
exportTWAHistogramToCsv=Histogramm der wahren Windwinkel in CSV exportieren
|
||||
exportWindSpeedHistogramToCsv=Histogramm der wahren Windgeschwindigkeiten in CSV exportieren
|
||||
optionalBearerTokenForWindImport=Optionales Bearer Token für Wind-Import
|
||||
+12
-2
@@ -6099,7 +6099,17 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
return Activator.getInstance().getGoogleMapsLoaderAuthenticationParams();
|
||||
}
|
||||
|
||||
protected IgtimiConnection createIgtimiConnection() {
|
||||
return getIgtimiConnectionFactory().getOrCreateConnection(()->getSecurityService().getCurrentUser() != null ? getSecurityService().getAccessToken(getSecurityService().getCurrentUser().getName()) : null);
|
||||
/**
|
||||
* @param optionalBearerToken
|
||||
* if present, this bearer token is used to authenticate the Igtimi connection; otherwise, we try to use
|
||||
* Igtimi default credentials provided at startup through the {@code igtimi.bearer.token} system
|
||||
* property. Only if no such system property has been set, we look for a logged-in user in the
|
||||
* {@link #getSecurityService() security service} and use its access token
|
||||
*/
|
||||
protected IgtimiConnection createIgtimiConnection(Optional<String> optionalBearerToken) {
|
||||
return optionalBearerToken.map(bearerToken->getIgtimiConnectionFactory().getOrCreateConnection(bearerToken))
|
||||
.orElse(getIgtimiConnectionFactory().getOrCreateConnection(()->getSecurityService().getCurrentUser() != null
|
||||
? getSecurityService().getAccessToken(getSecurityService().getCurrentUser().getName())
|
||||
: null));
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -2215,7 +2215,7 @@ public class SailingServiceWriteImpl extends SailingServiceImpl implements Saili
|
||||
|
||||
@Override
|
||||
public Map<RegattaAndRaceIdentifier, Integer> importWindFromIgtimi(List<RaceDTO> selectedRaces,
|
||||
boolean correctByDeclination)
|
||||
boolean correctByDeclination, String optionalBearerTokenOrNull)
|
||||
throws IllegalStateException, ClientProtocolException, IOException, org.json.simple.parser.ParseException {
|
||||
final List<DynamicTrackedRace> trackedRaces = new ArrayList<>();
|
||||
if (selectedRaces != null && !selectedRaces.isEmpty()) {
|
||||
@@ -2238,7 +2238,7 @@ public class SailingServiceWriteImpl extends SailingServiceImpl implements Saili
|
||||
}
|
||||
}
|
||||
Map<RegattaAndRaceIdentifier, Integer> numberOfWindFixesImportedPerRace = new HashMap<RegattaAndRaceIdentifier, Integer>();
|
||||
final IgtimiConnection conn = createIgtimiConnection();
|
||||
final IgtimiConnection conn = createIgtimiConnection(Optional.ofNullable(optionalBearerTokenOrNull));
|
||||
// filter account based on used permissions to read account:
|
||||
Map<TrackedRace, Integer> resultsForAccounts = conn.importWindIntoRace(trackedRaces, correctByDeclination);
|
||||
for (Entry<TrackedRace, Integer> resultForAccount : resultsForAccounts.entrySet()) {
|
||||
|
||||
Reference in new issue
Block a user