Merge branch 'master' into bug4202

This commit is contained in:
Steffen Schaefer
2018-08-08 07:58:14 +02:00
5 changed files with 51 additions and 31 deletions
@@ -46,7 +46,11 @@ public enum MaxPointsReason {
/** Time limit Expired */
TLE(/* discardable */ true, /* advanceCompetitorsTrackedWorse */ true, /* appliesAtStartOfRace */ false),
/** Standard Penalty by Race Committee; gives a certain number of penalty points on top of rank-inferred score */
STP(/* discardable */ true, /* advanceCompetitorsTrackedWorse */ false, /* appliesAtStartOfRace */ true);
STP(/* discardable */ true, /* advanceCompetitorsTrackedWorse */ false, /* appliesAtStartOfRace */ true),
/** Disqualified after causing a tangle in an incident */
DCT(/* discardable */ true, /* advanceCompetitorsTrackedWorse */ true, /* appliesAtStartOfRace */ false),
/** Retired after causing a tangle */
RCT(/* discardable */ true, /* advanceCompetitorsTrackedWorse */ true, /* appliesAtStartOfRace */ false);
private final boolean discardable;
@@ -16,6 +16,7 @@ import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogDependentStartTimeEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPassChangeEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl;
import com.sap.sailing.domain.abstractlog.race.impl.SimpleRaceLogIdentifierImpl;
import com.sap.sailing.domain.base.CompetitorWithBoat;
@@ -73,5 +74,8 @@ public class TrackedRaceStartTimeUpdateForDependentStartTimeTest extends TrackBa
assertEquals(r1StartTimeToSet, r1StartTime[0]);
assertNotNull(r2StartTime[0]);
assertEquals(r1StartTimeToSet.plus(startTimeDiff), r2StartTime[0]);
// bug 4708: test that r2's start time is reverted to null after r1 loses its start time
r1RaceLog.add(new RaceLogPassChangeEventImpl(MillisecondsTimePoint.now(), author, /* pass */ 1));
assertNull(r2StartTime[0]);
}
}
@@ -698,8 +698,9 @@ public class ManeuverDetectorImpl extends AbstractManeuverDetectorImpl {
} catch (NoWindException e) {
tackAfterManeuver = null;
}
maneuver = new ManeuverWithMainCurveBoundariesImpl(maneuverType, tackAfterManeuver, maneuverPosition, maneuverMainCurveDetails.getTimePoint(),
maneuverMainCurveDetails.extractCurveBoundariesOnly(), maneuverUnstableCourseAndSpeedBoundaries,
maneuver = new ManeuverWithMainCurveBoundariesImpl(maneuverType, tackAfterManeuver, maneuverPosition,
maneuverMainCurveDetails.getTimePoint(), maneuverMainCurveDetails.extractCurveBoundariesOnly(),
maneuverUnstableCourseAndSpeedBoundaries,
maneuverMainCurveDetails.getMaxTurningRateInDegreesPerSecond(), markPassing, maneuverLoss);
}
return maneuver;
@@ -723,7 +724,8 @@ public class ManeuverDetectorImpl extends AbstractManeuverDetectorImpl {
// For upwind/downwind legs, find the mean course between inbound and outbound course and project actual
// and
// extrapolated positions onto it:
Bearing middleManeuverAngle = speedWithBearingWhenSpeedStartedToDrop.getBearing().middle(speedWithBearingAfterManeuver.getBearing());
Bearing middleManeuverAngle = speedWithBearingWhenSpeedStartedToDrop.getBearing()
.middle(speedWithBearingAfterManeuver.getBearing());
// extrapolate maximum speed before maneuver to time point of maximum speed after maneuver and project
// resulting position
// onto the average maneuver course; compare to the projected position actually reached at the time
@@ -731,9 +733,9 @@ public class ManeuverDetectorImpl extends AbstractManeuverDetectorImpl {
// maneuver:
Position positionWhenSpeedStartedToDrop = track.getEstimatedPosition(timePointWhenSpeedStartedToDrop,
/* extrapolate */ false);
Position extrapolatedPositionAtTimePointOfMaxSpeedAfterManeuver = speedWithBearingWhenSpeedStartedToDrop.travelTo(
positionWhenSpeedStartedToDrop, timePointWhenSpeedStartedToDrop,
timePointWhenSpeedLevelledOffAfterManeuver);
Position extrapolatedPositionAtTimePointOfMaxSpeedAfterManeuver = speedWithBearingWhenSpeedStartedToDrop
.travelTo(positionWhenSpeedStartedToDrop, timePointWhenSpeedStartedToDrop,
timePointWhenSpeedLevelledOffAfterManeuver);
Position actualPositionAtTimePointOfMaxSpeedAfterManeuver = track
.getEstimatedPosition(timePointWhenSpeedLevelledOffAfterManeuver, /* extrapolate */ false);
Position projectedExtrapolatedPositionAtTimePointOfMaxSpeedAfterManeuver = extrapolatedPositionAtTimePointOfMaxSpeedAfterManeuver
@@ -745,9 +747,8 @@ public class ManeuverDetectorImpl extends AbstractManeuverDetectorImpl {
Distance projectedDistanceSailedIfNotManeuvering = positionWhenSpeedStartedToDrop
.getDistance(projectedExtrapolatedPositionAtTimePointOfMaxSpeedAfterManeuver);
return new ManeuverLoss(projectedDistanceSailed, projectedDistanceSailedIfNotManeuvering,
positionWhenSpeedStartedToDrop,
actualPositionAtTimePointOfMaxSpeedAfterManeuver, maneuverDuration, speedWithBearingWhenSpeedStartedToDrop,
middleManeuverAngle);
positionWhenSpeedStartedToDrop, actualPositionAtTimePointOfMaxSpeedAfterManeuver, maneuverDuration,
speedWithBearingWhenSpeedStartedToDrop, middleManeuverAngle);
}
protected Duration getDurationForDouglasPeuckerExtensionForMainCurveAnalysis(Duration approximateManeuverDuration) {
@@ -938,11 +939,25 @@ public class ManeuverDetectorImpl extends AbstractManeuverDetectorImpl {
if (isCourseChangeLimitExceededForCurveExtension(maneuverMainCurveDetails, maneuverStart)) {
maneuverStart = null;
}
// Stable course analysis is considered as not necessary for preparation phase of maneuver because no
// oversteering is usually performed before maneuver
TimePoint stableBearingAnalysisUntil = maneuverStart == null ? maneuverMainCurveDetails.getTimePointBefore()
: maneuverStart.getExtensionTimePoint();
Speed lowestSpeed = maneuverStart == null ? null : maneuverStart.getLowestSpeedWithinExtensionArea();
double courseChangeSinceManeuverMainCurveInDegrees = maneuverStart == null ? 0
: maneuverStart.getCourseChangeInDegreesWithinExtensionArea();
stepsToAnalyze = getSpeedWithBearingStepsWithinTimeRange(stepsToAnalyze, earliestTimePointForSpeedTrendAnalysis,
stableBearingAnalysisUntil);
ManeuverCurveBoundaryExtension stableBearingExtension = findStableBearingWithMaxAbsCourseChangeSpeed(
stepsToAnalyze, true, MAX_TURNING_RATE_IN_DEG_PER_SECOND_FOR_STABLE_COURSE_ANALYSIS);
if (stableBearingExtension != null
&& !isCourseChangeLimitExceededForCurveExtension(maneuverMainCurveDetails, stableBearingExtension)) {
maneuverStart = stableBearingExtension;
courseChangeSinceManeuverMainCurveInDegrees += stableBearingExtension
.getCourseChangeInDegreesWithinExtensionArea();
if (lowestSpeed == null
|| lowestSpeed.compareTo(stableBearingExtension.getLowestSpeedWithinExtensionArea()) > 0) {
lowestSpeed = stableBearingExtension.getLowestSpeedWithinExtensionArea();
}
}
return maneuverStart != null
? new ManeuverCurveBoundaryExtension(maneuverStart.getExtensionTimePoint(),
maneuverStart.getSpeedWithBearingAtExtensionTimePoint(),
@@ -959,8 +974,8 @@ public class ManeuverDetectorImpl extends AbstractManeuverDetectorImpl {
if (curveBoundaryExtension == null) {
return false;
}
return Math.abs(curveBoundaryExtension.getCourseChangeInDegreesWithinExtensionArea()) > Math
.abs(curveBoundaryExtension.getCourseChangeInDegreesWithinExtensionArea()) / 3.0;
return Math.abs(maneuverMainCurveDetails.getDirectionChangeInDegrees()) / 2.0 > Math
.abs(curveBoundaryExtension.getCourseChangeInDegreesWithinExtensionArea());
}
/**
@@ -188,8 +188,9 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
public void onStartTimeChanged(ReadonlyRaceState state) {
final TimePoint oldStartTime = getStartOfRace();
invalidateStartTime();
if (!Util.equalsWithNull(oldStartTime, getStartOfRace())) {
onStartTimeChangedByRaceCommittee(getStartOfRace());
final TimePoint startTimeFromRaceLog = state.getStartTime();
if (!Util.equalsWithNull(oldStartTime, startTimeFromRaceLog)) {
onStartTimeChangedByRaceCommittee(startTimeFromRaceLog);
}
}
};
@@ -23,6 +23,7 @@ import org.apache.http.message.BasicNameValuePair;
import org.json.simple.parser.ParseException;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.tracking.StartTimeChangedListener;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.TimePoint;
@@ -41,10 +42,13 @@ public class StartTimeUpdateHandler extends UpdateHandler implements StartTimeCh
* a new start time is received.
*/
private final Regatta regatta;
private final RaceAbortedHandler raceAbortedHandler;
public StartTimeUpdateHandler(URI updateURI, String tracTracUsername, String tracTracPassword,
public StartTimeUpdateHandler(URI updateURI, String username, String password,
Serializable tracTracEventId, Serializable raceId, Regatta regatta) {
super(updateURI, ACTION, tracTracUsername, tracTracPassword, tracTracEventId, raceId);
super(updateURI, ACTION, username, password, tracTracEventId, raceId);
this.raceAbortedHandler = new RaceAbortedHandler(updateURI, username, password, tracTracEventId, raceId);
this.regatta = regatta;
}
@@ -52,20 +56,12 @@ public class StartTimeUpdateHandler extends UpdateHandler implements StartTimeCh
public void startTimeChanged(TimePoint newStartTime) throws MalformedURLException, IOException, URISyntaxException {
if (isActive()) {
if (newStartTime == null) {
/*
* Do not reset start time based on request by Jorge from TracTrac:
*
* """
* We have detected that when you want to update the race start time your
* system sends before a message to reset the race start time. When your
* system invokes the first service our system changes the race start time
* to null and this value causes some secondary effects in our side.
*
* Can you just send the update_race_start_time without the
* reset_race_start_time? The reset_race_start_time service has to be used
* if you want to set the value to null.
* """
/* notify race status as POSTPONED according to Jorge's comment https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4708#c5 :
* The method that @frank has commented has to work:
* http://em.aws.tractrac.com/update_race_status?eventid=5f2f20f0-6cb2-0136-9eca-60a44ce903c3&raceid=81c082a0-7b1f-0136-166e-028f184941da&username=trac%40sapsailing.com&password=sap0912&race_status=POSTPONED
* This method changes the race start time to null.
*/
raceAbortedHandler.raceAborted(Flags.AP); // will send POSTPONED
} else {
HashMap<String, String> additionalParameters = new HashMap<String, String>();
additionalParameters.put(FIELD_RACE_START_TIME, String.valueOf(newStartTime.asMillis()));