diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/DetailType.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/DetailType.java index 7ffada87c7e..d3e24db6872 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/DetailType.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/DetailType.java @@ -100,6 +100,9 @@ public enum DetailType implements Serializable { OVERALL_TOTAL_DURATION_FOILED_IN_SECONDS(0, DESCENDING, "TOTAL_DURATION_FOILED_IN_SECONDS"), OVERALL_TOTAL_DISTANCE_FOILED_IN_METERS(0, DESCENDING, "TOTAL_DISTANCE_FOILED_IN_METERS"), RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS(2, DESCENDING), + RACE_CURRENT_COURSE_OVER_GROUND_IN_TRUE_DEGREES(1, ASCENDING), + RACE_CURRENT_POSITION_LAT_DEG(10, ASCENDING), + RACE_CURRENT_POSITION_LNG_DEG(10, ASCENDING), BRAVO_RACE_CURRENT_RIDE_HEIGHT_IN_METERS(2, DESCENDING), RACE_CURRENT_DISTANCE_FOILED_IN_METERS(0, DESCENDING), RACE_CURRENT_DURATION_FOILED_IN_SECONDS(0, DESCENDING), diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DetailTypeFormatter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DetailTypeFormatter.java index f7f8c563fcf..d0919e2b2af 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DetailTypeFormatter.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DetailTypeFormatter.java @@ -40,6 +40,12 @@ public class DetailTypeFormatter { return stringMessages.currentOrAverageSpeedOverGroundInKnots(); case RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS: return stringMessages.currentSpeedOverGroundInKnots(); + case RACE_CURRENT_COURSE_OVER_GROUND_IN_TRUE_DEGREES: + return stringMessages.courseOverGroundTrueDegrees(); + case RACE_CURRENT_POSITION_LAT_DEG: + return stringMessages.latitude(); + case RACE_CURRENT_POSITION_LNG_DEG: + return stringMessages.longitude(); case BRAVO_LEG_CURRENT_RIDE_HEIGHT_IN_METERS: return stringMessages.currentOrAverageRideHeightInMeters(); case BRAVOEXTENDED_LEG_CURRENT_DISTANCE_FOILED_IN_METERS: @@ -433,6 +439,9 @@ public class DetailTypeFormatter { return stringMessages.millimetersUnit(); case CHART_COURSE_OVER_GROUND_TRUE_DEGREES: + case RACE_CURRENT_COURSE_OVER_GROUND_IN_TRUE_DEGREES: + case RACE_CURRENT_POSITION_LAT_DEG: + case RACE_CURRENT_POSITION_LNG_DEG: case BRAVO_LEG_CURRENT_HEEL_IN_DEGREES: case BRAVO_LEG_CURRENT_PITCH_IN_DEGREES: case BRAVOEXTENDED_RACE_CURRENT_MAST_ROTATION_IN_DEGREES: @@ -657,6 +666,12 @@ public class DetailTypeFormatter { return stringMessages.currentOrAverageSpeedOverGroundInKnotsTooltip(); case RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS: return stringMessages.currentSpeedOverGroundInKnotsTooltip(); + case RACE_CURRENT_COURSE_OVER_GROUND_IN_TRUE_DEGREES: + return stringMessages.courseOverGroundTrueDegreesTooltip(); + case RACE_CURRENT_POSITION_LAT_DEG: + return stringMessages.currentPositionLatitudeTooltip(); + case RACE_CURRENT_POSITION_LNG_DEG: + return stringMessages.currentPositionLongitudeTooltip(); case BRAVO_LEG_CURRENT_RIDE_HEIGHT_IN_METERS: return stringMessages.currentOrAverageRideHeightInMetersTooltip(); case BRAVOEXTENDED_LEG_CURRENT_DISTANCE_FOILED_IN_METERS: diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index 57212b08eca..4def3ca14a3 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -2328,6 +2328,8 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String errorWhileLoadingUserSettings(String errorMessage); String certificates(); String dataBy(); + String currentPositionLatitudeTooltip(); + String currentPositionLongitudeTooltip(); String courseCreation(); String filterMarkTemplateByName(); String markTemplates(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index 0d81b7331e4..5c07e17b2d6 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -2331,6 +2331,8 @@ orcPerformanceCurveLegTypeDescriptionWindwardLeewardRealLive=Windward/Leeward (u errorWhileLoadingUserSettings=Error while loading user settings: {0} certificates=Certificates dataBy=Data by +currentPositionLatitudeTooltip=Latitude of position in degrees (positive values denote northern hemisphere, negative values denote southern hemisphere) +currentPositionLongitudeTooltip=Longitude of position in degrees (positive values denote east, negative values denote west) courseCreation=Course Creation filterMarkTemplateByName=Filter mark templates markTemplates=Mark Templates diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties old mode 100644 new mode 100755 index 8dae7d346de..32a6c502ce7 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -2346,6 +2346,8 @@ orcPerformanceCurveLegs=ORC Performance Curve Bahnschenkel errorAssigningCertificates=Beim Zuweisen von Messbriefen zu Booten ist ein Fehler aufgetreten: {0} certificates=Messbriefe dataBy=Daten von +currentPositionLatitudeTooltip=Geographische Breite der Position in Grad (positive Werte bezeichnen nördliche Breite, negative Werte südliche Breite) +currentPositionLongitudeTooltip=Geographische Länge der Position in Grad (positive Werte bezeichnen östliche Länge, negative Werte westliche Länge) courseCreation=Kurserstellung filterMarkTemplateByName=Bahnmarkenvorlagen filter markTemplates=Bahnmarkenvorlagen diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index 07dd555303d..b51bf3e0067 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -3538,6 +3538,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet 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 cogTrack = trackedRace.getTrack(competitor); if (cogTrack != null) { @@ -3545,6 +3546,20 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet result = (speedOverGround == null) ? null : speedOverGround.getBearing().getDegrees(); } break; + case RACE_CURRENT_POSITION_LAT_DEG: + final GPSFixTrack 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 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) { diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResourceV2.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResourceV2.java index 299f73f946c..f12527124ce 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResourceV2.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResourceV2.java @@ -33,6 +33,8 @@ import com.sap.sailing.domain.common.DetailType; import com.sap.sailing.domain.common.ManeuverType; 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.SpeedWithBearing; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.FleetDTO; @@ -41,14 +43,18 @@ import com.sap.sailing.domain.common.dto.LeaderboardEntryDTO; import com.sap.sailing.domain.common.dto.LeaderboardRowDTO; import com.sap.sailing.domain.common.dto.LegEntryDTO; import com.sap.sailing.domain.common.sharding.ShardingType; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.sharding.ShardingContext; +import com.sap.sailing.domain.tracking.GPSFixTrack; +import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sse.InvalidDateException; import com.sap.sse.common.Distance; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; +import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.security.shared.HasPermissions.DefaultActions; import com.sap.sse.security.shared.impl.SecuredSecurityTypes; @@ -243,7 +249,12 @@ public class LeaderboardsResourceV2 extends AbstractLeaderboardsResource { JSONObject jsonRaceDetails = new JSONObject(); jsonEntry.put("data", jsonRaceDetails); for (DetailType type : raceDetailsToShow) { - Pair valueForRaceDetailType = getValueForRaceDetailType(type, leaderboardRowDTO, leaderboardEntry, currentLegEntry); + final RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + final Competitor c = getService().getCompetitorAndBoatStore().getExistingCompetitorByIdAsString(competitor.getIdAsString()); + final TrackedRace trackedRace = c == null || raceColumn == null ? null : raceColumn.getTrackedRace(c); + Pair valueForRaceDetailType = getValueForRaceDetailType(type, + leaderboardRowDTO, leaderboardEntry, currentLegEntry, trackedRace, raceColumn, + c, new MillisecondsTimePoint(leaderboardDTO.getTimePoint())); if (valueForRaceDetailType != null && valueForRaceDetailType.getA() != null && valueForRaceDetailType.getB() != null) { jsonRaceDetails.put(valueForRaceDetailType.getA(), valueForRaceDetailType.getB()); } @@ -295,6 +306,9 @@ public class LeaderboardsResourceV2 extends AbstractLeaderboardsResource { DetailType.RACE_DISTANCE_TRAVELED, DetailType.RACE_TIME_TRAVELED, DetailType.RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS, + DetailType.RACE_CURRENT_COURSE_OVER_GROUND_IN_TRUE_DEGREES, + DetailType.RACE_CURRENT_POSITION_LAT_DEG, + DetailType.RACE_CURRENT_POSITION_LNG_DEG, DetailType.RACE_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD_IN_METERS, DetailType.NUMBER_OF_MANEUVERS, DetailType.RACE_CURRENT_LEG, @@ -305,7 +319,9 @@ public class LeaderboardsResourceV2 extends AbstractLeaderboardsResource { return new DetailType[] { DetailType.OVERALL_MAXIMUM_SPEED_OVER_GROUND_IN_KNOTS }; } - private Pair getValueForRaceDetailType(DetailType type, LeaderboardRowDTO leaderboardRowDTO, LeaderboardEntryDTO entry, LegEntryDTO currentLegEntry) { + private Pair getValueForRaceDetailType(DetailType type, LeaderboardRowDTO leaderboardRowDTO, + LeaderboardEntryDTO entry, LegEntryDTO currentLegEntry, TrackedRace trackedRace, RaceColumn raceColumn, + Competitor competitor, TimePoint timePoint) { String name; Object value = null; Pair result = null; @@ -350,6 +366,42 @@ public class LeaderboardsResourceV2 extends AbstractLeaderboardsResource { value = roundDouble(currentLegEntry.currentSpeedOverGroundInKnots, 2); } break; + case RACE_CURRENT_COURSE_OVER_GROUND_IN_TRUE_DEGREES: + name = "currentCourseOverGround-deg"; + if (trackedRace != null) { + final GPSFixTrack track = trackedRace.getTrack(competitor); + if (track != null) { + final SpeedWithBearing speed = track.getEstimatedSpeed(timePoint); + if (speed != null) { + value = roundDouble(speed.getBearing().getDegrees(), 2); + } + } + } + break; + case RACE_CURRENT_POSITION_LAT_DEG: + name = "currentPositionLatitude-deg"; + if (trackedRace != null) { + final GPSFixTrack track = trackedRace.getTrack(competitor); + if (track != null) { + final Position position = track.getEstimatedPosition(timePoint, /* extrapolated */ true); + if (position != null) { + value = roundDouble(position.getLatDeg(), 10); + } + } + } + break; + case RACE_CURRENT_POSITION_LNG_DEG: + name = "currentPositionLongitude-deg"; + if (trackedRace != null) { + final GPSFixTrack track = trackedRace.getTrack(competitor); + if (track != null) { + final Position position = track.getEstimatedPosition(timePoint, /* extrapolated */ true); + if (position != null) { + value = roundDouble(position.getLngDeg(), 10); + } + } + } + break; case NUMBER_OF_MANEUVERS: name = "numberOfManeuvers"; Integer numberOfManeuvers = null;