diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/PolarSheetsXYDiagramData.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/PolarSheetsXYDiagramData.java index 9311cda48d5..c6638dfe28d 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/PolarSheetsXYDiagramData.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/PolarSheetsXYDiagramData.java @@ -6,12 +6,6 @@ import java.util.List; import com.sap.sse.common.Util.Pair; public interface PolarSheetsXYDiagramData extends Serializable { - - List> getPointsForUpwindStarboardAverageSpeed(); - - List> getPointsForUpwindStarboardAverageAngle(); - - List> getPointsForUpwindStarboardAverageAngleMovingAverage(); List> getPointsForUpwindStarboardAverageSpeedMovingAverage(); diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/PolarSheetsXYDiagramDataImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/PolarSheetsXYDiagramDataImpl.java index 9c51a57807b..f47a1c99975 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/PolarSheetsXYDiagramDataImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/PolarSheetsXYDiagramDataImpl.java @@ -11,39 +11,15 @@ public class PolarSheetsXYDiagramDataImpl implements PolarSheetsXYDiagramData { PolarSheetsXYDiagramDataImpl() {} - private List> pointsForUpwindStarboardAverageAngle; - private List> pointsForUpwindStarboardAverageSpeed; - private List> pointsForUpwindStarboardAverageAngleMovingAverage; private List> pointsForUpwindStarboardAverageSpeedMovingAverage; private List> pointsForUpwindStarboardAverageConfidence; - public PolarSheetsXYDiagramDataImpl(List> pointsForUpwindStarboardAverageAngle, - List> pointsForUpwindStarboardAverageSpeed, - List> pointsForUpwindStarboardAverageAngleMovingAverage, - List> pointsForUpwindStarboardAverageSpeedMovingAverage, + public PolarSheetsXYDiagramDataImpl(List> pointsForUpwindStarboardAverageSpeedMovingAverage, List> pointsForUpwindStarboardAverageConfidence) { - this.pointsForUpwindStarboardAverageAngle = pointsForUpwindStarboardAverageAngle; - this.pointsForUpwindStarboardAverageSpeed = pointsForUpwindStarboardAverageSpeed; - this.pointsForUpwindStarboardAverageAngleMovingAverage = pointsForUpwindStarboardAverageAngleMovingAverage; this.pointsForUpwindStarboardAverageSpeedMovingAverage = pointsForUpwindStarboardAverageSpeedMovingAverage; this.pointsForUpwindStarboardAverageConfidence = pointsForUpwindStarboardAverageConfidence; } - @Override - public List> getPointsForUpwindStarboardAverageAngle() { - return pointsForUpwindStarboardAverageAngle; - } - - @Override - public List> getPointsForUpwindStarboardAverageSpeed() { - return pointsForUpwindStarboardAverageSpeed; - } - - @Override - public List> getPointsForUpwindStarboardAverageAngleMovingAverage() { - return pointsForUpwindStarboardAverageAngleMovingAverage; - } - @Override public List> getPointsForUpwindStarboardAverageSpeedMovingAverage() { return pointsForUpwindStarboardAverageSpeedMovingAverage; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/AngleOverDataSizeHistogramPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/AngleOverDataSizeHistogramPanel.java index 7fb32a7c65b..d8a71b6671e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/AngleOverDataSizeHistogramPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/AngleOverDataSizeHistogramPanel.java @@ -10,13 +10,13 @@ import java.util.Set; import org.moxieapps.gwt.highcharts.client.AxisTitle; import org.moxieapps.gwt.highcharts.client.Chart; +import org.moxieapps.gwt.highcharts.client.Legend; import org.moxieapps.gwt.highcharts.client.Point; import org.moxieapps.gwt.highcharts.client.Series; import org.moxieapps.gwt.highcharts.client.Series.Type; import org.moxieapps.gwt.highcharts.client.labels.XAxisLabels; import org.moxieapps.gwt.highcharts.client.plotOptions.AreaPlotOptions; import org.moxieapps.gwt.highcharts.client.plotOptions.Marker; -import org.moxieapps.gwt.highcharts.client.plotOptions.PlotOptions.Stacking; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.user.client.Timer; @@ -37,11 +37,14 @@ public class AngleOverDataSizeHistogramPanel extends DockLayoutPanel { private final StringMessages stringMessages; private final Map> seriesForId; + + private final Map seriesForName; public AngleOverDataSizeHistogramPanel(StringMessages stringMessages) { super(Unit.PX); this.seriesForId = new HashMap<>(); + this.seriesForName = new HashMap<>(); this.stringMessages = stringMessages; setSize("100%", "100%"); @@ -56,25 +59,28 @@ public class AngleOverDataSizeHistogramPanel extends DockLayoutPanel { histogramChart.getYAxis().setMin(0).setAxisTitle(new AxisTitle().setText(stringMessages.numberOfDataPoints())); histogramChart.getXAxis().setLabels(new XAxisLabels().setRotation(-90f).setY(10)) .setAxisTitle(new AxisTitle().setText(stringMessages.beatAngle())); - histogramChart.setAreaPlotOptions(new AreaPlotOptions().setStacking(Stacking.NORMAL).setLineColor("#666666") + histogramChart.setAreaPlotOptions(new AreaPlotOptions().setLineColor("#666666") .setLineWidth(1).setMarker(new Marker().setLineWidth(1).setLineColor("#666666"))); + histogramChart.setLegend(new Legend().setEnabled(false)); return histogramChart; } - public void addData(Map histogramDataPerAngle, String seriesId, String actualSeriesName) { + public void addData(Map histogramDataPerAngle, String seriesId, String actualSeriesName, boolean setVisible) { chart.setTitle(""); Series series = chart.createSeries(); Point[] points = toPoints(histogramDataPerAngle); - series.setPoints(points); + series.setPoints(points, false); series.setName(actualSeriesName); - chart.addSeries(series); + chart.addSeries(series, false, false); + series.setVisible(setVisible, false); if (!seriesForId.containsKey(seriesId)) { seriesForId.put(seriesId, new HashSet()); } Set seriesSet = seriesForId.get(seriesId); seriesSet.add(series); + seriesForName.put(actualSeriesName, series); } private Point[] toPoints(Map histogramDataPerAngle) { @@ -121,6 +127,7 @@ public class AngleOverDataSizeHistogramPanel extends DockLayoutPanel { public void removeSeries(String seriesId) { for (Series series : seriesForId.get(seriesId)) { chart.removeSeries(series); + seriesForName.remove(series.getName()); } seriesForId.remove(seriesId); } @@ -129,6 +136,22 @@ public class AngleOverDataSizeHistogramPanel extends DockLayoutPanel { chart.removeAllSeries(); seriesForId.clear(); } + + public void redrawChart() { + chart.redraw(); + } + + public void showSeries(String name) { + if (seriesForName.containsKey(name)) { + seriesForName.get(name).show(); + } + } + + public void hideSeries(String name) { + if (seriesForName.containsKey(name)) { + seriesForName.get(name).hide(); + } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsChartPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsChartPanel.java index f21fe20539f..ffc929decd2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsChartPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsChartPanel.java @@ -10,12 +10,14 @@ import java.util.Map.Entry; import org.moxieapps.gwt.highcharts.client.BaseChart; import org.moxieapps.gwt.highcharts.client.Chart; -import org.moxieapps.gwt.highcharts.client.Color; import org.moxieapps.gwt.highcharts.client.Point; import org.moxieapps.gwt.highcharts.client.Series; import org.moxieapps.gwt.highcharts.client.events.PointSelectEventHandler; +import org.moxieapps.gwt.highcharts.client.events.SeriesHideEvent; +import org.moxieapps.gwt.highcharts.client.events.SeriesHideEventHandler; +import org.moxieapps.gwt.highcharts.client.events.SeriesShowEvent; +import org.moxieapps.gwt.highcharts.client.events.SeriesShowEventHandler; import org.moxieapps.gwt.highcharts.client.plotOptions.LinePlotOptions; -import org.moxieapps.gwt.highcharts.client.plotOptions.Marker; import org.moxieapps.gwt.highcharts.client.plotOptions.SeriesPlotOptions; import com.google.gwt.dom.client.Style.Unit; @@ -44,18 +46,50 @@ public class PolarSheetsChartPanel extends DockLayoutPanel { private final Map polarSheetsDataMap; private final AngleOverDataSizeHistogramPanel angleOverDataSizeHistogramPanel; + private final SeriesPlotOptions seriesPlotOptions; public PolarSheetsChartPanel(StringMessages stringMessages, AngleOverDataSizeHistogramPanel angleOverDataSizeHistogramPanel) { super(Unit.PCT); + seriesPlotOptions = new SeriesPlotOptions(); this.stringMessages = stringMessages; this.angleOverDataSizeHistogramPanel = angleOverDataSizeHistogramPanel; polarSheetsDataMap = new HashMap(); setSize("100%", "100%"); chart = createPolarSheetChart(); + setSeriesShowHandler(createSeriesShowEventHandler()); + setSeriesHideHandler(createSeriesHideEventHandler()); seriesMap = new HashMap(); add(chart); } + private void setSeriesHideHandler(SeriesHideEventHandler seriesHideEventHandler) { + chart.setSeriesPlotOptions(seriesPlotOptions.setSeriesHideEventHandler(seriesHideEventHandler)); + } + + private SeriesShowEventHandler createSeriesShowEventHandler() { + return new SeriesShowEventHandler() { + + @Override + public boolean onShow(SeriesShowEvent seriesShowEvent) { + String name = seriesShowEvent.getSeriesName(); + angleOverDataSizeHistogramPanel.showSeries(name); + return true; + } + }; + } + + private SeriesHideEventHandler createSeriesHideEventHandler() { + return new SeriesHideEventHandler() { + + @Override + public boolean onHide(SeriesHideEvent seriesHideEvent) { + String name = seriesHideEvent.getSeriesName(); + angleOverDataSizeHistogramPanel.hideSeries(name); + return true; + } + }; + } + /** * Creates a polar diagram chart of the Line type. */ @@ -116,20 +150,30 @@ public class PolarSheetsChartPanel extends DockLayoutPanel { */ private void addValuesToSeries(String seriesId, PolarSheetsData result) { int stepCount = result.getStepping().getRawStepping().length; + boolean oneSeriesSetToVisible = false; if (seriesMap.containsKey(seriesId)) { for (int i = 0; i < stepCount; i++) { if (hasSufficientDataForWindspeed(result.getDataCountPerAngleForWindspeed(i))) { - String actualSeriesName = seriesId + "-" + result.getStepping().getRawStepping()[i]; - if (seriesMap.get(seriesId)[i] == null) { - createSeriesForWindspeed(seriesId, i, actualSeriesName); - } - Series series = seriesMap.get(seriesId)[i]; - //series.setPoints(result.getAveragedPolarDataByWindSpeed()[i], false); - Point[] points = createPointsWithMarkerAlphaAccordingToDataCount(result, i); + Point[] points = createPoints(result, i); if (points != null) { - series.setPoints(points); - angleOverDataSizeHistogramPanel.addData(result.getHistogramDataMap().get(i), seriesId, actualSeriesName); + String actualSeriesName = seriesId + "-" + result.getStepping().getRawStepping()[i]; + if (seriesMap.get(seriesId)[i] == null) { + createSeriesForWindspeed(seriesId, i, actualSeriesName); + } + Series series = seriesMap.get(seriesId)[i]; + // series.setPoints(result.getAveragedPolarDataByWindSpeed()[i], false); + + series.setPoints(points, false); + angleOverDataSizeHistogramPanel.addData(result.getHistogramDataMap().get(i), seriesId, + actualSeriesName, !oneSeriesSetToVisible); + angleOverDataSizeHistogramPanel.redrawChart(); + if (!oneSeriesSetToVisible) { + oneSeriesSetToVisible = true; + } else { + series.setVisible(false, false); + } } + } } } @@ -154,7 +198,7 @@ public class PolarSheetsChartPanel extends DockLayoutPanel { * Points are created using the polar sheets generation results. Points color and alpha in the graph is calculated * using statistical measures. */ - private Point[] createPointsWithMarkerAlphaAccordingToDataCount(PolarSheetsData result, int windspeed) { + private Point[] createPoints(PolarSheetsData result, int windspeed) { Point[] points = new Point[360]; List dataCountList = Arrays.asList(result.getDataCountPerAngleForWindspeed(windspeed)); Integer max = Collections.max(dataCountList); @@ -174,23 +218,6 @@ public class PolarSheetsChartPanel extends DockLayoutPanel { if (points[i] == null) { points[i] = new Point(result.getAveragedPolarDataByWindSpeed()[windspeed][i]); } - double alpha = (double) dataCountList.get(i) / (double) max; - int blue; - int red; - int radius; - if (alpha > 0.2) { - red = (int) (alpha * 255); - blue = 0; - radius = 2; - } else { - blue = (int) ((1 - alpha) * 255); - red = 0; - radius = 2; - } - - // Don't let the markers be invisible - alpha = 0.5 + 0.5 * alpha; - points[i].setMarker(new Marker().setFillColor(new Color(red, 0, blue, alpha)).setRadius(radius)); } return points; @@ -224,7 +251,7 @@ public class PolarSheetsChartPanel extends DockLayoutPanel { } /** - * Adds a the results of a polar sheet generation to the chart panel. Performs all necessary steps including adding + * Adds the results of a polar sheet generation to the chart panel. Performs all necessary steps including adding * the set of series to the map and redrawing the chart. * * @param id Set of series identifier. @@ -248,9 +275,13 @@ public class PolarSheetsChartPanel extends DockLayoutPanel { * Allows setting the point select handler for the chart. */ public void setPointSelectHandler(PointSelectEventHandler pointSelectEventHandler) { - chart.setSeriesPlotOptions(new SeriesPlotOptions().setAllowPointSelect(true).setPointSelectEventHandler( + chart.setSeriesPlotOptions(seriesPlotOptions.setAllowPointSelect(true).setPointSelectEventHandler( pointSelectEventHandler)); } + + private void setSeriesShowHandler(SeriesShowEventHandler eventHandler) { + chart.setSeriesPlotOptions(seriesPlotOptions.setSeriesShowEventHandler(eventHandler)); + } public Series[] getSeriesPerWindspeedForName(String name) { return seriesMap.get(name); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsXYDiagramPopupPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsXYDiagramPopupPanel.java index 44626872dc8..8432dd04f26 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsXYDiagramPopupPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsXYDiagramPopupPanel.java @@ -44,16 +44,6 @@ public class PolarSheetsXYDiagramPopupPanel extends DialogBox { }); containerPanel.add(closeButton); - Point[] pointsForUpwindStarboardAverageAngle = toPointArray(result.getPointsForUpwindStarboardAverageAngle()); - Series angleSeries = chart.createSeries(); - angleSeries.setPoints(pointsForUpwindStarboardAverageAngle); - //chart.addSeries(angleSeries); - - Point[] pointsForUpwindStarboardAverageSpeed = toPointArray(result.getPointsForUpwindStarboardAverageSpeed()); - Series speedSeries = chart.createSeries(); - speedSeries.setName("Upwind Starboard Speed - LinearRegressions"); - speedSeries.setPoints(pointsForUpwindStarboardAverageSpeed); - chart.addSeries(speedSeries); Point[] pointsForUpwindStarboardAverageSpeedMovingAverage = toPointArray(result.getPointsForUpwindStarboardAverageSpeedMovingAverage()); Series speedSeriesMovingAverage = chart.createSeries(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index 59cb2a64375..268b8e10073 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -126,6 +126,7 @@ import com.sap.sailing.domain.base.impl.RegattaImpl; import com.sap.sailing.domain.base.impl.SeriesImpl; import com.sap.sailing.domain.base.impl.TeamImpl; import com.sap.sailing.domain.common.Bearing; +import com.sap.sailing.domain.common.BoatClassMasterdata; import com.sap.sailing.domain.common.CountryCode; import com.sap.sailing.domain.common.DataImportProgress; import com.sap.sailing.domain.common.DetailType; @@ -3948,10 +3949,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public List getBoatClassNamesWithPolarSheetsAvailable() { - Set boatClasses = getService().getPolarDataService().getAllBoatClassesWithPolarSheetsAvailable(); + Set boatClasses = getService().getPolarDataService().getAllBoatClassesWithPolarSheetsAvailable(); List names = new ArrayList(); - for (BoatClass boatClass : boatClasses) { - names.add(boatClass.getName()); + for (BoatClassMasterdata boatClass : boatClasses) { + names.add(boatClass.getDisplayName()); } return names; } @@ -5351,39 +5352,25 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public PolarSheetsXYDiagramData createXYDiagramForBoatClass(String boatClassName) { BoatClass boatClass = getService().getBaseDomainFactory().getOrCreateBoatClass(boatClassName); - List> pointsForUpwindStarboardAverageSpeed = new ArrayList>(); - List> pointsForUpwindStarboardAverageAngle = new ArrayList>(); List> pointsForUpwindStarboardAverageSpeedMovingAverage = new ArrayList>(); - List> pointsForUpwindStarboardAverageAngleMovingAverage = new ArrayList>(); List> pointsForUpwindStarboardAverageConfidence = new ArrayList>(); for (double windInKnots = 0.1; windInKnots < 30; windInKnots = windInKnots + 0.1) { try { - SpeedWithBearingWithConfidence averageUpwindStarboard = getService().getPolarDataService() - .getAverageSpeedWithBearing(boatClass, new KnotSpeedImpl(windInKnots), LegType.UPWIND, - Tack.STARBOARD, true); - pointsForUpwindStarboardAverageSpeed.add(new Pair(windInKnots, averageUpwindStarboard - .getObject().getKnots())); - pointsForUpwindStarboardAverageAngle.add(new Pair(windInKnots, averageUpwindStarboard - .getObject().getBearing().getDegrees())); - pointsForUpwindStarboardAverageConfidence.add(new Pair(windInKnots, - averageUpwindStarboard.getConfidence())); - SpeedWithBearingWithConfidence averageUpwindStarboardMovingAverage = getService().getPolarDataService() .getAverageSpeedWithBearing(boatClass, new KnotSpeedImpl(windInKnots), LegType.UPWIND, - Tack.STARBOARD, false); + Tack.STARBOARD); pointsForUpwindStarboardAverageSpeedMovingAverage.add(new Pair(windInKnots, averageUpwindStarboardMovingAverage.getObject().getKnots())); - pointsForUpwindStarboardAverageAngleMovingAverage.add(new Pair(windInKnots, - averageUpwindStarboardMovingAverage.getObject().getBearing().getDegrees())); + + pointsForUpwindStarboardAverageConfidence.add(new Pair(windInKnots, + averageUpwindStarboardMovingAverage.getConfidence())); } catch (NotEnoughDataHasBeenAddedException e) { // Do not add a point to the result } } - PolarSheetsXYDiagramData data = new PolarSheetsXYDiagramDataImpl(pointsForUpwindStarboardAverageAngle, - pointsForUpwindStarboardAverageSpeed, pointsForUpwindStarboardAverageAngleMovingAverage, - pointsForUpwindStarboardAverageSpeedMovingAverage, pointsForUpwindStarboardAverageConfidence); + PolarSheetsXYDiagramData data = new PolarSheetsXYDiagramDataImpl(pointsForUpwindStarboardAverageSpeedMovingAverage, pointsForUpwindStarboardAverageConfidence); return data; } diff --git a/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/caching/test/PolarFixCacheRaceIntervalTest.java b/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/caching/test/PolarFixCacheRaceIntervalTest.java deleted file mode 100644 index f3ee8c2b40f..00000000000 --- a/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/caching/test/PolarFixCacheRaceIntervalTest.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.sap.sailing.polars.caching.test; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; - -import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; - -import org.junit.Test; - -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.polars.caching.PolarFixCacheRaceInterval; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; -import com.sap.sse.common.impl.MillisecondsTimePoint; - -public class PolarFixCacheRaceIntervalTest { - - @Test - public void testIntervalJoin() { - TrackedRace mockedTrackedRace1 = mock(TrackedRace.class); - TrackedRace mockedTrackedRace2 = mock(TrackedRace.class); - - Competitor mockedCompetitor1 = mock(Competitor.class); - Competitor mockedCompetitor2 = mock(Competitor.class); - - Calendar calender = Calendar.getInstance(); - calender.set(2014, 3, 17, 16, 0, 0); - TimePoint timePoint1 = new MillisecondsTimePoint(calender.getTime()); - calender.set(2014, 3, 17, 16, 10, 0); - TimePoint timePoint2 = new MillisecondsTimePoint(calender.getTime()); - - PolarFixCacheRaceInterval interval1 = createInterval1( - mockedTrackedRace1, mockedTrackedRace2, mockedCompetitor1, - mockedCompetitor2, timePoint1, timePoint2); - - PolarFixCacheRaceInterval interval2 = createInterval2( - mockedTrackedRace1, mockedTrackedRace2, mockedCompetitor1, - timePoint2); - PolarFixCacheRaceInterval joined = interval1.join(interval2); - - Map>> joinedMap = joined - .getCompetitorAndTimepointsForRace(); - - Map> explicitIntervalForRace1 = joinedMap.get(mockedTrackedRace1); - assertThat(explicitIntervalForRace1, notNullValue(Map.class)); - Pair explicitIntervalForCompetitor1 = explicitIntervalForRace1.get(mockedCompetitor1); - assertThat(explicitIntervalForCompetitor1, notNullValue(Pair.class)); - - TimePoint start1 = explicitIntervalForCompetitor1.getA(); - TimePoint end1 = explicitIntervalForCompetitor1.getB(); - - assertThat(start1, is(timePoint1)); - assertThat(end1, is(timePoint2)); - - } - - private PolarFixCacheRaceInterval createInterval1( - TrackedRace mockedTrackedRace1, TrackedRace mockedTrackedRace2, - Competitor mockedCompetitor1, Competitor mockedCompetitor2, - TimePoint timePoint1, TimePoint timePoint2) { - Map>> competitorAndTimepointsForRace = new HashMap>>(); - HashMap> mapForRace1 = new HashMap>(); - mapForRace1.put(mockedCompetitor1, new Pair(timePoint1, timePoint1)); - competitorAndTimepointsForRace.put(mockedTrackedRace1, mapForRace1); - HashMap> mapForRace2 = new HashMap>(); - mapForRace2.put(mockedCompetitor2, new Pair(timePoint1, timePoint2)); - competitorAndTimepointsForRace.put(mockedTrackedRace2, mapForRace2); - PolarFixCacheRaceInterval interval1 = new PolarFixCacheRaceInterval( - competitorAndTimepointsForRace); - return interval1; - } - - private PolarFixCacheRaceInterval createInterval2( - TrackedRace mockedTrackedRace1, TrackedRace mockedTrackedRace2, - Competitor mockedCompetitor1, TimePoint timePoint2) { - Map>> competitorAndTimepointsForRace = new HashMap>>(); - HashMap> mapForRace1 = new HashMap>(); - mapForRace1.put(mockedCompetitor1, new Pair( - timePoint2, timePoint2)); - competitorAndTimepointsForRace.put(mockedTrackedRace1, mapForRace1); - PolarFixCacheRaceInterval interval2 = new PolarFixCacheRaceInterval( - competitorAndTimepointsForRace); - return interval2; - } -} diff --git a/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/mining/test/PolarDataMinerTest.java b/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/mining/test/PolarDataMinerTest.java index 2d81c4d20b1..f42c269a5c4 100644 --- a/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/mining/test/PolarDataMinerTest.java +++ b/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/mining/test/PolarDataMinerTest.java @@ -58,6 +58,8 @@ public class PolarDataMinerTest { PolarDataMiner miner = new PolarDataMiner(); BoatClass mockedBoatClass = mock(BoatClass.class); + + when(mockedBoatClass.getName()).thenReturn("49ER"); GPSFixMoving fix1_1 = createMockedFix(13, 00, 54.431952, 10.186767, 45, 10.5); GPSFixMoving fix1_2 = createMockedFix(13, 30, 54.485034, 10.538303, 44.8, 10.6); @@ -107,17 +109,17 @@ public class PolarDataMinerTest { } SpeedWithConfidence estimatedSpeed1 = miner.estimateBoatSpeed(mockedBoatClass, new KnotSpeedImpl(15), - new DegreeBearingImpl(44.9), true); + new DegreeBearingImpl(44.9)); assertThat(estimatedSpeed1, is(notNullValue())); assertThat(estimatedSpeed1.getObject().getKnots(), is(closeTo(10.55, EPSILON))); SpeedWithConfidence estimatedSpeed2 = miner.estimateBoatSpeed(mockedBoatClass, new KnotSpeedImpl(15), - new DegreeBearingImpl(42), true); + new DegreeBearingImpl(42)); assertThat(estimatedSpeed2, is(notNullValue())); assertThat(estimatedSpeed2.getObject().getKnots(), is(closeTo(10.05, EPSILON))); SpeedWithConfidence estimatedSpeed3 = miner.estimateBoatSpeed(mockedBoatClass, new KnotSpeedImpl(15), - new DegreeBearingImpl(42.8), true); + new DegreeBearingImpl(42.8)); assertThat(estimatedSpeed3, is(notNullValue())); assertThat(estimatedSpeed3.getObject().getKnots(), is(closeTo(10, EPSILON))); } diff --git a/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/test/PolarSheetAnalyzerTest.java b/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/test/PolarSheetAnalyzerTest.java old mode 100644 new mode 100755 index 3904f40f0ef..e31e631a94a --- a/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/test/PolarSheetAnalyzerTest.java +++ b/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/test/PolarSheetAnalyzerTest.java @@ -31,25 +31,25 @@ public class PolarSheetAnalyzerTest { BoatClass boatClass = mock(BoatClass.class); SpeedWithBearingWithConfidence result = analyzer.getAverageUpwindSpeedWithBearingOnStarboardTackFor(boatClass, - new KnotSpeedImpl(14), true); + new KnotSpeedImpl(14)); assertThat(result.getObject().getKnots(), closeTo(8.5, 0.1)); assertThat(result.getObject().getBearing().getDegrees(), closeTo(50, 0.1)); assertThat(result.getConfidence(), closeTo(0.7, 0.1)); SpeedWithBearingWithConfidence result2 = analyzer.getAverageDownwindSpeedWithBearingOnStarboardTackFor(boatClass, - new KnotSpeedImpl(14), true); + new KnotSpeedImpl(14)); assertThat(result2.getObject().getKnots(), closeTo(14.2, 0.1)); assertThat(result2.getObject().getBearing().getDegrees(), closeTo(142.8, 0.1)); assertThat(result2.getConfidence(), closeTo(0.6, 0.1)); SpeedWithBearingWithConfidence result3 = analyzer.getAverageUpwindSpeedWithBearingOnPortTackFor(boatClass, - new KnotSpeedImpl(14), true); + new KnotSpeedImpl(14)); assertThat(result3.getObject().getKnots(), closeTo(8.6, 0.1)); assertThat(result3.getObject().getBearing().getDegrees(), closeTo(-49.5, 0.1)); assertThat(result3.getConfidence(), closeTo(0.7, 0.1)); SpeedWithBearingWithConfidence result4 = analyzer.getAverageDownwindSpeedWithBearingOnPortTackFor(boatClass, - new KnotSpeedImpl(14), true); + new KnotSpeedImpl(14)); assertThat(result4.getObject().getKnots(), closeTo(13.5, 0.1)); assertThat(result4.getObject().getBearing().getDegrees(), closeTo(-143.6, 0.1)); assertThat(result4.getConfidence(), closeTo(0.25, 0.1)); @@ -64,46 +64,46 @@ public class PolarSheetAnalyzerTest { //Starboard Upwind when(mockedPolarDataService.getSpeed(any(BoatClass.class), argThat(new SpeedMatcher(14)), - argThat(new BearingMatcher(49)), eq(true))).thenReturn( + argThat(new BearingMatcher(49)))).thenReturn( new SpeedWithConfidenceImpl(new KnotSpeedImpl(8.478048671702888), 0.5, null)); when(mockedPolarDataService.getSpeed(any(BoatClass.class), argThat(new SpeedMatcher(14)), - argThat(new BearingMatcher(50)), eq(true))).thenReturn( + argThat(new BearingMatcher(50)))).thenReturn( new SpeedWithConfidenceImpl(new KnotSpeedImpl(8.466303997538812), 0.5, null)); when(mockedPolarDataService.getSpeed(any(BoatClass.class), argThat(new SpeedMatcher(14)), - argThat(new BearingMatcher(51)), eq(true))).thenReturn( + argThat(new BearingMatcher(51)))).thenReturn( new SpeedWithConfidenceImpl(new KnotSpeedImpl(8.583383077026435), 0.5, null)); //Starboard Downwind when(mockedPolarDataService.getSpeed(any(BoatClass.class), argThat(new SpeedMatcher(14)), - argThat(new BearingMatcher(141)), eq(true))).thenReturn( + argThat(new BearingMatcher(141)))).thenReturn( new SpeedWithConfidenceImpl(new KnotSpeedImpl(13.794354053931528), 0.5, null)); when(mockedPolarDataService.getSpeed(any(BoatClass.class), argThat(new SpeedMatcher(14)), - argThat(new BearingMatcher(142)), eq(true))).thenReturn( + argThat(new BearingMatcher(142)))).thenReturn( new SpeedWithConfidenceImpl(new KnotSpeedImpl(13.665782579628802), 0.5, null)); when(mockedPolarDataService.getSpeed(any(BoatClass.class), argThat(new SpeedMatcher(14)), - argThat(new BearingMatcher(143)), eq(true))).thenReturn( + argThat(new BearingMatcher(143)))).thenReturn( new SpeedWithConfidenceImpl(new KnotSpeedImpl(14.169301888320263), 0.5, null)); //Port Upwind when(mockedPolarDataService.getSpeed(any(BoatClass.class), argThat(new SpeedMatcher(14)), - argThat(new BearingMatcher(-48)), eq(true))).thenReturn( + argThat(new BearingMatcher(-48)))).thenReturn( new SpeedWithConfidenceImpl(new KnotSpeedImpl(8.445599410456111), 0.5, null)); when(mockedPolarDataService.getSpeed(any(BoatClass.class), argThat(new SpeedMatcher(14)), - argThat(new BearingMatcher(-50)), eq(true))).thenReturn( + argThat(new BearingMatcher(-50)))).thenReturn( new SpeedWithConfidenceImpl(new KnotSpeedImpl(8.553274292235153), 0.5, null)); when(mockedPolarDataService.getSpeed(any(BoatClass.class), argThat(new SpeedMatcher(14)), - argThat(new BearingMatcher(-49)), eq(true))).thenReturn( + argThat(new BearingMatcher(-49)))).thenReturn( new SpeedWithConfidenceImpl(new KnotSpeedImpl(8.614582090896583), 0.5, null)); //Port Downwind when(mockedPolarDataService.getSpeed(any(BoatClass.class), argThat(new SpeedMatcher(14)), - argThat(new BearingMatcher(-145)), eq(true))).thenReturn( + argThat(new BearingMatcher(-145)))).thenReturn( new SpeedWithConfidenceImpl(new KnotSpeedImpl(13.78894715705271), 0.5, null)); when(mockedPolarDataService.getSpeed(any(BoatClass.class), argThat(new SpeedMatcher(14)), - argThat(new BearingMatcher(-144)), eq(true))).thenReturn( + argThat(new BearingMatcher(-144)))).thenReturn( new SpeedWithConfidenceImpl(new KnotSpeedImpl(13.420656294986587), 0.5, null)); when(mockedPolarDataService.getSpeed(any(BoatClass.class), argThat(new SpeedMatcher(14)), - argThat(new BearingMatcher(-143)), eq(true))).thenReturn( + argThat(new BearingMatcher(-143)))).thenReturn( new SpeedWithConfidenceImpl(new KnotSpeedImpl(13.268607457651942), 0.5, null)); return mockedPolarDataService; diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/PolarDataService.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/PolarDataService.java old mode 100644 new mode 100755 index 44a0290f3b2..d409fc58085 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/PolarDataService.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/PolarDataService.java @@ -9,6 +9,7 @@ import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.SpeedWithBearingWithConfidence; import com.sap.sailing.domain.base.SpeedWithConfidence; import com.sap.sailing.domain.common.Bearing; +import com.sap.sailing.domain.common.BoatClassMasterdata; import com.sap.sailing.domain.common.LegType; import com.sap.sailing.domain.common.PolarSheetGenerationSettings; import com.sap.sailing.domain.common.PolarSheetsData; @@ -16,8 +17,6 @@ import com.sap.sailing.domain.common.Speed; import com.sap.sailing.domain.common.Tack; import com.sap.sailing.domain.tracking.GPSFixMoving; import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.polars.analysis.PolarSheetAnalyzer; -import com.sap.sailing.polars.data.PolarFix; import com.sap.sailing.polars.regression.NotEnoughDataHasBeenAddedException; /** @@ -27,7 +26,6 @@ import com.sap.sailing.polars.regression.NotEnoughDataHasBeenAddedException; * * This service uses a {@link PolarSheetAnalyzer} for more advanced analysis. Its methods are facaded in this interface for * central access.

- * * The interesting methods for a client are {@link #getSpeed(BoatClass, Speed, Bearing, boolean)} if data for a specific angle is * needed and {@link #getAverageSpeedWithBearing(BoatClass, Speed, LegType, Tack)} * which also returns the average angle for the parameters provided. @@ -42,14 +40,11 @@ public interface PolarDataService { * @param boatClass * @param windSpeed * @param bearingToTheWind - * Boat's direction relative to the wind. either in -180 -> +180 or 0 -> 359 degrees - * @param useLinearRegression - * if true uses linear Regression for estimation in the wind interval, if false - * simple arithmetic mean in interval + * Boat's direction relative to the wind. either in -180 -> +180 or 0 -> 359 degrees interval. The true wind! * @return The speed the boat is moving at for the specified wind and bearing according to the polar diagram. * @throws NotEnoughDataHasBeenAddedException */ - SpeedWithConfidence getSpeed(BoatClass boatClass, Speed windSpeed, Bearing bearingToTheWind, boolean useLinearRegression) + SpeedWithConfidence getSpeed(BoatClass boatClass, Speed windSpeed, Bearing bearingToTheWind) throws NotEnoughDataHasBeenAddedException; /** @@ -62,8 +57,8 @@ public interface PolarDataService { * @param tack * Polar data can vary depending on the tack the boat is on. * @return The estimated average speed of a boat for the supplied parameters with the estimated average bearing to - * the wind and a confidence which consists of the confidences of the wind speed, and boat speed sources - * (50%) and a confidence calculated using the amount of underlying fixes (50%). 0 <= confidence < 1
+ * the true wind and a confidence which consists of the confidences of the wind speed, and boat speed sources (50%) + * and a confidence calculated using the amount of underlying fixes (50%). 0 <= confidence < 1
* A value with zero confidence doesn't have any significance!
*
* @@ -97,16 +92,6 @@ public interface PolarDataService { PolarSheetsData generatePolarSheet(Set trackedRaces, PolarSheetGenerationSettings settings, Executor executor) throws InterruptedException, ExecutionException; - void newRaceFinishedTracking(TrackedRace trackedRace); - - /** - * @param key - * The {@link BoatClass} to obtain fixes for. - * @return All raw polar fixes for the {@link BoatClass}. The implementation is responsible for deciding wether a - * cache is used or not. - */ - Set getPolarFixesForBoatClass(BoatClass key); - /** * * @param boatClass @@ -120,8 +105,16 @@ public interface PolarDataService { * @return The {@link BoatClass}es for which there are polar sheets available via * {@link PolarDataService#getPolarSheetForBoatClass(BoatClass)} */ - Set getAllBoatClassesWithPolarSheetsAvailable(); + Set getAllBoatClassesWithPolarSheetsAvailable(); + /** + * To be called in an appropriate listener. + * Starting point for fixes entering the backend polar data mining pipeline. + * + * @param fix + * @param competitor + * @param createdTrackedRace + */ void competitorPositionChanged(GPSFixMoving fix, Competitor competitor, TrackedRace createdTrackedRace); /** @@ -133,9 +126,6 @@ public interface PolarDataService { * @return array with datacount for all angles in the given area, else -1 */ int[] getDataCountsForWindSpeed(BoatClass boatClass, Speed windSpeed, int startAngleInclusive, int endAngleExclusive); - - SpeedWithBearingWithConfidence getAverageSpeedWithBearing(BoatClass boatClass, Speed windSpeed, - LegType legType, Tack tack, boolean useLinearRegression) throws NotEnoughDataHasBeenAddedException; } diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/analysis/PolarSheetAnalyzer.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/analysis/PolarSheetAnalyzer.java old mode 100644 new mode 100755 index b92feee0cd1..4122a17d0f1 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/analysis/PolarSheetAnalyzer.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/analysis/PolarSheetAnalyzer.java @@ -8,15 +8,15 @@ import com.sap.sailing.polars.regression.NotEnoughDataHasBeenAddedException; public interface PolarSheetAnalyzer { SpeedWithBearingWithConfidence getAverageUpwindSpeedWithBearingOnStarboardTackFor(BoatClass boatClass, - Speed windSpeed, boolean useLinReg) throws NotEnoughDataHasBeenAddedException; + Speed windSpeed) throws NotEnoughDataHasBeenAddedException; SpeedWithBearingWithConfidence getAverageDownwindSpeedWithBearingOnStarboardTackFor(BoatClass boatClass, - Speed windSpeed, boolean useLinReg) throws NotEnoughDataHasBeenAddedException; + Speed windSpeed) throws NotEnoughDataHasBeenAddedException; SpeedWithBearingWithConfidence getAverageUpwindSpeedWithBearingOnPortTackFor(BoatClass boatClass, - Speed windSpeed, boolean useLinReg) throws NotEnoughDataHasBeenAddedException; + Speed windSpeed) throws NotEnoughDataHasBeenAddedException; SpeedWithBearingWithConfidence getAverageDownwindSpeedWithBearingOnPortTackFor(BoatClass boatClass, - Speed windSpeed, boolean useLinReg) throws NotEnoughDataHasBeenAddedException; + Speed windSpeed) throws NotEnoughDataHasBeenAddedException; } \ No newline at end of file diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/analysis/impl/PolarSheetAnalyzerImpl.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/analysis/impl/PolarSheetAnalyzerImpl.java old mode 100644 new mode 100755 index 21623f6f49f..2be5d6df0e5 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/analysis/impl/PolarSheetAnalyzerImpl.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/analysis/impl/PolarSheetAnalyzerImpl.java @@ -29,52 +29,53 @@ public class PolarSheetAnalyzerImpl implements PolarSheetAnalyzer { } @Override - public SpeedWithBearingWithConfidence getAverageUpwindSpeedWithBearingOnStarboardTackFor(BoatClass boatClass, Speed windSpeed, boolean useLinReg) + public SpeedWithBearingWithConfidence getAverageUpwindSpeedWithBearingOnStarboardTackFor(BoatClass boatClass, Speed windSpeed) throws NotEnoughDataHasBeenAddedException { int startAngleInclusive = 1; int endAngleExclusive = 90; SpeedWithBearingWithConfidence speedWithBearing = estimateAnglePeakAndAverageSpeed(boatClass, windSpeed, startAngleInclusive, - endAngleExclusive, useLinReg); + endAngleExclusive); return speedWithBearing; } @Override - public SpeedWithBearingWithConfidence getAverageDownwindSpeedWithBearingOnStarboardTackFor(BoatClass boatClass, Speed windSpeed, boolean useLinReg) + public SpeedWithBearingWithConfidence getAverageDownwindSpeedWithBearingOnStarboardTackFor(BoatClass boatClass, Speed windSpeed) throws NotEnoughDataHasBeenAddedException { int startAngleInclusive = 91; int endAngleExclusive = 180; SpeedWithBearingWithConfidence speedWithBearing = estimateAnglePeakAndAverageSpeed(boatClass, windSpeed, startAngleInclusive, - endAngleExclusive, useLinReg); + endAngleExclusive); return speedWithBearing; } @Override - public SpeedWithBearingWithConfidence getAverageDownwindSpeedWithBearingOnPortTackFor(BoatClass boatClass, Speed windSpeed, boolean useLinReg) + public SpeedWithBearingWithConfidence getAverageDownwindSpeedWithBearingOnPortTackFor(BoatClass boatClass, Speed windSpeed) throws NotEnoughDataHasBeenAddedException { int startAngleInclusive = 181; int endAngleExclusive = 270; SpeedWithBearingWithConfidence speedWithBearing = estimateAnglePeakAndAverageSpeed(boatClass, windSpeed, startAngleInclusive, - endAngleExclusive, useLinReg); + endAngleExclusive); return speedWithBearing; } @Override - public SpeedWithBearingWithConfidence getAverageUpwindSpeedWithBearingOnPortTackFor(BoatClass boatClass, - Speed windSpeed, boolean useLinReg) throws NotEnoughDataHasBeenAddedException { + public SpeedWithBearingWithConfidence getAverageUpwindSpeedWithBearingOnPortTackFor(BoatClass boatClass, Speed windSpeed) + throws NotEnoughDataHasBeenAddedException { int startAngleInclusive = 271; int endAngleExclusive = 360; SpeedWithBearingWithConfidence speedWithBearing = estimateAnglePeakAndAverageSpeed(boatClass, windSpeed, - startAngleInclusive, endAngleExclusive, useLinReg); + endAngleExclusive); return speedWithBearing; } private SpeedWithBearingWithConfidence estimateAnglePeakAndAverageSpeed(BoatClass boatClass, Speed windSpeed, - int startAngleInclusive, int endAngleExclusive, boolean useLinearRegression) throws NotEnoughDataHasBeenAddedException { + int startAngleInclusive, int endAngleExclusive) throws NotEnoughDataHasBeenAddedException { int[] dataCountPerAngle = getDataCountArray(boatClass, windSpeed, startAngleInclusive, endAngleExclusive); double estimatedPeak = estimatePeak(boatClass, windSpeed, startAngleInclusive, endAngleExclusive, dataCountPerAngle); double convertedAngleIfOver180 = convertAngleIfNecessary(estimatedPeak); SpeedWithConfidence averagedSpeedWithConfidence = estimateSpeed(boatClass, windSpeed, convertedAngleIfOver180, useLinearRegression); + convertedAngleIfOver180); double originConfidence = averagedSpeedWithConfidence.getConfidence(); double overallConfidence = (originConfidence + calcDataCountConfidence(dataCountPerAngle, estimatedPeak)) / 2; Bearing bearing = new DegreeBearingImpl(convertedAngleIfOver180); @@ -110,10 +111,9 @@ public class PolarSheetAnalyzerImpl implements PolarSheetAnalyzer { return convertedAngleIfOver180; } - private SpeedWithConfidence estimateSpeed(BoatClass boatClass, Speed windSpeed, double estimatedPeak, - boolean useLinearRegression) throws NotEnoughDataHasBeenAddedException { + private SpeedWithConfidence estimateSpeed(BoatClass boatClass, Speed windSpeed, double estimatedPeak) throws NotEnoughDataHasBeenAddedException { SpeedWithConfidence speed = polarDataService.getSpeed(boatClass, windSpeed, new DegreeBearingImpl( - estimatedPeak), useLinearRegression); + estimatedPeak)); return speed; } diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/NoCacheEntryException.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/NoCacheEntryException.java deleted file mode 100644 index b4cfec4d06a..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/NoCacheEntryException.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.sap.sailing.polars.caching; - -import java.util.Set; - -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.polars.data.PolarFix; - -public class NoCacheEntryException extends Exception { - - private static final long serialVersionUID = 5547683568438235668L; - private final Set notCached; - private final Set resultList; - - public NoCacheEntryException(Set notCached, Set resultList) { - this.notCached = notCached; - this.resultList = resultList; - } - - public Set getNotCached() { - return notCached; - } - - public Set getCachedResultList() { - return resultList; - } - -} diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarFixCache.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarFixCache.java deleted file mode 100644 index c9306b315f2..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarFixCache.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.sap.sailing.polars.caching; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Executor; - -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.polars.data.PolarFix; -import com.sap.sailing.util.SmartFutureCache; - -public class PolarFixCache extends - SmartFutureCache>, PolarFixCacheRaceInterval> { - - private final List cacheUpdateDoneListeners = new ArrayList(); - - public PolarFixCache(Executor executor) { - super(new PolarFixCacheUpdater(executor), "polarFixCache"); - } - - @Override - protected void cache(BoatClass key, Map> value) { - super.cache(key, value); - synchronized (cacheUpdateDoneListeners) { - for (PolarFixCacheUpdateDoneListener listener : cacheUpdateDoneListeners) { - listener.cacheUpdateDoneForBoatClass(key); - } - } - } - - public void addListener(PolarFixCacheUpdateDoneListener listener) { - synchronized (cacheUpdateDoneListeners) { - cacheUpdateDoneListeners.add(listener); - } - } - - public void removeListener(PolarFixCacheUpdateDoneListener listener) { - synchronized (cacheUpdateDoneListeners) { - if (cacheUpdateDoneListeners.contains(listener)) { - cacheUpdateDoneListeners.remove(listener); - } - } - } - - public Set getFixesForTrackedRaces(Set trackedRaces) throws NoCacheEntryException { - Set resultList = new HashSet(); - Set notCached = new HashSet(); - for (TrackedRace trackedRace : trackedRaces) { - Map> result = get(trackedRace.getRace().getBoatClass(), false); - List resultForRace = result.get(trackedRace.getRaceIdentifier()); - if (resultForRace == null) { - notCached.add(trackedRace); - } else { - resultList.addAll(resultForRace); - } - } - if (notCached.size() > 0) { - throw new NoCacheEntryException(notCached, resultList); - } - return resultList; - } - -} diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarFixCacheRaceInterval.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarFixCacheRaceInterval.java deleted file mode 100644 index ed6717bc50f..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarFixCacheRaceInterval.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.sap.sailing.polars.caching; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.polars.aggregation.PolarFixRaceInterval; -import com.sap.sailing.util.SmartFutureCache.UpdateInterval; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; - -public class PolarFixCacheRaceInterval implements UpdateInterval, PolarFixRaceInterval { - - private final Map>> competitorAndTimepointsForRace; - - public PolarFixCacheRaceInterval( - Map>> competitorAndTimepointsForRace) { - this.competitorAndTimepointsForRace = competitorAndTimepointsForRace; - } - - @Override - public Map>> getCompetitorAndTimepointsForRace() { - return competitorAndTimepointsForRace; - } - - @Override - public PolarFixCacheRaceInterval join(PolarFixCacheRaceInterval otherUpdateInterval) { - Map>> joinedInterval = new HashMap>>(); - Set racesContainedInEitherMap = new HashSet(); - for (TrackedRace race : competitorAndTimepointsForRace.keySet()) { - racesContainedInEitherMap.add(race); - } - Map>> otherUpdateIntervalInExplicitForm = otherUpdateInterval - .getCompetitorAndTimepointsForRace(); - for (TrackedRace race : otherUpdateIntervalInExplicitForm.keySet()) { - racesContainedInEitherMap.add(race); - } - - for (TrackedRace race : racesContainedInEitherMap) { - HashMap> joinedMap = new HashMap>(); - Map> mapOfTimpointCompetitorPairs = competitorAndTimepointsForRace - .get(race); - if (mapOfTimpointCompetitorPairs != null) { - joinedMap.putAll(mapOfTimpointCompetitorPairs); - } - Map> mapOfOtherTimpointCompetitorPairs = otherUpdateIntervalInExplicitForm - .get(race); - if (mapOfOtherTimpointCompetitorPairs != null) { - mergeMap(joinedMap, mapOfOtherTimpointCompetitorPairs); - } - joinedInterval.put(race, joinedMap); - } - return new PolarFixCacheRaceInterval(joinedInterval); - } - - private void mergeMap(HashMap> joinedMap, - Map> mapOfOtherTimpointCompetitorPairs) { - for (Entry> otherEntry : mapOfOtherTimpointCompetitorPairs.entrySet()) { - - Competitor competitor = otherEntry.getKey(); - Pair otherValue = otherEntry.getValue(); - Pair existingValue = joinedMap.get(competitor); - if (existingValue != null) { - Pair joinedTimepointInterval = joinTimepointIntervals(existingValue, otherValue); - joinedMap.put(competitor, joinedTimepointInterval); - } else { - joinedMap.put(competitor, otherValue); - } - - } - } - - /** - * This method ignores a possible gap between the two intervals. - * - * @param existingValue - * @param otherValue - * @return - */ - private Pair joinTimepointIntervals(Pair existingValue, - Pair otherValue) { - TimePoint startExisting = existingValue.getA(); - TimePoint endExisting = existingValue.getB(); - TimePoint startOther = otherValue.getA(); - TimePoint endOther = otherValue.getB(); - - TimePoint startNew = startExisting.before(startOther) ? startExisting : startOther; - TimePoint endNew = endExisting.after(endOther) ? endExisting : endOther; - - return new Pair(startNew, endNew); - } - -} \ No newline at end of file diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarFixCacheUpdateDoneListener.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarFixCacheUpdateDoneListener.java deleted file mode 100644 index 75a32432e04..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarFixCacheUpdateDoneListener.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.sap.sailing.polars.caching; - -import com.sap.sailing.domain.base.BoatClass; - -public interface PolarFixCacheUpdateDoneListener { - - void cacheUpdateDoneForBoatClass(BoatClass key); - -} diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarFixCacheUpdater.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarFixCacheUpdater.java deleted file mode 100644 index db782760f85..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarFixCacheUpdater.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.sap.sailing.polars.caching; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.Executor; - -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.impl.PolarSheetGenerationSettingsImpl; -import com.sap.sailing.polars.aggregation.PolarFixAggregator; -import com.sap.sailing.polars.data.PolarFix; -import com.sap.sailing.util.SmartFutureCache.CacheUpdater; - -public class PolarFixCacheUpdater implements - CacheUpdater>, PolarFixCacheRaceInterval> { - - private final Executor executor; - - public PolarFixCacheUpdater(Executor executor) { - this.executor = executor; - } - - @Override - public Map> computeCacheUpdate(BoatClass key, - PolarFixCacheRaceInterval updateInterval) throws Exception { - PolarFixAggregator aggregator = new PolarFixAggregator(updateInterval, - PolarSheetGenerationSettingsImpl.createStandardPolarSettings(), executor); - Thread.sleep(updateInterval.getCompetitorAndTimepointsForRace().keySet().iterator().next() - .getMillisecondsOverWhichToAverageSpeed() / 2); - aggregator.startPolarFixAggregation(); - - return aggregator.get(); - } - - @Override - public Map> provideNewCacheValue(BoatClass key, - Map> oldCacheValue, - Map> computedCacheUpdate, PolarFixCacheRaceInterval updateInterval) { - Map> newCacheValue = new HashMap>(); - if (oldCacheValue != null) { - newCacheValue.putAll(oldCacheValue); - } - for (Entry> newEntry : computedCacheUpdate.entrySet()) { - List oldList = newCacheValue.get(newEntry.getKey()); - if (oldList != null) { - oldList.addAll(newEntry.getValue()); - } else { - newCacheValue.put(newEntry.getKey(), newEntry.getValue()); - } - } - return newCacheValue; - } - -} diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarSheetPerBoatClassCache.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarSheetPerBoatClassCache.java deleted file mode 100644 index 94e4fa0a4c8..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarSheetPerBoatClassCache.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.sap.sailing.polars.caching; - -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.common.PolarSheetsData; -import com.sap.sailing.polars.PolarDataService; -import com.sap.sailing.util.SmartFutureCache; - -public class PolarSheetPerBoatClassCache extends - SmartFutureCache - implements PolarFixCacheUpdateDoneListener { - - public PolarSheetPerBoatClassCache(PolarDataService polarDataService) { - super(new PolarSheetPerBoatClassCacheUpdater(polarDataService), "PolarSheetPerBoatClassCache"); - } - - @Override - public void cacheUpdateDoneForBoatClass(BoatClass key) { - triggerUpdate(key, new EmptyUpdateInterval()); - } - -} diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarSheetPerBoatClassCacheUpdater.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarSheetPerBoatClassCacheUpdater.java deleted file mode 100644 index fb94b05ea47..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/caching/PolarSheetPerBoatClassCacheUpdater.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.sap.sailing.polars.caching; - -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.common.PolarSheetGenerationSettings; -import com.sap.sailing.domain.common.PolarSheetsData; -import com.sap.sailing.domain.common.impl.PolarSheetGenerationSettingsImpl; -import com.sap.sailing.polars.PolarDataService; -import com.sap.sailing.polars.generation.PolarSheetGenerator; -import com.sap.sailing.util.SmartFutureCache.CacheUpdater; -import com.sap.sailing.util.SmartFutureCache.EmptyUpdateInterval; - -public class PolarSheetPerBoatClassCacheUpdater implements - CacheUpdater { - - private final PolarDataService polarDataService; - - public PolarSheetPerBoatClassCacheUpdater(PolarDataService polarDataService) { - this.polarDataService = polarDataService; - } - - @Override - public PolarSheetsData computeCacheUpdate(BoatClass key, EmptyUpdateInterval updateInterval) throws Exception { - PolarSheetGenerationSettings settings = PolarSheetGenerationSettingsImpl.createStandardPolarSettings(); - PolarSheetGenerator generator = new PolarSheetGenerator(polarDataService.getPolarFixesForBoatClass(key), - settings); - PolarSheetsData generationResult = generator.generate(); - return generationResult; - } - - @Override - public PolarSheetsData provideNewCacheValue(BoatClass key, PolarSheetsData oldCacheValue, - PolarSheetsData computedCacheUpdate, EmptyUpdateInterval updateInterval) { - return computedCacheUpdate; - } - -} diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/impl/PolarDataServiceImpl.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/impl/PolarDataServiceImpl.java old mode 100644 new mode 100755 index baaed92af7d..324e7a70695 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/impl/PolarDataServiceImpl.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/impl/PolarDataServiceImpl.java @@ -1,8 +1,5 @@ package com.sap.sailing.polars.impl; -import java.util.HashSet; -import java.util.List; -import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; @@ -12,10 +9,10 @@ import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.SpeedWithBearingWithConfidence; import com.sap.sailing.domain.base.SpeedWithConfidence; import com.sap.sailing.domain.common.Bearing; +import com.sap.sailing.domain.common.BoatClassMasterdata; import com.sap.sailing.domain.common.LegType; import com.sap.sailing.domain.common.PolarSheetGenerationSettings; import com.sap.sailing.domain.common.PolarSheetsData; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.Speed; import com.sap.sailing.domain.common.Tack; import com.sap.sailing.domain.tracking.GPSFixMoving; @@ -23,10 +20,6 @@ import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.polars.PolarDataService; import com.sap.sailing.polars.aggregation.PolarFixAggregator; import com.sap.sailing.polars.aggregation.SimplePolarFixRaceInterval; -import com.sap.sailing.polars.analysis.PolarSheetAnalyzer; -import com.sap.sailing.polars.analysis.impl.PolarSheetAnalyzerImpl; -import com.sap.sailing.polars.caching.PolarFixCache; -import com.sap.sailing.polars.caching.PolarSheetPerBoatClassCache; import com.sap.sailing.polars.data.PolarFix; import com.sap.sailing.polars.generation.PolarSheetGenerator; import com.sap.sailing.polars.mining.PolarDataMiner; @@ -43,48 +36,32 @@ import com.sap.sailing.util.SmartFutureCache; */ public class PolarDataServiceImpl implements PolarDataService { - private final PolarFixCache polarFixCache; - private final PolarSheetPerBoatClassCache polarSheetPerBoatClassCache; - - private final PolarSheetAnalyzer polarSheetAnalyzer; - private final PolarDataMiner polarDataMiner; public PolarDataServiceImpl(Executor executor) { - this.polarFixCache = new PolarFixCache(executor); - this.polarSheetPerBoatClassCache = new PolarSheetPerBoatClassCache(this); - polarFixCache.addListener(polarSheetPerBoatClassCache); - this.polarSheetAnalyzer = new PolarSheetAnalyzerImpl(this); this.polarDataMiner = new PolarDataMiner(); } @Override - public SpeedWithConfidence getSpeed(BoatClass boatClass, Speed windSpeed, Bearing bearingToTheWind, - boolean useLinearRegression) throws NotEnoughDataHasBeenAddedException { - return polarDataMiner.estimateBoatSpeed(boatClass, windSpeed, bearingToTheWind, useLinearRegression); - } - - @Override - public SpeedWithBearingWithConfidence getAverageSpeedWithBearing(BoatClass boatClass, Speed windSpeed, - LegType legType, Tack tack) throws NotEnoughDataHasBeenAddedException { - return getAverageSpeedWithBearing(boatClass, windSpeed, legType, tack, /* useLinearRegression */ true); + public SpeedWithConfidence getSpeed(BoatClass boatClass, Speed windSpeed, Bearing bearingToTheWind) throws NotEnoughDataHasBeenAddedException { + return polarDataMiner.estimateBoatSpeed(boatClass, windSpeed, bearingToTheWind); } @Override public SpeedWithBearingWithConfidence getAverageSpeedWithBearing(BoatClass boatClass, - Speed windSpeed, LegType legType, Tack tack, boolean useLinearRegression) throws NotEnoughDataHasBeenAddedException { + Speed windSpeed, LegType legType, Tack tack) throws NotEnoughDataHasBeenAddedException { SpeedWithBearingWithConfidence speedWithBearing = null; if (tack.equals(Tack.STARBOARD)) { if (legType.equals(LegType.UPWIND)) { - speedWithBearing = polarSheetAnalyzer.getAverageUpwindSpeedWithBearingOnStarboardTackFor(boatClass, windSpeed, useLinearRegression); + speedWithBearing = polarDataMiner.getAverageUpwindSpeedWithBearingOnStarboardTackFor(boatClass, windSpeed); } else if (legType.equals(LegType.DOWNWIND)) { - speedWithBearing = polarSheetAnalyzer.getAverageDownwindSpeedWithBearingOnStarboardTackFor(boatClass, windSpeed, useLinearRegression); + speedWithBearing = polarDataMiner.getAverageDownwindSpeedWithBearingOnStarboardTackFor(boatClass, windSpeed); } } else if (tack.equals(Tack.PORT)) { if (legType.equals(LegType.UPWIND)) { - return polarSheetAnalyzer.getAverageUpwindSpeedWithBearingOnPortTackFor(boatClass, windSpeed, useLinearRegression); + return polarDataMiner.getAverageUpwindSpeedWithBearingOnPortTackFor(boatClass, windSpeed); } else if (legType.equals(LegType.DOWNWIND)) { - return polarSheetAnalyzer.getAverageDownwindSpeedWithBearingOnPortTackFor(boatClass, windSpeed, useLinearRegression); + return polarDataMiner.getAverageDownwindSpeedWithBearingOnPortTackFor(boatClass, windSpeed); } } return speedWithBearing; @@ -95,69 +72,28 @@ public class PolarDataServiceImpl implements PolarDataService { public PolarSheetsData generatePolarSheet(Set trackedRaces, PolarSheetGenerationSettings settings, Executor executor) throws InterruptedException, ExecutionException { Set fixes; - // If settings are default, look into cache - // if (settings.areDefault()) { - // try { - // fixes = polarFixCache.getFixesForTrackedRaces(trackedRaces); - // } catch (NoCacheEntryException e) { - // // If there is no cache entry for at least one of the races: Aggregate for non-cached races. - // fixes = e.getCachedResultList(); - // PolarFixAggregator aggregator = new PolarFixAggregator( - // new SimplePolarFixRaceInterval(e.getNotCached()), - // settings, executor); - // aggregator.startPolarFixAggregation(); - // fixes.addAll(aggregator.getAggregationResultAsSingleList()); - // } - // } else { PolarFixAggregator aggregator = new PolarFixAggregator(new SimplePolarFixRaceInterval(trackedRaces), settings, executor); aggregator.startPolarFixAggregation(); fixes = aggregator.getAggregationResultAsSingleList(); - // } PolarSheetGenerator generator = new PolarSheetGenerator(fixes, settings); return generator.generate(); } - @Override - public void newRaceFinishedTracking(TrackedRace trackedRace) { - // TODO add a similar listening method, that deletes all cached data on removal of race - // HashSet set = new HashSet(); - // set.add(trackedRace); - // polarFixCache.triggerUpdate(trackedRace.getRace().getBoatClass(), new PolarFixCacheRaceInterval(set)); - } - - @Override - public Set getPolarFixesForBoatClass(BoatClass key) { - Map> fixesInMap = polarFixCache.get(key, false); - Set resultSet = new HashSet(); - for (List value : fixesInMap.values()) { - resultSet.addAll(value); - } - return resultSet; - } - @Override public PolarSheetsData getPolarSheetForBoatClass(BoatClass boatClass) { return polarDataMiner.createFullSheetForBoatClass(boatClass); - //return polarSheetPerBoatClassCache.get(boatClass, false); } @Override - public Set getAllBoatClassesWithPolarSheetsAvailable() { + public Set getAllBoatClassesWithPolarSheetsAvailable() { return polarDataMiner.getAvailableBoatClasses(); - //return polarSheetPerBoatClassCache.keySet(); } @Override public void competitorPositionChanged(final GPSFixMoving fix, final Competitor competitor, final TrackedRace createdTrackedRace) { polarDataMiner.addFix(fix, competitor, createdTrackedRace); - // TODO build datamining pipeline for the cache - - // PolarFixCacheRaceInterval interval = new PolarFixCacheRaceInterval(createIntervalSpecification( - // createdTrackedRace, competitor, timePoint)); - // polarFixCache.triggerUpdate(createdTrackedRace.getRace().getBoatClass(), interval); - } @Override @@ -165,15 +101,4 @@ public class PolarDataServiceImpl implements PolarDataService { return polarDataMiner.getDataCountsForWindSpeed(boatClass, windSpeed, startAngleInclusive, endAngleExclusive); } - // private Map>> createIntervalSpecification( - // TrackedRace createdTrackedRace, Competitor competitor, TimePoint timePoint) { - // HashMap>> result = new HashMap>>(); - // HashMap> competitorMap = new HashMap>(); - // competitorMap.put(competitor, new Pair(timePoint, timePoint)); - // result.put(createdTrackedRace, competitorMap); - // return result; - // } - } diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/AverageAngleContainer.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/AverageAngleContainer.java new file mode 100644 index 00000000000..cc57cab1a0c --- /dev/null +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/AverageAngleContainer.java @@ -0,0 +1,60 @@ +package com.sap.sailing.polars.mining; + +import java.util.HashMap; +import java.util.Map; + +import com.sap.sailing.domain.common.BoatClassMasterdata; +import com.sap.sailing.domain.common.Speed; +import com.sap.sse.common.Util.Triple; +import com.sap.sse.datamining.data.Cluster; +import com.sap.sse.datamining.data.ClusterGroup; + +public class AverageAngleContainer { + + private ClusterGroup speedClusterGroup; + + private Map, Triple>> dataCountAndAngleSumMap; + + public AverageAngleContainer(ClusterGroup speedClusterGroup) { + this.speedClusterGroup = speedClusterGroup; + dataCountAndAngleSumMap = new HashMap<>(); + } + + public void addFix(BoatClassMasterdata boatClassMasterdata, Speed windSpeed, + int roundedAngle) { + Cluster windCluster = speedClusterGroup.getClusterFor(windSpeed); + if (!dataCountAndAngleSumMap.containsKey(boatClassMasterdata)) { + dataCountAndAngleSumMap.put(boatClassMasterdata, new HashMap<>()); + } + Map, Triple> boatClassMap = dataCountAndAngleSumMap.get(boatClassMasterdata); + if(!boatClassMap.containsKey(windCluster)) { + boatClassMap.put(windCluster, createInitialTriple()); + } + Triple triple = boatClassMap.get(windCluster); + Integer dataCount = triple.getA(); + Double sum = triple.getB(); + dataCount = dataCount + 1; + sum = sum + roundedAngle; + double average = sum / (double) dataCount; + + boatClassMap.put(windCluster, new Triple(dataCount, sum, average)); + } + + private Triple createInitialTriple() { + return new Triple(0, 0.0, 0.0); + } + + Double getAverageAngle(BoatClassMasterdata boatClassMasterdata, Speed windSpeed) { + Double result = null; + if (dataCountAndAngleSumMap.containsKey(boatClassMasterdata)) { + Map, Triple> boatClassMap = dataCountAndAngleSumMap.get(boatClassMasterdata); + Cluster windCluster = speedClusterGroup.getClusterFor(windSpeed); + if(boatClassMap.containsKey(windCluster)) { + Triple triple = boatClassMap.get(windCluster); + result = triple.getC(); + } + } + return result; + } + +} diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/GPSFixMovingWithPolarContext.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/GPSFixMovingWithPolarContext.java index c60cd3f04b7..1ab80d5d43d 100644 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/GPSFixMovingWithPolarContext.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/GPSFixMovingWithPolarContext.java @@ -3,10 +3,10 @@ package com.sap.sailing.polars.mining; import java.util.HashSet; import java.util.Set; -import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.SpeedWithBearingWithConfidence; import com.sap.sailing.domain.common.Bearing; +import com.sap.sailing.domain.common.BoatClassMasterdata; import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.Speed; import com.sap.sailing.domain.common.SpeedWithBearing; @@ -93,8 +93,8 @@ public class GPSFixMovingWithPolarContext implements PolarClusterKey { } @Override - public BoatClass getBoatClass() { - return race.getRace().getBoatClass(); + public BoatClassMasterdata getBoatClassMasterData() { + return BoatClassMasterdata.resolveBoatClass(race.getRace().getBoatClass().getName()); } private Set collectWindSourcesToIgnoreForBearing() { diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/IncrementalRegressionProcessor.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/IncrementalRegressionProcessor.java old mode 100644 new mode 100755 index 0a1baefb36b..9c560d57b67 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/IncrementalRegressionProcessor.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/IncrementalRegressionProcessor.java @@ -9,13 +9,19 @@ import java.util.logging.Logger; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.SpeedWithBearingWithConfidence; import com.sap.sailing.domain.base.SpeedWithConfidence; +import com.sap.sailing.domain.base.impl.SpeedWithBearingWithConfidenceImpl; import com.sap.sailing.domain.base.impl.SpeedWithConfidenceImpl; import com.sap.sailing.domain.common.Bearing; +import com.sap.sailing.domain.common.BoatClassMasterdata; import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.Speed; +import com.sap.sailing.domain.common.SpeedWithBearing; import com.sap.sailing.domain.common.confidence.BearingWithConfidence; +import com.sap.sailing.domain.common.impl.DegreeBearingImpl; import com.sap.sailing.domain.common.impl.KnotSpeedImpl; +import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; import com.sap.sailing.domain.tracking.WindWithConfidence; +import com.sap.sailing.polars.analysis.PolarSheetAnalyzer; import com.sap.sailing.polars.regression.BoatSpeedEstimator; import com.sap.sailing.polars.regression.NotEnoughDataHasBeenAddedException; import com.sap.sse.common.TimePoint; @@ -28,18 +34,28 @@ import com.sap.sse.datamining.factories.GroupKeyFactory; import com.sap.sse.datamining.impl.components.GroupedDataEntry; import com.sap.sse.datamining.shared.GroupKey; -public class IncrementalRegressionProcessor implements Processor,Void> { - +public class IncrementalRegressionProcessor implements Processor, Void>, + PolarSheetAnalyzer { + private static final Logger logger = Logger.getLogger(IncrementalRegressionProcessor.class.getName()); private final Map boatSpeedEstimators = new HashMap(); private final ClusterGroup speedClusterGroup; - - private final Set availableBoatClasses = new HashSet<>(); + + private final Set availableBoatClasses = new HashSet<>(); + + private final AverageAngleContainer upwindStarboardAverageAngleContainer; + private final AverageAngleContainer downwindStarboardAverageAngleContainer; + private final AverageAngleContainer upwindPortAverageAngleContainer; + private final AverageAngleContainer downwindPortAverageAngleContainer; public IncrementalRegressionProcessor(ClusterGroup speedClusterGroup) { this.speedClusterGroup = speedClusterGroup; + this.upwindStarboardAverageAngleContainer = new AverageAngleContainer(speedClusterGroup); + this.downwindStarboardAverageAngleContainer = new AverageAngleContainer(speedClusterGroup); + this.upwindPortAverageAngleContainer = new AverageAngleContainer(speedClusterGroup); + this.downwindPortAverageAngleContainer = new AverageAngleContainer(speedClusterGroup); } @Override @@ -49,7 +65,7 @@ public class IncrementalRegressionProcessor implements Processor angleToTheWind = fix.getAngleToTheWind(); - + WindWithConfidence> windSpeed = fix.getWindSpeed(); - + SpeedWithBearingWithConfidence boatSpeedWithConfidence = fix.getBoatSpeed(); - - - //Only add GPS data if speeds and angles are not null, else do nothing! + + // Only add GPS data if speeds and angles are not null, else do nothing! if (angleToTheWind != null && windSpeed != null && boatSpeedWithConfidence != null) { - + fillAverageAngleContainer(fix, element, windSpeed); WindWithConfidence> windWithConfidenceForSpeed = windSpeed; - + double confidenceForWindSpeed = windWithConfidenceForSpeed.getConfidence(); double confidenceForWindBearing = angleToTheWind.getConfidence(); double confidenceForBoatSpeed = boatSpeedWithConfidence.getConfidence(); double averagedConfidence = (confidenceForBoatSpeed + confidenceForWindBearing + confidenceForWindSpeed) / 3; - boatSpeedEstimator.addData(windWithConfidenceForSpeed.getObject().getKnots(), angleToTheWind.getObject() - .getDegrees(), boatSpeedWithConfidence.getObject().getKnots(), averagedConfidence); - } + boatSpeedEstimator.addData(boatSpeedWithConfidence.getObject().getKnots(), averagedConfidence); + } + } + + private void fillAverageAngleContainer(GPSFixMovingWithPolarContext fix, + GroupedDataEntry element, + WindWithConfidence> windSpeed) { + int roundedAngle = fix.getRoundedAngleToTheWind().getAngle(); + if (roundedAngle < -90) { + downwindPortAverageAngleContainer.addFix(element.getDataEntry().getBoatClassMasterData(), + windSpeed.getObject(), roundedAngle); + } else if (roundedAngle < 0) { + upwindPortAverageAngleContainer.addFix(element.getDataEntry().getBoatClassMasterData(), + windSpeed.getObject(), roundedAngle); + } else if (roundedAngle > 0) { + upwindStarboardAverageAngleContainer.addFix(element.getDataEntry().getBoatClassMasterData(), + windSpeed.getObject(), roundedAngle); + } else if (roundedAngle > 90) { + downwindStarboardAverageAngleContainer.addFix(element.getDataEntry().getBoatClassMasterData(), + windSpeed.getObject(), roundedAngle); + } } @Override @@ -109,9 +142,9 @@ public class IncrementalRegressionProcessor implements Processor, Integer> estimateBoatSpeed(final BoatClass boatClass, final Speed windSpeed, + final Bearing angleToTheWind) throws NotEnoughDataHasBeenAddedException { + int dataCount = 0; PolarClusterKey key = new PolarClusterKey() { @Override public RoundedAngleToTheWind getRoundedAngleToTheWind() { @@ -119,8 +152,8 @@ public class IncrementalRegressionProcessor implements Processor( @@ -154,7 +187,7 @@ public class IncrementalRegressionProcessor implements Processor getAvailableBoatClasses() { + public Set getAvailableBoatClasses() { return availableBoatClasses; } @@ -170,4 +203,48 @@ public class IncrementalRegressionProcessor implements Processor getAverageUpwindSpeedWithBearingOnStarboardTackFor(BoatClass boatClass, + Speed windSpeed) throws NotEnoughDataHasBeenAddedException { + Double averageAngle = upwindStarboardAverageAngleContainer.getAverageAngle( + BoatClassMasterdata.resolveBoatClass(boatClass.getName()), windSpeed); + return estimateSpeedForAverageAngle(boatClass, windSpeed, averageAngle); + } + + private SpeedWithBearingWithConfidence estimateSpeedForAverageAngle(BoatClass boatClass, Speed windSpeed, + Double averageAngle) throws NotEnoughDataHasBeenAddedException { + if (averageAngle == null) { + throw new NotEnoughDataHasBeenAddedException(); + } + DegreeBearingImpl angleToTheWind = new DegreeBearingImpl(averageAngle); + SpeedWithConfidence estimatedSpeed = estimateBoatSpeed(boatClass, windSpeed, angleToTheWind).getA(); + SpeedWithBearing speedWithBearing = new KnotSpeedWithBearingImpl(estimatedSpeed.getObject().getKnots(), + angleToTheWind); + return new SpeedWithBearingWithConfidenceImpl(speedWithBearing, estimatedSpeed.getConfidence(), null); + } + + @Override + public SpeedWithBearingWithConfidence getAverageDownwindSpeedWithBearingOnStarboardTackFor( + BoatClass boatClass, Speed windSpeed) throws NotEnoughDataHasBeenAddedException { + Double averageAngle = downwindStarboardAverageAngleContainer.getAverageAngle( + BoatClassMasterdata.resolveBoatClass(boatClass.getName()), windSpeed); + return estimateSpeedForAverageAngle(boatClass, windSpeed, averageAngle); + } + + @Override + public SpeedWithBearingWithConfidence getAverageUpwindSpeedWithBearingOnPortTackFor(BoatClass boatClass, + Speed windSpeed) throws NotEnoughDataHasBeenAddedException { + Double averageAngle = upwindPortAverageAngleContainer.getAverageAngle( + BoatClassMasterdata.resolveBoatClass(boatClass.getName()), windSpeed); + return estimateSpeedForAverageAngle(boatClass, windSpeed, averageAngle); + } + + @Override + public SpeedWithBearingWithConfidence getAverageDownwindSpeedWithBearingOnPortTackFor(BoatClass boatClass, + Speed windSpeed) throws NotEnoughDataHasBeenAddedException { + Double averageAngle = downwindPortAverageAngleContainer.getAverageAngle( + BoatClassMasterdata.resolveBoatClass(boatClass.getName()), windSpeed); + return estimateSpeedForAverageAngle(boatClass, windSpeed, averageAngle); + } + } diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarClusterKey.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarClusterKey.java index 51e89b3298d..ca963cca24c 100644 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarClusterKey.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarClusterKey.java @@ -1,6 +1,6 @@ package com.sap.sailing.polars.mining; -import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.common.BoatClassMasterdata; import com.sap.sailing.domain.common.Speed; import com.sap.sse.datamining.data.Cluster; import com.sap.sse.datamining.shared.annotations.Dimension; @@ -22,6 +22,6 @@ public interface PolarClusterKey { Cluster getWindSpeedCluster(); @Dimension(messageKey = "boatClass") - BoatClass getBoatClass(); + BoatClassMasterdata getBoatClassMasterData(); } \ No newline at end of file diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarDataDimensionCollectionFactory.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarDataDimensionCollectionFactory.java index 8ded454c339..c8a1afbd380 100644 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarDataDimensionCollectionFactory.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarDataDimensionCollectionFactory.java @@ -3,7 +3,7 @@ package com.sap.sailing.polars.mining; import java.util.ArrayList; import java.util.Collection; -import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.common.BoatClassMasterdata; import com.sap.sse.datamining.factories.FunctionFactory; import com.sap.sse.datamining.functions.Function; @@ -17,8 +17,8 @@ public class PolarDataDimensionCollectionFactory { new Class[0])); Function windSpeedFunction = functionFactory.createMethodWrappingFunction(PolarClusterKey.class .getMethod("getWindSpeedCluster", new Class[0])); - Function boatClassFunction = functionFactory.createMethodWrappingFunction(PolarClusterKey.class - .getMethod("getBoatClass", new Class[0])); + Function boatClassFunction = functionFactory.createMethodWrappingFunction(PolarClusterKey.class + .getMethod("getBoatClassMasterData", new Class[0])); dimensions.add(boatClassFunction); dimensions.add(angleFunction); diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarDataMiner.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarDataMiner.java old mode 100644 new mode 100755 index a02ed90d8f2..6bc9af00f9c --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarDataMiner.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarDataMiner.java @@ -12,9 +12,11 @@ import java.util.concurrent.TimeUnit; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.SpeedWithBearingWithConfidence; import com.sap.sailing.domain.base.SpeedWithConfidence; import com.sap.sailing.domain.base.impl.SpeedWithConfidenceImpl; import com.sap.sailing.domain.common.Bearing; +import com.sap.sailing.domain.common.BoatClassMasterdata; import com.sap.sailing.domain.common.PolarSheetGenerationSettings; import com.sap.sailing.domain.common.PolarSheetsData; import com.sap.sailing.domain.common.PolarSheetsHistogramData; @@ -28,6 +30,7 @@ import com.sap.sailing.domain.common.impl.WindSteppingWithMaxDistance; import com.sap.sailing.domain.tracking.GPSFixMoving; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.polars.mining.IncrementalRegressionProcessor.SpeedWithConfidenceAndDataCount; +import com.sap.sailing.polars.analysis.PolarSheetAnalyzer; import com.sap.sailing.polars.regression.NotEnoughDataHasBeenAddedException; import com.sap.sse.datamining.components.Processor; import com.sap.sse.datamining.data.ClusterGroup; @@ -36,7 +39,7 @@ import com.sap.sse.datamining.impl.components.GroupedDataEntry; import com.sap.sse.datamining.impl.components.ParallelFilteringProcessor; import com.sap.sse.datamining.impl.components.ParallelMultiDimensionsValueNestingGroupingProcessor; -public class PolarDataMiner { +public class PolarDataMiner implements PolarSheetAnalyzer { private static final int THREAD_POOL_SIZE = Math.max(Runtime.getRuntime().availableProcessors(), 3); private static final ThreadPoolExecutor executor = createExecutor(); @@ -117,10 +120,9 @@ public class PolarDataMiner { * @return * @throws NotEnoughDataHasBeenAddedException */ - public SpeedWithConfidence estimateBoatSpeed(BoatClass boatClass, Speed windSpeed, Bearing angleToTheWind, - boolean useLinearRegression) + public SpeedWithConfidence estimateBoatSpeed(BoatClass boatClass, Speed windSpeed, Bearing angleToTheWind) throws NotEnoughDataHasBeenAddedException { - return incrementalRegressionProcessor.estimateBoatSpeed(boatClass, windSpeed, angleToTheWind, useLinearRegression).getSpeedWithConfidence(); + return incrementalRegressionProcessor.estimateBoatSpeed(boatClass, windSpeed, angleToTheWind).getSpeedWithConfidence(); } @@ -144,7 +146,7 @@ public class PolarDataMiner { try { int convertedAngle = convertAngleIfNecessary(angle); speedWithConfidenceAndDataCount = incrementalRegressionProcessor.estimateBoatSpeed(boatClass, - new KnotSpeedImpl(windSpeed), new DegreeBearingImpl(convertedAngle), true); + new KnotSpeedImpl(windSpeed), new DegreeBearingImpl(convertedAngle)); } catch (NotEnoughDataHasBeenAddedException e) { // No data so put in a 0 speed with 0 confidence speedWithConfidenceAndDataCount = new SpeedWithConfidenceAndDataCount( @@ -204,7 +206,7 @@ public class PolarDataMiner { - public Set getAvailableBoatClasses() { + public Set getAvailableBoatClasses() { return incrementalRegressionProcessor.getAvailableBoatClasses(); } @@ -216,7 +218,7 @@ public class PolarDataMiner { if (angle >= startAngleInclusive && angle < endAngleExclusive) { try { dataCounts[angle] = incrementalRegressionProcessor.estimateBoatSpeed(boatClass, windSpeed, - new DegreeBearingImpl(convertAngleIfNecessary(angle)), true).getDataCount(); + new DegreeBearingImpl(convertAngleIfNecessary(angle))).getDataCount(); } catch (NotEnoughDataHasBeenAddedException e) { dataCounts[angle] = 0; } @@ -227,4 +229,36 @@ public class PolarDataMiner { return dataCounts; } + + + @Override + public SpeedWithBearingWithConfidence getAverageUpwindSpeedWithBearingOnStarboardTackFor(BoatClass boatClass, + Speed windSpeed) throws NotEnoughDataHasBeenAddedException { + return incrementalRegressionProcessor.getAverageUpwindSpeedWithBearingOnStarboardTackFor(boatClass, windSpeed); + } + + + + @Override + public SpeedWithBearingWithConfidence getAverageDownwindSpeedWithBearingOnStarboardTackFor( + BoatClass boatClass, Speed windSpeed) throws NotEnoughDataHasBeenAddedException { + return incrementalRegressionProcessor.getAverageDownwindSpeedWithBearingOnStarboardTackFor(boatClass, windSpeed); + } + + + + @Override + public SpeedWithBearingWithConfidence getAverageUpwindSpeedWithBearingOnPortTackFor(BoatClass boatClass, + Speed windSpeed) throws NotEnoughDataHasBeenAddedException { + return incrementalRegressionProcessor.getAverageUpwindSpeedWithBearingOnPortTackFor(boatClass, windSpeed); + } + + + + @Override + public SpeedWithBearingWithConfidence getAverageDownwindSpeedWithBearingOnPortTackFor(BoatClass boatClass, + Speed windSpeed) throws NotEnoughDataHasBeenAddedException { + return incrementalRegressionProcessor.getAverageDownwindSpeedWithBearingOnPortTackFor(boatClass, windSpeed); + } + } diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/RoundedAngleToTheWind.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/RoundedAngleToTheWind.java index b0d48bdf912..75363ff9e62 100644 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/RoundedAngleToTheWind.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/RoundedAngleToTheWind.java @@ -12,14 +12,14 @@ public class RoundedAngleToTheWind { @Override public String toString() { - return "" + angle; + return "" + getAngle(); } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + angle; + result = prime * result + getAngle(); return result; } @@ -32,9 +32,13 @@ public class RoundedAngleToTheWind { if (getClass() != obj.getClass()) return false; RoundedAngleToTheWind other = (RoundedAngleToTheWind) obj; - if (angle != other.angle) + if (getAngle() != other.getAngle()) return false; return true; } + public int getAngle() { + return angle; + } + } diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/regression/BoatSpeedEstimator.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/regression/BoatSpeedEstimator.java index 70ff5a7a774..2cfd19d2dac 100644 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/regression/BoatSpeedEstimator.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/regression/BoatSpeedEstimator.java @@ -1,31 +1,31 @@ package com.sap.sailing.polars.regression; +import java.io.ObjectInputStream; +import java.io.Serializable; import com.sap.sailing.polars.mining.IncrementalRegressionProcessor; -import com.sap.sailing.polars.regression.impl.IncrementalLeastSquaresProcessor; import com.sap.sailing.util.impl.LockUtil; import com.sap.sailing.util.impl.NamedReentrantReadWriteLock; /** - * Combines two linear regression processors. One with the angle to the wind as the x axis and the other with the wind - * speed on the x axis. Both y axis represent the boat speed. + * Supplies incremental arithmetic mean for confidence and speed. * - * {@link #estimateSpeed(double, double)} returns the average of the estimation of both regressions. + * {@link #estimateSpeed(double, double)} returns the average of the speed * - * Note that this class should only be used for a small interval on a polar sheet. The + * Note that this class should only be used for a small wind interval on a polar sheet. The * {@link IncrementalRegressionProcessor} is one example for that. It has one instance of the {@link BoatSpeedEstimator} - * for each wind speed level and rounded angle combination. + * for each wind boatclass, speed level and rounded angle combination. * * @author Frederik Petersen (D054528) * */ -public class BoatSpeedEstimator { +public class BoatSpeedEstimator implements Serializable { - private IncrementalLinearRegressionProcessor angleRegression = new IncrementalLeastSquaresProcessor(); + private static final long serialVersionUID = -254184914347332658L; - private IncrementalLinearRegressionProcessor windSpeedRegression = new IncrementalLeastSquaresProcessor(); - - private NamedReentrantReadWriteLock lock = new NamedReentrantReadWriteLock(getClass().getName(), true); + private double speedSum = 0; + private transient NamedReentrantReadWriteLock lock = createLock(); + private double confidenceSum = 0; private int dataCount = 0; @@ -33,30 +33,24 @@ public class BoatSpeedEstimator { /** * @param useLinearRegression if false mean of wind interval is used, otherwise linear regression */ - public double estimateSpeed(double windSpeed, double angleToTheWind, boolean useLinearRegression) throws NotEnoughDataHasBeenAddedException { + public double estimateSpeed(double windSpeed, double angleToTheWind) throws NotEnoughDataHasBeenAddedException { LockUtil.lockForRead(lock); + if (dataCount < 1) { + throw new NotEnoughDataHasBeenAddedException(); + } double result; try { - if (useLinearRegression) { - double angleEstimated = angleRegression.getEstimatedY(angleToTheWind); - double windSpeedEstimated = windSpeedRegression.getEstimatedY(windSpeed); - - result = (angleEstimated + windSpeedEstimated) / 2.0; - } else { - //Return average for that wind interval - result = windSpeedRegression.getMeanOfY(); - } + result = speedSum / dataCount; } finally { LockUtil.unlockAfterRead(lock); } return result; } - public void addData(double windSpeed, double angleToTheWind, double boatSpeed, double confidence) { + public void addData(double boatSpeed, double confidence) { LockUtil.lockForWrite(lock); try { - angleRegression.addMeasuredPoint(angleToTheWind, boatSpeed); - windSpeedRegression.addMeasuredPoint(windSpeed, boatSpeed); + speedSum = speedSum + boatSpeed; dataCount++; confidenceSum = confidenceSum + confidence; } finally { @@ -71,5 +65,13 @@ public class BoatSpeedEstimator { public double getConfidence() { return confidenceSum / dataCount; } + + private void readObject(ObjectInputStream ois) { + lock = createLock(); + } + + private NamedReentrantReadWriteLock createLock() { + return new NamedReentrantReadWriteLock(getClass().getName(), true); + } } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/PolarResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/PolarResource.java index 730c7a3b76c..45f56b0c112 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/PolarResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/PolarResource.java @@ -42,7 +42,7 @@ public class PolarResource extends AbstractSailingServerResource { ResponseBuilder responseBuilder; try { speedWithConfidence = getService().getPolarDataService().getSpeed(boatClass, new KnotSpeedImpl(windSpeed), - new DegreeBearingImpl(angle), true); + new DegreeBearingImpl(angle)); String resultString = "Speed: " + speedWithConfidence.getObject().getKnots() + "kn; Confidence: " + speedWithConfidence.getConfidence(); responseBuilder = Response.ok(resultString, MediaType.TEXT_PLAIN); 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 41cfc5c5e19..ea70cf04535 100755 --- 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 @@ -88,7 +88,6 @@ import com.sap.sailing.domain.common.RegattaIdentifier; import com.sap.sailing.domain.common.RegattaName; import com.sap.sailing.domain.common.Renamable; import com.sap.sailing.domain.common.ScoringSchemeType; -import com.sap.sailing.domain.common.TrackedRaceStatusEnum; import com.sap.sailing.domain.common.WindSource; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO; @@ -1949,7 +1948,6 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes replicate(new TrackRegatta(regatta.getRegattaIdentifier())); regattaTrackingCache.put(regatta, result); ensureRegattaIsObservedForDefaultLeaderboardAndAutoLeaderboardLinking(result); - addRaceTrackingFinishedListenerForPolarFixCache(result); } return result; } finally { @@ -1957,28 +1955,6 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes } } - private void addRaceTrackingFinishedListenerForPolarFixCache(DynamicTrackedRegatta result) { - RaceListener raceListenerForPolarFixCacheUpdate = new RaceListener() { - @Override - public void raceRemoved(TrackedRace trackedRace) { - // TODO remove fixes from polar fix cache - } - - @Override - public void raceAdded(final TrackedRace trackedRace) { - trackedRace.addListener(new AbstractRaceChangeListener() { - @Override - public void statusChanged(TrackedRaceStatus newStatus) { - if (newStatus.getStatus() == TrackedRaceStatusEnum.FINISHED) { - polarDataService.newRaceFinishedTracking(trackedRace); - } - } - }); - } - }; - result.addRaceListener(raceListenerForPolarFixCacheUpdate); - } - @Override public DynamicTrackedRegatta getTrackedRegatta(com.sap.sailing.domain.base.Regatta regatta) { return regattaTrackingCache.get(regatta);