mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-01 08:40:52 +00:00
added time-on-time and time-on-distance fields and listener pattern on Competitor/DynamicCompetitor
This commit is contained in:
1 parent
33c479260b
commit
26d178b3d9
8 files changed
+149
-2
No files matched your search
+33
@@ -2,7 +2,9 @@ package com.sap.sailing.domain.base;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.IsManagedByCache;
|
||||
import com.sap.sse.common.Named;
|
||||
import com.sap.sse.common.WithID;
|
||||
@@ -39,4 +41,35 @@ public interface Competitor extends Named, WithID, IsManagedByCache<SharedDomain
|
||||
* without effect.
|
||||
*/
|
||||
void removeCompetitorChangeListener(CompetitorChangeListener listener);
|
||||
|
||||
/**
|
||||
* The default time-on-time handicap factor for this competitor. If <code>null</code>, no time-on-time handicap
|
||||
* factor is defined for this competitor. For a simple time-on-time scheme, the factor is multiplied with the actual
|
||||
* time sailed to obtain the corrected time. For a "performance line" system, afterwards an additional
|
||||
* distance-based allowance may be subtracted from the resulting time.
|
||||
* <p>
|
||||
*
|
||||
* A particular regatta can make specific arrangements and override this default value for this competitor in its
|
||||
* {@link RegattaLog}, accommodating for the fact that in between regattas competitors may get a new, different
|
||||
* rating, resulting in different handicaps for different regattas.
|
||||
*
|
||||
* @see #getTimeOnDistanceAllowancePerNauticalMile
|
||||
*/
|
||||
Double getTimeOnTimeFactor();
|
||||
|
||||
/**
|
||||
* The default time-on-distance time allowance for this competitor, used in handicap regattas. If <code>null</code>,
|
||||
* no time-on-distance allowance is defined for this competitor. For a simple time-on-distance scheme, the factor is
|
||||
* multiplied with the (windward) course length and the result is subtracted from the actual time sailed to obtain
|
||||
* the corrected time. For a "performance line" system, the actual time sailed will be multiplied with the
|
||||
* {@link #getTimeOnTimeFactor() time-on-time factor} before subtracting the time-on-distance allowance.
|
||||
* <p>
|
||||
*
|
||||
* A particular regatta can make specific arrangements and override this default value for this competitor in its
|
||||
* {@link RegattaLog}, accommodating for the fact that in between regattas competitors may get a new, different
|
||||
* rating, resulting in different handicaps for different regattas.
|
||||
*
|
||||
* @see #getTimeOnTimeFactor
|
||||
*/
|
||||
Duration getTimeOnDistanceAllowancePerNauticalMile();
|
||||
}
|
||||
+5
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.base;
|
||||
import java.net.URI;
|
||||
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.Duration;
|
||||
|
||||
public interface CompetitorChangeListener extends BoatChangeListener, NationalityChangeListener {
|
||||
void colorChanged(Color oldColor, Color newColor);
|
||||
@@ -12,4 +13,8 @@ public interface CompetitorChangeListener extends BoatChangeListener, Nationalit
|
||||
void emailChanged(String oldEmail, String newEmail);
|
||||
|
||||
void flagImageChanged(URI oldFlagImageURI, URI newFlagImageURI);
|
||||
|
||||
void timeOnTimeFactorChanged(Double oldTimeOnTimeFactor, Double newTimeOnTimeFactor);
|
||||
|
||||
void timeOnDistanceAllowancePerNauticalMileChanged(Duration oldTimeOnDistanceAllowancePerNauticalMile, Duration newTimeOnDistanceAllowancePerNauticalMile);
|
||||
}
|
||||
+36
@@ -11,6 +11,7 @@ import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.CompetitorChangeListener;
|
||||
import com.sap.sailing.domain.base.SharedDomainFactory;
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class CompetitorImpl implements DynamicCompetitor {
|
||||
@@ -23,6 +24,8 @@ public class CompetitorImpl implements DynamicCompetitor {
|
||||
private transient Set<CompetitorChangeListener> listeners;
|
||||
private String email;
|
||||
private URI flagImage;
|
||||
private Double timeOnTimeFactor;
|
||||
private Duration timeOnDistanceAllowancePerNauticalMile;
|
||||
|
||||
public CompetitorImpl(Serializable id, String name, Color color, String email, URI flagImage, DynamicTeam team, DynamicBoat boat) {
|
||||
this.id = id;
|
||||
@@ -153,4 +156,37 @@ public class CompetitorImpl implements DynamicCompetitor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getTimeOnTimeFactor() {
|
||||
return timeOnTimeFactor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Duration getTimeOnDistanceAllowancePerNauticalMile() {
|
||||
return timeOnDistanceAllowancePerNauticalMile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTimeOnTimeFactor(Double timeOnTimeFactor) {
|
||||
Double oldTimeOnTimeFactor = this.timeOnTimeFactor;
|
||||
this.timeOnTimeFactor = timeOnTimeFactor;
|
||||
if (!Util.equalsWithNull(oldTimeOnTimeFactor, timeOnTimeFactor)) {
|
||||
for (CompetitorChangeListener listener : getListeners()) {
|
||||
listener.timeOnTimeFactorChanged(oldTimeOnTimeFactor, timeOnTimeFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTimeOnDistanceAllowancePerNauticalMile(Duration timeOnDistanceAllowancePerNauticalMile) {
|
||||
Duration oldTimeOnDistanceAllowancePerNauticalMile = this.timeOnDistanceAllowancePerNauticalMile;
|
||||
this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile;
|
||||
if (!Util.equalsWithNull(oldTimeOnDistanceAllowancePerNauticalMile, timeOnDistanceAllowancePerNauticalMile)) {
|
||||
for (CompetitorChangeListener listener : getListeners()) {
|
||||
listener.timeOnDistanceAllowancePerNauticalMileChanged(oldTimeOnDistanceAllowancePerNauticalMile, timeOnDistanceAllowancePerNauticalMile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+5
@@ -5,6 +5,7 @@ import java.net.URI;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.Renamable;
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.Duration;
|
||||
|
||||
public interface DynamicCompetitor extends Competitor, Renamable {
|
||||
DynamicBoat getBoat();
|
||||
@@ -16,4 +17,8 @@ public interface DynamicCompetitor extends Competitor, Renamable {
|
||||
void setEmail(String email);
|
||||
|
||||
void setFlagImage(URI flagImage);
|
||||
|
||||
void setTimeOnTimeFactor(Double timeOnTimeFactor);
|
||||
|
||||
void setTimeOnDistanceAllowancePerNauticalMile(Duration timeOnDistanceAllowancePerNauticalMile);
|
||||
}
|
||||
+45
@@ -21,6 +21,7 @@ import com.sap.sailing.domain.base.WithNationality;
|
||||
import com.sap.sailing.domain.base.impl.DomainFactoryImpl;
|
||||
import com.sap.sailing.domain.base.impl.DynamicCompetitor;
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.impl.RGBColor;
|
||||
|
||||
/**
|
||||
@@ -53,6 +54,12 @@ public class CompetitorListenerTest extends AbstractSerializationTest {
|
||||
private boolean flagImageChanged;
|
||||
private URI oldFlagImageURL;
|
||||
private URI newFlagImageURL;
|
||||
private boolean timeOnTimeFactorChanged;
|
||||
private Double oldTimeOnTimeFactor;
|
||||
private Double newTimeOnTimeFactor;
|
||||
private boolean timeOnDistanceAllowancePerNauticalMileChanged;
|
||||
private Duration oldTimeOnDistanceAllowancePerNauticalMile;
|
||||
private Duration newTimeOnDistanceAllowancePerNauticalMile;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -77,6 +84,12 @@ public class CompetitorListenerTest extends AbstractSerializationTest {
|
||||
flagImageChanged = false;
|
||||
oldFlagImageURL = null;
|
||||
newFlagImageURL = null;
|
||||
timeOnTimeFactorChanged = false;
|
||||
oldTimeOnTimeFactor = null;
|
||||
newTimeOnTimeFactor = null;
|
||||
timeOnDistanceAllowancePerNauticalMileChanged = false;
|
||||
oldTimeOnDistanceAllowancePerNauticalMile = null;
|
||||
newTimeOnDistanceAllowancePerNauticalMile = null;
|
||||
listener = new CompetitorChangeListener() {
|
||||
private static final long serialVersionUID = 4581029778988240209L;
|
||||
|
||||
@@ -122,6 +135,22 @@ public class CompetitorListenerTest extends AbstractSerializationTest {
|
||||
CompetitorListenerTest.this.oldFlagImageURL = oldFlagImageURL;
|
||||
CompetitorListenerTest.this.newFlagImageURL = newFlagImageURL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void timeOnTimeFactorChanged(Double oldTimeOnTimeFactor, Double newTimeOnTimeFactor) {
|
||||
timeOnTimeFactorChanged = true;
|
||||
CompetitorListenerTest.this.oldTimeOnTimeFactor = oldTimeOnTimeFactor;
|
||||
CompetitorListenerTest.this.newTimeOnTimeFactor = newTimeOnTimeFactor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void timeOnDistanceAllowancePerNauticalMileChanged(
|
||||
Duration oldTimeOnDistanceAllowancePerNauticalMile,
|
||||
Duration newTimeOnDistanceAllowancePerNauticalMile) {
|
||||
timeOnDistanceAllowancePerNauticalMileChanged = true;
|
||||
CompetitorListenerTest.this.oldTimeOnDistanceAllowancePerNauticalMile = oldTimeOnDistanceAllowancePerNauticalMile;
|
||||
CompetitorListenerTest.this.newTimeOnDistanceAllowancePerNauticalMile = newTimeOnDistanceAllowancePerNauticalMile;
|
||||
}
|
||||
};
|
||||
competitor.addCompetitorChangeListener(listener);
|
||||
}
|
||||
@@ -138,6 +167,22 @@ public class CompetitorListenerTest extends AbstractSerializationTest {
|
||||
assertNull(competitor.getTeam().getNationality());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeTimeOnTimeFactor() {
|
||||
competitor.setTimeOnTimeFactor(1.209);
|
||||
assertTrue(timeOnTimeFactorChanged);
|
||||
assertNull(oldTimeOnTimeFactor);
|
||||
assertEquals(1.209, newTimeOnTimeFactor, 0.00000001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeTimeOnDistanceAllowancePerNauticalMile() {
|
||||
competitor.setTimeOnDistanceAllowancePerNauticalMile(Duration.ONE_HOUR);
|
||||
assertTrue(timeOnDistanceAllowancePerNauticalMileChanged);
|
||||
assertNull(oldTimeOnDistanceAllowancePerNauticalMile);
|
||||
assertEquals(Duration.ONE_HOUR.asMillis(), newTimeOnDistanceAllowancePerNauticalMile.asMillis());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleCompetitorListenerPatternForName() {
|
||||
competitor.setName("Dr. Hasso Plattner");
|
||||
|
||||
+12
@@ -23,6 +23,7 @@ import com.sap.sailing.domain.tracking.RaceChangeListener;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener;
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.concurrent.ConcurrentWeakHashMap;
|
||||
import com.sap.sse.concurrent.LockUtil;
|
||||
import com.sap.sse.concurrent.NamedReentrantReadWriteLock;
|
||||
@@ -127,6 +128,17 @@ public class LeaderboardCacheManager {
|
||||
public void flagImageChanged(URI oldFlagImageURL, URI newFlagImageURL) {
|
||||
removeFromCache(leaderboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void timeOnTimeFactorChanged(Double oldTimeOnTimeFactor, Double newTimeOnTimeFactor) {
|
||||
removeFromCache(leaderboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void timeOnDistanceAllowancePerNauticalMileChanged(Duration oldTimeOnDistanceAllowancePerNauticalMile,
|
||||
Duration newTimeOnDistanceAllowancePerNauticalMile) {
|
||||
removeFromCache(leaderboard);
|
||||
}
|
||||
}
|
||||
|
||||
private class CacheInvalidationUponScoreCorrectionListener implements ScoreCorrectionListener {
|
||||
|
||||
+2
-2
@@ -127,7 +127,7 @@ public class ORCPerformanceCurveCertificate implements Serializable {
|
||||
* {@link #durationPerNauticalMileAtTrueWindAngleAndSpeed} which duration is expected for the competitor
|
||||
* described by this certificate to sail the complete <code>leg</code>.
|
||||
*/
|
||||
private Map<Speed, Duration> getAllowancesForLegPerTrueWindSpeed(TrackedLeg leg, Bearing trueWindToDirection) throws FunctionEvaluationException {
|
||||
protected Map<Speed, Duration> getAllowancesForLegPerTrueWindSpeed(TrackedLeg leg, Bearing trueWindToDirection) throws FunctionEvaluationException {
|
||||
Bearing legBearing = leg.getLegBearing(leg.getReferenceTimePoint());
|
||||
Distance greatCircleLegDistance = leg.getGreatCircleDistance(leg.getReferenceTimePoint());
|
||||
if (trueWindToDirection == null) {
|
||||
@@ -145,7 +145,7 @@ public class ORCPerformanceCurveCertificate implements Serializable {
|
||||
*
|
||||
* If the <code>competitor</code> hasn't started the race yet, <code>null</code> is returned.
|
||||
*/
|
||||
private Map<Speed, Duration> getAllowances(TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) {
|
||||
protected Map<Speed, Duration> getAllowances(TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) {
|
||||
final Map<Speed, Duration> result;
|
||||
if (trackedRace.getMarkPassings(competitor).isEmpty()) {
|
||||
result = null;
|
||||
|
||||
+11
@@ -10,6 +10,7 @@ import com.sap.sailing.domain.base.Team;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.IsManagedByCache;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
@@ -89,6 +90,16 @@ public class DummyMarkPassingWithTimePointOnly implements MarkPassing {
|
||||
public URI getFlagImage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getTimeOnTimeFactor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Duration getTimeOnDistanceAllowancePerNauticalMile() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user