Bug 5085: Include all known device mappings per MarkConfiguration and

not only the current one
This commit is contained in:
Steffen Schaefer committed 2020-01-13 14:16:30 +01:00
1 parent 8dc87b1080
commit 223400a378
8 files changed
+158 -41

No files matched your search

@@ -2,6 +2,8 @@ package com.sap.sailing.domain.coursetemplate;
import com.sap.sailing.domain.common.DeviceIdentifier;
import com.sap.sailing.domain.common.Position;
import com.sap.sse.common.TimeRange;
import com.sap.sse.common.Util.Pair;
/**
* Used on a {@link MarkConfiguration} as a response to a client, providing a result-oriented view on a mark
@@ -12,6 +14,7 @@ import com.sap.sailing.domain.common.Position;
*
*/
public interface MarkConfigurationResponseAnnotation {
// TODO decide if it would be beneficial to use GPSFix instead. Most but not all code paths may provide a GPSFix but MarkProperties with a fixed position does not have a TimePoint associated with the Position.
Position getLastKnownPosition();
DeviceIdentifier getCurrentTrackingDevice();
Iterable<Pair<DeviceIdentifier, TimeRange>> getDeviceMappings();
}
@@ -1,17 +1,35 @@
package com.sap.sailing.domain.coursetemplate.impl;
import java.util.Collections;
import com.sap.sailing.domain.common.DeviceIdentifier;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.coursetemplate.MarkConfigurationResponseAnnotation;
import com.sap.sse.common.TimeRange;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.impl.TimeRangeImpl;
public class MarkConfigurationResponseAnnotationImpl implements MarkConfigurationResponseAnnotation {
private final Position lastKnownPosition;
private final DeviceIdentifier currentTrackingDevice;
private final Iterable<Pair<DeviceIdentifier, TimeRange>> deviceMappings;
public MarkConfigurationResponseAnnotationImpl(Position lastKnownPosition) {
super();
this.lastKnownPosition = lastKnownPosition;
this.deviceMappings = Collections.emptySet();
}
public MarkConfigurationResponseAnnotationImpl(Position lastKnownPosition, DeviceIdentifier currentTrackingDevice) {
super();
this.lastKnownPosition = lastKnownPosition;
this.currentTrackingDevice = currentTrackingDevice;
this.deviceMappings = Collections.singleton(new Pair<>(currentTrackingDevice, new TimeRangeImpl(null, null)));
}
public MarkConfigurationResponseAnnotationImpl(Position lastKnownPosition,
Iterable<Pair<DeviceIdentifier, TimeRange>> deviceMappings) {
super();
this.lastKnownPosition = lastKnownPosition;
this.deviceMappings = deviceMappings;
}
@Override
@@ -20,7 +38,7 @@ public class MarkConfigurationResponseAnnotationImpl implements MarkConfiguratio
}
@Override
public DeviceIdentifier getCurrentTrackingDevice() {
return currentTrackingDevice;
public Iterable<Pair<DeviceIdentifier, TimeRange>> getDeviceMappings() {
return deviceMappings;
}
}
@@ -9,6 +9,7 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceMappingFinder;
import com.sap.sailing.domain.base.Mark;
@@ -17,6 +18,7 @@ import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.DeviceIdentifier;
import com.sap.sailing.domain.common.PassingInstruction;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.tracking.GPSFix;
import com.sap.sailing.domain.coursetemplate.CommonMarkProperties;
import com.sap.sailing.domain.coursetemplate.CourseConfiguration;
import com.sap.sailing.domain.coursetemplate.CourseTemplate;
@@ -50,7 +52,12 @@ import com.sap.sailing.domain.coursetemplate.impl.RegattaMarkConfigurationImpl;
import com.sap.sailing.domain.coursetemplate.impl.WaypointWithMarkConfigurationImpl;
import com.sap.sailing.domain.racelogtracking.DeviceMappingWithRegattaLogEvent;
import com.sap.sailing.domain.sharedsailingdata.SharedSailingData;
import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.TimeRange;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.WithID;
import com.sap.sse.common.impl.MillisecondsTimePoint;
/**
* Builder API for constructing a {@link CourseConfiguration}. Various domain objects like {@link MarkTemplate}s,
@@ -255,11 +262,12 @@ public class CourseConfigurationBuilder {
associatedRoles, waypoints, optionalRepeatablePart, numberOfLaps, name, optionalImageUrl);
}
public static MarkConfigurationResponseAnnotation getPositioningIfAvailable(Regatta regatta, Mark mark, Function<DeviceIdentifier, Position> positionResolver) {
final DeviceIdentifier identifier = findDeviceForMostRecentOrOngoingMapping(regatta, mark);
return createMarkConfigurationResponseAnnotation(positionResolver, identifier);
public static MarkConfigurationResponseAnnotation getPositioningIfAvailable(Regatta regatta,
TrackedRace optionalRace, Mark mark, Function<DeviceIdentifier, Position> positionResolver) {
return createMarkConfigurationResponseAnnotation(optionalRace, mark, positionResolver,
findAllDevicesAndMappedRangesForMark(regatta, mark));
}
private static MarkConfigurationResponseAnnotation createMarkConfigurationResponseAnnotation(
Function<DeviceIdentifier, Position> positionResolver, final DeviceIdentifier identifier) {
final Position position;
@@ -271,14 +279,43 @@ public class CourseConfigurationBuilder {
return new MarkConfigurationResponseAnnotationImpl(position, identifier);
}
/**
* @return the device mapping from the set of {@code foundMappings} which is either ongoing or has the most recent
* end time point
*/
private static DeviceIdentifier findDeviceForMostRecentOrOngoingMapping(
final Regatta regatta, final Mark mark) {
final DeviceMappingWithRegattaLogEvent<Mark> mostRecentOrOngoingMapping = findMostRecentOrOngoingMapping(regatta, mark);
return mostRecentOrOngoingMapping == null ? null : mostRecentOrOngoingMapping.getDevice();
private static MarkConfigurationResponseAnnotation createMarkConfigurationResponseAnnotation(
TrackedRace optionalRace, Mark mark,
Function<DeviceIdentifier, Position> positionResolver,
Iterable<Pair<DeviceIdentifier, TimeRange>> deviceMappings) {
Position position = null;
if (optionalRace != null) {
final GPSFixTrack<Mark, GPSFix> trackForMark = optionalRace.getTrack(mark);
if (trackForMark != null) {
final GPSFix lastFixOrNull = trackForMark.getLastFixAtOrBefore(MillisecondsTimePoint.now());
if (lastFixOrNull != null) {
position = lastFixOrNull.getPosition();
}
}
}
if (position == null) {
final Pair<DeviceIdentifier,TimeRange> mostRecentOrOngoingMapping = findMostRecentOrOngoingMapping(deviceMappings);
if (mostRecentOrOngoingMapping != null) {
position = positionResolver.apply(mostRecentOrOngoingMapping.getA());
}
}
return new MarkConfigurationResponseAnnotationImpl(position, deviceMappings);
}
public static Pair<DeviceIdentifier, TimeRange> findMostRecentOrOngoingMapping(
Iterable<Pair<DeviceIdentifier, TimeRange>> deviceMappings) {
Pair<DeviceIdentifier, TimeRange> bestMatchingDeviceMapping = null;
for (Pair<DeviceIdentifier, TimeRange> deviceMapping : deviceMappings) {
if (bestMatchingDeviceMapping == null
|| (deviceMapping.getB().hasOpenEnd() && !bestMatchingDeviceMapping.getB().hasOpenEnd())
|| (deviceMapping.getB().hasOpenEnd() && bestMatchingDeviceMapping.getB().hasOpenEnd()
&& deviceMapping.getB().startsAfter(bestMatchingDeviceMapping.getB()))
|| (!deviceMapping.getB().hasOpenEnd() && !bestMatchingDeviceMapping.getB().hasOpenEnd()
&& deviceMapping.getB().endsAfter(bestMatchingDeviceMapping.getB()))) {
bestMatchingDeviceMapping = deviceMapping;
}
}
return bestMatchingDeviceMapping;
}
/**
@@ -306,6 +343,14 @@ public class CourseConfigurationBuilder {
}
return bestMatchingDeviceMapping;
}
public static Iterable<Pair<DeviceIdentifier, TimeRange>> findAllDevicesAndMappedRangesForMark(
final Regatta regatta, Mark mark) {
final Map<WithID, List<DeviceMappingWithRegattaLogEvent<WithID>>> deviceMappings = new RegattaLogDeviceMappingFinder<>(
regatta.getRegattaLog()).analyze();
final List<DeviceMappingWithRegattaLogEvent<WithID>> foundMappings = deviceMappings.get(mark);
return foundMappings.stream().map(dm -> new Pair<>(dm.getDevice(), dm.getTimeRange())).collect(Collectors.toList());
}
/**
* For a {@link MarkProperties} object finds its {@link MarkProperties#getPositioningInformation()} and if it is {@code null}, returns {@code null};
@@ -321,7 +366,7 @@ public class CourseConfigurationBuilder {
result = positioning.accept(new PositioningVisitor<MarkConfigurationResponseAnnotation>() {
@Override
public MarkConfigurationResponseAnnotation visit(FixedPositioning fixedPositioning) {
return new MarkConfigurationResponseAnnotationImpl(fixedPositioning.getFixedPosition(), /* tracking device */ null);
return new MarkConfigurationResponseAnnotationImpl(fixedPositioning.getFixedPosition());
}
@Override
@@ -25,6 +25,8 @@ import com.sap.sailing.domain.coursetemplate.RegattaMarkConfiguration;
import com.sap.sailing.domain.coursetemplate.RepeatablePart;
import com.sap.sailing.domain.coursetemplate.WaypointWithMarkConfiguration;
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
import com.sap.sse.common.TimeRange;
import com.sap.sse.common.Util.Pair;
public class CourseConfigurationJsonSerializer implements JsonSerializer<CourseConfiguration<MarkConfigurationResponseAnnotation>> {
@@ -39,7 +41,11 @@ public class CourseConfigurationJsonSerializer implements JsonSerializer<CourseC
public static final String FIELD_MARK_CONFIGURATION_FREESTYLE_PROPERTIES = "freestyleProperties";
public static final String FIELD_MARK_CONFIGURATION_ASSOCIATED_ROLE = "associatedRole";
public static final String FIELD_MARK_CONFIGURATION_ASSOCIATED_ROLE_ID = "associatedRoleId";
public static final String FIELD_MARK_CONFIGURATION_CURRENT_TRACKING_DEVICE_ID = "currentTrackingDeviceId";
public static final String FIELD_MARK_CONFIGURATION_TRACKING_DEVICE_MAPPINGS = "trackingDevices";
public static final String FIELD_MARK_CONFIGURATION_TRACKING_DEVICE_TYPE = "trackingDeviceType";
public static final String FIELD_MARK_CONFIGURATION_TRACKING_DEVICE_HASH = "trackingDeviceHash";
public static final String FIELD_MARK_CONFIGURATION_TRACKING_DEVICE_MAPPED_FROM = "trackingDeviceMappedFromMillis";
public static final String FIELD_MARK_CONFIGURATION_TRACKING_DEVICE_MAPPED_TO = "trackingDeviceMappedToMillis";
public static final String FIELD_MARK_CONFIGURATION_LAST_KNOWN_POSITION = "lastKnownPosition";
public static final String FIELD_MARK_CONFIGURATION_POSITIONING = "positioning";
public static final String FIELD_MARK_CONFIGURATION_STORE_TO_INVENTORY = "storeToInventory";
@@ -55,13 +61,11 @@ public class CourseConfigurationJsonSerializer implements JsonSerializer<CourseC
private final JsonSerializer<RepeatablePart> repeatablePartJsonSerializer;
private final JsonSerializer<CommonMarkProperties> commonMarkPropertiesJsonSerializer;
private final JsonSerializer<Position> positionJsonSerializer;
private final JsonSerializer<DeviceIdentifier> deviceIdentifierJsonSerializer;
public CourseConfigurationJsonSerializer(DeviceIdentifierJsonSerializer deviceIdentifierSerializer) {
public CourseConfigurationJsonSerializer() {
repeatablePartJsonSerializer = new RepeatablePartJsonSerializer();
commonMarkPropertiesJsonSerializer = new CommonMarkPropertiesJsonSerializer();
this.positionJsonSerializer = new PositionJsonSerializer();
this.deviceIdentifierJsonSerializer = deviceIdentifierSerializer;
}
@Override
@@ -136,9 +140,27 @@ public class CourseConfigurationJsonSerializer implements JsonSerializer<CourseC
markConfigurationsEntry.put(FIELD_MARK_CONFIGURATION_EFFECTIVE_PROPERTIES,
commonMarkPropertiesJsonSerializer.serialize(markConfiguration.getEffectiveProperties()));
if (markConfiguration.getAnnotationInfo() != null) {
if (markConfiguration.getAnnotationInfo().getCurrentTrackingDevice() != null) {
markConfigurationsEntry.put(FIELD_MARK_CONFIGURATION_CURRENT_TRACKING_DEVICE_ID,
deviceIdentifierJsonSerializer.serialize(markConfiguration.getAnnotationInfo().getCurrentTrackingDevice()));
final JSONArray deviceMappings = new JSONArray();
markConfigurationsEntry.put(FIELD_MARK_CONFIGURATION_TRACKING_DEVICE_MAPPINGS,
deviceMappings);
for (Pair<DeviceIdentifier, TimeRange> deviceMapping : markConfiguration.getAnnotationInfo()
.getDeviceMappings()) {
final JSONObject deviceMappingObject = new JSONObject();
final DeviceIdentifier deviceIdentifier = deviceMapping.getA();
deviceMappingObject.put(FIELD_MARK_CONFIGURATION_TRACKING_DEVICE_TYPE,
deviceIdentifier.getIdentifierType());
deviceMappingObject.put(FIELD_MARK_CONFIGURATION_TRACKING_DEVICE_HASH,
HashedStringUtil.toHashedString(deviceIdentifier.getStringRepresentation()));
final TimeRange mappedTimeRange = deviceMapping.getB();
if (!mappedTimeRange.hasOpenBeginning()) {
deviceMappingObject.put(FIELD_MARK_CONFIGURATION_TRACKING_DEVICE_MAPPED_FROM,
mappedTimeRange.from().asMillis());
}
if (!mappedTimeRange.hasOpenEnd()) {
deviceMappingObject.put(FIELD_MARK_CONFIGURATION_TRACKING_DEVICE_MAPPED_TO,
mappedTimeRange.to().asMillis());
}
deviceMappings.add(deviceMappingObject);
}
if (markConfiguration.getAnnotationInfo().getLastKnownPosition() != null) {
markConfigurationsEntry.put(FIELD_MARK_CONFIGURATION_LAST_KNOWN_POSITION,
@@ -0,0 +1,24 @@
package com.sap.sailing.server.gateway.serialization.impl;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class HashedStringUtil {
public static String toHashedString(String stringToHash) {
assert stringToHash != null;
final MessageDigest messageDigest;
try {
messageDigest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(e);
}
final byte[] digest = messageDigest.digest(stringToHash.getBytes(StandardCharsets.UTF_8));
final StringBuilder sb = new StringBuilder(digest.length * 2);
for (byte b : digest) {
sb.append(String.format("%02X ", b));
}
return sb.toString();
}
}
@@ -72,7 +72,6 @@ import com.sap.sailing.server.gateway.deserialization.impl.DeviceIdentifierJsonD
import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource;
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
import com.sap.sailing.server.gateway.serialization.impl.CourseConfigurationJsonSerializer;
import com.sap.sailing.server.gateway.serialization.impl.DeviceIdentifierJsonSerializer;
import com.sap.sailing.server.gateway.serialization.racelog.tracking.DeviceIdentifierJsonHandler;
import com.sap.sailing.server.gateway.serialization.racelog.tracking.impl.PlaceHolderDeviceIdentifierJsonHandler;
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
@@ -175,7 +174,8 @@ public class CourseConfigurationResource extends AbstractSailingServerResource {
// set of marks to be used while defining a course for the regatta.
// An additional call to get the marks defined in the regatta isn't necessary with the described behavior of this API.
final CourseConfiguration<MarkConfigurationResponseAnnotation> courseConfiguration = getService().getCourseAndMarkConfigurationFactory()
.createCourseConfigurationFromRegatta(courseBase, regatta, tags);
.createCourseConfigurationFromRegatta(courseBase, regatta, raceColumnByName.getTrackedRace(fleetByName),
tags);
final JSONObject jsonResult = getCourseConfigurationJsonSerializer().serialize(courseConfiguration);
return Response.ok(jsonResult.toJSONString()).build();
}
@@ -341,7 +341,8 @@ public class CourseConfigurationResource extends AbstractSailingServerResource {
result = null;
}
} else {
result = CourseConfigurationBuilder.getPositioningIfAvailable(regatta, regattaMark, positionResolverFromDeviceIdentifier);
result = CourseConfigurationBuilder.getPositioningIfAvailable(regatta, /* optionalRace */ null, regattaMark,
positionResolverFromDeviceIdentifier);
}
return result;
}
@@ -399,14 +400,15 @@ public class CourseConfigurationResource extends AbstractSailingServerResource {
raceLog.add(new RaceLogCourseDesignChangedEventImpl(timestampForLogEntries, getService().getServerAuthor(),
raceLog.getCurrentPassId(), course, CourseDesignerMode.BY_MARKS));
final CourseConfiguration<MarkConfigurationResponseAnnotation> courseConfigurationResult = getService().getCourseAndMarkConfigurationFactory()
.createCourseConfigurationFromRegatta(course, regatta, /* tagsToFilterMarkProperties */ null);
.createCourseConfigurationFromRegatta(course, regatta, raceColumnByName.getTrackedRace(fleetByName),
/* tagsToFilterMarkProperties */ null);
final String jsonString = getCourseConfigurationJsonSerializer().serialize(courseConfigurationResult).toJSONString();
return Response.ok(jsonString).build();
}
private synchronized JsonSerializer<CourseConfiguration<MarkConfigurationResponseAnnotation>> getCourseConfigurationJsonSerializer() {
if (courseConfigurationJsonSerializer == null) {
courseConfigurationJsonSerializer = new CourseConfigurationJsonSerializer(new DeviceIdentifierJsonSerializer(getDeviceJsonServiceFinder()));
courseConfigurationJsonSerializer = new CourseConfigurationJsonSerializer();
}
return courseConfigurationJsonSerializer;
}
@@ -26,6 +26,7 @@ import com.sap.sailing.domain.coursetemplate.RepeatablePart;
import com.sap.sailing.domain.coursetemplate.WaypointTemplate;
import com.sap.sailing.domain.coursetemplate.WaypointWithMarkConfiguration;
import com.sap.sailing.domain.coursetemplate.WithOptionalRepeatablePart;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.TimePoint;
import com.sap.sse.security.shared.impl.UserGroup;
@@ -141,7 +142,7 @@ public interface CourseAndMarkConfigurationFactory {
* {@link CourseTemplate} needs to match all given tags.
*/
CourseConfiguration<MarkConfigurationResponseAnnotation> createCourseConfigurationFromRegatta(CourseBase optionalCourse, Regatta regatta,
Iterable<String> tagsToFilterMarkProperties);
TrackedRace optionalRace, Iterable<String> tagsToFilterMarkProperties);
/**
* TODO: not implemented yet
@@ -590,7 +590,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
for (Mark mark : raceColumn.getAvailableMarks()) {
markConfigurationsByMark
.computeIfAbsent(mark,
m -> createMarkConfigurationForRegattaMark(courseTemplate, optionalRegatta, m));
m -> createMarkConfigurationForRegattaMark(courseTemplate, optionalRegatta, /* optionalRace */ null, m));
}
}
final LastUsageBasedAssociater<RegattaMarkConfiguration<MarkConfigurationResponseAnnotation>, IsMarkRole> usagesForRole = new LastUsageBasedAssociater<>(
@@ -629,7 +629,7 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
// FIXME the following can never be "absent" because all race columns have been enumerated and all their getAllAvailableMarks() have been mapped in markConfigurationsByMark already
final RegattaMarkConfiguration<MarkConfigurationResponseAnnotation> regattaMarkConfiguration = markConfigurationsByMark
.computeIfAbsent(mark,
m -> createMarkConfigurationForRegattaMark(courseTemplate, optionalRegatta, m));
m -> createMarkConfigurationForRegattaMark(courseTemplate, optionalRegatta, /* optionalRace */ null, m));
lastUsages.compute(regattaMarkConfiguration,
(mc, existingTP) -> (existingTP == null || existingTP.before(effectiveUsageTP))
? effectiveUsageTP
@@ -738,11 +738,12 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
@Override
public CourseConfiguration<MarkConfigurationResponseAnnotation> createCourseConfigurationFromRegatta(CourseBase course, Regatta regatta,
Iterable<String> tagsToFilterMarkProperties) {
TrackedRace optionalRace, Iterable<String> tagsToFilterMarkProperties) {
assert regatta != null;
final Set<MarkConfiguration<MarkConfigurationResponseAnnotation>> allMarkConfigurations = new HashSet<>();
final CourseTemplate courseTemplateOrNull = course == null ? null : resolveCourseTemplateSafe(course);
final Map<Mark, RegattaMarkConfiguration<MarkConfigurationResponseAnnotation>> markConfigurationsByMark = createMarkConfigurationsForRegatta(regatta, courseTemplateOrNull);
final Map<Mark, RegattaMarkConfiguration<MarkConfigurationResponseAnnotation>> markConfigurationsByMark = createMarkConfigurationsForRegatta(
regatta, optionalRace, courseTemplateOrNull);
allMarkConfigurations.addAll(markConfigurationsByMark.values());
final Map<MarkConfiguration<MarkConfigurationResponseAnnotation>, IsMarkRole> resultingRoleMapping = new HashMap<>();
if (course != null) {
@@ -814,13 +815,14 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
resultingWaypoints, optionalRepeatablePart, numberOfLaps, name, optionalImageURL);
}
private Map<Mark, RegattaMarkConfiguration<MarkConfigurationResponseAnnotation>> createMarkConfigurationsForRegatta(Regatta regatta, CourseTemplate courseTemplate) {
private Map<Mark, RegattaMarkConfiguration<MarkConfigurationResponseAnnotation>> createMarkConfigurationsForRegatta(
Regatta regatta, TrackedRace optionalRace, CourseTemplate courseTemplate) {
final Map<Mark, RegattaMarkConfiguration<MarkConfigurationResponseAnnotation>> result = new HashMap<>();
for (RaceColumn raceColumn : regatta.getRaceColumns()) {
for (Mark mark : raceColumn.getAvailableMarks()) {
result
.computeIfAbsent(mark,
m -> createMarkConfigurationForRegattaMark(courseTemplate, regatta, m));
m -> createMarkConfigurationForRegattaMark(courseTemplate, regatta, optionalRace, m));
}
}
return result;
@@ -965,8 +967,8 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
}
}
private MarkConfigurationResponseAnnotation getPositioningIfAvailable(Regatta regatta, Mark mark) {
return CourseConfigurationBuilder.getPositioningIfAvailable(regatta, mark, lastKnownPositionResolver);
private MarkConfigurationResponseAnnotation getPositioningIfAvailable(Regatta regatta, TrackedRace optionalRace, Mark mark) {
return CourseConfigurationBuilder.getPositioningIfAvailable(regatta, optionalRace, mark, lastKnownPositionResolver);
}
private MarkConfigurationResponseAnnotation getPositioningIfAvailable(MarkProperties markProperties) {
@@ -1003,14 +1005,14 @@ public class CourseAndMarkConfigurationFactoryImpl implements CourseAndMarkConfi
}
private RegattaMarkConfiguration<MarkConfigurationResponseAnnotation> createMarkConfigurationForRegattaMark(CourseTemplate courseTemplate,
Regatta regatta, Mark mark) {
Regatta regatta, TrackedRace optionalRace, Mark mark) {
final UUID markTemplateIdOrNull = mark.getOriginatingMarkTemplateIdOrNull();
final MarkTemplate markTemplateOrNull = markTemplateIdOrNull == null ? null : resolveMarkTemplateByID(courseTemplate, markTemplateIdOrNull);
final UUID markPropertiesIdOrNull = mark.getOriginatingMarkPropertiesIdOrNull();
final MarkProperties markPropertiesOrNull = markPropertiesIdOrNull == null ? null
: getSharedSailingData().getMarkPropertiesById(markPropertiesIdOrNull);
final RegattaMarkConfiguration<MarkConfigurationResponseAnnotation> regattaMarkConfiguration = new RegattaMarkConfigurationImpl<MarkConfigurationResponseAnnotation>(
mark, getPositioningIfAvailable(regatta, mark), markTemplateOrNull, markPropertiesOrNull);
mark, getPositioningIfAvailable(regatta, optionalRace, mark), markTemplateOrNull, markPropertiesOrNull);
return regattaMarkConfiguration;
}