mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-13 14:12:11 +00:00
bug5043: avoid filtering out candidates for fixed mark passings in StationarySequence
This commit is contained in:
1 parent
8109d94ddf
commit
9ec982c19f
6 files changed
+56
-19
No files matched your search
+7
-7
@@ -19,26 +19,26 @@ public class MostProbableCandidatesInSmallTimeRangeFilterTest extends AbstractCa
|
||||
|
||||
@Test
|
||||
public void testGetTimeWiseContiguousDistanceCandidates() {
|
||||
final NavigableSet<Candidate> result = filter.getTimeWiseContiguousDistanceCandidates(competitorCandidates, c3, /* includeStartFrom */ true);
|
||||
final NavigableSet<Candidate> result = filter.getTimeWiseContiguousCandidates(competitorCandidates, c3, /* includeStartFrom */ true);
|
||||
assertContainsExactly(result, c1, c2, c3, c4, c5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTimeWiseContiguousDistanceCandidatesOnRightBorder() {
|
||||
final NavigableSet<Candidate> result = filter.getTimeWiseContiguousDistanceCandidates(competitorCandidates, c5, /* includeStartFrom */ true);
|
||||
final NavigableSet<Candidate> result = filter.getTimeWiseContiguousCandidates(competitorCandidates, c5, /* includeStartFrom */ true);
|
||||
assertContainsExactly(result, c1, c2, c3, c4, c5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTimeWiseContiguousDistanceCandidatesOnLeftBorder() {
|
||||
final NavigableSet<Candidate> result = filter.getTimeWiseContiguousDistanceCandidates(competitorCandidates, c6, /* includeStartFrom */ true);
|
||||
final NavigableSet<Candidate> result = filter.getTimeWiseContiguousCandidates(competitorCandidates, c6, /* includeStartFrom */ true);
|
||||
assertContainsExactly(result, c6, c7, c8, c9, c10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTimeWiseContiguousDistanceCandidatesInMiddleOfGapNotInserted() {
|
||||
final Candidate middleOfGap = candidate(c5.getTimePoint().plus(c5.getTimePoint().until(c6.getTimePoint()).divide(2)), "gap");
|
||||
final NavigableSet<Candidate> result = filter.getTimeWiseContiguousDistanceCandidates(competitorCandidates, middleOfGap,
|
||||
final NavigableSet<Candidate> result = filter.getTimeWiseContiguousCandidates(competitorCandidates, middleOfGap,
|
||||
/* includeStartFrom */ true);
|
||||
assertContainsExactly(result, c1, c2, c3, c4, c5, middleOfGap, c6, c7, c8, c9, c10);
|
||||
}
|
||||
@@ -46,7 +46,7 @@ public class MostProbableCandidatesInSmallTimeRangeFilterTest extends AbstractCa
|
||||
@Test
|
||||
public void testGetTimeWiseContiguousDistanceCandidatesInMiddleOfGapNotInsertedDontIncludeStartFrom() {
|
||||
final Candidate middleOfGap = candidate(c5.getTimePoint().plus(c5.getTimePoint().until(c6.getTimePoint()).divide(2)), "gap");
|
||||
final NavigableSet<Candidate> result = filter.getTimeWiseContiguousDistanceCandidates(competitorCandidates, middleOfGap,
|
||||
final NavigableSet<Candidate> result = filter.getTimeWiseContiguousCandidates(competitorCandidates, middleOfGap,
|
||||
/* includeStartFrom */ false);
|
||||
assertContainsExactly(result, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10);
|
||||
}
|
||||
@@ -55,7 +55,7 @@ public class MostProbableCandidatesInSmallTimeRangeFilterTest extends AbstractCa
|
||||
public void testGetTimeWiseContiguousDistanceCandidatesInMiddleOfGapInserted() {
|
||||
final Candidate middleOfGap = candidate(c5.getTimePoint().plus(c5.getTimePoint().until(c6.getTimePoint()).divide(2)), "gap");
|
||||
competitorCandidates.add(middleOfGap);
|
||||
final NavigableSet<Candidate> result = filter.getTimeWiseContiguousDistanceCandidates(competitorCandidates, middleOfGap,
|
||||
final NavigableSet<Candidate> result = filter.getTimeWiseContiguousCandidates(competitorCandidates, middleOfGap,
|
||||
/* includeStartFrom */ true);
|
||||
assertContainsExactly(result, c1, c2, c3, c4, c5, middleOfGap, c6, c7, c8, c9, c10);
|
||||
}
|
||||
@@ -65,7 +65,7 @@ public class MostProbableCandidatesInSmallTimeRangeFilterTest extends AbstractCa
|
||||
competitorCandidates.remove(c5);
|
||||
competitorCandidates.remove(c6);
|
||||
final Candidate middleOfGap = candidate(c5.getTimePoint().plus(c5.getTimePoint().until(c6.getTimePoint()).divide(2)), "gap");
|
||||
final NavigableSet<Candidate> result = filter.getTimeWiseContiguousDistanceCandidates(competitorCandidates, middleOfGap,
|
||||
final NavigableSet<Candidate> result = filter.getTimeWiseContiguousCandidates(competitorCandidates, middleOfGap,
|
||||
/* includeStartFrom */ true);
|
||||
assertContainsExactly(result, middleOfGap);
|
||||
}
|
||||
|
||||
+7
@@ -20,6 +20,13 @@ import com.sap.sse.common.Timed;
|
||||
public interface Candidate extends Comparable<CandidateImpl>, Timed {
|
||||
|
||||
Waypoint getWaypoint();
|
||||
|
||||
/**
|
||||
* Is this a candidate for a fixed mark passing?
|
||||
*/
|
||||
default boolean isFixed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
int getOneBasedIndexOfWaypoint();
|
||||
|
||||
|
||||
+1
-1
@@ -474,7 +474,7 @@ public class CandidateChooserImpl implements CandidateChooser {
|
||||
public void setFixedPassing(Competitor c, Integer zeroBasedIndexOfWaypoint, TimePoint t) {
|
||||
LockUtil.lockForWrite(perCompetitorLocks.get(c));
|
||||
try {
|
||||
Candidate fixedCan = new CandidateImpl(zeroBasedIndexOfWaypoint + 1, t, 1, Util.get(race.getRace().getCourse().getWaypoints(), zeroBasedIndexOfWaypoint));
|
||||
Candidate fixedCan = new CandidateForFixedMarkPassingImpl(zeroBasedIndexOfWaypoint + 1, t, 1, Util.get(race.getRace().getCourse().getWaypoints(), zeroBasedIndexOfWaypoint));
|
||||
NavigableSet<Candidate> fixed = fixedPassings.get(c);
|
||||
if (fixed != null) { // can only set the mark passing if the competitor is still part of this race
|
||||
if (!fixed.add(fixedCan)) {
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.sap.sailing.domain.markpassingcalculation.impl;
|
||||
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class CandidateForFixedMarkPassingImpl extends CandidateImpl {
|
||||
private static final long serialVersionUID = 3657502693032556232L;
|
||||
|
||||
public CandidateForFixedMarkPassingImpl(int oneBasedIndexOfWaypoint, TimePoint p, double probability, Waypoint w) {
|
||||
super(oneBasedIndexOfWaypoint, p, probability, w);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFixed() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -102,7 +102,7 @@ public class MostProbableCandidatesInSmallTimeRangeFilter {
|
||||
while (!newCandidatesModifiableCopy.isEmpty()) {
|
||||
final Candidate nextNewCandidate = newCandidatesModifiableCopy.iterator().next();
|
||||
newCandidatesModifiableCopy.remove(nextNewCandidate);
|
||||
final NavigableSet<Candidate> contiguousSequenceForNextNewCandidate = getTimeWiseContiguousDistanceCandidates(competitorCandidates, nextNewCandidate, /* includeStartFrom */ true);
|
||||
final NavigableSet<Candidate> contiguousSequenceForNextNewCandidate = getTimeWiseContiguousCandidates(competitorCandidates, nextNewCandidate, /* includeStartFrom */ true);
|
||||
disjointSequencesAffectedByNewAndRemovedCandidates.add(contiguousSequenceForNextNewCandidate);
|
||||
// remove the candidate grouped in the sequence from the remaining new candidates to consider
|
||||
// because they have been "scooped up" by this sequence already and need no further consideration:
|
||||
@@ -122,7 +122,7 @@ public class MostProbableCandidatesInSmallTimeRangeFilter {
|
||||
while (!removedCandidatesModifiableCopy.isEmpty()) {
|
||||
final Candidate nextRemovedCandidate = removedCandidatesModifiableCopy.iterator().next();
|
||||
removedCandidatesModifiableCopy.remove(nextRemovedCandidate);
|
||||
final NavigableSet<Candidate> contiguousSequenceForNextRemovedCandidate = getTimeWiseContiguousDistanceCandidates(competitorCandidates, nextRemovedCandidate, /* includeStartFrom */ false);
|
||||
final NavigableSet<Candidate> contiguousSequenceForNextRemovedCandidate = getTimeWiseContiguousCandidates(competitorCandidates, nextRemovedCandidate, /* includeStartFrom */ false);
|
||||
removeAllRemovedCandidatesInOrNearSequence(contiguousSequenceForNextRemovedCandidate, removedCandidatesModifiableCopy);
|
||||
// If adjacent sequences were added before and after the removed candidate,
|
||||
// we need to distinguish whether the gap around the removed candidate was greater
|
||||
@@ -233,7 +233,7 @@ public class MostProbableCandidatesInSmallTimeRangeFilter {
|
||||
* @param includeStartFrom
|
||||
* whether or not to include {@code startFrom} in the resulting set
|
||||
*/
|
||||
public NavigableSet<Candidate> getTimeWiseContiguousDistanceCandidates(NavigableSet<Candidate> competitorCandidates, Candidate startFrom, boolean includeStartFrom) {
|
||||
public NavigableSet<Candidate> getTimeWiseContiguousCandidates(NavigableSet<Candidate> competitorCandidates, Candidate startFrom, boolean includeStartFrom) {
|
||||
final NavigableSet<Candidate> result = new TreeSet<>(candidateComparator);
|
||||
if (includeStartFrom) {
|
||||
result.add(startFrom);
|
||||
|
||||
+21
-8
@@ -89,7 +89,7 @@ public class StationarySequence {
|
||||
// borders of this sequence:
|
||||
final TimeRange timeRangeNoLongerPassingFilter = getExtendedEndBorderRange(extendedBy);
|
||||
if (timeRangeNoLongerPassingFilter != null) {
|
||||
removeFromFilterResult(timeRangeNoLongerPassingFilter, candidatesEffectivelyAdded, candidatesEffectivelyRemoved);
|
||||
removeFromFilterResultUnlessFixed(timeRangeNoLongerPassingFilter, candidatesEffectivelyAdded, candidatesEffectivelyRemoved);
|
||||
}
|
||||
}
|
||||
return bounds != null;
|
||||
@@ -158,7 +158,7 @@ public class StationarySequence {
|
||||
// borders of this sequence:
|
||||
final TimeRange timeRangeNoLongerPassingFilter = getExtendedStartBorderRange(extendedBy);
|
||||
if (timeRangeNoLongerPassingFilter != null) {
|
||||
removeFromFilterResult(timeRangeNoLongerPassingFilter, candidatesEffectivelyAdded, candidatesEffectivelyRemoved);
|
||||
removeFromFilterResultUnlessFixed(timeRangeNoLongerPassingFilter, candidatesEffectivelyAdded, candidatesEffectivelyRemoved);
|
||||
}
|
||||
}
|
||||
return bounds != null;
|
||||
@@ -204,11 +204,15 @@ public class StationarySequence {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void removeFromFilterResult(final TimeRange timeRangeNoLongerPassingFilter, Set<Candidate> candidatesEffectivelyAdded,
|
||||
private void removeFromFilterResultUnlessFixed(final TimeRange timeRangeNoLongerPassingFilter, Set<Candidate> candidatesEffectivelyAdded,
|
||||
Set<Candidate> candidatesEffectivelyRemoved) {
|
||||
final SortedSet<Candidate> candidatesNoLongerPassingFilter = getCandidatesInTimeRange(timeRangeNoLongerPassingFilter);
|
||||
candidatesEffectivelyAdded.removeAll(candidatesNoLongerPassingFilter);
|
||||
candidatesEffectivelyRemoved.addAll(candidatesNoLongerPassingFilter);
|
||||
for (final Candidate candidate : candidatesNoLongerPassingFilter) {
|
||||
if (!candidate.isFixed()) {
|
||||
candidatesEffectivelyAdded.removeAll(candidatesNoLongerPassingFilter);
|
||||
candidatesEffectivelyRemoved.addAll(candidatesNoLongerPassingFilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SortedSet<Candidate> getCandidatesInTimeRange(final TimeRange timeRange) {
|
||||
@@ -219,7 +223,16 @@ public class StationarySequence {
|
||||
}
|
||||
|
||||
public Iterable<Candidate> getValidCandidates() {
|
||||
return ()->candidates.stream().filter(c->isCloseEnoughToSequenceBorder(c)).iterator();
|
||||
return ()->candidates.stream().filter(c->isValidCandidate(c)).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* A candidate that is part of this stationary sequence is considered valid if it is time-wise close
|
||||
* enough to one of the sequence's borders (see {@link #CANDIDATE_FILTER_TIME_WINDOW}) or if it is
|
||||
* a candidate for a {@link Candidate#isFixed() fixed mark passing}.
|
||||
*/
|
||||
private boolean isValidCandidate(Candidate c) {
|
||||
return c.isFixed() || isCloseEnoughToSequenceBorder(c);
|
||||
}
|
||||
|
||||
private boolean isCloseEnoughToSequenceBorder(Candidate candidate) {
|
||||
@@ -246,7 +259,7 @@ public class StationarySequence {
|
||||
assert !candidates.contains(candidate) && !getFirst().getTimePoint().after(candidate.getTimePoint()) &&
|
||||
!getLast().getTimePoint().before(candidate.getTimePoint());
|
||||
candidates.add(candidate);
|
||||
if (isCloseEnoughToSequenceBorder(candidate)) {
|
||||
if (isValidCandidate(candidate)) {
|
||||
candidatesEffectivelyAdded.add(candidate);
|
||||
candidatesEffectivelyRemoved.remove(candidate);
|
||||
}
|
||||
@@ -269,7 +282,7 @@ public class StationarySequence {
|
||||
void remove(Candidate candidate, Set<Candidate> candidatesEffectivelyAdded, Set<Candidate> candidatesEffectivelyRemoved,
|
||||
NavigableSet<StationarySequence> stationarySequenceSetToUpdate) {
|
||||
assert candidates.contains(candidate);
|
||||
final boolean wasValidCandidate = isCloseEnoughToSequenceBorder(candidate);
|
||||
final boolean wasValidCandidate = isValidCandidate(candidate);
|
||||
final boolean wasFirst = candidate == getFirst();
|
||||
final boolean wasLast = candidate == getLast();
|
||||
if (wasFirst || size() == 2) { // if size() == 2 then it will shrink to 1 and this sequence shall be removed
|
||||
|
||||
Reference in new issue
Block a user