mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-22 20:13:52 +00:00
Merge branch 'master' into bug2775
Conflicts: java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties java/com.sap.sailing.server/src/com/sap/sailing/server/impl/Activator.java
This commit is contained in:
commit
793c2c0341
215 files changed
+11209
-6198
No files matched your search
+1
-1
@@ -19,7 +19,7 @@
|
||||
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog -console -clean"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Djetty.port=8889 -Dreplication.exchangeName=sapsailinganalytics-replica -Declipse.ignoreApp=true -Dosgi.noShutdown=true -Dexpedition.udp.port=2011 -Xmx6000m -XX:+UseG1GC -Djetty.home=${project_loc:com.sap.sailing.server}/../target/configuration/jetty -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties -XX:+UseMembar -Dmongo.dbName=replica -Dreplicate.on.start=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl -Dreplicate.master.queue.host=52.16.112.6 -Dreplicate.master.queue.port=5672 -Dreplicate.master.servlet.port=8888 -Dreplicate.master.servlet.host=54.154.72.33 -Dreplicate.master.exchange.name=sapsailinganalytics-dev"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Djetty.port=8889 -Dreplication.exchangeName=sapsailinganalytics-replica -Declipse.ignoreApp=true -Dosgi.noShutdown=true -Dexpedition.udp.port=2011 -Xmx6000m -XX:+UseG1GC -Djetty.home=${project_loc:com.sap.sailing.server}/../target/configuration/jetty -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties -XX:+UseMembar -Dmongo.dbName=replica -Dreplicate.on.start=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.RegattaLogSensorDataTrackerTrackedRegattaListener -Dreplicate.master.queue.host=52.16.112.6 -Dreplicate.master.queue.port=5672 -Dreplicate.master.servlet.port=8888 -Dreplicate.master.servlet.host=54.154.72.33 -Dreplicate.master.exchange.name=sapsailinganalytics-dev"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc}"/>
|
||||
<stringAttribute key="pde.version" value="3.3"/>
|
||||
<booleanAttribute key="show_selected_only" value="false"/>
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog -console -clean"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Djetty.port=8889 -Dreplication.exchangeName=sapsailinganalytics-replica -Declipse.ignoreApp=true -Dosgi.noShutdown=true -Dexpedition.udp.port=2011 -Xmx6000m -XX:+UseG1GC -Djetty.home=${project_loc:com.sap.sailing.server}/../target/configuration/jetty -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties -XX:+UseMembar -Dmongo.dbName=replica -Dreplicate.on.start=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl -Dreplicate.master.queue.host=127.0.0.1 -Dreplicate.master.queue.port=5672 -Dreplicate.master.servlet.port=8888 -Dreplicate.master.servlet.host=127.0.0.1 -Dreplicate.master.exchange.name=sapsailinganalytics"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Djetty.port=8889 -Dreplication.exchangeName=sapsailinganalytics-replica -Declipse.ignoreApp=true -Dosgi.noShutdown=true -Dexpedition.udp.port=2011 -Xmx6000m -XX:+UseG1GC -Djetty.home=${project_loc:com.sap.sailing.server}/../target/configuration/jetty -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties -XX:+UseMembar -Dmongo.dbName=replica -Dreplicate.on.start=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.RegattaLogSensorDataTrackerTrackedRegattaListener -Dreplicate.master.queue.host=127.0.0.1 -Dreplicate.master.queue.port=5672 -Dreplicate.master.servlet.port=8888 -Dreplicate.master.servlet.host=127.0.0.1 -Dreplicate.master.exchange.name=sapsailinganalytics"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc}"/>
|
||||
<stringAttribute key="pde.version" value="3.3"/>
|
||||
<booleanAttribute key="show_selected_only" value="false"/>
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
@@ -61,7 +62,7 @@ import com.sap.sailing.domain.leaderboard.ScoringScheme;
|
||||
import com.sap.sailing.domain.persistence.DomainObjectFactory;
|
||||
import com.sap.sailing.domain.persistence.MongoObjectFactory;
|
||||
import com.sap.sailing.domain.polars.PolarDataService;
|
||||
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
|
||||
import com.sap.sailing.domain.racelog.tracking.SensorFixStore;
|
||||
import com.sap.sailing.domain.ranking.RankingMetricConstructor;
|
||||
import com.sap.sailing.domain.regattalike.LeaderboardThatHasRegattaLike;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
@@ -303,7 +304,7 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
|
||||
*/
|
||||
void updateStoredLeaderboardGroup(LeaderboardGroup leaderboardGroup);
|
||||
|
||||
DynamicTrackedRace createTrackedRace(RegattaAndRaceIdentifier raceIdentifier, WindStore windStore, GPSFixStore gpsFixStore,
|
||||
DynamicTrackedRace createTrackedRace(RegattaAndRaceIdentifier raceIdentifier, WindStore windStore,
|
||||
long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, boolean useMarkPassingCalculator);
|
||||
|
||||
Regatta getOrCreateDefaultRegatta(String name, String boatClassName, Serializable id);
|
||||
@@ -531,8 +532,8 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
|
||||
PolarDataService getPolarDataService();
|
||||
|
||||
SimulationService getSimulationService();
|
||||
|
||||
GPSFixStore getGPSFixStore();
|
||||
|
||||
SensorFixStore getSensorFixStore();
|
||||
|
||||
RaceTracker getRaceTrackerById(Object id);
|
||||
|
||||
@@ -617,4 +618,11 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
|
||||
ClassLoader getCombinedMasterDataClassLoader();
|
||||
|
||||
Iterable<Competitor> getCompetitorInOrderOfWindwardDistanceTraveledFarthestFirst(TrackedRace trackedRace, TimePoint timePoint);
|
||||
|
||||
/**
|
||||
* Gets the {@link RaceTracker} associated with a given {@link RegattaAndRaceIdentifier}. If the {@link RaceTracker}
|
||||
* isn't available yet, the given callback will be informed asynchronously on registration of the RaceTracker in
|
||||
* question.
|
||||
*/
|
||||
void getRaceTrackerByRegattaAndRaceIdentifier(RegattaAndRaceIdentifier raceIdentifier, Consumer<RaceTracker> callback);
|
||||
}
|
||||
@@ -21,9 +21,11 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer;
|
||||
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
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.racelog.tracking.GPSFixMongoHandler;
|
||||
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.sailing.domain.polars.PolarDataService;
|
||||
@@ -60,6 +62,8 @@ public class Activator implements BundleActivator {
|
||||
private ServiceTracker<MasterDataImportClassLoaderService, MasterDataImportClassLoaderService> masterDataImportClassLoaderServiceTracker;
|
||||
|
||||
private ServiceTracker<PolarDataService, PolarDataService> polarDataServiceTracker;
|
||||
|
||||
private OSGiBasedTrackedRegattaListener trackedRegattaListener;
|
||||
|
||||
public Activator() {
|
||||
clearPersistentCompetitors = Boolean.valueOf(System.getProperty(CLEAR_PERSISTENT_COMPETITORS_PROPERTY_NAME, ""+false));
|
||||
@@ -71,12 +75,14 @@ public class Activator implements BundleActivator {
|
||||
extenderBundleTracker = new ExtenderBundleTracker(context);
|
||||
extenderBundleTracker.open();
|
||||
|
||||
trackedRegattaListener = new OSGiBasedTrackedRegattaListener(context);
|
||||
|
||||
// At this point the OSGi resolver is used as device type service finder.
|
||||
// In the case that we are not in an OSGi context (e.g. running a JUnit test instead),
|
||||
// this code block is not run, and the test case can inject some other type of finder
|
||||
// instead.
|
||||
serviceFinderFactory = new CachedOsgiTypeBasedServiceFinderFactory(context);
|
||||
racingEventService = new RacingEventServiceImpl(clearPersistentCompetitors, serviceFinderFactory);
|
||||
racingEventService = new RacingEventServiceImpl(clearPersistentCompetitors, serviceFinderFactory, trackedRegattaListener);
|
||||
|
||||
masterDataImportClassLoaderServiceTracker = new ServiceTracker<MasterDataImportClassLoaderService, MasterDataImportClassLoaderService>(
|
||||
context, MasterDataImportClassLoaderService.class,
|
||||
@@ -98,19 +104,23 @@ public class Activator implements BundleActivator {
|
||||
final GPSFixMongoHandlerImpl gpsFixMongoHandler = new GPSFixMongoHandlerImpl(racingEventService.getMongoObjectFactory(),
|
||||
racingEventService.getDomainObjectFactory());
|
||||
properties.put(TypeBasedServiceFinder.TYPE, GPSFixImpl.class.getName());
|
||||
registrations.add(context.registerService(GPSFixMongoHandler.class,
|
||||
registrations.add(context.registerService(FixMongoHandler.class,
|
||||
gpsFixMongoHandler, properties));
|
||||
// legacy type name; some DBs may still contain fixes marked with this old package name:
|
||||
properties.put(TypeBasedServiceFinder.TYPE, "com.sap.sailing.domain.tracking.impl.GPSFixImpl");
|
||||
registrations.add(context.registerService(GPSFixMongoHandler.class,
|
||||
registrations.add(context.registerService(FixMongoHandler.class,
|
||||
gpsFixMongoHandler, properties));
|
||||
final GPSFixMovingMongoHandlerImpl gpsFixMovingMongoHandler = new GPSFixMovingMongoHandlerImpl(racingEventService.getMongoObjectFactory(),
|
||||
racingEventService.getDomainObjectFactory());
|
||||
properties.put(TypeBasedServiceFinder.TYPE, GPSFixMovingImpl.class.getName());
|
||||
registrations.add(context.registerService(GPSFixMongoHandler.class, gpsFixMovingMongoHandler, properties));
|
||||
registrations.add(context.registerService(FixMongoHandler.class, gpsFixMovingMongoHandler, properties));
|
||||
// legacy type name; some DBs may still contain fixes marked with this old package name:
|
||||
properties.put(TypeBasedServiceFinder.TYPE, "com.sap.sailing.domain.tracking.impl.GPSFixMovingImpl");
|
||||
registrations.add(context.registerService(GPSFixMongoHandler.class, gpsFixMovingMongoHandler, properties));
|
||||
registrations.add(context.registerService(FixMongoHandler.class, gpsFixMovingMongoHandler, properties));
|
||||
properties.put(TypeBasedServiceFinder.TYPE, DoubleVectorFixImpl.class.getName());
|
||||
registrations.add(context.registerService(FixMongoHandler.class, new DoubleVectorFixMongoHandlerImpl(racingEventService.getMongoObjectFactory(),
|
||||
racingEventService.getDomainObjectFactory()), properties));
|
||||
|
||||
|
||||
registerPreferenceConvertersWhenUserStoreIsAvailable(context);
|
||||
|
||||
@@ -165,6 +175,7 @@ public class Activator implements BundleActivator {
|
||||
for (ServiceRegistration<?> reg : registrations) {
|
||||
reg.unregister();
|
||||
}
|
||||
trackedRegattaListener.close();
|
||||
registrations.clear();
|
||||
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||
mbs.unregisterMBean(mBeanName);
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.sap.sailing.server.impl;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
import com.sap.sailing.domain.tracking.TrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegattaListener;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
|
||||
public class OSGiBasedTrackedRegattaListener implements TrackedRegattaListener {
|
||||
|
||||
private ServiceTracker<TrackedRegattaListener, TrackedRegattaListener> serviceTracker;
|
||||
|
||||
public OSGiBasedTrackedRegattaListener(BundleContext context) {
|
||||
serviceTracker = ServiceTrackerFactory.createAndOpen(context, TrackedRegattaListener.class);
|
||||
serviceTracker.open(true);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
serviceTracker.close();
|
||||
}
|
||||
|
||||
private void forEachListener(Consumer<TrackedRegattaListener> consumer) {
|
||||
for(ServiceReference<TrackedRegattaListener> serviceReference : serviceTracker.getServiceReferences()) {
|
||||
TrackedRegattaListener listener = serviceTracker.getService(serviceReference);
|
||||
if(listener != null) {
|
||||
consumer.accept(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void regattaAdded(TrackedRegatta trackedRegatta) {
|
||||
forEachListener((listener) -> listener.regattaAdded(trackedRegatta));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void regattaRemoved(TrackedRegatta trackedRegatta) {
|
||||
forEachListener((listener) -> listener.regattaRemoved(trackedRegatta));
|
||||
}
|
||||
}
|
||||
+142
-47
@@ -35,6 +35,7 @@ import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
@@ -58,6 +59,7 @@ import com.sap.sailing.domain.abstractlog.race.state.RaceState;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.impl.ReadonlyRaceStateImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.CompetitorStore;
|
||||
import com.sap.sailing.domain.base.CompetitorStore.CompetitorUpdateListener;
|
||||
@@ -110,6 +112,7 @@ import com.sap.sailing.domain.common.media.MediaTrack;
|
||||
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.common.tracking.SensorFix;
|
||||
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.FlexibleRaceColumn;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
@@ -131,11 +134,11 @@ import com.sap.sailing.domain.persistence.MongoWindStoreFactory;
|
||||
import com.sap.sailing.domain.persistence.PersistenceFactory;
|
||||
import com.sap.sailing.domain.persistence.media.MediaDB;
|
||||
import com.sap.sailing.domain.persistence.media.MediaDBFactory;
|
||||
import com.sap.sailing.domain.persistence.racelog.tracking.MongoGPSFixStoreFactory;
|
||||
import com.sap.sailing.domain.persistence.racelog.tracking.MongoSensorFixStoreFactory;
|
||||
import com.sap.sailing.domain.polars.PolarDataService;
|
||||
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
|
||||
import com.sap.sailing.domain.racelog.RaceLogStore;
|
||||
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
|
||||
import com.sap.sailing.domain.racelog.tracking.SensorFixStore;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.ranking.RankingMetric.CompetitorRankingInfo;
|
||||
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
|
||||
@@ -144,8 +147,10 @@ import com.sap.sailing.domain.regattalike.HasRegattaLike;
|
||||
import com.sap.sailing.domain.regattalike.IsRegattaLike;
|
||||
import com.sap.sailing.domain.regattalike.LeaderboardThatHasRegattaLike;
|
||||
import com.sap.sailing.domain.regattalog.RegattaLogStore;
|
||||
import com.sap.sailing.domain.tracking.DynamicSensorFixTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.EmptyTrackedRegattaListener;
|
||||
import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.RaceChangeListener;
|
||||
@@ -156,6 +161,7 @@ import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParameters;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.TrackedRaceStatus;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegattaListener;
|
||||
import com.sap.sailing.domain.tracking.WindStore;
|
||||
import com.sap.sailing.domain.tracking.WindTracker;
|
||||
import com.sap.sailing.domain.tracking.WindTrackerFactory;
|
||||
@@ -183,6 +189,8 @@ import com.sap.sailing.server.operationaltransformation.CreateOrUpdateDeviceConf
|
||||
import com.sap.sailing.server.operationaltransformation.CreateTrackedRace;
|
||||
import com.sap.sailing.server.operationaltransformation.DataImportFailed;
|
||||
import com.sap.sailing.server.operationaltransformation.RecordCompetitorGPSFix;
|
||||
import com.sap.sailing.server.operationaltransformation.RecordCompetitorSensorFix;
|
||||
import com.sap.sailing.server.operationaltransformation.RecordCompetitorSensorFixTrack;
|
||||
import com.sap.sailing.server.operationaltransformation.RecordMarkGPSFix;
|
||||
import com.sap.sailing.server.operationaltransformation.RecordMarkGPSFixForExistingTrack;
|
||||
import com.sap.sailing.server.operationaltransformation.RecordMarkGPSFixForNewMarkTrack;
|
||||
@@ -295,6 +303,15 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
*/
|
||||
private final ConcurrentHashMap<Object, NamedReentrantReadWriteLock> raceTrackersByIDLocks;
|
||||
|
||||
/**
|
||||
* Using {@link #getRaceTrackerByRegattaAndRaceIdentifier(RegattaAndRaceIdentifier, Consumer)}, one can request a
|
||||
* {@link RaceTracker} for a specific race. It can be that the requested {@link RaceTracker} isn't registered in
|
||||
* {@link #raceTrackersByRegatta}. To not need a Thread to wait for the RaceTracker to get available, a callback
|
||||
* will be registered that fires on registration of the RaceTracker. If the {@link RaceTracker} will not be
|
||||
* registered, the callback only leads to a minor leak.
|
||||
*/
|
||||
private volatile transient ConcurrentHashMap<RegattaAndRaceIdentifier, Set<Consumer<RaceTracker>>> raceTrackerCallbacks;
|
||||
|
||||
/**
|
||||
* Leaderboards managed by this racing event service
|
||||
*/
|
||||
@@ -361,7 +378,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
protected final DeviceConfigurationMapImpl configurationMap;
|
||||
|
||||
private final WindStore windStore;
|
||||
private final GPSFixStore gpsFixStore;
|
||||
private final SensorFixStore sensorFixStore;
|
||||
|
||||
/**
|
||||
* This author should be used for server generated race log events
|
||||
@@ -404,6 +421,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
|
||||
private SailingServerConfiguration sailingServerConfiguration;
|
||||
|
||||
private final TrackedRegattaListener trackedRegattaListener;
|
||||
|
||||
/**
|
||||
* Providing the constructor parameters for a new {@link RacingEventServiceImpl} instance is a bit tricky
|
||||
* in some cases because containment and initialization order of some types is fairly tightly coupled.
|
||||
@@ -432,15 +451,19 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
this(true, null);
|
||||
}
|
||||
|
||||
public RacingEventServiceImpl(WindStore windStore, GPSFixStore gpsFixStore,
|
||||
public RacingEventServiceImpl(WindStore windStore, SensorFixStore sensorFixStore,
|
||||
TypeBasedServiceFinderFactory serviceFinderFactory) {
|
||||
this(true, windStore, gpsFixStore, serviceFinderFactory);
|
||||
this(true, windStore, sensorFixStore, serviceFinderFactory);
|
||||
}
|
||||
|
||||
void setBundleContext(BundleContext bundleContext) {
|
||||
this.bundleContext = bundleContext;
|
||||
}
|
||||
|
||||
public RacingEventServiceImpl(boolean clearPersistentCompetitorStore, final TypeBasedServiceFinderFactory serviceFinderFactory) {
|
||||
this(clearPersistentCompetitorStore, serviceFinderFactory, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #RacingEventServiceImpl()}, but allows callers to specify that the persistent competitor collection
|
||||
* be cleared before the service starts.
|
||||
@@ -450,7 +473,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
* database collection cleared as well. Use with caution! When used with <code>false</code>, competitors
|
||||
* created and stored during previous service executions will initially be loaded.
|
||||
*/
|
||||
public RacingEventServiceImpl(boolean clearPersistentCompetitorStore, final TypeBasedServiceFinderFactory serviceFinderFactory) {
|
||||
public RacingEventServiceImpl(boolean clearPersistentCompetitorStore, final TypeBasedServiceFinderFactory serviceFinderFactory, TrackedRegattaListener trackedRegattaListener) {
|
||||
this((final RaceLogResolver raceLogResolver)-> {
|
||||
return new ConstructorParameters() {
|
||||
private final MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(serviceFinderFactory);
|
||||
@@ -463,11 +486,11 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
@Override public DomainFactory getBaseDomainFactory() { return competitorStore.getBaseDomainFactory(); }
|
||||
@Override public CompetitorStore getCompetitorStore() { return competitorStore; }
|
||||
};
|
||||
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), null, null, serviceFinderFactory);
|
||||
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), null, null, serviceFinderFactory ,trackedRegattaListener);
|
||||
}
|
||||
|
||||
private RacingEventServiceImpl(final boolean clearPersistentCompetitorStore, WindStore windStore,
|
||||
GPSFixStore gpsFixStore, final TypeBasedServiceFinderFactory serviceFinderFactory) {
|
||||
SensorFixStore sensorFixStore, final TypeBasedServiceFinderFactory serviceFinderFactory) {
|
||||
this((final RaceLogResolver raceLogResolver)-> {
|
||||
return new ConstructorParameters() {
|
||||
private final MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(serviceFinderFactory);
|
||||
@@ -480,7 +503,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
@Override public DomainFactory getBaseDomainFactory() { return competitorStore.getBaseDomainFactory(); }
|
||||
@Override public CompetitorStore getCompetitorStore() { return competitorStore; }
|
||||
};
|
||||
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), windStore, gpsFixStore, serviceFinderFactory);
|
||||
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), windStore, sensorFixStore, serviceFinderFactory, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -490,7 +513,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
* persistence.
|
||||
*/
|
||||
public RacingEventServiceImpl(Function<RaceLogResolver, DomainObjectFactory> domainObjectFactoryProvider,
|
||||
final MongoObjectFactory mongoObjectFactory, MediaDB mediaDB, WindStore windStore, GPSFixStore gpsFixStore) {
|
||||
final MongoObjectFactory mongoObjectFactory, MediaDB mediaDB, WindStore windStore, SensorFixStore sensorFixStore) {
|
||||
this((final RaceLogResolver raceLogResolver)-> {
|
||||
return new ConstructorParameters() {
|
||||
private final DomainObjectFactory domainObjectFactory = domainObjectFactoryProvider.apply(raceLogResolver);
|
||||
@@ -500,11 +523,11 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
@Override public DomainFactory getBaseDomainFactory() { return domainObjectFactory.getBaseDomainFactory(); }
|
||||
@Override public CompetitorStore getCompetitorStore() { return getBaseDomainFactory().getCompetitorStore(); }
|
||||
};
|
||||
}, mediaDB, windStore, gpsFixStore, null);
|
||||
}, mediaDB, windStore, sensorFixStore, null, null);
|
||||
}
|
||||
|
||||
public RacingEventServiceImpl(final DomainObjectFactory domainObjectFactory, MongoObjectFactory mongoObjectFactory,
|
||||
MediaDB mediaDB, WindStore windStore, GPSFixStore gpsFixStore) {
|
||||
MediaDB mediaDB, WindStore windStore, SensorFixStore sensorFixStore) {
|
||||
this((final RaceLogResolver raceLogResolver)-> {
|
||||
return new ConstructorParameters() {
|
||||
@Override public DomainObjectFactory getDomainObjectFactory() { return domainObjectFactory; }
|
||||
@@ -512,7 +535,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
@Override public DomainFactory getBaseDomainFactory() { return domainObjectFactory.getBaseDomainFactory(); }
|
||||
@Override public CompetitorStore getCompetitorStore() { return getBaseDomainFactory().getCompetitorStore(); }
|
||||
};
|
||||
}, mediaDB, windStore, gpsFixStore, null);
|
||||
}, mediaDB, windStore, sensorFixStore, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -525,7 +548,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
* associations per race tracked.
|
||||
*/
|
||||
public RacingEventServiceImpl(Function<RaceLogResolver, ConstructorParameters> constructorParametersProvider, MediaDB mediaDb,
|
||||
WindStore windStore, GPSFixStore gpsFixStore, TypeBasedServiceFinderFactory serviceFinderFactory) {
|
||||
final WindStore windStore, final SensorFixStore sensorFixStore, TypeBasedServiceFinderFactory serviceFinderFactory, TrackedRegattaListener trackedRegattaListener) {
|
||||
logger.info("Created " + this);
|
||||
final ConstructorParameters constructorParameters = constructorParametersProvider.apply(this);
|
||||
this.domainObjectFactory = constructorParameters.getDomainObjectFactory();
|
||||
@@ -536,12 +559,11 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
this.mongoObjectFactory = constructorParameters.getMongoObjectFactory();
|
||||
this.mediaDB = mediaDb;
|
||||
this.competitorStore = constructorParameters.getCompetitorStore();
|
||||
if (windStore == null) {
|
||||
try {
|
||||
windStore = MongoWindStoreFactory.INSTANCE.getMongoWindStore(mongoObjectFactory, domainObjectFactory);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
try {
|
||||
this.windStore = windStore == null ? MongoWindStoreFactory.INSTANCE.getMongoWindStore(mongoObjectFactory,
|
||||
domainObjectFactory) : windStore;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
this.competitorStore.addCompetitorUpdateListener(new CompetitorUpdateListener() {
|
||||
@Override
|
||||
@@ -553,7 +575,6 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
competitor.getSearchTag()));
|
||||
}
|
||||
});
|
||||
this.windStore = windStore;
|
||||
this.dataImportLock = new DataImportLockWithProgress();
|
||||
|
||||
remoteSailingServerSet = new RemoteSailingServerSet(scheduler);
|
||||
@@ -567,6 +588,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
false);
|
||||
raceTrackersByID = new ConcurrentHashMap<>();
|
||||
raceTrackersByIDLocks = new ConcurrentHashMap<>();
|
||||
raceTrackerCallbacks = new ConcurrentHashMap<>();
|
||||
leaderboardGroupsByName = new ConcurrentHashMap<>();
|
||||
leaderboardGroupsByID = new ConcurrentHashMap<>();
|
||||
leaderboardGroupsByNameLock = new NamedReentrantReadWriteLock("leaderboardGroupsByName for " + this, /* fair */
|
||||
@@ -588,19 +610,19 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
this.regattaLogReplicator = new RegattaLogReplicator(this);
|
||||
this.raceLogScoringReplicator = new RaceLogScoringReplicator(this);
|
||||
this.mediaLibrary = new MediaLibrary();
|
||||
if (gpsFixStore == null) {
|
||||
try {
|
||||
gpsFixStore = MongoGPSFixStoreFactory.INSTANCE.getMongoGPSFixStore(mongoObjectFactory,
|
||||
domainObjectFactory, serviceFinderFactory);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
try {
|
||||
this.sensorFixStore = sensorFixStore == null ? MongoSensorFixStoreFactory.INSTANCE.getMongoGPSFixStore(
|
||||
mongoObjectFactory, domainObjectFactory, serviceFinderFactory) : sensorFixStore;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
this.gpsFixStore = gpsFixStore;
|
||||
|
||||
this.configurationMap = new DeviceConfigurationMapImpl();
|
||||
this.serviceFinderFactory = serviceFinderFactory;
|
||||
|
||||
this.trackedRegattaListener = trackedRegattaListener == null ? EmptyTrackedRegattaListener.INSTANCE : trackedRegattaListener;
|
||||
|
||||
sailingServerConfiguration = domainObjectFactory.loadServerConfiguration();
|
||||
final Iterable<Pair<Event, Boolean>> loadedEventsWithRequireStoreFlag = loadStoredEvents();
|
||||
loadStoredRegattas();
|
||||
@@ -1353,10 +1375,10 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
Regatta regatta = regattaToAddTo == null ? null : getRegatta(regattaToAddTo);
|
||||
if (regatta == null) {
|
||||
// create tracker and use an existing or create a default regatta
|
||||
tracker = params.createRaceTracker(this, windStore, gpsFixStore, /* raceLogResolver */ this);
|
||||
tracker = params.createRaceTracker(this, windStore, /* raceLogResolver */ this);
|
||||
} else {
|
||||
// use the regatta selected by the RaceIdentifier regattaToAddTo
|
||||
tracker = params.createRaceTracker(regatta, this, windStore, gpsFixStore, /* raceLogResolver */ this);
|
||||
tracker = params.createRaceTracker(regatta, this, windStore, /* raceLogResolver */ this);
|
||||
assert tracker.getRegatta() == regatta;
|
||||
}
|
||||
LockUtil.lockForWrite(raceTrackersByRegattaLock);
|
||||
@@ -1368,6 +1390,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
raceTrackersByRegatta.put(tracker.getRegatta(), trackers);
|
||||
}
|
||||
trackers.add(tracker);
|
||||
notifyListenersForNewRaceTracker(tracker);
|
||||
} finally {
|
||||
LockUtil.unlockAfterWrite(raceTrackersByRegattaLock);
|
||||
}
|
||||
@@ -1403,11 +1426,6 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
logger.warning("Wind store mismatch. Requested wind store: " + windStore
|
||||
+ ". Wind store in use by existing tracker: " + existingTrackersWindStore);
|
||||
}
|
||||
GPSFixStore existingTrackersGPSFixStore = tracker.getGPSFixStore();
|
||||
if (!existingTrackersGPSFixStore.equals(gpsFixStore)) {
|
||||
logger.warning("GPSFix store mismatch. Requested GPSFix store: " + gpsFixStore
|
||||
+ ". GPSFix store in use by existing tracker: " + existingTrackersGPSFixStore);
|
||||
}
|
||||
}
|
||||
if (timeoutInMilliseconds != -1) {
|
||||
scheduleAbortTrackerAfterInitialTimeout(tracker, timeoutInMilliseconds);
|
||||
@@ -1494,11 +1512,11 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
|
||||
@Override
|
||||
public DynamicTrackedRace createTrackedRace(RegattaAndRaceIdentifier raceIdentifier, WindStore windStore,
|
||||
GPSFixStore gpsFixStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind,
|
||||
long delayToLiveInMillis, long millisecondsOverWhichToAverageWind,
|
||||
long millisecondsOverWhichToAverageSpeed, boolean useMarkPassingCalculator) {
|
||||
DynamicTrackedRegatta trackedRegatta = getOrCreateTrackedRegatta(getRegatta(raceIdentifier));
|
||||
RaceDefinition race = getRace(raceIdentifier);
|
||||
return trackedRegatta.createTrackedRace(race, Collections.<Sideline> emptyList(), windStore, gpsFixStore,
|
||||
return trackedRegatta.createTrackedRace(race, Collections.<Sideline> emptyList(), windStore,
|
||||
delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed,
|
||||
/* raceDefinitionSetToUpdate */null, useMarkPassingCalculator, /* raceLogResolver */ this);
|
||||
}
|
||||
@@ -1556,8 +1574,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
public void raceAdded(TrackedRace trackedRace) {
|
||||
// replicate the addition of the tracked race:
|
||||
CreateTrackedRace op = new CreateTrackedRace(trackedRace.getRaceIdentifier(), trackedRace.getWindStore(),
|
||||
trackedRace.getGPSFixStore(), trackedRace.getDelayToLiveInMillis(),
|
||||
trackedRace.getMillisecondsOverWhichToAverageWind(),
|
||||
trackedRace.getDelayToLiveInMillis(), trackedRace.getMillisecondsOverWhichToAverageWind(),
|
||||
trackedRace.getMillisecondsOverWhichToAverageSpeed());
|
||||
replicate(op);
|
||||
linkRaceToConfiguredLeaderboardColumns(trackedRace);
|
||||
@@ -1615,13 +1632,13 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startOfTrackingChanged(TimePoint startOfTracking) {
|
||||
replicate(new UpdateStartOfTracking(getRaceIdentifier(), startOfTracking));
|
||||
public void startOfTrackingChanged(TimePoint oldStartOfTracking, TimePoint newStartOfTracking) {
|
||||
replicate(new UpdateStartOfTracking(getRaceIdentifier(), newStartOfTracking));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endOfTrackingChanged(TimePoint endOfTracking) {
|
||||
replicate(new UpdateEndOfTracking(getRaceIdentifier(), endOfTracking));
|
||||
public void endOfTrackingChanged(TimePoint oldEndOfTracking, TimePoint newEndOfTracking) {
|
||||
replicate(new UpdateEndOfTracking(getRaceIdentifier(), newEndOfTracking));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1702,11 +1719,35 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
public void speedAveragingChanged(long oldMillisecondsOverWhichToAverage, long newMillisecondsOverWhichToAverage) {
|
||||
replicate(new UpdateWindAveragingTime(getRaceIdentifier(), newMillisecondsOverWhichToAverage));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void competitorSensorTrackAdded(DynamicSensorFixTrack<Competitor, ?> track) {
|
||||
replicate(new RecordCompetitorSensorFixTrack(getRaceIdentifier(), track));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void competitorSensorFixAdded(Competitor competitor, String trackName, SensorFix fix) {
|
||||
replicate(new RecordCompetitorSensorFix(getRaceIdentifier(), competitor, trackName, fix));
|
||||
}
|
||||
|
||||
private RegattaAndRaceIdentifier getRaceIdentifier() {
|
||||
return trackedRace.getRaceIdentifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void regattaLogAttached(RegattaLog regattaLog) {
|
||||
// no action required
|
||||
}
|
||||
|
||||
@Override
|
||||
public void raceLogAttached(RaceLog regattaLog) {
|
||||
// no action required
|
||||
}
|
||||
|
||||
@Override
|
||||
public void raceLogDetached(RaceLog raceLog) {
|
||||
// no action required
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2116,6 +2157,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
replicate(new TrackRegatta(regatta.getRegattaIdentifier()));
|
||||
regattaTrackingCache.put(regatta, result);
|
||||
ensureRegattaIsObservedForDefaultLeaderboardAndAutoLeaderboardLinking(result);
|
||||
|
||||
trackedRegattaListener.regattaAdded(result);
|
||||
}
|
||||
return result;
|
||||
} finally {
|
||||
@@ -2139,6 +2182,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
LockUtil.unlockAfterWrite(regattaTrackingCacheLock);
|
||||
}
|
||||
stopObservingRegattaForRedaultLeaderboardAndAutoLeaderboardLinking(trackedRegatta);
|
||||
trackedRegattaListener.regattaRemoved(trackedRegatta);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -3026,8 +3070,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
}
|
||||
|
||||
@Override
|
||||
public GPSFixStore getGPSFixStore() {
|
||||
return gpsFixStore;
|
||||
public SensorFixStore getSensorFixStore() {
|
||||
return sensorFixStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -3310,4 +3354,55 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getRaceTrackerByRegattaAndRaceIdentifier(RegattaAndRaceIdentifier raceIdentifier,
|
||||
Consumer<RaceTracker> callback) {
|
||||
LockUtil.lockForRead(regattasByNameLock);
|
||||
Regatta regatta = regattasByName.get(raceIdentifier.getRegattaName());
|
||||
LockUtil.unlockAfterRead(regattasByNameLock);
|
||||
if (regatta != null) {
|
||||
LockUtil.lockForRead(raceTrackersByRegattaLock);
|
||||
try {
|
||||
Set<RaceTracker> raceTrackersForRegatta = raceTrackersByRegatta.get(regatta);
|
||||
if(raceTrackersForRegatta != null) {
|
||||
for (RaceTracker raceTracker : raceTrackersForRegatta) {
|
||||
if (raceTracker.getRaceIdentifiers().contains(raceIdentifier)) {
|
||||
callback.accept(raceTracker);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Util.addToValueSet(getRaceTrackerCallbacks(), raceIdentifier, callback);
|
||||
} finally {
|
||||
LockUtil.unlockAfterRead(raceTrackersByRegattaLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ConcurrentHashMap<RegattaAndRaceIdentifier, Set<Consumer<RaceTracker>>> getRaceTrackerCallbacks() {
|
||||
if (raceTrackerCallbacks == null) {
|
||||
synchronized (this) {
|
||||
if (raceTrackerCallbacks == null) {
|
||||
raceTrackerCallbacks = new ConcurrentHashMap<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
return raceTrackerCallbacks;
|
||||
}
|
||||
|
||||
private void notifyListenersForNewRaceTracker(RaceTracker tracker) {
|
||||
LockUtil.lockForRead(raceTrackersByRegattaLock);
|
||||
try {
|
||||
tracker.getRaceIdentifiers().forEach((raceIdentifier) -> {
|
||||
Set<Consumer<RaceTracker>> callbacks = getRaceTrackerCallbacks().remove(raceIdentifier);
|
||||
if (callbacks != null) {
|
||||
callbacks.forEach((callback) -> callback.accept(tracker));
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
LockUtil.unlockAfterRead(raceTrackersByRegattaLock);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+19
-7
@@ -31,9 +31,9 @@ import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.common.tracking.SensorFix;
|
||||
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
||||
import com.sap.sailing.domain.polars.PolarDataService;
|
||||
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
|
||||
import com.sap.sailing.domain.ranking.RankingMetric;
|
||||
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
|
||||
import com.sap.sailing.domain.tracking.CourseDesignChangedListener;
|
||||
@@ -44,6 +44,7 @@ import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.RaceAbortedListener;
|
||||
import com.sap.sailing.domain.tracking.RaceChangeListener;
|
||||
import com.sap.sailing.domain.tracking.RaceExecutionOrderProvider;
|
||||
import com.sap.sailing.domain.tracking.SensorFixTrack;
|
||||
import com.sap.sailing.domain.tracking.StartTimeChangedListener;
|
||||
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
@@ -535,11 +536,6 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GPSFixStore getGPSFixStore() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRaceAbortedListener(RaceAbortedListener listener) {
|
||||
}
|
||||
@@ -554,7 +550,7 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void waitForLoadingFromGPSFixStoreToFinishRunning(RegattaLog fromRegattaLog) throws InterruptedException {
|
||||
public void waitForLoadingToFinish() throws InterruptedException {
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -639,4 +635,20 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials {
|
||||
@Override
|
||||
public void updateStartAndEndOfTracking(boolean waitForGPSFixesToLoad) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <FixT extends SensorFix, TrackT extends SensorFixTrack<Competitor, FixT>> TrackT getSensorTrack(
|
||||
Competitor competitor, String trackName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<RegattaLog> getAttachedRegattaLogs() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<RaceLog> getAttachedRaceLogs() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
+6
-19
@@ -4,8 +4,6 @@ import com.sap.sailing.domain.base.RaceDefinition;
|
||||
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.racelog.tracking.EmptyGPSFixStore;
|
||||
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegatta;
|
||||
@@ -36,26 +34,15 @@ public class CreateTrackedRace extends AbstractRaceOperation<DynamicTrackedRace>
|
||||
*/
|
||||
private transient final WindStore windStore;
|
||||
|
||||
/**
|
||||
* If a {@link GPSFixStore} is provided to this command, it will be used for the construction of the tracked race.
|
||||
* However, after de-serialization, the store will always be <code>null</code>, causing the use of an
|
||||
* {@link EmptyGPSFixStore}.
|
||||
*/
|
||||
private transient final GPSFixStore gpsFixStore;
|
||||
|
||||
/**
|
||||
* @param windStore
|
||||
* if <code>null</code>, an {@link EmptyWindStore} will be used. Note that the {@link #windStore} field
|
||||
* won't be serialized. A receiver of this operation will therefore always use an {@link EmptyWindStore}.
|
||||
* @param gpsFixStore
|
||||
* if <code>null</code>, an {@link EmptyGPSFixStore} will be used. Note that the {@link #gpsFixStore} field
|
||||
* won't be serialized. A receiver of this operation will therefore always use an {@link EmptyWindStore}.
|
||||
*/
|
||||
public CreateTrackedRace(RegattaAndRaceIdentifier raceIdentifier, WindStore windStore, GPSFixStore gpsFixStore,
|
||||
long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed) {
|
||||
public CreateTrackedRace(RegattaAndRaceIdentifier raceIdentifier, WindStore windStore, long delayToLiveInMillis,
|
||||
long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed) {
|
||||
super(raceIdentifier);
|
||||
this.windStore = windStore;
|
||||
this.gpsFixStore = gpsFixStore;
|
||||
this.delayToLiveInMillis = delayToLiveInMillis;
|
||||
this.millisecondsOverWhichToAverageWind = millisecondsOverWhichToAverageWind;
|
||||
this.millisecondsOverWhichToAverageSpeed = millisecondsOverWhichToAverageSpeed;
|
||||
@@ -75,10 +62,10 @@ public class CreateTrackedRace extends AbstractRaceOperation<DynamicTrackedRace>
|
||||
|
||||
@Override
|
||||
public DynamicTrackedRace internalApplyTo(RacingEventService toState) {
|
||||
return toState.createTrackedRace(getRaceIdentifier(), windStore == null ? EmptyWindStore.INSTANCE : windStore,
|
||||
gpsFixStore == null ? EmptyGPSFixStore.INSTANCE : gpsFixStore,
|
||||
delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed,
|
||||
/* useMarkPassingCalculator */ false); // no separate mark passing calculations in replica;
|
||||
return toState.createTrackedRace(getRaceIdentifier(), windStore == null ? EmptyWindStore.INSTANCE : windStore,
|
||||
delayToLiveInMillis, millisecondsOverWhichToAverageWind,
|
||||
millisecondsOverWhichToAverageSpeed, /* useMarkPassingCalculator */ false);
|
||||
// no separate mark passing calculations in replica;
|
||||
// Mark passings are computed on master and are replicated separately.
|
||||
// See UpdateMarkPassings
|
||||
}
|
||||
|
||||
+11
-10
@@ -31,8 +31,6 @@ import com.sap.sailing.domain.common.RaceIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.impl.MasterDataImportObjectCreationCountImpl;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||
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.GPSFixImpl;
|
||||
@@ -49,7 +47,7 @@ import com.sap.sailing.domain.persistence.MongoRaceLogStoreFactory;
|
||||
import com.sap.sailing.domain.persistence.MongoRegattaLogStoreFactory;
|
||||
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
|
||||
import com.sap.sailing.domain.racelog.RaceLogStore;
|
||||
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
|
||||
import com.sap.sailing.domain.racelog.tracking.SensorFixStore;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.regattalike.HasRegattaLike;
|
||||
import com.sap.sailing.domain.regattalike.IsRegattaLike;
|
||||
@@ -64,6 +62,7 @@ import com.sap.sailing.server.RacingEventServiceOperation;
|
||||
import com.sap.sailing.server.masterdata.DataImportLockWithProgress;
|
||||
import com.sap.sailing.server.masterdata.DummyTrackedRace;
|
||||
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
|
||||
import com.sap.sse.common.Timed;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.concurrent.LockUtil;
|
||||
|
||||
@@ -402,21 +401,23 @@ public class ImportMasterDataOperation extends
|
||||
|
||||
|
||||
private void importRaceLogTrackingGPSFixes(RacingEventService toState) {
|
||||
Map<DeviceIdentifier, Set<GPSFix>> raceLogTrackingFixes = masterData.getRaceLogTrackingFixes();
|
||||
Map<DeviceIdentifier, Set<Timed>> raceLogTrackingFixes = masterData.getRaceLogTrackingFixes();
|
||||
if (raceLogTrackingFixes != null) {
|
||||
GPSFixStore store = toState.getGPSFixStore();
|
||||
for (Entry<DeviceIdentifier, Set<GPSFix>> entry : raceLogTrackingFixes.entrySet()) {
|
||||
SensorFixStore store = toState.getSensorFixStore();
|
||||
for (Entry<DeviceIdentifier, Set<Timed>> entry : raceLogTrackingFixes.entrySet()) {
|
||||
DeviceIdentifier device = entry.getKey();
|
||||
for (GPSFix fixToAdd : entry.getValue()) {
|
||||
for (Timed fixToAdd : entry.getValue()) {
|
||||
try {
|
||||
if (fixToAdd instanceof CompactGPSFixMovingImpl) {
|
||||
fixToAdd = new GPSFixMovingImpl(fixToAdd.getPosition(), fixToAdd.getTimePoint(),
|
||||
CompactGPSFixMovingImpl gpsFix = (CompactGPSFixMovingImpl) fixToAdd;
|
||||
fixToAdd = new GPSFixMovingImpl(gpsFix.getPosition(), fixToAdd.getTimePoint(),
|
||||
((CompactGPSFixMovingImpl) fixToAdd).getSpeed());
|
||||
} else if (fixToAdd instanceof CompactGPSFixImpl) {
|
||||
fixToAdd = new GPSFixImpl(fixToAdd.getPosition(), fixToAdd.getTimePoint());
|
||||
CompactGPSFixImpl gpsFix = (CompactGPSFixImpl) fixToAdd;
|
||||
fixToAdd = new GPSFixImpl(gpsFix.getPosition(), fixToAdd.getTimePoint());
|
||||
}
|
||||
store.storeFix(device, fixToAdd);
|
||||
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
|
||||
} catch (NoCorrespondingServiceRegisteredException e) {
|
||||
logger.severe("Failed to store race log tracking fix while importing.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package com.sap.sailing.server.operationaltransformation;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.tracking.SensorFix;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sailing.server.RacingEventServiceOperation;
|
||||
|
||||
public class RecordCompetitorSensorFix extends AbstractRaceOperation<Void> {
|
||||
private static final long serialVersionUID = -7092704633177037511L;
|
||||
private final Serializable competitorID;
|
||||
private final SensorFix fix;
|
||||
private final String trackName;
|
||||
|
||||
public RecordCompetitorSensorFix(RegattaAndRaceIdentifier raceIdentifier, Competitor competitor, String trackName, SensorFix fix) {
|
||||
super(raceIdentifier);
|
||||
this.trackName = trackName;
|
||||
this.competitorID = competitor.getId();
|
||||
this.fix = fix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Operations of this type can be run in parallel to other operations; subsequent operations do not have to wait
|
||||
* for this operation's completion.
|
||||
*/
|
||||
@Override
|
||||
public boolean requiresSynchronousExecution() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void internalApplyTo(RacingEventService toState) throws Exception {
|
||||
DynamicTrackedRace trackedRace = (DynamicTrackedRace) toState.getTrackedRace(getRaceIdentifier());
|
||||
Competitor competitor = trackedRace.getRace().getCompetitorById(competitorID);
|
||||
trackedRace.recordSensorFix(competitor, trackName, fix, /* onlyWhenInTrackingTimeInterval */ false); // record the fix in any case
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation<?> transformClientOp(RacingEventServiceOperation<?> serverOp) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation<?> transformServerOp(RacingEventServiceOperation<?> clientOp) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package com.sap.sailing.server.operationaltransformation;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.tracking.DynamicSensorFixTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sailing.server.RacingEventServiceOperation;
|
||||
|
||||
public class RecordCompetitorSensorFixTrack extends AbstractRaceOperation<Void> {
|
||||
private static final long serialVersionUID = -7092704633177037511L;
|
||||
private DynamicSensorFixTrack<Competitor, ?> track;
|
||||
|
||||
public RecordCompetitorSensorFixTrack(RegattaAndRaceIdentifier raceIdentifier, DynamicSensorFixTrack<Competitor, ?> track) {
|
||||
super(raceIdentifier);
|
||||
this.track = track;
|
||||
}
|
||||
|
||||
/**
|
||||
* Operations of this type can be run in parallel to other operations; subsequent operations do not have to wait
|
||||
* for this operation's completion.
|
||||
*/
|
||||
@Override
|
||||
public boolean requiresSynchronousExecution() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void internalApplyTo(RacingEventService toState) throws Exception {
|
||||
DynamicTrackedRace trackedRace = (DynamicTrackedRace) toState.getTrackedRace(getRaceIdentifier());
|
||||
trackedRace.addSensorTrack(track.getTrackedItem(), track.getTrackName(), track);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation<?> transformClientOp(RacingEventServiceOperation<?> serverOp) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation<?> transformServerOp(RacingEventServiceOperation<?> clientOp) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -3,10 +3,11 @@ package com.sap.sailing.server.operationaltransformation;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.TrackedRaceStatus;
|
||||
import com.sap.sailing.domain.tracking.TrackingDataLoader;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sailing.server.RacingEventServiceOperation;
|
||||
|
||||
public class UpdateTrackedRaceStatus extends AbstractRaceOperation<Void> {
|
||||
public class UpdateTrackedRaceStatus extends AbstractRaceOperation<Void> implements TrackingDataLoader {
|
||||
private static final long serialVersionUID = 5847067037829132465L;
|
||||
private final TrackedRaceStatus newStatus;
|
||||
|
||||
@@ -18,7 +19,7 @@ public class UpdateTrackedRaceStatus extends AbstractRaceOperation<Void> {
|
||||
@Override
|
||||
public Void internalApplyTo(RacingEventService toState) throws Exception {
|
||||
DynamicTrackedRace trackedRace = (DynamicTrackedRace) toState.getTrackedRace(getRaceIdentifier());
|
||||
trackedRace.setStatus(newStatus);
|
||||
trackedRace.onStatusChanged(this, newStatus);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -189,12 +189,12 @@ public class SimulationServiceImpl implements SimulationService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startOfTrackingChanged(TimePoint startOfTracking) {
|
||||
public void startOfTrackingChanged(TimePoint oldStartOfTracking, TimePoint newStartOfTracking) {
|
||||
// irrelevant for simulation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endOfTrackingChanged(TimePoint endOfTracking) {
|
||||
public void endOfTrackingChanged(TimePoint oldEndOfTracking, TimePoint newEndOfTracking) {
|
||||
// irrelevant for simulation
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user