mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-21 03:30:12 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
5ef2631380
5 files changed
+128
-112
No files matched your search
+2
@@ -857,6 +857,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
DBCollection windTracks = database.getCollection(CollectionNames.WIND_TRACKS.name());
|
||||
ensureIndicesOnWindTracks(windTracks);
|
||||
BasicDBObject queryById = new BasicDBObject();
|
||||
// the default query is by the RACE_ID key:
|
||||
queryById.put(FieldNames.RACE_ID.name(), race.getId());
|
||||
if (constrainToWindSource != null) {
|
||||
queryById.put(FieldNames.WIND_SOURCE_NAME.name(), constrainToWindSource.name());
|
||||
@@ -864,6 +865,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
for (DBObject dbWind : windTracks.find(queryById)) {
|
||||
loadWindFix(result, dbWind, millisecondsOverWhichToAverageWind);
|
||||
}
|
||||
// Additionally check for legacy wind fixes stored with the old EVENT_NAME key; if any are found, migrate them
|
||||
BasicDBObject queryByName = new BasicDBObject();
|
||||
queryByName.put(FieldNames.EVENT_NAME.name(), regattaName);
|
||||
queryByName.put(FieldNames.RACE_NAME.name(), race.getName());
|
||||
|
||||
+2
-4
@@ -617,10 +617,8 @@ public class TrackBasedEstimationWindTrackImpl extends VirtualWindTrackImpl {
|
||||
private void invalidateForNewWind(Wind wind, WindSource windSource) {
|
||||
WindTrack windTrack = getTrackedRace().getOrCreateWindTrack(windSource);
|
||||
// check what the next fixes before and after the one affected are; if they are further than the
|
||||
// averagingInterval
|
||||
// away, extend the invalidation interval accordingly because the entire span up to the next fix may be
|
||||
// influenced
|
||||
// by adding/removing a fix in a sparsely occupied track. See
|
||||
// averagingInterval away, extend the invalidation interval accordingly because the entire span up
|
||||
// to the next fix may be influenced by adding/removing a fix in a sparsely occupied track. See
|
||||
// WindTrackImpl.getAveragedWindUnsynchronized(Position p, TimePoint at)
|
||||
long averagingInterval = getTrackedRace().getMillisecondsOverWhichToAverageWind();
|
||||
final TimePoint timePoint = wind.getTimePoint();
|
||||
|
||||
+12
-6
@@ -1249,13 +1249,19 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
DummyMarkPassingWithTimePointOnly markPassingTimePoint = new DummyMarkPassingWithTimePointOnly(timePoint);
|
||||
TrackedLegOfCompetitor result = null;
|
||||
if (!competitorMarkPassings.isEmpty()) {
|
||||
MarkPassing lastMarkPassingAtOfBeforeTimePoint = competitorMarkPassings.floor(markPassingTimePoint);
|
||||
if (lastMarkPassingAtOfBeforeTimePoint != null) {
|
||||
Waypoint waypointPassedLastAtOrBeforeTimePoint = lastMarkPassingAtOfBeforeTimePoint.getWaypoint();
|
||||
// don't return a leg if competitor has already finished last leg and therefore the race
|
||||
if (waypointPassedLastAtOrBeforeTimePoint != getRace().getCourse().getLastWaypoint()) {
|
||||
result = getTrackedLegStartingAt(waypointPassedLastAtOrBeforeTimePoint).getTrackedLeg(competitor);
|
||||
final Course course = getRace().getCourse();
|
||||
course.lockForRead();
|
||||
try {
|
||||
MarkPassing lastMarkPassingAtOfBeforeTimePoint = competitorMarkPassings.floor(markPassingTimePoint);
|
||||
if (lastMarkPassingAtOfBeforeTimePoint != null) {
|
||||
Waypoint waypointPassedLastAtOrBeforeTimePoint = lastMarkPassingAtOfBeforeTimePoint.getWaypoint();
|
||||
// don't return a leg if competitor has already finished last leg and therefore the race
|
||||
if (waypointPassedLastAtOrBeforeTimePoint != course.getLastWaypoint()) {
|
||||
result = getTrackedLegStartingAt(waypointPassedLastAtOrBeforeTimePoint).getTrackedLeg(competitor);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
course.unlockAfterRead();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
+1
-1
@@ -1605,7 +1605,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
}
|
||||
Wind wind = new WindImpl(p, at, speedWithBearing);
|
||||
Iterable<WindSource> webWindSources = trackedRace.getWindSources(WindSourceType.WEB);
|
||||
if(Util.size(webWindSources) == 0) {
|
||||
if (Util.size(webWindSources) == 0) {
|
||||
// create a new WEB wind source if not available
|
||||
trackedRace.recordWind(wind, new WindSourceImpl(WindSourceType.WEB));
|
||||
} else {
|
||||
|
||||
+111
-101
@@ -724,109 +724,119 @@ public class RegattasResource extends AbstractSailingServerResource {
|
||||
.getStartOfRace().asMillis());
|
||||
|
||||
JSONArray jsonLegs = new JSONArray();
|
||||
for (TrackedLeg leg : trackedRace.getTrackedLegs()) {
|
||||
JSONObject jsonLeg = new JSONObject();
|
||||
jsonLeg.put("from", leg.getLeg().getFrom().getName());
|
||||
jsonLeg.put("fromWaypointId", leg.getLeg().getFrom().getId());
|
||||
jsonLeg.put("to", leg.getLeg().getTo().getName());
|
||||
jsonLeg.put("toWaypointId", leg.getLeg().getTo().getId());
|
||||
try {
|
||||
jsonLeg.put("upOrDownwindLeg", leg.isUpOrDownwindLeg(timePoint));
|
||||
} catch (NoWindException e) {
|
||||
// no wind, then it's simply no upwind or downwind leg
|
||||
jsonLeg.put("upOrDownwindLeg", "false");
|
||||
}
|
||||
JSONArray jsonCompetitors = new JSONArray();
|
||||
Map<Competitor, Integer> ranks = leg.getRanks(timePoint);
|
||||
for (Competitor competitor : trackedRace.getRace().getCompetitors()) {
|
||||
JSONObject jsonCompetitorInLeg = new JSONObject();
|
||||
TrackedLegOfCompetitor trackedLegOfCompetitor = leg.getTrackedLeg(competitor);
|
||||
if (trackedLegOfCompetitor != null) {
|
||||
jsonCompetitorInLeg.put("id", competitor.getId() != null ? competitor.getId().toString()
|
||||
: null);
|
||||
jsonCompetitorInLeg.put("name", competitor.getName());
|
||||
jsonCompetitorInLeg.put("sailNumber", competitor.getBoat().getSailID());
|
||||
jsonCompetitorInLeg.put("color", competitor.getColor() != null ? competitor.getColor()
|
||||
.getAsHtml() : null);
|
||||
|
||||
Speed averageSpeedOverGround = trackedLegOfCompetitor.getAverageSpeedOverGround(timePoint);
|
||||
if (averageSpeedOverGround != null) {
|
||||
jsonCompetitorInLeg.put("averageSOG-kts", UnitSerializationUtil.knotsDecimalFormatter
|
||||
.format(averageSpeedOverGround.getKnots()));
|
||||
}
|
||||
try {
|
||||
Integer numberOfTacks = trackedLegOfCompetitor.getNumberOfTacks(timePoint, /* waitForLatest */
|
||||
false);
|
||||
Integer numberOfJibes = trackedLegOfCompetitor.getNumberOfJibes(timePoint, /* waitForLatest */
|
||||
false);
|
||||
Integer numberOfPenaltyCircles = trackedLegOfCompetitor.getNumberOfPenaltyCircles(
|
||||
timePoint, /* waitForLatest */false);
|
||||
jsonCompetitorInLeg.put("tacks", numberOfTacks);
|
||||
jsonCompetitorInLeg.put("jibes", numberOfJibes);
|
||||
jsonCompetitorInLeg.put("penaltyCircles", numberOfPenaltyCircles);
|
||||
} catch (NoWindException e) {
|
||||
logger.log(Level.FINE,
|
||||
"No wind information while trying to determing maneuvers for competitor "
|
||||
+ competitor.getName(), e);
|
||||
}
|
||||
|
||||
TimePoint startTime = trackedLegOfCompetitor.getStartTime();
|
||||
TimePoint finishTime = trackedLegOfCompetitor.getFinishTime();
|
||||
TimePoint startOfRace = trackedRace.getStartOfRace();
|
||||
// between the start of the race and the start of the first leg we have no 'timeSinceGun'
|
||||
// for the competitor
|
||||
if (startOfRace != null && startTime != null) {
|
||||
long timeSinceGun = -1;
|
||||
if (finishTime != null) {
|
||||
timeSinceGun = finishTime.asMillis() - startOfRace.asMillis();
|
||||
} else {
|
||||
timeSinceGun = timePoint.asMillis() - startOfRace.asMillis();
|
||||
}
|
||||
if (timeSinceGun > 0) {
|
||||
jsonCompetitorInLeg.put("timeSinceGun-ms", timeSinceGun);
|
||||
}
|
||||
Distance distanceSinceGun = trackedRace.getTrack(competitor).getDistanceTraveled(
|
||||
startOfRace, finishTime != null ? finishTime : timePoint);
|
||||
if (distanceSinceGun != null) {
|
||||
jsonCompetitorInLeg.put("distanceSinceGun-m", distanceSinceGun.getMeters());
|
||||
}
|
||||
}
|
||||
|
||||
Distance distanceTraveled = trackedLegOfCompetitor.getDistanceTraveled(timePoint);
|
||||
if (distanceTraveled != null) {
|
||||
jsonCompetitorInLeg.put("distanceTraveled-m",
|
||||
UnitSerializationUtil.distanceDecimalFormatter.format(distanceTraveled
|
||||
.getMeters()));
|
||||
}
|
||||
Distance distanceTraveledIncludingGateStart = trackedLegOfCompetitor.getDistanceTraveledConsideringGateStart(timePoint);
|
||||
if (distanceTraveledIncludingGateStart != null) {
|
||||
jsonCompetitorInLeg.put("distanceTraveledIncludingGateStart-m",
|
||||
UnitSerializationUtil.distanceDecimalFormatter
|
||||
.format(distanceTraveledIncludingGateStart.getMeters()));
|
||||
}
|
||||
try {
|
||||
Integer rank = ranks.get(competitor);
|
||||
jsonCompetitorInLeg.put("rank", rank);
|
||||
} catch (RuntimeException re) {
|
||||
if (re.getCause() != null && re.getCause() instanceof NoWindException) {
|
||||
// well, we don't know the wind direction, so we can't compute a ranking
|
||||
} else {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
try {
|
||||
jsonCompetitorInLeg.put("gapToLeader-s", trackedLegOfCompetitor
|
||||
.getGapToLeaderInSeconds(timePoint, WindPositionMode.LEG_MIDDLE));
|
||||
} catch (NoWindException e1) {
|
||||
// well, we don't know the wind direction... then no gap to leader will be shown...
|
||||
}
|
||||
jsonCompetitorInLeg.put("started", trackedLegOfCompetitor.hasStartedLeg(timePoint));
|
||||
jsonCompetitorInLeg.put("finished", trackedLegOfCompetitor.hasFinishedLeg(timePoint));
|
||||
jsonCompetitors.add(jsonCompetitorInLeg);
|
||||
Course course = trackedRace.getRace().getCourse();
|
||||
course.lockForRead();
|
||||
try {
|
||||
for (TrackedLeg leg : trackedRace.getTrackedLegs()) {
|
||||
JSONObject jsonLeg = new JSONObject();
|
||||
jsonLeg.put("from", leg.getLeg().getFrom().getName());
|
||||
jsonLeg.put("fromWaypointId", leg.getLeg().getFrom().getId());
|
||||
jsonLeg.put("to", leg.getLeg().getTo().getName());
|
||||
jsonLeg.put("toWaypointId", leg.getLeg().getTo().getId());
|
||||
try {
|
||||
jsonLeg.put("upOrDownwindLeg", leg.isUpOrDownwindLeg(timePoint));
|
||||
} catch (NoWindException e) {
|
||||
// no wind, then it's simply no upwind or downwind leg
|
||||
jsonLeg.put("upOrDownwindLeg", "false");
|
||||
}
|
||||
JSONArray jsonCompetitors = new JSONArray();
|
||||
Map<Competitor, Integer> ranks = leg.getRanks(timePoint);
|
||||
for (Competitor competitor : trackedRace.getRace().getCompetitors()) {
|
||||
JSONObject jsonCompetitorInLeg = new JSONObject();
|
||||
TrackedLegOfCompetitor trackedLegOfCompetitor = leg.getTrackedLeg(competitor);
|
||||
if (trackedLegOfCompetitor != null) {
|
||||
jsonCompetitorInLeg.put("id", competitor.getId() != null ? competitor.getId()
|
||||
.toString() : null);
|
||||
jsonCompetitorInLeg.put("name", competitor.getName());
|
||||
jsonCompetitorInLeg.put("sailNumber", competitor.getBoat().getSailID());
|
||||
jsonCompetitorInLeg.put("color", competitor.getColor() != null ? competitor.getColor()
|
||||
.getAsHtml() : null);
|
||||
|
||||
Speed averageSpeedOverGround = trackedLegOfCompetitor
|
||||
.getAverageSpeedOverGround(timePoint);
|
||||
if (averageSpeedOverGround != null) {
|
||||
jsonCompetitorInLeg.put("averageSOG-kts",
|
||||
UnitSerializationUtil.knotsDecimalFormatter.format(averageSpeedOverGround
|
||||
.getKnots()));
|
||||
}
|
||||
try {
|
||||
Integer numberOfTacks = trackedLegOfCompetitor.getNumberOfTacks(timePoint, /* waitForLatest */
|
||||
false);
|
||||
Integer numberOfJibes = trackedLegOfCompetitor.getNumberOfJibes(timePoint, /* waitForLatest */
|
||||
false);
|
||||
Integer numberOfPenaltyCircles = trackedLegOfCompetitor.getNumberOfPenaltyCircles(
|
||||
timePoint, /* waitForLatest */false);
|
||||
jsonCompetitorInLeg.put("tacks", numberOfTacks);
|
||||
jsonCompetitorInLeg.put("jibes", numberOfJibes);
|
||||
jsonCompetitorInLeg.put("penaltyCircles", numberOfPenaltyCircles);
|
||||
} catch (NoWindException e) {
|
||||
logger.log(Level.FINE,
|
||||
"No wind information while trying to determing maneuvers for competitor "
|
||||
+ competitor.getName(), e);
|
||||
}
|
||||
|
||||
TimePoint startTime = trackedLegOfCompetitor.getStartTime();
|
||||
TimePoint finishTime = trackedLegOfCompetitor.getFinishTime();
|
||||
TimePoint startOfRace = trackedRace.getStartOfRace();
|
||||
// between the start of the race and the start of the first leg we have no
|
||||
// 'timeSinceGun'
|
||||
// for the competitor
|
||||
if (startOfRace != null && startTime != null) {
|
||||
long timeSinceGun = -1;
|
||||
if (finishTime != null) {
|
||||
timeSinceGun = finishTime.asMillis() - startOfRace.asMillis();
|
||||
} else {
|
||||
timeSinceGun = timePoint.asMillis() - startOfRace.asMillis();
|
||||
}
|
||||
if (timeSinceGun > 0) {
|
||||
jsonCompetitorInLeg.put("timeSinceGun-ms", timeSinceGun);
|
||||
}
|
||||
Distance distanceSinceGun = trackedRace.getTrack(competitor).getDistanceTraveled(
|
||||
startOfRace, finishTime != null ? finishTime : timePoint);
|
||||
if (distanceSinceGun != null) {
|
||||
jsonCompetitorInLeg.put("distanceSinceGun-m", distanceSinceGun.getMeters());
|
||||
}
|
||||
}
|
||||
|
||||
Distance distanceTraveled = trackedLegOfCompetitor.getDistanceTraveled(timePoint);
|
||||
if (distanceTraveled != null) {
|
||||
jsonCompetitorInLeg.put("distanceTraveled-m",
|
||||
UnitSerializationUtil.distanceDecimalFormatter.format(distanceTraveled
|
||||
.getMeters()));
|
||||
}
|
||||
Distance distanceTraveledIncludingGateStart = trackedLegOfCompetitor
|
||||
.getDistanceTraveledConsideringGateStart(timePoint);
|
||||
if (distanceTraveledIncludingGateStart != null) {
|
||||
jsonCompetitorInLeg.put("distanceTraveledIncludingGateStart-m",
|
||||
UnitSerializationUtil.distanceDecimalFormatter
|
||||
.format(distanceTraveledIncludingGateStart.getMeters()));
|
||||
}
|
||||
try {
|
||||
Integer rank = ranks.get(competitor);
|
||||
jsonCompetitorInLeg.put("rank", rank);
|
||||
} catch (RuntimeException re) {
|
||||
if (re.getCause() != null && re.getCause() instanceof NoWindException) {
|
||||
// well, we don't know the wind direction, so we can't compute a ranking
|
||||
} else {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
try {
|
||||
jsonCompetitorInLeg.put("gapToLeader-s", trackedLegOfCompetitor
|
||||
.getGapToLeaderInSeconds(timePoint, WindPositionMode.LEG_MIDDLE));
|
||||
} catch (NoWindException e1) {
|
||||
// well, we don't know the wind direction... then no gap to leader will be shown...
|
||||
}
|
||||
jsonCompetitorInLeg.put("started", trackedLegOfCompetitor.hasStartedLeg(timePoint));
|
||||
jsonCompetitorInLeg.put("finished", trackedLegOfCompetitor.hasFinishedLeg(timePoint));
|
||||
jsonCompetitors.add(jsonCompetitorInLeg);
|
||||
}
|
||||
}
|
||||
jsonLeg.put("competitors", jsonCompetitors);
|
||||
jsonLegs.add(jsonLeg);
|
||||
}
|
||||
jsonLeg.put("competitors", jsonCompetitors);
|
||||
jsonLegs.add(jsonLeg);
|
||||
} finally {
|
||||
course.unlockAfterRead();
|
||||
}
|
||||
jsonRaceResults.put("legs", jsonLegs);
|
||||
|
||||
|
||||
Reference in new issue
Block a user