mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-13 22:15:26 +00:00
Merge branch 'master' of ssh://sapsailing.com/home/trac/git into bug5384
This commit is contained in:
commit
2833b5d5d5
69 files changed
+565
-462
No files matched your search
@@ -94,6 +94,7 @@ SAP is at the center of today’s technology revolution, developing innovations
|
||||
## HowTo
|
||||
|
||||
* [[Onboarding|wiki/howto/onboarding]]
|
||||
* [[Managing Events with the AdminConsole|wiki/howto/adminconsoleinstructions]]
|
||||
* [[Importing Sessions from Expedition|wiki/howto/expeditionimport]]
|
||||
* [[Checking our DBs for a user record by e-mail|wiki/howto/privacy]]
|
||||
* [[Managing ORC Performance Curve Regattas|wiki/howto/setup-orc-regatta]]
|
||||
|
||||
@@ -372,6 +372,7 @@ public enum DetailType implements Serializable {
|
||||
allowed.add(RACE_IMPLIED_WIND);
|
||||
allowed.add(RACE_CALCULATED_TIME_AT_ESTIMATED_ARRIVAL_AT_COMPETITOR_FARTHEST_AHEAD);
|
||||
allowed.add(RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS);
|
||||
allowed.add(RACE_CURRENT_COURSE_OVER_GROUND_IN_TRUE_DEGREES);
|
||||
allowed.add(RACE_CURRENT_DISTANCE_FOILED_IN_METERS);
|
||||
allowed.add(RACE_CURRENT_DURATION_FOILED_IN_SECONDS);
|
||||
allowed.add(RACE_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD_IN_METERS);
|
||||
|
||||
+1
-10
@@ -16,20 +16,15 @@ public class BoatClassDTO extends NamedDTO implements Serializable, Comparable<B
|
||||
|
||||
private Distance hullLength;
|
||||
private Distance hullBeam;
|
||||
private String displayName;
|
||||
|
||||
BoatClassDTO() {}
|
||||
|
||||
public BoatClassDTO(String name, String displayName, Distance hullLength, Distance hullBeam) {
|
||||
public BoatClassDTO(String name, Distance hullLength, Distance hullBeam) {
|
||||
super(name);
|
||||
this.hullLength = hullLength;
|
||||
this.hullBeam = hullBeam;
|
||||
}
|
||||
|
||||
public BoatClassDTO(String name, Distance hullLength, Distance hullBeam) {
|
||||
this(name, /* display name */ null, hullLength, hullBeam);
|
||||
}
|
||||
|
||||
public Distance getHullLength() {
|
||||
return hullLength;
|
||||
}
|
||||
@@ -38,10 +33,6 @@ public class BoatClassDTO extends NamedDTO implements Serializable, Comparable<B
|
||||
return hullBeam;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(BoatClassDTO o) {
|
||||
return getName().compareToIgnoreCase(o.getName());
|
||||
|
||||
+11
@@ -5,6 +5,7 @@ import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.common.RaceIdentifier;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.common.impl.MeterDistance;
|
||||
import com.sap.sse.common.Bearing;
|
||||
@@ -141,6 +142,8 @@ public class LeaderboardEntryDTO implements Serializable {
|
||||
* farthest ahead for all subsequent legs.
|
||||
*/
|
||||
public Duration calculatedTimeAtEstimatedArrivalAtCompetitorFarthestAhead;
|
||||
|
||||
public SpeedWithBearing currentSpeedAndCourseOverGround;
|
||||
|
||||
/**
|
||||
* If <code>null</code>, no leg details are known yet, the race is not being tracked or the details
|
||||
@@ -618,6 +621,8 @@ public class LeaderboardEntryDTO implements Serializable {
|
||||
result = prime * result + ((calculatedTime == null) ? 0 : calculatedTime.hashCode());
|
||||
result = prime * result + ((calculatedTimeAtEstimatedArrivalAtCompetitorFarthestAhead == null) ? 0
|
||||
: calculatedTimeAtEstimatedArrivalAtCompetitorFarthestAhead.hashCode());
|
||||
result = prime * result + ((currentSpeedAndCourseOverGround == null) ? 0
|
||||
: currentSpeedAndCourseOverGround.hashCode());
|
||||
result = prime * result + (discarded ? 1231 : 1237);
|
||||
result = prime * result + ((distanceToStarboardSideOfStartLineInMeters == null) ? 0
|
||||
: distanceToStarboardSideOfStartLineInMeters.hashCode());
|
||||
@@ -703,6 +708,12 @@ public class LeaderboardEntryDTO implements Serializable {
|
||||
} else if (!calculatedTimeAtEstimatedArrivalAtCompetitorFarthestAhead
|
||||
.equals(other.calculatedTimeAtEstimatedArrivalAtCompetitorFarthestAhead))
|
||||
return false;
|
||||
if (currentSpeedAndCourseOverGround == null) {
|
||||
if (other.currentSpeedAndCourseOverGround != null)
|
||||
return false;
|
||||
} else if (!currentSpeedAndCourseOverGround
|
||||
.equals(other.currentSpeedAndCourseOverGround))
|
||||
return false;
|
||||
if (discarded != other.discarded)
|
||||
return false;
|
||||
if (distanceToStarboardSideOfStartLineInMeters == null) {
|
||||
|
||||
+2
-1
@@ -24,7 +24,8 @@ public enum AvailableWindFinderSpotCollections {
|
||||
TEGERNSEE("tegernsee"),
|
||||
TORTOLA("tortola"),
|
||||
AUCKLAND("auckland"),
|
||||
AARHUS("aarhus");
|
||||
AARHUS("aarhus"),
|
||||
NEW_YORK("new_york");
|
||||
|
||||
private final String name;
|
||||
|
||||
|
||||
+5
-5
@@ -65,7 +65,7 @@ public class CurrentRaceFilterImplTest {
|
||||
_505RaceRows.add(_505RaceRow);
|
||||
_505Series.add(new SeriesWithRowsImpl("Default", /* isMedal */ false, /* isFleetsCanRunInParallel */ false, _505RaceRows));
|
||||
final RaceGroup _505 = new RaceGroupImpl("505", /* displayName */ null,
|
||||
new BoatClassImpl(BoatClassMasterdata._5O5.getDisplayName(), BoatClassMasterdata._5O5), /* canBoatsOfCompetitorsChangePerRace */ false,
|
||||
new BoatClassImpl(BoatClassMasterdata._5O5), /* canBoatsOfCompetitorsChangePerRace */ false,
|
||||
_505Series, /* regattaConfiguration */ null);
|
||||
return _505;
|
||||
}
|
||||
@@ -75,7 +75,7 @@ public class CurrentRaceFilterImplTest {
|
||||
final List<RaceRow> yesRaceRows = Arrays.asList(createRaceRow(1, 9, "R", "Yellow"), createRaceRow(1, 9, "R", "Blue"));
|
||||
yesSeries.add(new SeriesWithRowsImpl("Default", /* isMedal */ false, /* isFleetsCanRunInParallel */ true, yesRaceRows));
|
||||
final RaceGroup yes = new RaceGroupImpl("YES", /* displayName */ null,
|
||||
new BoatClassImpl(BoatClassMasterdata._470.getDisplayName(), BoatClassMasterdata._470), /* canBoatsOfCompetitorsChangePerRace */ false,
|
||||
new BoatClassImpl(BoatClassMasterdata._470), /* canBoatsOfCompetitorsChangePerRace */ false,
|
||||
yesSeries, /* regattaConfiguration */ null);
|
||||
return yes;
|
||||
}
|
||||
@@ -89,7 +89,7 @@ public class CurrentRaceFilterImplTest {
|
||||
final List<RaceRow> isafMedalRaceRows = Arrays.asList(createRaceRow(1, 1, "M", "Medal"));
|
||||
isafSeries.add(new SeriesWithRowsImpl("Medal", /* isMedal */ true, /* isFleetsCanRunInParallel */ true, isafMedalRaceRows));
|
||||
final RaceGroup isaf = new RaceGroupImpl("ISAF", /* displayName */ null,
|
||||
new BoatClassImpl(BoatClassMasterdata._470.getDisplayName(), BoatClassMasterdata._470), /* canBoatsOfCompetitorsChangePerRace */ false,
|
||||
new BoatClassImpl(BoatClassMasterdata._470), /* canBoatsOfCompetitorsChangePerRace */ false,
|
||||
isafSeries, /* regattaConfiguration */ null);
|
||||
return isaf;
|
||||
}
|
||||
@@ -109,7 +109,7 @@ public class CurrentRaceFilterImplTest {
|
||||
final List<RaceRow> essDay4RaceRows = Arrays.asList(createRaceRow(16, 5, "R", "Default"));
|
||||
essSeries.add(new SeriesWithRowsImpl("Day 4", /* isMedal */ false, /* isFleetsCanRunInParallel */ true, essDay4RaceRows));
|
||||
final RaceGroup ess = new RaceGroupImpl("ESS", /* displayName */ null,
|
||||
new BoatClassImpl(BoatClassMasterdata.EXTREME_40.getDisplayName(), BoatClassMasterdata.EXTREME_40), /* canBoatsOfCompetitorsChangePerRace */ false,
|
||||
new BoatClassImpl(BoatClassMasterdata.EXTREME_40), /* canBoatsOfCompetitorsChangePerRace */ false,
|
||||
essSeries, /* regattaConfiguration */ null);
|
||||
return ess;
|
||||
}
|
||||
@@ -119,7 +119,7 @@ public class CurrentRaceFilterImplTest {
|
||||
final List<RaceRow> leagueRaceRows = Arrays.asList(createRaceRow(1, 15, "F", "Red"), createRaceRow(1, 15, "F", "Green"), createRaceRow(1, 15, "F", "Blue"));
|
||||
leagueSeries.add(new SeriesWithRowsImpl("Default", /* isMedal */ false, /* isFleetsCanRunInParallel */ false, leagueRaceRows));
|
||||
final RaceGroup league = new RaceGroupImpl("League", /* displayName */ null,
|
||||
new BoatClassImpl(BoatClassMasterdata.J70.getDisplayName(), BoatClassMasterdata.J70), /* canBoatsOfCompetitorsChangePerRace */ false,
|
||||
new BoatClassImpl(BoatClassMasterdata.J70), /* canBoatsOfCompetitorsChangePerRace */ false,
|
||||
leagueSeries, /* regattaConfiguration */ null);
|
||||
return league;
|
||||
}
|
||||
|
||||
-2
@@ -45,8 +45,6 @@ public interface BoatClass extends Named, IsManagedByCache<SharedDomainFactory<?
|
||||
*/
|
||||
boolean typicallyStartsUpwind();
|
||||
|
||||
String getDisplayName();
|
||||
|
||||
Distance getHullLength();
|
||||
|
||||
Distance getHullBeam();
|
||||
|
||||
+8
-15
@@ -39,7 +39,6 @@ public class BoatClassImpl extends NamedImpl implements BoatClass {
|
||||
|
||||
private final boolean typicallyStartsUpwind;
|
||||
|
||||
private final String displayName;
|
||||
|
||||
private final Distance hullLength;
|
||||
|
||||
@@ -48,22 +47,20 @@ public class BoatClassImpl extends NamedImpl implements BoatClass {
|
||||
private final BoatHullType hullType;
|
||||
|
||||
public BoatClassImpl(String name, boolean typicallyStartsUpwind) {
|
||||
this(name, typicallyStartsUpwind, /* displayName */ null,
|
||||
// use the typical dinghy parameters as default
|
||||
/* hull length */ new MeterDistance(5), /* hullBeam */ new MeterDistance(1.8),
|
||||
/* hullType */ BoatHullType.MONOHULL);
|
||||
this(name, typicallyStartsUpwind, // use the typical dinghy parameters as default
|
||||
/* hull length */ new MeterDistance(5),
|
||||
/* hullBeam */ new MeterDistance(1.8), /* hullType */ BoatHullType.MONOHULL);
|
||||
}
|
||||
|
||||
public BoatClassImpl(String name, BoatClassMasterdata masterData) {
|
||||
this(name, masterData.isTypicallyStartsUpwind(), masterData.getDisplayName(), masterData.getHullLength(),
|
||||
masterData.getHullBeam(), masterData.getHullType());
|
||||
public BoatClassImpl(BoatClassMasterdata masterData) {
|
||||
this(masterData.getDisplayName(), masterData.isTypicallyStartsUpwind(), masterData.getHullLength(), masterData.getHullBeam(),
|
||||
masterData.getHullType());
|
||||
}
|
||||
|
||||
public BoatClassImpl(String name, boolean typicallyStartsUpwind, String displayName,
|
||||
Distance hullLength, Distance hullBeam, BoatHullType hullType) {
|
||||
public BoatClassImpl(String name, boolean typicallyStartsUpwind, Distance hullLength,
|
||||
Distance hullBeam, BoatHullType hullType) {
|
||||
super(name);
|
||||
this.typicallyStartsUpwind = typicallyStartsUpwind;
|
||||
this.displayName = displayName;
|
||||
this.hullLength = hullLength;
|
||||
this.hullBeam = hullBeam;
|
||||
this.hullType = hullType;
|
||||
@@ -136,10 +133,6 @@ public class BoatClassImpl extends NamedImpl implements BoatClass {
|
||||
return domainFactory.getOrCreateBoatClass(getName(), typicallyStartsUpwind());
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public Distance getHullBeam() {
|
||||
return hullBeam;
|
||||
}
|
||||
|
||||
+1
-1
@@ -353,7 +353,7 @@ public class SharedDomainFactoryImpl<RLR extends RaceLogResolver> implements Sha
|
||||
result = boatClassCache.get(unifiedBoatClassName);
|
||||
if (result == null) {
|
||||
if (unifiedBoatClassName != null && boatClassMasterdata != null) {
|
||||
result = new BoatClassImpl(boatClassMasterdata.getDisplayName(), boatClassMasterdata);
|
||||
result = new BoatClassImpl(boatClassMasterdata);
|
||||
boatClassCache.put(unifiedBoatClassName, result);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -647,7 +647,7 @@ public class TransientCompetitorAndBoatStoreImpl implements CompetitorAndBoatSto
|
||||
boatDTO = weakBoatDTOCache.get(b);
|
||||
if (boatDTO == null) {
|
||||
BoatClassDTO boatClassDTO = new BoatClassDTO(b.getBoatClass().getName(),
|
||||
b.getBoatClass().getDisplayName(), b.getBoatClass().getHullLength(), b.getBoatClass().getHullBeam());
|
||||
b.getBoatClass().getHullLength(), b.getBoatClass().getHullBeam());
|
||||
boatDTO = new BoatDTO(b.getId().toString(), b.getName(), boatClassDTO, b.getSailID(), b.getColor());
|
||||
weakBoatDTOCache.put(b, boatDTO);
|
||||
}
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard
|
||||
new ThresholdBasedResultDiscardingRuleImpl(new int[0]), new LowPoint(), courseArea);
|
||||
competitorProviderFlexibleLeaderboard = new CompetitorProviderFromRaceColumnsAndRegattaLike(flexibleLeaderboard);
|
||||
regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE,
|
||||
EmptyRegattaLogStore.INSTANCE, "Test Regatta", new BoatClassImpl("49er", BoatClassMasterdata._49ER),
|
||||
EmptyRegattaLogStore.INSTANCE, "Test Regatta", new BoatClassImpl(BoatClassMasterdata._49ER),
|
||||
/* canBoatsOfCompetitorsChangePerRace */ true, CompetitorRegistrationType.CLOSED, /* startDate */ null, /* endDate */null,
|
||||
/* trackedRegattaRegistry */null, new LowPoint(), UUID.randomUUID(),
|
||||
courseArea, /* registrationLinkSecret */ UUID.randomUUID().toString());
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ public class CourseUpdateDuringNonAtomicSerializationTest implements Serializabl
|
||||
removeCalls = new HashMap<>();
|
||||
course = new CourseImpl("Test Course", waypoints);
|
||||
Regatta regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, "Test Regatta",
|
||||
new BoatClassImpl("505", BoatClassMasterdata._5O5),
|
||||
new BoatClassImpl(BoatClassMasterdata._5O5),
|
||||
/* canBoatsOfCompetitorsChangePerRace */ true, CompetitorRegistrationType.CLOSED,
|
||||
/*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null,
|
||||
new LowPoint(), UUID.randomUUID(), new CourseAreaImpl("Alpha", UUID.randomUUID()),
|
||||
|
||||
+4
-4
@@ -33,7 +33,7 @@ public class DomainFactoryImplTest {
|
||||
public void testGetDominantBoatClass_TestWithOneObject() {
|
||||
List<String> list = new ArrayList<>();
|
||||
list.add("LSR");
|
||||
Assert.assertEquals("Laser Int.", domainFactory.getDominantBoatClass(list).getDisplayName());
|
||||
Assert.assertEquals("Laser Int.", domainFactory.getDominantBoatClass(list).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -41,7 +41,7 @@ public class DomainFactoryImplTest {
|
||||
List<String> list = new ArrayList<>();
|
||||
list.add("LSR");
|
||||
list.add("18.Footer");
|
||||
String result = domainFactory.getDominantBoatClass(list).getDisplayName();
|
||||
String result = domainFactory.getDominantBoatClass(list).getName();
|
||||
if(!(result == "Laser Int." || result == "18Footer")) {
|
||||
Assert.assertEquals("Laser Int.", result);
|
||||
}
|
||||
@@ -53,7 +53,7 @@ public class DomainFactoryImplTest {
|
||||
list.add("LSR");
|
||||
list.add("18.Footer");
|
||||
list.add("LSR");
|
||||
String result = domainFactory.getDominantBoatClass(list).getDisplayName();
|
||||
String result = domainFactory.getDominantBoatClass(list).getName();
|
||||
Assert.assertEquals("Laser Int.", result);
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class DomainFactoryImplTest {
|
||||
list.add("18.Footer");
|
||||
list.add("Laser Int.");
|
||||
list.add("Laser");
|
||||
String result = domainFactory.getDominantBoatClass(list).getDisplayName();
|
||||
String result = domainFactory.getDominantBoatClass(list).getName();
|
||||
Assert.assertEquals("Laser Int.", result);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -218,7 +218,7 @@ public abstract class TrackBasedTest {
|
||||
}
|
||||
|
||||
public static RegattaImpl createTestRegatta(String regattaName, Iterable<String> raceColumnNames) {
|
||||
final BoatClass boatClass = new BoatClassImpl("boat class name", BoatClassMasterdata._12M);
|
||||
final BoatClass boatClass = new BoatClassImpl(BoatClassMasterdata._12M);
|
||||
final TimePoint startDate = MillisecondsTimePoint.now();
|
||||
final TimePoint endDate = startDate.plus(MillisecondsDurationImpl.ONE_DAY);
|
||||
final boolean isMedal = false;
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class AbstractMockedRaceMarkPassingTest {
|
||||
final BoatClassImpl boatClass = new BoatClassImpl("boat", true, "boat", new MeterDistance(10), new MeterDistance(5), null);
|
||||
final BoatClassImpl boatClass = new BoatClassImpl("boat", true, new MeterDistance(10), new MeterDistance(5), null);
|
||||
protected Competitor ron = new CompetitorImpl("Ron", "Ron", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
|
||||
protected Competitor tom = new CompetitorImpl("Tom", "Tom", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
|
||||
protected Competitor ben = new CompetitorImpl("Ben", "Ben", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ public class MarkPassingCalculatorWithTrackersOnStartBoatTest extends AbstractEx
|
||||
@Before
|
||||
public void setUp() throws IOException, ParseException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
||||
startOfSetup = MillisecondsTimePoint.now();
|
||||
trackedRace = readRace("/MoevensteinCompetitorPositions.json.gz", "/MoevensteinMarkPositions.json.gz", new BoatClassImpl("J/70", BoatClassMasterdata.J70));
|
||||
trackedRace = readRace("/MoevensteinCompetitorPositions.json.gz", "/MoevensteinMarkPositions.json.gz", new BoatClassImpl(BoatClassMasterdata.J70));
|
||||
markPassings = new HashMap<>();
|
||||
for (final Competitor competitor : trackedRace.getRace().getCompetitors()) {
|
||||
markPassings.put(competitor, trackedRace.getMarkPassings(competitor, /* waitForLatest */ true));
|
||||
|
||||
+2
-1
@@ -394,7 +394,7 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard {
|
||||
this.getScoreCorrection() == null ? null : this.getScoreCorrection().getComment(),
|
||||
this.getScoringScheme() == null ? null : this.getScoringScheme().getType(), this
|
||||
.getScoringScheme().isHigherBetter(), () -> UUID.randomUUID().toString(), addOverallDetails,
|
||||
boatClass==null?null:new BoatClassDTO(boatClass.getName(), boatClass.getDisplayName(), boatClass.getHullLength(), boatClass.getHullBeam()));
|
||||
boatClass==null?null:new BoatClassDTO(boatClass.getName(), boatClass.getHullLength(), boatClass.getHullBeam()));
|
||||
result.type = getLeaderboardType();
|
||||
result.competitors = new ArrayList<>();
|
||||
result.setName(this.getName());
|
||||
@@ -689,6 +689,7 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard {
|
||||
Date timePointOfLastPositionFixAtOrBeforeQueryTimePoint = getTimePointOfLastFixAtOrBefore(competitor, trackedRace, timePoint);
|
||||
if (track != null) {
|
||||
entryDTO.averageSamplingInterval = track.getAverageIntervalBetweenRawFixes();
|
||||
entryDTO.currentSpeedAndCourseOverGround = track.getEstimatedSpeed(timePoint);
|
||||
}
|
||||
if (timePointOfLastPositionFixAtOrBeforeQueryTimePoint != null) {
|
||||
long timeDifferenceInMs = timePoint.asMillis() - timePointOfLastPositionFixAtOrBeforeQueryTimePoint.getTime();
|
||||
|
||||
+1
-1
@@ -629,7 +629,7 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
|
||||
final Set<CertificateHandle> restrictedResults = new HashSet<>();
|
||||
for (final CertificateHandle handle : filterHandlesForCurrentYear(certificateHandles)) {
|
||||
final BoatClassMasterdata boatClassMasterData = BoatClassMasterdata.resolveBoatClass(handle.getBoatClassName());
|
||||
if (boatClassMasterData != null && boatClassMasterData.getDisplayName().equals(boatClass.getDisplayName())) {
|
||||
if (boatClassMasterData != null && boatClassMasterData.getDisplayName().equals(boatClass.getName())) {
|
||||
restrictedResults.add(handle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -753,7 +753,7 @@
|
||||
"acknowledgements": [
|
||||
"Copyright 2016 yanwsh@gmail.com"
|
||||
],
|
||||
"key": "Apache License 2.0"
|
||||
"key": "ASL2.0"
|
||||
}
|
||||
],
|
||||
"licenses": [
|
||||
@@ -781,5 +781,27 @@
|
||||
"key": "UNIDATA",
|
||||
"file": "unidata.txt"
|
||||
}
|
||||
],
|
||||
"disclaimers":[
|
||||
{
|
||||
"title":"SAP Legal Disclosure",
|
||||
"link": "https://www.sap.com/corporate/en/legal/impressum.html",
|
||||
"content": "Please visit ${link} to view the general SAP legal disclosure."
|
||||
},
|
||||
{
|
||||
"title":"YouTube",
|
||||
"link": "https://www.youtube.com/t/terms",
|
||||
"content": "The application utilizes the YouTube video streaming service. Therefore, by using the application, users implicitly agree to the terms of service provided by YouTube, found under ${link}."
|
||||
},
|
||||
{
|
||||
"title":"Google Privacy",
|
||||
"link": "https://policies.google.com/privacy",
|
||||
"content": "The application utilizes services of Google. Therefore, by using the application, users implicitly agree to the privacy policies of Google, as stated under ${link}."
|
||||
},
|
||||
{
|
||||
"title":"Google Maps",
|
||||
"link": "http://www.google.com/intl/en/policies/terms/",
|
||||
"content": "Google Maps Service (\"GM Service\"). If the Cloud Service accesses the GM Service through a Google Maps API, customer's use of the GM Service is subject to Google's Terms of Service, which are set forth at ${link}. If customer does not accept the Google Terms of Service, including, but not limited to, all limitations and restrictions therein, customer may not use the GM Service in the Cloud Service. Use of the GM Service in or through the Cloud Service will constitute customer's acceptance of Google's Terms of Service. Customer's usage of the GM Service in or through the Cloud Service can be terminated by SAP without reason at any time and SAP will not be required to provide an equivalent service via another provider."
|
||||
}
|
||||
]
|
||||
}
|
||||
+12
-3
@@ -3,6 +3,8 @@ package com.sap.sailing.gwt.home.communication.user.profile;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import com.google.gwt.core.shared.GwtIncompatible;
|
||||
import com.sap.sailing.domain.base.CompetitorAndBoatStore;
|
||||
import com.sap.sailing.domain.base.impl.DynamicCompetitor;
|
||||
import com.sap.sailing.domain.common.dto.BoatClassDTO;
|
||||
import com.sap.sailing.gwt.home.communication.SailingAction;
|
||||
import com.sap.sailing.gwt.home.communication.SailingDispatchContext;
|
||||
@@ -11,6 +13,7 @@ import com.sap.sailing.server.impl.preferences.model.BoatClassNotificationPrefer
|
||||
import com.sap.sailing.server.impl.preferences.model.BoatClassNotificationPreferences;
|
||||
import com.sap.sailing.server.impl.preferences.model.CompetitorNotificationPreference;
|
||||
import com.sap.sailing.server.impl.preferences.model.CompetitorNotificationPreferences;
|
||||
import com.sap.sailing.server.interfaces.RacingEventService;
|
||||
import com.sap.sse.gwt.dispatch.shared.exceptions.DispatchException;
|
||||
|
||||
/**
|
||||
@@ -33,8 +36,8 @@ public class GetFavoritesAction implements SailingAction<FavoritesResult> {
|
||||
boolean notifyAboutUpcomingRaces = false, notifyAboutResults = false;
|
||||
if (preferences != null) {
|
||||
for (BoatClassNotificationPreference pref : preferences.getBoatClasses()) {
|
||||
String name = pref.getBoatClass().getName(), displayName = pref.getBoatClass().getDisplayName();
|
||||
selected.add(new BoatClassDTO(name, displayName, pref.getBoatClass().getHullLength(), pref.getBoatClass().getHullBeam()));
|
||||
String name = pref.getBoatClass().getName();
|
||||
selected.add(new BoatClassDTO(name, pref.getBoatClass().getHullLength(), pref.getBoatClass().getHullBeam()));
|
||||
notifyAboutUpcomingRaces |= pref.isNotifyAboutUpcomingRaces();
|
||||
notifyAboutResults |= pref.isNotifyAboutResults();
|
||||
}
|
||||
@@ -50,7 +53,13 @@ public class GetFavoritesAction implements SailingAction<FavoritesResult> {
|
||||
boolean notifyAboutResults = false;
|
||||
if (preferences != null) {
|
||||
for (CompetitorNotificationPreference pref : preferences.getCompetitors()) {
|
||||
selected.add(new SimpleCompetitorWithIdDTO(pref.getCompetitor()));
|
||||
final String competitorId = pref.getCompetitorId();
|
||||
final RacingEventService racingEventService = ctx.getRacingEventService();
|
||||
final CompetitorAndBoatStore competitorAndBoatStore = racingEventService.getCompetitorAndBoatStore();
|
||||
DynamicCompetitor competitor = competitorAndBoatStore.getExistingCompetitorByIdAsString(competitorId);
|
||||
selected.add(competitor == null ?
|
||||
new SimpleCompetitorWithIdDTO(competitorId,"Not found","ID:" + competitorId, null, null)
|
||||
: new SimpleCompetitorWithIdDTO(competitor));
|
||||
notifyAboutResults |= pref.isNotifyAboutResults();
|
||||
}
|
||||
}
|
||||
|
||||
+8
-4
@@ -4,7 +4,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.core.shared.GwtIncompatible;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.CompetitorAndBoatStore;
|
||||
import com.sap.sailing.gwt.home.communication.SailingAction;
|
||||
import com.sap.sailing.gwt.home.communication.SailingDispatchContext;
|
||||
@@ -36,9 +35,14 @@ public class SaveFavoriteCompetitorsAction implements SailingAction<VoidResult>,
|
||||
List<CompetitorNotificationPreference> competitorPreferences = new ArrayList<>();
|
||||
CompetitorAndBoatStore competitorStore = ctx.getRacingEventService().getCompetitorAndBoatStore();
|
||||
for (SimpleCompetitorWithIdDTO competitorDTO : favorites.getSelectedCompetitors()) {
|
||||
Competitor competitor = competitorStore.getExistingCompetitorByIdAsString(competitorDTO.getIdAsString());
|
||||
competitorPreferences.add(new CompetitorNotificationPreference(competitorStore, competitor,
|
||||
favorites.isNotifyAboutResults()));
|
||||
String competitorId = competitorDTO.getIdAsString();
|
||||
if (competitorStore.getExistingCompetitorByIdAsString(competitorId) != null) {
|
||||
competitorPreferences
|
||||
.add(new CompetitorNotificationPreference(competitorId, favorites.isNotifyAboutResults()));
|
||||
} else {
|
||||
throw new DispatchException(
|
||||
"Competitor with ID: " + competitorId + "is not an existing Competitor on this server.");
|
||||
}
|
||||
}
|
||||
prefs.setCompetitors(competitorPreferences);
|
||||
ctx.setPreferenceForCurrentUser(CompetitorNotificationPreferences.PREF_NAME, prefs);
|
||||
|
||||
+1
-1
@@ -102,6 +102,6 @@ public interface SailorProfileConverter {
|
||||
/** @return converted BoatClassDTO from BoatClass */
|
||||
@GwtIncompatible
|
||||
default BoatClassDTO convertBoatClassToDTO(BoatClass bc) {
|
||||
return new BoatClassDTO(bc.getName(), bc.getDisplayName(), bc.getHullLength(), bc.getHullBeam());
|
||||
return new BoatClassDTO(bc.getName(), bc.getHullLength(), bc.getHullBeam());
|
||||
}
|
||||
}
|
||||
+6
@@ -12,6 +12,12 @@
|
||||
by the tab for the next three months. We're looking forward to your feedback!</li>
|
||||
<li>Bug fix: if a start or finish line was missing position information for one of its ends, the map display
|
||||
of tracks and course broke. This has been fixed now.</li>
|
||||
<li>For better visibility especially with satellite view enabled, rhumb line display now uses a bright
|
||||
green color.</li>
|
||||
<li>Added an optional COG (Course over Ground) column to the leaderboard which shows all competitors'
|
||||
COG in true degrees.</li>
|
||||
<li>The rhumb line ("course middle line") for the first leg is now already displayed prior to the
|
||||
start time point.</li>
|
||||
</ul>
|
||||
<h5 class="articleSubheadline">September 2020</h5>
|
||||
<ul class="bulletList">
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.sap.sailing.gwt.home.shared.places.imprint;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.DivElement;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.home.shared.places.imprint.data.DisclaimerData;
|
||||
|
||||
public class DisclaimerItem extends Composite {
|
||||
|
||||
private static final String LINK_PLACEHOLDER = "${link}";
|
||||
|
||||
private static DisclaimerItemUiBinder uiBinder = GWT.create(DisclaimerItemUiBinder.class);
|
||||
|
||||
interface DisclaimerItemUiBinder extends UiBinder<Widget, DisclaimerItem> {
|
||||
}
|
||||
|
||||
@UiField
|
||||
Label disclaimerItemTitle;
|
||||
@UiField
|
||||
DivElement disclaimerItemContent;
|
||||
|
||||
public DisclaimerItem() {
|
||||
super();
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
}
|
||||
|
||||
public void setDisclaimer(final DisclaimerData disclaimer) {
|
||||
if(disclaimer != null) {
|
||||
disclaimerItemTitle.setText(disclaimer.getTitle());
|
||||
final String content = disclaimer.getContent();
|
||||
final String contentWithLink = content.replace(LINK_PLACEHOLDER,
|
||||
"<a href=\"" + disclaimer.getLink() + "\" >" + disclaimer.getLink() + "</a>");
|
||||
disclaimerItemContent.setInnerHTML(contentWithLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
|
||||
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
|
||||
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:cell="urn:import:com.google.gwt.user.cellview.client"
|
||||
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared">
|
||||
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:style>
|
||||
.disclaimerItem {
|
||||
border-color: black;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
font-family: monospace, monospace;
|
||||
display: block;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.disclaimerItemTitle {
|
||||
font-size: 1.3em;
|
||||
margin: 5px 0px 5px 0px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.disclaimerItemContent {
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
</ui:style>
|
||||
<g:HTMLPanel>
|
||||
<div ui:field="disclaimerItem" class="{style.disclaimerItem}" >
|
||||
<g:Label ui:field="disclaimerItemTitle" styleName="{style.disclaimerItemTitle}" />
|
||||
<div ui:field="disclaimerItemContent" class="{style.disclaimerItemContent}" />
|
||||
</div>
|
||||
</g:HTMLPanel>
|
||||
</ui:UiBinder>
|
||||
+1
@@ -44,6 +44,7 @@ public class ImprintActivity extends AbstractActivity implements ImprintView.Pre
|
||||
for (LicenseData license : data.getLicenses()) {
|
||||
licenseMap.put(license.getKey(), license);
|
||||
}
|
||||
view.addDisclaimers(imprintData.getDisclaimers());
|
||||
view.showComponents(imprintData.getComponents());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
+3
@@ -2,6 +2,7 @@ package com.sap.sailing.gwt.home.shared.places.imprint;
|
||||
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.home.shared.places.imprint.data.ComponentData;
|
||||
import com.sap.sailing.gwt.home.shared.places.imprint.data.DisclaimerData;
|
||||
import com.sap.sailing.gwt.home.shared.places.imprint.data.LicenseData;
|
||||
|
||||
public interface ImprintView {
|
||||
@@ -12,6 +13,8 @@ public interface ImprintView {
|
||||
interface Presenter {
|
||||
void didSelect(ComponentData selectedObject);
|
||||
}
|
||||
|
||||
public void addDisclaimers(final DisclaimerData[] disclaimers);
|
||||
|
||||
void showComponents(ComponentData[] components);
|
||||
|
||||
|
||||
+16
-14
@@ -16,18 +16,18 @@ import com.google.gwt.text.shared.Renderer;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.ValueListBox;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.home.shared.places.imprint.data.ComponentData;
|
||||
import com.sap.sailing.gwt.home.shared.places.imprint.data.DisclaimerData;
|
||||
import com.sap.sailing.gwt.home.shared.places.imprint.data.LicenseData;
|
||||
|
||||
public class ImprintViewImpl extends Composite implements ImprintView {
|
||||
private static final String GOOGLE_LEGAL = "Google Maps Service (\"GM Service\"). If the Cloud Service accesses the GM Service through a Google Maps API, Customer's use of the GM Service is subject to Google's Terms of Service, which are set forth at http://www.google.com/intl/en/policies/terms/. If Customer does not accept the Google Terms of Service, including, but not limited to, all limitations and restrictions therein, Customer may not use the GM Service in the Cloud Service. Use of the GM Service in or through the Cloud Service will constitute Customer's acceptance of Google's Terms of Service. Customer's usage of the GM Service in or through the Cloud Service can be terminated by SAP without reason at any time and SAP will not be required to provide an equivalent service via another provider.";
|
||||
|
||||
private static SponsoringPageViewUiBinder uiBinder = GWT.create(SponsoringPageViewUiBinder.class);
|
||||
private static ImprintViewImplUiBinder uiBinder = GWT.create(ImprintViewImplUiBinder.class);
|
||||
|
||||
interface SponsoringPageViewUiBinder extends UiBinder<Widget, ImprintViewImpl> {
|
||||
interface ImprintViewImplUiBinder extends UiBinder<Widget, ImprintViewImpl> {
|
||||
}
|
||||
|
||||
private Presenter currentPresenter;
|
||||
@@ -37,15 +37,13 @@ public class ImprintViewImpl extends Composite implements ImprintView {
|
||||
@UiField
|
||||
Element ownerUi;
|
||||
@UiField
|
||||
Element nameUi;
|
||||
@UiField
|
||||
AnchorElement homepageUi;
|
||||
@UiField
|
||||
DivElement acknowledgmentUi;
|
||||
@UiField
|
||||
DivElement licenseTextUi;
|
||||
@UiField
|
||||
Label googleLegal;
|
||||
FlowPanel disclaimers;
|
||||
|
||||
public ImprintViewImpl() {
|
||||
super();
|
||||
@@ -78,15 +76,23 @@ public class ImprintViewImpl extends Composite implements ImprintView {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
googleLegal.setText(GOOGLE_LEGAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPresenter(Presenter currentPresenter) {
|
||||
this.currentPresenter = currentPresenter;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addDisclaimers(final DisclaimerData[] disclaimers) {
|
||||
if(disclaimers!= null) {
|
||||
for(DisclaimerData disclaimer : disclaimers) {
|
||||
DisclaimerItem disclaimerItem = new DisclaimerItem();
|
||||
disclaimerItem.setDisclaimer(disclaimer);
|
||||
this.disclaimers.add(disclaimerItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showComponents(final ComponentData[] components) {
|
||||
@@ -95,7 +101,6 @@ public class ImprintViewImpl extends Composite implements ImprintView {
|
||||
componentListUi.setVisible(false);
|
||||
componentListUi.setAcceptableValues(new ArrayList<ComponentData>());
|
||||
ownerUi.setInnerText("");
|
||||
nameUi.setInnerText("--");
|
||||
homepageUi.getStyle().setVisibility(Style.Visibility.HIDDEN);
|
||||
acknowledgmentUi.getStyle().setVisibility(Style.Visibility.HIDDEN);
|
||||
licenseTextUi.getStyle().setVisibility(Style.Visibility.HIDDEN);
|
||||
@@ -104,7 +109,6 @@ public class ImprintViewImpl extends Composite implements ImprintView {
|
||||
componentListUi.setAcceptableValues(Arrays.asList(components));
|
||||
componentListUi.setVisible(true);
|
||||
ownerUi.setInnerText("--");
|
||||
nameUi.setInnerText("");
|
||||
homepageUi.getStyle().setVisibility(Style.Visibility.VISIBLE);
|
||||
acknowledgmentUi.getStyle().setVisibility(Style.Visibility.VISIBLE);
|
||||
licenseTextUi.getStyle().setVisibility(Style.Visibility.VISIBLE);
|
||||
@@ -114,7 +118,6 @@ public class ImprintViewImpl extends Composite implements ImprintView {
|
||||
|
||||
@Override
|
||||
public void showComponents(ComponentData component, LicenseData license) {
|
||||
nameUi.setInnerText(component.getName() + ", v." + component.getVersion());
|
||||
ownerUi.setInnerText(component.getOwner());
|
||||
homepageUi.setHref(component.getHomepage());
|
||||
homepageUi.setInnerText(component.getHomepage());
|
||||
@@ -130,7 +133,6 @@ public class ImprintViewImpl extends Composite implements ImprintView {
|
||||
@Override
|
||||
public void resetComponent() {
|
||||
ownerUi.setInnerText("--");
|
||||
nameUi.setInnerText("");
|
||||
homepageUi.setInnerText("");
|
||||
acknowledgmentUi.setInnerText("");
|
||||
licenseTextUi.setInnerText("");
|
||||
|
||||
+53
-56
@@ -3,66 +3,63 @@
|
||||
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:cell="urn:import:com.google.gwt.user.cellview.client"
|
||||
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared">
|
||||
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
|
||||
<ui:with field="res"
|
||||
type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:style>
|
||||
.outerPanel {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.listbox {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 3em;
|
||||
line-height: 2em;
|
||||
|
||||
font-size: 20px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
|
||||
margin-top: 40px;
|
||||
}
|
||||
.owner {
|
||||
margin-top: 50px;
|
||||
}
|
||||
.homepage {
|
||||
display: block;
|
||||
margin-top: 40px;
|
||||
}
|
||||
.acknowledgment {
|
||||
margin-top: 40px;
|
||||
display: block;
|
||||
overflow: auto;
|
||||
font-size: smaller;
|
||||
}
|
||||
.licenseText {
|
||||
display: block;
|
||||
margin: 50px 10px;
|
||||
padding: 10px 10px;
|
||||
|
||||
}
|
||||
.googleMaps {
|
||||
border-color: black;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
font-family: monospace, monospace;
|
||||
display: block;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
</ui:style>
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:style>
|
||||
.outerPanel {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.majorHeader {
|
||||
margin: 30px 0 30px 0;
|
||||
font-weight: bold;
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.listbox {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 3em;
|
||||
line-height: 2em;
|
||||
font-size: 1.6em;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.owner {
|
||||
margin-top: 30px;
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.homepage {
|
||||
display: block;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.acknowledgement {
|
||||
margin-top: 40px;
|
||||
display: block;
|
||||
overflow: auto;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.licenseText {
|
||||
display: block;
|
||||
margin: 50px 10px;
|
||||
padding: 10px 0 10px 0;
|
||||
}
|
||||
</ui:style>
|
||||
<g:HTMLPanel addStyleNames="{res.mediaCss.grid} {style.outerPanel}">
|
||||
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
|
||||
<a href="http://www.sap.com/about/legal/impressum.html"><ui:text from='{i18n.footerLegal}' /></a>
|
||||
<g:Label styleName="{style.googleMaps}" ui:field="googleLegal"/>
|
||||
<div class= "{style.majorHeader}">Legal Disclaimers: </div>
|
||||
<g:FlowPanel ui:field="disclaimers"/>
|
||||
<div class= "{style.majorHeader}">Further Components used: </div>
|
||||
<g:ValueListBox ui:field="componentListUi"
|
||||
styleName="{style.listbox}" />
|
||||
<h1 ui:field="nameUi" class="{style.owner}"/>
|
||||
<h2 ui:field="ownerUi" class="{style.owner}"/>
|
||||
addStyleNames="{style.listbox}" />
|
||||
<div ui:field="ownerUi" class="{style.owner}"/>
|
||||
<a ui:field="homepageUi" class="{style.homepage}"/>
|
||||
<div ui:field="acknowledgmentUi" class="{style.acknowledgment}"/>
|
||||
<div ui:field="acknowledgmentUi" class="{style.acknowledgement}"/>
|
||||
<div ui:field="licenseTextUi" class="{style.licenseText}"/>
|
||||
</div>
|
||||
</g:HTMLPanel>
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.sap.sailing.gwt.home.shared.places.imprint.data;
|
||||
|
||||
import com.google.gwt.core.client.JavaScriptObject;
|
||||
|
||||
public class DisclaimerData extends JavaScriptObject {
|
||||
protected DisclaimerData() {
|
||||
};
|
||||
|
||||
public final native String getTitle() /*-{
|
||||
return this.title;
|
||||
}-*/;
|
||||
|
||||
public final native String getLink() /*-{
|
||||
return this.link;
|
||||
}-*/;
|
||||
|
||||
public final native String getContent() /*-{
|
||||
return this.content;
|
||||
}-*/;
|
||||
|
||||
}
|
||||
+4
-2
@@ -13,6 +13,8 @@ public class ImprintData extends JavaScriptObject {
|
||||
public final native ComponentData[] getComponents() /*-{
|
||||
return this.components;
|
||||
}-*/;
|
||||
|
||||
|
||||
|
||||
public final native DisclaimerData[] getDisclaimers() /*-{
|
||||
return this.disclaimers;
|
||||
}-*/;
|
||||
}
|
||||
+1
-1
@@ -278,7 +278,7 @@ public class CompetitorRegistrationsPanel extends FlowPanel implements BusyDispl
|
||||
});
|
||||
}
|
||||
|
||||
public void deactivateRegistrationButtons(String tooltip){
|
||||
public void deactivateRegistrationButtons(String tooltip) {
|
||||
registerBtn.setEnabled(false);
|
||||
unregisterBtn.setEnabled(false);
|
||||
addCompetitorWithBoatButton.setEnabled(false);
|
||||
|
||||
+3
-3
@@ -53,7 +53,7 @@ public class RaceLogCompetitorRegistrationDialog extends AbstractCompetitorRegis
|
||||
public String getErrorMessage(Set<CompetitorDTO> valueToValidate) {
|
||||
String result = null;
|
||||
if (getCompetitorRegistrationInRaceLogCheckBox() != null && !getCompetitorRegistrationInRaceLogCheckBox().getValue()) {
|
||||
result = stringMessages.competitorRegistrationsOnRaceDisabled();
|
||||
result = stringMessages.competitorRegistrationsOnRaceDisabled(stringMessages.registerCompetitorsOnRace());
|
||||
} else {
|
||||
Set<CompetitorDTO> difference = new HashSet<>();
|
||||
for (Set<CompetitorDTO> competitors : fleetsWithCompetitors.values()) {
|
||||
@@ -232,7 +232,7 @@ public class RaceLogCompetitorRegistrationDialog extends AbstractCompetitorRegis
|
||||
if (isEnabled) {
|
||||
competitorRegistrationsPanel.activateRegistrationButtons();
|
||||
} else {
|
||||
competitorRegistrationsPanel.deactivateRegistrationButtons(stringMessages.competitorRegistrationsOnRaceDisabled());
|
||||
competitorRegistrationsPanel.deactivateRegistrationButtons(stringMessages.competitorRegistrationsOnRaceDisabled(stringMessages.registerCompetitorsOnRace()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ public class RaceLogCompetitorRegistrationDialog extends AbstractCompetitorRegis
|
||||
public void onSuccess(Void isEnabled) {
|
||||
getOrCreateCompetitorRegistrationInRaceLogCheckBox(stringMessages).setValue(false);
|
||||
competitorRegistrationsPanel.deactivateRegistrationButtons(stringMessages
|
||||
.competitorRegistrationsOnRaceDisabled());
|
||||
.competitorRegistrationsOnRaceDisabled(stringMessages.registerCompetitorsOnRace()));
|
||||
competitorRegistrationsPanel.refreshCompetitors();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1530,7 +1530,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
|
||||
String doYouWantToDisableCompetitorsRegistrationsOnTheRace();
|
||||
String warningDirectCompetitorRegistration();
|
||||
String warningRegattaCompetitorRegistration();
|
||||
String competitorRegistrationsOnRaceDisabled();
|
||||
String competitorRegistrationsOnRaceDisabled(String nameOfCheckboxToEnable);
|
||||
String warningForDisabledCompetitors(String competitorsSet);
|
||||
String competitorToolTipMessage(String competitorName, String currentFleetName, String assignedToFleet, String raceName);
|
||||
String addMarkToRegatta();
|
||||
|
||||
+1
-1
@@ -1523,7 +1523,7 @@ doYouWantToRegisterCompetitorsDirectlyOnTheRace=Do you want to register competit
|
||||
doYouWantToDisableCompetitorsRegistrationsOnTheRace=Do you want to disable competitor registrations on the Race?
|
||||
warningDirectCompetitorRegistration=Warning! This setting will lead to competitors for this race being registered on a per race basis. Competitors will not be automatically registered for this race, when registering them on the corresponding regatta.
|
||||
warningRegattaCompetitorRegistration=Warning! This will reactivate competior registrations on the regatta. All competitor registrations from the regatta will automatically be used as competitor registration for this race.
|
||||
competitorRegistrationsOnRaceDisabled=Competitor Registrations are disabled for this race. Enable by checking the checkbox to the left.
|
||||
competitorRegistrationsOnRaceDisabled=Competitor Registrations are disabled for this race. Enable by ticking the checkbox "{0}".
|
||||
warningForDisabledCompetitors=The following competitors cannot be registered to this race : {0}
|
||||
competitorToolTipMessage={0} has already been assigned to fleet {2} in race {3} and therefore cannot be assigned to fleet {1} within the same race
|
||||
addMarkToRegatta=Add Mark to Regatta
|
||||
|
||||
+1
-1
@@ -1501,7 +1501,7 @@ doYouWantToRegisterCompetitorsDirectlyOnTheRace=Wollen Sie Teilnehmer direkt auf
|
||||
warningDirectCompetitorRegistration=Warnung! Diese Einstellung führt dazu, dass Teilnehmer dieses Rennens von nun an auf Rennebene registriert werden müssen. Dies ist nur sinnvoll, wenn sich die Teilnehmer verschiedener Rennen einer Regatta unterscheiden.
|
||||
warningRegattaCompetitorRegistration=Warnung! Diese Einstellung reaktiviert die Teilnehmerregistrierung auf Regatta-Ebene. Alle Teilnehmer der zu diesem Rennen gehörenden Regatta werden automatisch Teilnehmer dieses Rennens.
|
||||
doYouWantToDisableCompetitorsRegistrationsOnTheRace=Wollen Sie Teilnehmer auf Regatta- statt Rennebene registrieren?
|
||||
competitorRegistrationsOnRaceDisabled=Teilnehmeranmeldung ist für dieses Rennen auf Rennebene deaktiviert. Aktivieren durch selektieren der CheckBox auf der linken Seite.
|
||||
competitorRegistrationsOnRaceDisabled=Teilnehmeranmeldung ist für dieses Rennen auf Rennebene deaktiviert. Aktivieren durch selektieren der CheckBox "{0}".
|
||||
warningForDisabledCompetitors=Die folgenden Teilnehmer konnten nicht für diese Wettfahrt angemeldet werden: {0}
|
||||
competitorToolTipMessage=Teilnehmer {0} ist bereits der Gruppe {2} in der Wettfahrt {3} zugewiesen und kann daher nicht der Gruppe {1} in der selben Wettfahrt zugewiesen werden
|
||||
addMarkToRegatta=Tonne zu Regatta hinzufügen
|
||||
|
||||
+1
-1
@@ -1517,7 +1517,7 @@ doYouWantToRegisterCompetitorsDirectlyOnTheRace=¿Desea registrar competidores d
|
||||
doYouWantToDisableCompetitorsRegistrationsOnTheRace=¿Desea deshabilitar los registros de competidores en la carrera?
|
||||
warningDirectCompetitorRegistration=Advertencia: esta parametrización provocará que los competidores de esta carrera se registren por carreras. Los competidores no se registrarán automáticamente para esta carrera cuando se registren para la regata correspondiente.
|
||||
warningRegattaCompetitorRegistration=Advertencia: esto reactivará los registros de los competidores en la regata. Todos los registros de los competidores en la regata se utilizarán automáticamente como registros de los competidores para esta carrera.
|
||||
competitorRegistrationsOnRaceDisabled=Los registros de competidores están deshabilitados para esta carrera. Habilítelos marcando la casilla de selección de la izquierda.
|
||||
competitorRegistrationsOnRaceDisabled=Los registros de competidores están deshabilitados para esta carrera. Habilítelos marcando la casilla de selección "{0}".
|
||||
warningForDisabledCompetitors=Los siguientes competidores no se pueden registrar para esta carrera: {0}
|
||||
competitorToolTipMessage={0} ya ha sido asignado a la flota {2} en la carrera {3} y, por consiguiente, no se puede asignar a la flota {1} de la misma carrera
|
||||
addMarkToRegatta=Añadir marca a regata
|
||||
|
||||
+1
-1
@@ -1517,7 +1517,7 @@ doYouWantToRegisterCompetitorsDirectlyOnTheRace=Voulez-vous inscrire les concurr
|
||||
doYouWantToDisableCompetitorsRegistrationsOnTheRace=Voulez-vous désactiver l''inscription des concurrents pour la course ?
|
||||
warningDirectCompetitorRegistration=Avertissement : cette option engendrera l''inscription des concurrents de cette course séparément à chaque course. Si les concurrents sont inscrits à une régate, ils ne seront pas automatiquement inscrits à cette course.
|
||||
warningRegattaCompetitorRegistration=Avertissement : ceci réactivera l''inscription des concurrents à la régate. Toutes les inscriptions à la régate seront automatiquement utilisées comme inscriptions à cette course.
|
||||
competitorRegistrationsOnRaceDisabled=Les inscriptions des concurrents sont désactivées pour cette course. Pour les activer, cochez la case sur la gauche.
|
||||
competitorRegistrationsOnRaceDisabled=Les inscriptions des concurrents sont désactivées pour cette course. Pour les activer, cochez la case "{0}".
|
||||
warningForDisabledCompetitors=Les concurrents suivants ne peuvent pas être inscrits à cette course : {0}
|
||||
competitorToolTipMessage={0} a déjà été affecté à la flotte {2} dans la course {3} et ne peut donc pas être affecté à la flotte {1} dans la même course.
|
||||
addMarkToRegatta=Ajouter marque à la régate
|
||||
|
||||
+1
-1
@@ -1517,7 +1517,7 @@ doYouWantToRegisterCompetitorsDirectlyOnTheRace=Registrare i concorrenti diretta
|
||||
doYouWantToDisableCompetitorsRegistrationsOnTheRace=Disabilitare le registrazioni concorrenti direttamente nella gara?
|
||||
warningDirectCompetitorRegistration=Attenzione! Questa impostazione farà sì che i concorrenti a questa gara vengano registrati in base alla gara. I concorrenti non verranno automaticamente registrati a questa gara se la registrazione viene eseguita per la regata corrispondente.
|
||||
warningRegattaCompetitorRegistration=Attenzione! In tal modo verranno riattivate le registrazioni dei concorrenti alla regata. Tutte le registrazioni dei concorrenti derivanti dalla regata verranno automaticamente utilizzate come registrazione dei concorrenti a questa gara.
|
||||
competitorRegistrationsOnRaceDisabled=Le registrazioni dei concorrenti sono disabilitate per questa gara. Per abilitarle spuntare la casella di controllo a sinistra.
|
||||
competitorRegistrationsOnRaceDisabled=Le registrazioni dei concorrenti sono disabilitate per questa gara. Per abilitarle spuntare la casella di controllo "{0}".
|
||||
warningForDisabledCompetitors=I seguenti concorrenti non possono essere registrati a questa gara: {0}
|
||||
competitorToolTipMessage={0} è già stato assegnato alla flotta {2} nella gara {3} e non può quindi essere assegnato alla flotta {1} nella stessa gara
|
||||
addMarkToRegatta=Aggiungi segnale a regata
|
||||
|
||||
+1
-1
@@ -1517,7 +1517,7 @@ doYouWantToRegisterCompetitorsDirectlyOnTheRace=レースに競技者を直接
|
||||
doYouWantToDisableCompetitorsRegistrationsOnTheRace=レースへの競技者登録を無効にしますか
|
||||
warningDirectCompetitorRegistration=警告: この設定を行うと、このレースの競技者がレースごとに登録されることにつながります。競技者は、該当するレガッタに登録されるときに、このレースに対して自動的には登録されません。
|
||||
warningRegattaCompetitorRegistration=警告: これにより、レガッタへの競技者登録が再有効化されます。レガッタからのすべての競技者登録が、このレースに対する競技者登録として自動的に使用されます。
|
||||
competitorRegistrationsOnRaceDisabled=競技者登録はこのレースに対して無効化されています。左側のチェックボックスを選択して有効化します。
|
||||
competitorRegistrationsOnRaceDisabled=競技者登録はこのレースに対して無効化されています。左側のチェックボックスを選択して有効化します。 "{0}"
|
||||
warningForDisabledCompetitors=次の競技者はこのレースに登録することができません: {0}
|
||||
competitorToolTipMessage={0} はすでにレース {3} のフリート {2} に割り当てられており、そのため同一レース内でフリート {1} に割り当てることはできません
|
||||
addMarkToRegatta=マークをレガッタに追加
|
||||
|
||||
+1
-1
@@ -1517,7 +1517,7 @@ doYouWantToRegisterCompetitorsDirectlyOnTheRace=Você quer registrar competidore
|
||||
doYouWantToDisableCompetitorsRegistrationsOnTheRace=Você quer desativar os registros dos competidores na corrida?
|
||||
warningDirectCompetitorRegistration=Advertência! Esta configuração fará com que os competidores sejam registrados corrida a corrida. Os competidores não serão registrados automaticamente para esta corrida, ao efetuar o registro na regata correspondente.
|
||||
warningRegattaCompetitorRegistration=Advertência! Isto irá reativar os registros de competidores na regata. Todos os registros de competidores da regata serão utilizados automaticamente como registro do competidor para esta corrida.
|
||||
competitorRegistrationsOnRaceDisabled=Os registros dos competidores estão desativados para esta corrida. Ative-os marcando o campo de seleção à esquerda.
|
||||
competitorRegistrationsOnRaceDisabled=Os registros dos competidores estão desativados para esta corrida. Ative-os marcando o campo de seleção à esquerda. "{0}"
|
||||
warningForDisabledCompetitors=Os competidores seguintes não podem ser registrados nesta corrida: {0}
|
||||
competitorToolTipMessage={0} já foi atribuído à flotilha {2} na corrida {3} e por isso não pode ser atribuído à flotilha {1} na mesma corrida
|
||||
addMarkToRegatta=Adicionar marca à regata
|
||||
|
||||
+1
-1
@@ -1517,7 +1517,7 @@ doYouWantToRegisterCompetitorsDirectlyOnTheRace=Зарегистрировать
|
||||
doYouWantToDisableCompetitorsRegistrationsOnTheRace=Отключить регистрации участников в гонке?
|
||||
warningDirectCompetitorRegistration=Внимание! Этот параметр приведет к регистрации участников этой гонки только в данной гонке. При регистрации в соответствующей регате они не будут автоматически зарегистрированы в данной гонке.
|
||||
warningRegattaCompetitorRegistration=Внимание! Это приведет к повторной активации регистраций участника в регате. Все регистрации участника из регаты будут автоматически использованы как регистрация участника для данной гонки.
|
||||
competitorRegistrationsOnRaceDisabled=Регистрации участника отключены для данной гонки. Чтобы включить, установите флажок слева.
|
||||
competitorRegistrationsOnRaceDisabled=Регистрации участника отключены для данной гонки. Чтобы включить, установите флажок слева. "{0}"
|
||||
warningForDisabledCompetitors=Регистрация следующих участников на эту гонку невозможна: {0}
|
||||
competitorToolTipMessage={0} уже присвоен флоту {2} в гонке {3} и поэтому не может быть присвоен флоту {1} в той же самой гонке
|
||||
addMarkToRegatta=Добавить отметку к регате
|
||||
|
||||
+1
-1
@@ -1517,7 +1517,7 @@ doYouWantToRegisterCompetitorsDirectlyOnTheRace=是否直接在比赛轮次注
|
||||
doYouWantToDisableCompetitorsRegistrationsOnTheRace=是否要禁用参赛队在比赛轮次注册?
|
||||
warningDirectCompetitorRegistration=警告! 此设置会导致此比赛轮次的参赛队在每个比赛轮次注册。 在相应的比赛中注册参赛队时,将无法自动注册此比赛轮次。
|
||||
warningRegattaCompetitorRegistration=警告! 此操作将重新激活参赛队注册比赛。 比赛中的所有参赛队注册将自动用作此比赛轮次的参赛队注册。
|
||||
competitorRegistrationsOnRaceDisabled=参赛队注册已针对此比赛轮次禁用。选中左侧的复选框可启用。
|
||||
competitorRegistrationsOnRaceDisabled=参赛队注册已针对此比赛轮次禁用。选中左侧的复选框可启用。 "{0}"
|
||||
warningForDisabledCompetitors=以下参赛队无法注册此比赛轮次:{0}
|
||||
competitorToolTipMessage={0}已分配到比赛轮次{3}中的船队{2},因此,无法分配到同一比赛轮次中的船队{1}
|
||||
addMarkToRegatta=向比赛添加标志
|
||||
|
||||
-10
@@ -126,7 +126,6 @@ public class MediaManagementControl extends AbstractMediaSelectionControl implem
|
||||
videoCheckBox.setTitle(videoTrack.toString());
|
||||
videoCheckBox.setValue(selectedVideos.contains(videoTrack));
|
||||
videoCheckBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
|
||||
|
||||
@Override
|
||||
public void onValueChange(ValueChangeEvent<Boolean> changeEvent) {
|
||||
if (changeEvent.getValue()) {
|
||||
@@ -136,12 +135,10 @@ public class MediaManagementControl extends AbstractMediaSelectionControl implem
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (mediaPlayerManager.allowsEditing(videoTrack)) {
|
||||
HorizontalPanel panel = new HorizontalPanel();
|
||||
panel.setWidth("100%");
|
||||
panel.add(videoCheckBox);
|
||||
|
||||
Button deleteButton = createDeleteButton(videoTrack);
|
||||
panel.add(deleteButton);
|
||||
ToggleButton connectButton = createConnectButton(videoTrack);
|
||||
@@ -154,7 +151,6 @@ public class MediaManagementControl extends AbstractMediaSelectionControl implem
|
||||
} else {
|
||||
return videoCheckBox;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private ToggleButton createConnectButton(final MediaTrackWithSecurityDTO videoTrack) {
|
||||
@@ -163,7 +159,6 @@ public class MediaManagementControl extends AbstractMediaSelectionControl implem
|
||||
.contains(mediaPlayerManager.getCurrentRace()));
|
||||
connectButton.setTitle("Connect video to this race");
|
||||
connectButton.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
|
||||
|
||||
@Override
|
||||
public void onValueChange(ValueChangeEvent<Boolean> changeEvent) {
|
||||
if (connectButton.isDown()) {
|
||||
@@ -184,7 +179,6 @@ public class MediaManagementControl extends AbstractMediaSelectionControl implem
|
||||
private void disconnectVideoFromRace(final MediaTrackWithSecurityDTO videoTrack, final ToggleButton connectButton) {
|
||||
videoTrack.assignedRaces.remove(mediaPlayerManager.getCurrentRace());
|
||||
mediaPlayerManager.getMediaServiceWrite().updateRace(videoTrack, new AsyncCallback<Void>() {
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
mediaPlayerManager.getErrorReporter().reportError(t.toString());
|
||||
@@ -196,13 +190,11 @@ public class MediaManagementControl extends AbstractMediaSelectionControl implem
|
||||
mediaPlayerManager.closeFloatingPlayer(videoTrack);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void connectVideoToRace(final MediaTrack videoTrack, final ToggleButton connectButton) {
|
||||
videoTrack.assignedRaces.add(mediaPlayerManager.getCurrentRace());
|
||||
mediaPlayerManager.getMediaServiceWrite().updateRace(videoTrack, new AsyncCallback<Void>() {
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
mediaPlayerManager.getErrorReporter().reportError(t.toString());
|
||||
@@ -246,7 +238,6 @@ public class MediaManagementControl extends AbstractMediaSelectionControl implem
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (mediaPlayerManager.allowsEditing(audioTrack) && audioTrack != null) {
|
||||
HorizontalPanel panel = new HorizontalPanel();
|
||||
panel.setWidth("100%");
|
||||
@@ -277,5 +268,4 @@ public class MediaManagementControl extends AbstractMediaSelectionControl implem
|
||||
@Override
|
||||
protected void updateUi() {
|
||||
}
|
||||
|
||||
}
|
||||
-182
@@ -1,182 +0,0 @@
|
||||
package com.sap.sailing.gwt.ui.client.media;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.event.logical.shared.CloseEvent;
|
||||
import com.google.gwt.event.logical.shared.CloseHandler;
|
||||
import com.google.gwt.event.logical.shared.ValueChangeEvent;
|
||||
import com.google.gwt.event.logical.shared.ValueChangeHandler;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.CheckBox;
|
||||
import com.google.gwt.user.client.ui.DialogBox;
|
||||
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
|
||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.Panel;
|
||||
import com.google.gwt.user.client.ui.PopupPanel;
|
||||
import com.google.gwt.user.client.ui.RadioButton;
|
||||
import com.google.gwt.user.client.ui.UIObject;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.domain.common.media.MediaTrack;
|
||||
|
||||
public class MediaSelectionDialog implements CloseHandler<PopupPanel> {
|
||||
|
||||
static interface MediaSelectionListener {
|
||||
|
||||
void audioChanged(MediaTrack audioTrack);
|
||||
|
||||
void videoSelected(MediaTrack videoTrack);
|
||||
|
||||
void videoDeselected(MediaTrack videoTrack);
|
||||
|
||||
void addMediaTrack();
|
||||
|
||||
void deleteMediaTrack(MediaTrack mediaTrack);
|
||||
|
||||
boolean allowsAddDelete();
|
||||
|
||||
}
|
||||
|
||||
private final DialogBox dialogControl;
|
||||
private final MediaSelectionListener mediaSelectionListener;
|
||||
private final Map<MediaTrack, CheckBox> videoCheckBoxes = new HashMap<MediaTrack, CheckBox>();
|
||||
|
||||
MediaSelectionDialog(MediaSelectionListener mediaSelectionListener) {
|
||||
this.mediaSelectionListener = mediaSelectionListener;
|
||||
dialogControl = new DialogBox(true, false);
|
||||
dialogControl.setText("Select Playback Media");
|
||||
dialogControl.addCloseHandler(this);
|
||||
}
|
||||
|
||||
public void show(Collection<MediaTrack> videoTracks, Set<MediaTrack> selectedVideos, Collection<MediaTrack> audioTracks, MediaTrack selectedAudioTrack, boolean showAddButton, UIObject popupLocation) {
|
||||
Panel grid = new VerticalPanel();
|
||||
if (!audioTracks.isEmpty()) {
|
||||
grid.add(createAudioHeader());
|
||||
grid.add((RadioButton) createAudioButton(null, selectedAudioTrack));
|
||||
for (MediaTrack audioTrack : audioTracks) {
|
||||
grid.add(createAudioButton(audioTrack, selectedAudioTrack));
|
||||
}
|
||||
}
|
||||
if (!videoTracks.isEmpty()) {
|
||||
grid.add(createVideoHeader());
|
||||
for (MediaTrack videoTrack : videoTracks) {
|
||||
grid.add(createVideoCheckBox(videoTrack, selectedVideos));
|
||||
}
|
||||
}
|
||||
if (mediaSelectionListener.allowsAddDelete()) {
|
||||
Button addButton = new Button("Add", new ClickHandler() {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
mediaSelectionListener.addMediaTrack();
|
||||
}
|
||||
});
|
||||
grid.add(addButton);
|
||||
}
|
||||
dialogControl.add(grid);
|
||||
dialogControl.showRelativeTo(popupLocation);
|
||||
}
|
||||
|
||||
private Widget createVideoCheckBox(final MediaTrack videoTrack, Set<MediaTrack> selectedVideos) {
|
||||
CheckBox videoCheckBox = new CheckBox(videoTrack.title);
|
||||
videoCheckBoxes.put(videoTrack, videoCheckBox);
|
||||
videoCheckBox.setTitle(videoTrack.toString());
|
||||
videoCheckBox.setValue(selectedVideos.contains(videoTrack));
|
||||
videoCheckBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
|
||||
|
||||
@Override
|
||||
public void onValueChange(ValueChangeEvent<Boolean> changeEvent) {
|
||||
if (changeEvent.getValue()) {
|
||||
mediaSelectionListener.videoSelected(videoTrack);
|
||||
} else {
|
||||
mediaSelectionListener.videoDeselected(videoTrack);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (mediaSelectionListener.allowsAddDelete()) {
|
||||
HorizontalPanel panel = new HorizontalPanel();
|
||||
panel.setWidth("100%");
|
||||
panel.add(videoCheckBox);
|
||||
|
||||
Button deleteButton = new Button("X", new ClickHandler() {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
mediaSelectionListener.deleteMediaTrack(videoTrack);
|
||||
}
|
||||
});
|
||||
panel.setCellHorizontalAlignment(deleteButton, HasHorizontalAlignment.ALIGN_RIGHT);
|
||||
panel.add(deleteButton);
|
||||
|
||||
return panel;
|
||||
} else {
|
||||
return videoCheckBox;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void selectVideo(MediaTrack videoTrack) {
|
||||
CheckBox videoCheckBox = videoCheckBoxes.get(videoTrack);
|
||||
if (videoCheckBox != null) {
|
||||
videoCheckBox.setValue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void unselectVideo(MediaTrack videoTrack) {
|
||||
CheckBox videoCheckBox = videoCheckBoxes.get(videoTrack);
|
||||
if (videoCheckBox != null) {
|
||||
videoCheckBox.setValue(false);
|
||||
}
|
||||
}
|
||||
|
||||
private Widget createVideoHeader() {
|
||||
Label audioHeader = new Label("Videos");
|
||||
return audioHeader;
|
||||
}
|
||||
|
||||
private Widget createAudioButton(final MediaTrack audioTrack, MediaTrack selectedAudioTrack) {
|
||||
String label = audioTrack != null ? audioTrack.title: "Sound off";
|
||||
String title = audioTrack != null ? audioTrack.toString() : "Turn off all sound channels.";
|
||||
RadioButton audioButton = new RadioButton("group-name", label);
|
||||
audioButton.setTitle(title);
|
||||
audioButton.setValue(audioTrack == selectedAudioTrack);
|
||||
audioButton.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
|
||||
|
||||
@Override
|
||||
public void onValueChange(ValueChangeEvent<Boolean> changeEvent) {
|
||||
if (changeEvent.getValue()) {
|
||||
mediaSelectionListener.audioChanged(audioTrack);
|
||||
}
|
||||
}
|
||||
});
|
||||
return audioButton;
|
||||
}
|
||||
|
||||
private Widget createAudioHeader() {
|
||||
Label audioHeader = new Label("Audio Tracks");
|
||||
return audioHeader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(CloseEvent<PopupPanel> arg0) {
|
||||
dialogControl.clear();
|
||||
videoCheckBoxes.clear();
|
||||
}
|
||||
|
||||
public boolean isShowing() {
|
||||
return dialogControl.isShowing();
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
dialogControl.hide(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-9
@@ -170,9 +170,10 @@ import com.sap.sse.gwt.shared.DebugConstants;
|
||||
public class RaceMap extends AbstractCompositeComponent<RaceMapSettings> implements TimeListener, CompetitorSelectionChangeListener,
|
||||
RaceTimesInfoProviderListener, TailFactory, ColorMapperChangedListener, RequiresDataInitialization, RequiresResize, QuickFlagDataValuesProvider {
|
||||
/* Line colors */
|
||||
static final String ADVANTAGE_LINE_COLOR = "#ff9900"; // orange
|
||||
static final String START_LINE_COLOR = "#ffffff";
|
||||
static final String FINISH_LINE_COLOR = "#000000";
|
||||
static private final RGBColor COURSE_MIDDLE_LINE_COLOR = new RGBColor("#0eed1d"); // selected by Larry Rosenfeld...
|
||||
static final Color ADVANTAGE_LINE_COLOR = new RGBColor("#ff9900"); // orange
|
||||
static final Color START_LINE_COLOR = Color.WHITE;
|
||||
static final Color FINISH_LINE_COLOR = Color.BLACK;
|
||||
static final Color LOWLIGHTED_TAIL_COLOR = new RGBColor(200, 200, 200);
|
||||
/* Line opacities and stroke weights */
|
||||
static final double LOWLIGHTED_TAIL_OPACITY = 0.3;
|
||||
@@ -1824,7 +1825,7 @@ public class RaceMap extends AbstractCompositeComponent<RaceMapSettings> impleme
|
||||
PolylineOptions options = PolylineOptions.newInstance();
|
||||
options.setClickable(true);
|
||||
options.setGeodesic(true);
|
||||
options.setStrokeColor(ADVANTAGE_LINE_COLOR);
|
||||
options.setStrokeColor(ADVANTAGE_LINE_COLOR.getAsHtml());
|
||||
options.setStrokeWeight(1);
|
||||
options.setStrokeOpacity(0.5);
|
||||
|
||||
@@ -1966,7 +1967,7 @@ public class RaceMap extends AbstractCompositeComponent<RaceMapSettings> impleme
|
||||
(settings.getHelpLinesSettings().isVisible(HelpLineTypes.COURSEGEOMETRY) &&
|
||||
(!startLineEqualsFinishLine(courseDTO) || showFinishLineBasedOnCurrentLeg));
|
||||
startLine = showOrRemoveOrUpdateLine(startLine, reallyShowStartLine, startLineLeftPosition,
|
||||
startLineRightPosition, startLineInfoProvider, START_LINE_COLOR, STANDARD_LINE_STROKEWEIGHT,
|
||||
startLineRightPosition, startLineInfoProvider, START_LINE_COLOR.getAsHtml(), STANDARD_LINE_STROKEWEIGHT,
|
||||
STANDARD_LINE_OPACITY);
|
||||
// draw the finish line
|
||||
final Position finishLineLeftPosition = numberOfFinishWaypointMarks == 0 ? null : courseDTO.getFinishMarkPositions().get(0);
|
||||
@@ -1981,7 +1982,7 @@ public class RaceMap extends AbstractCompositeComponent<RaceMapSettings> impleme
|
||||
finishLineAdvantageText.delete(0, finishLineAdvantageText.length());
|
||||
}
|
||||
finishLine = showOrRemoveOrUpdateLine(finishLine, reallyShowFinishLine, finishLineLeftPosition,
|
||||
finishLineRightPosition, finishLineInfoProvider, FINISH_LINE_COLOR, STANDARD_LINE_STROKEWEIGHT,
|
||||
finishLineRightPosition, finishLineInfoProvider, FINISH_LINE_COLOR.getAsHtml(), STANDARD_LINE_STROKEWEIGHT,
|
||||
STANDARD_LINE_STROKEWEIGHT);
|
||||
// the control point pairs for which we already decided whether or not
|
||||
// to show a course middle line for; values tell whether to show the line and for which zero-based
|
||||
@@ -1993,8 +1994,9 @@ public class RaceMap extends AbstractCompositeComponent<RaceMapSettings> impleme
|
||||
boolean showCourseMiddleLine = keysAlreadyHandled.containsKey(key) && keysAlreadyHandled.get(key).getA() ||
|
||||
settings.getHelpLinesSettings().isVisible(HelpLineTypes.COURSEGEOMETRY) ||
|
||||
(settings.getHelpLinesSettings().isVisible(HelpLineTypes.COURSEMIDDLELINE)
|
||||
&& courseDTO.currentLegNumber > 0
|
||||
&& courseDTO.currentLegNumber-1 == zeroBasedIndexOfStartWaypoint);
|
||||
// show the line for the current leg or for the first leg if we are still before the start
|
||||
&& (courseDTO.currentLegNumber-1 == zeroBasedIndexOfStartWaypoint) ||
|
||||
courseDTO.currentLegNumber == 0 && zeroBasedIndexOfStartWaypoint == 0);
|
||||
keysAlreadyHandled.put(key, new Pair<>(showCourseMiddleLine, zeroBasedIndexOfStartWaypoint));
|
||||
}
|
||||
Set<Set<ControlPointDTO>> keysToConsider = new HashSet<>(keysAlreadyHandled.keySet());
|
||||
@@ -2068,7 +2070,7 @@ public class RaceMap extends AbstractCompositeComponent<RaceMapSettings> impleme
|
||||
}
|
||||
};
|
||||
return showOrRemoveOrUpdateLine(lineToShowOrRemoveOrUpdate, showLine, position1DTO, position2DTO,
|
||||
lineInfoProvider, "#2268a0", STANDARD_LINE_STROKEWEIGHT, STANDARD_LINE_OPACITY);
|
||||
lineInfoProvider, COURSE_MIDDLE_LINE_COLOR.getAsHtml(), STANDARD_LINE_STROKEWEIGHT, STANDARD_LINE_OPACITY);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+42
-12
@@ -1203,6 +1203,10 @@ public abstract class LeaderboardPanel<LS extends LeaderboardSettings> extends A
|
||||
new FormattedDoubleLeaderboardRowDTODetailTypeColumn(DetailType.RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS,
|
||||
new RaceCurrentSpeedOverGroundInKnots(), LEG_COLUMN_HEADER_STYLE, LEG_COLUMN_STYLE,
|
||||
LeaderboardPanel.this));
|
||||
result.put(DetailType.RACE_CURRENT_COURSE_OVER_GROUND_IN_TRUE_DEGREES,
|
||||
new FormattedDoubleLeaderboardRowDTODetailTypeColumn(DetailType.RACE_CURRENT_COURSE_OVER_GROUND_IN_TRUE_DEGREES,
|
||||
new RaceCurrentCourseOverGroundInTrueDegrees(), LEG_COLUMN_HEADER_STYLE, LEG_COLUMN_STYLE,
|
||||
LeaderboardPanel.this));
|
||||
result.put(DetailType.BRAVO_RACE_CURRENT_RIDE_HEIGHT_IN_METERS,
|
||||
new RideHeightColumn(DetailType.BRAVO_RACE_CURRENT_RIDE_HEIGHT_IN_METERS,
|
||||
new RaceCurrentRideHeightInMeters(), LEG_COLUMN_HEADER_STYLE, LEG_COLUMN_STYLE,
|
||||
@@ -1580,6 +1584,44 @@ public abstract class LeaderboardPanel<LS extends LeaderboardSettings> extends A
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the average absolute (distance always counted as positive, no matter whether left or right)
|
||||
* cross-track error for the race
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*/
|
||||
private class RaceCurrentSpeedOverGroundInKnots implements DataExtractor<Double, LeaderboardRowDTO> {
|
||||
@Override
|
||||
public Double get(LeaderboardRowDTO row) {
|
||||
Double result = null;
|
||||
LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceColumnName.get(getRaceColumnName());
|
||||
if (fieldsForRace != null) {
|
||||
result = fieldsForRace.currentSpeedAndCourseOverGround == null ? null :
|
||||
fieldsForRace.currentSpeedAndCourseOverGround.getKnots();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the average absolute (distance always counted as positive, no matter whether left or right)
|
||||
* cross-track error for the race
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*/
|
||||
private class RaceCurrentCourseOverGroundInTrueDegrees implements DataExtractor<Double, LeaderboardRowDTO> {
|
||||
@Override
|
||||
public Double get(LeaderboardRowDTO row) {
|
||||
Double result = null;
|
||||
LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceColumnName.get(getRaceColumnName());
|
||||
if (fieldsForRace != null) {
|
||||
result = fieldsForRace.currentSpeedAndCourseOverGround == null ? null :
|
||||
fieldsForRace.currentSpeedAndCourseOverGround.getBearing().getDegrees();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the average absolute (distance always counted as positive, no matter whether left or right)
|
||||
* cross-track error for the race
|
||||
@@ -1912,18 +1954,6 @@ public abstract class LeaderboardPanel<LS extends LeaderboardSettings> extends A
|
||||
}
|
||||
}
|
||||
|
||||
private class RaceCurrentSpeedOverGroundInKnots extends AbstractLastLegDetailField<Double> {
|
||||
@Override
|
||||
protected Double getBeforeLastLegFinished(LegEntryDTO currentLegDetail) {
|
||||
return currentLegDetail.currentSpeedOverGroundInKnots;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Double getAfterLastLegFinished(LeaderboardRowDTO row) {
|
||||
return new RaceAverageSpeedInKnots().get(row);
|
||||
}
|
||||
}
|
||||
|
||||
private class RaceCurrentRideHeightInMeters extends AbstractLastLegDetailField<Double> {
|
||||
@Override
|
||||
protected Double getBeforeLastLegFinished(LegEntryDTO currentLegDetail) {
|
||||
|
||||
+1
-1
@@ -965,7 +965,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
}
|
||||
|
||||
private BoatClassDTO convertToBoatClassDTO(BoatClass boatClass) {
|
||||
return boatClass==null?null:new BoatClassDTO(boatClass.getName(), boatClass.getDisplayName(), boatClass.getHullLength(), boatClass.getHullBeam());
|
||||
return boatClass==null?null:new BoatClassDTO(boatClass.getName(), boatClass.getHullLength(), boatClass.getHullBeam());
|
||||
}
|
||||
|
||||
private List<SeriesDTO> convertToSeriesDTOs(Regatta regatta) {
|
||||
|
||||
+6
-11
@@ -2019,15 +2019,12 @@ public class SailingServiceWriteImpl extends SailingServiceImpl implements Saili
|
||||
Set<CompetitorWithBoatDTO> competitorDTOs)
|
||||
throws CompetitorRegistrationOnRaceLogDisabledException, NotFoundException {
|
||||
getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName));
|
||||
|
||||
RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName);
|
||||
Fleet fleet = getFleetByName(raceColumn, fleetName);
|
||||
|
||||
Map<CompetitorWithBoat, Boat> competitorsToRegister = new HashMap<>();
|
||||
for (CompetitorWithBoatDTO dto : competitorDTOs) {
|
||||
competitorsToRegister.put(getCompetitor(dto), getBoat(dto.getBoat()));
|
||||
}
|
||||
|
||||
Map<CompetitorWithBoat, Boat> competitorsRegisteredInRaceLog = new HashMap<>();
|
||||
for (final Entry<Competitor, Boat> e : raceColumn.getCompetitorsRegisteredInRacelog(fleet).entrySet()) {
|
||||
competitorsRegisteredInRaceLog.put((CompetitorWithBoat) e.getKey(), e.getValue());
|
||||
@@ -2150,10 +2147,10 @@ public class SailingServiceWriteImpl extends SailingServiceImpl implements Saili
|
||||
int flightCount = 0;
|
||||
int groupCount = 0;
|
||||
for (RaceColumn raceColumn : leaderboard.getRaceColumns()) {
|
||||
if (Util.contains(selectedFlightNames, raceColumn.getName())) {
|
||||
groupCount = 0;
|
||||
for (Fleet fleet : raceColumn.getFleets()) {
|
||||
raceColumn.enableCompetitorRegistrationOnRaceLog(fleet);
|
||||
groupCount = 0;
|
||||
for (Fleet fleet : raceColumn.getFleets()) {
|
||||
raceColumn.enableCompetitorRegistrationOnRaceLog(fleet);
|
||||
if (Util.contains(selectedFlightNames, raceColumn.getName())) {
|
||||
Map<CompetitorDTO, BoatDTO> competitors = new HashMap<>();
|
||||
List<Pair<CompetitorDTO, BoatDTO>> competitorsFromPairingList = pairingListDTO.getPairingList()
|
||||
.get(flightCount).get(groupCount);
|
||||
@@ -2165,14 +2162,12 @@ public class SailingServiceWriteImpl extends SailingServiceImpl implements Saili
|
||||
this.setCompetitorRegistrationsInRaceLog(leaderboard.getName(), raceColumn.getName(),
|
||||
fleet.getName(), competitors);
|
||||
groupCount++;
|
||||
}
|
||||
flightCount++;
|
||||
} else {
|
||||
for (Fleet fleet : raceColumn.getFleets()) {
|
||||
} else {
|
||||
this.setCompetitorRegistrationsInRaceLog(leaderboard.getName(), raceColumn.getName(),
|
||||
fleet.getName(), new HashSet<CompetitorWithBoatDTO>());
|
||||
}
|
||||
}
|
||||
flightCount++;
|
||||
}
|
||||
if (leaderboard instanceof LeaderboardThatHasRegattaLike && flightMultiplier > 1) {
|
||||
final IsRegattaLike regattaLike = ((LeaderboardThatHasRegattaLike) leaderboard).getRegattaLike();
|
||||
|
||||
+5
@@ -14,6 +14,11 @@ public class CoursePositionsDTO implements IsSerializable {
|
||||
public Set<MarkDTO> marks;
|
||||
|
||||
public int totalLegsCount;
|
||||
|
||||
/**
|
||||
* The leg number is 0 before the start, the number of the current leg during the race
|
||||
* and the number of the last leg at the end of the race even if the race has finished.
|
||||
*/
|
||||
public int currentLegNumber;
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ public class LeaderboardUpdateEventNewsProvider implements EventNewsProvider {
|
||||
if (leaderboard instanceof RegattaLeaderboard) {
|
||||
BoatClass boatClass = ((RegattaLeaderboard) leaderboard).getRegatta().getBoatClass();
|
||||
if (boatClass != null) {
|
||||
boatClassName = boatClass.getDisplayName();
|
||||
boatClassName = boatClass.getName();
|
||||
}
|
||||
}
|
||||
result.add(new LeaderboardUpdateNewsItem(event.getId(), timePointOfLatestModification.asDate(), leaderboard.getName(), displayName, boatClassName));
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ public enum DetailCheckboxInfo {
|
||||
REGATTA_RANK(DetailType.REGATTA_RANK, "Regatta Rank"), TOTAL_DISTANCE(DetailType.OVERALL_TOTAL_DISTANCE_TRAVELED , "Total distance"), TOTAL_AVERAGE_SPEED_OVER_GROUND(DetailType.OVERALL_TOTAL_AVERAGE_SPEED_OVER_GROUND, "∅ SOG"), TOTAL_TIME(DetailType.OVERALL_TOTAL_TIME_SAILED_IN_SECONDS, "Total time"), MAXIMUM_SPEED_OVER_GROUND(DetailType.OVERALL_MAXIMUM_SPEED_OVER_GROUND_IN_KNOTS, "Max SOG"), TIME_ON_TIME_FACTOR(DetailType.OVERALL_TIME_ON_TIME_FACTOR, "ToT Factor"), TIME_ON_DISTANCE_ALLOWANCE(DetailType.OVERALL_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE, "ToD Allowance"),
|
||||
|
||||
// Race details
|
||||
RACE_GAP_TO_LEADER(DetailType.RACE_GAP_TO_LEADER_IN_SECONDS, "Gap to leader"), RACE_AVERAGE_SPEED_OVER_GROUND(DetailType.RACE_AVERAGE_SPEED_OVER_GROUND_IN_KNOTS, "∅ Speed"), RACE_DISTANCE(DetailType.RACE_DISTANCE_TRAVELED, "Distance"), RACE_DISTANCE_INCLUDING_GATE_START(DetailType.RACE_DISTANCE_TRAVELED_INCLUDING_GATE_START, "Distance (w/ Gate Start)"), RACE_TIME(DetailType.RACE_TIME_TRAVELED, "Time"), RACE_CURRENT_SPEED_OVER_GROUND(DetailType.RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS, "SOG"), RACE_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD(DetailType.RACE_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD_IN_METERS, "Gap"), NUMBER_OF_MANEUVERS(DetailType.NUMBER_OF_MANEUVERS, "Maneuvers"), DISPLAY_LEGS(DetailType.RACE_DISPLAY_LEGS, "Legs"), CURRENT_LEG(DetailType.RACE_CURRENT_LEG, "On Leg"), RACE_AVERAGE_ABSOLUTE_CROSS_TRACK_ERROR(DetailType.RACE_AVERAGE_ABSOLUTE_CROSS_TRACK_ERROR_IN_METERS, "∅ XTE"), RACE_AVERAGE_SIGNED_CROSS_TRACK_ERROR(DetailType.RACE_AVERAGE_SIGNED_CROSS_TRACK_ERROR_IN_METERS, "∅ XTE +/-"), RACE_RATIO_BETWEEN_TIME_SINCE_LAST_POSITION_FIX_AND_AVERAGE_SAMPLING_INTERVAL(DetailType.RACE_RATIO_BETWEEN_TIME_SINCE_LAST_POSITION_FIX_AND_AVERAGE_SAMPLING_INTERVAL, "GPS Lag"),
|
||||
RACE_GAP_TO_LEADER(DetailType.RACE_GAP_TO_LEADER_IN_SECONDS, "Gap to leader"), RACE_AVERAGE_SPEED_OVER_GROUND(DetailType.RACE_AVERAGE_SPEED_OVER_GROUND_IN_KNOTS, "∅ Speed"), RACE_DISTANCE(DetailType.RACE_DISTANCE_TRAVELED, "Distance"), RACE_DISTANCE_INCLUDING_GATE_START(DetailType.RACE_DISTANCE_TRAVELED_INCLUDING_GATE_START, "Distance (w/ Gate Start)"), RACE_TIME(DetailType.RACE_TIME_TRAVELED, "Time"), RACE_CURRENT_SPEED_OVER_GROUND(DetailType.RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS, "SOG"), RACE_CURRENT_COURSE_OVER_GROUND(DetailType.RACE_CURRENT_COURSE_OVER_GROUND_IN_TRUE_DEGREES, "COG"), RACE_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD(DetailType.RACE_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD_IN_METERS, "Gap"), NUMBER_OF_MANEUVERS(DetailType.NUMBER_OF_MANEUVERS, "Maneuvers"), DISPLAY_LEGS(DetailType.RACE_DISPLAY_LEGS, "Legs"), CURRENT_LEG(DetailType.RACE_CURRENT_LEG, "On Leg"), RACE_AVERAGE_ABSOLUTE_CROSS_TRACK_ERROR(DetailType.RACE_AVERAGE_ABSOLUTE_CROSS_TRACK_ERROR_IN_METERS, "∅ XTE"), RACE_AVERAGE_SIGNED_CROSS_TRACK_ERROR(DetailType.RACE_AVERAGE_SIGNED_CROSS_TRACK_ERROR_IN_METERS, "∅ XTE +/-"), RACE_RATIO_BETWEEN_TIME_SINCE_LAST_POSITION_FIX_AND_AVERAGE_SAMPLING_INTERVAL(DetailType.RACE_RATIO_BETWEEN_TIME_SINCE_LAST_POSITION_FIX_AND_AVERAGE_SAMPLING_INTERVAL, "GPS Lag"),
|
||||
|
||||
// Race Start Analysis
|
||||
RACE_DISTANCE_TO_START_FIVE_SECONDS_BEFORE_START(DetailType.RACE_DISTANCE_TO_START_FIVE_SECONDS_BEFORE_RACE_START, "Distance to line 5s before start"), RACE_SPEED_OVER_GROUND_FIVE_SECONDS_BEFORE_START(DetailType.RACE_SPEED_OVER_GROUND_FIVE_SECONDS_BEFORE_START, "SOG 5s before start"), DISTANCE_TO_START_AT_RACE_START(DetailType.DISTANCE_TO_START_AT_RACE_START, "Distance to line at Start"), TIME_BETWEEN_RACE_START_AND_COMPETITOR_START(DetailType.TIME_BETWEEN_RACE_START_AND_COMPETITOR_START, "Start delay"), SPEED_OVER_GROUND_AT_RACE_START(DetailType.SPEED_OVER_GROUND_AT_RACE_START, "SOG at Start"), SPEED_OVER_GROUND_WHEN_STARTING(DetailType.SPEED_OVER_GROUND_WHEN_PASSING_START, "SOG when Starting"), DISTANCE_TO_STARBOARD_END_OF_STARTLINE_WHEN_STARTING(DetailType.DISTANCE_TO_STARBOARD_END_OF_STARTLINE_WHEN_PASSING_START_IN_METERS, "Dist. Stb-Side of Line when Starting"), START_TACK(DetailType.START_TACK, "Start Tack"),
|
||||
|
||||
+3
-3
@@ -53,9 +53,9 @@ public class BoatClassJsonSerializer implements JsonSerializer<BoatClass> {
|
||||
result.put(FIELD_HULL_BEAM_IN_METERS, boatClass.getHullBeam().getMeters());
|
||||
}
|
||||
final JSONArray aliasNames = new JSONArray();
|
||||
if (boatClass.getDisplayName() != null) {
|
||||
result.put(FIELD_DISPLAY_NAME, boatClass.getDisplayName());
|
||||
final BoatClassMasterdata masterData = BoatClassMasterdata.resolveBoatClass(boatClass.getDisplayName());
|
||||
if (boatClass.getName() != null) {
|
||||
result.put(FIELD_DISPLAY_NAME, boatClass.getName());
|
||||
final BoatClassMasterdata masterData = BoatClassMasterdata.resolveBoatClass(boatClass.getName());
|
||||
if (masterData != null) {
|
||||
result.put(FIELD_ICON_URL, "/gwt/src/main/resources/com/sap/sailing/gwt/ui/client/images/boatclass/"+masterData.name().replaceAll("^_", "")+".png");
|
||||
aliasNames.addAll(Arrays.asList(masterData.getAlternativeNames()));
|
||||
|
||||
+1
-1
@@ -123,7 +123,7 @@ public class RaceLogEventDeserializerTest {
|
||||
|
||||
@Test
|
||||
public void testSerializationAndDeserializationForRaceLogORCCertificateAssignmentEvent() throws IOException, ParseException {
|
||||
final Boat boat = new BoatImpl(UUID.randomUUID(), "Testboot", new BoatClassImpl("Testklasse", BoatClassMasterdata.ORC), "GER 007");
|
||||
final Boat boat = new BoatImpl(UUID.randomUUID(), "Testboot", new BoatClassImpl(BoatClassMasterdata.ORC), "GER 007");
|
||||
final ORCCertificate certificate = ORCCertificatesImporter.INSTANCE.read(new StringReader("NATCERTN.FILE_ID SAILNUMB NAME TYPE BUILDER DESIGNER YEAR CLUB OWNER ADRS1 ADRS2 C_Type D CREW DD_MM_yyYY HH:MM:SS LOA IMSL DRAFT BMAX DSPL INDEX DA GPH TMF ILCGA PLT-O PLD-O WL6 WL8 WL10 WL12 WL14 WL16 WL20 OL6 OL8 OL10 OL12 OL14 OL16 OL20 CR6 CR8 CR10 CR12 CR14 CR16 CR20 NSP6 NSP8 NSP10 NSP12 NSP14 NSP16 NSP20 OC6 OC8 OC10 OC12 OC14 OC16 OC20 UA6 UA8 UA10 UA12 UA14 UA16 UA20 DA6 DA8 DA10 DA12 DA14 DA16 DA20 UP6 UP8 UP10 UP12 UP14 UP16 UP20 R526 R528 R5210 R5212 R5214 R5216 R5220 R606 R608 R6010 R6012 R6014 R6016 R6020 R756 R758 R7510 R7512 R7514 R7516 R7520 R906 R908 R9010 R9012 R9014 R9016 R9020 R1106 R1108 R11010 R11012 R11014 R11016 R11020 R1206 R1208 R12010 R12012 R12014 R12016 R12020 R1356 R1358 R13510 R13512 R13514 R13516 R13520 R1506 R1508 R15010 R15012 R15014 R15016 R15020 D6 D8 D10 D12 D14 D16 D20 OTNLOW OTNMED OTNHIG ITNLOW ITNMED ITNHIG DH_TOD DH_TOT PLT-I PLD-I TMF-OF PLT2H PLD2H OSN ReferenceNo CDL DSPS WSS MAIN GENOA SYM ASYM OTDLOW OTDMED OTDHIG ITDLOW ITDMED ITDHIG NS_TOD NS_TOT GNSTOD GNSTOT GDHTOD GDHTOT\r\n" +
|
||||
"AUT017/19noi AUT NOI Sunbeam 40.1 Sunbeam Yachts J&J 2014 Austria CLUB C 789 12 03 2019 15:54:33 11.990 10.960 2.067 3.99 8500. 122.3 0.33 655.6 0.9532 708.2 0.000 0.0 1148.6 906.3 768.6 681.6 629.2 597.0 570.9 1081.1 863.0 740.1 664.4 621.3 598.6 579.4 930.4 739.6 634.3 571.5 532.6 508.0 480.5 930.4 739.6 634.3 571.5 532.6 508.0 480.5 1153.3 850.5 688.3 589.6 538.7 504.5 456.8 44.5 42.6 42.1 41.2 40.5 40.0 40.5 154.1 160.1 167.4 171.2 174.1 175.7 178.3 1101.4 902.4 790.1 719.8 688.5 678.5 681.3 706.8 592.3 524.6 490.4 475.6 470.2 468.3 661.7 559.6 502.6 476.1 462.8 456.1 452.9 630.6 534.7 487.5 465.4 451.0 440.1 428.5 638.5 537.7 487.2 464.0 448.6 433.5 410.8 711.0 581.4 506.6 472.4 453.4 437.2 404.7 754.8 616.9 533.9 486.1 462.0 444.9 411.8 883.0 695.9 592.5 522.9 482.7 460.6 427.5 1036.8 794.8 661.5 576.5 516.0 480.1 442.8 1195.8 910.2 747.1 643.3 569.7 515.5 460.4 0.8624 1.1782 1.3607 0.6570 0.9425 1.1340 0.0 0.0000 0.000 0.0 0.9470 0.000 0.0 633.6 AUT00002508 9.784 9570 36.0 45.7 39.3 0.0 0.0 782.7 572.9 496.1 1027.4 716.2 595.2 633.6 0.9470 655.6 0.9152 0.0 0.0000")).getCertificates().iterator().next();
|
||||
final RaceLogORCCertificateAssignmentEventImpl originalEvent = new RaceLogORCCertificateAssignmentEventImpl(timePoint, timePoint, author, UUID.randomUUID(), 0, certificate, boat);
|
||||
|
||||
+2
-2
@@ -353,7 +353,7 @@ public class EstimationDataSerializationDeserializationTest {
|
||||
BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er", /* typicallyStartsUpwind */true);
|
||||
String name = boatClass.getName();
|
||||
boolean typicallyStartsUpwind = boatClass.typicallyStartsUpwind();
|
||||
String displayName = boatClass.getDisplayName();
|
||||
String displayName = boatClass.getName();
|
||||
Distance hullLength = boatClass.getHullLength();
|
||||
Distance hullBeam = boatClass.getHullBeam();
|
||||
BoatHullType hullType = boatClass.getHullType();
|
||||
@@ -363,7 +363,7 @@ public class EstimationDataSerializationDeserializationTest {
|
||||
BoatClass deserialized = deserializer.deserialize(json);
|
||||
assertEquals(name, deserialized.getName());
|
||||
assertEquals(typicallyStartsUpwind, deserialized.typicallyStartsUpwind());
|
||||
assertEquals(displayName, deserialized.getDisplayName());
|
||||
assertEquals(displayName, deserialized.getName());
|
||||
assertEquals(hullLength, deserialized.getHullLength());
|
||||
assertEquals(hullBeam, deserialized.getHullBeam());
|
||||
assertEquals(hullType, deserialized.getHullType());
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ public class DetailedBoatClassJsonSerializer extends BoatClassJsonSerializer {
|
||||
@Override
|
||||
public JSONObject serialize(BoatClass boatClass) {
|
||||
JSONObject result = super.serialize(boatClass);
|
||||
result.put(DISPLAY_NAME, boatClass.getDisplayName());
|
||||
result.put(DISPLAY_NAME, boatClass.getName());
|
||||
result.put(HULL_LENGTH_IN_METERS, boatClass.getHullLength().getMeters());
|
||||
result.put(HULL_BEAM_IN_METERS, boatClass.getHullBeam().getMeters());
|
||||
result.put(HULL_TYPE, boatClass.getHullType().toString());
|
||||
|
||||
+38
-5
@@ -3,13 +3,18 @@ package com.sap.sailing.server.impl.preferences;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.CompetitorAndBoatStore;
|
||||
import com.sap.sailing.domain.base.impl.DynamicCompetitor;
|
||||
import com.sap.sailing.server.impl.preferences.model.CompetitorNotificationPreference;
|
||||
import com.sap.sailing.server.impl.preferences.model.CompetitorNotificationPreferences;
|
||||
import com.sap.sse.security.PreferenceObjectBasedNotificationSet;
|
||||
import com.sap.sse.security.StoreServiceTrackerCustomizer;
|
||||
import com.sap.sse.security.interfaces.UserStore;
|
||||
|
||||
/**
|
||||
@@ -19,16 +24,41 @@ import com.sap.sse.security.interfaces.UserStore;
|
||||
*/
|
||||
public abstract class AbstractCompetitorNotificationSet
|
||||
extends PreferenceObjectBasedNotificationSet<CompetitorNotificationPreferences, Competitor> {
|
||||
private static final Logger logger = Logger.getLogger(AbstractCompetitorNotificationSet.class.getName());
|
||||
private CompetitorAndBoatStore competitorAndBoatStore;
|
||||
private ServiceTracker<CompetitorAndBoatStore, CompetitorAndBoatStore> tracker;
|
||||
|
||||
public AbstractCompetitorNotificationSet(UserStore store) {
|
||||
super(CompetitorNotificationPreferences.PREF_NAME, store);
|
||||
public AbstractCompetitorNotificationSet(UserStore userStore, CompetitorAndBoatStore competitorAndBoatStore) {
|
||||
super(CompetitorNotificationPreferences.PREF_NAME, userStore);
|
||||
this.competitorAndBoatStore = competitorAndBoatStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used to automatically track {@link UserStore} as OSGi service.
|
||||
* Constructor used to automatically track {@link UserStore} and {@link CompetitorAndBoatStore} as OSGi service.
|
||||
*/
|
||||
public AbstractCompetitorNotificationSet(BundleContext bundleContext) {
|
||||
super(CompetitorNotificationPreferences.PREF_NAME, bundleContext);
|
||||
if (bundleContext == null) {
|
||||
this.tracker = null;
|
||||
} else {
|
||||
this.tracker = new ServiceTracker<CompetitorAndBoatStore, CompetitorAndBoatStore>(bundleContext,
|
||||
CompetitorAndBoatStore.class,
|
||||
new StoreServiceTrackerCustomizer<CompetitorAndBoatStore>(bundleContext, logger) {
|
||||
@Override
|
||||
protected void setStore(CompetitorAndBoatStore store) {
|
||||
AbstractCompetitorNotificationSet.this.competitorAndBoatStore = store;
|
||||
}
|
||||
@Override
|
||||
protected void removeStore() {
|
||||
AbstractCompetitorNotificationSet.this.competitorAndBoatStore = null;
|
||||
}
|
||||
@Override
|
||||
protected CompetitorAndBoatStore getStore() {
|
||||
return AbstractCompetitorNotificationSet.this.competitorAndBoatStore;
|
||||
}
|
||||
});
|
||||
this.tracker.open();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -36,12 +66,15 @@ public abstract class AbstractCompetitorNotificationSet
|
||||
Set<Competitor> result = new HashSet<>();
|
||||
for (CompetitorNotificationPreference pref : preference.getCompetitors()) {
|
||||
if (shouldNotifyFor(pref)) {
|
||||
result.add(pref.getCompetitor());
|
||||
String competitorId = pref.getCompetitorId();
|
||||
DynamicCompetitor competitor = competitorAndBoatStore.getExistingCompetitorByIdAsString(competitorId);
|
||||
if (competitor != null) {
|
||||
result.add(competitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected abstract boolean shouldNotifyFor(CompetitorNotificationPreference pref);
|
||||
|
||||
}
|
||||
+4
-3
@@ -3,6 +3,7 @@ package com.sap.sailing.server.impl.preferences;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.CompetitorAndBoatStore;
|
||||
import com.sap.sailing.server.impl.preferences.model.CompetitorNotificationPreference;
|
||||
import com.sap.sse.security.interfaces.UserStore;
|
||||
|
||||
@@ -12,12 +13,12 @@ import com.sap.sse.security.interfaces.UserStore;
|
||||
*/
|
||||
public class CompetitorResultsNotificationSet extends AbstractCompetitorNotificationSet {
|
||||
|
||||
public CompetitorResultsNotificationSet(UserStore store) {
|
||||
super(store);
|
||||
public CompetitorResultsNotificationSet(UserStore store, CompetitorAndBoatStore competitorAndBoatStore) {
|
||||
super(store, competitorAndBoatStore);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used to automatically track {@link UserStore} as OSGi service.
|
||||
* Constructor used to automatically track {@link UserStore} and {@link CompetitorAndBoatStore} as OSGi service.
|
||||
*/
|
||||
public CompetitorResultsNotificationSet(BundleContext bundleContext) {
|
||||
super(bundleContext);
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ public class BoatClassSetting extends AbstractValueSetting<BoatClass> {
|
||||
|
||||
@Override
|
||||
public String toStringValue(BoatClass value) {
|
||||
return value == null ? null : value.getDisplayName();
|
||||
return value == null ? null : value.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+9
-11
@@ -1,25 +1,23 @@
|
||||
package com.sap.sailing.server.impl.preferences.model;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.CompetitorAndBoatStore;
|
||||
import com.sap.sse.common.settings.generic.AbstractGenericSerializableSettings;
|
||||
import com.sap.sse.common.settings.generic.BooleanSetting;
|
||||
import com.sap.sse.common.settings.generic.StringSetting;
|
||||
|
||||
public class CompetitorNotificationPreference extends AbstractGenericSerializableSettings {
|
||||
private static final long serialVersionUID = -6510535362114348707L;
|
||||
|
||||
private transient CompetitorSetting competitor;
|
||||
private transient StringSetting competitorId;
|
||||
private transient BooleanSetting notifyAboutResults;
|
||||
|
||||
public CompetitorNotificationPreference(CompetitorAndBoatStore competitorStore) {
|
||||
competitor = new CompetitorSetting("competitor", this, competitorStore);
|
||||
public CompetitorNotificationPreference() {
|
||||
competitorId = new StringSetting("competitor", this);
|
||||
notifyAboutResults = new BooleanSetting("notifyAboutResults", this, false);
|
||||
}
|
||||
|
||||
public CompetitorNotificationPreference(CompetitorAndBoatStore competitorStore, Competitor competitor,
|
||||
boolean notifyAboutResults) {
|
||||
this(competitorStore);
|
||||
this.competitor.setValue(competitor);
|
||||
public CompetitorNotificationPreference(String competitorId, boolean notifyAboutResults) {
|
||||
this();
|
||||
this.competitorId.setValue(competitorId);
|
||||
this.notifyAboutResults.setValue(notifyAboutResults);
|
||||
}
|
||||
|
||||
@@ -32,8 +30,8 @@ public class CompetitorNotificationPreference extends AbstractGenericSerializabl
|
||||
// The usage of Java Serialization isn't planned by now, either.
|
||||
}
|
||||
|
||||
public Competitor getCompetitor() {
|
||||
return competitor.getValue();
|
||||
public String getCompetitorId() {
|
||||
return competitorId.getValue();
|
||||
}
|
||||
|
||||
public boolean isNotifyAboutResults() {
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ public class CompetitorNotificationPreferences extends AbstractGenericSerializab
|
||||
|
||||
public CompetitorNotificationPreferences(RacingEventService racingEventService) {
|
||||
competitors = new SettingsList<>("competitors", this,
|
||||
() -> new CompetitorNotificationPreference(racingEventService.getCompetitorAndBoatStore()));
|
||||
() -> new CompetitorNotificationPreference());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
package com.sap.sailing.server.impl.preferences.model;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.CompetitorAndBoatStore;
|
||||
import com.sap.sse.common.settings.generic.AbstractGenericSerializableSettings;
|
||||
import com.sap.sse.common.settings.generic.base.AbstractValueSetting;
|
||||
|
||||
/**
|
||||
* Specific setting to hold a {@link Competitor} instance. The competitor is being serialized as ID and deserialized
|
||||
* doing as lookup in the given {@link CompetitorAndBoatStore}.
|
||||
*/
|
||||
public class CompetitorSetting extends AbstractValueSetting<Competitor> {
|
||||
|
||||
protected CompetitorSetting(String name, AbstractGenericSerializableSettings settings,
|
||||
CompetitorAndBoatStore competitorStore) {
|
||||
super(name, settings, null, new CompetitorConverter(competitorStore));
|
||||
}
|
||||
}
|
||||
+9
-8
@@ -14,6 +14,7 @@ import org.osgi.framework.BundleContext;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.CompetitorAndBoatStore;
|
||||
import com.sap.sailing.domain.base.Event;
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
@@ -60,11 +61,11 @@ public class SailingNotificationServiceImpl implements SailingNotificationServic
|
||||
* Constructor used for unit tests to not need BundelContext but directly work with a given UserStore.
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
public SailingNotificationServiceImpl(UserStore userStore, MailQueue mailQueue) throws MalformedURLException {
|
||||
public SailingNotificationServiceImpl(UserStore userStore, CompetitorAndBoatStore competitorAndBoatStore, MailQueue mailQueue) throws MalformedURLException {
|
||||
this(mailQueue,
|
||||
new BoatClassResultsNotificationSet(userStore),
|
||||
new BoatClassUpcomingRaceNotificationSet(userStore),
|
||||
new CompetitorResultsNotificationSet(userStore));
|
||||
new CompetitorResultsNotificationSet(userStore, competitorAndBoatStore));
|
||||
}
|
||||
|
||||
public SailingNotificationServiceImpl(MailQueue mailQueue, BoatClassResultsNotificationSet boatClassResults,
|
||||
@@ -209,8 +210,8 @@ public class SailingNotificationServiceImpl implements SailingNotificationServic
|
||||
protected NotificationMailTemplate getMailTemplate(BoatClass objectToNotifyAbout, Locale locale) {
|
||||
String raceDescription = calculateRaceDescription(locale, event, leaderboard, raceColumn, fleet);
|
||||
return new NotificationMailTemplate(
|
||||
messages.get(locale, "boatClassRaceFinishedSubject", boatClass.getDisplayName()),
|
||||
messages.get(locale, "boatClassRaceFinishedBody", boatClass.getDisplayName(),
|
||||
messages.get(locale, "boatClassRaceFinishedSubject", boatClass.getName()),
|
||||
messages.get(locale, "boatClassRaceFinishedBody", boatClass.getName(),
|
||||
raceDescription),
|
||||
RaceBoardLinkFactory.getBaseURL(event),
|
||||
createRaceBoardShowRaceLink(trackedRace, leaderboard, event, leaderboardGroup, locale),
|
||||
@@ -229,8 +230,8 @@ public class SailingNotificationServiceImpl implements SailingNotificationServic
|
||||
protected NotificationMailTemplate getMailTemplate(BoatClass objectToNotifyAbout, Locale locale) {
|
||||
String leaderboardDescription = calculateLeaderboardDescription(locale, event, leaderboard);
|
||||
return new NotificationMailTemplate(
|
||||
messages.get(locale, "boatClassScoreCorrectionSubject", boatClass.getDisplayName()),
|
||||
messages.get(locale, "boatClassScoreCorrectionBody", boatClass.getDisplayName(),
|
||||
messages.get(locale, "boatClassScoreCorrectionSubject", boatClass.getName()),
|
||||
messages.get(locale, "boatClassScoreCorrectionBody", boatClass.getName(),
|
||||
leaderboardDescription),
|
||||
RaceBoardLinkFactory.getBaseURL(event),
|
||||
createHomeLeaderboardLink(leaderboard, event, locale));
|
||||
@@ -249,8 +250,8 @@ public class SailingNotificationServiceImpl implements SailingNotificationServic
|
||||
String time = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG, locale)
|
||||
.format(when.asDate());
|
||||
return new NotificationMailTemplate(
|
||||
messages.get(locale, "boatClassUpcomingRaceSubject", boatClass.getDisplayName()),
|
||||
messages.get(locale, "boatClassUpcomingRaceBody", boatClass.getDisplayName(),
|
||||
messages.get(locale, "boatClassUpcomingRaceSubject", boatClass.getName()),
|
||||
messages.get(locale, "boatClassUpcomingRaceBody", boatClass.getName(),
|
||||
raceDescription, time),
|
||||
RaceBoardLinkFactory.getBaseURL(event),
|
||||
createHomeRacesListLink(leaderboard, event, locale));
|
||||
|
||||
+3
-3
@@ -833,12 +833,12 @@ public class PolarDiagramBase implements PolarDiagram, Serializable {
|
||||
public long getTurnLoss() {
|
||||
// TODO: retrieve values from polar data mining
|
||||
int turnLoss;
|
||||
if ((this.boatClass.getDisplayName() != null) && (this.boatClass.getDisplayName().equals(BoatClassMasterdata.EXTREME_40.getDisplayName()))) {
|
||||
if ((this.boatClass.getName() != null) && (this.boatClass.getName().equals(BoatClassMasterdata.EXTREME_40.getDisplayName()))) {
|
||||
turnLoss = 2000;
|
||||
} else if ((this.boatClass.getDisplayName() != null) && (this.boatClass.getDisplayName().equals(BoatClassMasterdata.GC_32.getDisplayName()))) {
|
||||
} else if ((this.boatClass.getName() != null) && (this.boatClass.getName().equals(BoatClassMasterdata.GC_32.getDisplayName()))) {
|
||||
// TODO: Needs to be validated
|
||||
turnLoss = 2000;
|
||||
} else if ((this.boatClass.getDisplayName() != null) && (this.boatClass.getDisplayName().equals(BoatClassMasterdata._5O5.getDisplayName()))) {
|
||||
} else if ((this.boatClass.getName() != null) && (this.boatClass.getName().equals(BoatClassMasterdata._5O5.getDisplayName()))) {
|
||||
turnLoss = 5000;
|
||||
} else {
|
||||
turnLoss = 4000; // default value
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ public class PolarDiagramFactoryImpl implements PolarDiagramFactory {
|
||||
public PolarDiagram getPolarDiagram(BoatClass boatClass) {
|
||||
// TODO generalize to dependency on boat class; this is just the first hard-coded example
|
||||
String csvFilePath;
|
||||
if (boatClass.getDisplayName().equals(BoatClassMasterdata._49ER.getDisplayName())) {
|
||||
if (boatClass.getName().equals(BoatClassMasterdata._49ER.getDisplayName())) {
|
||||
csvFilePath = "PolarDiagram49STG.csv";
|
||||
} else {
|
||||
return null;
|
||||
|
||||
@@ -30,6 +30,11 @@
|
||||
<li>The "unlink" button in the competitor import dialog now shows again correctly.</li>
|
||||
<li>Competitors to be imported for which a competitor already exists with an equal ID are
|
||||
now recognized as "similar" and suggested for mapping.</li>
|
||||
<li>Fixed bug that occurred when a pairing list was to be inserted into a regatta's series,
|
||||
and another series existed whose races not yet had the flag set that allows per-race competitor
|
||||
assignments.</li>
|
||||
<li>WindFinder has offered us a new spot collection <tt>new_york</tt> which is now listed in the corresponding
|
||||
content assist in the Events editing dialog, tab "WindFinder".</li>
|
||||
</ul>
|
||||
<h2 class="articleSubheadline">September 2020</h2>
|
||||
<ul class="bulletList">
|
||||
|
||||
+19
-36
@@ -11,9 +11,7 @@ import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
import org.osgi.util.tracker.ServiceTrackerCustomizer;
|
||||
|
||||
import com.sap.sse.common.Stoppable;
|
||||
import com.sap.sse.common.Util;
|
||||
@@ -66,9 +64,7 @@ public abstract class PreferenceObjectBasedNotificationSet<PrefT, T> implements
|
||||
*/
|
||||
private final Map<T, Set<String>> notifications = new HashMap<>();
|
||||
|
||||
private final BundleContext context;
|
||||
|
||||
private final String key;
|
||||
protected final BundleContext context;
|
||||
|
||||
private final ServiceTracker<UserStore, UserStore> tracker;
|
||||
|
||||
@@ -78,15 +74,29 @@ public abstract class PreferenceObjectBasedNotificationSet<PrefT, T> implements
|
||||
* Constructor used to automatically track {@link UserStore} as OSGi service.
|
||||
*/
|
||||
public PreferenceObjectBasedNotificationSet(String key, BundleContext context) {
|
||||
this.key = key;
|
||||
this.context = context;
|
||||
if (context == null) {
|
||||
this.tracker = null;
|
||||
} else {
|
||||
this.tracker = new ServiceTracker<UserStore, UserStore>(context, UserStore.class, new Cutomizer());
|
||||
this.tracker = new ServiceTracker<UserStore, UserStore>(context, UserStore.class,
|
||||
new StoreServiceTrackerCustomizer<UserStore>(context, logger) {
|
||||
@Override
|
||||
protected void setStore(UserStore store) {
|
||||
PreferenceObjectBasedNotificationSet.this.store = store;
|
||||
store.addPreferenceObjectListener(key, listener, true);
|
||||
}
|
||||
@Override
|
||||
protected void removeStore() {
|
||||
PreferenceObjectBasedNotificationSet.this.store = null;
|
||||
}
|
||||
@Override
|
||||
protected UserStore getStore() {
|
||||
return PreferenceObjectBasedNotificationSet.this.store;
|
||||
}
|
||||
});
|
||||
this.tracker.open();
|
||||
}
|
||||
this.lock = new NamedReentrantReadWriteLock(getClass().getName()+" for "+key, /* fair */ false);
|
||||
this.lock = new NamedReentrantReadWriteLock(getClass().getName()+" for "+ key, /* fair */ false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +116,7 @@ public abstract class PreferenceObjectBasedNotificationSet<PrefT, T> implements
|
||||
removeStore();
|
||||
}
|
||||
|
||||
private void removeStore() {
|
||||
protected void removeStore() {
|
||||
if (store != null) {
|
||||
store.removePreferenceObjectListener(listener);
|
||||
store = null;
|
||||
@@ -186,31 +196,4 @@ public abstract class PreferenceObjectBasedNotificationSet<PrefT, T> implements
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Cutomizer implements ServiceTrackerCustomizer<UserStore, UserStore> {
|
||||
@Override
|
||||
public UserStore addingService(ServiceReference<UserStore> reference) {
|
||||
UserStore store = context.getService(reference);
|
||||
if (PreferenceObjectBasedNotificationSet.this.store != null
|
||||
&& PreferenceObjectBasedNotificationSet.this.store != store) {
|
||||
logger.severe("Multiple " + UserStore.class.getSimpleName()
|
||||
+ " instances found. Only one instance is handled.");
|
||||
} else {
|
||||
PreferenceObjectBasedNotificationSet.this.store = store;
|
||||
store.addPreferenceObjectListener(key, listener, true);
|
||||
}
|
||||
return store;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifiedService(ServiceReference<UserStore> reference, UserStore service) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removedService(ServiceReference<UserStore> reference, UserStore service) {
|
||||
if (PreferenceObjectBasedNotificationSet.this.store == service) {
|
||||
removeStore();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.sap.sse.security;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
import org.osgi.util.tracker.ServiceTrackerCustomizer;
|
||||
|
||||
import com.sap.sse.security.interfaces.UserStore;
|
||||
|
||||
public abstract class StoreServiceTrackerCustomizer<T> implements ServiceTrackerCustomizer<T, T> {
|
||||
private final Logger logger;
|
||||
|
||||
private final BundleContext context;
|
||||
|
||||
public StoreServiceTrackerCustomizer(BundleContext context, Logger logger) {
|
||||
this.logger = logger;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
protected abstract void setStore(T store);
|
||||
|
||||
protected abstract void removeStore();
|
||||
|
||||
protected abstract T getStore();
|
||||
|
||||
@Override
|
||||
public T addingService(ServiceReference<T> reference) {
|
||||
T contextStore = context.getService(reference);
|
||||
T thisStore = getStore();
|
||||
if (thisStore != null && thisStore != contextStore) {
|
||||
logger.severe("Multiple " + UserStore.class.getSimpleName()
|
||||
+ " instances found. Only one instance is handled.");
|
||||
} else {
|
||||
setStore(contextStore);
|
||||
}
|
||||
return contextStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifiedService(ServiceReference<T> reference, T store) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removedService(ServiceReference<T> reference, T store) {
|
||||
if (getStore() == store) {
|
||||
removeStore();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
1. [General Introduction to SAP Sailing Analytics](https://sapsailing-documentation.s3-eu-west-1.amazonaws.com/adminconsole/Advanced+Topics/MatchraceSetup.mp4)
|
||||
|
||||
2. General Introduction to SAP Sailing Analytics Backend
|
||||
Overview Functions, Features, known issues and quirks (Explaining start/stop of races and connecting races and how it can go wrong (dos and donts)
|
||||
|
||||
3. How to enhance events created with Sail Insight
|
||||
Moving Marks
|
||||
Adding Marks
|
||||
Managing Media (enhance event website)
|
||||
Editing competitors - what can be changed, what can not be changed (Name, Sailnumber, Boatclass)
|
||||
How to correct results
|
||||
How to combine single regattas into one event
|
||||
How to add GPS data of individual boats
|
||||
Adding Video Playback to a Race Replay
|
||||
|
||||
4. Using the race Manager app in combination with Sail insight
|
||||
To manage results
|
||||
To add and update Wind data
|
||||
To manage a daily schedule
|
||||
To manage start times
|
||||
…
|
||||
|
||||
|
||||
|
||||
- Anlegen eines einfachen Events in der Admin Console
|
||||
- Rechteverwaltung des Events: "Publishing"-Levels (show on homepage und/vs. Group Ownership Management)
|
||||
- Grundlagen Rechteverwaltung: User, Group, Permissions, Roles, Ownerships
|
||||
- [Create an event with multiple regattas](https://sapsailing-documentation.s3-eu-west-1.amazonaws.com/adminconsole/Advanced+Topics/Setting+up+Events+with+multiple+Regattas+or+Classes.mp4)
|
||||
* (boat) classes
|
||||
* assigning regattas to course areas
|
||||
* leaderboards, including sub-divisions
|
||||
- Details of regatta set-up explained:
|
||||
* Provisioned/changing boats
|
||||
* all the bells and whistles including advanced discarding rules
|
||||
- Import competitors from Manage2Sail
|
||||
- Import results using Manage2Sail as an example
|
||||
- Importing an entire event from Manage2Sail ("regatta structure import")
|
||||
- How to get going with the Race Manager App?
|
||||
- Setting up TracTrac connectivity
|
||||
- Setting things up for Smartphone Tracking
|
||||
- How to invite competitors for Sail Insight tracking?
|
||||
* closed regatta, e-mail per competitor
|
||||
* open unmoderated regatta, share QR code/link
|
||||
- How to use the Buoy Pinger app?
|
||||
- Using display names for leaderboards to keep things tidy
|
||||
- Using media to enrich the event
|
||||
* Add images and videos to my event
|
||||
* Link and time-sync audio and video clips to my races
|
||||
- Different ways to add wind data
|
||||
* GRIB files
|
||||
* manual entry in AdminConsole
|
||||
* using the Race Manager App for wind data entry
|
||||
* Expedition logs
|
||||
* Bravo files
|
||||
* connecting Expedition live
|
||||
* Igtimi WindBot live connectivity
|
||||
* Igtimi WindBot data import
|
||||
- Handling split fleet racing
|
||||
* setting it up in the regatta
|
||||
- Course set-up and mark positioning explained
|
||||
* AdminConsole + RaceBoard
|
||||
* Sail Insight
|
||||
* Race Manager App
|
||||
* Buoy Pinger App
|
||||
- Setting up and running ORC PCS regattas
|
||||
- [Setting up a Matchrace Regatta](https://sapsailing-documentation.s3-eu-west-1.amazonaws.com/adminconsole/Advanced+Topics/MatchraceSetup.mp4)
|
||||
- Setting up a 4 boat final
|
||||
- Tips and Tricks for Cleansing Your Event
|
||||
* check max speeds to find outliers
|
||||
* check for mark passing completeness
|
||||
* spot-checks for mark positions in multiple races
|
||||
Reference in new issue
Block a user