mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-04 10:09:42 +00:00
bug6077: moved functionality for competitor details from SailingService to RacingEventService
This commit is contained in:
1 parent
b1345fec72
commit
6ed60b500a
4 files changed
+473
-439
No files matched your search
+8
-439
@@ -47,8 +47,6 @@ import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.RunnableFuture;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -62,8 +60,6 @@ import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.math.FunctionEvaluationException;
|
||||
import org.apache.commons.math.MaxIterationsExceededException;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
@@ -177,7 +173,6 @@ import com.sap.sailing.domain.common.RegattaScoreCorrections.ScoreCorrectionsFor
|
||||
import com.sap.sailing.domain.common.ScoreCorrectionProvider;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.common.TackType;
|
||||
import com.sap.sailing.domain.common.TrackedRaceStatusEnum;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
@@ -270,7 +265,6 @@ import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCalculationReuse
|
||||
import com.sap.sailing.domain.leaderboard.caching.LiveLeaderboardUpdater;
|
||||
import com.sap.sailing.domain.leaderboard.meta.MetaLeaderboardColumn;
|
||||
import com.sap.sailing.domain.markpassinghash.MarkPassingRaceFingerprintRegistry;
|
||||
import com.sap.sailing.domain.orc.ORCPerformanceCurveRankingMetric;
|
||||
import com.sap.sailing.domain.orc.ORCPublicCertificateDatabase;
|
||||
import com.sap.sailing.domain.orc.ORCPublicCertificateDatabase.CertificateHandle;
|
||||
import com.sap.sailing.domain.persistence.DomainObjectFactory;
|
||||
@@ -285,8 +279,6 @@ import com.sap.sailing.domain.racelogtracking.DeviceMapping;
|
||||
import com.sap.sailing.domain.racelogtracking.RaceLogTrackingAdapter;
|
||||
import com.sap.sailing.domain.racelogtracking.RaceLogTrackingAdapterFactory;
|
||||
import com.sap.sailing.domain.racelogtracking.impl.DeviceMappingImpl;
|
||||
import com.sap.sailing.domain.ranking.RankingMetric;
|
||||
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
|
||||
import com.sap.sailing.domain.regattalike.HasRegattaLike;
|
||||
import com.sap.sailing.domain.regattalike.LeaderboardThatHasRegattaLike;
|
||||
import com.sap.sailing.domain.regattalog.RegattaLogStore;
|
||||
@@ -316,7 +308,6 @@ import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.TrackingConnectorInfo;
|
||||
import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache;
|
||||
import com.sap.sailing.domain.tracking.WindPositionMode;
|
||||
import com.sap.sailing.domain.tracking.WindTrack;
|
||||
import com.sap.sailing.domain.tracking.WindWithConfidence;
|
||||
import com.sap.sailing.domain.tractracadapter.RaceRecord;
|
||||
@@ -2580,436 +2571,6 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param leaderboardGroupId
|
||||
* if not {@code null}, this takes precedence over the {@code leaderboardGroupName} parameter which will
|
||||
* then be ignored and will be used to look up an optional leaderboard group providing the context, e.g.,
|
||||
* for seasonal scores from an overall leaderboard
|
||||
* @param leaderboardGroupName
|
||||
* evaluated only if {@code leaderboardGroupId} was {@code null}; may even be {@code null} if
|
||||
* {@code leaderboardGroupId} is {@code null} too because leaderboard group resolution is optional. If a
|
||||
* non-{@code null} name is provided here and if {@code leaderboardGroupId} was {@code null} then the
|
||||
* name is used to try to resolve the leaderboard group by name.
|
||||
*/
|
||||
public Double getCompetitorRaceDataEntry(DetailType dataType, TrackedRace trackedRace, Competitor competitor,
|
||||
TimePoint timePoint, String leaderboardGroupName, UUID leaderboardGroupId, String leaderboardName,
|
||||
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws NoWindException {
|
||||
Double result = null;
|
||||
final Course course = trackedRace.getRace().getCourse();
|
||||
course.lockForRead(); // make sure the tracked leg survives this call even if a course update is pending
|
||||
trackedRace.lockForRead(trackedRace.getMarkPassings(competitor));
|
||||
try {
|
||||
final TrackedLegOfCompetitor trackedLeg = trackedRace.getTrackedLeg(competitor, timePoint);
|
||||
switch (dataType) {
|
||||
case LEG_TACKTYPE_LONGTACK_SHORTTACK:
|
||||
final TackType tackType;
|
||||
if (trackedLeg != null && (tackType = trackedLeg.getTackType(timePoint, cache)) != null ) {
|
||||
result = tackType==TackType.LONGTACK ? 1.0 : -1.0;
|
||||
} else {
|
||||
// trackedLeg == null || tackType == null;
|
||||
result = 0.0;
|
||||
}
|
||||
break;
|
||||
case RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS:
|
||||
final GPSFixTrack<Competitor, GPSFixMoving> sogTrack = trackedRace.getTrack(competitor);
|
||||
if (sogTrack != null) {
|
||||
SpeedWithBearing speedOverGround = sogTrack.getEstimatedSpeed(timePoint);
|
||||
result = (speedOverGround == null) ? null : speedOverGround.getKnots();
|
||||
}
|
||||
break;
|
||||
case RACE_CURRENT_COURSE_OVER_GROUND_IN_TRUE_DEGREES:
|
||||
case CHART_COURSE_OVER_GROUND_TRUE_DEGREES:
|
||||
final GPSFixTrack<Competitor, GPSFixMoving> cogTrack = trackedRace.getTrack(competitor);
|
||||
if (cogTrack != null) {
|
||||
SpeedWithBearing speedOverGround = cogTrack.getEstimatedSpeed(timePoint);
|
||||
result = (speedOverGround == null) ? null : speedOverGround.getBearing().getDegrees();
|
||||
}
|
||||
break;
|
||||
case RACE_CURRENT_POSITION_LAT_DEG:
|
||||
final GPSFixTrack<Competitor, GPSFixMoving> latTrack = trackedRace.getTrack(competitor);
|
||||
if (latTrack != null) {
|
||||
Position position = latTrack.getEstimatedPosition(timePoint, /* extrapolate */ true);
|
||||
result = (position == null) ? null : position.getLatDeg();
|
||||
}
|
||||
break;
|
||||
case RACE_CURRENT_POSITION_LNG_DEG:
|
||||
final GPSFixTrack<Competitor, GPSFixMoving> lngTrack = trackedRace.getTrack(competitor);
|
||||
if (lngTrack != null) {
|
||||
Position position = lngTrack.getEstimatedPosition(timePoint, /* extrapolate */ true);
|
||||
result = (position == null) ? null : position.getLngDeg();
|
||||
}
|
||||
break;
|
||||
case LEG_VELOCITY_MADE_GOOD_IN_KNOTS:
|
||||
final Speed velocityMadeGood;
|
||||
if (trackedLeg != null) {
|
||||
velocityMadeGood = trackedLeg.getVelocityMadeGood(timePoint, WindPositionMode.EXACT, cache);
|
||||
} else {
|
||||
// check if wind information is available; if so, compute a VMG only based on wind data:
|
||||
velocityMadeGood = trackedRace.getVelocityMadeGood(competitor, timePoint, cache);
|
||||
}
|
||||
result = (velocityMadeGood == null) ? null : velocityMadeGood.getKnots();
|
||||
break;
|
||||
case LEG_DISTANCE_TRAVELED:
|
||||
if (trackedLeg != null) {
|
||||
Distance distanceTraveled = trackedRace.getDistanceTraveled(competitor, timePoint);
|
||||
result = distanceTraveled == null ? null : distanceTraveled.getMeters();
|
||||
}
|
||||
break;
|
||||
case LEG_DISTANCE_TRAVELED_INCLUDING_GATE_START:
|
||||
if (trackedLeg != null) {
|
||||
Distance distanceTraveledConsideringGateStart = trackedRace.getDistanceTraveledIncludingGateStart(competitor, timePoint);
|
||||
result = distanceTraveledConsideringGateStart == null ? null : distanceTraveledConsideringGateStart.getMeters();
|
||||
}
|
||||
break;
|
||||
case LEG_GAP_TO_LEADER_IN_SECONDS:
|
||||
if (trackedLeg != null) {
|
||||
final RankingInfo rankingInfo = trackedRace.getRankingMetric().getRankingInfo(timePoint, cache);
|
||||
final Duration gapToLeaderInOwnTime = trackedLeg.getTrackedLeg().getTrackedRace().getRankingMetric().getGapToLeaderInOwnTime(rankingInfo, competitor, cache);
|
||||
result = gapToLeaderInOwnTime == null ? null : gapToLeaderInOwnTime.asSeconds();
|
||||
}
|
||||
break;
|
||||
case CHART_WINDWARD_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD:
|
||||
if (trackedLeg != null) {
|
||||
final RankingInfo rankingInfo = trackedRace.getRankingMetric().getRankingInfo(timePoint, cache);
|
||||
Distance distanceToLeader = trackedLeg.getWindwardDistanceToCompetitorFarthestAhead(timePoint, WindPositionMode.LEG_MIDDLE, rankingInfo, cache);
|
||||
result = (distanceToLeader == null) ? null : distanceToLeader.getMeters();
|
||||
}
|
||||
break;
|
||||
case RACE_IMPLIED_WIND:
|
||||
final RankingMetric rankingMetric = trackedRace.getRankingMetric();
|
||||
if (rankingMetric instanceof ORCPerformanceCurveRankingMetric) {
|
||||
final ORCPerformanceCurveRankingMetric orcPcsRankingMetric =
|
||||
(ORCPerformanceCurveRankingMetric) rankingMetric;
|
||||
try {
|
||||
final Speed impliedWind = orcPcsRankingMetric.getImpliedWind(competitor, timePoint, cache);
|
||||
result = impliedWind == null ? null : impliedWind.getKnots();
|
||||
} catch (MaxIterationsExceededException | FunctionEvaluationException e) {
|
||||
logger.log(Level.WARNING, "Problem computing implied wind", e);
|
||||
result = null;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RACE_RANK:
|
||||
if (trackedLeg != null) {
|
||||
result = (double) trackedLeg.getRank(timePoint, cache);
|
||||
}
|
||||
break;
|
||||
case REGATTA_RANK:
|
||||
if (leaderboardName == null || leaderboardName.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName);
|
||||
result = leaderboard == null ? null : (double) leaderboard.getTotalRankOfCompetitor(competitor,
|
||||
timePoint);
|
||||
break;
|
||||
case OVERALL_RANK:
|
||||
if (leaderboardGroupName == null || leaderboardGroupName.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
final LeaderboardGroup group = getLeaderboardGroupByIdOrName(leaderboardGroupId, leaderboardGroupName);
|
||||
Leaderboard overall = group.getOverallLeaderboard();
|
||||
result = overall == null ? null : (double) overall.getTotalRankOfCompetitor(competitor, timePoint);
|
||||
break;
|
||||
case CHART_DISTANCE_TO_START_LINE:
|
||||
TimePoint startOfRace = trackedRace.getStartOfRace();
|
||||
if (startOfRace == null || timePoint.before(startOfRace) || timePoint.equals(startOfRace)) {
|
||||
Distance distanceToStartLine = trackedRace.getDistanceToStartLine(competitor, timePoint);
|
||||
result = distanceToStartLine == null ? null : distanceToStartLine.getMeters();
|
||||
}
|
||||
break;
|
||||
case CHART_BEAT_ANGLE:
|
||||
case CHART_ABS_TWA:
|
||||
Bearing twa = trackedRace.getTWA(competitor, timePoint, cache);
|
||||
result = twa == null ? null : twa.getDegrees();
|
||||
if (result != null && dataType == DetailType.CHART_ABS_TWA) {
|
||||
result = Math.abs(result);
|
||||
}
|
||||
break;
|
||||
case BRAVO_RACE_HEEL_IN_DEGREES:
|
||||
case BRAVO_LEG_CURRENT_HEEL_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getHeel, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVO_RACE_PITCH_IN_DEGREES:
|
||||
case BRAVO_LEG_CURRENT_PITCH_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getPitch, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVO_RACE_CURRENT_RIDE_HEIGHT_IN_METERS: {
|
||||
result = getBravoDistanceInMeters(BravoFixTrack::getRideHeight, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_PORT_DAGGERBOARD_RAKE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getPortDaggerboardRakeIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_STBD_DAGGERBOARD_RAKE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getStbdDaggerboardRakeStbdIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_PORT_RUDDER_RAKE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getPortRudderRakeIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_STBD_RUDDER_RAKE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getStbdRudderRakeIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_MAST_ROTATION_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getMastRotationIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_LEEWAY_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getLeewayIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_SET: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getSetIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_DRIFT_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getDriftIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_DEPTH_IN_METERS: {
|
||||
result = getBravoDistanceInMeters(BravoFixTrack::getDepthIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_RUDDER_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getRudderIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_TACK_ANGLE_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getTackAngleIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_DEFLECTOR_PERCENTAGE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getDeflectorPercentageIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_DEFLECTOR_IN_MILLIMETERS: {
|
||||
Double deflectorInMeters = getBravoDistanceInMeters(BravoFixTrack::getDeflectorIfAvailable, trackedRace, competitor, timePoint);
|
||||
result = deflectorInMeters == null ? null : (deflectorInMeters * 1000.);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_RAKE_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getRakeIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_TARGET_HEEL_ANGLE_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getTargetHeelIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_FORESTAY_LOAD: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getForestayLoadIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_FORESTAY_PRESSURE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getForestayPressureIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_TARGET_BOATSPEED_PERCENTAGE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getTargetBoatspeedPIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
|
||||
case EXPEDITION_RACE_AWA: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionAWAIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_AWS: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionAWSIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_BARO: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionBaroIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_BOAT_SPEED: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionBoatSpeedIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_COG: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionCOGIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_COURSE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionCourseDetailIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_DIST_TO_PORT_LAYLINE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistToPortLaylineIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_DIST_TO_STB_LAYLINE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistToStbLaylineIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_DISTANCE_BELOW_LINE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistanceBelowLineInMetersIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_DISTANCE_TO_COMMITTEE_BOAT: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistanceToCommitteeBoatIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_DISTANCE_TO_PIN: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistanceToPinDetailIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_FORESTAY_LOAD: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionForestayLoadIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_HEADING: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionHeadingIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_JIB_CAR_PORT: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionJibCarPortIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_JIB_CAR_STBD: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionJibCarStbdIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_LINE_SQUARE_FOR_WIND_DIRECTION: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionLineSquareForWindIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_LOAD_P: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionLoadPIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_LOAD_S: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionLoadSIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_MAST_BUTT: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionMastButtIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_RAKE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionRakeIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_RATE_OF_TURN: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionRateOfTurnIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_RUDDER_ANGLE: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getRudderIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_SOG: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionSOGIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TARG_BOAT_SPEED: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTargBoatSpeedIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TARG_TWA: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTargTWAIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TARGET_HEEL: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTargetHeelIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TIME_TO_BURN_TO_COMMITTEE_BOAT: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToBurnToCommitteeBoatIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TIME_TO_BURN_TO_LINE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToBurnToLineInSecondsIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TIME_TO_BURN_TO_PIN: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToBurnToPinIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TIME_TO_COMMITTEE_BOAT: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToCommitteeBoatIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TIME_TO_GUN: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToGunInSecondsIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TIME_TO_PIN: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToPinIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TIME_TO_PORT_LAYLINE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToPortLaylineIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TIME_TO_STB_LAYLINE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToStbLaylineIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TWA: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTWAIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TWD: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTWDIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TWS: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTWSIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_VMG: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionVMGIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_VMG_TARG_VMG_DELTA: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionVMGTargVMGDeltaIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new UnsupportedOperationException("There is currently no support for the enum value '" + dataType
|
||||
+ "' in this method.");
|
||||
}
|
||||
return result;
|
||||
} finally {
|
||||
trackedRace.unlockAfterRead(trackedRace.getMarkPassings(competitor));
|
||||
course.unlockAfterRead();
|
||||
}
|
||||
}
|
||||
|
||||
private Double getBravoDoubleValue(BiFunction<BravoFixTrack<Competitor>, TimePoint, Double> valueGetter,
|
||||
TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) {
|
||||
return getBravoValue(valueGetter, Function.identity(), trackedRace, competitor, timePoint);
|
||||
}
|
||||
|
||||
private Double getBravoBearingInDegrees(BiFunction<BravoFixTrack<Competitor>, TimePoint, Bearing> valueGetter,
|
||||
TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) {
|
||||
return getBravoValue(valueGetter, Bearing::getDegrees, trackedRace, competitor, timePoint);
|
||||
}
|
||||
|
||||
private Double getBravoDistanceInMeters(BiFunction<BravoFixTrack<Competitor>, TimePoint, Distance> valueGetter,
|
||||
TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) {
|
||||
return getBravoValue(valueGetter, Distance::getMeters, trackedRace, competitor, timePoint);
|
||||
}
|
||||
|
||||
private <T> Double getBravoValue(BiFunction<BravoFixTrack<Competitor>, TimePoint, T> valueGetter,
|
||||
Function<T, Double> mapperToDouble,
|
||||
TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) {
|
||||
final Double result;
|
||||
final BravoFixTrack<Competitor> bravoFixTrack = trackedRace
|
||||
.<BravoFix, BravoFixTrack<Competitor>> getSensorTrack(competitor, BravoFixTrack.TRACK_NAME);
|
||||
if (bravoFixTrack != null) {
|
||||
final T t = valueGetter.apply(bravoFixTrack, timePoint);
|
||||
result = t == null ? null : mapperToDouble.apply(t);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompetitorsRaceDataDTO getCompetitorsRaceData(RegattaAndRaceIdentifier race, List<CompetitorDTO> competitors, Date from, Date to,
|
||||
final long stepSizeInMillis, final DetailType detailType, final String leaderboardGroupName, final UUID leaderboardGroupId,
|
||||
@@ -3103,6 +2664,14 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
return result;
|
||||
}
|
||||
|
||||
public Double getCompetitorRaceDataEntry(DetailType detailType, TrackedRace trackedRace,
|
||||
Competitor competitor, TimePoint timePoint, String leaderboardGroupName,
|
||||
UUID leaderboardGroupId, String leaderboardName,
|
||||
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws NoWindException {
|
||||
return getService().getCompetitorRaceDataEntry(detailType, trackedRace, competitor, timePoint,
|
||||
getLeaderboardGroupByIdOrName(leaderboardGroupId, leaderboardGroupName), leaderboardName, cache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Triple<String, List<CompetitorDTO>, List<Double>>> getLeaderboardDataEntriesForAllRaceColumns(String leaderboardName,
|
||||
Date date, DetailType detailType) throws Exception {
|
||||
|
||||
+18
@@ -55,6 +55,8 @@ import com.sap.sailing.domain.common.CompetitorDescriptor;
|
||||
import com.sap.sailing.domain.common.CompetitorRegistrationType;
|
||||
import com.sap.sailing.domain.common.DataImportProgress;
|
||||
import com.sap.sailing.domain.common.DataImportSubProgress;
|
||||
import com.sap.sailing.domain.common.DetailType;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.RaceFetcher;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
@@ -102,6 +104,7 @@ import com.sap.sailing.domain.tracking.TrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
|
||||
import com.sap.sailing.domain.tracking.TrackerManager;
|
||||
import com.sap.sailing.domain.tracking.TrackingConnectorInfo;
|
||||
import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache;
|
||||
import com.sap.sailing.domain.tracking.WindStore;
|
||||
import com.sap.sailing.domain.tracking.WindTracker;
|
||||
import com.sap.sailing.server.operationaltransformation.RemoveEvent;
|
||||
@@ -1084,4 +1087,19 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
|
||||
String fleetName, Set<String> markIds);
|
||||
|
||||
Iterable<CompetitorProvider> getAllCompetitorProviders();
|
||||
|
||||
/**
|
||||
* @param leaderboardGroupId
|
||||
* if not {@code null}, this takes precedence over the {@code leaderboardGroupName} parameter which will
|
||||
* then be ignored and will be used to look up an optional leaderboard group providing the context, e.g.,
|
||||
* for seasonal scores from an overall leaderboard
|
||||
* @param leaderboardGroupName
|
||||
* evaluated only if {@code leaderboardGroupId} was {@code null}; may even be {@code null} if
|
||||
* {@code leaderboardGroupId} is {@code null} too because leaderboard group resolution is optional. If a
|
||||
* non-{@code null} name is provided here and if {@code leaderboardGroupId} was {@code null} then the
|
||||
* name is used to try to resolve the leaderboard group by name.
|
||||
*/
|
||||
Double getCompetitorRaceDataEntry(DetailType dataType, TrackedRace trackedRace, Competitor competitor,
|
||||
TimePoint timePoint, LeaderboardGroup leaderboardGroup, String leaderboardName,
|
||||
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws NoWindException;
|
||||
}
|
||||
@@ -12,6 +12,7 @@ Import-Package: com.sap.sailing.server.gateway.deserialization,
|
||||
javax.mail;version="1.4.0",
|
||||
javax.mail.internet;version="1.4.0",
|
||||
javax.mail.util;version="1.4.0",
|
||||
org.apache.commons.math;version="[2.1.0,3.0.0)",
|
||||
org.json.simple,
|
||||
org.json.simple.parser,
|
||||
org.osgi.framework;version="1.3.0",
|
||||
|
||||
+446
@@ -57,6 +57,8 @@ import javax.management.MalformedObjectNameException;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.commons.math.FunctionEvaluationException;
|
||||
import org.apache.commons.math.MaxIterationsExceededException;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authz.UnauthorizedException;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
@@ -139,9 +141,11 @@ import com.sap.sailing.domain.common.CompetitorDescriptor;
|
||||
import com.sap.sailing.domain.common.CompetitorRegistrationType;
|
||||
import com.sap.sailing.domain.common.DataImportProgress;
|
||||
import com.sap.sailing.domain.common.DataImportSubProgress;
|
||||
import com.sap.sailing.domain.common.DetailType;
|
||||
import com.sap.sailing.domain.common.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.common.LeaderboardType;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.RaceIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
@@ -149,6 +153,8 @@ import com.sap.sailing.domain.common.RegattaIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaName;
|
||||
import com.sap.sailing.domain.common.ScoreCorrectionProvider;
|
||||
import com.sap.sailing.domain.common.ScoringSchemeType;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.TackType;
|
||||
import com.sap.sailing.domain.common.TrackedRaceStatusEnum;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
@@ -166,6 +172,7 @@ import com.sap.sailing.domain.common.racelog.RacingProcedureType;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.DoesNotHaveRegattaLogException;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.MarkAlreadyUsedInRaceException;
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
import com.sap.sailing.domain.common.tracking.BravoFix;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.common.tracking.SensorFix;
|
||||
@@ -190,6 +197,7 @@ import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRul
|
||||
import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard;
|
||||
import com.sap.sailing.domain.markpassinghash.MarkPassingRaceFingerprint;
|
||||
import com.sap.sailing.domain.markpassinghash.MarkPassingRaceFingerprintRegistry;
|
||||
import com.sap.sailing.domain.orc.ORCPerformanceCurveRankingMetric;
|
||||
import com.sap.sailing.domain.persistence.DomainObjectFactory;
|
||||
import com.sap.sailing.domain.persistence.MongoObjectFactory;
|
||||
import com.sap.sailing.domain.persistence.MongoRaceLogStoreFactory;
|
||||
@@ -205,6 +213,8 @@ import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver;
|
||||
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
|
||||
import com.sap.sailing.domain.racelog.RaceLogStore;
|
||||
import com.sap.sailing.domain.racelog.tracking.SensorFixStore;
|
||||
import com.sap.sailing.domain.ranking.RankingMetric;
|
||||
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
|
||||
import com.sap.sailing.domain.ranking.RankingMetricConstructor;
|
||||
import com.sap.sailing.domain.regattalike.HasRegattaLike;
|
||||
import com.sap.sailing.domain.regattalike.IsRegattaLike;
|
||||
@@ -213,6 +223,7 @@ import com.sap.sailing.domain.regattalog.RegattaLogStore;
|
||||
import com.sap.sailing.domain.resultimport.ResultUrlProvider;
|
||||
import com.sap.sailing.domain.statistics.Statistics;
|
||||
import com.sap.sailing.domain.tracking.AddResult;
|
||||
import com.sap.sailing.domain.tracking.BravoFixTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet;
|
||||
import com.sap.sailing.domain.tracking.DynamicSensorFixTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
@@ -227,11 +238,14 @@ import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParameters;
|
||||
import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParametersHandler;
|
||||
import com.sap.sailing.domain.tracking.RaceTrackingHandler;
|
||||
import com.sap.sailing.domain.tracking.RaceTrackingHandler.DefaultRaceTrackingHandler;
|
||||
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
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.TrackingConnectorInfo;
|
||||
import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache;
|
||||
import com.sap.sailing.domain.tracking.WindPositionMode;
|
||||
import com.sap.sailing.domain.tracking.WindStore;
|
||||
import com.sap.sailing.domain.tracking.WindTracker;
|
||||
import com.sap.sailing.domain.tracking.WindTrackerFactory;
|
||||
@@ -316,9 +330,11 @@ import com.sap.sailing.server.tagging.TaggingServiceFactory;
|
||||
import com.sap.sailing.server.util.EventUtil;
|
||||
import com.sap.sailing.shared.server.SharedSailingData;
|
||||
import com.sap.sse.ServerInfo;
|
||||
import com.sap.sse.common.Bearing;
|
||||
import com.sap.sse.common.Distance;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.PairingListCreationException;
|
||||
import com.sap.sse.common.Speed;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.TypeBasedServiceFinder;
|
||||
import com.sap.sse.common.TypeBasedServiceFinderFactory;
|
||||
@@ -5433,4 +5449,434 @@ Replicator {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param leaderboardGroupId
|
||||
* if not {@code null}, this takes precedence over the {@code leaderboardGroupName} parameter which will
|
||||
* then be ignored and will be used to look up an optional leaderboard group providing the context, e.g.,
|
||||
* for seasonal scores from an overall leaderboard
|
||||
* @param leaderboardGroupName
|
||||
* evaluated only if {@code leaderboardGroupId} was {@code null}; may even be {@code null} if
|
||||
* {@code leaderboardGroupId} is {@code null} too because leaderboard group resolution is optional. If a
|
||||
* non-{@code null} name is provided here and if {@code leaderboardGroupId} was {@code null} then the
|
||||
* name is used to try to resolve the leaderboard group by name.
|
||||
*/
|
||||
@Override
|
||||
public Double getCompetitorRaceDataEntry(DetailType dataType, TrackedRace trackedRace, Competitor competitor,
|
||||
TimePoint timePoint, LeaderboardGroup leaderboardGroup, String leaderboardName,
|
||||
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws NoWindException {
|
||||
Double result = null;
|
||||
final Course course = trackedRace.getRace().getCourse();
|
||||
course.lockForRead(); // make sure the tracked leg survives this call even if a course update is pending
|
||||
trackedRace.lockForRead(trackedRace.getMarkPassings(competitor));
|
||||
try {
|
||||
final TrackedLegOfCompetitor trackedLeg = trackedRace.getTrackedLeg(competitor, timePoint);
|
||||
switch (dataType) {
|
||||
case LEG_TACKTYPE_LONGTACK_SHORTTACK:
|
||||
final TackType tackType;
|
||||
if (trackedLeg != null && (tackType = trackedLeg.getTackType(timePoint, cache)) != null ) {
|
||||
result = tackType==TackType.LONGTACK ? 1.0 : -1.0;
|
||||
} else {
|
||||
// trackedLeg == null || tackType == null;
|
||||
result = 0.0;
|
||||
}
|
||||
break;
|
||||
case RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS:
|
||||
final GPSFixTrack<Competitor, GPSFixMoving> sogTrack = trackedRace.getTrack(competitor);
|
||||
if (sogTrack != null) {
|
||||
SpeedWithBearing speedOverGround = sogTrack.getEstimatedSpeed(timePoint);
|
||||
result = (speedOverGround == null) ? null : speedOverGround.getKnots();
|
||||
}
|
||||
break;
|
||||
case RACE_CURRENT_COURSE_OVER_GROUND_IN_TRUE_DEGREES:
|
||||
case CHART_COURSE_OVER_GROUND_TRUE_DEGREES:
|
||||
final GPSFixTrack<Competitor, GPSFixMoving> cogTrack = trackedRace.getTrack(competitor);
|
||||
if (cogTrack != null) {
|
||||
SpeedWithBearing speedOverGround = cogTrack.getEstimatedSpeed(timePoint);
|
||||
result = (speedOverGround == null) ? null : speedOverGround.getBearing().getDegrees();
|
||||
}
|
||||
break;
|
||||
case RACE_CURRENT_POSITION_LAT_DEG:
|
||||
final GPSFixTrack<Competitor, GPSFixMoving> latTrack = trackedRace.getTrack(competitor);
|
||||
if (latTrack != null) {
|
||||
Position position = latTrack.getEstimatedPosition(timePoint, /* extrapolate */ true);
|
||||
result = (position == null) ? null : position.getLatDeg();
|
||||
}
|
||||
break;
|
||||
case RACE_CURRENT_POSITION_LNG_DEG:
|
||||
final GPSFixTrack<Competitor, GPSFixMoving> lngTrack = trackedRace.getTrack(competitor);
|
||||
if (lngTrack != null) {
|
||||
Position position = lngTrack.getEstimatedPosition(timePoint, /* extrapolate */ true);
|
||||
result = (position == null) ? null : position.getLngDeg();
|
||||
}
|
||||
break;
|
||||
case LEG_VELOCITY_MADE_GOOD_IN_KNOTS:
|
||||
final Speed velocityMadeGood;
|
||||
if (trackedLeg != null) {
|
||||
velocityMadeGood = trackedLeg.getVelocityMadeGood(timePoint, WindPositionMode.EXACT, cache);
|
||||
} else {
|
||||
// check if wind information is available; if so, compute a VMG only based on wind data:
|
||||
velocityMadeGood = trackedRace.getVelocityMadeGood(competitor, timePoint, cache);
|
||||
}
|
||||
result = (velocityMadeGood == null) ? null : velocityMadeGood.getKnots();
|
||||
break;
|
||||
case LEG_DISTANCE_TRAVELED:
|
||||
if (trackedLeg != null) {
|
||||
Distance distanceTraveled = trackedRace.getDistanceTraveled(competitor, timePoint);
|
||||
result = distanceTraveled == null ? null : distanceTraveled.getMeters();
|
||||
}
|
||||
break;
|
||||
case LEG_DISTANCE_TRAVELED_INCLUDING_GATE_START:
|
||||
if (trackedLeg != null) {
|
||||
Distance distanceTraveledConsideringGateStart = trackedRace.getDistanceTraveledIncludingGateStart(competitor, timePoint);
|
||||
result = distanceTraveledConsideringGateStart == null ? null : distanceTraveledConsideringGateStart.getMeters();
|
||||
}
|
||||
break;
|
||||
case LEG_GAP_TO_LEADER_IN_SECONDS:
|
||||
if (trackedLeg != null) {
|
||||
final RankingInfo rankingInfo = trackedRace.getRankingMetric().getRankingInfo(timePoint, cache);
|
||||
final Duration gapToLeaderInOwnTime = trackedLeg.getTrackedLeg().getTrackedRace().getRankingMetric().getGapToLeaderInOwnTime(rankingInfo, competitor, cache);
|
||||
result = gapToLeaderInOwnTime == null ? null : gapToLeaderInOwnTime.asSeconds();
|
||||
}
|
||||
break;
|
||||
case CHART_WINDWARD_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD:
|
||||
if (trackedLeg != null) {
|
||||
final RankingInfo rankingInfo = trackedRace.getRankingMetric().getRankingInfo(timePoint, cache);
|
||||
Distance distanceToLeader = trackedLeg.getWindwardDistanceToCompetitorFarthestAhead(timePoint, WindPositionMode.LEG_MIDDLE, rankingInfo, cache);
|
||||
result = (distanceToLeader == null) ? null : distanceToLeader.getMeters();
|
||||
}
|
||||
break;
|
||||
case RACE_IMPLIED_WIND:
|
||||
final RankingMetric rankingMetric = trackedRace.getRankingMetric();
|
||||
if (rankingMetric instanceof ORCPerformanceCurveRankingMetric) {
|
||||
final ORCPerformanceCurveRankingMetric orcPcsRankingMetric =
|
||||
(ORCPerformanceCurveRankingMetric) rankingMetric;
|
||||
try {
|
||||
final Speed impliedWind = orcPcsRankingMetric.getImpliedWind(competitor, timePoint, cache);
|
||||
result = impliedWind == null ? null : impliedWind.getKnots();
|
||||
} catch (MaxIterationsExceededException | FunctionEvaluationException e) {
|
||||
logger.log(Level.WARNING, "Problem computing implied wind", e);
|
||||
result = null;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RACE_RANK:
|
||||
if (trackedLeg != null) {
|
||||
result = (double) trackedLeg.getRank(timePoint, cache);
|
||||
}
|
||||
break;
|
||||
case REGATTA_RANK:
|
||||
if (leaderboardName == null || leaderboardName.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
Leaderboard leaderboard = getLeaderboardByName(leaderboardName);
|
||||
result = leaderboard == null ? null : (double) leaderboard.getTotalRankOfCompetitor(competitor,
|
||||
timePoint);
|
||||
break;
|
||||
case OVERALL_RANK:
|
||||
if (leaderboardGroup == null) {
|
||||
break;
|
||||
}
|
||||
Leaderboard overall = leaderboardGroup.getOverallLeaderboard();
|
||||
result = overall == null ? null : (double) overall.getTotalRankOfCompetitor(competitor, timePoint);
|
||||
break;
|
||||
case CHART_DISTANCE_TO_START_LINE:
|
||||
TimePoint startOfRace = trackedRace.getStartOfRace();
|
||||
if (startOfRace == null || timePoint.before(startOfRace) || timePoint.equals(startOfRace)) {
|
||||
Distance distanceToStartLine = trackedRace.getDistanceToStartLine(competitor, timePoint);
|
||||
result = distanceToStartLine == null ? null : distanceToStartLine.getMeters();
|
||||
}
|
||||
break;
|
||||
case CHART_BEAT_ANGLE:
|
||||
case CHART_ABS_TWA:
|
||||
Bearing twa = trackedRace.getTWA(competitor, timePoint, cache);
|
||||
result = twa == null ? null : twa.getDegrees();
|
||||
if (result != null && dataType == DetailType.CHART_ABS_TWA) {
|
||||
result = Math.abs(result);
|
||||
}
|
||||
break;
|
||||
case BRAVO_RACE_HEEL_IN_DEGREES:
|
||||
case BRAVO_LEG_CURRENT_HEEL_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getHeel, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVO_RACE_PITCH_IN_DEGREES:
|
||||
case BRAVO_LEG_CURRENT_PITCH_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getPitch, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVO_RACE_CURRENT_RIDE_HEIGHT_IN_METERS: {
|
||||
result = getBravoDistanceInMeters(BravoFixTrack::getRideHeight, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_PORT_DAGGERBOARD_RAKE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getPortDaggerboardRakeIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_STBD_DAGGERBOARD_RAKE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getStbdDaggerboardRakeStbdIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_PORT_RUDDER_RAKE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getPortRudderRakeIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_STBD_RUDDER_RAKE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getStbdRudderRakeIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_MAST_ROTATION_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getMastRotationIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_LEEWAY_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getLeewayIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_SET: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getSetIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_DRIFT_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getDriftIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_DEPTH_IN_METERS: {
|
||||
result = getBravoDistanceInMeters(BravoFixTrack::getDepthIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_RUDDER_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getRudderIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_TACK_ANGLE_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getTackAngleIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_DEFLECTOR_PERCENTAGE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getDeflectorPercentageIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_DEFLECTOR_IN_MILLIMETERS: {
|
||||
Double deflectorInMeters = getBravoDistanceInMeters(BravoFixTrack::getDeflectorIfAvailable, trackedRace, competitor, timePoint);
|
||||
result = deflectorInMeters == null ? null : (deflectorInMeters * 1000.);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_RAKE_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getRakeIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_TARGET_HEEL_ANGLE_IN_DEGREES: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getTargetHeelIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_FORESTAY_LOAD: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getForestayLoadIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_FORESTAY_PRESSURE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getForestayPressureIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case BRAVOEXTENDED_RACE_CURRENT_TARGET_BOATSPEED_PERCENTAGE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getTargetBoatspeedPIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
|
||||
case EXPEDITION_RACE_AWA: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionAWAIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_AWS: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionAWSIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_BARO: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionBaroIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_BOAT_SPEED: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionBoatSpeedIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_COG: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionCOGIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_COURSE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionCourseDetailIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_DIST_TO_PORT_LAYLINE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistToPortLaylineIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_DIST_TO_STB_LAYLINE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistToStbLaylineIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_DISTANCE_BELOW_LINE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistanceBelowLineInMetersIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_DISTANCE_TO_COMMITTEE_BOAT: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistanceToCommitteeBoatIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_DISTANCE_TO_PIN: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionDistanceToPinDetailIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_FORESTAY_LOAD: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionForestayLoadIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_HEADING: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionHeadingIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_JIB_CAR_PORT: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionJibCarPortIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_JIB_CAR_STBD: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionJibCarStbdIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_LINE_SQUARE_FOR_WIND_DIRECTION: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionLineSquareForWindIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_LOAD_P: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionLoadPIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_LOAD_S: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionLoadSIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_MAST_BUTT: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionMastButtIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_RAKE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionRakeIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_RATE_OF_TURN: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionRateOfTurnIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_RUDDER_ANGLE: {
|
||||
result = getBravoBearingInDegrees(BravoFixTrack::getRudderIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_SOG: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionSOGIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TARG_BOAT_SPEED: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTargBoatSpeedIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TARG_TWA: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTargTWAIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TARGET_HEEL: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTargetHeelIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TIME_TO_BURN_TO_COMMITTEE_BOAT: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToBurnToCommitteeBoatIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TIME_TO_BURN_TO_LINE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToBurnToLineInSecondsIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TIME_TO_BURN_TO_PIN: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToBurnToPinIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TIME_TO_COMMITTEE_BOAT: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToCommitteeBoatIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TIME_TO_GUN: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToGunInSecondsIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TIME_TO_PIN: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToPinIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TIME_TO_PORT_LAYLINE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToPortLaylineIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TIME_TO_STB_LAYLINE: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTimeToStbLaylineIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TWA: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTWAIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TWD: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTWDIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_TWS: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionTWSIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_VMG: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionVMGIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
case EXPEDITION_RACE_VMG_TARG_VMG_DELTA: {
|
||||
result = getBravoDoubleValue(BravoFixTrack::getExpeditionVMGTargVMGDeltaIfAvailable, trackedRace, competitor, timePoint);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new UnsupportedOperationException("There is currently no support for the enum value '" + dataType
|
||||
+ "' in this method.");
|
||||
}
|
||||
return result;
|
||||
} finally {
|
||||
trackedRace.unlockAfterRead(trackedRace.getMarkPassings(competitor));
|
||||
course.unlockAfterRead();
|
||||
}
|
||||
}
|
||||
|
||||
private Double getBravoDoubleValue(BiFunction<BravoFixTrack<Competitor>, TimePoint, Double> valueGetter,
|
||||
TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) {
|
||||
return getBravoValue(valueGetter, Function.identity(), trackedRace, competitor, timePoint);
|
||||
}
|
||||
|
||||
private Double getBravoBearingInDegrees(BiFunction<BravoFixTrack<Competitor>, TimePoint, Bearing> valueGetter,
|
||||
TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) {
|
||||
return getBravoValue(valueGetter, Bearing::getDegrees, trackedRace, competitor, timePoint);
|
||||
}
|
||||
|
||||
private Double getBravoDistanceInMeters(BiFunction<BravoFixTrack<Competitor>, TimePoint, Distance> valueGetter,
|
||||
TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) {
|
||||
return getBravoValue(valueGetter, Distance::getMeters, trackedRace, competitor, timePoint);
|
||||
}
|
||||
|
||||
private <T> Double getBravoValue(BiFunction<BravoFixTrack<Competitor>, TimePoint, T> valueGetter,
|
||||
Function<T, Double> mapperToDouble,
|
||||
TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) {
|
||||
final Double result;
|
||||
final BravoFixTrack<Competitor> bravoFixTrack = trackedRace
|
||||
.<BravoFix, BravoFixTrack<Competitor>> getSensorTrack(competitor, BravoFixTrack.TRACK_NAME);
|
||||
if (bravoFixTrack != null) {
|
||||
final T t = valueGetter.apply(bravoFixTrack, timePoint);
|
||||
result = t == null ? null : mapperToDouble.apply(t);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user