From 3a989c1c1a094fb23259a75b0af8c6ee5cf7d589 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 17 Aug 2016 15:05:58 +0200 Subject: [PATCH 01/96] Added some initial tests for save/load of DoubleVectorFixes/SensorFixes --- .../test/impl/SensorFixStoreAndLoadTest.java | 216 ++++++++++++++++++ .../mock/MockGPSFixMongoServiceFinder.java | 4 + 2 files changed, 220 insertions(+) create mode 100644 java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java new file mode 100644 index 00000000000..80e913d7247 --- /dev/null +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java @@ -0,0 +1,216 @@ +package com.sap.sailing.domain.racelogtracking.test.impl; + +import static com.sap.sse.common.Util.size; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNull; +import static org.mockito.Mockito.mock; + +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.Collections; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.mongodb.DB; +import com.mongodb.MongoException; +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDefineMarkEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorBravoMappingEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRevokeEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.impl.RegattaLogImpl; +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.Course; +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.Sideline; +import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.base.impl.CourseImpl; +import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; +import com.sap.sailing.domain.base.impl.RegattaImpl; +import com.sap.sailing.domain.base.impl.WaypointImpl; +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.sensordata.BravoSensorDataMetadata; +import com.sap.sailing.domain.common.tracking.DoubleVectorFix; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.common.tracking.impl.DoubleVectorFixImpl; +import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; +import com.sap.sailing.domain.persistence.PersistenceFactory; +import com.sap.sailing.domain.persistence.impl.CollectionNames; +import com.sap.sailing.domain.persistence.racelog.tracking.impl.MongoSensorFixStoreImpl; +import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore; +import com.sap.sailing.domain.racelog.tracking.SensorFixMapper; +import com.sap.sailing.domain.racelog.tracking.SensorFixStore; +import com.sap.sailing.domain.racelog.tracking.test.mock.MockSmartphoneImeiServiceFinderFactory; +import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier; +import com.sap.sailing.domain.racelogsensortracking.SensorFixMapperFactory; +import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; +import com.sap.sailing.domain.racelogtracking.impl.BravoDataFixMapper; +import com.sap.sailing.domain.racelogtracking.impl.fixtracker.FixLoaderAndTracker; +import com.sap.sailing.domain.ranking.OneDesignRankingMetric; +import com.sap.sailing.domain.regattalog.impl.EmptyRegattaLogStore; +import com.sap.sailing.domain.tracking.BravoFixTrack; +import com.sap.sailing.domain.tracking.DynamicTrack; +import com.sap.sailing.domain.tracking.DynamicTrackedRace; +import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; +import com.sap.sailing.domain.tracking.Track; +import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl; +import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl; +import com.sap.sailing.domain.tracking.impl.EmptyWindStore; +import com.sap.sse.common.Timed; +import com.sap.sse.common.impl.MillisecondsTimePoint; + +public class SensorFixStoreAndLoadTest { + protected final MockSmartphoneImeiServiceFinderFactory serviceFinderFactory = new MockSmartphoneImeiServiceFinderFactory(); + protected final DeviceIdentifier device = new SmartphoneImeiIdentifier("a"); + protected RaceLog raceLog; + protected RegattaLog regattaLog; + protected SensorFixStore store; + protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + protected final Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + protected final Mark mark = DomainFactory.INSTANCE.getOrCreateMark("mark"); + protected final Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); + private final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er"); + + protected final AbstractLogEventAuthor author = new LogEventAuthorImpl("author", 0); + private DynamicTrackedRace trackedRace; + + protected GPSFixMoving createFix(long millis, double lat, double lng, double knots, double degrees) { + return new GPSFixMovingImpl(new DegreePosition(lat, lng), + new MillisecondsTimePoint(millis), new KnotSpeedWithBearingImpl(knots, new DegreeBearingImpl(degrees))); + } + + @Before + public void setUp() throws UnknownHostException, MongoException { + DB db = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory().getDatabase(); + db.getCollection(CollectionNames.GPS_FIXES.name()).drop(); + db.getCollection(CollectionNames.GPS_FIXES_METADATA.name()).drop(); + raceLog = new RaceLogImpl("racelog"); + regattaLog = new RegattaLogImpl("regattalog"); + + store = new MongoSensorFixStoreImpl(PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory(), serviceFinderFactory); + + regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark)); + regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author, new MillisecondsTimePoint(1), 0, mark2)); + Course course = new CourseImpl("course", Arrays.asList(new Waypoint[] { new WaypointImpl(mark), + new WaypointImpl(mark2) })); + RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, Arrays.asList(comp, comp2)); + DynamicTrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE, + EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, + /* startDate */ null, /* endDate */null, null, null, "a", null)); + trackedRace = new DynamicTrackedRaceImpl(regatta, race, + Collections. emptyList(), EmptyWindStore.INSTANCE, 0, 0, 0, + /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new, mock(RaceLogResolver.class)); + } + + @After + public void after() { + DB db = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory().getDatabase(); + db.getCollection(CollectionNames.GPS_FIXES.name()).drop(); + db.getCollection(CollectionNames.GPS_FIXES_METADATA.name()).drop(); + } + + @Test + public void testLoadAlreadyAddedFixes() throws InterruptedException { + + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); +// regattaLog.add(new RegattaLogCloseOpenEndedDeviceMappingEventImpl(new MillisecondsTimePoint(4), author, deviceMappingEventId, closingTimePoint) + + addFixes(); + + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); + + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); + + trackedRace.waitForLoadingToFinish(); + + BravoFixTrack bravoFixTrack = trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME); + + testNumberOfRawFixes(bravoFixTrack, 2); + + fixLoaderAndTracker.stop(true); + } + + @Test + public void testAddFixesWhileTracking() throws InterruptedException { + + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); + + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); + + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); + + addFixes(); + + trackedRace.waitForLoadingToFinish(); + + BravoFixTrack bravoFixTrack = trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME); + + testNumberOfRawFixes(bravoFixTrack, 2); + + fixLoaderAndTracker.stop(true); + } + + @Test + public void testNothingloadedForRevokedMapping() throws InterruptedException { + RegattaLogDeviceCompetitorBravoMappingEventImpl mappingEvent = new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200)); + regattaLog.add(mappingEvent); + regattaLog.add(new RegattaLogRevokeEventImpl(author, mappingEvent, "Test purposes")); + + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); + + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); + + addFixes(); + + trackedRace.waitForLoadingToFinish(); + + assertNull(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME)); + + fixLoaderAndTracker.stop(true); + } + + private void addFixes() { + store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(110, 1337.0)); + store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(120, 1338.0)); + store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(210, 1336.0)); + } + + private FixLoaderAndTracker createFixLoaderAndTracker() { + return new FixLoaderAndTracker(trackedRace, store, new SensorFixMapperFactory() { + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public > SensorFixMapper createCompetitorMapper( + Class> eventType) { + return (SensorFixMapper)new BravoDataFixMapper(); + } + }); + } + + protected void testNumberOfRawFixes(Track track, long expected) { + track.lockForRead(); + assertEquals(expected, size(track.getRawFixes())); + track.unlockAfterRead(); + } + + private DoubleVectorFix createBravoDoubleVectorFixWithRideHeight(long timestamp, double rideHeight) { + double[] fixData = new double[BravoSensorDataMetadata.INSTANCE.getColumns().size()]; + fixData[BravoSensorDataMetadata.INSTANCE.rideHeightColumn] = rideHeight; + return new DoubleVectorFixImpl(new MillisecondsTimePoint(timestamp), fixData); + } +} diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.testsupport/src/com/sap/sailing/domain/racelog/tracking/test/mock/MockGPSFixMongoServiceFinder.java b/java/com.sap.sailing.domain.racelogtrackingadapter.testsupport/src/com/sap/sailing/domain/racelog/tracking/test/mock/MockGPSFixMongoServiceFinder.java index f7cc5ebfb8f..587b128c16d 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.testsupport/src/com/sap/sailing/domain/racelog/tracking/test/mock/MockGPSFixMongoServiceFinder.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.testsupport/src/com/sap/sailing/domain/racelog/tracking/test/mock/MockGPSFixMongoServiceFinder.java @@ -6,11 +6,13 @@ import java.util.Set; import com.sap.sailing.domain.common.tracking.impl.CompactGPSFixImpl; import com.sap.sailing.domain.common.tracking.impl.CompactGPSFixMovingImpl; +import com.sap.sailing.domain.common.tracking.impl.DoubleVectorFixImpl; import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl; import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; import com.sap.sailing.domain.persistence.impl.DomainObjectFactoryImpl; import com.sap.sailing.domain.persistence.impl.MongoObjectFactoryImpl; import com.sap.sailing.domain.persistence.racelog.tracking.FixMongoHandler; +import com.sap.sailing.domain.persistence.racelog.tracking.impl.DoubleVectorFixMongoHandlerImpl; import com.sap.sailing.domain.persistence.racelog.tracking.impl.GPSFixMongoHandlerImpl; import com.sap.sailing.domain.persistence.racelog.tracking.impl.GPSFixMovingMongoHandlerImpl; import com.sap.sse.common.TypeBasedServiceFinder; @@ -20,6 +22,7 @@ public class MockGPSFixMongoServiceFinder implements TypeBasedServiceFinder movingHandler = new GPSFixMovingMongoHandlerImpl(mof, dof); private final FixMongoHandler handler = new GPSFixMongoHandlerImpl(mof, dof); + private final FixMongoHandler doubleVectorFixHandler = new DoubleVectorFixMongoHandlerImpl(mof, dof); @Override public FixMongoHandler findService(String fixType) { @@ -27,6 +30,7 @@ public class MockGPSFixMongoServiceFinder implements TypeBasedServiceFinder Date: Wed, 17 Aug 2016 17:17:41 +0200 Subject: [PATCH 02/96] Fixed a bug that caused RegattaLogDeviceMappings.mappingChanged to be called under wrong conditions --- .../impl/fixtracker/RegattaLogDeviceMappings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RegattaLogDeviceMappings.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RegattaLogDeviceMappings.java index b0a4cb254c3..ed19707f292 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RegattaLogDeviceMappings.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RegattaLogDeviceMappings.java @@ -261,7 +261,7 @@ public abstract class RegattaLogDeviceMappings { oldMappings); if (oldMapping == null) { mappingAdded(newMapping); - } else if (newMapping.getTimeRange().equals(oldMapping.getTimeRange())) { + } else if (!newMapping.getTimeRange().equals(oldMapping.getTimeRange())) { mappingChanged(oldMapping, newMapping); } } From a69df323d7020676224e73b7d33672997b8e80ce Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 17 Aug 2016 17:19:10 +0200 Subject: [PATCH 03/96] Added a failing test for a case that isn't currently implemented: When revoking the close event for a DeviceMapping event, fixes after the old end TimePoint need to be loaded. --- .../test/impl/SensorFixStoreAndLoadTest.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java index 80e913d7247..eb75a935ed0 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java @@ -8,6 +8,7 @@ import static org.mockito.Mockito.mock; import java.net.UnknownHostException; import java.util.Arrays; import java.util.Collections; +import java.util.UUID; import org.junit.After; import org.junit.Before; @@ -22,6 +23,7 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogCloseOpenEndedDeviceMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDefineMarkEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorBravoMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRevokeEventImpl; @@ -183,6 +185,34 @@ public class SensorFixStoreAndLoadTest { fixLoaderAndTracker.stop(true); } + + @Test + public void testLoadFixesWhenClosingEventIsRevoked() throws InterruptedException { + UUID mappingEventId = UUID.randomUUID(); + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(MillisecondsTimePoint.now(), new MillisecondsTimePoint(3), author, mappingEventId, comp, device, new MillisecondsTimePoint(100), null)); + RegattaLogCloseOpenEndedDeviceMappingEventImpl closeEvent = new RegattaLogCloseOpenEndedDeviceMappingEventImpl(new MillisecondsTimePoint(4), author, mappingEventId, new MillisecondsTimePoint(200)); + regattaLog.add(closeEvent); + + addFixes(); + + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); + + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); + + trackedRace.waitForLoadingToFinish(); + + BravoFixTrack bravoFixTrack = trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME); + + testNumberOfRawFixes(bravoFixTrack, 2); + + regattaLog.add(new RegattaLogRevokeEventImpl(author, closeEvent, "Test purposes")); + + trackedRace.waitForLoadingToFinish(); + testNumberOfRawFixes(bravoFixTrack, 3); + + fixLoaderAndTracker.stop(true); + } private void addFixes() { store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(110, 1337.0)); From ba8e2a605151e234dc417a8886653054559e96c7 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 17 Aug 2016 17:20:57 +0200 Subject: [PATCH 04/96] When the TimeRange of a DeviceMapping changes we need to load fixes for partial TimeRanges that weren't already covered by the old mapping's TimeRange --- .../impl/fixtracker/FixLoaderAndTracker.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/FixLoaderAndTracker.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/FixLoaderAndTracker.java index 43f5f0b9851..582c0f56e6e 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/FixLoaderAndTracker.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/FixLoaderAndTracker.java @@ -365,8 +365,22 @@ public class FixLoaderAndTracker implements TrackingDataLoader { @Override protected void mappingChanged(DeviceMappingWithRegattaLogEvent oldMapping, DeviceMappingWithRegattaLogEvent newMapping) { - // TODO can the new time range be bigger than the old one? In this case we would need to load the - // additional time range. + final TimeRange newTimeRange = newMapping.getTimeRange(); + final TimeRange oldTimeRange = oldMapping.getTimeRange(); + if(newTimeRange.endsAfter(oldTimeRange)) { + final TimePoint oldTo= oldTimeRange.to(); + final TimePoint newFrom = newTimeRange.from(); + final TimePoint from = oldTo.after(newFrom) ? oldTo : newFrom; + final TimeRange rangeToLoad = new TimeRangeImpl(from, newTimeRange.to()); + loadFixes(rangeToLoad, newMapping); + } + if(newTimeRange.startsBefore(oldTimeRange)) { + final TimePoint oldFrom= oldTimeRange.from(); + final TimePoint newTo = newTimeRange.to(); + final TimePoint to = oldFrom.after(newTo) ? oldFrom : newTo; + final TimeRange rangeToLoad = new TimeRangeImpl(newTimeRange.from(), to); + loadFixes(rangeToLoad, newMapping); + } } } } From 748c101077903672ebcaa871236394db865d2f2e Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Thu, 18 Aug 2016 12:01:55 +0200 Subject: [PATCH 05/96] Added more tests for save/load of DoubleVectorFixes/SensorFixes and mapping of BravoFixes --- .../test/impl/SensorFixStoreAndLoadTest.java | 254 +++++++++++++----- 1 file changed, 191 insertions(+), 63 deletions(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java index eb75a935ed0..6134828798b 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java @@ -74,13 +74,17 @@ import com.sap.sse.common.Timed; import com.sap.sse.common.impl.MillisecondsTimePoint; public class SensorFixStoreAndLoadTest { - protected final MockSmartphoneImeiServiceFinderFactory serviceFinderFactory = new MockSmartphoneImeiServiceFinderFactory(); + private static final long FIX_TIMESTAMP = 110; + private static final double FIX_RIDE_HEIGHT = 1337.0; + protected final MockSmartphoneImeiServiceFinderFactory serviceFinderFactory = new MockSmartphoneImeiServiceFinderFactory(); protected final DeviceIdentifier device = new SmartphoneImeiIdentifier("a"); protected RaceLog raceLog; protected RegattaLog regattaLog; protected SensorFixStore store; - protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); - protected final Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, + null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + protected final Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, + null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); protected final Mark mark = DomainFactory.INSTANCE.getOrCreateMark("mark"); protected final Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); private final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er"); @@ -89,10 +93,10 @@ public class SensorFixStoreAndLoadTest { private DynamicTrackedRace trackedRace; protected GPSFixMoving createFix(long millis, double lat, double lng, double knots, double degrees) { - return new GPSFixMovingImpl(new DegreePosition(lat, lng), - new MillisecondsTimePoint(millis), new KnotSpeedWithBearingImpl(knots, new DegreeBearingImpl(degrees))); + return new GPSFixMovingImpl(new DegreePosition(lat, lng), new MillisecondsTimePoint(millis), + new KnotSpeedWithBearingImpl(knots, new DegreeBearingImpl(degrees))); } - + @Before public void setUp() throws UnknownHostException, MongoException { DB db = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory().getDatabase(); @@ -100,20 +104,23 @@ public class SensorFixStoreAndLoadTest { db.getCollection(CollectionNames.GPS_FIXES_METADATA.name()).drop(); raceLog = new RaceLogImpl("racelog"); regattaLog = new RegattaLogImpl("regattalog"); - - store = new MongoSensorFixStoreImpl(PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory(), serviceFinderFactory); - regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark)); - regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author, new MillisecondsTimePoint(1), 0, mark2)); - Course course = new CourseImpl("course", Arrays.asList(new Waypoint[] { new WaypointImpl(mark), - new WaypointImpl(mark2) })); + store = new MongoSensorFixStoreImpl(PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), + PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory(), serviceFinderFactory); + + regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, + new MillisecondsTimePoint(1), 0, mark)); + regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author, + new MillisecondsTimePoint(1), 0, mark2)); + Course course = new CourseImpl("course", + Arrays.asList(new Waypoint[] { new WaypointImpl(mark), new WaypointImpl(mark2) })); RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, Arrays.asList(comp, comp2)); DynamicTrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */ null, /* endDate */null, null, null, "a", null)); - trackedRace = new DynamicTrackedRaceImpl(regatta, race, - Collections. emptyList(), EmptyWindStore.INSTANCE, 0, 0, 0, - /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new, mock(RaceLogResolver.class)); + trackedRace = new DynamicTrackedRaceImpl(regatta, race, Collections. emptyList(), + EmptyWindStore.INSTANCE, 0, 0, 0, /* useMarkPassingCalculator */ false, OneDesignRankingMetric::new, + mock(RaceLogResolver.class)); } @After @@ -122,112 +129,233 @@ public class SensorFixStoreAndLoadTest { db.getCollection(CollectionNames.GPS_FIXES.name()).drop(); db.getCollection(CollectionNames.GPS_FIXES_METADATA.name()).drop(); } - + @Test public void testLoadAlreadyAddedFixes() throws InterruptedException { - - regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); -// regattaLog.add(new RegattaLogCloseOpenEndedDeviceMappingEventImpl(new MillisecondsTimePoint(4), author, deviceMappingEventId, closingTimePoint) - + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, + device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); + addFixes(); - + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); - + trackedRace.attachRaceLog(raceLog); trackedRace.attachRegattaLog(regattaLog); - + trackedRace.waitForLoadingToFinish(); - - BravoFixTrack bravoFixTrack = trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME); - - testNumberOfRawFixes(bravoFixTrack, 2); - + + testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 2); + fixLoaderAndTracker.stop(true); } - + @Test public void testAddFixesWhileTracking() throws InterruptedException { - - regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); - + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, + device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); - + trackedRace.attachRaceLog(raceLog); trackedRace.attachRegattaLog(regattaLog); - + addFixes(); - + trackedRace.waitForLoadingToFinish(); - - BravoFixTrack bravoFixTrack = trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME); - - testNumberOfRawFixes(bravoFixTrack, 2); - + + testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 2); + fixLoaderAndTracker.stop(true); } - + + @Test + public void testNoFixesAreLoadedIfNoStoredFixIsInTimeRange() throws InterruptedException { + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, + device, new MillisecondsTimePoint(300), new MillisecondsTimePoint(400))); + + addFixes(); + + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); + + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); + + trackedRace.waitForLoadingToFinish(); + + testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 0); + + fixLoaderAndTracker.stop(true); + } + + @Test + public void testFixesNotInMappedTiomeRangeAreIgnoredWhileTracking() throws InterruptedException { + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, + device, new MillisecondsTimePoint(300), new MillisecondsTimePoint(400))); + + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); + + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); + + addFixes(); + + trackedRace.waitForLoadingToFinish(); + + testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 0); + + fixLoaderAndTracker.stop(true); + } + + @Test + public void testCompetitorWithoutMappingHasNoTrack() throws InterruptedException { + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, + device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); + + addFixes(); + + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); + + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); + + trackedRace.waitForLoadingToFinish(); + + assertNull(trackedRace.getSensorTrack(comp2, BravoFixTrack.TRACK_NAME)); + + fixLoaderAndTracker.stop(true); + } + + @Test + public void testDeviceIsMappedToDifferentCompetitorsInDifferentTimeRanges() throws InterruptedException { + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, + device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp2, + device, new MillisecondsTimePoint(201), new MillisecondsTimePoint(300))); + + addFixes(); + + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); + + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); + + trackedRace.waitForLoadingToFinish(); + + testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 2); + testNumberOfRawFixes(trackedRace.getSensorTrack(comp2, BravoFixTrack.TRACK_NAME), 1); + + fixLoaderAndTracker.stop(true); + } + + @Test + public void testMultipleMappingsForOneDeviceAndCompetitor() throws InterruptedException { + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, + device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, + device, new MillisecondsTimePoint(201), new MillisecondsTimePoint(300))); + + addFixes(); + + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); + + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); + + trackedRace.waitForLoadingToFinish(); + + testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 3); + + fixLoaderAndTracker.stop(true); + } + @Test public void testNothingloadedForRevokedMapping() throws InterruptedException { - RegattaLogDeviceCompetitorBravoMappingEventImpl mappingEvent = new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200)); + RegattaLogDeviceCompetitorBravoMappingEventImpl mappingEvent = new RegattaLogDeviceCompetitorBravoMappingEventImpl( + new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(100), + new MillisecondsTimePoint(200)); regattaLog.add(mappingEvent); regattaLog.add(new RegattaLogRevokeEventImpl(author, mappingEvent, "Test purposes")); - + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); - + trackedRace.attachRaceLog(raceLog); trackedRace.attachRegattaLog(regattaLog); - + addFixes(); - + trackedRace.waitForLoadingToFinish(); - + assertNull(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME)); - + fixLoaderAndTracker.stop(true); } - + @Test public void testLoadFixesWhenClosingEventIsRevoked() throws InterruptedException { UUID mappingEventId = UUID.randomUUID(); - regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(MillisecondsTimePoint.now(), new MillisecondsTimePoint(3), author, mappingEventId, comp, device, new MillisecondsTimePoint(100), null)); - RegattaLogCloseOpenEndedDeviceMappingEventImpl closeEvent = new RegattaLogCloseOpenEndedDeviceMappingEventImpl(new MillisecondsTimePoint(4), author, mappingEventId, new MillisecondsTimePoint(200)); + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(MillisecondsTimePoint.now(), + new MillisecondsTimePoint(3), author, mappingEventId, comp, device, new MillisecondsTimePoint(100), + null)); + RegattaLogCloseOpenEndedDeviceMappingEventImpl closeEvent = new RegattaLogCloseOpenEndedDeviceMappingEventImpl( + new MillisecondsTimePoint(4), author, mappingEventId, new MillisecondsTimePoint(200)); regattaLog.add(closeEvent); - + addFixes(); - + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); - + trackedRace.attachRaceLog(raceLog); trackedRace.attachRegattaLog(regattaLog); - + trackedRace.waitForLoadingToFinish(); - + BravoFixTrack bravoFixTrack = trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME); - + testNumberOfRawFixes(bravoFixTrack, 2); - + regattaLog.add(new RegattaLogRevokeEventImpl(author, closeEvent, "Test purposes")); trackedRace.waitForLoadingToFinish(); testNumberOfRawFixes(bravoFixTrack, 3); - + + fixLoaderAndTracker.stop(true); + } + + @Test + public void testBravoFixIsCorrectlyWrapped() throws InterruptedException { + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, + device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); + + addFixes(); + + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); + + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); + + trackedRace.waitForLoadingToFinish(); + + BravoFixTrack bravoFixTrack = trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME); + assertEquals(1337.0, + bravoFixTrack.getFirstFixAtOrAfter(new MillisecondsTimePoint(FIX_TIMESTAMP)).getRideHeight()); + fixLoaderAndTracker.stop(true); } private void addFixes() { - store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(110, 1337.0)); + store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP, FIX_RIDE_HEIGHT)); store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(120, 1338.0)); store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(210, 1336.0)); } private FixLoaderAndTracker createFixLoaderAndTracker() { return new FixLoaderAndTracker(trackedRace, store, new SensorFixMapperFactory() { - + @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public > SensorFixMapper createCompetitorMapper( Class> eventType) { - return (SensorFixMapper)new BravoDataFixMapper(); + return (SensorFixMapper) new BravoDataFixMapper(); } }); } @@ -237,7 +365,7 @@ public class SensorFixStoreAndLoadTest { assertEquals(expected, size(track.getRawFixes())); track.unlockAfterRead(); } - + private DoubleVectorFix createBravoDoubleVectorFixWithRideHeight(long timestamp, double rideHeight) { double[] fixData = new double[BravoSensorDataMetadata.INSTANCE.getColumns().size()]; fixData[BravoSensorDataMetadata.INSTANCE.rideHeightColumn] = rideHeight; From eaa2cd487a89ae04dfdcedfadda97f251fc5b731 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Thu, 18 Aug 2016 15:00:52 +0200 Subject: [PATCH 06/96] Added more tests for save/load of DoubleVectorFixes/SensorFixes and mapping of BravoFixes --- .../test/impl/SensorFixStoreAndLoadTest.java | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java index 6134828798b..c1bc8443537 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java @@ -188,7 +188,7 @@ public class SensorFixStoreAndLoadTest { } @Test - public void testFixesNotInMappedTiomeRangeAreIgnoredWhileTracking() throws InterruptedException { + public void testFixesNotInMappedTimeRangeAreIgnoredWhileTracking() throws InterruptedException { regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(300), new MillisecondsTimePoint(400))); @@ -289,6 +289,34 @@ public class SensorFixStoreAndLoadTest { fixLoaderAndTracker.stop(true); } + + @Test + public void testFixesAreLoadedIfThereIsOneRevokedAndOneNonRevokedMapping() throws InterruptedException { + // revoked mapping timestamp 100-300 + RegattaLogDeviceCompetitorBravoMappingEventImpl mappingEvent = new RegattaLogDeviceCompetitorBravoMappingEventImpl( + new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(100), + new MillisecondsTimePoint(300)); + regattaLog.add(mappingEvent); + regattaLog.add(new RegattaLogRevokeEventImpl(author, mappingEvent, "Test purposes")); + + // non-revoked mapping timestamp 100-200 + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, + device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); + + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); + + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); + + addFixes(); + + trackedRace.waitForLoadingToFinish(); + + // Only Fixes from 100 to 200 may be included + testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 2); + + fixLoaderAndTracker.stop(true); + } @Test public void testLoadFixesWhenClosingEventIsRevoked() throws InterruptedException { From fa8be0f0b1947e60eb7eb45d56835d7fc5941a5e Mon Sep 17 00:00:00 2001 From: Papick Garcia Taboada Date: Thu, 1 Sep 2016 17:35:05 +0200 Subject: [PATCH 07/96] Better device to competitor mapping visualization on bravo data import --- .../trackimport/DoubleVectorFixImporter.java | 2 +- .../AbstractFileImportWidget.java | 8 +- ...gImportSensorDataAndAddMappingsDialog.java | 55 ++------ .../adminconsole/SensorDataImportWidget.java | 1 + ...ileImportDeviceIdentifierTableWrapper.java | 124 ++++++++++++++++-- .../impl/SensorDataImportServlet.java | 14 +- .../trackfiles/test/BravoDataImportTest.java | 2 +- .../impl/BravoDataImporterImpl.java | 4 +- 8 files changed, 140 insertions(+), 70 deletions(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/trackimport/DoubleVectorFixImporter.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/trackimport/DoubleVectorFixImporter.java index 6a44a51156b..0e1e75cdf6f 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/trackimport/DoubleVectorFixImporter.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/trackimport/DoubleVectorFixImporter.java @@ -37,7 +37,7 @@ public interface DoubleVectorFixImporter { * @throws IOException * if there is a problem while reading the file */ - void importFixes(InputStream inputStream, Callback callback, String sourceName) + void importFixes(InputStream inputStream, Callback callback, String filename, String sourceName) throws FormatNotSupportedException, IOException; /** diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractFileImportWidget.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractFileImportWidget.java index 22f61ee64c9..d462a8ddd9a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractFileImportWidget.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractFileImportWidget.java @@ -41,6 +41,7 @@ public abstract class AbstractFileImportWidget extends Composite { protected final SailingServiceAsync sailingService; private final StringMessages stringMessages; private final ErrorReporter errorReporter; + private boolean shouldClearListOnNewUploadComplete = true; protected AbstractFileImportWidget(String formActionUrl, StringMessages stringMessages, TrackFileImportDeviceIdentifierTableWrapper table, SailingServiceAsync sailingService, @@ -73,7 +74,9 @@ public abstract class AbstractFileImportWidget extends Composite { @UiHandler("formPanelUi") void onFileImportComplete(SubmitCompleteEvent event) { - table.getDataProvider().getList().clear(); + if (shouldClearListOnNewUploadComplete) { + table.getDataProvider().getList().clear(); + } String[] uuids = event.getResults().split("\\n"); if (uuids.length != 1 || (uuids.length > 0 && !uuids[0].isEmpty())) { sailingService.getTrackFileImportDeviceIds(Arrays.asList(uuids), @@ -106,4 +109,7 @@ public abstract class AbstractFileImportWidget extends Composite { protected abstract void getImporterTypes(AsyncCallback> callback); + protected void setShouldClearListOnNewUploadComplete(boolean shouldClearListOnNewUploadComplete) { + this.shouldClearListOnNewUploadComplete = shouldClearListOnNewUploadComplete; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogImportSensorDataAndAddMappingsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogImportSensorDataAndAddMappingsDialog.java index 6691ddf6c7c..919bfa88667 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogImportSensorDataAndAddMappingsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogImportSensorDataAndAddMappingsDialog.java @@ -2,9 +2,7 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.List; -import java.util.Map; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.CaptionPanel; @@ -31,11 +29,8 @@ public class RegattaLogImportSensorDataAndAddMappingsDialog extends DataEntryDia protected final CompetitorTableWrapper> competitorTable; private final StringMessages stringMessages; - private final Map mappings = new HashMap<>(); private TrackFileImportDeviceIdentifierDTO deviceToSelect; - private CompetitorDTO compToSelect; - private boolean inInstableTransitionState = false; public RegattaLogImportSensorDataAndAddMappingsDialog(SailingServiceAsync sailingService, final ErrorReporter errorReporter, final StringMessages stringMessages, String leaderboardName, @@ -50,11 +45,16 @@ public class RegattaLogImportSensorDataAndAddMappingsDialog extends DataEntryDia }, true, callback); this.stringMessages = stringMessages; deviceIdTable = new TrackFileImportDeviceIdentifierTableWrapper(sailingService, stringMessages, errorReporter); + deviceIdTable.removeTrackNameColumn(); + importWidget = new SensorDataImportWidget(deviceIdTable, stringMessages, sailingService, errorReporter); deviceIdTable.getSelectionModel().addSelectionChangeHandler(new SelectionChangeEvent.Handler() { @Override public void onSelectionChange(SelectionChangeEvent event) { - deviceSelectionChanged(deviceIdTable.getSelectionModel().getSelectedObject()); + CompetitorDTO mappedComp = deviceIdTable.getMappedCompetitorForCurrentSelection(); + if (mappedComp != null) { + competitorTable.getSelectionModel().setSelected(mappedComp, true); + } } }); competitorTable = new CompetitorTableWrapper<>(sailingService, stringMessages, errorReporter, /* multiSelection */ @@ -63,7 +63,8 @@ public class RegattaLogImportSensorDataAndAddMappingsDialog extends DataEntryDia competitorTable.getSelectionModel().addSelectionChangeHandler(new SelectionChangeEvent.Handler() { @Override public void onSelectionChange(SelectionChangeEvent event) { - mappedToSelectionChanged(competitorTable.getSelectionModel().getSelectedObject()); + deviceIdTable.didSelectCompetitorForMapping(competitorTable.getSelectionModel().getSelectedObject()); + validate(); } }); @@ -95,42 +96,6 @@ public class RegattaLogImportSensorDataAndAddMappingsDialog extends DataEntryDia } } - /** - * Avoid programmatic deselections that re-trigger the selection listeners and lead to a loop. - */ - private void select() { - if (inInstableTransitionState) { - if (deviceIdTable.getSelectionModel().getSelectedObject() == deviceToSelect - && competitorTable.getSelectionModel().getSelectedObject() == compToSelect) { - inInstableTransitionState = false; - } - } else { - inInstableTransitionState = true; - selectOrClear(deviceIdTable.getSelectionModel(), deviceToSelect); - selectOrClear(competitorTable.getSelectionModel(), compToSelect); - } - } - - private void mappedToSelectionChanged(CompetitorDTO mappedTo) { - if (!inInstableTransitionState) { - TrackFileImportDeviceIdentifierDTO device = deviceIdTable.getSelectionModel().getSelectedObject(); - if (device != null) { - mappings.put(device, mappedTo); - } - compToSelect = mappedTo; - } - select(); - validate(); - } - - private void deviceSelectionChanged(TrackFileImportDeviceIdentifierDTO deviceId) { - if (!inInstableTransitionState) { - deviceToSelect = deviceId; - compToSelect = deviceId != null ? mappings.get(deviceId) : null; - } - select(); - } - @Override protected Widget getAdditionalWidget() { HorizontalPanel panel = new HorizontalPanel(); @@ -150,9 +115,9 @@ public class RegattaLogImportSensorDataAndAddMappingsDialog extends DataEntryDia protected Collection getResult() { List result = new ArrayList<>(); String dataType = importWidget.getSelectedImporterType(); - for (TrackFileImportDeviceIdentifierDTO device : mappings.keySet()) { + for (TrackFileImportDeviceIdentifierDTO device : deviceIdTable.getMappings().keySet()) { DeviceIdentifierDTO deviceIdDto = new DeviceIdentifierDTO("FILE", device.uuidAsString); - MappableToDevice mappedTo = mappings.get(device); + MappableToDevice mappedTo = deviceIdTable.getMappings().get(device); result.add(new TypedDeviceMappingDTO(deviceIdDto, device.from, device.to, mappedTo, null, dataType)); } return result; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SensorDataImportWidget.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SensorDataImportWidget.java index c6ff1885e74..20ec0834486 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SensorDataImportWidget.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SensorDataImportWidget.java @@ -14,6 +14,7 @@ public class SensorDataImportWidget extends AbstractFileImportWidget implements final SailingServiceAsync sailingService, final ErrorReporter errorReporter) { super("/sailingserver/sensordata/import", stringMessages, table, sailingService, errorReporter); setMultipleFileUploadEnabled(true); + setShouldClearListOnNewUploadComplete(false); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackFileImportDeviceIdentifierTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackFileImportDeviceIdentifierTableWrapper.java index 12d730da684..d5beb50c7f5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackFileImportDeviceIdentifierTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackFileImportDeviceIdentifierTableWrapper.java @@ -1,6 +1,18 @@ package com.sap.sailing.gwt.ui.adminconsole; +import java.util.HashMap; +import java.util.Map; + +import com.google.gwt.dom.builder.shared.TableCellBuilder; +import com.google.gwt.dom.builder.shared.TableRowBuilder; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; +import com.google.gwt.safehtml.shared.SafeHtmlUtils; +import com.google.gwt.user.cellview.client.AbstractCellTable; +import com.google.gwt.user.cellview.client.AbstractCellTable.Style; +import com.google.gwt.user.cellview.client.DefaultCellTableBuilder; +import com.google.gwt.user.cellview.client.RowStyles; import com.google.gwt.user.cellview.client.TextColumn; +import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; @@ -9,11 +21,13 @@ import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.celltable.EntityIdentityComparator; import com.sap.sse.gwt.client.celltable.RefreshableSingleSelectionModel; -public class TrackFileImportDeviceIdentifierTableWrapper extends TableWrapper> { - - public TrackFileImportDeviceIdentifierTableWrapper(SailingServiceAsync sailingService, StringMessages stringMessages, - ErrorReporter errorReporter) { +public class TrackFileImportDeviceIdentifierTableWrapper extends + TableWrapper> { + private TextColumn trackNameColumn; + private final Map mappings = new HashMap<>(); + + public TrackFileImportDeviceIdentifierTableWrapper(SailingServiceAsync sailingService, + StringMessages stringMessages, ErrorReporter errorReporter) { super(sailingService, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true, new EntityIdentityComparator() { @Override @@ -21,54 +35,49 @@ RefreshableSingleSelectionModel> { TrackFileImportDeviceIdentifierDTO dto2) { return dto1.uuidAsString.equals(dto2.uuidAsString); } + @Override public int hashCode(TrackFileImportDeviceIdentifierDTO t) { return t.uuidAsString.hashCode(); } }); - TextColumn uuidColumn = new TextColumn() { @Override public String getValue(TrackFileImportDeviceIdentifierDTO object) { return object.uuidAsString; } }; - TextColumn fileNameColumn = new TextColumn() { @Override public String getValue(TrackFileImportDeviceIdentifierDTO object) { return object.fileName; } }; - - TextColumn trackNameColumn = new TextColumn() { + trackNameColumn = new TextColumn() { @Override public String getValue(TrackFileImportDeviceIdentifierDTO object) { return object.trackName; } }; - TextColumn fromColumn = new TextColumn() { @Override public String getValue(TrackFileImportDeviceIdentifierDTO object) { return DateAndTimeFormatterUtil.formatDateAndTime(object.from); } }; - TextColumn toColumn = new TextColumn() { @Override public String getValue(TrackFileImportDeviceIdentifierDTO object) { return DateAndTimeFormatterUtil.formatDateAndTime(object.to); } }; - TextColumn numberOfFixesColumn = new TextColumn() { @Override public String getValue(TrackFileImportDeviceIdentifierDTO object) { return "" + object.numFixes; } }; - + table.setTableBuilder(new MappingTableBuilder(table)); table.addColumn(uuidColumn, "UUID"); table.addColumn(fileNameColumn, "Filename"); table.addColumn(trackNameColumn, "Trackname"); @@ -77,4 +86,93 @@ RefreshableSingleSelectionModel> { table.addColumn(numberOfFixesColumn, "# fixes"); } + public void removeTrackNameColumn() { + table.removeColumn(trackNameColumn); + } + + class MappingTableBuilder extends DefaultCellTableBuilder { + private final String evenRowStyle; + private final String oddRowStyle; + private final String selectedRowStyle; + private final String cellStyle; + private final String evenCellStyle; + private final String oddCellStyle; + private final String firstColumnStyle; + private final String lastColumnStyle; + private final String selectedCellStyle; + private final AbstractCellTable cellTable; + + public MappingTableBuilder(AbstractCellTable cellTable) { + super(cellTable); + this.cellTable = cellTable; + Style style = cellTable.getResources().style(); + evenRowStyle = style.evenRow(); + oddRowStyle = style.oddRow(); + selectedRowStyle = " " + style.selectedRow(); + cellStyle = style.cell(); + evenCellStyle = " " + style.evenRowCell(); + oddCellStyle = " " + style.oddRowCell(); + firstColumnStyle = " " + style.firstColumn(); + lastColumnStyle = " " + style.lastColumn(); + selectedCellStyle = " " + style.selectedRowCell(); + } + + @Override + public void buildRowImpl(TrackFileImportDeviceIdentifierDTO rowValue, int absRowIndex) { + super.buildRowImpl(rowValue, absRowIndex); + boolean isEven = absRowIndex % 2 == 0; + + StringBuilder trClasses = new StringBuilder(isEven ? evenRowStyle : oddRowStyle); + RowStyles rowStyles = cellTable.getRowStyles(); + if (rowStyles != null) { + String extraRowStyles = rowStyles.getStyleNames(rowValue, absRowIndex); + if (extraRowStyles != null) { + trClasses.append(" ").append(extraRowStyles); + } + } + + StringBuilder tdClasses = new StringBuilder(cellStyle); + tdClasses.append(isEven ? evenCellStyle : oddCellStyle); + + TableRowBuilder tr = startRow(); + tr.className(trClasses.toString()); + tr.startTD().className(new StringBuilder(tdClasses).append(firstColumnStyle).toString()) + .html(SafeHtmlUtils.fromSafeConstant(" ")).end(); + TableCellBuilder td = tr.startTD(); + td.className(tdClasses.toString()); + td.colSpan(getColumns().size() - 1); + CompetitorDTO competitorDTO = mappings.get(rowValue); + if (competitorDTO == null) { + td.html(new SafeHtmlBuilder().appendEscaped("--").toSafeHtml()); + } else { + td.html(new SafeHtmlBuilder().appendEscaped(competitorDTO.getName()).toSafeHtml()); + } + td.end(); + tr.end(); + } + } + + public CompetitorDTO getMappedCompetitorForCurrentSelection() { + TrackFileImportDeviceIdentifierDTO selectedObject = getSelectionModel().getSelectedObject(); + if (selectedObject != null) { + return mappings.get(selectedObject); + } + return null; + } + + public void didSelectCompetitorForMapping(CompetitorDTO competitor) { + TrackFileImportDeviceIdentifierDTO selectedObject = getSelectionModel().getSelectedObject(); + if (selectedObject != null) { + if (competitor != null) { + mappings.put(selectedObject, competitor); + } else { + mappings.remove(selectedObject); + } + } + table.redraw(); + } + + public Map getMappings() { + return mappings; + } } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/SensorDataImportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/SensorDataImportServlet.java index 5d3f8db5a36..398e15a659e 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/SensorDataImportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/SensorDataImportServlet.java @@ -2,7 +2,6 @@ package com.sap.sailing.server.gateway.trackfiles.impl; import java.io.BufferedInputStream; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -54,16 +53,17 @@ public class SensorDataImportServlet extends AbstractFileUploadServlet { * * @throws IOException */ - private Iterable importFiles(Iterable> files) + private Iterable importFiles(Iterable> files) throws IOException { final Set deviceIds = new HashSet<>(); final Map from = new HashMap<>(); final Map to = new HashMap<>(); final Collection availableImporters = new LinkedHashSet<>(); availableImporters.addAll(getOSGiRegisteredImporters()); - for (Pair file : files) { + for (Pair file : files) { final String requestedImporterName = file.getA(); - BufferedInputStream in = new BufferedInputStream(file.getB()) { + final FileItem fi = file.getB(); + BufferedInputStream in = new BufferedInputStream(fi.getInputStream()) { @Override public void close() throws IOException { // prevent importers from closing this stream @@ -109,7 +109,7 @@ public class SensorDataImportServlet extends AbstractFileUploadServlet { } } } - }, requestedImporterName); + }, fi.getName(), requestedImporterName); logger.log(Level.INFO, "Successfully imported file " + requestedImporterName); } catch (FormatNotSupportedException e) { logger.log(Level.INFO, "Failed to import file " + requestedImporterName); @@ -124,7 +124,6 @@ public class SensorDataImportServlet extends AbstractFileUploadServlet { @Override protected void process(List fileItems, HttpServletRequest req, HttpServletResponse resp) throws IOException { - List> files = new ArrayList<>(); String importerName = null; searchForPrefferedImporter: for (FileItem fi : fileItems) { if ("preferredImporter".equalsIgnoreCase(fi.getFieldName())) { @@ -135,9 +134,10 @@ public class SensorDataImportServlet extends AbstractFileUploadServlet { if (importerName == null) { importerName = "BRAVO"; } + List> files = new ArrayList<>(); for (FileItem fi : fileItems) { if ("file".equalsIgnoreCase(fi.getFieldName())) { - files.add(new Pair<>(importerName, fi.getInputStream())); + files.add(new Pair<>(importerName, fi)); } } final Iterable mappingList = importFiles(files); diff --git a/java/com.sap.sailing.server.trackfiles.test/src/com/sap/sailing/server/trackfiles/test/BravoDataImportTest.java b/java/com.sap.sailing.server.trackfiles.test/src/com/sap/sailing/server/trackfiles/test/BravoDataImportTest.java index 7c07fa0f682..5fe5f150b5f 100644 --- a/java/com.sap.sailing.server.trackfiles.test/src/com/sap/sailing/server/trackfiles/test/BravoDataImportTest.java +++ b/java/com.sap.sailing.server.trackfiles.test/src/com/sap/sailing/server/trackfiles/test/BravoDataImportTest.java @@ -53,7 +53,7 @@ public class BravoDataImportTest { callbackCallCount++; sumRideHeight += new BravoFixImpl(fix).getRideHeight(); } - }, "source"); + }, "filename", "source"); Assert.assertEquals(importData.expectedFixesCount, callbackCallCount); Assert.assertEquals(importData.expectedAverageRideHeight, callbackCallCount == 0 ? sumRideHeight : sumRideHeight / callbackCallCount, 0.00001); diff --git a/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/BravoDataImporterImpl.java b/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/BravoDataImporterImpl.java index 48885321dd1..bf0ecf344ee 100644 --- a/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/BravoDataImporterImpl.java +++ b/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/BravoDataImporterImpl.java @@ -46,10 +46,10 @@ public class BravoDataImporterImpl implements DoubleVectorFixImporter { private final String BOF = "jjlDATE\tjjlTIME\tEpoch"; private static final int BATCH_SIZE = 5000; - public void importFixes(InputStream inputStream, Callback callback, String sourceName) + public void importFixes(InputStream inputStream, Callback callback, String filename, String sourceName) throws FormatNotSupportedException, IOException { final TrackFileImportDeviceIdentifier trackIdentifier = new TrackFileImportDeviceIdentifierImpl( - UUID.randomUUID(), sourceName, sourceName + "_Imu", MillisecondsTimePoint.now()); + UUID.randomUUID(), filename, sourceName + "_Imu", MillisecondsTimePoint.now()); try { LOG.fine("Import CSV from " + sourceName); final InputStreamReader isr; From 51e2b7007dafb203fb38971e83ec58b1c1f7d4b7 Mon Sep 17 00:00:00 2001 From: Vladislav Chumak Date: Mon, 5 Sep 2016 18:48:48 +0200 Subject: [PATCH 08/96] Extended tests for fix tracking with multiple fix types --- .../test/impl/SensorFixStoreAndLoadTest.java | 215 ++++++++++++++++-- 1 file changed, 200 insertions(+), 15 deletions(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java index c1bc8443537..18855395de3 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java @@ -5,9 +5,11 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNull; import static org.mockito.Mockito.mock; +import java.io.Serializable; import java.net.UnknownHostException; import java.util.Arrays; import java.util.Collections; +import java.util.List; import java.util.UUID; import org.junit.After; @@ -21,8 +23,12 @@ import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; +import com.sap.sailing.domain.abstractlog.regatta.MappingEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorSensorDataMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogCloseOpenEndedDeviceMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDefineMarkEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorBravoMappingEventImpl; @@ -46,6 +52,7 @@ import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; import com.sap.sailing.domain.common.sensordata.BravoSensorDataMetadata; import com.sap.sailing.domain.common.tracking.DoubleVectorFix; import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.common.tracking.SensorFix; import com.sap.sailing.domain.common.tracking.impl.DoubleVectorFixImpl; import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; import com.sap.sailing.domain.persistence.PersistenceFactory; @@ -63,6 +70,7 @@ import com.sap.sailing.domain.racelogtracking.impl.fixtracker.FixLoaderAndTracke import com.sap.sailing.domain.ranking.OneDesignRankingMetric; import com.sap.sailing.domain.regattalog.impl.EmptyRegattaLogStore; import com.sap.sailing.domain.tracking.BravoFixTrack; +import com.sap.sailing.domain.tracking.DynamicSensorFixTrack; import com.sap.sailing.domain.tracking.DynamicTrack; import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; @@ -70,14 +78,19 @@ import com.sap.sailing.domain.tracking.Track; import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl; import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl; import com.sap.sailing.domain.tracking.impl.EmptyWindStore; +import com.sap.sailing.domain.tracking.impl.SensorFixTrackImpl; +import com.sap.sse.common.TimePoint; import com.sap.sse.common.Timed; +import com.sap.sse.common.WithID; import com.sap.sse.common.impl.MillisecondsTimePoint; public class SensorFixStoreAndLoadTest { private static final long FIX_TIMESTAMP = 110; private static final double FIX_RIDE_HEIGHT = 1337.0; + private static final double FIX_TEST_VALUE = 12.0; protected final MockSmartphoneImeiServiceFinderFactory serviceFinderFactory = new MockSmartphoneImeiServiceFinderFactory(); protected final DeviceIdentifier device = new SmartphoneImeiIdentifier("a"); + protected final DeviceIdentifier deviceTest = new SmartphoneImeiIdentifier("b"); protected RaceLog raceLog; protected RegattaLog regattaLog; protected SensorFixStore store; @@ -135,7 +148,7 @@ public class SensorFixStoreAndLoadTest { regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); - addFixes(); + addBravoFixes(); FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); @@ -159,7 +172,7 @@ public class SensorFixStoreAndLoadTest { trackedRace.attachRaceLog(raceLog); trackedRace.attachRegattaLog(regattaLog); - addFixes(); + addBravoFixes(); trackedRace.waitForLoadingToFinish(); @@ -173,7 +186,7 @@ public class SensorFixStoreAndLoadTest { regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(300), new MillisecondsTimePoint(400))); - addFixes(); + addBravoFixes(); FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); @@ -197,7 +210,7 @@ public class SensorFixStoreAndLoadTest { trackedRace.attachRaceLog(raceLog); trackedRace.attachRegattaLog(regattaLog); - addFixes(); + addBravoFixes(); trackedRace.waitForLoadingToFinish(); @@ -211,7 +224,7 @@ public class SensorFixStoreAndLoadTest { regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); - addFixes(); + addBravoFixes(); FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); @@ -232,7 +245,7 @@ public class SensorFixStoreAndLoadTest { regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp2, device, new MillisecondsTimePoint(201), new MillisecondsTimePoint(300))); - addFixes(); + addBravoFixes(); FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); @@ -254,7 +267,7 @@ public class SensorFixStoreAndLoadTest { regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(201), new MillisecondsTimePoint(300))); - addFixes(); + addBravoFixes(); FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); @@ -269,7 +282,7 @@ public class SensorFixStoreAndLoadTest { } @Test - public void testNothingloadedForRevokedMapping() throws InterruptedException { + public void testNothingLoadedForRevokedMapping() throws InterruptedException { RegattaLogDeviceCompetitorBravoMappingEventImpl mappingEvent = new RegattaLogDeviceCompetitorBravoMappingEventImpl( new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200)); @@ -281,7 +294,7 @@ public class SensorFixStoreAndLoadTest { trackedRace.attachRaceLog(raceLog); trackedRace.attachRegattaLog(regattaLog); - addFixes(); + addBravoFixes(); trackedRace.waitForLoadingToFinish(); @@ -308,7 +321,7 @@ public class SensorFixStoreAndLoadTest { trackedRace.attachRaceLog(raceLog); trackedRace.attachRegattaLog(regattaLog); - addFixes(); + addBravoFixes(); trackedRace.waitForLoadingToFinish(); @@ -328,7 +341,7 @@ public class SensorFixStoreAndLoadTest { new MillisecondsTimePoint(4), author, mappingEventId, new MillisecondsTimePoint(200)); regattaLog.add(closeEvent); - addFixes(); + addBravoFixes(); FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); @@ -354,7 +367,7 @@ public class SensorFixStoreAndLoadTest { regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); - addFixes(); + addBravoFixes(); FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); @@ -364,26 +377,82 @@ public class SensorFixStoreAndLoadTest { trackedRace.waitForLoadingToFinish(); BravoFixTrack bravoFixTrack = trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME); - assertEquals(1337.0, + assertEquals(FIX_RIDE_HEIGHT, bravoFixTrack.getFirstFixAtOrAfter(new MillisecondsTimePoint(FIX_TIMESTAMP)).getRideHeight()); fixLoaderAndTracker.stop(true); } + + @Test + public void testMultipleFixTypesAreLoadedInSeparateTracks() throws InterruptedException { + regattaLog.add(new RegattaLogDeviceCompetitorTestMappingEventImpl(new MillisecondsTimePoint(1), author, comp, + deviceTest, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, + device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); + + addTestFixes(); + addBravoFixes(); - private void addFixes() { + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); + + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); + + trackedRace.waitForLoadingToFinish(); + + testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 2); + testNumberOfRawFixes(trackedRace.getSensorTrack(comp, TestFixTrackImpl.TRACK_NAME), 1); + + fixLoaderAndTracker.stop(true); + } + + @Test + public void testMultipleFixTypesAreLoadedInSeparateTracksWhileTracking() throws InterruptedException { + regattaLog.add(new RegattaLogDeviceCompetitorTestMappingEventImpl(new MillisecondsTimePoint(1), author, comp, + deviceTest, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, + device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); + + + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); + + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); + + addTestFixes(); + addBravoFixes(); + + trackedRace.waitForLoadingToFinish(); + + testNumberOfRawFixes(trackedRace.getSensorTrack(comp, TestFixTrackImpl.TRACK_NAME), 1); + testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 2); + + fixLoaderAndTracker.stop(true); + } + + private void addBravoFixes() { store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP, FIX_RIDE_HEIGHT)); store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(120, 1338.0)); store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(210, 1336.0)); } private FixLoaderAndTracker createFixLoaderAndTracker() { + return new FixLoaderAndTracker(trackedRace, store, new SensorFixMapperFactory() { + private TestDataFixMapper testDataFixMapper = new TestDataFixMapper(); + private BravoDataFixMapper bravoDataFixMapper = new BravoDataFixMapper(); @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public > SensorFixMapper createCompetitorMapper( Class> eventType) { - return (SensorFixMapper) new BravoDataFixMapper(); + if(bravoDataFixMapper.isResponsibleFor(eventType)) { + return (SensorFixMapper) bravoDataFixMapper; + } + if(testDataFixMapper.isResponsibleFor(eventType)) { + return (SensorFixMapper) testDataFixMapper; + } + throw new IllegalArgumentException("Unknown event type"); } }); } @@ -399,4 +468,120 @@ public class SensorFixStoreAndLoadTest { fixData[BravoSensorDataMetadata.INSTANCE.rideHeightColumn] = rideHeight; return new DoubleVectorFixImpl(new MillisecondsTimePoint(timestamp), fixData); } + + private void addTestFixes() { + store.storeFix(deviceTest, createTestDoubleVectorFixWithTestValue(FIX_TIMESTAMP, FIX_TEST_VALUE)); + } + + private DoubleVectorFix createTestDoubleVectorFixWithTestValue(long timestamp, double testValue) { + double[] fixData = new double[TestFixImpl.COLUMNS.size()]; + fixData[TestFixImpl.TEST_COLUMN_INDEX] = testValue; + return new DoubleVectorFixImpl(new MillisecondsTimePoint(timestamp), fixData); + } + + private static class TestFixImpl implements SensorFix { + private static final long serialVersionUID = 2033254212013220L; + + public static final String TEST_COLUMN = "testColumn"; + public static final int TEST_COLUMN_INDEX = 1; + + public static final List COLUMNS = Collections.unmodifiableList(Arrays.asList("blub", TEST_COLUMN)); + + private final DoubleVectorFix fix; + + public TestFixImpl(DoubleVectorFix fix) { + this.fix = fix; + } + + @Override + public double get(String valueName) { + return fix.get(COLUMNS.indexOf(valueName)); + } + + @Override + public TimePoint getTimePoint() { + return fix.getTimePoint(); + } + + public double getTestValue() { + return fix.get(TEST_COLUMN_INDEX); + } + + } + + public class TestFixTrackImpl extends SensorFixTrackImpl { + private static final long serialVersionUID = 5517848726454386L; + + public static final String TRACK_NAME = "TestFixTrack"; + + public TestFixTrackImpl(ItemType trackedItem, String trackName) { + super(trackedItem, trackName, TestFixImpl.COLUMNS, + TRACK_NAME + " for " + trackedItem); + } + + public Double getTextValue(TimePoint timePoint) { + TestFixImpl fixAfter = getFirstFixAtOrAfter(timePoint); + if (fixAfter != null && fixAfter.getTimePoint().compareTo(timePoint) == 0) { + // exact match of timepoint -> no interpolation necessary + return fixAfter.getTestValue(); + } + TestFixImpl fixBefore = getLastFixAtOrBefore(timePoint); + if (fixBefore != null && fixBefore.getTimePoint().compareTo(timePoint) == 0) { + // exact match of timepoint -> no interpolation necessary + return fixBefore.getTestValue(); + } + if (fixAfter == null || fixBefore == null) { + // the fix is out of the TimeRange where we have fixes + return null; + } + return fixBefore.getTestValue(); + } + } + + public class TestDataFixMapper implements SensorFixMapper, Competitor> { + + @Override + public DynamicSensorFixTrack getTrack(DynamicTrackedRace race, Competitor key) { + return race.getOrCreateSensorTrack(key, TestFixTrackImpl.TRACK_NAME, + () -> new TestFixTrackImpl(key, TestFixTrackImpl.TRACK_NAME)); + } + + @Override + public TestFixImpl map(DoubleVectorFix fix) { + return new TestFixImpl(fix); + } + + @Override + public boolean isResponsibleFor(Class> eventType) { + return RegattaLogDeviceCompetitorTestMappingEventImpl.class.isAssignableFrom(eventType); + } + } + + public class RegattaLogDeviceCompetitorTestMappingEventImpl extends RegattaLogDeviceMappingEventImpl + implements RegattaLogDeviceCompetitorSensorDataMappingEvent { + private static final long serialVersionUID = -14940305448048753L; + + + public RegattaLogDeviceCompetitorTestMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable pId, Competitor mappedTo, DeviceIdentifier device, + TimePoint from, TimePoint to) { + super(createdAt, logicalTimePoint, author, pId, mappedTo, device, from, to); + } + + public RegattaLogDeviceCompetitorTestMappingEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, + Competitor mappedTo, DeviceIdentifier device, TimePoint from, TimePoint to) { + super(logicalTimePoint, author, mappedTo, device, from, to); + } + + @Override + public void accept(RegattaLogEventVisitor visitor) { + visitor.visit(this); + } + + @Override + public void accept(MappingEventVisitor visitor) { + visitor.visit(this); + } + } + } From e66d2db2edaf8504880f57bd4bb2a58e3cedc2b0 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Tue, 6 Sep 2016 08:55:01 +0200 Subject: [PATCH 09/96] Removed TODOs that are already done or documented on a better place --- .../impl/fixtracker/RegattaLogDeviceMappings.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RegattaLogDeviceMappings.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RegattaLogDeviceMappings.java index 90346e82430..d11d1f7c3a3 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RegattaLogDeviceMappings.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RegattaLogDeviceMappings.java @@ -237,8 +237,6 @@ public abstract class RegattaLogDeviceMappings { * @throws DoesNotHaveRegattaLogException */ private final > void updateMappings(boolean loadIfNotCovered) { - // TODO remove fixes, if mappings have been removed - // check if there are new time ranges not covered so far final Map>> newMappings = calculateMappings(); final Map>> oldMappings = new HashMap<>(); LockUtil.lockForWrite(mappingsLock); From ee7c8c3b7f660137288aca4feabf3b9db71adf39 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Tue, 6 Sep 2016 08:56:14 +0200 Subject: [PATCH 10/96] Removed flag that is true in all cases --- .../impl/fixtracker/RegattaLogDeviceMappings.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RegattaLogDeviceMappings.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RegattaLogDeviceMappings.java index d11d1f7c3a3..c9a2e0281a2 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RegattaLogDeviceMappings.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RegattaLogDeviceMappings.java @@ -131,7 +131,7 @@ public abstract class RegattaLogDeviceMappings { protected void updateMappings() { try { - updateMappings(true); + updateMappingsInternal(); } catch (Exception e) { logger.log(Level.WARNING, "Could not update device mappings", e); } @@ -236,7 +236,7 @@ public abstract class RegattaLogDeviceMappings { * * @throws DoesNotHaveRegattaLogException */ - private final > void updateMappings(boolean loadIfNotCovered) { + private final > void updateMappingsInternal() { final Map>> newMappings = calculateMappings(); final Map>> oldMappings = new HashMap<>(); LockUtil.lockForWrite(mappingsLock); @@ -259,9 +259,7 @@ public abstract class RegattaLogDeviceMappings { } finally { LockUtil.unlockAfterWrite(mappingsLock); } - if (loadIfNotCovered) { - calculateDiff(oldMappings, newMappings); - } + calculateDiff(oldMappings, newMappings); } private void calculateDiff(Map>> previousMappings, From 3e0bb675b6629b81e6f4b28256b381895c82726a Mon Sep 17 00:00:00 2001 From: Papick Garcia Taboada Date: Tue, 6 Sep 2016 09:46:17 +0200 Subject: [PATCH 11/96] Introduced RTE for unknown importer, removed Imu suffix from track name --- .../server/gateway/trackfiles/impl/SensorDataImportServlet.java | 2 +- .../sailing/server/trackfiles/impl/BravoDataImporterImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/SensorDataImportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/SensorDataImportServlet.java index 398e15a659e..30ad5e13f72 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/SensorDataImportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/SensorDataImportServlet.java @@ -132,7 +132,7 @@ public class SensorDataImportServlet extends AbstractFileUploadServlet { } } if (importerName == null) { - importerName = "BRAVO"; + throw new RuntimeException("Missing preferred importer"); } List> files = new ArrayList<>(); for (FileItem fi : fileItems) { diff --git a/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/BravoDataImporterImpl.java b/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/BravoDataImporterImpl.java index bf0ecf344ee..7607efc56cc 100644 --- a/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/BravoDataImporterImpl.java +++ b/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/BravoDataImporterImpl.java @@ -49,7 +49,7 @@ public class BravoDataImporterImpl implements DoubleVectorFixImporter { public void importFixes(InputStream inputStream, Callback callback, String filename, String sourceName) throws FormatNotSupportedException, IOException { final TrackFileImportDeviceIdentifier trackIdentifier = new TrackFileImportDeviceIdentifierImpl( - UUID.randomUUID(), filename, sourceName + "_Imu", MillisecondsTimePoint.now()); + UUID.randomUUID(), filename, sourceName, MillisecondsTimePoint.now()); try { LOG.fine("Import CSV from " + sourceName); final InputStreamReader isr; From 87019c44e22e432d7b976b3a232b2ebf3b54a04b Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Tue, 6 Sep 2016 14:43:30 +0200 Subject: [PATCH 12/96] Added a test case which ensures that TrackedRace.attachRegattaLog is called when setting a TrackedRace to a RaceColumn --- .../RegattaLogAttachOnTrackedRaceTest.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogAttachOnTrackedRaceTest.java diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogAttachOnTrackedRaceTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogAttachOnTrackedRaceTest.java new file mode 100644 index 00000000000..b9db265ecec --- /dev/null +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogAttachOnTrackedRaceTest.java @@ -0,0 +1,80 @@ +package com.sap.sailing.domain.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.abstractlog.regatta.impl.RegattaLogImpl; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; +import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; +import com.sap.sailing.domain.leaderboard.impl.LowPoint; +import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore; +import com.sap.sailing.domain.regattalike.RegattaLikeIdentifier; +import com.sap.sailing.domain.regattalog.RegattaLogStore; +import com.sap.sailing.domain.test.mock.MockedTrackedRace; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sse.common.Util; + +public class RegattaLogAttachOnTrackedRaceTest { + + private class MyMockedRegattaLogStore implements RegattaLogStore { + private Map regattaLogs = new HashMap<>(); + @Override + public RegattaLog getRegattaLog(RegattaLikeIdentifier regattaLikeId, boolean ignoreCache) { + if(!regattaLogs.containsKey(regattaLikeId)) { + regattaLogs.put(regattaLikeId, new RegattaLogImpl(regattaLikeId)); + } + return regattaLogs.get(regattaLikeId); + } + + @Override + public void removeRegattaLog(RegattaLikeIdentifier regattaLikeId) { + } + + @Override + public void addImportedRegattaLog(RegattaLog regattaLog, RegattaLikeIdentifier identifier) { + } + } + + private class MyMockedTrackedRace extends MockedTrackedRace { + private static final long serialVersionUID = -5450144964435682919L; + + private RegattaLog regattaLog; + @Override + public void attachRegattaLog(RegattaLog regattaLog) { + this.regattaLog = regattaLog; + } + + @Override + public Iterable getAttachedRegattaLogs() { + return Collections.singletonList(regattaLog); + } + } + + private FlexibleLeaderboard leaderboard; + + @Before + public void setUp() { + leaderboard = new FlexibleLeaderboardImpl(EmptyRaceLogStore.INSTANCE, new MyMockedRegattaLogStore(), "", null, new LowPoint(), null); + } + + @Test + public void testAttachRegattaLogIsCalledWhenTrackedRaceIsSetToARaceColumn() { + RaceColumn column = leaderboard.addRaceColumn("R1", false); + TrackedRace trackedRace = new MyMockedTrackedRace(); + Fleet defaultFleet = Util.get(column.getFleets(), 0); + column.setTrackedRace(defaultFleet, trackedRace); + assertEquals(1, Util.size(trackedRace.getAttachedRegattaLogs())); + assertSame(leaderboard.getRegattaLog(), Util.get(trackedRace.getAttachedRegattaLogs(), 0)); + } + +} From a7fcd47ddafbd2542edc31bb4ce0c70d4cb0fa26 Mon Sep 17 00:00:00 2001 From: Vladislav Chumak Date: Tue, 6 Sep 2016 14:46:59 +0200 Subject: [PATCH 13/96] Extended tests with multiple fix types for mapping validation --- .../test/impl/SensorFixStoreAndLoadTest.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java index 18855395de3..a6e89233fe5 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java @@ -86,7 +86,11 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public class SensorFixStoreAndLoadTest { private static final long FIX_TIMESTAMP = 110; + private static final long FIX_TIMESTAMP2 = 120; + private static final long FIX_TIMESTAMP3 = 210; private static final double FIX_RIDE_HEIGHT = 1337.0; + private static final double FIX_RIDE_HEIGHT2 = 1338.0; + private static final double FIX_RIDE_HEIGHT3 = 1336.0; private static final double FIX_TEST_VALUE = 12.0; protected final MockSmartphoneImeiServiceFinderFactory serviceFinderFactory = new MockSmartphoneImeiServiceFinderFactory(); protected final DeviceIdentifier device = new SmartphoneImeiIdentifier("a"); @@ -429,6 +433,39 @@ public class SensorFixStoreAndLoadTest { fixLoaderAndTracker.stop(true); } + + @Test + public void testMultipleFixTypesAreMappedCorrectly() throws InterruptedException { + regattaLog.add(new RegattaLogDeviceCompetitorTestMappingEventImpl(new MillisecondsTimePoint(1), author, comp, + deviceTest, new MillisecondsTimePoint(100), new MillisecondsTimePoint(300))); + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, + device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(300))); + + + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); + + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); + + addTestFixes(); + addBravoFixes(); + + trackedRace.waitForLoadingToFinish(); + + BravoFixTrack bravoFixTrack = trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME); + assertEquals(FIX_RIDE_HEIGHT, + bravoFixTrack.getFirstFixAtOrAfter(new MillisecondsTimePoint(FIX_TIMESTAMP)).getRideHeight()); + assertEquals(FIX_RIDE_HEIGHT2, + bravoFixTrack.getFirstFixAtOrAfter(new MillisecondsTimePoint(FIX_TIMESTAMP2)).getRideHeight()); + assertEquals(FIX_RIDE_HEIGHT3, + bravoFixTrack.getFirstFixAtOrAfter(new MillisecondsTimePoint(FIX_TIMESTAMP3)).getRideHeight()); + + TestFixTrackImpl testFixTrack = trackedRace.getSensorTrack(comp, TestFixTrackImpl.TRACK_NAME); + assertEquals(FIX_TEST_VALUE, + testFixTrack.getFirstFixAtOrAfter(new MillisecondsTimePoint(FIX_TIMESTAMP)).getTestValue()); + + fixLoaderAndTracker.stop(true); + } private void addBravoFixes() { store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP, FIX_RIDE_HEIGHT)); From 93b9dbbfc3665622016df7d19360704cad8f6354 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Tue, 6 Sep 2016 14:49:57 +0200 Subject: [PATCH 14/96] Fixed several compiler warnings --- ...gattaLogImportSensorDataAndAddMappingsDialog.java | 12 ------------ .../TrackFileImportDeviceIdentifierTableWrapper.java | 6 ------ 2 files changed, 18 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogImportSensorDataAndAddMappingsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogImportSensorDataAndAddMappingsDialog.java index 919bfa88667..1db0f615e1e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogImportSensorDataAndAddMappingsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogImportSensorDataAndAddMappingsDialog.java @@ -10,7 +10,6 @@ import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.view.client.SelectionChangeEvent; -import com.google.gwt.view.client.SingleSelectionModel; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; @@ -29,9 +28,6 @@ public class RegattaLogImportSensorDataAndAddMappingsDialog extends DataEntryDia protected final CompetitorTableWrapper> competitorTable; private final StringMessages stringMessages; - - private TrackFileImportDeviceIdentifierDTO deviceToSelect; - public RegattaLogImportSensorDataAndAddMappingsDialog(SailingServiceAsync sailingService, final ErrorReporter errorReporter, final StringMessages stringMessages, String leaderboardName, DialogCallback> callback) { @@ -88,14 +84,6 @@ public class RegattaLogImportSensorDataAndAddMappingsDialog extends DataEntryDia }); } - private static void selectOrClear(SingleSelectionModel selectionModel, T object) { - if (object == null) { - selectionModel.clear(); - } else { - selectionModel.setSelected(object, true); - } - } - @Override protected Widget getAdditionalWidget() { HorizontalPanel panel = new HorizontalPanel(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackFileImportDeviceIdentifierTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackFileImportDeviceIdentifierTableWrapper.java index d5beb50c7f5..b2217694978 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackFileImportDeviceIdentifierTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackFileImportDeviceIdentifierTableWrapper.java @@ -93,13 +93,10 @@ public class TrackFileImportDeviceIdentifierTableWrapper extends class MappingTableBuilder extends DefaultCellTableBuilder { private final String evenRowStyle; private final String oddRowStyle; - private final String selectedRowStyle; private final String cellStyle; private final String evenCellStyle; private final String oddCellStyle; private final String firstColumnStyle; - private final String lastColumnStyle; - private final String selectedCellStyle; private final AbstractCellTable cellTable; public MappingTableBuilder(AbstractCellTable cellTable) { @@ -108,13 +105,10 @@ public class TrackFileImportDeviceIdentifierTableWrapper extends Style style = cellTable.getResources().style(); evenRowStyle = style.evenRow(); oddRowStyle = style.oddRow(); - selectedRowStyle = " " + style.selectedRow(); cellStyle = style.cell(); evenCellStyle = " " + style.evenRowCell(); oddCellStyle = " " + style.oddRowCell(); firstColumnStyle = " " + style.firstColumn(); - lastColumnStyle = " " + style.lastColumn(); - selectedCellStyle = " " + style.selectedRowCell(); } @Override From 20fc0bbe52b5536dcc16692e2000979800e472a4 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 7 Sep 2016 14:07:25 +0200 Subject: [PATCH 15/96] Added equals/hashCode to DoubleVectorFixImpl for improved testability --- .../tracking/impl/DoubleVectorFixImpl.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/DoubleVectorFixImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/DoubleVectorFixImpl.java index 67edd307e56..9c6b1ca99f3 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/DoubleVectorFixImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/DoubleVectorFixImpl.java @@ -1,5 +1,7 @@ package com.sap.sailing.domain.common.tracking.impl; +import java.util.Arrays; + import com.sap.sailing.domain.common.tracking.DoubleVectorFix; import com.sap.sse.common.TimePoint; @@ -34,4 +36,31 @@ public class DoubleVectorFixImpl implements DoubleVectorFix { return fixData; } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + Arrays.hashCode(fixData); + result = prime * result + ((timePoint == null) ? 0 : timePoint.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + DoubleVectorFixImpl other = (DoubleVectorFixImpl) obj; + if (!Arrays.equals(fixData, other.fixData)) + return false; + if (timePoint == null) { + if (other.timePoint != null) + return false; + } else if (!timePoint.equals(other.timePoint)) + return false; + return true; + } } From be6203e2a4b3d2418c79c5c5fd12c21803ab816e Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Wed, 7 Sep 2016 14:47:19 +0200 Subject: [PATCH 16/96] Extended MasterDataImportTest to also verify that DoubleVectorFixes are correctly imported --- .../server/test/MasterDataImportTest.java | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java index 915604c2c40..e4fd473c073 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java @@ -47,7 +47,9 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningConf import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorBravoMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.base.BoatClass; @@ -94,7 +96,9 @@ import com.sap.sailing.domain.common.impl.WindImpl; import com.sap.sailing.domain.common.impl.WindSourceWithAdditionalID; import com.sap.sailing.domain.common.media.MediaTrack; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; +import com.sap.sailing.domain.common.sensordata.BravoSensorDataMetadata; import com.sap.sailing.domain.common.tracking.GPSFix; +import com.sap.sailing.domain.common.tracking.impl.DoubleVectorFixImpl; import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard; @@ -108,11 +112,12 @@ import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard; import com.sap.sailing.domain.persistence.PersistenceFactory; import com.sap.sailing.domain.persistence.media.MediaDBFactory; import com.sap.sailing.domain.racelog.tracking.EmptySensorFixStore; +import com.sap.sailing.domain.racelog.tracking.SensorFixStore; import com.sap.sailing.domain.racelog.tracking.test.mock.MockSmartphoneImeiServiceFinderFactory; import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier; import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; import com.sap.sailing.domain.ranking.OneDesignRankingMetric; -import com.sap.sailing.domain.test.TrackBasedTest; +import com.sap.sailing.domain.test.TrackBasedTest; import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.WindTrack; @@ -123,9 +128,10 @@ import com.sap.sailing.server.gateway.jaxrs.spi.MasterDataResource; import com.sap.sailing.server.impl.RacingEventServiceImpl; import com.sap.sailing.server.masterdata.DummyTrackedRace; import com.sap.sailing.server.masterdata.MasterDataImporter; -import com.sap.sailing.server.testsupport.RacingEventServiceImplMock; +import com.sap.sailing.server.testsupport.RacingEventServiceImplMock; import com.sap.sse.common.Color; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Timed; import com.sap.sse.common.Util; import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; @@ -289,6 +295,18 @@ public class MasterDataImportTest { GPSFix gpsFix = new GPSFixMovingImpl(new DegreePosition(54.333, 10.133), logTimePoint2, new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(90))); sourceService.getSensorFixStore().storeFix(deviceIdentifier, gpsFix); + + // Add sensor fix + DeviceIdentifier deviceIdentifier2 = new SmartphoneImeiIdentifier("b"); + RegattaLogDeviceMappingEvent bravoMappingEvent = new RegattaLogDeviceCompetitorBravoMappingEventImpl( + logTimePoint4, author, competitor, deviceIdentifier2, logTimePoint, + logTimePoint3); + regatta.getRegattaLog().add(bravoMappingEvent); + double[] fixData = new double[BravoSensorDataMetadata.INSTANCE.getColumns().size()]; + double rideHeightValue = 1337.0; + fixData[BravoSensorDataMetadata.INSTANCE.rideHeightColumn] = rideHeightValue; + DoubleVectorFixImpl doubleVectorFix = new DoubleVectorFixImpl(logTimePoint2, fixData); + sourceService.getSensorFixStore().storeFix(deviceIdentifier2, doubleVectorFix); // Set score correction double scoreCorrection = 12.0; @@ -427,7 +445,13 @@ public class MasterDataImportTest { Assert.assertEquals(competitor.getId(), registerEventOnTarget.getCompetitor().getId()); // Check for import of racelogtracking fix - Assert.assertTrue(destService.getSensorFixStore().getNumberOfFixes(deviceIdentifier) == 1); + SensorFixStore sensorFixStore = destService.getSensorFixStore(); + Assert.assertEquals(1, sensorFixStore.getNumberOfFixes(deviceIdentifier)); + verifyFix(gpsFix, sensorFixStore, logTimePoint, logTimePoint3, deviceIdentifier); + + // Check for import of sensor fix + Assert.assertEquals(1, sensorFixStore.getNumberOfFixes(deviceIdentifier2)); + verifyFix(doubleVectorFix, sensorFixStore, logTimePoint, logTimePoint3, deviceIdentifier2); // Check for persisting of race log events: RacingEventService dest2 = new RacingEventServiceImplMock(){}; @@ -446,6 +470,17 @@ public class MasterDataImportTest { Assert.assertNotNull(registerEventOnTarget2); Assert.assertEquals(registerEvent.getId(), registerEventOnTarget2.getId()); } + + private void verifyFix(Timed expectedFix, SensorFixStore store, TimePoint start, TimePoint end, DeviceIdentifier deviceIdentifier) { + List fixes = new ArrayList<>(1); + try { + store.loadFixes(fixes::add, deviceIdentifier, start, end, true); + assertEquals(1, fixes.size()); + assertEquals(expectedFix, fixes.get(0)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } @Test public void testMasterDataImportForScoreCorrections() throws MalformedURLException, IOException, From 6aa54216837c1a90a464bf12ce939db0d071afe1 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Fri, 9 Sep 2016 13:26:22 +0200 Subject: [PATCH 17/96] Also dropping RegattaLogs and RaceLogs in SensorFixStoreAndLoadTest --- .../test/impl/SensorFixStoreAndLoadTest.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java index a6e89233fe5..446340c9b91 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java @@ -116,9 +116,7 @@ public class SensorFixStoreAndLoadTest { @Before public void setUp() throws UnknownHostException, MongoException { - DB db = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory().getDatabase(); - db.getCollection(CollectionNames.GPS_FIXES.name()).drop(); - db.getCollection(CollectionNames.GPS_FIXES_METADATA.name()).drop(); + dropPersistedData(); raceLog = new RaceLogImpl("racelog"); regattaLog = new RegattaLogImpl("regattalog"); @@ -140,11 +138,17 @@ public class SensorFixStoreAndLoadTest { mock(RaceLogResolver.class)); } - @After - public void after() { + private void dropPersistedData() { DB db = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory().getDatabase(); db.getCollection(CollectionNames.GPS_FIXES.name()).drop(); db.getCollection(CollectionNames.GPS_FIXES_METADATA.name()).drop(); + db.getCollection(CollectionNames.REGATTA_LOGS.name()).drop(); + db.getCollection(CollectionNames.RACE_LOGS.name()).drop(); + } + + @After + public void after() { + dropPersistedData(); } @Test From 91aaa1cdb4c42eca704f6c040fb3bf18945f5518 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Fri, 9 Sep 2016 13:28:31 +0200 Subject: [PATCH 18/96] Always using the local set of RaceLogs in RaceLogFixTrackerManager --- .../impl/fixtracker/RaceLogFixTrackerManager.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RaceLogFixTrackerManager.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RaceLogFixTrackerManager.java index 5efe9c08bf4..d0edf58d240 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RaceLogFixTrackerManager.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RaceLogFixTrackerManager.java @@ -120,7 +120,7 @@ public class RaceLogFixTrackerManager implements TrackingDataLoader { stopTrackerIfStillRunning(preemptive); trackedRace.removeListener(raceChangeListener); synchronized (knownRaceLogs) { - for (RaceLog raceLog : trackedRace.getAttachedRaceLogs()) { + for (RaceLog raceLog : knownRaceLogs) { removeRaceLogUnlocked(raceLog); } } @@ -142,10 +142,12 @@ public class RaceLogFixTrackerManager implements TrackingDataLoader { } boolean isForTracking() { - for (RaceLog raceLog : trackedRace.getAttachedRaceLogs()) { - RaceLogTrackingState raceLogTrackingState = new RaceLogTrackingStateAnalyzer(raceLog).analyze(); - if (raceLogTrackingState.isForTracking()) { - return true; + synchronized (knownRaceLogs) { + for (RaceLog raceLog : knownRaceLogs) { + RaceLogTrackingState raceLogTrackingState = new RaceLogTrackingStateAnalyzer(raceLog).analyze(); + if (raceLogTrackingState.isForTracking()) { + return true; + } } } return false; From e61ecb68819d7a761b45f29cb7ecfbcfef899c1b Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Fri, 9 Sep 2016 13:29:06 +0200 Subject: [PATCH 19/96] Also dropping RegattaLogs and RaceLogs in AbstractGPSFixStoreTest --- .../domain/racelogtracking/test/AbstractGPSFixStoreTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java index ed21eaf7f14..cef4a6b47c7 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java @@ -71,6 +71,8 @@ public class AbstractGPSFixStoreTest { MongoObjectFactoryImpl mongoOF = (MongoObjectFactoryImpl) service.getMongoObjectFactory(); mongoOF.getGPSFixCollection().drop(); mongoOF.getGPSFixMetadataCollection().drop(); + mongoOF.getRaceLogCollection().drop(); + mongoOF.getRegattaLogCollection().drop(); } protected void map(RegattaLog regattaLog, Competitor comp, DeviceIdentifier device, long from, long to) { From 9bd8edd953d7daac3df6817d2dd0288c63cffe47 Mon Sep 17 00:00:00 2001 From: Papick Garcia Taboada Date: Fri, 9 Sep 2016 14:13:53 +0200 Subject: [PATCH 20/96] Added failing Test for loading sensor fixes --- .../test/impl/SensorFixStoreAndLoadTest.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java index 446340c9b91..3704ec33f53 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java @@ -2,6 +2,7 @@ package com.sap.sailing.domain.racelogtracking.test.impl; import static com.sap.sse.common.Util.size; import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; import static org.mockito.Mockito.mock; @@ -22,7 +23,9 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEndOfTrackingEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.MappingEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; @@ -625,4 +628,25 @@ public class SensorFixStoreAndLoadTest { } } + @Test + public void testThatMappingsOutsideOfTheTrackedIntervalDontCauseLoadingToFail() throws InterruptedException { + raceLog.add(new RaceLogStartOfTrackingEventImpl(new MillisecondsTimePoint(100), author, 0)); + raceLog.add(new RaceLogEndOfTrackingEventImpl(new MillisecondsTimePoint(300), author, 0)); + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, + device, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, + device, new MillisecondsTimePoint(10), new MillisecondsTimePoint(20))); + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp2, + deviceTest, new MillisecondsTimePoint(100), new MillisecondsTimePoint(200))); + regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp2, + deviceTest, new MillisecondsTimePoint(10), new MillisecondsTimePoint(20))); + addBravoFixes(); + FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); + trackedRace.waitForLoadingToFinish(); + assertNotNull(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME)); + assertNotNull(trackedRace.getSensorTrack(comp2, BravoFixTrack.TRACK_NAME)); + fixLoaderAndTracker.stop(true); + } } From 00354e3b7b77688e981f86a970fbbd7f76ded6c4 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Fri, 9 Sep 2016 14:14:53 +0200 Subject: [PATCH 21/96] Fixed NPE that causes loading of sensor fixes to fail --- .../impl/fixtracker/FixLoaderAndTracker.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/FixLoaderAndTracker.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/FixLoaderAndTracker.java index e2d809f3bb9..2f78f46f34a 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/FixLoaderAndTracker.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/FixLoaderAndTracker.java @@ -160,6 +160,9 @@ public class FixLoaderAndTracker implements TrackingDataLoader { } private void loadFixes(TimeRange timeRangeToLoad, DeviceMappingWithRegattaLogEvent mapping) { + if(timeRangeToLoad == null) { + return; + } if (preemptiveStopRequested.get()) { return; } @@ -276,10 +279,7 @@ public class FixLoaderAndTracker implements TrackingDataLoader { protected void loadFixesForExtendedTimeRange(TimePoint loadFixesFrom, TimePoint loadFixesTo) { final TimeRangeImpl extendedTimeRange = new TimeRangeImpl(loadFixesFrom, loadFixesTo); deviceMappings.forEachMapping((mapping) -> { - TimeRange timeRangeToLoad = extendedTimeRange.intersection(mapping.getTimeRange()); - if (timeRangeToLoad != null && !preemptiveStopRequested.get()) { - loadFixes(timeRangeToLoad, mapping); - } + loadFixes(extendedTimeRange.intersection(mapping.getTimeRange()), mapping); }); } From c235551fc034db2136e23e5d89f98492a26feea3 Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Fri, 9 Sep 2016 14:15:28 +0200 Subject: [PATCH 22/96] Changes to make the update of device mappings more robust --- .../fixtracker/RegattaLogDeviceMappings.java | 55 ++++++++++++++----- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RegattaLogDeviceMappings.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RegattaLogDeviceMappings.java index c9a2e0281a2..d94e3e265ef 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RegattaLogDeviceMappings.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/fixtracker/RegattaLogDeviceMappings.java @@ -265,27 +265,27 @@ public abstract class RegattaLogDeviceMappings { private void calculateDiff(Map>> previousMappings, Map>> newMappings) { Set itemsToProcess = new HashSet(previousMappings.keySet()); - itemsToProcess.addAll(newMappings.keySet()); - for(ItemT item : itemsToProcess) { - if(!newMappings.containsKey(item)) { - previousMappings.get(item).forEach(this::mappingRemoved); - } else { + itemsToProcess.addAll(newMappings.keySet()); + for(ItemT item : itemsToProcess) { + if(!newMappings.containsKey(item)) { + previousMappings.get(item).forEach(this::mappingRemovedInternal); + } else { final List> oldMappings = previousMappings.containsKey(item) ? previousMappings.get(item) : Collections.emptyList(); - - for (DeviceMappingWithRegattaLogEvent newMapping : newMappings.get(item)) { - DeviceMappingWithRegattaLogEvent oldMapping = findAndRemoveMapping(newMapping, - oldMappings); - if (oldMapping == null) { - mappingAdded(newMapping); - } else if (!newMapping.getTimeRange().equals(oldMapping.getTimeRange())) { - mappingChanged(oldMapping, newMapping); - } + + for (DeviceMappingWithRegattaLogEvent newMapping : newMappings.get(item)) { + DeviceMappingWithRegattaLogEvent oldMapping = findAndRemoveMapping(newMapping, + oldMappings); + if (oldMapping == null) { + mappingAddedInternal(newMapping); + } else if (!newMapping.getTimeRange().equals(oldMapping.getTimeRange())) { + mappingChangedInternal(oldMapping, newMapping); } - oldMappings.forEach(this::mappingRemoved); } + oldMappings.forEach(this::mappingRemovedInternal); } } + } /** * Called when a {@link DeviceMapping} was removed. @@ -293,6 +293,14 @@ public abstract class RegattaLogDeviceMappings { * @param mapping the removed mapping */ protected abstract void mappingRemoved(DeviceMappingWithRegattaLogEvent mapping); + + private void mappingRemovedInternal(DeviceMappingWithRegattaLogEvent mapping) { + try { + mappingRemoved(mapping); + } catch(Exception e) { + logger.log(Level.SEVERE, "error while removing mapping " + mapping, e); + } + } /** * Called when a {@link DeviceMapping} was added. @@ -300,6 +308,14 @@ public abstract class RegattaLogDeviceMappings { * @param mapping the new mapping */ protected abstract void mappingAdded(DeviceMappingWithRegattaLogEvent mapping); + + private void mappingAddedInternal(DeviceMappingWithRegattaLogEvent mapping) { + try { + mappingAdded(mapping); + } catch(Exception e) { + logger.log(Level.SEVERE, "error while adding mapping " + mapping, e); + } + } /** * Called when a {@link DeviceMapping} was changed regarding its mapped time range. @@ -311,6 +327,15 @@ public abstract class RegattaLogDeviceMappings { protected abstract void mappingChanged(DeviceMappingWithRegattaLogEvent oldMapping, DeviceMappingWithRegattaLogEvent newMapping); + private void mappingChangedInternal(DeviceMappingWithRegattaLogEvent oldMapping, + DeviceMappingWithRegattaLogEvent newMapping) { + try { + mappingChanged(oldMapping, newMapping); + } catch(Exception e) { + logger.log(Level.SEVERE, "error while changing mapping old: " + oldMapping + "; new: " + newMapping, e); + } + } + private DeviceMappingWithRegattaLogEvent findAndRemoveMapping( DeviceMappingWithRegattaLogEvent mappingToFind, List> newItemsToProcess) { From 790cfba57251e35170260753f4a4ef562341cbcd Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Mon, 12 Sep 2016 09:17:46 +0200 Subject: [PATCH 23/96] Added initial tests for SensorFixStore --- .../test/impl/SensorFixStoreTest.java | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreTest.java diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreTest.java new file mode 100644 index 00000000000..de140d19940 --- /dev/null +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreTest.java @@ -0,0 +1,151 @@ +package com.sap.sailing.domain.racelogtracking.test.impl; + +import static org.junit.Assert.assertEquals; + +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.mongodb.DB; +import com.mongodb.MongoException; +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.racelog.tracking.TransformationException; +import com.sap.sailing.domain.common.sensordata.BravoSensorDataMetadata; +import com.sap.sailing.domain.common.tracking.DoubleVectorFix; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.common.tracking.impl.DoubleVectorFixImpl; +import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; +import com.sap.sailing.domain.persistence.PersistenceFactory; +import com.sap.sailing.domain.persistence.impl.CollectionNames; +import com.sap.sailing.domain.persistence.racelog.tracking.impl.MongoSensorFixStoreImpl; +import com.sap.sailing.domain.racelog.tracking.SensorFixStore; +import com.sap.sailing.domain.racelog.tracking.test.mock.MockSmartphoneImeiServiceFinderFactory; +import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier; +import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; +import com.sap.sse.common.Timed; +import com.sap.sse.common.impl.MillisecondsTimePoint; + +public class SensorFixStoreTest { + private static final long FIX_TIMESTAMP = 110; + private static final long FIX_TIMESTAMP2 = 120; + private static final double FIX_RIDE_HEIGHT = 1337.0; + private static final double FIX_RIDE_HEIGHT2 = 1338.0; + protected final MockSmartphoneImeiServiceFinderFactory serviceFinderFactory = new MockSmartphoneImeiServiceFinderFactory(); + protected final DeviceIdentifier device = new SmartphoneImeiIdentifier("a"); + protected final DeviceIdentifier device2 = new SmartphoneImeiIdentifier("b"); + protected SensorFixStore store; + + protected GPSFixMoving createFix(long millis, double lat, double lng, double knots, double degrees) { + return new GPSFixMovingImpl(new DegreePosition(lat, lng), new MillisecondsTimePoint(millis), + new KnotSpeedWithBearingImpl(knots, new DegreeBearingImpl(degrees))); + } + + @Before + public void setUp() throws UnknownHostException, MongoException { + dropPersistedData(); + newStore(); + + } + + private void newStore() { + store = new MongoSensorFixStoreImpl(PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), + PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory(), serviceFinderFactory); + } + + @After + public void after() { + dropPersistedData(); + } + + private void dropPersistedData() { + DB db = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory().getDatabase(); + db.getCollection(CollectionNames.GPS_FIXES.name()).drop(); + db.getCollection(CollectionNames.GPS_FIXES_METADATA.name()).drop(); + } + + @Test + public void testFixIsPersisted() throws Exception { + addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + assertEquals(1, store.getNumberOfFixes(device)); + } + + /** + * Ensures that no local caching in the store makes in seem to work but data will be lost on restart of the system. + */ + @Test + public void testFixIsFoundByOtherStoreInstance() throws Exception { + addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + + newStore(); + assertEquals(1, store.getNumberOfFixes(device)); + } + + @Test + public void testFixDataIsPreservedOnStore() throws Exception { + DoubleVectorFix fix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + + verifySingleFix(fix, 100, 200, device, true); + } + + @Test + public void testFixWithinExclusiveBoundsIsLoaded() throws Exception { + DoubleVectorFix fix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + verifySingleFix(fix, FIX_TIMESTAMP - 1, FIX_TIMESTAMP + 1, device, false); + } + + @Test + public void testFixOnInclusiveLowerBoundIsLoaded() throws Exception { + DoubleVectorFix fix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + verifySingleFix(fix, FIX_TIMESTAMP, FIX_TIMESTAMP + 1, device, true); + } + + @Test + public void testFixOnInclusiveUpperBoundIsLoaded() throws Exception { + DoubleVectorFix fix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + verifySingleFix(fix, FIX_TIMESTAMP-1, FIX_TIMESTAMP, device, true); + } + + @Test + public void testFixesOnExclusiveBoundsArentLoaded() throws Exception { + addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + addBravoFix(device, FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2); + verifyNoFix(FIX_TIMESTAMP, FIX_TIMESTAMP2, device, false); + } + + private void verifySingleFix(Timed expectedFix, long start, long end, DeviceIdentifier device, boolean inclusive) throws Exception { + List loadedFixes = loadFixes(start, end, device, inclusive); + assertEquals(1, loadedFixes.size()); + assertEquals(expectedFix, loadedFixes.get(0)); + } + + private void verifyNoFix(long start, long end, DeviceIdentifier device, boolean inclusive) throws Exception { + List loadedFixes = loadFixes(start, end, device, inclusive); + assertEquals(0, loadedFixes.size()); + } + + private List loadFixes(long start, long end, DeviceIdentifier device, boolean inclusive) + throws TransformationException { + List loadedFixes = new ArrayList<>(); + + store.loadFixes(loadedFixes::add, device, new MillisecondsTimePoint(start), new MillisecondsTimePoint(end), inclusive); + return loadedFixes; + } + + private DoubleVectorFix addBravoFix(DeviceIdentifier device, long timestamp, double rideHeight) { + DoubleVectorFix fix = createBravoDoubleVectorFixWithRideHeight(timestamp, rideHeight); + store.storeFix(device, fix); + return fix; + } + + private DoubleVectorFix createBravoDoubleVectorFixWithRideHeight(long timestamp, double rideHeight) { + double[] fixData = new double[BravoSensorDataMetadata.INSTANCE.getColumns().size()]; + fixData[BravoSensorDataMetadata.INSTANCE.rideHeightColumn] = rideHeight; + return new DoubleVectorFixImpl(new MillisecondsTimePoint(timestamp), fixData); + } +} From 2571dbc8cefdd41dc38ed7c55d3d8cfbbcf261bf Mon Sep 17 00:00:00 2001 From: Vladislav Chumak Date: Mon, 12 Sep 2016 19:13:12 +0200 Subject: [PATCH 24/96] Extended SensorFixStore tests with testing of listeners --- .../test/impl/SensorFixStoreTest.java | 152 +++++++++++++++++- 1 file changed, 151 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreTest.java index de140d19940..b0f30541d03 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreTest.java @@ -9,6 +9,7 @@ import java.util.List; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.mockito.Mockito; import com.mongodb.DB; import com.mongodb.MongoException; @@ -24,6 +25,7 @@ import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; import com.sap.sailing.domain.persistence.PersistenceFactory; import com.sap.sailing.domain.persistence.impl.CollectionNames; import com.sap.sailing.domain.persistence.racelog.tracking.impl.MongoSensorFixStoreImpl; +import com.sap.sailing.domain.racelog.tracking.FixReceivedListener; import com.sap.sailing.domain.racelog.tracking.SensorFixStore; import com.sap.sailing.domain.racelog.tracking.test.mock.MockSmartphoneImeiServiceFinderFactory; import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier; @@ -117,7 +119,155 @@ public class SensorFixStoreTest { addBravoFix(device, FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2); verifyNoFix(FIX_TIMESTAMP, FIX_TIMESTAMP2, device, false); } - + + @Test + public void testSingleListenerIsNotified() throws Exception { + FixReceivedListener listener = mockFixReceivedListener(); + store.addListener(listener, device); + DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + + Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix); + } + + @Test + public void testMultipleListenersForSameDeviceAreNotified() throws Exception { + FixReceivedListener listener1 = mockFixReceivedListener(); + FixReceivedListener listener2 = mockFixReceivedListener(); + store.addListener(listener1, device); + store.addListener(listener2, device); + DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + + Mockito.verify(listener1, Mockito.times(1)).fixReceived(device, doubleVectorFix); + Mockito.verify(listener2, Mockito.times(1)).fixReceived(device, doubleVectorFix); + } + + @Test + public void testListenerForNonMatchingDeviceIsNotNotified() throws Exception { + FixReceivedListener listener = mockFixReceivedListener(); + store.addListener(listener, device); + addBravoFix(device2, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + + Mockito.verifyZeroInteractions(listener); + } + + @Test + public void testOnlyListenerForMatchingDeviceIsNotified() throws Exception { + FixReceivedListener listener1 = mockFixReceivedListener(); + FixReceivedListener listener2 = mockFixReceivedListener(); + store.addListener(listener1, device); + store.addListener(listener2, device2); + DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + + Mockito.verify(listener1, Mockito.times(1)).fixReceived(device, doubleVectorFix); + Mockito.verifyZeroInteractions(listener2); + } + + @Test + public void testListenerForMatchingDeviceIsNotifiedMultipleTimes() throws Exception { + FixReceivedListener listener = mockFixReceivedListener(); + store.addListener(listener, device); + DoubleVectorFix doubleVectorFix1 = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + DoubleVectorFix doubleVectorFix2 = addBravoFix(device, FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2); + + Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix1); + Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix2); + Mockito.verifyNoMoreInteractions(listener); + } + + @Test + public void testAfterRemoveListenerIsNotNotified() throws Exception { + FixReceivedListener listener = mockFixReceivedListener(); + store.addListener(listener, device); + store.removeListener(listener); + addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + Mockito.verifyZeroInteractions(listener); + } + + @Test + public void testAfterRemoveForDeviceListenerIsNotNotified() throws Exception { + FixReceivedListener listener = mockFixReceivedListener(); + store.addListener(listener, device); + store.removeListener(listener, device); + addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + Mockito.verifyZeroInteractions(listener); + } + + @Test + public void testAfterRemoveForNonMatchingDeviceListenerIsNotified() throws Exception { + FixReceivedListener listener = mockFixReceivedListener(); + store.addListener(listener, device); + store.removeListener(listener, device2); + DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix); + } + + @Test + public void testListenerForMultipleDevicesIsNotifiedMultipleTimes() throws Exception { + FixReceivedListener listener = mockFixReceivedListener(); + store.addListener(listener, device); + store.addListener(listener, device2); + DoubleVectorFix doubleVectorFix1 = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + DoubleVectorFix doubleVectorFix2 = addBravoFix(device2, FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2); + Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix1); + Mockito.verify(listener, Mockito.times(1)).fixReceived(device2, doubleVectorFix2); + Mockito.verifyNoMoreInteractions(listener); + } + + @Test + public void testAfterRemoveListenerForMultipleDevicesIsNotNotified() throws Exception { + FixReceivedListener listener = mockFixReceivedListener(); + store.addListener(listener, device); + store.addListener(listener, device2); + store.removeListener(listener); + addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + addBravoFix(device2, FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2); + Mockito.verifyZeroInteractions(listener); + } + + @Test + public void testAfterRemoveListenerForOneDevicesIsNotifiedForOtherDevice() throws Exception { + FixReceivedListener listener = mockFixReceivedListener(); + store.addListener(listener, device); + store.addListener(listener, device2); + store.removeListener(listener, device); + addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + DoubleVectorFix doubleVectorFix2 = addBravoFix(device2, FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2); + Mockito.verify(listener, Mockito.times(1)).fixReceived(device2, doubleVectorFix2); + Mockito.verifyNoMoreInteractions(listener); + } + + @Test + public void testAfterRemoveListenerOtherListenerIsNotified() throws Exception { + FixReceivedListener listener1 = mockFixReceivedListener(); + FixReceivedListener listener2 = mockFixReceivedListener(); + store.addListener(listener1, device); + store.addListener(listener2, device); + store.removeListener(listener1); + DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + Mockito.verify(listener2, Mockito.times(1)).fixReceived(device, doubleVectorFix); + Mockito.verifyNoMoreInteractions(listener2); + Mockito.verifyZeroInteractions(listener1); + } + + @Test + public void testAfterRemoveForDeviceListenerOtherListenerIsNotified() throws Exception { + FixReceivedListener listener1 = mockFixReceivedListener(); + FixReceivedListener listener2 = mockFixReceivedListener(); + store.addListener(listener1, device); + store.addListener(listener2, device); + store.removeListener(listener1, device); + DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT); + Mockito.verify(listener2, Mockito.times(1)).fixReceived(device, doubleVectorFix); + Mockito.verifyNoMoreInteractions(listener2); + Mockito.verifyZeroInteractions(listener1); + } + + @SuppressWarnings("unchecked") + private FixReceivedListener mockFixReceivedListener() { + FixReceivedListener listener = Mockito.mock(FixReceivedListener.class); + return listener; + } + private void verifySingleFix(Timed expectedFix, long start, long end, DeviceIdentifier device, boolean inclusive) throws Exception { List loadedFixes = loadFixes(start, end, device, inclusive); assertEquals(1, loadedFixes.size()); From c5311cad7c69b0527b364373710395ece8f94fb5 Mon Sep 17 00:00:00 2001 From: Papick Garcia Taboada Date: Tue, 13 Sep 2016 16:59:25 +0200 Subject: [PATCH 25/96] Fixed log output to use filename --- .../server/trackfiles/impl/BravoDataImporterImpl.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/BravoDataImporterImpl.java b/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/BravoDataImporterImpl.java index 7607efc56cc..bb8d9d0b60e 100644 --- a/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/BravoDataImporterImpl.java +++ b/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/BravoDataImporterImpl.java @@ -51,10 +51,10 @@ public class BravoDataImporterImpl implements DoubleVectorFixImporter { final TrackFileImportDeviceIdentifier trackIdentifier = new TrackFileImportDeviceIdentifierImpl( UUID.randomUUID(), filename, sourceName, MillisecondsTimePoint.now()); try { - LOG.fine("Import CSV from " + sourceName); + LOG.fine("Import CSV from " + filename); final InputStreamReader isr; if (sourceName.endsWith("gz")) { - LOG.fine("Using gzip stream reader " + sourceName); + LOG.fine("Using gzip stream reader " + filename); isr = new InputStreamReader(new GZIPInputStream(inputStream)); } else { isr = new InputStreamReader(inputStream); @@ -63,10 +63,10 @@ public class BravoDataImporterImpl implements DoubleVectorFixImporter { try (BufferedReader buffer = new BufferedReader(isr)) { String headerLine = null; headerSearch: while (headerLine == null) { - LOG.fine("Searching for header in imu file"); + LOG.fine("Searching for header in bravo file"); String headerCandidate = buffer.readLine(); if (headerCandidate == null) { - throw new RuntimeException("Missing required header in file " + sourceName); + throw new RuntimeException("Missing required header in file " + filename); } if (headerCandidate.startsWith(BOF)) { LOG.fine("Found header"); @@ -91,7 +91,7 @@ public class BravoDataImporterImpl implements DoubleVectorFixImporter { buffer.close(); } } catch (Exception e) { - LOG.log(Level.SEVERE, "Exception parsing CSV file " + sourceName, e); + LOG.log(Level.SEVERE, "Exception parsing bravo CSV file " + filename, e); } } From 85a75da5effc1059e684002a09c06e43346d608b Mon Sep 17 00:00:00 2001 From: Papick Garcia Taboada Date: Tue, 13 Sep 2016 17:00:10 +0200 Subject: [PATCH 26/96] Using try-with-resource --- .../trackfiles/impl/GPSFixImportTest.java | 132 ++++++++++++++---- .../impl/SensorDataImportServlet.java | 62 ++++---- .../impl/TrackFilesImportServlet.java | 123 ++++++++-------- .../RouteConverterGpx11ExtensionsTest.java | 55 ++++---- .../trackfiles/test/TrackFileImportTest.java | 44 +++--- .../test/TrackedRacesExportTest.java | 34 ++--- 6 files changed, 252 insertions(+), 198 deletions(-) diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/trackfiles/impl/GPSFixImportTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/trackfiles/impl/GPSFixImportTest.java index f1092ae3abd..b9f844c78f5 100755 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/trackfiles/impl/GPSFixImportTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/trackfiles/impl/GPSFixImportTest.java @@ -4,11 +4,15 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.BufferedInputStream; +import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; import java.util.Arrays; import java.util.Collection; +import org.apache.commons.fileupload.FileItem; import org.junit.Test; import com.sap.sailing.domain.common.tracking.GPSFix; @@ -30,32 +34,33 @@ public class GPSFixImportTest { @Test public void testReReadingEOFFromBufferedInputStream() throws IOException { - InputStream in = getClass().getResourceAsStream("/Cardiff Race17 - COMPETITORS.gpx"); - BufferedInputStreamWithPublicBuffer bis = new BufferedInputStreamWithPublicBuffer(in); - bis.mark(10*1024*1024); // the file has ~2MB, so 10MB is much more than twice the size, so should never be required - int size = 0; - while (bis.read() != -1) { - size++; + try (InputStream in = getClass().getResourceAsStream("/Cardiff Race17 - COMPETITORS.gpx"); + BufferedInputStreamWithPublicBuffer bis = new BufferedInputStreamWithPublicBuffer(in)) { + bis.mark(10 * 1024 * 1024); // the file has ~2MB, so 10MB is much more than twice the size, so should never + // be required + int size = 0; + while (bis.read() != -1) { + size++; + } + bis.reset(); + int secondSize = 0; + while (bis.read() != -1) { + secondSize++; + } + assertEquals(size, secondSize); + assertTrue(bis.getBuffer().length < 8 * 1024 * 1024); + bis.reset(); + int thirdSize = 0; + while (bis.read() != -1) { + thirdSize++; + } + assertEquals(size, thirdSize); + assertTrue(bis.getBuffer().length < 8 * 1024 * 1024); + // Now try to read EOF multiple times + for (int i = 1; i < 1000; i++) { + assertEquals(-1, bis.read()); + } } - bis.reset(); - int secondSize = 0; - while (bis.read() != -1) { - secondSize++; - } - assertEquals(size, secondSize); - assertTrue(bis.getBuffer().length < 8*1024*1024); - bis.reset(); - int thirdSize = 0; - while (bis.read() != -1) { - thirdSize++; - } - assertEquals(size, thirdSize); - assertTrue(bis.getBuffer().length < 8*1024*1024); - // Now try to read EOF multiple times - for (int i=1; i<1000; i++) { - assertEquals(-1, bis.read()); - } - bis.close(); } @Test @@ -73,8 +78,81 @@ public class GPSFixImportTest { public void storeFix(GPSFix fix, DeviceIdentifier deviceIdentifier) { } }; - InputStream in = getClass().getResourceAsStream("/Cardiff Race17 - COMPETITORS.gpx"); - servlet.importFiles(Arrays.asList(new Pair<>("test.gpx", in)), new AlwaysFailingGPSFixImporter(-1)); + FileItem fi = new FileItem() { + private static final long serialVersionUID = 1L; + + @Override + public void write(File file) throws Exception { + } + + @Override + public void setFormField(boolean state) { + } + + @Override + public void setFieldName(String name) { + } + + @Override + public boolean isInMemory() { + return false; + } + + @Override + public boolean isFormField() { + return false; + } + + @Override + public String getString(String encoding) throws UnsupportedEncodingException { + return null; + } + + @Override + public String getString() { + return null; + } + + @Override + public long getSize() { + return 0; + } + + @Override + public OutputStream getOutputStream() throws IOException { + return null; + } + + @Override + public String getName() { + return "Cardiff Race17 - COMPETITORS.gpx"; + } + + @Override + public InputStream getInputStream() throws IOException { + return getClass().getResourceAsStream("/" + getName()); + } + + @Override + public String getFieldName() { + return null; + } + + @Override + public String getContentType() { + return null; + } + + @Override + public byte[] get() { + return null; + } + + @Override + public void delete() { + } + }; + servlet.importFiles(Arrays.asList(new Pair<>("test.gpx", fi)), new AlwaysFailingGPSFixImporter(-1)); // getting to here without errors is good enough } } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/SensorDataImportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/SensorDataImportServlet.java index 2b05c88e9d3..c6004de2610 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/SensorDataImportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/SensorDataImportServlet.java @@ -63,12 +63,6 @@ public class SensorDataImportServlet extends AbstractFileUploadServlet { for (Pair file : files) { final String requestedImporterName = file.getA(); final FileItem fi = file.getB(); - BufferedInputStream in = new BufferedInputStream(fi.getInputStream()) { - @Override - public void close() throws IOException { - // prevent importers from closing this stream - } - }; DoubleVectorFixImporter importerToUse = null; for (DoubleVectorFixImporter candidate : availableImporters) { if (candidate.getType().equals(requestedImporterName)) { @@ -77,43 +71,37 @@ public class SensorDataImportServlet extends AbstractFileUploadServlet { } } if (importerToUse == null) { - in.close(); throw new RuntimeException("Sensor importer not found"); } - in.mark(READ_BUFFER_SIZE); - - try { - in.reset(); - } catch (IOException e1) { - logger.log(Level.SEVERE, "Could not reset stream", e1); - } logger.log(Level.INFO, "Going to import sensor data file with importer " + importerToUse.getClass().getSimpleName()); - try { - importerToUse.importFixes(in, new DoubleVectorFixImporter.Callback() { - @Override - public void addFixes(Iterable fixes, TrackFileImportDeviceIdentifier device) { - deviceIds.add(device); - storeFixes(fixes, device); - TimePoint earliestFixSoFarFromCurrentDevice = from.get(device); - TimePoint latestFixSoFarFromCurrentDevice = to.get(device); - for (DoubleVectorFix fix : fixes) { - if (earliestFixSoFarFromCurrentDevice == null - || earliestFixSoFarFromCurrentDevice.after(fix.getTimePoint())) { - earliestFixSoFarFromCurrentDevice = fix.getTimePoint(); - from.put(device, earliestFixSoFarFromCurrentDevice); - } - if (latestFixSoFarFromCurrentDevice == null - || latestFixSoFarFromCurrentDevice.before(fix.getTimePoint())) { - latestFixSoFarFromCurrentDevice = fix.getTimePoint(); - to.put(device, latestFixSoFarFromCurrentDevice); + try (BufferedInputStream in = new BufferedInputStream(fi.getInputStream())) { + try { + importerToUse.importFixes(in, new DoubleVectorFixImporter.Callback() { + @Override + public void addFixes(Iterable fixes, TrackFileImportDeviceIdentifier device) { + deviceIds.add(device); + storeFixes(fixes, device); + TimePoint earliestFixSoFarFromCurrentDevice = from.get(device); + TimePoint latestFixSoFarFromCurrentDevice = to.get(device); + for (DoubleVectorFix fix : fixes) { + if (earliestFixSoFarFromCurrentDevice == null + || earliestFixSoFarFromCurrentDevice.after(fix.getTimePoint())) { + earliestFixSoFarFromCurrentDevice = fix.getTimePoint(); + from.put(device, earliestFixSoFarFromCurrentDevice); + } + if (latestFixSoFarFromCurrentDevice == null + || latestFixSoFarFromCurrentDevice.before(fix.getTimePoint())) { + latestFixSoFarFromCurrentDevice = fix.getTimePoint(); + to.put(device, latestFixSoFarFromCurrentDevice); + } } } - } - }, fi.getName(), requestedImporterName); - logger.log(Level.INFO, "Successfully imported file " + requestedImporterName); - } catch (FormatNotSupportedException e) { - logger.log(Level.INFO, "Failed to import file " + requestedImporterName); + }, fi.getName(), requestedImporterName); + logger.log(Level.INFO, "Successfully imported file " + requestedImporterName); + } catch (FormatNotSupportedException e) { + logger.log(Level.INFO, "Failed to import file " + requestedImporterName); + } } } return deviceIds; diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/TrackFilesImportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/TrackFilesImportServlet.java index 6ac0062645b..f0d9f915c00 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/TrackFilesImportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/TrackFilesImportServlet.java @@ -2,18 +2,17 @@ package com.sap.sailing.server.gateway.trackfiles.impl; import java.io.BufferedInputStream; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -42,7 +41,8 @@ import com.sap.sse.common.Util.Pair; * The available importers are tried one by one in the following order, until the first one is found that does not fail * with an {@link FormatNotSupportedException}: *