9fdf410f46ad549604099b93333bc1bba5738a2a
java/com.sap.sailing.domain.tractracadapter.persistence/src/com/sap/sailing/domain/tractracadapter/persistence/impl/TracTracConnectivityParamsHandler.java
| ... | ... | @@ -3,6 +3,7 @@ package com.sap.sailing.domain.tractracadapter.persistence.impl; |
| 3 | 3 | import java.io.IOException; |
| 4 | 4 | import java.net.MalformedURLException; |
| 5 | 5 | import java.net.URI; |
| 6 | +import java.net.URISyntaxException; |
|
| 6 | 7 | import java.net.URL; |
| 7 | 8 | import java.util.HashMap; |
| 8 | 9 | import java.util.Map; |
| ... | ... | @@ -24,6 +25,8 @@ import com.sap.sse.common.impl.MillisecondsDurationImpl; |
| 24 | 25 | import com.sap.sse.common.impl.MillisecondsTimePoint; |
| 25 | 26 | import com.sap.sse.security.SecurityService; |
| 26 | 27 | import com.sap.sse.security.SessionUtils; |
| 28 | +import com.tractrac.model.lib.api.event.CreateModelException; |
|
| 29 | +import com.tractrac.util.lib.api.exceptions.TimeOutException; |
|
| 27 | 30 | |
| 28 | 31 | /** |
| 29 | 32 | * Handles mapping TracTrac connectivity parameters from and to a map with {@link String} keys. The |
| ... | ... | @@ -139,7 +142,7 @@ public class TracTracConnectivityParamsHandler extends AbstractRaceTrackingConne |
| 139 | 142 | } |
| 140 | 143 | |
| 141 | 144 | private void updatePersistentTracTracConfiguration(RaceTrackingConnectivityParametersImpl params) |
| 142 | - throws MalformedURLException, IOException, ParseException { |
|
| 145 | + throws MalformedURLException, IOException, ParseException, CreateModelException, URISyntaxException, TimeOutException { |
|
| 143 | 146 | final String jsonURL = params.getTractracRace().getParameterSet().getParameter("eventJSON"); |
| 144 | 147 | final String creatorName = SessionUtils.getPrincipal().toString(); |
| 145 | 148 | final TracTracConfigurationImpl tracTracConfiguration = new TracTracConfigurationImpl(creatorName, params.getTractracRace().getEvent().getName(), jsonURL, |
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java
| ... | ... | @@ -65,6 +65,7 @@ import com.tractrac.model.lib.api.route.IControlPoint; |
| 65 | 65 | import com.tractrac.subscription.lib.api.IEventSubscriber; |
| 66 | 66 | import com.tractrac.subscription.lib.api.IRaceSubscriber; |
| 67 | 67 | import com.tractrac.subscription.lib.api.SubscriberInitializationException; |
| 68 | +import com.tractrac.util.lib.api.exceptions.TimeOutException; |
|
| 68 | 69 | |
| 69 | 70 | import difflib.PatchFailedException; |
| 70 | 71 | |
| ... | ... | @@ -152,8 +153,8 @@ public interface DomainFactory { |
| 152 | 153 | WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry, RaceLogAndTrackedRaceResolver raceLogResolver, |
| 153 | 154 | LeaderboardGroupResolver leaderboardGroupResolver, |
| 154 | 155 | RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds, |
| 155 | - RaceTrackingHandler raceTrackingHandler) |
|
| 156 | - throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException; |
|
| 156 | + RaceTrackingHandler raceTrackingHandler) throws URISyntaxException, SubscriberInitializationException, |
|
| 157 | + IOException, InterruptedException, CreateModelException, TimeOutException; |
|
| 157 | 158 | |
| 158 | 159 | /** |
| 159 | 160 | * Same as {@link #createRaceTracker(URL, URI, URI, URI, TimePoint, TimePoint, WindStore, TrackedRegattaRegistry)}, |
| ... | ... | @@ -165,7 +166,7 @@ public interface DomainFactory { |
| 165 | 166 | RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds, |
| 166 | 167 | RaceTrackingHandler raceTrackingHandler) |
| 167 | 168 | throws MalformedURLException, FileNotFoundException, URISyntaxException, CreateModelException, |
| 168 | - SubscriberInitializationException, IOException, InterruptedException; |
|
| 169 | + SubscriberInitializationException, IOException, InterruptedException, TimeOutException; |
|
| 169 | 170 | |
| 170 | 171 | BoatClass getOrCreateBoatClass(String competitorClassName); |
| 171 | 172 |
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java
| ... | ... | @@ -116,6 +116,7 @@ import com.tractrac.model.lib.api.route.IControlPoint; |
| 116 | 116 | import com.tractrac.subscription.lib.api.IEventSubscriber; |
| 117 | 117 | import com.tractrac.subscription.lib.api.IRaceSubscriber; |
| 118 | 118 | import com.tractrac.subscription.lib.api.SubscriberInitializationException; |
| 119 | +import com.tractrac.util.lib.api.exceptions.TimeOutException; |
|
| 119 | 120 | |
| 120 | 121 | import difflib.PatchFailedException; |
| 121 | 122 | |
| ... | ... | @@ -645,7 +646,8 @@ public class DomainFactoryImpl implements DomainFactory { |
| 645 | 646 | try { |
| 646 | 647 | raceDefinition = raceTrackingHandler.createRaceDefinition(trackedRegatta.getRegatta(), raceName, course, boatClass, competitorsAndBoats, raceId); |
| 647 | 648 | } catch (RuntimeException exception) { |
| 648 | - final String reasonForNotAddingRaceToRegatta = "Error while creating race " + raceDefinition + " for regatta " + trackedRegatta.getRegatta(); |
|
| 649 | + final String reasonForNotAddingRaceToRegatta = "Error while creating race " + raceDefinition |
|
| 650 | + + " for regatta " + trackedRegatta.getRegatta() + ": " + exception.getMessage(); |
|
| 649 | 651 | errorWhileTryingToTrackRace(trackedRegatta, raceDefinitionSetToUpdate, raceDefinition, reasonForNotAddingRaceToRegatta); |
| 650 | 652 | } |
| 651 | 653 | } else { |
| ... | ... | @@ -1029,7 +1031,7 @@ public class DomainFactoryImpl implements DomainFactory { |
| 1029 | 1031 | LeaderboardGroupResolver leaderboardGroupResolver, |
| 1030 | 1032 | RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds, |
| 1031 | 1033 | RaceTrackingHandler raceTrackingHandler) |
| 1032 | - throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException { |
|
| 1034 | + throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException, CreateModelException, TimeOutException { |
|
| 1033 | 1035 | return new TracTracRaceTrackerImpl(this, raceLogStore, regattaLogStore, windStore, trackedRegattaRegistry, |
| 1034 | 1036 | raceLogResolver, leaderboardGroupResolver, connectivityParams, timeoutInMilliseconds, raceTrackingHandler); |
| 1035 | 1037 | } |
| ... | ... | @@ -1040,7 +1042,7 @@ public class DomainFactoryImpl implements DomainFactory { |
| 1040 | 1042 | LeaderboardGroupResolver leaderboardGroupResolver, |
| 1041 | 1043 | RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds, |
| 1042 | 1044 | RaceTrackingHandler raceTrackingHandler) throws URISyntaxException, CreateModelException, |
| 1043 | - SubscriberInitializationException, IOException, InterruptedException { |
|
| 1045 | + SubscriberInitializationException, IOException, InterruptedException, TimeOutException { |
|
| 1044 | 1046 | return new TracTracRaceTrackerImpl(regatta, this, raceLogStore, regattaLogStore, windStore, trackedRegattaRegistry, |
| 1045 | 1047 | raceLogResolver, leaderboardGroupResolver, connectivityParams, timeoutInMilliseconds, raceTrackingHandler); |
| 1046 | 1048 | } |
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceTrackingConnectivityParametersImpl.java
| ... | ... | @@ -25,6 +25,7 @@ import com.tractrac.model.lib.api.ModelLocator; |
| 25 | 25 | import com.tractrac.model.lib.api.event.CreateModelException; |
| 26 | 26 | import com.tractrac.model.lib.api.event.IRace; |
| 27 | 27 | import com.tractrac.subscription.lib.api.SubscriberInitializationException; |
| 28 | +import com.tractrac.util.lib.api.exceptions.TimeOutException; |
|
| 28 | 29 | |
| 29 | 30 | public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTrackingConnectivityParameters { |
| 30 | 31 | |
| ... | ... | @@ -49,7 +50,6 @@ public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTracking |
| 49 | 50 | private final String raceVisibility; |
| 50 | 51 | private final boolean useInternalMarkPassingAlgorithm; |
| 51 | 52 | private final boolean preferReplayIfAvailable; |
| 52 | - private final transient IRace tractracRace; |
|
| 53 | 53 | private final int timeoutInMillis; |
| 54 | 54 | private final boolean useOfficialEventsToUpdateRaceLog; |
| 55 | 55 | |
| ... | ... | @@ -78,11 +78,7 @@ public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTracking |
| 78 | 78 | this.useOfficialEventsToUpdateRaceLog = useOfficialEventsToUpdateRaceLog; |
| 79 | 79 | this.paramURL = paramURL; |
| 80 | 80 | this.timeoutInMillis = timeoutInMillis; |
| 81 | - if (timeoutInMillis == -1) { |
|
| 82 | - this.tractracRace = ModelLocator.getEventFactory().createRace(new URI(paramURL.toString())); |
|
| 83 | - } else { |
|
| 84 | - this.tractracRace = ModelLocator.getEventFactory().createRace(new URI(paramURL.toString()), timeoutInMillis); |
|
| 85 | - } |
|
| 81 | + final IRace tractracRace = getTractracRace(); |
|
| 86 | 82 | if (preferReplayIfAvailable && isReplayRace(tractracRace) && |
| 87 | 83 | (!Util.equalsWithNull(liveURI, tractracRace.getLiveURI()) || !Util.equalsWithNull(storedURI, tractracRace.getStoredURI()))) { |
| 88 | 84 | logger.info("Replay format available and preferred for race " + tractracRace.getName() |
| ... | ... | @@ -114,8 +110,14 @@ public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTracking |
| 114 | 110 | return tractracRace.getStoredURI() != null && tractracRace.getStoredURI().toString().toLowerCase().endsWith(".mtb"); |
| 115 | 111 | } |
| 116 | 112 | |
| 117 | - public IRace getTractracRace() { |
|
| 118 | - return tractracRace; |
|
| 113 | + public IRace getTractracRace() throws CreateModelException, URISyntaxException, TimeOutException { |
|
| 114 | + final IRace result; |
|
| 115 | + if (getTimeoutInMillis() == -1) { |
|
| 116 | + result = ModelLocator.getEventFactory().createRace(new URI(paramURL.toString())); |
|
| 117 | + } else { |
|
| 118 | + result = ModelLocator.getEventFactory().createRace(new URI(paramURL.toString()), getTimeoutInMillis()); |
|
| 119 | + } |
|
| 120 | + return result; |
|
| 119 | 121 | } |
| 120 | 122 | |
| 121 | 123 | @Override |
| ... | ... | @@ -127,7 +129,7 @@ public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTracking |
| 127 | 129 | public RaceTracker createRaceTracker(TrackedRegattaRegistry trackedRegattaRegistry, WindStore windStore, |
| 128 | 130 | RaceLogAndTrackedRaceResolver raceLogResolver, LeaderboardGroupResolver leaderboardGroupResolver, |
| 129 | 131 | long timeoutInMilliseconds, RaceTrackingHandler raceTrackingHandler) throws URISyntaxException, |
| 130 | - CreateModelException, SubscriberInitializationException, IOException, InterruptedException { |
|
| 132 | + CreateModelException, SubscriberInitializationException, IOException, InterruptedException, TimeOutException { |
|
| 131 | 133 | RaceTracker tracker = domainFactory.createRaceTracker(raceLogStore, regattaLogStore, windStore, |
| 132 | 134 | trackedRegattaRegistry, raceLogResolver, leaderboardGroupResolver, this, timeoutInMilliseconds, |
| 133 | 135 | raceTrackingHandler); |
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java
| ... | ... | @@ -56,6 +56,7 @@ import com.sap.sse.common.Duration; |
| 56 | 56 | import com.sap.sse.common.TimePoint; |
| 57 | 57 | import com.sap.sse.common.Util; |
| 58 | 58 | import com.sap.sse.util.impl.ThreadFactoryWithPriority; |
| 59 | +import com.tractrac.model.lib.api.event.CreateModelException; |
|
| 59 | 60 | import com.tractrac.model.lib.api.event.DataSource; |
| 60 | 61 | import com.tractrac.model.lib.api.event.ICompetitor; |
| 61 | 62 | import com.tractrac.model.lib.api.event.IEvent; |
| ... | ... | @@ -71,6 +72,7 @@ import com.tractrac.subscription.lib.api.event.IConnectionStatusListener; |
| 71 | 72 | import com.tractrac.subscription.lib.api.event.ILiveDataEvent; |
| 72 | 73 | import com.tractrac.subscription.lib.api.event.IStoredDataEvent; |
| 73 | 74 | import com.tractrac.subscription.lib.api.race.IRacesListener; |
| 75 | +import com.tractrac.util.lib.api.exceptions.TimeOutException; |
|
| 74 | 76 | |
| 75 | 77 | public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl |
| 76 | 78 | implements IConnectionStatusListener, TracTracRaceTracker, DynamicRaceDefinitionSet, TrackingDataLoader { |
| ... | ... | @@ -270,11 +272,12 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl |
| 270 | 272 | * you expect things to have loaded; see also |
| 271 | 273 | * {@link RaceTracker#TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS}. |
| 272 | 274 | */ |
| 273 | - TracTracRaceTrackerImpl(DomainFactory domainFactory, RaceLogStore raceLogStore, |
|
| 274 | - RegattaLogStore regattaLogStore, WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry, |
|
| 275 | - RaceLogAndTrackedRaceResolver raceLogResolver, LeaderboardGroupResolver leaderboardGroupResolver, RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds, |
|
| 276 | - RaceTrackingHandler raceTrackingHandler) |
|
| 277 | - throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException { |
|
| 275 | + TracTracRaceTrackerImpl(DomainFactory domainFactory, RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, |
|
| 276 | + WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry, |
|
| 277 | + RaceLogAndTrackedRaceResolver raceLogResolver, LeaderboardGroupResolver leaderboardGroupResolver, |
|
| 278 | + RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds, |
|
| 279 | + RaceTrackingHandler raceTrackingHandler) throws URISyntaxException, SubscriberInitializationException, |
|
| 280 | + IOException, InterruptedException, CreateModelException, TimeOutException { |
|
| 278 | 281 | this(/* regatta */ null, domainFactory, raceLogStore, regattaLogStore, windStore, trackedRegattaRegistry, |
| 279 | 282 | raceLogResolver, leaderboardGroupResolver, connectivityParams, timeoutInMilliseconds, |
| 280 | 283 | raceTrackingHandler); |
| ... | ... | @@ -299,7 +302,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl |
| 299 | 302 | RaceLogAndTrackedRaceResolver raceLogResolver, LeaderboardGroupResolver leaderboardGroupResolver, |
| 300 | 303 | RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds, |
| 301 | 304 | RaceTrackingHandler raceTrackingHandler) |
| 302 | - throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException { |
|
| 305 | + throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException, CreateModelException, TimeOutException { |
|
| 303 | 306 | super(connectivityParams); |
| 304 | 307 | final URL paramURL = connectivityParams.getParamURL(); |
| 305 | 308 | final URI liveURI = connectivityParams.getLiveURI(); |
java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRegattaRegistry.java
| ... | ... | @@ -102,11 +102,15 @@ public interface TrackedRegattaRegistry { |
| 102 | 102 | * example, if tracking for a regatta shall be started early, so as to enable race officials to see the course |
| 103 | 103 | * geometry and wind data for the first race of the day, then especially in self-service scenarios there may be late |
| 104 | 104 | * competitors registrations that happen after tracking has been started. These competitors, depending on how the |
| 105 | - * connector in use works, may make it into the regatta's leaderboard, but not into the {@link RaceDefinition}. |
|
| 106 | - * This would be unfortunate as those competitors then would remain invisible until the race is reloaded.<p> |
|
| 105 | + * connector in use works, may make it into the regatta's leaderboard, but not into the {@link RaceDefinition}. This |
|
| 106 | + * would be unfortunate as those competitors then would remain invisible until the race is reloaded. |
|
| 107 | + * <p> |
|
| 107 | 108 | * |
| 108 | 109 | * See also <a href="https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=5219">bug 5219</a> for a discussion. |
| 109 | - * @return |
|
| 110 | + * |
|
| 111 | + * @return {@code null} if it was not possible to re-load the race, either because the regatta doesn't allow for it, |
|
| 112 | + * or because the connectivity parameters were not found; a {@link RaceHandle} for the re-started race |
|
| 113 | + * otherwise. |
|
| 110 | 114 | */ |
| 111 | 115 | RaceHandle updateRaceCompetitors(Regatta regatta, RaceDefinition race) throws Exception; |
| 112 | 116 | } |
java/com.sap.sailing.server.gateway/webservices/api/v2/leaderboardGetDoc.html
| ... | ... | @@ -71,7 +71,8 @@ There is also the 'ALL' shortcut constant which can be used to get all available |
| 71 | 71 | </tr> |
| 72 | 72 | <tr> |
| 73 | 73 | <td> </td> |
| 74 | - <td>raceDetails [Default = RACE_GAP_TO_LEADER_IN_SECONDS, RACE_AVERAGE_SPEED_OVER_GROUND_IN_KNOTS, RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS, RACE_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD_IN_METERS, CURRENT_LEG]</td> |
|
| 74 | + <td>raceDetails [Default = RACE_GAP_TO_LEADER_IN_SECONDS, RACE_AVERAGE_SPEED_OVER_GROUND_IN_KNOTS, RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS, RACE_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD_IN_METERS, CURRENT_LEG]; |
|
| 75 | + use "ALL" to get all detail types supported.</td> |
|
| 75 | 76 | </tr> |
| 76 | 77 | <tr> |
| 77 | 78 | <td> </td> |
java/com.sap.sailing.server.test/.settings/org.eclipse.core.resources.prefs
| ... | ... | @@ -1,2 +1,3 @@ |
| 1 | 1 | eclipse.preferences.version=1 |
| 2 | +encoding//src/com/sap/sailing/server/test/AutomaticRetrackUponCompetitorSetChangeTest.java=UTF-8 |
|
| 2 | 3 | encoding//src/com/sap/sailing/server/util/ShardingLeaderBoardEncodingTest.java=UTF-8 |
java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/AutomaticRetrackUponCompetitorSetChangeTest.java
| ... | ... | @@ -0,0 +1,183 @@ |
| 1 | +package com.sap.sailing.server.test; |
|
| 2 | + |
|
| 3 | +import static org.junit.Assert.assertEquals; |
|
| 4 | +import static org.junit.Assert.assertNotNull; |
|
| 5 | +import static org.junit.Assert.assertNotSame; |
|
| 6 | +import static org.junit.Assert.fail; |
|
| 7 | +import static org.mockito.Mockito.mock; |
|
| 8 | +import static org.mockito.Mockito.when; |
|
| 9 | + |
|
| 10 | +import java.net.URI; |
|
| 11 | +import java.net.URL; |
|
| 12 | +import java.util.Arrays; |
|
| 13 | +import java.util.Collections; |
|
| 14 | +import java.util.GregorianCalendar; |
|
| 15 | +import java.util.TimeZone; |
|
| 16 | +import java.util.UUID; |
|
| 17 | + |
|
| 18 | +import org.mockito.Matchers; |
|
| 19 | +import org.junit.After; |
|
| 20 | +import org.junit.Before; |
|
| 21 | +import org.junit.Test; |
|
| 22 | +import org.osgi.framework.BundleContext; |
|
| 23 | + |
|
| 24 | +import com.sap.sailing.domain.base.Competitor; |
|
| 25 | +import com.sap.sailing.domain.base.CompetitorAndBoatStore; |
|
| 26 | +import com.sap.sailing.domain.base.DomainFactory; |
|
| 27 | +import com.sap.sailing.domain.base.RaceDefinition; |
|
| 28 | +import com.sap.sailing.domain.base.Regatta; |
|
| 29 | +import com.sap.sailing.domain.base.impl.DomainFactoryImpl; |
|
| 30 | +import com.sap.sailing.domain.common.CompetitorRegistrationType; |
|
| 31 | +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; |
|
| 32 | +import com.sap.sailing.domain.common.RegattaName; |
|
| 33 | +import com.sap.sailing.domain.common.dto.FleetDTO; |
|
| 34 | +import com.sap.sailing.domain.leaderboard.impl.LowPoint; |
|
| 35 | +import com.sap.sailing.domain.persistence.DomainObjectFactory; |
|
| 36 | +import com.sap.sailing.domain.persistence.MongoObjectFactory; |
|
| 37 | +import com.sap.sailing.domain.persistence.PersistenceFactory; |
|
| 38 | +import com.sap.sailing.domain.persistence.media.MediaDBFactory; |
|
| 39 | +import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver; |
|
| 40 | +import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore; |
|
| 41 | +import com.sap.sailing.domain.racelog.tracking.EmptySensorFixStore; |
|
| 42 | +import com.sap.sailing.domain.ranking.OneDesignRankingMetric; |
|
| 43 | +import com.sap.sailing.domain.regattalog.impl.EmptyRegattaLogStore; |
|
| 44 | +import com.sap.sailing.domain.test.AbstractTracTracLiveTest; |
|
| 45 | +import com.sap.sailing.domain.tracking.RaceHandle; |
|
| 46 | +import com.sap.sailing.domain.tracking.RaceTracker; |
|
| 47 | +import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParameters; |
|
| 48 | +import com.sap.sailing.domain.tracking.RaceTrackingHandler.DefaultRaceTrackingHandler; |
|
| 49 | +import com.sap.sailing.domain.tracking.TrackedRace; |
|
| 50 | +import com.sap.sailing.domain.tracking.impl.EmptyWindStore; |
|
| 51 | +import com.sap.sailing.server.impl.RacingEventServiceImpl; |
|
| 52 | +import com.sap.sailing.server.impl.RacingEventServiceImpl.ConstructorParameters; |
|
| 53 | +import com.sap.sailing.server.interfaces.RacingEventService; |
|
| 54 | +import com.sap.sailing.server.operationaltransformation.CreateTrackedRace; |
|
| 55 | +import com.sap.sailing.server.operationaltransformation.UpdateSeries; |
|
| 56 | +import com.sap.sailing.server.testsupport.SecurityBundleTestWrapper; |
|
| 57 | +import com.sap.sse.common.Color; |
|
| 58 | +import com.sap.sse.common.Util; |
|
| 59 | +import com.sap.sse.common.impl.MillisecondsTimePoint; |
|
| 60 | +import com.sap.sse.mongodb.MongoDBService; |
|
| 61 | +import com.sap.sse.replication.FullyInitializedReplicableTracker; |
|
| 62 | +import com.sap.sse.replication.OperationExecutionListener; |
|
| 63 | +import com.sap.sse.replication.OperationWithResult; |
|
| 64 | +import com.sap.sse.security.SecurityService; |
|
| 65 | + |
|
| 66 | +/** |
|
| 67 | + * See also bug 5219 (https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=5219). |
|
| 68 | + * |
|
| 69 | + * @author Axel Uhl (D043530) |
|
| 70 | + * |
|
| 71 | + */ |
|
| 72 | +public class AutomaticRetrackUponCompetitorSetChangeTest { |
|
| 73 | + private TrackedRace trackedRace; |
|
| 74 | + private RegattaAndRaceIdentifier raceIdentifier; |
|
| 75 | + private RaceHandle racesHandle; |
|
| 76 | + private final boolean[] notifier = new boolean[1]; |
|
| 77 | + private RaceTrackingConnectivityParameters trackingParams; |
|
| 78 | + private RacingEventServiceImpl service; |
|
| 79 | + private MongoDBService mongoDBService; |
|
| 80 | + private MongoObjectFactory mongoObjectFactory; |
|
| 81 | + |
|
| 82 | + @Before |
|
| 83 | + public void setUp() throws Exception { |
|
| 84 | + final BundleContext contextMock = mock(BundleContext.class); |
|
| 85 | + when(contextMock.createFilter(Matchers.anyObject())).thenReturn(null); |
|
| 86 | + mongoDBService = MongoDBService.INSTANCE; |
|
| 87 | + mongoDBService.getDB().drop(); |
|
| 88 | + mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(mongoDBService); |
|
| 89 | + final SecurityService securityService = new SecurityBundleTestWrapper().initializeSecurityServiceForTesting(); |
|
| 90 | + service = new RacingEventServiceImpl((final RaceLogAndTrackedRaceResolver raceLogResolver)-> { |
|
| 91 | + return new ConstructorParameters() { |
|
| 92 | + private final DomainFactory baseDomainFactory = new DomainFactoryImpl(raceLogResolver); |
|
| 93 | + @Override public DomainObjectFactory getDomainObjectFactory() { return PersistenceFactory.INSTANCE.getDomainObjectFactory(mongoDBService, baseDomainFactory); } |
|
| 94 | + @Override public MongoObjectFactory getMongoObjectFactory() { return mongoObjectFactory; } |
|
| 95 | + @Override public DomainFactory getBaseDomainFactory() { return baseDomainFactory; } |
|
| 96 | + @Override public CompetitorAndBoatStore getCompetitorAndBoatStore() { return getBaseDomainFactory().getCompetitorAndBoatStore(); } |
|
| 97 | + }; |
|
| 98 | + }, MediaDBFactory.INSTANCE.getMediaDB(mongoDBService), EmptyWindStore.INSTANCE, |
|
| 99 | + EmptySensorFixStore.INSTANCE, null, null, /* sailingNotificationService */ null, |
|
| 100 | + /* trackedRaceStatisticsCache */ null, /* restoreTrackedRaces */ false, |
|
| 101 | + /* security service tracker */ new FullyInitializedReplicableTracker<SecurityService>(contextMock, (String) "class", null, null) { |
|
| 102 | + @Override |
|
| 103 | + public SecurityService getInitializedService(long timeoutInMillis) throws InterruptedException { |
|
| 104 | + return securityService; |
|
| 105 | + } |
|
| 106 | + }, /* sharedSailingData */ null, /* replicationServiceTracker */ null, |
|
| 107 | + /* scoreCorrectionProviderServiceTracker */ null, /* resultUrlRegistryServiceTracker */ null); |
|
| 108 | + URL paramURL = new URL("http://event.tractrac.com/events/event_20150818_Bundesliga/4c54e750-27c2-0133-5064-60a44ce903c3.txt"); |
|
| 109 | + URI liveURI = AbstractTracTracLiveTest.getLiveURI(); |
|
| 110 | + URI storedURI = new URI("http://event.tractrac.com/events/event_20150818_Bundesliga/datafiles/4c54e750-27c2-0133-5064-60a44ce903c3.mtb"); |
|
| 111 | + URI courseDesignUpdateURI = AbstractTracTracLiveTest.getCourseDesignUpdateURI(); |
|
| 112 | + String tracTracUsername = AbstractTracTracLiveTest.getTracTracUsername(); |
|
| 113 | + String tracTracPassword = AbstractTracTracLiveTest.getTracTracPassword(); |
|
| 114 | + GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("UTC")); |
|
| 115 | + cal.set(2015, 8, 22, 9, 23, 57); |
|
| 116 | + MillisecondsTimePoint startOfTracking = new MillisecondsTimePoint(cal.getTimeInMillis()); |
|
| 117 | + cal.set(2015, 8, 22, 15, 26, 34); |
|
| 118 | + MillisecondsTimePoint endOfTracking = new MillisecondsTimePoint(cal.getTimeInMillis()); |
|
| 119 | + service.addOperationExecutionListener(new OperationExecutionListener<RacingEventService>() { |
|
| 120 | + @Override |
|
| 121 | + public <T> void executed(OperationWithResult<RacingEventService, T> operation) { |
|
| 122 | + if (operation instanceof CreateTrackedRace) { |
|
| 123 | + synchronized (notifier) { |
|
| 124 | + notifier[0] = true; |
|
| 125 | + notifier.notifyAll(); |
|
| 126 | + } |
|
| 127 | + } |
|
| 128 | + } |
|
| 129 | + }); |
|
| 130 | + trackingParams = new com.sap.sailing.domain.tractracadapter.impl.DomainFactoryImpl(service.getBaseDomainFactory()) |
|
| 131 | + .createTrackingConnectivityParameters(paramURL, liveURI, storedURI, courseDesignUpdateURI, |
|
| 132 | + startOfTracking, endOfTracking, /* delayToLiveInMillis */ |
|
| 133 | + 0l, /* offsetToStartTimeOfSimulatedRace */null, /*ignoreTracTracMarkPassings*/ false, EmptyRaceLogStore.INSTANCE, |
|
| 134 | + EmptyRegattaLogStore.INSTANCE, tracTracUsername, tracTracPassword, "", "", /* trackWind */ false, /* correctWindDirectionByMagneticDeclination */ false, |
|
| 135 | + /* preferReplayIfAvailable */ false, /* timeoutInMillis */ (int) RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS, /* useOfficialEventsToUpdateRaceLog */ false); |
|
| 136 | + } |
|
| 137 | + |
|
| 138 | + private void startTracking() throws Exception { |
|
| 139 | + final Regatta regatta = service.createRegatta("Test regatta", "J/70", |
|
| 140 | + /* canBoatsOfCompetitorsChangePerRace==true because it's a league race we're using for this test */ true, |
|
| 141 | + CompetitorRegistrationType.CLOSED, /* registrationLinkSecret */ null, |
|
| 142 | + /* startDate */ null, /* endDate */ null, UUID.randomUUID(), |
|
| 143 | + /* start with no series */ Collections.emptySet(), |
|
| 144 | + /* persistent */ true, new LowPoint(), /* defaultCourseAreaId */ UUID.randomUUID(), |
|
| 145 | + /* buoyZoneRadiusInHullLengths */ 2., /* useStartTimeInference */ false, /* controlTrackingFromStartAndFinishTimes */ false, |
|
| 146 | + /* autoRestartTrackingUponCompetitorSetChange */ true, /* rankingMetricConstructor */ OneDesignRankingMetric::new); |
|
| 147 | + final RegattaName regattaIdentifier = new RegattaName(regatta.getName()); |
|
| 148 | + service.apply(new UpdateSeries(regattaIdentifier, "Default", "Default", /* isMedal */ false, /* isFleetsCanRunInParallel */ false, |
|
| 149 | + /* resultDiscardingThresholds */ null, /* startsWithZeroScore */ false, /* firstColumnIsNonDiscardableCarryForward */ false, |
|
| 150 | + /* hasSplitFleetContiguousScoring */ false, /* maximumNumberOfDiscards */ null, |
|
| 151 | + Arrays.asList(new FleetDTO("Red", 0, Color.RED), new FleetDTO("Green", 0, Color.GREEN), new FleetDTO("Blue", 0, Color.BLUE)))); |
|
| 152 | + racesHandle = service.addRace(/* regattaToAddTo */ regattaIdentifier, trackingParams, /* timeoutInMilliseconds */ 60000, |
|
| 153 | + new DefaultRaceTrackingHandler()); |
|
| 154 | + // wait for the race to show up |
|
| 155 | + RaceDefinition race = racesHandle.getRace(RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS); |
|
| 156 | + if (race == null) { |
|
| 157 | + fail("Waiting for tracked race timed out"); |
|
| 158 | + } |
|
| 159 | + raceIdentifier = racesHandle.getRaceTracker().getRaceIdentifier(); |
|
| 160 | + trackedRace = service.getTrackedRace(raceIdentifier); |
|
| 161 | + } |
|
| 162 | + |
|
| 163 | + @Test |
|
| 164 | + public void testStartTrackingAndRetrack() throws Exception { |
|
| 165 | + startTracking(); |
|
| 166 | + final RaceDefinition race = trackedRace.getRace(); |
|
| 167 | + Iterable<Competitor> masterCompetitors = race.getCompetitors(); |
|
| 168 | + assertEquals(Util.size(masterCompetitors), 6); |
|
| 169 | + final RaceHandle newHandle = service.updateRaceCompetitors(trackedRace.getTrackedRegatta().getRegatta(), race); |
|
| 170 | + final RaceDefinition newRace = newHandle.getRace(RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS); |
|
| 171 | + assertNotNull(newRace); |
|
| 172 | + assertEquals(race.getId(), newRace.getId()); |
|
| 173 | + assertNotSame(race, newRace); |
|
| 174 | + racesHandle = newHandle; // ensure that tearDown tears down the correct tracker |
|
| 175 | + } |
|
| 176 | + |
|
| 177 | + @After |
|
| 178 | + public void tearDown() throws Exception { |
|
| 179 | + if (racesHandle != null) { |
|
| 180 | + racesHandle.getRaceTracker().stop(/* preemptive */ false); |
|
| 181 | + } |
|
| 182 | + } |
|
| 183 | +} |
java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java
| ... | ... | @@ -2760,7 +2760,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes |
| 2760 | 2760 | final RaceTrackingConnectivityParameters connectivityParams = connectivityParametersByRace.get(race); |
| 2761 | 2761 | if (connectivityParams != null) { |
| 2762 | 2762 | removeRace(regatta, race); |
| 2763 | - result = addRace(regatta.getRegattaIdentifier(), connectivityParams, RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS); |
|
| 2763 | + result = addRace(regatta.getRegattaIdentifier(), connectivityParams, RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS, |
|
| 2764 | + new DefaultRaceTrackingHandler()); // no need for ownership setting here because we're only "re-tracking" an existing race |
|
| 2764 | 2765 | } else { |
| 2765 | 2766 | result = null; |
| 2766 | 2767 | logger.warning("Unable to update race competitors for race "+race+" in regatta "+regatta+ |
java/com.sap.sse.gwt/.project
| ... | ... | @@ -10,6 +10,16 @@ |
| 10 | 10 | <arguments> |
| 11 | 11 | </arguments> |
| 12 | 12 | </buildCommand> |
| 13 | + <buildCommand> |
|
| 14 | + <name>org.eclipse.pde.ManifestBuilder</name> |
|
| 15 | + <arguments> |
|
| 16 | + </arguments> |
|
| 17 | + </buildCommand> |
|
| 18 | + <buildCommand> |
|
| 19 | + <name>org.eclipse.pde.SchemaBuilder</name> |
|
| 20 | + <arguments> |
|
| 21 | + </arguments> |
|
| 22 | + </buildCommand> |
|
| 13 | 23 | <buildCommand> |
| 14 | 24 | <name>com.gwtplugins.gdt.eclipse.core.webAppProjectValidator</name> |
| 15 | 25 | <arguments> |
java/com.sap.sse.gwt/GWT xdStorage Sample SDM.launch
| ... | ... | @@ -51,6 +51,7 @@ |
| 51 | 51 | <stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.gwtplugins.gwt.eclipse.core.moduleClasspathProvider"/> |
| 52 | 52 | <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/> |
| 53 | 53 | <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/> |
| 54 | +<stringAttribute key="org.eclipse.jdt.launching.MODULE_NAME" value="com.sap.sse.gwt"/> |
|
| 54 | 55 | <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-style PRETTY -incremental -workDir "${project_loc:com.sap.sse.gwt}/.tmp/gwt-work" -war "${project_loc:com.sap.sse.gwt}" -noserver -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -logLevel INFO -codeServerPort 9877 -startupUrl /gwt-base/StorageMessagingTest.html -startupUrl /gwt-base/StorageMessaging.html com.sap.sse.gwt.StorageMessaging com.sap.sse.gwt.StorageMessagingTest"/> |
| 55 | 56 | <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sse.gwt"/> |
| 56 | 57 | <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XX:+UseG1GC -XX:+UseStringDeduplication -Dgwt.watchFileChanges=false -Xmx2048m -Dgwt-usearchives=false -Dgwt.persistentunitcache=false"/> |
java/com.sap.sse.gwt/META-INF/MANIFEST.MF
| ... | ... | @@ -59,11 +59,9 @@ Export-Package: com.google.gwt.user.client.rpc.core.java.util, |
| 59 | 59 | com.sap.sse.gwt.client.useragent, |
| 60 | 60 | com.sap.sse.gwt.client.xdstorage, |
| 61 | 61 | com.sap.sse.gwt.common, |
| 62 | - com.sap.sse.gwt.dispatch.client, |
|
| 63 | 62 | com.sap.sse.gwt.dispatch.client.system, |
| 64 | 63 | com.sap.sse.gwt.dispatch.client.system.batching, |
| 65 | 64 | com.sap.sse.gwt.dispatch.client.system.caching, |
| 66 | - com.sap.sse.gwt.dispatch.client.system.routing, |
|
| 67 | 65 | com.sap.sse.gwt.dispatch.client.transport.gwtrpc, |
| 68 | 66 | com.sap.sse.gwt.dispatch.servlets, |
| 69 | 67 | com.sap.sse.gwt.dispatch.shared.caching, |
| ... | ... | @@ -73,7 +71,6 @@ Export-Package: com.google.gwt.user.client.rpc.core.java.util, |
| 73 | 71 | com.sap.sse.gwt.resources, |
| 74 | 72 | com.sap.sse.gwt.server, |
| 75 | 73 | com.sap.sse.gwt.server.filestorage, |
| 76 | - com.sap.sse.gwt.server.replication, |
|
| 77 | 74 | com.sap.sse.gwt.settings, |
| 78 | 75 | com.sap.sse.gwt.shared, |
| 79 | 76 | com.sap.sse.gwt.shared.filestorage, |
wiki/howto/onboarding.md
| ... | ... | @@ -114,6 +114,7 @@ The primary Git repository for the project is hosted on sapsailing.com. It is mi |
| 114 | 114 | 4. On clear workspace additional steps should be performed once: |
| 115 | 115 | 1. Run "GWT Dashboards SDM" launch configuration. After successful start, launch configuration can be stopped. |
| 116 | 116 | 2. Run "GWT Security SDM" launch configuration. After successful start, launch configuration can be stopped. |
| 117 | + 3. Run "GWT xdStorage Sample SDM" launch configuration. After successful start, launch configuration can be stopped. |
|
| 117 | 118 | 5. Run the Race Analysis Suite |
| 118 | 119 | * Start the MongoDB (cd /somePathTo MongoDB/mongodb/bin; rm c:/data/SAP/sailing/mongodb/mongod.lock; ./mongod --dbpath c:/data/SAP/sailing/mongodb) |
| 119 | 120 | * Start the appropriate Eclipse launch configuration (e.g. 'Sailing Server (no Proxy)') You´ll find this in the debug dropdown |