mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-09 13:50:57 +00:00
Added a more dynamic way of wind-stepping for polar sheets
This commit is contained in:
1 parent
ff3609e695
commit
b3331c1c27
11 files changed
+91
-28
No files matched your search
+2
@@ -12,4 +12,6 @@ public interface PolarSheetsData extends Serializable {
|
||||
|
||||
Integer[] getDataCountPerAngleForWindspeed(int beaufort);
|
||||
|
||||
Integer[] getStepping();
|
||||
|
||||
}
|
||||
+9
-1
@@ -13,17 +13,20 @@ public class PolarSheetsDataImpl implements PolarSheetsData {
|
||||
private boolean complete;
|
||||
|
||||
private int dataCount;
|
||||
|
||||
private Integer[] stepping;
|
||||
|
||||
private Map<Integer,Integer[]> dataCountPerAngleForWindspeed;
|
||||
|
||||
//For GWT Serialization
|
||||
PolarSheetsDataImpl() {};
|
||||
|
||||
public PolarSheetsDataImpl(Number[][] averagedPolarDataByWindSpeed, boolean complete, int dataCount, Map<Integer,Integer[]> dataCountPerAngleForWindspeed) {
|
||||
public PolarSheetsDataImpl(Number[][] averagedPolarDataByWindSpeed, boolean complete, int dataCount, Map<Integer,Integer[]> dataCountPerAngleForWindspeed, Integer[] stepping) {
|
||||
this.averagedPolarDataByWindSpeed = averagedPolarDataByWindSpeed;
|
||||
this.complete = complete;
|
||||
this.dataCount = dataCount;
|
||||
this.dataCountPerAngleForWindspeed = dataCountPerAngleForWindspeed;
|
||||
this.stepping = stepping;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -46,5 +49,10 @@ public class PolarSheetsDataImpl implements PolarSheetsData {
|
||||
public Integer[] getDataCountPerAngleForWindspeed(int beaufort) {
|
||||
return dataCountPerAngleForWindspeed.get(beaufort);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer[] getStepping() {
|
||||
return stepping;
|
||||
}
|
||||
|
||||
}
|
||||
+3
-3
@@ -72,9 +72,9 @@ public class PolarSheetGenerationTest {
|
||||
|
||||
PolarSheetsData data = resultContainer.getPolarData();
|
||||
Assert.assertEquals(4, data.getDataCount());
|
||||
Assert.assertEquals(4.0, data.getAveragedPolarDataByWindSpeed()[1][45]);
|
||||
Assert.assertEquals(2.0, data.getAveragedPolarDataByWindSpeed()[1][55]);
|
||||
Assert.assertEquals(6.0, data.getAveragedPolarDataByWindSpeed()[1][30]);
|
||||
Assert.assertEquals(4.0, data.getAveragedPolarDataByWindSpeed()[0][45]);
|
||||
Assert.assertEquals(2.0, data.getAveragedPolarDataByWindSpeed()[0][55]);
|
||||
Assert.assertEquals(6.0, data.getAveragedPolarDataByWindSpeed()[0][30]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+21
-12
@@ -32,6 +32,8 @@ public class PolarSheetGenerationWorker {
|
||||
|
||||
private final Executor executor;
|
||||
|
||||
private PolarSheetsWindStepping stepping;
|
||||
|
||||
/**
|
||||
* Will prepare the {@link PerRaceAndCompetitorPolarSheetGenerationWorker}s per race & per competitor. This includes
|
||||
* determining start and end time.
|
||||
@@ -42,6 +44,8 @@ public class PolarSheetGenerationWorker {
|
||||
* executes the tasks upon {@link #startPolarSheetGeneration()}
|
||||
*/
|
||||
public PolarSheetGenerationWorker(Set<TrackedRace> trackedRaces, Executor executor) {
|
||||
Integer[] levels = {4,6,8,10,12,14,16,20,25,30};
|
||||
stepping = new PolarSheetsWindStepping(levels);
|
||||
polarData = initializePolarDataContainer();
|
||||
this.executor = executor;
|
||||
workers = new HashSet<PerRaceAndCompetitorPolarSheetGenerationWorker>();
|
||||
@@ -107,11 +111,12 @@ public class PolarSheetGenerationWorker {
|
||||
* product.
|
||||
*/
|
||||
public PolarSheetsData getPolarData() {
|
||||
Number[][] averagedPolarDataByWindSpeed = new Number[13][360];
|
||||
int levelCount = stepping.getNumberOfLevels();
|
||||
Number[][] averagedPolarDataByWindSpeed = new Number[levelCount][360];
|
||||
Integer[] dataCountPerAngle = new Integer[360];
|
||||
int dataCount = 0;
|
||||
Map<Integer, Integer[]> dataCountPerAngleForWindspeed = new HashMap<Integer, Integer[]>();
|
||||
for (int i = 0; i < 13; i++) {
|
||||
for (int i = 0; i < levelCount; i++) {
|
||||
dataCountPerAngleForWindspeed.put(i, new Integer[360]);
|
||||
}
|
||||
for (int i = 0; i < 360; i++) {
|
||||
@@ -119,22 +124,22 @@ public class PolarSheetGenerationWorker {
|
||||
BoatAndWindSpeed[] values = polarData.get(i).toArray(new BoatAndWindSpeed[polarData.get(i).size()]);
|
||||
dataCount = dataCount + values.length;
|
||||
dataCountPerAngle[i] = values.length;
|
||||
double[] sumsPerWindSpeed = new double[13];
|
||||
int[] dataCountPerWindSpeed = new int[13];
|
||||
double[] sumsPerWindSpeed = new double[levelCount];
|
||||
int[] dataCountPerWindSpeed = new int[levelCount];
|
||||
for (BoatAndWindSpeed singleDataPoint : values) {
|
||||
if (singleDataPoint != null) {
|
||||
int windSpeed = (int) singleDataPoint.getWindSpeed().getBeaufort();
|
||||
//Somehow beaufort sometimes gets bigger than twelve. TODO: Investigation
|
||||
if (windSpeed > 12) {
|
||||
windSpeed = 12;
|
||||
double windSpeed = singleDataPoint.getWindSpeed().getKnots();
|
||||
int level = stepping.getLevelForValue(windSpeed);
|
||||
if (level < 0) {
|
||||
continue;
|
||||
}
|
||||
//TODO enable different kinds of metrics for boats speed
|
||||
sumsPerWindSpeed[windSpeed] = sumsPerWindSpeed[windSpeed] + singleDataPoint.getBoatSpeed().getKnots();
|
||||
dataCountPerWindSpeed[windSpeed]++;
|
||||
sumsPerWindSpeed[level] = sumsPerWindSpeed[level] + singleDataPoint.getBoatSpeed().getKnots();
|
||||
dataCountPerWindSpeed[level]++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < 13; j++) {
|
||||
for (int j = 0; j < levelCount; j++) {
|
||||
Double average = sumsPerWindSpeed[j] / dataCountPerWindSpeed[j];
|
||||
if (average.isNaN()) {
|
||||
average = new Double(0);
|
||||
@@ -156,7 +161,7 @@ public class PolarSheetGenerationWorker {
|
||||
}
|
||||
|
||||
PolarSheetsData data = new PolarSheetsDataImpl(averagedPolarDataByWindSpeed, complete, dataCount,
|
||||
dataCountPerAngleForWindspeed);
|
||||
dataCountPerAngleForWindspeed, stepping.getRawStepping());
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -171,4 +176,8 @@ public class PolarSheetGenerationWorker {
|
||||
return polarData;
|
||||
}
|
||||
|
||||
public PolarSheetsWindStepping getStepping() {
|
||||
return stepping;
|
||||
}
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package com.sap.sailing.domain.polarsheets;
|
||||
|
||||
public class PolarSheetsWindStepping {
|
||||
|
||||
private Integer[] levels;
|
||||
|
||||
public PolarSheetsWindStepping(Integer[] levels) {
|
||||
this.levels = levels;
|
||||
}
|
||||
|
||||
public int getNumberOfLevels() {
|
||||
return levels.length;
|
||||
}
|
||||
|
||||
public int getLevelForValue(double speed) {
|
||||
for (int i = 0; i < levels.length - 1; i++) {
|
||||
if (speed < levels[i] || speed < levels[i] + ((levels[i+1] - levels[i]) / 2)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
if (speed < levels[levels.length - 1] + 5) {
|
||||
return levels.length - 1;
|
||||
}
|
||||
|
||||
//To high over highest level
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Integer[] getRawStepping() {
|
||||
return levels;
|
||||
}
|
||||
|
||||
}
|
||||
+3
-3
@@ -77,9 +77,9 @@ public class PolarSheetGenerationServiceTest {
|
||||
Assert.assertNotNull(results);
|
||||
|
||||
Assert.assertEquals(4, results.getDataCount());
|
||||
Assert.assertEquals(4.0, results.getAveragedPolarDataByWindSpeed()[1][45]);
|
||||
Assert.assertEquals(2.0, results.getAveragedPolarDataByWindSpeed()[1][55]);
|
||||
Assert.assertEquals(6.0, results.getAveragedPolarDataByWindSpeed()[1][30]);
|
||||
Assert.assertEquals(4.0, results.getAveragedPolarDataByWindSpeed()[0][45]);
|
||||
Assert.assertEquals(2.0, results.getAveragedPolarDataByWindSpeed()[0][55]);
|
||||
Assert.assertEquals(6.0, results.getAveragedPolarDataByWindSpeed()[0][30]);
|
||||
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -288,7 +288,7 @@ public interface SailingService extends RemoteService {
|
||||
|
||||
PolarSheetsData getPolarSheetsGenerationResults(String id);
|
||||
|
||||
PolarSheetsHistogramData getPolarSheetData(String polarSheetId, int angle, int windSpeed);
|
||||
PolarSheetsHistogramData getPolarSheetData(String polarSheetId, int angle, int windSpeedLevel);
|
||||
|
||||
EventDTO getEventById(Serializable id);
|
||||
|
||||
|
||||
+1
-1
@@ -429,7 +429,7 @@ public interface SailingServiceAsync {
|
||||
|
||||
void getPolarSheetsGenerationResults(String id, AsyncCallback<PolarSheetsData> asyncCallback);
|
||||
|
||||
void getPolarSheetData(String polarSheetId, int angle, int windSpeed, AsyncCallback<PolarSheetsHistogramData> wrapperCallback);
|
||||
void getPolarSheetData(String polarSheetId, int angle, int windSpeedLevel, AsyncCallback<PolarSheetsHistogramData> wrapperCallback);
|
||||
|
||||
void getRegattaOverviewEntriesForEvent(String eventIdAsString, AsyncCallback<List<RegattaOverviewEntryDTO>> asyncCallback);
|
||||
|
||||
|
||||
+7
-6
@@ -52,12 +52,12 @@ public class PolarSheetsChartPanel extends SimplePanel implements RequiresResize
|
||||
}
|
||||
}
|
||||
|
||||
private void createSeriesForWindspeed(String name, int windSpeed) {
|
||||
private void createSeriesForWindspeed(String name, int windSpeedLevel, int windSpeed) {
|
||||
Series[] seriesPerWindSpeed = seriesMap.get(name);
|
||||
Number[] forEachDeg = initializeDataForNewSeries();
|
||||
seriesPerWindSpeed[windSpeed] = chart.createSeries().setPoints(forEachDeg);
|
||||
seriesPerWindSpeed[windSpeed].setName(name + "-" + (windSpeed));
|
||||
chart.addSeries(seriesPerWindSpeed[windSpeed]);
|
||||
seriesPerWindSpeed[windSpeedLevel] = chart.createSeries().setPoints(forEachDeg);
|
||||
seriesPerWindSpeed[windSpeedLevel].setName(name + "-" + windSpeed);
|
||||
chart.addSeries(seriesPerWindSpeed[windSpeedLevel]);
|
||||
}
|
||||
|
||||
private Number[] initializeDataForNewSeries() {
|
||||
@@ -66,11 +66,12 @@ public class PolarSheetsChartPanel extends SimplePanel implements RequiresResize
|
||||
}
|
||||
|
||||
private void addValuesToSeries(String seriesId, PolarSheetsData result) {
|
||||
int stepCount = result.getStepping().length;
|
||||
if (seriesMap.containsKey(seriesId)) {
|
||||
for (int i = 0; i < 13; i++) {
|
||||
for (int i = 0; i < stepCount; i++) {
|
||||
if (hasSufficientDataForWindspeed(result.getDataCountPerAngleForWindspeed(i), result.getDataCount())) {
|
||||
if (seriesMap.get(seriesId)[i] == null) {
|
||||
createSeriesForWindspeed(seriesId, i);
|
||||
createSeriesForWindspeed(seriesId, i, result.getStepping()[i]);
|
||||
}
|
||||
Series series = seriesMap.get(seriesId)[i];
|
||||
series.setPoints(result.getAveragedPolarDataByWindSpeed()[i], false);
|
||||
|
||||
+5
@@ -12,10 +12,12 @@ import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.client.Timer;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.FormPanel;
|
||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.ListBox;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.sap.sailing.domain.common.PolarSheetGenerationTriggerResponse;
|
||||
import com.sap.sailing.domain.common.PolarSheetsData;
|
||||
@@ -81,6 +83,9 @@ public class PolarSheetsPanel extends FormPanel implements RaceSelectionChangeLi
|
||||
histogramPanel = new PolarSheetsHistogramPanel(stringMessages);
|
||||
histogramPanel.getElement().setAttribute("align", "top");
|
||||
rightPanel.add(histogramPanel);
|
||||
ListBox nameListBox = new ListBox();
|
||||
rightPanel.add(nameListBox);
|
||||
Button exportButton = new Button("Export");
|
||||
mainPanel.add(splitPanel);
|
||||
|
||||
asyncActionsExecutor = new AsyncActionsExecutor();
|
||||
|
||||
+6
-1
@@ -130,6 +130,7 @@ import com.sap.sailing.domain.persistence.MongoRaceLogStoreFactory;
|
||||
import com.sap.sailing.domain.persistence.MongoWindStoreFactory;
|
||||
import com.sap.sailing.domain.polarsheets.BoatAndWindSpeed;
|
||||
import com.sap.sailing.domain.polarsheets.PolarSheetGenerationWorker;
|
||||
import com.sap.sailing.domain.polarsheets.PolarSheetsWindStepping;
|
||||
import com.sap.sailing.domain.racelog.PassAwareRaceLog;
|
||||
import com.sap.sailing.domain.racelog.RaceLog;
|
||||
import com.sap.sailing.domain.racelog.RaceLogFlagEvent;
|
||||
@@ -2689,6 +2690,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
if (httpServletRequest != null) {
|
||||
HttpSession session = httpServletRequest.getSession();
|
||||
session.setAttribute(id, worker.getCompleteData());
|
||||
session.setAttribute("stepping", worker.getStepping());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -2713,11 +2715,14 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
//TODO exception handling
|
||||
return null;
|
||||
}
|
||||
|
||||
PolarSheetsWindStepping stepping = (PolarSheetsWindStepping) session.getAttribute("stepping");
|
||||
|
||||
List<Double> dataForAngleAndWindSpeed = new ArrayList<Double>();
|
||||
int windSpeedLevel = stepping.getLevelForValue(windSpeed);
|
||||
|
||||
for (BoatAndWindSpeed dataPoint: dataForAngle) {
|
||||
if (((int) dataPoint.getWindSpeed().getBeaufort()) == windSpeed) {
|
||||
if ((stepping.getLevelForValue(dataPoint.getWindSpeed().getKnots()) == windSpeedLevel)) {
|
||||
dataForAngleAndWindSpeed.add(dataPoint.getBoatSpeed().getKnots());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user