diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/polars/PolarDataService.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/polars/PolarDataService.java index 4de45c1e63b..37817b4cbb5 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/polars/PolarDataService.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/polars/PolarDataService.java @@ -1,8 +1,6 @@ package com.sap.sailing.domain.polars; import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; import org.apache.commons.math.analysis.polynomials.PolynomialFunction; @@ -14,8 +12,6 @@ import com.sap.sailing.domain.base.SpeedWithConfidence; import com.sap.sailing.domain.common.Bearing; import com.sap.sailing.domain.common.LegType; import com.sap.sailing.domain.common.ManeuverType; -import com.sap.sailing.domain.common.PolarSheetGenerationSettings; -import com.sap.sailing.domain.common.PolarSheetsData; import com.sap.sailing.domain.common.Speed; import com.sap.sailing.domain.common.Tack; import com.sap.sailing.domain.common.confidence.BearingWithConfidence; @@ -51,30 +47,6 @@ public interface PolarDataService { */ SpeedWithConfidence getSpeed(BoatClass boatClass, Speed windSpeed, Bearing trueWindAngle) throws NotEnoughDataHasBeenAddedException; - - - /** - * Generates a polar sheet for given races and settings using the provided executor for the worker threads. This - * method does not access a cache for now. - * - * @param trackedRaces - * The set of races to generate the diagram for. - * @param settings - * Settings as supplied by the user. - * @param executor - * The executor to run the worker threads with. - * @return The generated polar sheet with meta data. - */ - PolarSheetsData generatePolarSheet(Set trackedRaces, PolarSheetGenerationSettings settings, - Executor executor) throws InterruptedException, ExecutionException; - - /** - * - * @param boatClass - * The {@link BoatClass} to obtain the polar sheet for. - * @return The polar sheet for all existing races of the {@link BoatClass}. - */ - PolarSheetsData getPolarSheetForBoatClass(BoatClass boatClass); /** * diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PolarSheetGenerationServiceTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PolarSheetGenerationServiceTest.java deleted file mode 100755 index 0f3b6c8745e..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PolarSheetGenerationServiceTest.java +++ /dev/null @@ -1,239 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.NavigableSet; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentSkipListSet; - -import junit.framework.Assert; - -import org.junit.Test; - -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.RaceDefinition; -import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.CompetitorImpl; -import com.sap.sailing.domain.base.impl.CourseImpl; -import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; -import com.sap.sailing.domain.base.impl.TeamImpl; -import com.sap.sailing.domain.base.impl.WaypointImpl; -import com.sap.sailing.domain.common.PolarSheetGenerationResponse; -import com.sap.sailing.domain.common.PolarSheetGenerationSettings; -import com.sap.sailing.domain.common.PolarSheetsData; -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.RegattaNameAndRaceName; -import com.sap.sailing.domain.common.SpeedWithBearing; -import com.sap.sailing.domain.common.Wind; -import com.sap.sailing.domain.common.WindSource; -import com.sap.sailing.domain.common.WindSourceType; -import com.sap.sailing.domain.common.impl.DegreeBearingImpl; -import com.sap.sailing.domain.common.impl.DegreePosition; -import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; -import com.sap.sailing.domain.common.impl.PolarSheetGenerationSettingsImpl; -import com.sap.sailing.domain.common.impl.WindImpl; -import com.sap.sailing.domain.common.impl.WindSourceImpl; -import com.sap.sailing.domain.common.impl.WindSpeedSteppingWithMaxDistance; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; -import com.sap.sailing.domain.tracking.DynamicGPSFixTrack; -import com.sap.sailing.domain.tracking.DynamicTrackedRace; -import com.sap.sailing.domain.tracking.MarkPassing; -import com.sap.sailing.domain.tracking.WindWithConfidence; -import com.sap.sailing.domain.tracking.impl.DynamicGPSFixMovingTrackImpl; -import com.sap.sailing.domain.tracking.impl.MarkPassingByTimeComparator; -import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; -import com.sap.sailing.domain.tracking.impl.WindWithConfidenceImpl; -import com.sap.sailing.gwt.ui.client.SailingService; -import com.sap.sailing.server.RacingEventService; -import com.sap.sailing.server.impl.RacingEventServiceImpl; -import com.sap.sse.common.Color; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.impl.MillisecondsTimePoint; - -public class PolarSheetGenerationServiceTest { - - private static final String BOAT_CLASS = "Forelle"; - - @Test - public void testPolarSheetGenerationService() throws Exception { - - SailingService service = new MockSailingServiceForPolarSheetGeneration(); - - double[] levels = { 4., 6., 8., 10., 12., 14., 16., 20., 25., 30. }; - WindSpeedSteppingWithMaxDistance windStepping = new WindSpeedSteppingWithMaxDistance(levels, 2.0); - PolarSheetGenerationSettings settings = new PolarSheetGenerationSettingsImpl(1, 0, 1, 20, 0, false, true, 5, - 0.05, false, windStepping, false, 0); - - List idList = new ArrayList(); - idList.add(new RegattaNameAndRaceName("IrgendeineRegatta", "IrgendeinRennen")); - - PolarSheetGenerationResponse triggerData = service.generatePolarSheetForRaces(idList, settings, ""); - Assert.assertNotNull(triggerData); - Assert.assertEquals(BOAT_CLASS, triggerData.getName()); - Assert.assertNotNull(triggerData.getId()); - - PolarSheetsData results = triggerData.getData(); - - Assert.assertNotNull(results); - - Assert.assertEquals(4, results.getDataCount()); - Assert.assertEquals(4.0, results.getAveragedPolarDataByWindSpeed()[0][45]); - Assert.assertEquals(2.0, results.getAveragedPolarDataByWindSpeed()[0][55]); - Assert.assertEquals(6.0, results.getAveragedPolarDataByWindSpeed()[0][35]); - - } - - - @SuppressWarnings("serial") - private class MockSailingServiceForPolarSheetGeneration extends SailingServiceImplMock { - @Override - protected RacingEventService getService() { - RacingEventService service = new MockRacingEventServiceForPolarSheetGeneration(); - return service; - } - } - - private class MockRacingEventServiceForPolarSheetGeneration extends RacingEventServiceImpl { - - @Override - public DynamicTrackedRace getTrackedRace(RegattaAndRaceIdentifier raceIdentifier) { - MockTrackedRaceForPolarSheetGeneration trackedRace = new MockTrackedRaceForPolarSheetGeneration(); - return trackedRace; - } - - } - - @SuppressWarnings("serial") - private class MockTrackedRaceForPolarSheetGeneration extends MockedTrackedRace { - @Override - public DynamicGPSFixTrack getTrack(Competitor competitor) { - DynamicGPSFixTrack track = new MockDynamicGPSFixMovinTrackForPolarSheetGeneration(competitor, 0); - //Before start - track.addGPSFix(new MockGPSFixMovingForPolarSheetGeneration(new DegreePosition(0.009, 0.009), new MillisecondsTimePoint(3), new KnotSpeedWithBearingImpl(12.0, new DegreeBearingImpl(-45.0)))); - //Race - track.addGPSFix(new MockGPSFixMovingForPolarSheetGeneration(new DegreePosition(1.0, 1.0), new MillisecondsTimePoint(10), new KnotSpeedWithBearingImpl(3.0, new DegreeBearingImpl(-45.0)))); - track.addGPSFix(new MockGPSFixMovingForPolarSheetGeneration(new DegreePosition(1.001, 1.001), new MillisecondsTimePoint(11), new KnotSpeedWithBearingImpl(5.0, new DegreeBearingImpl(-45.0)))); - track.addGPSFix(new MockGPSFixMovingForPolarSheetGeneration(new DegreePosition(1.002, 1.002), new MillisecondsTimePoint(12), new KnotSpeedWithBearingImpl(2.0, new DegreeBearingImpl(-55.0)))); - track.addGPSFix(new MockGPSFixMovingForPolarSheetGeneration(new DegreePosition(1.003, 1.003), new MillisecondsTimePoint(13), new KnotSpeedWithBearingImpl(6.0, new DegreeBearingImpl(-35.0)))); - //After Finish - track.addGPSFix(new MockGPSFixMovingForPolarSheetGeneration(new DegreePosition(1.01, 1.01), new MillisecondsTimePoint(75), new KnotSpeedWithBearingImpl(12.0, new DegreeBearingImpl(-45.0)))); - return track; - } - - @Override - public Wind getWind(Position p, TimePoint at) { - Wind wind = new WindImpl(p, at, new KnotSpeedWithBearingImpl(2.0, new DegreeBearingImpl(180.0))); - return wind; - } - - @Override - public Wind getWind(Position p, TimePoint at, Set windSourcesToExclude) { - return getWind(p, at); - } - - @Override - public WindWithConfidence> getWindWithConfidence(Position p, TimePoint at) { - return new WindWithConfidenceImpl>(new WindImpl(p, at, - new KnotSpeedWithBearingImpl(2.0, new DegreeBearingImpl(180.0))), 0.9, - new com.sap.sse.common.Util.Pair(p, at), true); - } - - @Override - public WindWithConfidence> getWindWithConfidence(Position p, TimePoint at, - Set windSourcesToExclude) { - return getWindWithConfidence(p, at); - } - - @Override - public RaceDefinition getRace() { - BoatClass forelle = new BoatClassImpl("Forelle", true); - ArrayList waypoints = new ArrayList(); - waypoints.add(new WaypointImpl(null)); - waypoints.add(new WaypointImpl(null)); - waypoints.add(new WaypointImpl(null)); - waypoints.add(new WaypointImpl(null)); - waypoints.add(new WaypointImpl(null)); - waypoints.add(new WaypointImpl(null)); - waypoints.add(new WaypointImpl(null)); - ArrayList competitors = new ArrayList(); - Competitor competitor = new CompetitorImpl(UUID.randomUUID(), "Hans Frantz", Color.RED, null, null, - new TeamImpl("SAP", null, null), new BoatImpl("Schnelle Forelle", forelle, "GER000"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); - competitors.add(competitor); - RaceDefinition race = new RaceDefinitionImpl("Forelle1", new CourseImpl("ForelleCourse", waypoints), forelle, competitors); - return race; - } - - @Override - public NavigableSet getMarkPassings(Competitor competitor) { - NavigableSet passings = new ConcurrentSkipListSet( - MarkPassingByTimeComparator.INSTANCE); - passings.add(new MarkPassingImpl(new MillisecondsTimePoint(10), null, competitor)); - passings.add(new MarkPassingImpl(new MillisecondsTimePoint(20), null, competitor)); - passings.add(new MarkPassingImpl(new MillisecondsTimePoint(30), null, competitor)); - passings.add(new MarkPassingImpl(new MillisecondsTimePoint(40), null, competitor)); - passings.add(new MarkPassingImpl(new MillisecondsTimePoint(50), null, competitor)); - passings.add(new MarkPassingImpl(new MillisecondsTimePoint(60), null, competitor)); - passings.add(new MarkPassingImpl(new MillisecondsTimePoint(70), null, competitor)); - return passings; - } - - @Override - public Set getWindSources(WindSourceType type) { - Set sources = new HashSet(); - sources.add(new WindSourceImpl(type)); - return sources; - } - - @Override - public TimePoint getStartOfRace() { - return new MillisecondsTimePoint(9); - } - - @Override - public TimePoint getEndOfRace() { - return new MillisecondsTimePoint(80); - }; - } - - @SuppressWarnings("serial") - private class MockGPSFixMovingForPolarSheetGeneration extends GPSFixMovingImpl { - - public MockGPSFixMovingForPolarSheetGeneration(Position position, TimePoint timePoint, SpeedWithBearing speed) { - super(position, timePoint, speed); - } - - @Override - public boolean isValidCached() { - return true; - } - - } - - @SuppressWarnings("serial") - private class MockDynamicGPSFixMovinTrackForPolarSheetGeneration extends DynamicGPSFixMovingTrackImpl { - - public MockDynamicGPSFixMovinTrackForPolarSheetGeneration(ItemType trackedItem, - long millisecondsOverWhichToAverage) { - super(trackedItem, millisecondsOverWhichToAverage); - } - - @Override - protected boolean isValid(NavigableSet rawFixes, GPSFixMoving e) { - return true; - } - - @Override - public SpeedWithBearing getEstimatedSpeed(TimePoint at) { - return this.getFirstFixAtOrAfter(at).getSpeed(); - } - - } - -} diff --git a/java/com.sap.sailing.gwt.ui/PolarSheets.css b/java/com.sap.sailing.gwt.ui/PolarSheets.css deleted file mode 100644 index e94192e52cb..00000000000 --- a/java/com.sap.sailing.gwt.ui/PolarSheets.css +++ /dev/null @@ -1,128 +0,0 @@ -/** Add css rules here for your application. */ -/* - body #calendar:after - content: " "; - display: block; - height: 0; - clear: both; - visibility: hidden; -*/ - -.clear { - clear: both; - font-size: 1px; - height: 0px; - line-height: 0px; - margin: -1px 0 0; - width: 100%; } - -.cover { - left: -1000px; - overflow: hidden; - position: absolute; - top: -1000px; } - -body { - background: #fff; - font-family: 'Open Sans', Arial, Verdana, sans-serif; - line-height: 1; - font-size: 14px; - font-weight: 400; - padding: 85px 0 120px 0; - margin: 0; - } - -/** Example rules used by the template application (remove for your app) */ -h1 { - font-size: 2em; - font-weight: bold; - color: #777777; - margin: 40px 0px 70px; - text-align: center; - } - -table { - border-collapse: separate; } - -.leaderboardMargin { - margin: 5px; -} - -.leaderboardContent { -} - -.leaderboardContent td, .leaderboardContent th { - vertical-align: bottom; - line-height: 1.3; - padding-top: 2px; -} - -.leaderboardContent-toolbar { - -} - -.leaderboardLabel { - border-bottom: 2px solid #007dc0; - font-weight: bold; - margin: 5px; - } - -.refreshAndSettings { - background: #f2f2f2; - border-bottom: 2px solid #fff; - border-top: 2px solid #fff; - height: 30px; } - -.refreshAndSettings table td { - padding: 0 10px 0 0;} - -.refreshAndSettings table table td{ - padding: 0 0 0 0;} - -input.magnifier{ - display: block; - margin: 3px auto 0 auto !important; -} - -body, table td, select, button { - font-family: 'Open Sans', Arial, Verdana, sans-serif; - font-weight: 300; - font-size: 14px; -} - -.errorLabel { - color: #FF0000; -} - -.abstractChartPanel-importantMessageOfChart { - font-family: 'Open Sans',Arial,Verdana,sans-serif; - font-weight: 600; - font-size: 20px; - height: 70px; - margin: 0 auto; - padding: 49px 0 0 80px; - width: 300px; - color: #7c7c7c; - background: url(images/important-message.png) left center no-repeat; -} - -.LeaderboardHeader { - position: relative; - margin: 0 auto; - width: 400px; - text-align: center; - font-family: 'Open Sans', Arial, Verdana, sans-serif; - font-size: 18px; - color: #fff; - margin-top: 22px; -} - -.leaderboardHeading { - font-size: 16px; - font-family: 'Open Sans', Arial, Verdana, sans-serif; - font-weight: bold; -} - -.gwt-DialogBox { - z-index: 20; -} diff --git a/java/com.sap.sailing.gwt.ui/PolarSheets.html b/java/com.sap.sailing.gwt.ui/PolarSheets.html deleted file mode 100644 index 8449145b9f7..00000000000 --- a/java/com.sap.sailing.gwt.ui/PolarSheets.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - SAP Sailing Analytics Polar Sheets - - - - - - - - - - - - - - - - - - - - - - diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch b/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch index a3aff4a0ab3..47ba9bdd69b 100755 --- a/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch @@ -56,7 +56,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch b/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch index eae6162cfdb..42cb71a2d96 100644 --- a/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch @@ -11,7 +11,6 @@ - @@ -74,7 +73,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT.launch b/java/com.sap.sailing.gwt.ui/SailingGWT.launch index c498593f424..e2cdc9e0df7 100755 --- a/java/com.sap.sailing.gwt.ui/SailingGWT.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT.launch @@ -10,7 +10,6 @@ - @@ -72,7 +71,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/build.properties b/java/com.sap.sailing.gwt.ui/build.properties index 75618842ba3..9a0247eb1d6 100644 --- a/java/com.sap.sailing.gwt.ui/build.properties +++ b/java/com.sap.sailing.gwt.ui/build.properties @@ -21,7 +21,6 @@ bin.includes = META-INF/,\ RaceBoard.html,\ Spectator.html,\ com.sap.sailing.gwt.ui.Spectator/,\ - com.sap.sailing.gwt.ui.PolarSheets/,\ com.sap.sailing.gwt.ui.RaceBoard/,\ Spectator.css,\ com.sap.sailing.gwt.ui.Simulator/,\ @@ -35,8 +34,6 @@ bin.includes = META-INF/,\ com.sap.sailing.gwt.ui.YoutubePopup/,\ YoutubePopup.html,\ BrowserUnsupported.html,\ - PolarSheets.css,\ - PolarSheets.html,\ com.sap.sailing.gwt.ui.DataMining/,\ DataMining.css,\ DataMining.html,\ diff --git a/java/com.sap.sailing.gwt.ui/pom.xml b/java/com.sap.sailing.gwt.ui/pom.xml index 7585839ee56..d51dd03da2b 100755 --- a/java/com.sap.sailing.gwt.ui/pom.xml +++ b/java/com.sap.sailing.gwt.ui/pom.xml @@ -163,7 +163,6 @@ com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.regattaoverview.RegattaOverview - com.sap.sailing.gwt.ui.PolarSheets - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/test/PolarSheetGenerationTest.java b/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/test/PolarSheetGenerationTest.java deleted file mode 100644 index 2a95da4b34b..00000000000 --- a/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/test/PolarSheetGenerationTest.java +++ /dev/null @@ -1,315 +0,0 @@ -package com.sap.sailing.polars.test; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.NavigableSet; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentSkipListSet; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import org.junit.Assert; -import org.junit.Test; - -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.RaceDefinition; -import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.CompetitorImpl; -import com.sap.sailing.domain.base.impl.CourseImpl; -import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; -import com.sap.sailing.domain.base.impl.TeamImpl; -import com.sap.sailing.domain.base.impl.WaypointImpl; -import com.sap.sailing.domain.common.PolarSheetGenerationSettings; -import com.sap.sailing.domain.common.PolarSheetsData; -import com.sap.sailing.domain.common.PolarSheetsHistogramData; -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.SpeedWithBearing; -import com.sap.sailing.domain.common.Wind; -import com.sap.sailing.domain.common.WindSource; -import com.sap.sailing.domain.common.WindSourceType; -import com.sap.sailing.domain.common.impl.DegreeBearingImpl; -import com.sap.sailing.domain.common.impl.DegreePosition; -import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; -import com.sap.sailing.domain.common.impl.PolarSheetGenerationSettingsImpl; -import com.sap.sailing.domain.common.impl.WindImpl; -import com.sap.sailing.domain.common.impl.WindSourceImpl; -import com.sap.sailing.domain.common.impl.WindSpeedSteppingWithMaxDistance; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; -import com.sap.sailing.domain.test.mock.MockedTrackedRace; -import com.sap.sailing.domain.tracking.DynamicGPSFixTrack; -import com.sap.sailing.domain.tracking.MarkPassing; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.WindWithConfidence; -import com.sap.sailing.domain.tracking.impl.DynamicGPSFixMovingTrackImpl; -import com.sap.sailing.domain.tracking.impl.MarkPassingByTimeComparator; -import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; -import com.sap.sailing.domain.tracking.impl.WindWithConfidenceImpl; -import com.sap.sailing.polars.aggregation.PolarFixAggregationWorker; -import com.sap.sailing.polars.aggregation.PolarFixAggregator; -import com.sap.sailing.polars.aggregation.SimplePolarFixRaceInterval; -import com.sap.sailing.polars.data.DataPointWithOriginInfo; -import com.sap.sailing.polars.data.PolarFix; -import com.sap.sailing.polars.data.impl.DataPointWithOriginInfoImpl; -import com.sap.sailing.polars.generation.PolarSheetGenerator; -import com.sap.sailing.polars.generation.PolarSheetHistogramBuilder; -import com.sap.sse.common.Color; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.impl.MillisecondsTimePoint; - -public class PolarSheetGenerationTest { - - @Test - public void testPolarSheetRawDataGeneration() throws InterruptedException, ExecutionException { - Executor executor = new ThreadPoolExecutor(/* corePoolSize */Runtime.getRuntime().availableProcessors(), - /* maximumPoolSize */Runtime.getRuntime().availableProcessors(), - /* keepAliveTime */60, TimeUnit.SECONDS, - /* workQueue */new LinkedBlockingQueue()); - - MockTrackedRaceForPolarSheetGeneration race = new MockTrackedRaceForPolarSheetGeneration(); - - double[] levels = { 4., 6., 8., 10., 12., 14., 16., 20., 25., 30. }; - WindSpeedSteppingWithMaxDistance windStepping = new WindSpeedSteppingWithMaxDistance(levels, 2.0); - PolarSheetGenerationSettings settings = new PolarSheetGenerationSettingsImpl(1, 0, 1, 20, 0, false, true, 5, - 0.05, false, windStepping, false, 0); - - TimePoint startTime = new MillisecondsTimePoint(9); - TimePoint endTime = new MillisecondsTimePoint(80); - // Only used for storing and exporting results in this test case: - PolarFixAggregator resultContainer = new PolarFixAggregator(new SimplePolarFixRaceInterval( - new HashSet()), - settings, executor); - - BoatClass forelle = new BoatClassImpl("Forelle", true); - Competitor competitor = new CompetitorImpl(UUID.randomUUID(), "Hans Frantz", Color.RED, null, null, - new TeamImpl("SAP", null, null), new BoatImpl("Schnelle Forelle", forelle, "GER000"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); - - PolarFixAggregationWorker task = new PolarFixAggregationWorker(race, - resultContainer, startTime, endTime, - competitor, settings, null); - - executor.execute(task); - double timeUntilTimeout = 1000; - while (!task.isDone() && timeUntilTimeout > 0) { - Thread.sleep(100); - timeUntilTimeout = timeUntilTimeout - 0.1; - } - - Set fixes = resultContainer.getAggregationResultAsSingleList(); - - PolarSheetGenerator generator = new PolarSheetGenerator(fixes, settings); - PolarSheetsData data = generator.generate(); - Assert.assertEquals(4, data.getDataCount()); - Assert.assertEquals(4.0, data.getAveragedPolarDataByWindSpeed()[0][45]); - Assert.assertEquals(2.0, data.getAveragedPolarDataByWindSpeed()[0][55]); - Assert.assertEquals(6.0, data.getAveragedPolarDataByWindSpeed()[0][35]); - - } - - @Test - public void testHistogramBuilder() { - double[] levels = { 4., 6., 8., 10., 12., 14., 16., 20., 25., 30. }; - WindSpeedSteppingWithMaxDistance windStepping = new WindSpeedSteppingWithMaxDistance(levels, 2.0); - PolarSheetGenerationSettings settings = new PolarSheetGenerationSettingsImpl(1, 0, 1, 10, 0, false, true, 5, - 0.05, false, windStepping, false, 0); - PolarSheetHistogramBuilder builder = new PolarSheetHistogramBuilder(settings); - - - List rawData = new ArrayList(); - rawData.add(new DataPointWithOriginInfoImpl(1.09, "", "")); - rawData.add(new DataPointWithOriginInfoImpl(1.0, "", "")); - rawData.add(new DataPointWithOriginInfoImpl(1.11, "", "")); - rawData.add(new DataPointWithOriginInfoImpl(1.46, "", "")); - rawData.add(new DataPointWithOriginInfoImpl(1.56, "", "")); - rawData.add(new DataPointWithOriginInfoImpl(2.05, "", "")); - rawData.add(new DataPointWithOriginInfoImpl(2.09, "", "")); - rawData.add(new DataPointWithOriginInfoImpl(3.0, "", "")); - rawData.add(new DataPointWithOriginInfoImpl(2.999, "", "")); - PolarSheetsHistogramData result = builder.build(rawData, 0, 0); - Number[] xValues = result.getxValues(); - Assert.assertEquals(10, xValues.length); - Assert.assertTrue(xValues[4].doubleValue() > 1.9 - 0.001 && xValues[4].doubleValue() < 1.9 + 0.001); - Number[] yValues = result.getyValues(); - Assert.assertEquals(10, yValues.length); - Assert.assertEquals(3, yValues[0]); - Assert.assertEquals(0, yValues[1]); - Assert.assertEquals(2, yValues[2]); - Assert.assertEquals(2, yValues[9]); - } - - @Test - public void testOutlierNeighborhoodAlgorithm() { - PolarSheetGenerationSettings settings = PolarSheetGenerationSettingsImpl.createStandardPolarSettings(); - List values = new ArrayList(); - values.add(new DataPointWithOriginInfoImpl(0., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - values.add(new DataPointWithOriginInfoImpl(20., "", "")); - int[] count = new int[1]; - count[0] = values.size(); - Map> valuesInMap = new HashMap>(); - valuesInMap.put(0, values); - double pct = PolarSheetGenerator.getNeighboorhoodSizePercentage(count, valuesInMap, 0, 0, - new DataPointWithOriginInfoImpl(0.0, "", ""), settings); - - Assert.assertTrue(pct < 0.05); - - pct = PolarSheetGenerator.getNeighboorhoodSizePercentage(count, valuesInMap, 0, 2, - new DataPointWithOriginInfoImpl(20.0, "", ""), settings); - - Assert.assertTrue(pct > 0.05); - - } - - - @SuppressWarnings("serial") - private class MockTrackedRaceForPolarSheetGeneration extends MockedTrackedRace { - @Override - public DynamicGPSFixTrack getTrack(Competitor competitor) { - DynamicGPSFixTrack track = new MockDynamicGPSFixMovinTrackForPolarSheetGeneration(competitor, 0); - //Before start - track.addGPSFix(new MockGPSFixMovingForPolarSheetGeneration(new DegreePosition(0.009, 0.009), new MillisecondsTimePoint(3), new KnotSpeedWithBearingImpl(12.0, new DegreeBearingImpl(-45.0)))); - //Race - track.addGPSFix(new MockGPSFixMovingForPolarSheetGeneration(new DegreePosition(1.0, 1.0), new MillisecondsTimePoint(10), new KnotSpeedWithBearingImpl(3.0, new DegreeBearingImpl(-45.0)))); - track.addGPSFix(new MockGPSFixMovingForPolarSheetGeneration(new DegreePosition(1.001, 1.001), new MillisecondsTimePoint(11), new KnotSpeedWithBearingImpl(5.0, new DegreeBearingImpl(-45.0)))); - track.addGPSFix(new MockGPSFixMovingForPolarSheetGeneration(new DegreePosition(1.002, 1.002), new MillisecondsTimePoint(12), new KnotSpeedWithBearingImpl(2.0, new DegreeBearingImpl(-55.0)))); - track.addGPSFix(new MockGPSFixMovingForPolarSheetGeneration(new DegreePosition(1.003, 1.003), new MillisecondsTimePoint(13), new KnotSpeedWithBearingImpl(6.0, new DegreeBearingImpl(-35.0)))); - //After Finish - track.addGPSFix(new MockGPSFixMovingForPolarSheetGeneration(new DegreePosition(1.01, 1.01), new MillisecondsTimePoint(75), new KnotSpeedWithBearingImpl(12.0, new DegreeBearingImpl(-45.0)))); - return track; - } - - @Override - public Wind getWind(Position p, TimePoint at) { - Wind wind = new WindImpl(p, at, new KnotSpeedWithBearingImpl(2.0, new DegreeBearingImpl(180.0))); - return wind; - } - - @Override - public Wind getWind(Position p, TimePoint at, Set windSourcesToExclude) { - return getWind(p, at); - } - - @Override - public WindWithConfidence> getWindWithConfidence(Position p, TimePoint at) { - return new WindWithConfidenceImpl>(new WindImpl(p, at, - new KnotSpeedWithBearingImpl(2.0, new DegreeBearingImpl(180.0))), 0.9, - new com.sap.sse.common.Util.Pair(p, at), true); - } - - @Override - public WindWithConfidence> getWindWithConfidence(Position p, TimePoint at, - Set windSourcesToExclude) { - return getWindWithConfidence(p, at); - } - - @Override - public RaceDefinition getRace() { - BoatClass forelle = new BoatClassImpl("Forelle", true); - ArrayList waypoints = new ArrayList(); - waypoints.add(new WaypointImpl(null)); - waypoints.add(new WaypointImpl(null)); - waypoints.add(new WaypointImpl(null)); - waypoints.add(new WaypointImpl(null)); - waypoints.add(new WaypointImpl(null)); - waypoints.add(new WaypointImpl(null)); - waypoints.add(new WaypointImpl(null)); - RaceDefinition race = new RaceDefinitionImpl("Forelle1", new CourseImpl("ForelleCourse", waypoints), forelle, new ArrayList()); - return race; - } - - @Override - public NavigableSet getMarkPassings(Competitor competitor) { - NavigableSet passings = new ConcurrentSkipListSet( - MarkPassingByTimeComparator.INSTANCE); - passings.add(new MarkPassingImpl(new MillisecondsTimePoint(10), null, competitor)); - passings.add(new MarkPassingImpl(new MillisecondsTimePoint(20), null, competitor)); - passings.add(new MarkPassingImpl(new MillisecondsTimePoint(30), null, competitor)); - passings.add(new MarkPassingImpl(new MillisecondsTimePoint(40), null, competitor)); - passings.add(new MarkPassingImpl(new MillisecondsTimePoint(50), null, competitor)); - passings.add(new MarkPassingImpl(new MillisecondsTimePoint(60), null, competitor)); - passings.add(new MarkPassingImpl(new MillisecondsTimePoint(70), null, competitor)); - return passings; - } - - @Override - public Set getWindSources(WindSourceType type) { - Set sources = new HashSet<>(); - sources.add(new WindSourceImpl(type)); - return sources; - } - } - - @SuppressWarnings("serial") - private class MockGPSFixMovingForPolarSheetGeneration extends GPSFixMovingImpl { - - public MockGPSFixMovingForPolarSheetGeneration(Position position, TimePoint timePoint, SpeedWithBearing speed) { - super(position, timePoint, speed); - } - - @Override - public boolean isValidCached() { - return true; - } - - } - - @SuppressWarnings("serial") - private class MockDynamicGPSFixMovinTrackForPolarSheetGeneration extends DynamicGPSFixMovingTrackImpl { - - public MockDynamicGPSFixMovinTrackForPolarSheetGeneration(ItemType trackedItem, - long millisecondsOverWhichToAverage) { - super(trackedItem, millisecondsOverWhichToAverage); - } - - @Override - protected boolean isValid(NavigableSet rawFixes, GPSFixMoving e) { - return true; - } - - @Override - public SpeedWithBearing getEstimatedSpeed(TimePoint at) { - return this.getFirstFixAtOrAfter(at).getSpeed(); - } - - } - -} diff --git a/java/com.sap.sailing.polars/META-INF/MANIFEST.MF b/java/com.sap.sailing.polars/META-INF/MANIFEST.MF index 964acf9e30f..64b04cc4241 100644 --- a/java/com.sap.sailing.polars/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.polars/META-INF/MANIFEST.MF @@ -7,7 +7,6 @@ Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ClassPath: . Export-Package: - com.sap.sailing.polars.data, com.sap.sailing.polars.mining, com.sap.sailing.polars.regression, com.sap.sailing.polars.windestimation diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/aggregation/PolarFixAggregationWorker.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/aggregation/PolarFixAggregationWorker.java deleted file mode 100644 index 1878d65ca0f..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/aggregation/PolarFixAggregationWorker.java +++ /dev/null @@ -1,252 +0,0 @@ -package com.sap.sailing.polars.aggregation; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.NavigableSet; -import java.util.Set; - -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.common.PolarSheetGenerationSettings; -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.WindSource; -import com.sap.sailing.domain.common.WindSourceType; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.tracking.GPSFixTrack; -import com.sap.sailing.domain.tracking.MarkPassing; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.WindWithConfidence; -import com.sap.sailing.polars.data.PolarFix; -import com.sap.sailing.polars.data.impl.PolarFixImpl; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; - -/** - * Iterates through the fixes of one competitor in one tracked race and fills the {@link PolarFixAggregator} with - * datapoints that are found for the speed of the boat and its angle to the wind - * - * @author D054528 Frederik Petersen - * - */ -public class PolarFixAggregationWorker implements Runnable { - - private final TrackedRace race; - - private final PolarFixAggregator polarSheetGenerationWorker; - - private TimePoint startTime; - - private TimePoint endTime; - - private final Competitor competitor; - - private boolean noConfidence = false; - - private boolean done = false; - - private int finishedEarlyAtWaypoint = -1; - - private PolarSheetGenerationSettings settings; - - private Pair intervalBeginningAndEnd; - - public PolarFixAggregationWorker(TrackedRace race, PolarFixAggregator polarSheetGenerationWorker, - TimePoint startTime, TimePoint endTime, Competitor competitor, PolarSheetGenerationSettings settings, - Pair intervalBeginningAndEnd) { - super(); - this.race = race; - this.polarSheetGenerationWorker = polarSheetGenerationWorker; - this.startTime = startTime; - this.endTime = endTime; - this.competitor = competitor; - this.settings = settings; - this.intervalBeginningAndEnd = intervalBeginningAndEnd; - optimizeStartTime(); - optimizeEndTime(); - checkIfRaceAborted(); - checkIfIntervalBeforeOrAfterRace(); - } - - private void checkIfIntervalBeforeOrAfterRace() { - if (intervalBeginningAndEnd != null) { - TimePoint intervalStart = intervalBeginningAndEnd.getA(); - if (intervalStart.after(endTime)) { - noConfidence = true; - } - TimePoint intervalEnd = intervalBeginningAndEnd.getB(); - if (intervalEnd.before(startTime)) { - noConfidence = true; - } - } - } - - private void checkIfRaceAborted() { - NavigableSet markPassings = race.getMarkPassings(competitor); - if (markPassings == null || markPassings.size() < 1) { - return; - } - if (markPassings.size() < race.getRace().getCourse().getLegs().size() + 1) { - finishedEarlyAtWaypoint = markPassings.size() - 1; - } - } - - private void optimizeEndTime() { - NavigableSet markPassings = race.getMarkPassings(competitor); - if (markPassings == null || markPassings.size() < 1) { - return; - } - MarkPassing passedFinish = markPassings.last(); - TimePoint passedFinishTimePoint = passedFinish.getTimePoint(); - if (passedFinishTimePoint.before(endTime)) { - endTime = passedFinishTimePoint; - } - } - - private void optimizeStartTime() { - NavigableSet markPassings = race.getMarkPassings(competitor); - if (markPassings == null || markPassings.size() < 1) { - noConfidence = true; - return; - } - MarkPassing passedStart = markPassings.first(); - TimePoint passedStartTimePoint = passedStart.getTimePoint(); - if (passedStartTimePoint.after(startTime)) { - startTime = passedStartTimePoint; - } - } - - @Override - public void run() { - if (noConfidence || (finishedEarlyAtWaypoint != -1 && finishedEarlyAtWaypoint < 3)) { - done = true; - } else { - GPSFixTrack track = race.getTrack(competitor); - track.lockForRead(); - try { - Iterator fixesIterator; - if (intervalBeginningAndEnd != null) { - TimePoint startOfIntervalToCheck = intervalBeginningAndEnd.getA().before(startTime) ? startTime - : intervalBeginningAndEnd.getA(); - TimePoint endOfIntervalToCheck = intervalBeginningAndEnd.getB().after(endTime) ? endTime - : intervalBeginningAndEnd.getB(); - fixesIterator = track.getFixes(startOfIntervalToCheck, true, endOfIntervalToCheck, true).iterator(); - } else { - // No timepoint interval given - fixesIterator = track.getFixesIterator(startTime, true); - } - TimePoint lastConsideredTimePoint = null; - if (finishedEarlyAtWaypoint != -1) { - NavigableSet markPassings = race.getMarkPassings(competitor); - MarkPassing lastConsideredPassing = markPassings.last(); - lastConsideredPassing = markPassings.lower(lastConsideredPassing); - lastConsideredTimePoint = lastConsideredPassing.getTimePoint(); - } - boolean reachedEnd = false; - while (fixesIterator.hasNext() && reachedEnd == false) { - GPSFixMoving fix = fixesIterator.next(); - if (fix.getTimePoint().after(endTime) - || (lastConsideredTimePoint != null && fix.getTimePoint().after(lastConsideredTimePoint))) { - reachedEnd = true; - } else { - addFixIfValid(track, fix); - } - } - } finally { - track.unlockAfterRead(); - done = true; - } - } - } - - private void addFixIfValid(GPSFixTrack track, GPSFixMoving fix) { - if (!track.hasDirectionChange(fix.getTimePoint(), race.getRace().getBoatClass() - .getManeuverDegreeAngleThreshold())) { - List>>> windWithConfidenceList = new ArrayList>>>(); - if (settings.useOnlyWindGaugesForWindSpeed()) { - if (settings.splitByWindgauges()) { - windWithConfidenceList.addAll(addAllWindsOfWindGaugesSplitOneByOne(fix)); - } else { - windWithConfidenceList.add(new Pair>>( - createWindGaugesString(race), race.getWindWithConfidence(fix.getPosition(), - fix.getTimePoint(), collectWindSourcesToIgnoreForSpeed()))); - } - } else { - windWithConfidenceList.add(new Pair>>("Combined", - race.getWindWithConfidence(fix.getPosition(), fix.getTimePoint()))); - } - - for (Pair>> windWithSourceIdStringPair : windWithConfidenceList) { - WindWithConfidence> windWithConfidence = windWithSourceIdStringPair.getB(); - if (windWithConfidence != null && windWithConfidence.useSpeed() - && windWithConfidence.getConfidence() >= settings.getMinimumWindConfidence()) { - PolarFix polarFix = new PolarFixImpl(fix, race, track, windWithConfidence.getObject(), settings, - windWithSourceIdStringPair.getA()); - polarSheetGenerationWorker.addPolarFix(race.getRaceIdentifier(), polarFix); - } - } - } - } - - private Collection>>> addAllWindsOfWindGaugesSplitOneByOne( - GPSFixMoving fix) { - Iterable windGaugeSources = race.getWindSources(WindSourceType.EXPEDITION); - List>>> windWithConfidenceList = new ArrayList>>>(); - for (WindSource windGaugeSource : windGaugeSources) { - Iterable allSources = race.getWindSources(); - Set allSourcesButTheSingleWindGaugeSource = new HashSet(); - for (WindSource windSource : allSources) { - if (windSource != windGaugeSource) { - allSourcesButTheSingleWindGaugeSource.add(windSource); - } - } - windWithConfidenceList.add(new Pair>>(windGaugeSource - .getId().toString(), race.getWindWithConfidence(fix.getPosition(), fix.getTimePoint(), - allSourcesButTheSingleWindGaugeSource))); - } - return windWithConfidenceList; - } - - private String createWindGaugesString(TrackedRace race) { - Iterable gaugeWindSources = race.getWindSources(WindSourceType.EXPEDITION); - String gaugeIdString = ""; - for (WindSource source : gaugeWindSources) { - if (gaugeIdString.isEmpty()) { - gaugeIdString = "" + source.getId(); - } else { - gaugeIdString = gaugeIdString + "+" + source.getId(); - } - } - return gaugeIdString; - } - - public boolean isDone() { - return done; - } - - private Set collectWindSourcesToIgnoreForSpeed() { - Set windSourcesToExclude = new HashSet(); - Iterable combinedSources = race.getWindSources(WindSourceType.COMBINED); - for (WindSource combinedSource : combinedSources) { - windSourcesToExclude.add(combinedSource); - } - Iterable courseSources = race.getWindSources(WindSourceType.COURSE_BASED); - for (WindSource courseSource : courseSources) { - windSourcesToExclude.add(courseSource); - } - Iterable trackBasedSources = race.getWindSources(WindSourceType.TRACK_BASED_ESTIMATION); - for (WindSource trackBasedSource : trackBasedSources) { - windSourcesToExclude.add(trackBasedSource); - } - Iterable rcSources = race.getWindSources(WindSourceType.RACECOMMITTEE); - for (WindSource rcSource : rcSources) { - windSourcesToExclude.add(rcSource); - } - Iterable webSources = race.getWindSources(WindSourceType.WEB); - for (WindSource webSource : webSources) { - windSourcesToExclude.add(webSource); - } - return windSourcesToExclude; - } -} diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/aggregation/PolarFixAggregator.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/aggregation/PolarFixAggregator.java deleted file mode 100644 index ab1e99e2bd4..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/aggregation/PolarFixAggregator.java +++ /dev/null @@ -1,168 +0,0 @@ -package com.sap.sailing.polars.aggregation; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.RaceDefinition; -import com.sap.sailing.domain.common.PolarSheetGenerationSettings; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.polars.data.PolarFix; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; - -/** - * Allows extracting data about average speed for each angle creating the foundation of polar-sheet generation. Tasks - * are assigned to the executor per race & per competitor and the results are filled on the go to allow progress - * indication in the polar-sheet itself. - * - * @author D054528 Frederik Petersen - * - */ -public class PolarFixAggregator implements Future>> { - - private final Set workers; - - private final Executor executor; - - private final Map> fixes = new HashMap>(); - - /** - * Will prepare the {@link PolarFixAggregationWorker}s per race & per competitor. This includes determining start - * and end time. - * - * @param updateInterval - * from which the data is to be collected - * @param settings - * @param executor - * executes the tasks upon {@link #startPolarFixAggregation()} - */ - public PolarFixAggregator(PolarFixRaceInterval updateInterval, PolarSheetGenerationSettings settings, - Executor executor) { - this.executor = executor; - workers = new HashSet(); - for (Entry>> entry : updateInterval - .getCompetitorAndTimepointsForRace().entrySet()) { - TrackedRace race = entry.getKey(); - TimePoint startTime = race.getStartOfRace(); - TimePoint endTime = race.getEndOfRace(); - if (endTime == null) { - endTime = race.getTimePointOfNewestEvent(); - } - RaceDefinition raceDefinition = race.getRace(); - - Map> detailedInterval = entry.getValue(); - if (detailedInterval == null) { - Iterable competitors = raceDefinition.getCompetitors(); - for (Competitor competitor : competitors) { - PolarFixAggregationWorker task = new PolarFixAggregationWorker(race, this, startTime, endTime, - competitor, settings, null); - workers.add(task); - } - } else { - for (Entry> competitorEntry : detailedInterval.entrySet()) { - Competitor competitor = competitorEntry.getKey(); - Pair intervalBeginningAndEnd = competitorEntry.getValue(); - PolarFixAggregationWorker task = new PolarFixAggregationWorker(race, this, startTime, endTime, - competitor, settings, intervalBeginningAndEnd); - workers.add(task); - } - } - - } - } - - /** - * Starts the {@link PolarFixAggregationWorker}s - */ - public void startPolarFixAggregation() { - for (Runnable task : workers) { - executor.execute(task); - } - } - - /** - * To be called from {@link PolarFixAggregationWorker} for adding a datapoint to the list of results wind's speed in - * knots - */ - protected void addPolarFix(RegattaAndRaceIdentifier raceId, PolarFix polarFix) { - synchronized (fixes) { - List existingList = fixes.get(raceId); - if (existingList == null) { - existingList = new ArrayList(); - fixes.put(raceId, existingList); - } - existingList.add(polarFix); - } - } - - private boolean allWorkersDone() { - boolean complete = true; - for (PolarFixAggregationWorker task : workers) { - if (!task.isDone()) { - complete = false; - break; - } - } - return complete; - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return false; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean isDone() { - return allWorkersDone(); - } - - @Override - public Map> get() throws InterruptedException, ExecutionException { - while (!isDone()) { - Thread.sleep(100); - } - return fixes; - } - - @Override - public Map> get(long timeout, TimeUnit unit) throws InterruptedException, - ExecutionException, TimeoutException { - long timeRun = 0; - long timeoutInMillis = unit.toMillis(timeout); - while (!isDone() && timeRun < timeoutInMillis) { - Thread.sleep(100); - timeRun = timeRun + 100; - } - if (timeRun >= timeoutInMillis) { - throw new TimeoutException(); - } - return fixes; - } - - public Set getAggregationResultAsSingleList() throws InterruptedException, ExecutionException { - Set fixes = new HashSet(); - Map> aggregationResult = get(); - for (List list : aggregationResult.values()) { - fixes.addAll(list); - } - return fixes; - } - -} diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/aggregation/PolarFixRaceInterval.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/aggregation/PolarFixRaceInterval.java deleted file mode 100644 index 8c8c1a9ffc9..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/aggregation/PolarFixRaceInterval.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.sap.sailing.polars.aggregation; - -import java.util.Map; - -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; - -public interface PolarFixRaceInterval { - - Map>> getCompetitorAndTimepointsForRace(); - -} diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/aggregation/SimplePolarFixRaceInterval.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/aggregation/SimplePolarFixRaceInterval.java deleted file mode 100644 index 6f99bdff331..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/aggregation/SimplePolarFixRaceInterval.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.sap.sailing.polars.aggregation; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; - -public class SimplePolarFixRaceInterval implements PolarFixRaceInterval { - - private final Map>> intervalMap; - - public SimplePolarFixRaceInterval(Set races) { - intervalMap = new HashMap>>(); - for (TrackedRace race : races) { - intervalMap.put(race, null); - } - } - - @Override - public Map>> getCompetitorAndTimepointsForRace() { - return intervalMap; - } - -} diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/BoatAndWindSpeedWithOriginInfo.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/BoatAndWindSpeedWithOriginInfo.java deleted file mode 100644 index 8293414e4f8..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/BoatAndWindSpeedWithOriginInfo.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.sap.sailing.polars.data; - -import com.sap.sailing.domain.common.Speed; - -public interface BoatAndWindSpeedWithOriginInfo { - - public Speed getBoatSpeed(); - - public Speed getWindSpeed(); - - public String getWindGaugesIdString(); - - public String getDayString(); - -} diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/DataPointWithOriginInfo.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/DataPointWithOriginInfo.java deleted file mode 100644 index 9d8887e4064..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/DataPointWithOriginInfo.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.sap.sailing.polars.data; - -public interface DataPointWithOriginInfo extends Comparable { - - public abstract Double getRawData(); - - public abstract String getWindGaugeIdString(); - - public abstract String getDayString(); - -} \ No newline at end of file diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/PolarFix.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/PolarFix.java deleted file mode 100644 index 3b0380d11be..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/PolarFix.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.sap.sailing.polars.data; - -import com.sap.sailing.domain.common.Speed; -import com.sap.sailing.domain.common.SpeedWithBearing; - -public interface PolarFix { - - public abstract SpeedWithBearing getBoatSpeed(); - - public abstract Speed getWindSpeed(); - - public abstract double getTrueWindAngleDeg(); - - public abstract String getGaugeIdString(); - - public abstract String getDayString(); - -} \ No newline at end of file diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/impl/BoatAndWindSpeedWithOriginInfoImpl.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/impl/BoatAndWindSpeedWithOriginInfoImpl.java deleted file mode 100644 index d9d7cccd76f..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/impl/BoatAndWindSpeedWithOriginInfoImpl.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.sap.sailing.polars.data.impl; - -import com.sap.sailing.domain.common.Speed; -import com.sap.sailing.polars.data.BoatAndWindSpeedWithOriginInfo; - -public class BoatAndWindSpeedWithOriginInfoImpl implements BoatAndWindSpeedWithOriginInfo { - - private Speed boatSpeed; - private Speed windSpeed; - private String windGaugesIdString; - private String dayString; - - public BoatAndWindSpeedWithOriginInfoImpl(Speed boatSpeed, Speed windSpeed, String windGaugesIdString, - String dayString) { - this.boatSpeed = boatSpeed; - this.windSpeed = windSpeed; - this.windGaugesIdString = windGaugesIdString; - this.dayString = dayString; - } - - @Override - public Speed getBoatSpeed() { - return boatSpeed; - } - - @Override - public Speed getWindSpeed() { - return windSpeed; - } - - @Override - public String getWindGaugesIdString() { - return windGaugesIdString; - } - - @Override - public String getDayString() { - return dayString; - } - -} diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/impl/DataPointWithOriginInfoImpl.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/impl/DataPointWithOriginInfoImpl.java deleted file mode 100644 index 680b667fdaf..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/impl/DataPointWithOriginInfoImpl.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.sap.sailing.polars.data.impl; - -import com.sap.sailing.polars.data.DataPointWithOriginInfo; - -public class DataPointWithOriginInfoImpl implements DataPointWithOriginInfo { - - private Double rawData; - - private String windGaugeIdString; - - private String dayString; - - public DataPointWithOriginInfoImpl(Double rawData, String windGaugeIdString, String dayString) { - this.rawData = rawData; - this.windGaugeIdString = windGaugeIdString; - this.dayString = dayString; - } - - @Override - public Double getRawData() { - return rawData; - } - - @Override - public String getWindGaugeIdString() { - return windGaugeIdString; - } - - @Override - public String getDayString() { - return dayString; - } - - @Override - public int compareTo(DataPointWithOriginInfo o) { - return getRawData().compareTo(o.getRawData()); - } - -} diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/impl/PolarFixImpl.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/impl/PolarFixImpl.java deleted file mode 100644 index 7b874d4e920..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/data/impl/PolarFixImpl.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.sap.sailing.polars.data.impl; - -import java.text.SimpleDateFormat; -import java.util.HashSet; -import java.util.Set; - -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.common.Bearing; -import com.sap.sailing.domain.common.PolarSheetGenerationSettings; -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.Wind; -import com.sap.sailing.domain.common.WindSource; -import com.sap.sailing.domain.common.WindSourceType; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.tracking.GPSFixTrack; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.polars.data.PolarFix; -import com.sap.sse.common.TimePoint; - -public class PolarFixImpl implements PolarFix { - - private SpeedWithBearing boatSpeed; - private Speed windSpeed; - private double trueWindAngleDeg; - private String gaugeIdString; - private String dayString; - - public PolarFixImpl(GPSFixMoving fix, TrackedRace race, GPSFixTrack track, - Wind windSpeed, PolarSheetGenerationSettings settings, String gaugeIdString) { - boatSpeed = track.getEstimatedSpeed(fix.getTimePoint()); - Bearing bearing = boatSpeed.getBearing(); - - Position position = fix.getPosition(); - this.gaugeIdString = gaugeIdString; - dayString = createDayString(race); - this.windSpeed = windSpeed; - Set windSourcesToExclude; - if (settings.useOnlyEstimatedForWindDirection()) { - windSourcesToExclude = collectWindSourcesToIgnoreForBearing(race, /* exclude course based */true); - } else { - windSourcesToExclude = new HashSet(); - } - - Wind windEstimated = race.getWind(position, fix.getTimePoint(), windSourcesToExclude); - if (windEstimated == null) { - // no estimated wind; try to include course layout - windSourcesToExclude = collectWindSourcesToIgnoreForBearing(race, /* exclude course based */false); - windEstimated = race.getWind(position, fix.getTimePoint(), windSourcesToExclude); - } - if (windEstimated == null) { - windEstimated = windSpeed; // maybe no upwind start; need to default to measured wind speed/direction - } - Bearing windBearing = windEstimated.getFrom(); - trueWindAngleDeg = bearing.getDifferenceTo(windBearing).getDegrees(); - } - - private String createDayString(TrackedRace race) { - TimePoint startTimePoint = race.getStartOfRace(); - String resultDateString = "NoDate"; - if (startTimePoint != null) { - SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd"); - resultDateString = fmt.format(startTimePoint.asDate()); - } - - return resultDateString; - } - - public Set collectWindSourcesToIgnoreForBearing(TrackedRace race, boolean excludeCourseBased) { - Set windSourcesToExclude = new HashSet(); - Iterable combinedSources = race.getWindSources(WindSourceType.COMBINED); - for (WindSource combinedSource : combinedSources) { - windSourcesToExclude.add(combinedSource); - } - if (excludeCourseBased) { - Iterable courseSources = race.getWindSources(WindSourceType.COURSE_BASED); - for (WindSource courseSource : courseSources) { - windSourcesToExclude.add(courseSource); - } - } - Iterable expSources = race.getWindSources(WindSourceType.EXPEDITION); - for (WindSource expSource : expSources) { - windSourcesToExclude.add(expSource); - } - Iterable rcSources = race.getWindSources(WindSourceType.RACECOMMITTEE); - for (WindSource rcSource : rcSources) { - windSourcesToExclude.add(rcSource); - } - Iterable webSources = race.getWindSources(WindSourceType.WEB); - for (WindSource webSource : webSources) { - windSourcesToExclude.add(webSource); - } - return windSourcesToExclude; - } - - @Override - public SpeedWithBearing getBoatSpeed() { - return boatSpeed; - } - - @Override - public Speed getWindSpeed() { - return windSpeed; - } - - @Override - public double getTrueWindAngleDeg() { - return trueWindAngleDeg; - } - - @Override - public String getGaugeIdString() { - return gaugeIdString; - } - - @Override - public String getDayString() { - return dayString; - } - -} diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/generation/PolarSheetGenerator.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/generation/PolarSheetGenerator.java deleted file mode 100644 index a227cbf7212..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/generation/PolarSheetGenerator.java +++ /dev/null @@ -1,273 +0,0 @@ -package com.sap.sailing.polars.generation; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.sap.sailing.domain.common.PolarSheetGenerationSettings; -import com.sap.sailing.domain.common.PolarSheetsData; -import com.sap.sailing.domain.common.PolarSheetsHistogramData; -import com.sap.sailing.domain.common.Speed; -import com.sap.sailing.domain.common.impl.PolarSheetsDataImpl; -import com.sap.sailing.domain.common.impl.WindSpeedSteppingWithMaxDistance; -import com.sap.sailing.polars.data.BoatAndWindSpeedWithOriginInfo; -import com.sap.sailing.polars.data.DataPointWithOriginInfo; -import com.sap.sailing.polars.data.PolarFix; -import com.sap.sailing.polars.data.impl.BoatAndWindSpeedWithOriginInfoImpl; -import com.sap.sailing.polars.data.impl.DataPointWithOriginInfoImpl; - -public class PolarSheetGenerator { - - private final List> polarData; - - private WindSpeedSteppingWithMaxDistance stepping; - - private PolarSheetGenerationSettings settings; - - private final Set fixes; - - public PolarSheetGenerator(Set fixes, PolarSheetGenerationSettings settings) { - this.settings = settings; - this.fixes = fixes; - stepping = settings.getWindSpeedStepping(); - polarData = initializePolarDataContainer(); - } - - private List> initializePolarDataContainer() { - List> container = new ArrayList>(); - for (int i = 0; i < 360; i++) { - container.add(new ArrayList()); - } - return container; - } - - private void addPolarFix(PolarFix polarFix) { - long roundedAngleDeg = Math.round(polarFix.getTrueWindAngleDeg()); - Speed boatSpeed = polarFix.getBoatSpeed(); - Speed windSpeed = polarFix.getWindSpeed(); - int angleDeg = (int) roundedAngleDeg; - if (angleDeg < 0) { - angleDeg = (360 + angleDeg); - } - BoatAndWindSpeedWithOriginInfo speeds = new BoatAndWindSpeedWithOriginInfoImpl(boatSpeed, windSpeed, - polarFix.getGaugeIdString(), polarFix.getDayString()); - polarData.get(angleDeg).add(speeds); - } - - /** - * - * @return results already averaged per angle. Also datacount overall and per angle. And a completion flag to show - * if the complete polar sheet has been generated or if the current results are only an intermediate - * product. - */ - public PolarSheetsData generate() { - - for (PolarFix fix : fixes) { - addPolarFix(fix); - } - - PolarSheetHistogramBuilder histogramBuilder = new PolarSheetHistogramBuilder(settings); - - int levelCount = stepping.getNumberOfLevels(); - Number[][] averagedPolarDataByWindSpeed = new Number[levelCount][360]; - Integer[] dataCountPerAngle = new Integer[360]; - int dataCount = 0; - Map dataCountPerAngleForWindspeed = new HashMap(); - Map> histogramDataMap = new HashMap>(); - Map totalDataCountPerWindSpeed = new HashMap(); - for (int levelIndex = 0; levelIndex < levelCount; levelIndex++) { - dataCountPerAngleForWindspeed.put(levelIndex, new Integer[360]); - histogramDataMap.put(levelIndex, new HashMap()); - totalDataCountPerWindSpeed.put(levelIndex, 0); - } - for (int angleIndex = 0; angleIndex < 360; angleIndex++) { - // Avoid Concurrent modification of lists, so get current state as an array; lock would slow things down - BoatAndWindSpeedWithOriginInfo[] values = polarData.get(angleIndex).toArray( - new BoatAndWindSpeedWithOriginInfo[polarData.get(angleIndex).size()]); - dataCount = dataCount + values.length; - dataCountPerAngle[angleIndex] = values.length; - double[] sumsPerWindSpeed = new double[levelCount]; - int[] dataCountPerWindSpeed = new int[levelCount]; - Map> dataSetForWindLevel = new HashMap>(); - gatherPolarData(values, sumsPerWindSpeed, dataCountPerWindSpeed, dataSetForWindLevel); - - calculateStatisticalMeasuresAndHistogramData(histogramBuilder, levelCount, averagedPolarDataByWindSpeed, - dataCountPerAngleForWindspeed, histogramDataMap, totalDataCountPerWindSpeed, angleIndex, - sumsPerWindSpeed, dataCountPerWindSpeed, dataSetForWindLevel); - - } - - for (int j = 0; j < levelCount; j++) { - for (PolarSheetsHistogramData histogramData : histogramDataMap.get(j).values()) { - Double polarSheetPointConfidenceMeasure = Math.min(1, histogramData.getCoefficiantOfVariation() - * (histogramData.getDataCount() / (double) totalDataCountPerWindSpeed.get(j)) * 80); - histogramData.setConfidenceMeasure(polarSheetPointConfidenceMeasure); - } - } - - PolarSheetsData data = new PolarSheetsDataImpl(averagedPolarDataByWindSpeed, dataCount, - dataCountPerAngleForWindspeed, stepping, histogramDataMap); - - return data; - } - - private void gatherPolarData(BoatAndWindSpeedWithOriginInfo[] values, double[] sumsPerWindSpeed, - int[] dataCountPerWindSpeed, Map> dataSetForWindLevel) { - for (BoatAndWindSpeedWithOriginInfo singleDataPoint : values) { - if (singleDataPoint != null) { - double windSpeed = singleDataPoint.getWindSpeed().getKnots(); - int level = stepping.getLevelIndexForValue(windSpeed); - if (level >= 0) { - double speed = singleDataPoint.getBoatSpeed().getKnots(); - String windGaugesIdString = singleDataPoint.getWindGaugesIdString(); - String dayString = singleDataPoint.getDayString(); - if (!dataSetForWindLevel.containsKey(level)) { - dataSetForWindLevel.put(level, new ArrayList()); - } - dataSetForWindLevel.get(level).add( - new DataPointWithOriginInfoImpl(speed, windGaugesIdString, dayString)); - sumsPerWindSpeed[level] = sumsPerWindSpeed[level] + speed; - dataCountPerWindSpeed[level]++; - } - } - } - } - - private void calculateStatisticalMeasuresAndHistogramData(PolarSheetHistogramBuilder histogramBuilder, - int levelCount, Number[][] averagedPolarDataByWindSpeed, - Map dataCountPerAngleForWindspeed, - Map> histogramDataMap, - Map totalDataCountPerWindSpeed, int angleIndex, double[] sumsPerWindSpeed, - int[] dataCountPerWindSpeed, Map> dataSetForWindLevel) { - for (int levelIndex = 0; levelIndex < levelCount; levelIndex++) { - if (settings.shouldRemoveOutliers() && dataSetForWindLevel.get(levelIndex) != null) { - List withoutOutliers = new ArrayList(); - Collections.sort(dataSetForWindLevel.get(levelIndex)); - if (dataCountPerWindSpeed[levelIndex] > /* Minimum data count for outlier detection */10) { - performOutlierExclusion(sumsPerWindSpeed, dataCountPerWindSpeed, dataSetForWindLevel, levelIndex, - withoutOutliers); - } - - } - - if (dataCountPerWindSpeed[levelIndex] < settings.getMinimumDataCountPerAngle()) { - dataSetForWindLevel.put(levelIndex, new ArrayList()); - sumsPerWindSpeed[levelIndex] = 0; - dataCountPerWindSpeed[levelIndex] = 0; - } - totalDataCountPerWindSpeed.put(levelIndex, totalDataCountPerWindSpeed.get(levelIndex) - + dataCountPerWindSpeed[levelIndex]); - Double average = sumsPerWindSpeed[levelIndex] / dataCountPerWindSpeed[levelIndex]; - if (average.isNaN()) { - average = new Double(0); - } - averagedPolarDataByWindSpeed[levelIndex][angleIndex] = average; - dataCountPerAngleForWindspeed.get(levelIndex)[angleIndex] = dataCountPerWindSpeed[levelIndex]; - double coefficiantOfVariation = 0; - if (dataCountPerWindSpeed[levelIndex] > 0 && average > 0) { - Double variance = sumsPerWindSpeed[levelIndex] / dataCountPerWindSpeed[levelIndex]; - Double standardDeviation = Math.sqrt(variance); - coefficiantOfVariation = standardDeviation / average; - } - List rawData = dataSetForWindLevel.get(levelIndex); - if (rawData == null || rawData.size() <= 0) { - continue; - } - PolarSheetsHistogramData histogramData = histogramBuilder - .build(rawData, angleIndex, coefficiantOfVariation); - histogramDataMap.get(levelIndex).put(angleIndex, histogramData); - - } - } - - private void performOutlierExclusion(double[] sumsPerWindSpeed, int[] dataCountPerWindSpeed, - Map> dataSetForWindLevel, int levelIndex, - List withoutOutliers) { - for (int dataIndex = 0; dataIndex < dataSetForWindLevel.get(levelIndex).size(); dataIndex++) { - DataPointWithOriginInfo dataPoint = dataSetForWindLevel.get(levelIndex).get(dataIndex); - double pct = getNeighboorhoodSizePercentage(dataCountPerWindSpeed, dataSetForWindLevel, levelIndex, - dataIndex, dataPoint, settings); - if (pct >= settings.getOutlierMinimumNeighborhoodPct()) { - withoutOutliers.add(dataPoint); - } else { - sumsPerWindSpeed[levelIndex] = sumsPerWindSpeed[levelIndex] - dataPoint.getRawData(); - dataCountPerWindSpeed[levelIndex]--; - } - } - dataSetForWindLevel.put(levelIndex, withoutOutliers); - } - - /** - * This method calculates the pct of the points neighborhoods based on a distance (in the settings) compared to the - * complete dataset. - */ - public static double getNeighboorhoodSizePercentage(int[] dataCountPerWindSpeed, - Map> valuesInMap, int levelIndex, int dataIndex, - DataPointWithOriginInfo dataPoint, PolarSheetGenerationSettings settings) { - int neighborCount = 0; - double pct = .0; - - int index = dataIndex; - // Left side - boolean done = false; - while (!done) { - index--; - if (index < 0) { - done = true; - } else { - Double dataPointToCheckForNeighborStatus = valuesInMap.get(levelIndex).get(index).getRawData(); - if (dataPoint.getRawData() - dataPointToCheckForNeighborStatus <= settings - .getOutlierDetectionNeighborhoodRadius()) { - neighborCount++; - } else { - done = true; - } - pct = (double) neighborCount / (double) dataCountPerWindSpeed[levelIndex]; - if (pct >= settings.getOutlierMinimumNeighborhoodPct()) { - done = true; - } - } - } - index = dataIndex; - // Right side - done = false; - while (!done) { - index++; - if (index >= dataCountPerWindSpeed[levelIndex]) { - done = true; - } else { - Double dataPointToCheckForNeighborStatus = valuesInMap.get(levelIndex).get(index).getRawData(); - if (dataPointToCheckForNeighborStatus - dataPoint.getRawData() <= settings - .getOutlierDetectionNeighborhoodRadius()) { - neighborCount++; - } else { - done = true; - } - pct = (double) neighborCount / (double) dataCountPerWindSpeed[levelIndex]; - if (pct >= settings.getOutlierMinimumNeighborhoodPct()) { - done = true; - } - } - } - pct = (double) neighborCount / (double) dataCountPerWindSpeed[levelIndex]; - return pct; - } - - /** - * Can be used to present more detailed data. - * - * @return The complete set of datapoints that have been added. Can be quite big, depending on the amount of races - * and competitors. - */ - public List> getCompleteData() { - return polarData; - } - - public WindSpeedSteppingWithMaxDistance getStepping() { - return stepping; - } - -} diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/generation/PolarSheetHistogramBuilder.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/generation/PolarSheetHistogramBuilder.java deleted file mode 100644 index b6af619266e..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/generation/PolarSheetHistogramBuilder.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.sap.sailing.polars.generation; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.sap.sailing.domain.common.PolarSheetGenerationSettings; -import com.sap.sailing.domain.common.PolarSheetsHistogramData; -import com.sap.sailing.domain.common.impl.PolarSheetsHistogramDataImpl; -import com.sap.sailing.polars.data.DataPointWithOriginInfo; - -public class PolarSheetHistogramBuilder { - - private PolarSheetGenerationSettings settings; - - public PolarSheetHistogramBuilder(PolarSheetGenerationSettings settings) { - this.settings = settings; - } - - public PolarSheetsHistogramData build(List rawData, int angleIndex, - double coefficiantOfVariation) { - DataPointWithOriginInfo minPoint = Collections.min(rawData); - DataPointWithOriginInfo maxPoint = Collections.max(rawData); - - Double min = minPoint.getRawData(); - Double max = maxPoint.getRawData(); - - int numberOfColumns = settings.getNumberOfHistogramColumns(); - double range = (max - min) / numberOfColumns; - Double[] xValues = new Double[numberOfColumns]; - for (int u = 0; u < numberOfColumns; u++) { - xValues[u] = min + u * range + (0.5 * range); - } - - Map yValuesByGaugeIds = new HashMap(); - Map yValuesByDay = new HashMap(); - Map yValuesByDayAndGaugeId = new HashMap(); - Integer[] yValues = new Integer[numberOfColumns]; - for (int i = 0; i < yValues.length; i++) { - yValues[i] = 0; - } - for (DataPointWithOriginInfo dataPoint : rawData) { - double notRoundedYet = (dataPoint.getRawData() - min) / range; - int u = (int) notRoundedYet; - if (u == numberOfColumns) { - // For max value - u = numberOfColumns - 1; - } - yValues[u]++; - - String gaugeIdsString = dataPoint.getWindGaugeIdString(); - createHistogramDataForArrangeOption(numberOfColumns, yValuesByGaugeIds, u, gaugeIdsString); - - String dayString = dataPoint.getDayString(); - createHistogramDataForArrangeOption(numberOfColumns, yValuesByDay, u, dayString); - - String dayAndGaugeIdString = dayString + "-" + gaugeIdsString; - createHistogramDataForArrangeOption(numberOfColumns, yValuesByDayAndGaugeId, u, dayAndGaugeIdString); - - } - - PolarSheetsHistogramData histogramData = new PolarSheetsHistogramDataImpl(angleIndex, xValues, yValues, - yValuesByGaugeIds, yValuesByDay, yValuesByDayAndGaugeId, rawData.size(), coefficiantOfVariation); - return histogramData; - } - - private void createHistogramDataForArrangeOption(int numberOfColumns, Map arrangerMap, int u, - String arrangerString) { - if (!arrangerMap.containsKey(arrangerString)) { - Integer[] yValuesForArrangerString = new Integer[numberOfColumns]; - for (int i = 0; i < yValuesForArrangerString.length; i++) { - yValuesForArrangerString[i] = 0; - } - arrangerMap.put(arrangerString, yValuesForArrangerString); - } - Integer[] yValuesForOneSpecificArrangerString = arrangerMap.get(arrangerString); - yValuesForOneSpecificArrangerString[u]++; - } - -} 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 index c88612c6323..17c60cebd1b 100755 --- 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 @@ -9,8 +9,6 @@ import java.net.MalformedURLException; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; import java.util.logging.Logger; import org.apache.commons.math.analysis.polynomials.PolynomialFunction; @@ -25,7 +23,6 @@ import com.sap.sailing.domain.common.Bearing; import com.sap.sailing.domain.common.LegType; import com.sap.sailing.domain.common.ManeuverType; import com.sap.sailing.domain.common.PolarSheetGenerationSettings; -import com.sap.sailing.domain.common.PolarSheetsData; import com.sap.sailing.domain.common.Speed; import com.sap.sailing.domain.common.Tack; import com.sap.sailing.domain.common.confidence.BearingWithConfidence; @@ -39,10 +36,6 @@ import com.sap.sailing.domain.polars.PolarDataService; import com.sap.sailing.domain.polars.PolarsChangedListener; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.polars.PolarDataOperation; -import com.sap.sailing.polars.aggregation.PolarFixAggregator; -import com.sap.sailing.polars.aggregation.SimplePolarFixRaceInterval; -import com.sap.sailing.polars.data.PolarFix; -import com.sap.sailing.polars.generation.PolarSheetGenerator; import com.sap.sailing.polars.mining.BearingClusterGroup; import com.sap.sailing.polars.mining.CubicRegressionPerCourseProcessor; import com.sap.sailing.polars.mining.PolarDataMiner; @@ -139,23 +132,6 @@ public class PolarDataServiceImpl implements PolarDataService, return averageSpeedAndCourseOverGround; } - @Override - public PolarSheetsData generatePolarSheet(Set trackedRaces, PolarSheetGenerationSettings settings, - Executor executor) throws InterruptedException, ExecutionException { - Set fixes; - 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 PolarSheetsData getPolarSheetForBoatClass(BoatClass boatClass) { - return polarDataMiner.createFullSheetForBoatClass(boatClass); - } - @Override public Set getAllBoatClassesWithPolarSheetsAvailable() { return polarDataMiner.getAvailableBoatClasses(); diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/MovingAveragePolarClusterKey.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/MovingAveragePolarClusterKey.java deleted file mode 100644 index 2b05318b6a3..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/MovingAveragePolarClusterKey.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.sap.sailing.polars.mining; - -import com.sap.sailing.domain.common.Speed; -import com.sap.sse.datamining.annotations.Dimension; -import com.sap.sse.datamining.data.Cluster; - -public interface MovingAveragePolarClusterKey extends LegTypePolarClusterKey { - - /** - * - * @return wind speed cluster - */ - @Dimension(messageKey = "windSpeed") - Cluster getWindSpeedCluster(); - -} \ No newline at end of file diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/MovingAverageProcessor.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/MovingAverageProcessor.java deleted file mode 100755 index 896c3f6aace..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/MovingAverageProcessor.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.sap.sailing.polars.mining; - -import java.io.Serializable; - -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.SpeedWithBearingWithConfidence; -import com.sap.sailing.domain.common.LegType; -import com.sap.sailing.domain.common.Speed; -import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException; -import com.sap.sse.datamining.components.Processor; -import com.sap.sse.datamining.data.ClusterGroup; -import com.sap.sse.datamining.impl.components.GroupedDataEntry; - -public interface MovingAverageProcessor extends Processor, Void>, - Serializable { - SpeedWithBearingWithConfidence getAverageSpeedAndCourseOverGround(BoatClass boatClass, Speed windSpeed, - LegType legType) throws NotEnoughDataHasBeenAddedException; - - ClusterGroup getSpeedCluster(); -} \ No newline at end of file diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/MovingAverageProcessorImpl.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/MovingAverageProcessorImpl.java deleted file mode 100755 index e48a36ebaaa..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/MovingAverageProcessorImpl.java +++ /dev/null @@ -1,223 +0,0 @@ -package com.sap.sailing.polars.mining; - -import java.util.HashMap; -import java.util.Map; -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.LegType; -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.KnotSpeedWithBearingImpl; -import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException; -import com.sap.sailing.domain.tracking.WindWithConfidence; -import com.sap.sailing.polars.regression.MovingAverageBoatSpeedEstimator; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; -import com.sap.sse.datamining.components.AdditionalResultDataBuilder; -import com.sap.sse.datamining.data.Cluster; -import com.sap.sse.datamining.data.ClusterGroup; -import com.sap.sse.datamining.factories.GroupKeyFactory; -import com.sap.sse.datamining.impl.components.GroupedDataEntry; -import com.sap.sse.datamining.shared.GroupKey; - -public class MovingAverageProcessorImpl implements MovingAverageProcessor { - - private static final long serialVersionUID = 9016357546663534562L; - - private static final Logger logger = Logger.getLogger(MovingAverageProcessorImpl.class.getName()); - - private final Map boatSpeedEstimators = new HashMap<>(); - - private final Map averageAngleContainers = new HashMap<>(); - - private final ClusterGroup speedClusterGroup; - - public MovingAverageProcessorImpl(ClusterGroup speedClusterGroup) { - this.speedClusterGroup = speedClusterGroup; - } - - @Override - public boolean canProcessElements() { - // TODO Auto-generated method stub - return true; - } - - @Override - public void processElement(GroupedDataEntry element) { - GPSFixMovingWithPolarContext fix = element.getDataEntry(); - if (fix.getLegType() == LegType.UPWIND || fix.getLegType() == LegType.DOWNWIND) { - GroupKey key = element.getKey(); - MovingAverageBoatSpeedEstimator boatSpeedEstimator; - synchronized (boatSpeedEstimators) { - boatSpeedEstimator = boatSpeedEstimators.get(key); - if (boatSpeedEstimator == null) { - boatSpeedEstimator = new MovingAverageBoatSpeedEstimator(); - boatSpeedEstimators.put(key, boatSpeedEstimator); - } - } - AverageAngleContainer averageAngleContainer; - synchronized (averageAngleContainers) { - averageAngleContainer = averageAngleContainers.get(key); - if (averageAngleContainer == null) { - averageAngleContainer = new AverageAngleContainer(); - averageAngleContainers.put(key, averageAngleContainer); - } - } - BearingWithConfidence angleToTheWind = fix.getAbsoluteAngleToTheWind(); - WindWithConfidence> windSpeed = fix.getWind(); - SpeedWithBearingWithConfidence boatSpeedWithConfidence = fix.getBoatSpeed(); - WindWithConfidence> windWithConfidenceForSpeed = windSpeed; - double confidenceForWindSpeed = windWithConfidenceForSpeed.getConfidence(); - double confidenceForWindBearing = angleToTheWind.getConfidence(); - double confidenceForBoatSpeed = boatSpeedWithConfidence.getConfidence(); - double averagedConfidence = (confidenceForBoatSpeed + confidenceForWindBearing + confidenceForWindSpeed) / 3; - averageAngleContainer.addFix(angleToTheWind.getObject().getDegrees()); - boatSpeedEstimator.addData(boatSpeedWithConfidence.getObject(), averagedConfidence); - } - } - - @Override - public void finish() throws InterruptedException { - // Nothing to do here - } - - @Override - public boolean isFinished() { - return false; - } - - @Override - public void abort() { - // TODO Auto-generated method stub - } - - @Override - public boolean isAborted() { - // TODO Auto-generated method stub - return false; - } - - @Override - public AdditionalResultDataBuilder getAdditionalResultData(AdditionalResultDataBuilder additionalDataBuilder) { - // TODO Auto-generated method stub - return null; - } - - public static class SpeedWithConfidenceAndDataCount { - private final SpeedWithConfidence speedWithConfidence; - private final int dataCount; - - protected SpeedWithConfidenceAndDataCount(SpeedWithConfidence speedWithConfidence, int dataCount) { - super(); - this.speedWithConfidence = speedWithConfidence; - this.dataCount = dataCount; - } - - public SpeedWithConfidence getSpeedWithConfidence() { - return speedWithConfidence; - } - - public int getDataCount() { - return dataCount; - } - } - - private SpeedWithConfidenceAndDataCount estimateBoatSpeed(GroupKey key) throws NotEnoughDataHasBeenAddedException { - MovingAverageBoatSpeedEstimator boatSpeedEstimator = boatSpeedEstimators.get(key); - if (boatSpeedEstimator == null) { - throw new NotEnoughDataHasBeenAddedException(); - } - Speed speedWithoutConfidence = boatSpeedEstimator.estimateSpeed(); - final int dataCount = boatSpeedEstimator.getDataCount(); - double confidence = boatSpeedEstimator.getConfidence(); - return new SpeedWithConfidenceAndDataCount(new SpeedWithConfidenceImpl(speedWithoutConfidence, - confidence, null), dataCount); - } - - private Bearing estimateAngle(GroupKey key) throws NotEnoughDataHasBeenAddedException { - AverageAngleContainer averageAngleContainer = averageAngleContainers.get(key); - if (averageAngleContainer == null) { - throw new NotEnoughDataHasBeenAddedException(); - } - return new DegreeBearingImpl(averageAngleContainer.getAverageAngleDeg()); - } - - @Override - public void onFailure(Throwable failure) { - logger.severe("Polar Data Mining Pipe failed."); - throw new RuntimeException("Polar Data Miner failed.", failure); - } - - @Override - public Class> getInputType() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Class getResultType() { - // No result type here, since this is a special case of a processor. It's the end of the pipe so to say. - return null; - } - - @Override - public SpeedWithBearingWithConfidence getAverageSpeedAndCourseOverGround(BoatClass boatClass, - Speed windSpeed, LegType legType) throws NotEnoughDataHasBeenAddedException { - SpeedWithBearingWithConfidence result = estimateSpeedAndAngle(boatClass, windSpeed, legType); - return result; - } - - private SpeedWithBearingWithConfidence estimateSpeedAndAngle(BoatClass boatClass, Speed windSpeed, - LegType legType) throws NotEnoughDataHasBeenAddedException { - GroupKey key = createGroupKey(boatClass, windSpeed, legType); - Bearing angleDiffTrueWindToBoat = estimateAngle(key); - SpeedWithConfidence estimatedSpeed = estimateBoatSpeed(key).getSpeedWithConfidence(); - SpeedWithBearing speedWithBearing = new KnotSpeedWithBearingImpl(estimatedSpeed.getObject().getKnots(), - angleDiffTrueWindToBoat); - return new SpeedWithBearingWithConfidenceImpl(speedWithBearing, estimatedSpeed.getConfidence(), null); - } - - private GroupKey createGroupKey(final BoatClass boatClass, final Speed windSpeed, final LegType legType) { - MovingAveragePolarClusterKey key = new MovingAveragePolarClusterKey() { - - @Override - public BoatClass getBoatClass() { - return boatClass; - } - - @Override - public Cluster getWindSpeedCluster() { - return speedClusterGroup.getClusterFor(windSpeed); - } - - @Override - public LegType getLegType() { - return legType; - } - }; - GroupKey compoundKey; - try { - compoundKey = GroupKeyFactory.createNestingCompoundKeyFor(key, PolarDataDimensionCollectionFactory - .getMovingAverageClusterKeyDimensions().iterator()); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - return compoundKey; - } - - @Override - public ClusterGroup getSpeedCluster() { - return speedClusterGroup; - } - -} 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 497a4ecc277..058c4bf28f5 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 @@ -12,24 +12,10 @@ import com.sap.sse.datamining.functions.Function; public class PolarDataDimensionCollectionFactory { - public static Collection> getMovingAverageClusterKeyDimensions() throws NoSuchMethodException { - Collection> dimensions = new ArrayList<>(); - FunctionFactory functionFactory = new FunctionFactory(); - addTackAndLegTypeDimensions(dimensions, functionFactory); - - addPolarBaseDimension(dimensions, functionFactory); - - Function windSpeedFunction = functionFactory - .createMethodWrappingFunction(MovingAveragePolarClusterKey.class.getMethod("getWindSpeedCluster", - new Class[0])); - dimensions.add(windSpeedFunction); - return dimensions; - } - private static void addTackAndLegTypeDimensions(Collection> dimensions, FunctionFactory functionFactory) throws NoSuchMethodException { Function legTypeFunction = functionFactory - .createMethodWrappingFunction(MovingAveragePolarClusterKey.class.getMethod("getLegType", + .createMethodWrappingFunction(LegTypePolarClusterKey.class.getMethod("getLegType", new Class[0])); dimensions.add(legTypeFunction); } @@ -37,7 +23,7 @@ public class PolarDataDimensionCollectionFactory { private static void addPolarBaseDimension(Collection> dimensions, FunctionFactory functionFactory) throws NoSuchMethodException { Function boatClassFunction = functionFactory - .createMethodWrappingFunction(MovingAveragePolarClusterKey.class.getMethod("getBoatClass", + .createMethodWrappingFunction(BasePolarClusterKey.class.getMethod("getBoatClass", new Class[0])); dimensions.add(boatClassFunction); } diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/regression/MovingAverageBoatSpeedEstimator.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/regression/MovingAverageBoatSpeedEstimator.java deleted file mode 100644 index e71db7a76f5..00000000000 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/regression/MovingAverageBoatSpeedEstimator.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.sap.sailing.polars.regression; - -import java.io.ObjectInputStream; -import java.io.Serializable; - -import com.sap.sailing.domain.common.Speed; -import com.sap.sailing.domain.common.impl.KnotSpeedImpl; -import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException; -import com.sap.sailing.polars.mining.MovingAverageProcessorImpl; -import com.sap.sse.concurrent.LockUtil; -import com.sap.sse.concurrent.NamedReentrantReadWriteLock; - -/** - * Supplies incremental arithmetic mean for confidence and speed. - *

- * - * {@link #estimateSpeed(double, double)} returns the average of the speed. - *

- * - * Note that this class should only be used for a small wind interval on a polar sheet. The - * {@link MovingAverageProcessorImpl} is one example for that. It has one instance of the - * {@link MovingAverageBoatSpeedEstimator} for each wind boatclass, speed level and rounded angle combination. - * - * @author Frederik Petersen (D054528) - * - */ -public class MovingAverageBoatSpeedEstimator implements Serializable { - - private static final long serialVersionUID = -254184914347332658L; - - private double speedSumInKnots = 0; - - private transient NamedReentrantReadWriteLock lock = createLock(); - - private double confidenceSum = 0; - - private int dataCount = 0; - - public Speed estimateSpeed() throws NotEnoughDataHasBeenAddedException { - LockUtil.lockForRead(lock); - if (dataCount < 1) { - throw new NotEnoughDataHasBeenAddedException(); - } - try { - return new KnotSpeedImpl(speedSumInKnots / dataCount); - } finally { - LockUtil.unlockAfterRead(lock); - } - } - - public void addData(Speed boatSpeed, double confidence) { - LockUtil.lockForWrite(lock); - try { - speedSumInKnots = speedSumInKnots + boatSpeed.getKnots(); - dataCount++; - confidenceSum = confidenceSum + confidence; - } finally { - LockUtil.unlockAfterWrite(lock); - } - } - - public int getDataCount() { - LockUtil.lockForRead(lock); - try { - return dataCount; - } finally { - LockUtil.unlockAfterRead(lock); - } - } - - public double getConfidence() { - LockUtil.lockForRead(lock); - try { - return confidenceSum / dataCount; - } finally { - LockUtil.unlockAfterRead(lock); - } - } - - private void readObject(ObjectInputStream ois) { - lock = createLock(); - } - - private NamedReentrantReadWriteLock createLock() { - return new NamedReentrantReadWriteLock(getClass().getName(), true); - } - -}