mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-28 00:16:46 +00:00
Merge remote-tracking branch 'origin/master'
Conflicts: java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties
This commit is contained in:
+1
@@ -65,6 +65,7 @@ public class RaceStartedAndFinishedReceiver extends AbstractReceiverWithQueue<Ra
|
||||
if (trackedRace.getStart() == null || !trackedRace.getStart().equals(start)) {
|
||||
trackedRace.setStartTimeReceived(start);
|
||||
}
|
||||
// TODO forward race stop time, event.getB().getStopTime()
|
||||
} else {
|
||||
logger.warning("Couldn't find tracked race for race " + event.getA().getName()
|
||||
+ ". Dropping start/stop event " + event);
|
||||
|
||||
+2
-2
@@ -555,8 +555,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
|
||||
|
||||
@Override
|
||||
public Wind getWind(Position p, TimePoint at, Iterable<WindSource> windSourcesToExclude) {
|
||||
final WindWithConfidence<Pair<Position, TimePoint>> windWithConfidence = getWindWithConfidence(p, at,
|
||||
windSourcesToExclude);
|
||||
final WindWithConfidence<Pair<Position, TimePoint>> windWithConfidence = getWindWithConfidence(p, at, windSourcesToExclude);
|
||||
return windWithConfidence == null ? null : windWithConfidence.getObject();
|
||||
}
|
||||
|
||||
@@ -576,6 +575,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
|
||||
.createWindAverager(timeWeigherThatPretendsToAlsoWeighPositions);
|
||||
List<WindWithConfidence<Pair<Position, TimePoint>>> windFixesWithConfidences = new ArrayList<WindWithConfidence<Pair<Position, TimePoint>>>();
|
||||
for (WindSource windSource : getWindSources()) {
|
||||
// TODO consider parallelizing
|
||||
if (!Util.contains(windSourcesToExclude, windSource)) {
|
||||
WindTrack track = getOrCreateWindTrack(windSource);
|
||||
WindWithConfidence<Pair<Position, TimePoint>> windWithConfidence = track.getAveragedWindWithConfidence(
|
||||
|
||||
+4
-4
@@ -35,11 +35,11 @@ interface AdminConsoleResources extends ClientBundle {
|
||||
@Source("com/sap/sailing/gwt/ui/client/images/reddot.png")
|
||||
ImageResource reddotIcon();
|
||||
|
||||
@Source("com/sap/sailing/gwt/ui/client/images/windarrow.png")
|
||||
ImageResource windDirectionIcon();
|
||||
@Source("com/sap/sailing/gwt/ui/client/images/wind_combined.png")
|
||||
ImageResource combinedWindIcon();
|
||||
|
||||
@Source("com/sap/sailing/gwt/ui/client/images/windsensor.png")
|
||||
ImageResource windSensorIcon();
|
||||
@Source("com/sap/sailing/gwt/ui/client/images/wind_expedition.png")
|
||||
ImageResource expeditionWindIcon();
|
||||
|
||||
@Source("com/sap/sailing/gwt/ui/client/images/boats/Blue_Port.png")
|
||||
ImageResource lowlightedBoatIcon_Port();
|
||||
|
||||
+1
-2
@@ -72,7 +72,6 @@ public class CombinedWindPanel extends FlowPanel implements TimeListener, RaceSe
|
||||
if (date != null) {
|
||||
if (selectedRaces != null && !selectedRaces.isEmpty()) {
|
||||
RaceIdentifier race = selectedRaces.get(selectedRaces.size() - 1);
|
||||
|
||||
if (race != null) {
|
||||
// draw the wind into the map, get the combined wind
|
||||
sailingService.getWindInfo(race, date, 1000L, 1, windSourceTypeNames,
|
||||
@@ -115,7 +114,7 @@ public class CombinedWindPanel extends FlowPanel implements TimeListener, RaceSe
|
||||
rotationDegOfWindSymbol = rotationDegOfWindSymbol - 360;
|
||||
String transformedImageURL = transformer.getTransformedImageURL(rotationDegOfWindSymbol, 1.0);
|
||||
windSymbolImage.setUrl(transformedImageURL);
|
||||
windSymbolImage.setTitle(Math.round(windFromDeg) + " " + stringMessages.degreesShort());
|
||||
windSymbolImage.setTitle(stringMessages.wind() + ": " + Math.round(windFromDeg) + " " + stringMessages.degreesShort());
|
||||
textLabel.setText(numberFormat.format(speedInKnots) + " " + stringMessages.averageSpeedInKnotsUnit());
|
||||
|
||||
if(!isVisible())
|
||||
|
||||
+25
-5
@@ -532,6 +532,14 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
|
||||
windSensorMarkers.put(windSource, windSensorMarker);
|
||||
map.addOverlay(windSensorMarker);
|
||||
} else {
|
||||
double windFromDeg = windDTO.dampenedTrueWindFromDeg;
|
||||
ImageTransformer transformer = imageResources.expeditionWindIconTransformer;
|
||||
|
||||
double rotationDegOfWindSymbol = 180.0 + windFromDeg;
|
||||
if(rotationDegOfWindSymbol >= 360.0)
|
||||
rotationDegOfWindSymbol = rotationDegOfWindSymbol - 360;
|
||||
String transformedImageURL = transformer.getTransformedImageURL(rotationDegOfWindSymbol, 1.0);
|
||||
windSensorMarker.setImage(transformedImageURL);
|
||||
windSensorMarker.setLatLng(LatLng.newInstance(windDTO.position.latDeg, windDTO.position.lngDeg));
|
||||
toRemoveWindSources.remove(windSource);
|
||||
}
|
||||
@@ -677,9 +685,19 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
|
||||
double latDeg = windDTO.position.latDeg;
|
||||
double lngDeg = windDTO.position.lngDeg;
|
||||
MarkerOptions options = MarkerOptions.newInstance();
|
||||
Icon icon = imageResources.windSensorIcon;
|
||||
|
||||
double windFromDeg = windDTO.dampenedTrueWindFromDeg;
|
||||
ImageTransformer transformer = imageResources.expeditionWindIconTransformer;
|
||||
|
||||
double rotationDegOfWindSymbol = 180.0 + windFromDeg;
|
||||
if(rotationDegOfWindSymbol >= 360.0)
|
||||
rotationDegOfWindSymbol = rotationDegOfWindSymbol - 360;
|
||||
String transformedImageURL = transformer.getTransformedImageURL(rotationDegOfWindSymbol, 1.0);
|
||||
|
||||
Icon icon = Icon.newInstance(transformedImageURL);
|
||||
icon.setIconAnchor(Point.newInstance(7, 13));
|
||||
options.setIcon(icon);
|
||||
options.setTitle("Expedition wind sensor");
|
||||
options.setTitle(stringMessages.wind() + ": " + Math.round(windFromDeg) + " " + stringMessages.degreesShort());
|
||||
final Marker windSensorMarker = new Marker(LatLng.newInstance(latDeg, lngDeg), options);
|
||||
windSensorMarker.addMarkerClickHandler(new MarkerClickHandler() {
|
||||
@Override
|
||||
@@ -713,7 +731,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
|
||||
|
||||
private String formatPosition(double lat, double lng) {
|
||||
NumberFormat numberFormat = NumberFormat.getFormat("0.0");
|
||||
String result = "Position: " + numberFormat.format(lat) + " lat, " + numberFormat.format(lng) + " lng";
|
||||
String result = stringMessages.position() + ": " + numberFormat.format(lat) + " lat, " + numberFormat.format(lng) + " lng";
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -730,9 +748,11 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
|
||||
}
|
||||
|
||||
private Widget getInfoWindowContent(WindDTO windDTO) {
|
||||
NumberFormat numberFormat = NumberFormat.getFormat("0.0");
|
||||
VerticalPanel result = new VerticalPanel();
|
||||
NumberFormat numberFormat = NumberFormat.getFormat("0.000");
|
||||
result.add(new Label("Wind: " + numberFormat.format(windDTO.dampenedTrueWindFromDeg) + " deg"));
|
||||
result.add(new Label(stringMessages.windSource() + ": " + "Expedition"));
|
||||
result.add(new Label(stringMessages.wind() + ": " + Math.round(windDTO.dampenedTrueWindFromDeg) + " " + stringMessages.degreesShort()));
|
||||
result.add(new Label(stringMessages.windSpeed() + ": " + numberFormat.format(windDTO.dampenedTrueWindSpeedInKnots)));
|
||||
result.add(new Label(formatPosition(windDTO.position.latDeg, windDTO.position.lngDeg)));
|
||||
return result;
|
||||
}
|
||||
|
||||
+8
-7
@@ -61,10 +61,13 @@ public class RaceMapResources {
|
||||
* An arrow showing the combined wind depending on the wind direction
|
||||
*/
|
||||
protected ImageTransformer combinedWindIconTransformer;
|
||||
|
||||
protected Icon buoyIcon;
|
||||
|
||||
protected Icon windSensorIcon;
|
||||
/**
|
||||
* An arrow showing the wind provided by a wind sensor on a boat
|
||||
*/
|
||||
protected ImageTransformer expeditionWindIconTransformer;
|
||||
|
||||
protected Icon buoyIcon;
|
||||
|
||||
protected Map<Pair<ManeuverType, Tack>, Icon> maneuverIconsForTypeAndTargetTack;
|
||||
|
||||
@@ -83,7 +86,8 @@ public class RaceMapResources {
|
||||
boatIconHighlightedPortTransformer = new ImageTransformer(resources.highlightedBoatIcon_Port());
|
||||
boatIconStarboardTransformer = new ImageTransformer(resources.lowlightedBoatIcon_Starboard());
|
||||
boatIconHighlightedStarboardTransformer = new ImageTransformer(resources.highlightedBoatIcon_Starboard());
|
||||
combinedWindIconTransformer = new ImageTransformer(resources.windDirectionIcon());
|
||||
combinedWindIconTransformer = new ImageTransformer(resources.combinedWindIcon());
|
||||
expeditionWindIconTransformer = new ImageTransformer(resources.expeditionWindIcon());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,9 +99,6 @@ public class RaceMapResources {
|
||||
buoyIcon = Icon.newInstance(resources.buoyIcon().getSafeUri().asString());
|
||||
buoyIcon.setIconAnchor(Point.newInstance(4, 4));
|
||||
|
||||
windSensorIcon = Icon.newInstance(resources.windSensorIcon().getSafeUri().asString());
|
||||
buoyIcon.setIconAnchor(Point.newInstance(0, 0));
|
||||
|
||||
Icon tackToStarboardIcon = Icon
|
||||
.newInstance("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=T|00FF00|000000");
|
||||
tackToStarboardIcon.setIconAnchor(Point.newInstance(10, 33));
|
||||
|
||||
-1
@@ -162,7 +162,6 @@ public class RaceMapSettingsDialogComponent implements SettingsDialogComponent<R
|
||||
if (valueToValidate.getTailLengthInMilliseconds() < 0) {
|
||||
errorMessage = stringMessages.tailLengthMustBeNonNegative();
|
||||
}
|
||||
|
||||
return errorMessage;
|
||||
}
|
||||
};
|
||||
|
||||
+54
-31
@@ -12,6 +12,7 @@ import org.moxieapps.gwt.highcharts.client.Axis;
|
||||
import org.moxieapps.gwt.highcharts.client.Chart;
|
||||
import org.moxieapps.gwt.highcharts.client.ChartSubtitle;
|
||||
import org.moxieapps.gwt.highcharts.client.ChartTitle;
|
||||
import org.moxieapps.gwt.highcharts.client.Color;
|
||||
import org.moxieapps.gwt.highcharts.client.Extremes;
|
||||
import org.moxieapps.gwt.highcharts.client.Legend;
|
||||
import org.moxieapps.gwt.highcharts.client.PlotLine;
|
||||
@@ -44,8 +45,8 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.client.TimeListener;
|
||||
import com.sap.sailing.gwt.ui.client.Timer;
|
||||
import com.sap.sailing.gwt.ui.client.WindSourceTypeFormatter;
|
||||
import com.sap.sailing.gwt.ui.client.Timer.PlayModes;
|
||||
import com.sap.sailing.gwt.ui.client.WindSourceTypeFormatter;
|
||||
import com.sap.sailing.gwt.ui.shared.WindDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.WindTrackInfoDTO;
|
||||
@@ -53,9 +54,12 @@ import com.sap.sailing.gwt.ui.shared.components.Component;
|
||||
import com.sap.sailing.gwt.ui.shared.components.SettingsDialogComponent;
|
||||
|
||||
public class WindChart extends SimplePanel implements Component<WindChartSettings>, RaceSelectionChangeListener, TimeListener, RequiresResize {
|
||||
public static final long DEFAULT_RESOLUTION_IN_MILLISECONDS = 5000;
|
||||
|
||||
private static final int LINE_WIDTH = 1;
|
||||
private final StringMessages stringMessages;
|
||||
private final Set<WindSourceType> windSourceTypesToDisplay;
|
||||
private long resolutionInMilliseconds;
|
||||
|
||||
/**
|
||||
* Holds one series for each wind source for which data has been received.
|
||||
@@ -132,6 +136,8 @@ public class WindChart extends SimplePanel implements Component<WindChartSetting
|
||||
}
|
||||
}));
|
||||
|
||||
chart.setBackgroundColor(new Color("#ebebec"));
|
||||
|
||||
if (allowTimeAdjust) {
|
||||
chart.setClickEventHandler(new ChartClickEventHandler() {
|
||||
@Override
|
||||
@@ -345,7 +351,7 @@ public class WindChart extends SimplePanel implements Component<WindChartSetting
|
||||
|
||||
@Override
|
||||
public SettingsDialogComponent<WindChartSettings> getSettingsDialogComponent() {
|
||||
return new WindChartSettingsDialogComponent(new WindChartSettings(windSourceTypesToDisplay), stringMessages);
|
||||
return new WindChartSettingsDialogComponent(new WindChartSettings(windSourceTypesToDisplay, resolutionInMilliseconds), stringMessages);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,6 +360,10 @@ public class WindChart extends SimplePanel implements Component<WindChartSetting
|
||||
*/
|
||||
@Override
|
||||
public void updateSettings(WindChartSettings newSettings) {
|
||||
if (newSettings.getResolutionInMilliseconds() != resolutionInMilliseconds) {
|
||||
resolutionInMilliseconds = newSettings.getResolutionInMilliseconds();
|
||||
clearCacheAndReload();
|
||||
}
|
||||
windSourceTypesToDisplay.clear();
|
||||
windSourceTypesToDisplay.addAll(newSettings.getWindSourceTypesToDisplay());
|
||||
chart.removeAllSeries(/* redraw */ false);
|
||||
@@ -368,6 +378,13 @@ public class WindChart extends SimplePanel implements Component<WindChartSetting
|
||||
chart.redraw();
|
||||
}
|
||||
|
||||
private void clearCacheAndReload() {
|
||||
timeOfEarliestRequestInMillis = null;
|
||||
timeOfLatestRequestInMillis = null;
|
||||
loadData(selectedRaceIdentifier, /* from */null, /* to */
|
||||
new Date(System.currentTimeMillis() - timer.getLivePlayDelayInMillis()), /* append */false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the series for the <code>windSource</code> specified. If the series is created and needs to be visible
|
||||
* based on the {@link #windSourceTypesToDisplay}, it is added to the chart.
|
||||
@@ -390,28 +407,33 @@ public class WindChart extends SimplePanel implements Component<WindChartSetting
|
||||
* of overwriting the existing series.
|
||||
*/
|
||||
private void loadData(final RaceIdentifier raceIdentifier, final Date from, final Date to, final boolean append) {
|
||||
sailingService.getWindInfo(raceIdentifier,
|
||||
// TODO Time interval should be determined by a selection in the chart but be at most 60s. See bug #121. Consider incremental updates for new data only.
|
||||
from, to, // use race start and time of newest event as default time period
|
||||
null, // retrieve data on all wind sources
|
||||
new AsyncCallback<WindInfoForRaceDTO>() {
|
||||
@Override
|
||||
public void onSuccess(WindInfoForRaceDTO result) {
|
||||
if (result != null) {
|
||||
updateStripChartSeries(result, append);
|
||||
} else {
|
||||
if (!append) {
|
||||
clearChart(); // no wind known for untracked race
|
||||
if (raceIdentifier == null) {
|
||||
clearChart();
|
||||
} else {
|
||||
sailingService.getWindInfo(raceIdentifier,
|
||||
// TODO Time interval should be determined by a selection in the chart but be at most 60s. See bug #121.
|
||||
// Consider incremental updates for new data only.
|
||||
from, to, resolutionInMilliseconds, // use race start and time of newest event as default time period
|
||||
null, // retrieve data on all wind sources
|
||||
new AsyncCallback<WindInfoForRaceDTO>() {
|
||||
@Override
|
||||
public void onSuccess(WindInfoForRaceDTO result) {
|
||||
if (result != null) {
|
||||
updateStripChartSeries(result, append);
|
||||
} else {
|
||||
if (!append) {
|
||||
clearChart(); // no wind known for untracked race
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError(stringMessages.errorFetchingWindInformationForRace()+" " + raceIdentifier + ": "
|
||||
+ caught.getMessage());
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError(stringMessages.errorFetchingWindInformationForRace() + " "
|
||||
+ raceIdentifier + ": " + caught.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void clearChart() {
|
||||
@@ -423,10 +445,7 @@ public class WindChart extends SimplePanel implements Component<WindChartSetting
|
||||
if (selectedRaces != null && !selectedRaces.isEmpty()) {
|
||||
// show wind of first selected race
|
||||
selectedRaceIdentifier = selectedRaces.iterator().next();
|
||||
timeOfEarliestRequestInMillis = null;
|
||||
timeOfLatestRequestInMillis = null;
|
||||
loadData(selectedRaceIdentifier, /* from */null, /* to */
|
||||
new Date(System.currentTimeMillis() - timer.getLivePlayDelayInMillis()), /* append */false);
|
||||
clearCacheAndReload();
|
||||
} else {
|
||||
clearChart();
|
||||
}
|
||||
@@ -473,12 +492,16 @@ public class WindChart extends SimplePanel implements Component<WindChartSetting
|
||||
private void updateTimeLine(Date date) {
|
||||
if (allowTimeAdjust) {
|
||||
Long x = date.getTime();
|
||||
Extremes extremes = chart.getYAxis(0).getExtremes();
|
||||
Point[] points = new Point[2];
|
||||
points[0] = new Point(x, extremes.getDataMin());
|
||||
points[1] = new Point(x, extremes.getDataMax());
|
||||
timeLineSeries.setPoints(points);
|
||||
ensureTimeLineIsVisible();
|
||||
try {
|
||||
Extremes extremes = chart.getYAxis(0).getExtremes();
|
||||
Point[] points = new Point[2];
|
||||
points[0] = new Point(x, extremes.getDataMin());
|
||||
points[1] = new Point(x, extremes.getDataMax());
|
||||
timeLineSeries.setPoints(points);
|
||||
ensureTimeLineIsVisible();
|
||||
} catch (NullPointerException e) {
|
||||
// explicitly do nothing; it means that getExtremes() has thrown an exception, so we don't know how to set them
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
-2
@@ -9,16 +9,32 @@ import com.sap.sailing.domain.common.WindSourceType;
|
||||
|
||||
public class WindChartSettings {
|
||||
private final Set<WindSourceType> windSourceTypesToDisplay;
|
||||
|
||||
private final long resolutionInMilliseconds;
|
||||
|
||||
public WindChartSettings(Set<WindSourceType> windSourceTypesToDisplay) {
|
||||
public WindChartSettings(Set<WindSourceType> windSourceTypesToDisplay, long resolutionInMilliseconds) {
|
||||
this.windSourceTypesToDisplay = windSourceTypesToDisplay;
|
||||
this.resolutionInMilliseconds = resolutionInMilliseconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses {@link WindChart#DEFAULT_RESOLUTION_IN_MILLISECONDS} as resolution
|
||||
*/
|
||||
public WindChartSettings(WindSourceType... windSourceTypesToDisplay) {
|
||||
this(new HashSet<WindSourceType>(windSourceTypesToDisplay==null?new ArrayList<WindSourceType>():Arrays.asList(windSourceTypesToDisplay)));
|
||||
this(WindChart.DEFAULT_RESOLUTION_IN_MILLISECONDS, windSourceTypesToDisplay);
|
||||
}
|
||||
|
||||
public WindChartSettings(long resolutionInMilliseconds, WindSourceType... windSourceTypesToDisplay) {
|
||||
this(new HashSet<WindSourceType>(windSourceTypesToDisplay == null ? new ArrayList<WindSourceType>()
|
||||
: Arrays.asList(windSourceTypesToDisplay)), resolutionInMilliseconds);
|
||||
}
|
||||
|
||||
public Set<WindSourceType> getWindSourceTypesToDisplay() {
|
||||
return windSourceTypesToDisplay;
|
||||
}
|
||||
|
||||
public long getResolutionInMilliseconds() {
|
||||
return resolutionInMilliseconds;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+22
-5
@@ -7,17 +7,21 @@ import java.util.Set;
|
||||
|
||||
import com.google.gwt.user.client.ui.CheckBox;
|
||||
import com.google.gwt.user.client.ui.FocusWidget;
|
||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.google.gwt.user.client.ui.IntegerBox;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.gwt.ui.client.DataEntryDialog;
|
||||
import com.sap.sailing.gwt.ui.client.DataEntryDialog.Validator;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.client.WindSourceTypeFormatter;
|
||||
import com.sap.sailing.gwt.ui.client.DataEntryDialog.Validator;
|
||||
import com.sap.sailing.gwt.ui.shared.components.SettingsDialogComponent;
|
||||
|
||||
public class WindChartSettingsDialogComponent implements SettingsDialogComponent<WindChartSettings> {
|
||||
private final WindChartSettings initialSettings;
|
||||
private IntegerBox resolutionInSecondsBox;
|
||||
private final Map<WindSourceType, CheckBox> checkboxes;
|
||||
private final StringMessages stringMessages;
|
||||
|
||||
@@ -31,6 +35,11 @@ public class WindChartSettingsDialogComponent implements SettingsDialogComponent
|
||||
@Override
|
||||
public Widget getAdditionalWidget(DataEntryDialog<?> dialog) {
|
||||
VerticalPanel vp = new VerticalPanel();
|
||||
resolutionInSecondsBox = dialog.createIntegerBox((int) (initialSettings.getResolutionInMilliseconds()/1000), /* visibleLength */ 5);
|
||||
HorizontalPanel hp = new HorizontalPanel();
|
||||
hp.add(new Label(stringMessages.stepSizeInSeconds()));
|
||||
hp.add(resolutionInSecondsBox);
|
||||
vp.add(hp);
|
||||
for (WindSourceType windSourceType : WindSourceType.values()) {
|
||||
CheckBox checkbox = dialog.createCheckbox(WindSourceTypeFormatter.format(windSourceType, stringMessages));
|
||||
checkboxes.put(windSourceType, checkbox);
|
||||
@@ -48,18 +57,26 @@ public class WindChartSettingsDialogComponent implements SettingsDialogComponent
|
||||
windSourceTypesToDisplay.add(e.getKey());
|
||||
}
|
||||
}
|
||||
return new WindChartSettings(windSourceTypesToDisplay);
|
||||
return new WindChartSettings(windSourceTypesToDisplay, resolutionInSecondsBox.getValue() == null ? -1 : resolutionInSecondsBox.getValue()*1000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Validator<WindChartSettings> getValidator() {
|
||||
// with checkboxes only, nothing can go wrong :-)
|
||||
return null;
|
||||
return new Validator<WindChartSettings>() {
|
||||
@Override
|
||||
public String getErrorMessage(WindChartSettings valueToValidate) {
|
||||
String errorMessage = null;
|
||||
if (valueToValidate.getResolutionInMilliseconds() < 1) {
|
||||
errorMessage = stringMessages.stepSizeMustBeGreaterThanNull();
|
||||
}
|
||||
return errorMessage;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public FocusWidget getFocusWidget() {
|
||||
return checkboxes.values().iterator().next();
|
||||
return resolutionInSecondsBox;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -179,8 +179,8 @@ public class WindPanel extends FormPanel implements EventDisplayer, WindShower,
|
||||
});
|
||||
windSourceSelectionPanel.add(showConfigAnchor);
|
||||
grid.setWidget(1, 0, windSourceSelectionPanel);
|
||||
windChart = new WindChart(sailingService, /* race selection provider */ raceSelectionProvider,
|
||||
new Timer(PlayModes.Replay), new WindChartSettings(WindSourceType.values()), stringMessages, errorReporter, false, false);
|
||||
windChart = new WindChart(sailingService, /* race selection provider */raceSelectionProvider, new Timer(
|
||||
PlayModes.Replay), new WindChartSettings(WindSourceType.values()), stringMessages, errorReporter, false, false);
|
||||
grid.setWidget(2, 0, windChart.getEntryWidget());
|
||||
grid.getCellFormatter().setVerticalAlignment(1, 1, HasVerticalAlignment.ALIGN_TOP);
|
||||
this.setWidget(grid);
|
||||
|
||||
+6
-3
@@ -58,6 +58,12 @@ public interface SailingService extends RemoteService {
|
||||
|
||||
void setWind(RaceIdentifier raceIdentifier, WindDTO wind);
|
||||
|
||||
WindInfoForRaceDTO getWindInfo(RaceIdentifier raceIdentifier, Date from, long millisecondsStepWidth,
|
||||
int numberOfFixes, Collection<String> windSourceTypeNames) throws NoWindException;
|
||||
|
||||
WindInfoForRaceDTO getWindInfo(RaceIdentifier raceIdentifier, Date from, Date to, long resolutionInMilliseconds,
|
||||
Collection<String> windSourceTypeNames);
|
||||
|
||||
Map<CompetitorDTO, List<GPSFixDTO>> getBoatPositions(RaceIdentifier raceIdentifier, Map<CompetitorDTO, Date> from,
|
||||
Map<CompetitorDTO, Date> to, boolean extrapolate) throws NoWindException;
|
||||
|
||||
@@ -164,7 +170,4 @@ public interface SailingService extends RemoteService {
|
||||
throws NoWindException;
|
||||
|
||||
void setRaceIsKnownToStartUpwind(RaceIdentifier raceIdentifier, boolean raceIsKnownToStartUpwind);
|
||||
|
||||
WindInfoForRaceDTO getWindInfo(RaceIdentifier raceIdentifier, Date from, long millisecondsStepWidth,
|
||||
int numberOfFixes, Collection<String> windSourceTypeNames) throws NoWindException;
|
||||
}
|
||||
|
||||
+23
-11
@@ -69,12 +69,16 @@ public interface SailingServiceAsync {
|
||||
*/
|
||||
void removeAndUntrackRace(EventAndRaceIdentifier eventAndRaceidentifier, AsyncCallback<Void> callback);
|
||||
|
||||
/**
|
||||
* @param windSources if <code>null</code>, information about all available wind sources will be provided
|
||||
*/
|
||||
void getWindInfo(RaceIdentifier raceIdentifier, Date from, Date to, WindSource[] windSources,
|
||||
AsyncCallback<WindInfoForRaceDTO> callback);
|
||||
|
||||
/**
|
||||
* @param from if <code>null</code>, the tracked race's start of tracking is used
|
||||
* @param to if <code>null</code>, the tracked race's time point of newest event is used
|
||||
*/
|
||||
void getWindInfo(RaceIdentifier raceIdentifier, Date from, Date to, long resolutionInMilliseconds,
|
||||
Collection<String> windSourceTypeNames, AsyncCallback<WindInfoForRaceDTO> callback);
|
||||
|
||||
/**
|
||||
* @param windSourceTypeNames
|
||||
* if <code>null</code>, data from all available wind sources will be returned, otherwise only from those
|
||||
@@ -84,6 +88,22 @@ public interface SailingServiceAsync {
|
||||
double latDeg, double lngDeg, Collection<String> windSourceTypeNames,
|
||||
AsyncCallback<WindInfoForRaceDTO> callback);
|
||||
|
||||
/**
|
||||
* Same as {@link #getWindInfo(RaceIdentifier, Date, long, int, double, double, Collection, AsyncCallback)}, only
|
||||
* that the wind is not requested for a specific position, but instead the wind sources associated with the tracked
|
||||
* race identified by <code>raceIdentifier</code> are requested to deliver their original position. This will in
|
||||
* particular preserve the positions of actual measurements and will deliver the averaged positions for averaged /
|
||||
* combined wind read-outs.
|
||||
*
|
||||
* @param from
|
||||
* must not be <code>null</code>
|
||||
* @param numberOfFixes
|
||||
* no matter how great this value is chosen, never returns data beyond the newest event recorded in the
|
||||
* race
|
||||
*/
|
||||
void getWindInfo(RaceIdentifier raceIdentifier, Date from, long millisecondsStepWidth, int numberOfFixes,
|
||||
Collection<String> windSourceTypeNames, AsyncCallback<WindInfoForRaceDTO> callback);
|
||||
|
||||
void setWind(RaceIdentifier raceIdentifier, WindDTO wind, AsyncCallback<Void> callback);
|
||||
|
||||
void removeWind(RaceIdentifier raceIdentifier, WindDTO windDTO, AsyncCallback<Void> callback);
|
||||
@@ -286,12 +306,4 @@ public interface SailingServiceAsync {
|
||||
void setRaceIsKnownToStartUpwind(RaceIdentifier raceIdentifier, boolean raceIsKnownToStartUpwind,
|
||||
AsyncCallback<Void> callback);
|
||||
|
||||
/**
|
||||
* Same as {@link #getWindInfo(RaceIdentifier, Date, long, int, double, double, Collection, AsyncCallback)}, only that the
|
||||
* wind is not requested for a specific position, but instead the wind sources associated with the tracked race identified
|
||||
* by <code>raceIdentifier</code> are requested to deliver their original position. This will in particular preserve the
|
||||
* positions of actual measurements and will deliver the averaged positions for averaged / combined wind read-outs.
|
||||
*/
|
||||
void getWindInfo(RaceIdentifier raceIdentifier, Date from, long millisecondsStepWidth, int numberOfFixes,
|
||||
Collection<String> windSourceTypeNames, AsyncCallback<WindInfoForRaceDTO> callback);
|
||||
}
|
||||
|
||||
+1
@@ -272,4 +272,5 @@ public interface StringMessages extends Messages {
|
||||
String expeditionWindSourceTypeName();
|
||||
String webWindSourceTypeName();
|
||||
String clickChartToSetTime();
|
||||
String position();
|
||||
}
|
||||
+2
-1
@@ -266,4 +266,5 @@ courseBasedWindSourceTypeName=Course Layout
|
||||
trackBasedEstimationWindSourceTypeName=Estimation
|
||||
expeditionWindSourceTypeName=Measured
|
||||
webWindSourceTypeName=Manual
|
||||
clickChartToSetTime=Click on the chart to set the time
|
||||
clickChartToSetTime=Click on the chart to set the time
|
||||
position=Position
|
||||
+2
-1
@@ -267,4 +267,5 @@ courseBasedWindSourceTypeName=Kurslayout
|
||||
trackBasedEstimationWindSourceTypeName=Schätzung
|
||||
expeditionWindSourceTypeName=Messung
|
||||
webWindSourceTypeName=Manuell
|
||||
clickChartToSetTime=Klicke auf das Diagramm um die Zeit zu setzen
|
||||
clickChartToSetTime=Klicke auf das Diagramm um die Zeit zu setzen
|
||||
position=Position
|
||||
+66
-7
@@ -599,6 +599,33 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
return windDTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses <code>wind</code> for both, the non-dampened and dampened fields of the {@link WindDTO} object returned
|
||||
*/
|
||||
protected WindDTO createWindDTOFromAlreadyAveraged(Wind wind, WindTrack windTrack) {
|
||||
WindDTO windDTO = new WindDTO();
|
||||
windDTO.trueWindBearingDeg = wind.getBearing().getDegrees();
|
||||
windDTO.trueWindFromDeg = wind.getBearing().reverse().getDegrees();
|
||||
windDTO.trueWindSpeedInKnots = wind.getKnots();
|
||||
windDTO.trueWindSpeedInMetersPerSecond = wind.getMetersPerSecond();
|
||||
windDTO.dampenedTrueWindBearingDeg = wind.getBearing().getDegrees();
|
||||
windDTO.dampenedTrueWindFromDeg = wind.getBearing().reverse().getDegrees();
|
||||
windDTO.dampenedTrueWindSpeedInKnots = wind.getKnots();
|
||||
windDTO.dampenedTrueWindSpeedInMetersPerSecond = wind.getMetersPerSecond();
|
||||
if (wind.getPosition() != null) {
|
||||
windDTO.position = new PositionDTO(wind.getPosition().getLatDeg(), wind.getPosition()
|
||||
.getLngDeg());
|
||||
}
|
||||
if (wind.getTimePoint() != null) {
|
||||
windDTO.timepoint = wind.getTimePoint().asMillis();
|
||||
}
|
||||
return windDTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the {@link WindTrack#getAveragedWind(Position, TimePoint) average wind} from all wind tracks or those identified
|
||||
* by <code>windSourceTypeNames</code>
|
||||
*/
|
||||
@Override
|
||||
public WindInfoForRaceDTO getWindInfo(RaceIdentifier raceIdentifier, Date from, long millisecondsStepWidth,
|
||||
int numberOfFixes, double latDeg, double lngDeg, Collection<String> windSourceTypeNames)
|
||||
@@ -628,7 +655,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
for (int i = 0; i < numberOfFixes; i++) {
|
||||
Wind wind = windTrack.getAveragedWind(position, timePoint);
|
||||
if (wind != null) {
|
||||
WindDTO windDTO = createWindDTO(wind, windTrack);
|
||||
WindDTO windDTO = createWindDTOFromAlreadyAveraged(wind, windTrack);
|
||||
windTrackInfoDTO.windFixes.add(windDTO);
|
||||
}
|
||||
timePoint = new MillisecondsTimePoint(timePoint.asMillis() + millisecondsStepWidth);
|
||||
@@ -643,31 +670,39 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
public WindInfoForRaceDTO getWindInfo(RaceIdentifier raceIdentifier, Date from, long millisecondsStepWidth,
|
||||
int numberOfFixes, Collection<String> windSourceTypeNames)
|
||||
throws NoWindException {
|
||||
WindInfoForRaceDTO result = null;
|
||||
assert from != null;
|
||||
TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier);
|
||||
WindInfoForRaceDTO result = getWindInfo(new MillisecondsTimePoint(from), millisecondsStepWidth, numberOfFixes,
|
||||
windSourceTypeNames, trackedRace);
|
||||
return result;
|
||||
}
|
||||
|
||||
private WindInfoForRaceDTO getWindInfo(TimePoint from, long millisecondsStepWidth, int numberOfFixes,
|
||||
Collection<String> windSourceTypeNames, TrackedRace trackedRace) {
|
||||
WindInfoForRaceDTO result = null;
|
||||
if (trackedRace != null) {
|
||||
TimePoint newestEvent = trackedRace.getTimePointOfNewestEvent();
|
||||
result = new WindInfoForRaceDTO();
|
||||
result.raceIsKnownToStartUpwind = trackedRace.raceIsKnownToStartUpwind();
|
||||
Map<WindSource, WindTrackInfoDTO> windTrackInfoDTOs = new HashMap<WindSource, WindTrackInfoDTO>();
|
||||
result.windTrackInfoByWindSource = windTrackInfoDTOs;
|
||||
List<WindSource> windSourcesToDeliver = new ArrayList<WindSource>();
|
||||
Util.addAll(trackedRace.getWindSources(), windSourcesToDeliver);
|
||||
// TODO bug #375: add the combined wind; currently, CombinedWindTrackImpl just takes too long to return results...
|
||||
windSourcesToDeliver.add(new WindSourceImpl(WindSourceType.COMBINED));
|
||||
for (WindSource windSource : windSourcesToDeliver) {
|
||||
// TODO consider parallelizing
|
||||
if (windSourceTypeNames == null || windSourceTypeNames.contains(windSource.getType().name())) {
|
||||
TimePoint fromTimePoint = new MillisecondsTimePoint(from);
|
||||
WindTrackInfoDTO windTrackInfoDTO = new WindTrackInfoDTO();
|
||||
windTrackInfoDTO.windFixes = new ArrayList<WindDTO>();
|
||||
WindTrack windTrack = trackedRace.getOrCreateWindTrack(windSource);
|
||||
windTrackInfoDTOs.put(windSource, windTrackInfoDTO);
|
||||
windTrackInfoDTO.dampeningIntervalInMilliseconds = windTrack
|
||||
.getMillisecondsOverWhichToAverageWind();
|
||||
TimePoint timePoint = fromTimePoint;
|
||||
for (int i = 0; i < numberOfFixes; i++) {
|
||||
TimePoint timePoint = from;
|
||||
for (int i = 0; i < numberOfFixes && timePoint.compareTo(newestEvent) < 0; i++) {
|
||||
Wind wind = windTrack.getAveragedWind(null, timePoint);
|
||||
if (wind != null) {
|
||||
WindDTO windDTO = createWindDTO(wind, windTrack);
|
||||
WindDTO windDTO = createWindDTOFromAlreadyAveraged(wind, windTrack);
|
||||
windTrackInfoDTO.windFixes.add(windDTO);
|
||||
}
|
||||
timePoint = new MillisecondsTimePoint(timePoint.asMillis() + millisecondsStepWidth);
|
||||
@@ -678,6 +713,30 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindInfoForRaceDTO getWindInfo(RaceIdentifier raceIdentifier, Date from, Date to,
|
||||
long resolutionInMilliseconds, Collection<String> windSourceTypeNames) {
|
||||
TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier);
|
||||
WindInfoForRaceDTO result = null;
|
||||
if (trackedRace != null) {
|
||||
TimePoint fromTimePoint;
|
||||
if (from == null) {
|
||||
fromTimePoint = trackedRace.getStartOfTracking();
|
||||
} else {
|
||||
fromTimePoint = new MillisecondsTimePoint(from);
|
||||
}
|
||||
TimePoint toTimePoint;
|
||||
if (to == null || to.getTime() > trackedRace.getTimePointOfNewestEvent().asMillis()) {
|
||||
toTimePoint = trackedRace.getTimePointOfNewestEvent();
|
||||
} else {
|
||||
toTimePoint = new MillisecondsTimePoint(to);
|
||||
}
|
||||
int numberOfFixes = (int) ((toTimePoint.asMillis() - fromTimePoint.asMillis())/resolutionInMilliseconds);
|
||||
result = getWindInfo(fromTimePoint, resolutionInMilliseconds, numberOfFixes, windSourceTypeNames, trackedRace);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWind(RaceIdentifier raceIdentifier, WindDTO windDTO) {
|
||||
DynamicTrackedRace trackedRace = (DynamicTrackedRace) getExistingTrackedRace(raceIdentifier);
|
||||
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 649 B |
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 830 B |
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 569 B |
Reference in New Issue
Block a user