mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-02 02:13:55 +00:00
Added synchronization for MarkPassing collections, fixing bug 342
This commit is contained in:
1 parent
2afb74b95a
commit
f36a657dc2
7 files changed
+159
-101
No files matched your search
+8
-3
@@ -7,6 +7,7 @@ import java.text.ParseException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.logging.Logger;
|
||||
@@ -193,9 +194,13 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl implemen
|
||||
// we need to use this to *update* the competitor's mark passings list, not *replace* it
|
||||
TreeMap<Integer, MarkPassing> markPassingsByMarkIndex = new TreeMap<Integer, MarkPassing>();
|
||||
// now fill with the already existing mark passings for the competitor identified by boatID...
|
||||
for (MarkPassing markPassing : trackedRace.getMarkPassings(competitor)) {
|
||||
markPassingsByMarkIndex.put(
|
||||
trackedRace.getRace().getCourse().getIndexOfWaypoint(markPassing.getWaypoint()), markPassing);
|
||||
NavigableSet<MarkPassing> markPassings = trackedRace.getMarkPassings(competitor);
|
||||
synchronized (markPassings) {
|
||||
for (MarkPassing markPassing : markPassings) {
|
||||
markPassingsByMarkIndex.put(
|
||||
trackedRace.getRace().getCourse().getIndexOfWaypoint(markPassing.getWaypoint()),
|
||||
markPassing);
|
||||
}
|
||||
}
|
||||
// ...and then overwrite those for which we received "new evidence"
|
||||
for (Triple<Integer, Integer, Long> markIndexRankAndTimeSinceStartInMilliseconds : markIndicesRanksAndTimesSinceStartInMilliseconds) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.tracking;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import com.sap.sailing.domain.base.Buoy;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
@@ -148,6 +149,10 @@ public interface TrackedRace {
|
||||
* which point in time. This can, e.g., be used to sort those competitors who already finished a leg within the leg
|
||||
* that ends with <code>waypoint</code>. The remaining competitors need to be ordered by the advantage line-related
|
||||
* distance to the waypoint.
|
||||
*
|
||||
* @return the iterable sequence of {@link MarkPassing}s as described above. To iterate on the resulting collection
|
||||
* the caller needs to synchronize on the iterable returned because insertions into the underlying
|
||||
* collection will also synchronize on that collection.
|
||||
*/
|
||||
Iterable<MarkPassing> getMarkPassingsInOrder(Waypoint waypoint);
|
||||
|
||||
@@ -199,7 +204,10 @@ public interface TrackedRace {
|
||||
* returned such that their {@link MarkPassing#getWaypoint() waypoints} are ordered in the same way they are ordered
|
||||
* in the race's {@link Course}. Note, that this doesn't necessarily guarantee ascending time points, particularly
|
||||
* if premature mark passings have been detected accidentally as can be the case with some tracking providers such
|
||||
* as TracTrac.
|
||||
* as TracTrac. If the caller wants to iterate on the resulting collection or construct a {@link SortedSet#headSet(Object)}
|
||||
* or {@link SortedSet#tailSet(Object)} and then iterate over that, the caller needs to synchronize on the
|
||||
* collection returned because insertions into the competitor's mark passing collection will also synchronize
|
||||
* on that collection.
|
||||
*/
|
||||
NavigableSet<MarkPassing> getMarkPassings(Competitor competitor);
|
||||
|
||||
|
||||
+23
-10
@@ -240,15 +240,22 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements
|
||||
public void updateMarkPassings(Competitor competitor, Iterable<MarkPassing> markPassings) {
|
||||
Map<Waypoint, MarkPassing> oldMarkPassings = new HashMap<Waypoint, MarkPassing>();
|
||||
synchronized (this) {
|
||||
for (MarkPassing oldMarkPassing : getMarkPassings(competitor)) {
|
||||
oldMarkPassings.put(oldMarkPassing.getWaypoint(), oldMarkPassing);
|
||||
NavigableSet<MarkPassing> markPassingsForCompetitor = getMarkPassings(competitor);
|
||||
synchronized (markPassingsForCompetitor) {
|
||||
for (MarkPassing oldMarkPassing : markPassingsForCompetitor) {
|
||||
oldMarkPassings.put(oldMarkPassing.getWaypoint(), oldMarkPassing);
|
||||
}
|
||||
}
|
||||
clearMarkPassings(competitor);
|
||||
NavigableSet<MarkPassing> competitorMarkPassings = getMarkPassings(competitor);
|
||||
TimePoint timePointOfLatestEvent = new MillisecondsTimePoint(0);
|
||||
for (MarkPassing markPassing : markPassings) {
|
||||
competitorMarkPassings.add(markPassing);
|
||||
getMarkPassingsInOrder(markPassing.getWaypoint()).add(markPassing);
|
||||
synchronized (markPassingsForCompetitor) {
|
||||
markPassingsForCompetitor.add(markPassing);
|
||||
}
|
||||
Collection<MarkPassing> markPassingsInOrderForWaypoint = getMarkPassingsInOrder(markPassing.getWaypoint());
|
||||
synchronized (markPassingsInOrderForWaypoint) {
|
||||
markPassingsInOrderForWaypoint.add(markPassing);
|
||||
}
|
||||
if (markPassing.getTimePoint().compareTo(timePointOfLatestEvent) > 0) {
|
||||
timePointOfLatestEvent = markPassing.getTimePoint();
|
||||
}
|
||||
@@ -267,11 +274,17 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements
|
||||
}
|
||||
|
||||
private void clearMarkPassings(Competitor competitor) {
|
||||
Iterator<MarkPassing> mpIter = getMarkPassings(competitor).iterator();
|
||||
while (mpIter.hasNext()) {
|
||||
MarkPassing mp = mpIter.next();
|
||||
mpIter.remove();
|
||||
getMarkPassingsInOrder(mp.getWaypoint()).remove(mp);
|
||||
NavigableSet<MarkPassing> markPassings = getMarkPassings(competitor);
|
||||
synchronized (markPassings) {
|
||||
Iterator<MarkPassing> mpIter = markPassings.iterator();
|
||||
while (mpIter.hasNext()) {
|
||||
MarkPassing mp = mpIter.next();
|
||||
mpIter.remove();
|
||||
Collection<MarkPassing> markPassingsInOrder = getMarkPassingsInOrder(mp.getWaypoint());
|
||||
synchronized (markPassingsInOrder) {
|
||||
markPassingsInOrder.remove(mp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+29
-22
@@ -43,28 +43,35 @@ public class RaceRankComparator implements Comparator<Competitor> {
|
||||
if (o1 == o2) {
|
||||
result = 0;
|
||||
} else {
|
||||
// TODO see also bug 340/342; need to synchronize on TrackedRace to avoid concurrent updates to MarkPassings, although this is course-grained
|
||||
NavigableSet<MarkPassing> o1MarkPassings = trackedRace.getMarkPassings(o1).headSet(
|
||||
markPassingWithTimePoint, /* inclusive */true);
|
||||
NavigableSet<MarkPassing> o2MarkPassings = trackedRace.getMarkPassings(o2).headSet(
|
||||
markPassingWithTimePoint, /* inclusive */true);
|
||||
result = o2MarkPassings.size() - o1MarkPassings.size(); // inverted: more legs means smaller rank
|
||||
if (result == 0 && o1MarkPassings.size() > 0) {
|
||||
// Competitors are on same leg and both have already started the first leg.
|
||||
// TrackedLegOfCompetitor comparison also correctly uses finish times for a leg
|
||||
// in case we have the final leg, so both competitors finished the race.
|
||||
TrackedLegOfCompetitor o1Leg = trackedRace.getCurrentLeg(o1, timePoint);
|
||||
if (o1Leg == null) {
|
||||
// both must already finished race; sort by race finish time: earlier time means smaller (better)
|
||||
// rank
|
||||
result = o1MarkPassings.last().getTimePoint().compareTo(o2MarkPassings.last().getTimePoint());
|
||||
} else {
|
||||
TrackedLegOfCompetitor o2Leg = trackedRace.getCurrentLeg(o2, timePoint);
|
||||
if (o2Leg == null) {
|
||||
result = 1; // o1Leg != null, so o1 has started leg already, o2 hasn't
|
||||
} else {
|
||||
result = new WindwardToGoComparator(trackedRace.getTrackedLeg(o1Leg.getLeg()), timePoint)
|
||||
.compare(o1Leg, o2Leg);
|
||||
NavigableSet<MarkPassing> o1MarkPassings = trackedRace.getMarkPassings(o1);
|
||||
synchronized (o1MarkPassings) {
|
||||
NavigableSet<MarkPassing> o2MarkPassings = trackedRace.getMarkPassings(o2);
|
||||
synchronized (o2MarkPassings) {
|
||||
NavigableSet<MarkPassing> o1MarkPassingsBeforeTimePoint = o1MarkPassings.headSet(
|
||||
markPassingWithTimePoint, /* inclusive */true);
|
||||
NavigableSet<MarkPassing> o2MarkPassingsBeforeTimePoint = o2MarkPassings.headSet(
|
||||
markPassingWithTimePoint, /* inclusive */true);
|
||||
result = o2MarkPassingsBeforeTimePoint.size() - o1MarkPassingsBeforeTimePoint.size(); // inverted: more legs means smaller rank
|
||||
if (result == 0 && o1MarkPassingsBeforeTimePoint.size() > 0) {
|
||||
// Competitors are on same leg and both have already started the first leg.
|
||||
// TrackedLegOfCompetitor comparison also correctly uses finish times for a leg
|
||||
// in case we have the final leg, so both competitors finished the race.
|
||||
TrackedLegOfCompetitor o1Leg = trackedRace.getCurrentLeg(o1, timePoint);
|
||||
if (o1Leg == null) {
|
||||
// both must already finished race; sort by race finish time: earlier time means smaller
|
||||
// (better)
|
||||
// rank
|
||||
result = o1MarkPassingsBeforeTimePoint.last().getTimePoint()
|
||||
.compareTo(o2MarkPassingsBeforeTimePoint.last().getTimePoint());
|
||||
} else {
|
||||
TrackedLegOfCompetitor o2Leg = trackedRace.getCurrentLeg(o2, timePoint);
|
||||
if (o2Leg == null) {
|
||||
result = 1; // o1Leg != null, so o1 has started leg already, o2 hasn't
|
||||
} else {
|
||||
result = new WindwardToGoComparator(trackedRace.getTrackedLeg(o1Leg.getLeg()),
|
||||
timePoint).compare(o1Leg, o2Leg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-4
@@ -374,13 +374,17 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor {
|
||||
if (windwardSpeed == null) {
|
||||
return null;
|
||||
} else {
|
||||
Iterator<MarkPassing> markPassingsForLegEnd = getTrackedRace().getMarkPassingsInOrder(getLeg().getTo())
|
||||
.iterator();
|
||||
// Has our competitor started the leg already? If not, we won't be able to compute a gap
|
||||
if (hasStartedLeg(timePoint)) {
|
||||
if (markPassingsForLegEnd.hasNext()) {
|
||||
Iterable<MarkPassing> markPassingsInOrder = getTrackedRace().getMarkPassingsInOrder(getLeg().getTo());
|
||||
MarkPassing firstMarkPassing = null;
|
||||
synchronized (markPassingsInOrder) {
|
||||
Iterator<MarkPassing> markPassingsForLegEnd = markPassingsInOrder.iterator();
|
||||
firstMarkPassing = markPassingsForLegEnd.next();
|
||||
}
|
||||
if (firstMarkPassing != null) {
|
||||
// someone has already finished the leg
|
||||
TimePoint whenLeaderFinishedLeg = markPassingsForLegEnd.next().getTimePoint();
|
||||
TimePoint whenLeaderFinishedLeg = firstMarkPassing.getTimePoint();
|
||||
// Was it before the requested timePoint?
|
||||
if (whenLeaderFinishedLeg.compareTo(timePoint) <= 0) {
|
||||
// Has our competitor also already finished this leg?
|
||||
|
||||
+40
-24
@@ -208,9 +208,15 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
|
||||
@Override
|
||||
public TimePoint getStart() {
|
||||
TimePoint result;
|
||||
Iterator<MarkPassing> markPassingsFirstMarkIter = getMarkPassingsInOrder(getRace().getCourse().getFirstWaypoint()).iterator();
|
||||
if (markPassingsFirstMarkIter.hasNext()) {
|
||||
MarkPassing firstMarkPassingFirstMark = markPassingsFirstMarkIter.next();
|
||||
Iterable<MarkPassing> markPassingsInOrder = getMarkPassingsInOrder(getRace().getCourse().getFirstWaypoint());
|
||||
MarkPassing firstMarkPassingFirstMark = null;
|
||||
synchronized (markPassingsInOrder) {
|
||||
Iterator<MarkPassing> markPassingsFirstMarkIter = markPassingsInOrder.iterator();
|
||||
if (markPassingsFirstMarkIter.hasNext()) {
|
||||
firstMarkPassingFirstMark = markPassingsFirstMarkIter.next();
|
||||
}
|
||||
}
|
||||
if (firstMarkPassingFirstMark != null) {
|
||||
TimePoint timeOfFirstMarkPassingFirstMark = firstMarkPassingFirstMark.getTimePoint();
|
||||
if (startTimeReceived != null) {
|
||||
long startTimeReceived2timeOfFirstMarkPassingFirstMark = timeOfFirstMarkPassingFirstMark.asMillis() -
|
||||
@@ -232,8 +238,11 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
|
||||
@Override
|
||||
public TimePoint getAssumedEnd() {
|
||||
TimePoint result = null;
|
||||
for (MarkPassing passingFinishLine : getMarkPassingsInOrder(getRace().getCourse().getLastWaypoint())) {
|
||||
result = passingFinishLine.getTimePoint();
|
||||
Iterable<MarkPassing> markPassingsInOrder = getMarkPassingsInOrder(getRace().getCourse().getLastWaypoint());
|
||||
synchronized (markPassingsInOrder) {
|
||||
for (MarkPassing passingFinishLine : markPassingsInOrder) {
|
||||
result = passingFinishLine.getTimePoint();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -756,19 +765,20 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
|
||||
if (!track.hasDirectionChange(timePoint, getManeuverDegreeAngleThreshold())) {
|
||||
// reduce confidence around mark passings:
|
||||
NavigableSet<MarkPassing> markPassings = getMarkPassings(competitor);
|
||||
NavigableSet<MarkPassing> prevMarkPassing = markPassings.headSet(dummyMarkPassingForNow, /* inclusive */ true);
|
||||
NavigableSet<MarkPassing> nextMarkPassing = markPassings.tailSet(dummyMarkPassingForNow, /* inclusive */ true);
|
||||
double markPassingProximityConfidenceReduction = 1.0;
|
||||
if (prevMarkPassing != null && !prevMarkPassing.isEmpty()) {
|
||||
markPassingProximityConfidenceReduction *= Math.max(0.0,
|
||||
1.0-weigherForMarkPassingProximity.getConfidence(prevMarkPassing.last().getTimePoint(), timePoint));
|
||||
synchronized (markPassings) {
|
||||
NavigableSet<MarkPassing> prevMarkPassing = markPassings.headSet(dummyMarkPassingForNow, /* inclusive */ true);
|
||||
NavigableSet<MarkPassing> nextMarkPassing = markPassings.tailSet(dummyMarkPassingForNow, /* inclusive */ true);
|
||||
if (prevMarkPassing != null && !prevMarkPassing.isEmpty()) {
|
||||
markPassingProximityConfidenceReduction *= Math.max(0.0,
|
||||
1.0-weigherForMarkPassingProximity.getConfidence(prevMarkPassing.last().getTimePoint(), timePoint));
|
||||
}
|
||||
if (nextMarkPassing != null && !nextMarkPassing.isEmpty()) {
|
||||
markPassingProximityConfidenceReduction *= Math.max(0.0,
|
||||
1.0-weigherForMarkPassingProximity.getConfidence(nextMarkPassing.first().getTimePoint(), timePoint));
|
||||
}
|
||||
}
|
||||
if (nextMarkPassing != null && !nextMarkPassing.isEmpty()) {
|
||||
markPassingProximityConfidenceReduction *= Math.max(0.0,
|
||||
1.0-weigherForMarkPassingProximity.getConfidence(nextMarkPassing.first().getTimePoint(), timePoint));
|
||||
}
|
||||
SpeedWithBearingWithConfidence<TimePoint> estimatedSpeedWithConfidence = track.getEstimatedSpeed(timePoint,
|
||||
weigher);
|
||||
SpeedWithBearingWithConfidence<TimePoint> estimatedSpeedWithConfidence = track.getEstimatedSpeed(timePoint, weigher);
|
||||
if (estimatedSpeedWithConfidence != null) {
|
||||
BearingWithConfidence<TimePoint> bearing = new BearingWithConfidenceImpl<TimePoint>(
|
||||
estimatedSpeedWithConfidence.getObject() == null ? null : estimatedSpeedWithConfidence.getObject().getBearing(),
|
||||
@@ -1117,13 +1127,18 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
|
||||
Placemark startBest = null;
|
||||
Placemark finishBest = null;
|
||||
|
||||
//Get start postition
|
||||
// Get start postition
|
||||
Waypoint start = getRace().getCourse().getFirstWaypoint();
|
||||
Iterable<MarkPassing> startPassings = getMarkPassingsInOrder(start);
|
||||
if (startPassings.iterator().hasNext()) {
|
||||
MarkPassing startPassing = startPassings.iterator().next();
|
||||
MarkPassing startPassing = null;
|
||||
synchronized (startPassings) {
|
||||
Iterator<MarkPassing> iterator = startPassings.iterator();
|
||||
if (iterator.hasNext()) {
|
||||
startPassing = iterator.next();
|
||||
}
|
||||
}
|
||||
if (startPassing != null) {
|
||||
Position startPosition = getApproximatePosition(start, startPassing.getTimePoint());
|
||||
|
||||
try {
|
||||
// Get distance to nearest placemark and calculate the search radius
|
||||
Placemark startNearest = ReverseGeocoder.INSTANCE.getPlacemarkNearest(startPosition);
|
||||
@@ -1142,13 +1157,14 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
|
||||
// Get finish position
|
||||
Waypoint finish = getRace().getCourse().getLastWaypoint();
|
||||
Iterable<MarkPassing> finishPassings = getMarkPassingsInOrder(finish);
|
||||
Iterator<MarkPassing> finishPassingsIterator = finishPassings.iterator();
|
||||
MarkPassing finishPassing = null;
|
||||
while (finishPassingsIterator.hasNext()) {
|
||||
finishPassing = (MarkPassing) finishPassingsIterator.next();
|
||||
synchronized (finishPassings) {
|
||||
Iterator<MarkPassing> finishPassingsIterator = finishPassings.iterator();
|
||||
while (finishPassingsIterator.hasNext()) {
|
||||
finishPassing = (MarkPassing) finishPassingsIterator.next();
|
||||
}
|
||||
}
|
||||
Position finishPosition = getApproximatePosition(finish, finishPassing.getTimePoint());
|
||||
|
||||
if (startPosition.getDistance(finishPosition).getKilometers() > ReverseGeocoder.POSITION_CACHE_DISTANCE_LIMIT_IN_KM) {
|
||||
try {
|
||||
// Get distance to nearest placemark and calculate the search radius
|
||||
|
||||
+42
-37
@@ -769,32 +769,35 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
// try to calculate the point in time where all boats passed the start line in a small time frame
|
||||
Waypoint from = trackedLeg.getLeg().getFrom();
|
||||
Iterable<MarkPassing> markPassings = trackedRace.getMarkPassingsInOrder(from);
|
||||
int markPassingsCount = Util.size(markPassings);
|
||||
// require more than half the boats registered for the race to have passed the start mark
|
||||
if (markPassings != null && markPassingsCount > Util.size(trackedRace.getRace().getCompetitors())/2) {
|
||||
long maxTimeFrameInMs = 60 * 1000; // = 1 minute
|
||||
Iterator<MarkPassing> iterator = markPassings.iterator();
|
||||
long currentTimeToCheck = 0;
|
||||
int enoughCompetitors = markPassingsCount / 2;
|
||||
int currentCompetitorsInTime = 0;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
MarkPassing currentMarkPassing = iterator.next();
|
||||
long diff = currentMarkPassing.getTimePoint().asMillis() - currentTimeToCheck;
|
||||
if (diff > maxTimeFrameInMs) {
|
||||
// reset the check
|
||||
currentCompetitorsInTime = 0;
|
||||
currentTimeToCheck = currentMarkPassing.getTimePoint().asMillis();
|
||||
} else {
|
||||
currentCompetitorsInTime++;
|
||||
if(currentCompetitorsInTime == enoughCompetitors) {
|
||||
Date passingDate = currentMarkPassing.getTimePoint().asDate();
|
||||
LegTimesInfoDTO legTimepointDTO = new LegTimesInfoDTO("S");
|
||||
legTimepointDTO.firstPassingDate = passingDate;
|
||||
legTimes.add(legTimepointDTO);
|
||||
raceTimesInfo.setStartOfRace(passingDate);
|
||||
lastLegPassingTime = passingDate;
|
||||
break;
|
||||
synchronized (markPassings) {
|
||||
int markPassingsCount = Util.size(markPassings);
|
||||
// require more than half the boats registered for the race to have passed the start mark
|
||||
if (markPassings != null
|
||||
&& markPassingsCount > Util.size(trackedRace.getRace().getCompetitors()) / 2) {
|
||||
long maxTimeFrameInMs = 60 * 1000; // = 1 minute
|
||||
Iterator<MarkPassing> iterator = markPassings.iterator();
|
||||
long currentTimeToCheck = 0;
|
||||
int enoughCompetitors = markPassingsCount / 2;
|
||||
int currentCompetitorsInTime = 0;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
MarkPassing currentMarkPassing = iterator.next();
|
||||
long diff = currentMarkPassing.getTimePoint().asMillis() - currentTimeToCheck;
|
||||
if (diff > maxTimeFrameInMs) {
|
||||
// reset the check
|
||||
currentCompetitorsInTime = 0;
|
||||
currentTimeToCheck = currentMarkPassing.getTimePoint().asMillis();
|
||||
} else {
|
||||
currentCompetitorsInTime++;
|
||||
if (currentCompetitorsInTime == enoughCompetitors) {
|
||||
Date passingDate = currentMarkPassing.getTimePoint().asDate();
|
||||
LegTimesInfoDTO legTimepointDTO = new LegTimesInfoDTO("S");
|
||||
legTimepointDTO.firstPassingDate = passingDate;
|
||||
legTimes.add(legTimepointDTO);
|
||||
raceTimesInfo.setStartOfRace(passingDate);
|
||||
lastLegPassingTime = passingDate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -807,17 +810,19 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
// ensure the passing date is in the right time order; there may perhaps be left-overs for marks to be reached later that
|
||||
// claim it has been passed in the past which may have been an accidental tracker read-out;
|
||||
// the results of getMarkPassingsInOrder(to) has by definition an ascending time-point ordering
|
||||
for (MarkPassing currentMarkPassing : markPassings) {
|
||||
Date currentPassingDate = currentMarkPassing.getTimePoint().asDate();
|
||||
if (lastLegPassingTime == null) {
|
||||
lastLegPassingTime = currentPassingDate;
|
||||
}
|
||||
if (currentPassingDate.after(lastLegPassingTime)) {
|
||||
LegTimesInfoDTO legTimepointDTO = new LegTimesInfoDTO("L" + i++);
|
||||
legTimepointDTO.firstPassingDate = currentPassingDate;
|
||||
legTimes.add(legTimepointDTO);
|
||||
lastLegPassingTime = currentPassingDate;
|
||||
break;
|
||||
synchronized (markPassings) {
|
||||
for (MarkPassing currentMarkPassing : markPassings) {
|
||||
Date currentPassingDate = currentMarkPassing.getTimePoint().asDate();
|
||||
if (lastLegPassingTime == null) {
|
||||
lastLegPassingTime = currentPassingDate;
|
||||
}
|
||||
if (currentPassingDate.after(lastLegPassingTime)) {
|
||||
LegTimesInfoDTO legTimepointDTO = new LegTimesInfoDTO("L" + i++);
|
||||
legTimepointDTO.firstPassingDate = currentPassingDate;
|
||||
legTimes.add(legTimepointDTO);
|
||||
lastLegPassingTime = currentPassingDate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user