diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/masterdataimport/TopLevelMasterData.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/masterdataimport/TopLevelMasterData.java index 21a84fb6dcb..768b39cc6f3 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/masterdataimport/TopLevelMasterData.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/masterdataimport/TopLevelMasterData.java @@ -23,6 +23,8 @@ import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.RegattaIdentifier; import com.sap.sailing.domain.common.WindSource; import com.sap.sailing.domain.common.media.MediaTrack; @@ -54,7 +56,7 @@ public class TopLevelMasterData implements Serializable { private static final long serialVersionUID = 4820893865792553281L; private final Map> raceIdStringsForRegatta; - private final Set allMediaTracks; + private final Set filteredMediaTracks; private final Set leaderboardGroups; private final Set windTrackMasterData; private final Map> eventForLeaderboardGroup; @@ -64,8 +66,6 @@ public class TopLevelMasterData implements Serializable { final Map regattaForRaceIdString, final Collection allMediaTracks, GPSFixStore gpsFixStore, boolean exportWind) { this.raceIdStringsForRegatta = convertToRaceIdStringsForRegattaMap(regattaForRaceIdString); - this.allMediaTracks = new HashSet(); - this.allMediaTracks.addAll(allMediaTracks); this.leaderboardGroups = groupsToExport; this.raceLogTrackingFixes = getAllRelevantRaceLogTrackingFixes(gpsFixStore); if (exportWind) { @@ -74,6 +74,8 @@ public class TopLevelMasterData implements Serializable { this.windTrackMasterData = new HashSet(); } this.eventForLeaderboardGroup = createEventMap(groupsToExport, allEvents); + this.filteredMediaTracks = new HashSet(); + filterMediaTracks(allMediaTracks, this.filteredMediaTracks); } private Map> getAllRelevantRaceLogTrackingFixes(GPSFixStore gpsFixStore) { @@ -240,8 +242,8 @@ public class TopLevelMasterData implements Serializable { } } - public Collection getAllMediaTracks() { - return allMediaTracks; + public Collection getFilteredMediaTracks() { + return this.filteredMediaTracks; } public Collection getLeaderboardGroups() { @@ -293,6 +295,43 @@ public class TopLevelMasterData implements Serializable { return regattas; } + /** + * Copies only those media tracks from allMediaTracks to filteredMediaTracks which are + * assigned to races related to the exported LeaderboardGroup. + */ + private void filterMediaTracks(Collection allMediaTracks, Set filteredMediaTracks) { + Set raceIdentitifiersForMediaExport = collectRaceIdentifiersForMediaExport(); + for (MediaTrack mediaTrack : allMediaTracks) { + for (RegattaAndRaceIdentifier raceIdentifier : mediaTrack.assignedRaces) { + if (raceIdentitifiersForMediaExport.contains(raceIdentifier)) { + filteredMediaTracks.add(mediaTrack); + continue; + } + } + } + } + + /** + * Returns the set of races (in form of raceIdentifiers) related to the exported LeaderboardGroup. + * + */ + private Set collectRaceIdentifiersForMediaExport() { + Set raceIdentifiers = new HashSet<>(); + for (LeaderboardGroup leaderboardGroup : leaderboardGroups) { + for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { + for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { + for (Fleet fleet : raceColumn.getFleets()) { + RaceIdentifier raceIdentifier = raceColumn.getRaceIdentifier(fleet); + if (raceIdentifier != null) { + raceIdentifiers.add(raceIdentifier); + } + } + } + } + } + return raceIdentifiers; + } + public Map> getRaceLogTrackingFixes() { return raceLogTrackingFixes; } diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/impl/MediaMasterDataExportTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/impl/MediaMasterDataExportTest.java new file mode 100644 index 00000000000..c676c77e60b --- /dev/null +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/impl/MediaMasterDataExportTest.java @@ -0,0 +1,189 @@ +package com.sap.sailing.server.impl; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.junit.Test; + +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.CourseArea; +import com.sap.sailing.domain.base.Event; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.base.Series; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.CourseAreaImpl; +import com.sap.sailing.domain.base.impl.FleetImpl; +import com.sap.sailing.domain.base.impl.RegattaImpl; +import com.sap.sailing.domain.base.impl.SeriesImpl; +import com.sap.sailing.domain.common.BoatClassMasterdata; +import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.RegattaNameAndRaceName; +import com.sap.sailing.domain.common.media.MediaTrack; +import com.sap.sailing.domain.common.media.MediaTrack.MimeType; +import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.LeaderboardGroup; +import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; +import com.sap.sailing.domain.leaderboard.ScoringScheme; +import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; +import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; +import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; +import com.sap.sailing.domain.leaderboard.impl.LowPoint; +import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardImpl; +import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; +import com.sap.sailing.domain.masterdataimport.TopLevelMasterData; +import com.sap.sailing.domain.racelog.tracking.GPSFixStore; +import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; +import com.sap.sse.common.Duration; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.impl.MillisecondsDurationImpl; +import com.sap.sse.common.impl.MillisecondsTimePoint; + +import static org.junit.Assert.*; + +import static org.mockito.Mockito.*; + +public class MediaMasterDataExportTest { + + static final String matchingRegattaName = "Matching Regatta"; + static final String missingRegattaName = "Missing Regatta"; + static final String matchingRace1 = "matching race 1"; + static final String matchingRace2 = "matching race 2"; + static final String matchingRace3 = "matching race 3"; + static final String missingRace1 = "missing race 1"; + static final String missingRace2 = "missing race 2"; + static final String missingRace3 = "missing race 3"; + + static final boolean displayGroupsInReverseOrder = true; + static final ThresholdBasedResultDiscardingRule resultDiscardingRule = new ThresholdBasedResultDiscardingRuleImpl(new int[0]); + static final BoatClass boatClass = new BoatClassImpl("boat class name", BoatClassMasterdata._12M); + static final TimePoint startDate = MillisecondsTimePoint.now(); + static final TimePoint endDate = startDate.plus(MillisecondsDurationImpl.ONE_DAY); + static final boolean isMedal = false; + static final Fleet regattaFleet = new FleetImpl("fleet name"); + static final boolean persistent = false; + static final ScoringScheme scoringScheme = new LowPoint(); + static final CourseArea courseArea = new CourseAreaImpl("Course Area", UUID.randomUUID()); + static final Serializable regatteId = "regatta id"; + + @Test + public void testTrackWithAssignedRaceButEmptyLeaderboardGroup() { + TimePoint startTime = null; + Duration duration = null; + MimeType mimeType = MimeType.mp4; + Collection allMediaTracks = Arrays.asList( + new MediaTrack("dbId 1", "title 1 for existing regatta and race", "url", startTime, duration, mimeType, Collections.singleton(new RegattaNameAndRaceName(matchingRegattaName, matchingRace1))), + new MediaTrack("dbId 2", "title 2 for existing one regatta and race and one missing regatta", "url", startTime, duration, mimeType, new HashSet(Arrays.asList(new RegattaNameAndRaceName(missingRegattaName, matchingRace2), new RegattaNameAndRaceName(matchingRegattaName, matchingRace2)))), + new MediaTrack("dbId 3", "title 1 for missing regatta", "url", startTime, duration, mimeType, Collections.singleton(new RegattaNameAndRaceName(missingRegattaName, matchingRace1))), + new MediaTrack("dbId 4", "title 2 for missing regatta", "url", startTime, duration, mimeType, new HashSet(Arrays.asList(new RegattaNameAndRaceName(missingRegattaName, matchingRace3), new RegattaNameAndRaceName(matchingRegattaName, missingRace1)))) + ); + Collection regattaRaces = Collections.emptyList(); + Collection flexibleRaces = Collections.emptyList(); + TopLevelMasterData topLevelMasterData = createTopLevelMasterData(regattaRaces , flexibleRaces, allMediaTracks); + Collection filteredMediaTracks = topLevelMasterData.getFilteredMediaTracks(); + assertEquals(0, filteredMediaTracks.size()); + } + + @Test + public void testTracksWithAssignedRaceAndMatchingRegattaInLeaderboardGroup() { + TimePoint startTime = null; + Duration duration = null; + MimeType mimeType = MimeType.mp4; + Collection allMediaTracks = Arrays.asList( + new MediaTrack("dbId 1", "title 1 for existing regatta and race", "url", startTime, duration, mimeType, Collections.singleton(new RegattaNameAndRaceName(matchingRegattaName, matchingRace1))), + new MediaTrack("dbId 2", "title 2 for existing one regatta and race and one missing regatta", "url", startTime, duration, mimeType, new HashSet(Arrays.asList(new RegattaNameAndRaceName(missingRegattaName, matchingRace2), new RegattaNameAndRaceName(matchingRegattaName, matchingRace2)))), + new MediaTrack("dbId 3", "title 3 for missing regatta", "url", startTime, duration, mimeType, Collections.singleton(new RegattaNameAndRaceName(missingRegattaName, matchingRace1))), + new MediaTrack("dbId 4", "title 4 for missing regatta", "url", startTime, duration, mimeType, new HashSet(Arrays.asList(new RegattaNameAndRaceName(missingRegattaName, matchingRace3), new RegattaNameAndRaceName(matchingRegattaName, missingRace1)))), + new MediaTrack("dbId 5", "title 5 for existing regatta and race", "url", startTime, duration, mimeType, Collections.singleton(new RegattaNameAndRaceName(matchingRegattaName, matchingRace1))) + ); + Collection regattaRaces = Arrays.asList( + new RegattaNameAndRaceName(matchingRegattaName, matchingRace1), + new RegattaNameAndRaceName(matchingRegattaName, matchingRace2), + new RegattaNameAndRaceName(matchingRegattaName, matchingRace3) + ); + Collection flexibleRaces = Collections.emptyList(); + TopLevelMasterData topLevelMasterData = createTopLevelMasterData(regattaRaces , flexibleRaces, allMediaTracks); + Collection filteredMediaTracks = topLevelMasterData.getFilteredMediaTracks(); + assertEquals(3, filteredMediaTracks.size()); + } + + @Test + public void testTrackWithAssignedRaceAndMatchingFlexibleLeaderboardInLeaderboardGroup() { + TimePoint startTime = null; + Duration duration = null; + MimeType mimeType = MimeType.mp4; + Collection allMediaTracks = Arrays.asList( + new MediaTrack("dbId 1", "title 1 for existing regatta and race", "url", startTime, duration, mimeType, Collections.singleton(new RegattaNameAndRaceName(matchingRegattaName, matchingRace1))), + new MediaTrack("dbId 2", "title 2 for existing one regatta and race and one missing regatta", "url", startTime, duration, mimeType, new HashSet(Arrays.asList(new RegattaNameAndRaceName(missingRegattaName, matchingRace2), new RegattaNameAndRaceName(matchingRegattaName, matchingRace2)))), + new MediaTrack("dbId 3", "title 3 for missing regatta", "url", startTime, duration, mimeType, Collections.singleton(new RegattaNameAndRaceName(missingRegattaName, matchingRace1))), + new MediaTrack("dbId 4", "title 4 for missing regatta", "url", startTime, duration, mimeType, new HashSet(Arrays.asList(new RegattaNameAndRaceName(missingRegattaName, matchingRace3), new RegattaNameAndRaceName(matchingRegattaName, missingRace1)))), + new MediaTrack("dbId 5", "title 5 for existing regatta and race", "url", startTime, duration, mimeType, Collections.singleton(new RegattaNameAndRaceName(matchingRegattaName, matchingRace1))) + ); + Collection regattaRaces = Collections.emptyList(); + Collection flexibleRaces = Arrays.asList( + new RegattaNameAndRaceName(matchingRegattaName, matchingRace1), + new RegattaNameAndRaceName(matchingRegattaName, matchingRace2), + new RegattaNameAndRaceName(matchingRegattaName, matchingRace3) + ); + TopLevelMasterData topLevelMasterData = createTopLevelMasterData(regattaRaces , flexibleRaces, allMediaTracks); + Collection filteredMediaTracks = topLevelMasterData.getFilteredMediaTracks(); + assertEquals(3, filteredMediaTracks.size()); + } + + private TopLevelMasterData createTopLevelMasterData(Collection regattaRaces, Collection flexibleRaces, Collection allMediaTracks) { + Set raceColumnNames = new HashSet<>(); + for (RaceIdentifier regattaAndRaceIdentifier : regattaRaces) { + raceColumnNames.add(regattaAndRaceIdentifier.getRaceName()); + } + Regatta regatta = createTestRegatta("regatta name", raceColumnNames); + RegattaLeaderboard regattaLeaderboard = new RegattaLeaderboardImpl(regatta, resultDiscardingRule); + assignRacesToRegattaLeaderboardColumns(regattaLeaderboard, regattaRaces); + + FlexibleLeaderboard flexibleLeaderboard = new FlexibleLeaderboardImpl("flexible leaderboard", resultDiscardingRule, scoringScheme , courseArea); + for (RaceIdentifier regattaAndRaceIdentifier : flexibleRaces) { + RaceColumn raceColumn = flexibleLeaderboard.addRaceColumn(regattaAndRaceIdentifier.getRaceName(), isMedal); + Fleet defaultFleet = raceColumn.getFleets().iterator().next(); + raceColumn.setRaceIdentifier(defaultFleet, regattaAndRaceIdentifier); + } + + + List leaderboards = Arrays.asList(regattaLeaderboard, flexibleLeaderboard); + LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl("name", "description", "displayName", displayGroupsInReverseOrder , leaderboards); + Set groupsToExport = Collections.singleton(leaderboardGroup); + Iterable allEvents = Collections.emptyList(); + Map regattaForRaceIdString = Collections.emptyMap(); + GPSFixStore gpsFixStore = mock(GPSFixStore.class); + boolean exportWind = false; + TopLevelMasterData topLevelMasterData = new TopLevelMasterData(groupsToExport , allEvents , regattaForRaceIdString, allMediaTracks , gpsFixStore , exportWind); + return topLevelMasterData; + } + + public static void assignRacesToRegattaLeaderboardColumns(RegattaLeaderboard leaderboard, Collection raceIdentifiers) { + Iterator regattaRacesIterator = raceIdentifiers.iterator(); + for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { + raceColumn.setRaceIdentifier(regattaFleet, regattaRacesIterator.next()); + } + } + + public static RegattaImpl createTestRegatta(String regattaName, Iterable raceColumnNames) { + Iterable regattaFleets = Collections.singleton(regattaFleet); + TrackedRegattaRegistry trackedRegattaRegistry = mock(TrackedRegattaRegistry.class); + Series series = new SeriesImpl("series name", isMedal, regattaFleets, raceColumnNames, trackedRegattaRegistry); + Iterable regattaSeries = Collections.singleton(series); + return new RegattaImpl(regattaName, boatClass, startDate, endDate, regattaSeries, persistent, scoringScheme, regatteId , courseArea); + } + + + +} 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 c553911c8d0..cb70250144e 100755 --- 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 @@ -1,11 +1,5 @@ package com.sap.sailing.server.test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; - import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -14,6 +8,7 @@ import java.io.Serializable; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; @@ -77,8 +72,10 @@ import com.sap.sailing.domain.common.CourseDesignerMode; import com.sap.sailing.domain.common.MasterDataImportObjectCreationCount; import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.RegattaNameAndRaceName; +import com.sap.sailing.domain.common.ScoringSchemeType; import com.sap.sailing.domain.common.SpeedWithBearing; import com.sap.sailing.domain.common.Wind; import com.sap.sailing.domain.common.WindSource; @@ -115,6 +112,7 @@ import com.sap.sailing.domain.tracking.impl.EmptyWindStore; import com.sap.sailing.server.RacingEventService; import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource; import com.sap.sailing.server.gateway.jaxrs.spi.MasterDataResource; +import com.sap.sailing.server.impl.MediaMasterDataExportTest; import com.sap.sailing.server.impl.RacingEventServiceImpl; import com.sap.sailing.server.masterdata.DummyTrackedRace; import com.sap.sailing.server.masterdata.MasterDataImporter; @@ -126,6 +124,10 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.mongodb.MongoDBConfiguration; import com.sap.sse.mongodb.MongoDBService; +import static org.junit.Assert.*; + +import static org.mockito.Mockito.*; + public class MasterDataImportTest { private static final String TEST_GROUP_NAME = "testGroup"; @@ -1674,17 +1676,45 @@ public class MasterDataImportTest { // Setup source service RacingEventService sourceService = new RacingEventServiceImpl(); Set assignedRaces = new HashSet(); - assignedRaces.add(new RegattaNameAndRaceName("49er", "R1")); - assignedRaces.add(new RegattaNameAndRaceName("49er", "R2")); - assignedRaces.add(new RegattaNameAndRaceName("48er", "F1")); - assignedRaces.add(new RegattaNameAndRaceName("48er", "F2")); - assignedRaces.add(new RegattaNameAndRaceName("48er", "F3")); + String regattaName1 = "49er"; + String regattaName2 = "49er FX"; + String missingRegattaName = "Missing Regatta"; + String raceName1 = "R1"; + String raceName2 = "R2"; + String raceName3 = "R3"; + String raceName4 = "R4"; + String raceName5 = "R5"; + String missingRaceName = "Missing Race"; + assignedRaces.add(new RegattaNameAndRaceName(regattaName1, raceName1)); + assignedRaces.add(new RegattaNameAndRaceName(regattaName1, raceName2)); + assignedRaces.add(new RegattaNameAndRaceName(regattaName1, raceName3)); + assignedRaces.add(new RegattaNameAndRaceName(regattaName2, raceName4)); + assignedRaces.add(new RegattaNameAndRaceName(regattaName2, raceName5)); + assignedRaces.add(new RegattaNameAndRaceName(missingRegattaName, missingRaceName)); MediaTrack trackOnSource = new MediaTrack("testTitle", "http://test/test.mp4", new MillisecondsTimePoint(0), MillisecondsDurationImpl.ONE_HOUR, MediaTrack.MimeType.mp4, assignedRaces); sourceService.mediaTrackAdded(trackOnSource); - + + Collection raceColumnNames = Arrays.asList(raceName1, raceName2, raceName3, raceName4, raceName5); + Regatta regatta = MediaMasterDataExportTest.createTestRegatta(regattaName1, raceColumnNames); + sourceService.addRegattaWithoutReplication(regatta); + int[] discardThresholds = new int[0]; + RegattaLeaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), "leaderboard display name", discardThresholds); + Collection raceIdentifiers = Arrays.asList( + new RegattaNameAndRaceName(regattaName1, raceName1), + new RegattaNameAndRaceName(regattaName1, raceName2), + new RegattaNameAndRaceName(regattaName1, raceName3), + new RegattaNameAndRaceName(regattaName2, raceName4), + new RegattaNameAndRaceName(regattaName2, raceName5) + ); + MediaMasterDataExportTest.assignRacesToRegattaLeaderboardColumns(leaderboard, raceIdentifiers); + boolean displayGroupsInReverseOrder = false; + int[] overallLeaderboardDiscardThresholds = new int[0]; + UUID leaderboardGropuUuid = UUID.randomUUID(); + LeaderboardGroup leaderboardGroup = sourceService.addLeaderboardGroup(leaderboardGropuUuid , "leaderboard group name", "leaderboard group description", "leaderboard group display name", displayGroupsInReverseOrder, Collections.singletonList(leaderboard.getName()), overallLeaderboardDiscardThresholds, ScoringSchemeType.LOW_POINT); + // Serialize - List groupNamesToExport = new ArrayList(); + List groupNamesToExport = Collections.singletonList(leaderboardGroup.getName()); RacingEventService destService; DomainFactory domainFactory; diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/MasterDataImporter.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/MasterDataImporter.java index d75e5abc351..c7da99ec747 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/MasterDataImporter.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/MasterDataImporter.java @@ -86,7 +86,7 @@ public class MasterDataImporter { ImportMasterDataOperation op = new ImportMasterDataOperation(topLevelMasterData, importOperationId, override, creationCount); creationCount = racingEventService.apply(op); - racingEventService.mediaTracksImported(topLevelMasterData.getAllMediaTracks(), override); + racingEventService.mediaTracksImported(topLevelMasterData.getFilteredMediaTracks(), override); return creationCount; }