Merge remote-tracking branch 'origin/master'

This commit is contained in:
Nick committed 2015-07-18 18:13:56 +02:00
commit 79ae7b8530
141 files changed
+4483 -2033

No files matched your search

+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
# groups Apache / httpd log entries into "${referrer}.ips" files, where ${referrer} is the
# referrer URL identifying the "event"; the lines written to the .ips files hold the IP
# address of the requestor, the date (not the time) and the user agent string.
# Sorting for unique entries should give a count similar to what goaccess is using to
# determine "unique visitors."
# A sample line:
# 505Worlds2012.sapsailing.com 66.249.73.53 - - [12/Jan/2014:03:33:11 +0000] "GET /robots.txt HTTP/1.1" 404 238 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
#cat $* | sed -e 's/^\([^ ]*\) \([^ ]*\) \([^ ]*\) \([^ ]*\) \[\([^:]*\):\([^]]*\)\] \"[^\"]*\" [^ ]* [^ ]* \"[^\"]\" \"\([\"]*\)\"\(.*\)$/\1 \2 \5 \7/'
cat $* | sed -e 's/^\([^ ]*\) \([^ ]*\) \([^ ]*\) \([^ ]*\) \[\([^:]*\):\([^]]*\)\] \"[^\"]*\" [^ ]* [^ ]* \"[^\"]*\" \"\([^\"]*\)\"/\1 \2 \5 \7/' | while read referrer hit; do
echo "$hit" >>${referrer}.ips
done
for i in *.ips; do
echo -n "$i "
cat $i | sort -u | wc | awk '{ print $1; }'
done | tee unique-ips-days-useragents-per-event
echo "Done. Wrote results to `pwd`/unique-ips-days-useragents-per-event
Binary file not shown.
@@ -148,7 +148,7 @@ public class StartlineAnalysisCard extends Composite implements HasWidgets, Star
asyncActionsExecutor, null, Collections.singletonList(startAnalysisDTO.regattaAndRaceIdentifier), 5000l /* requestInterval */); asyncActionsExecutor, null, Collections.singletonList(startAnalysisDTO.regattaAndRaceIdentifier), 5000l /* requestInterval */);
raceMap = new RaceMap(sailingServiceAsync, asyncActionsExecutor, null, timer, competitorSelectionModel, raceMap = new RaceMap(sailingServiceAsync, asyncActionsExecutor, null, timer, competitorSelectionModel,
StringMessages.INSTANCE, false, false, false, startAnalysisDTO.regattaAndRaceIdentifier, StringMessages.INSTANCE, false, false, false, startAnalysisDTO.regattaAndRaceIdentifier,
resources.combinedWindPanelStyle()); resources.combinedWindPanelStyle(), /* showHeaderPanel */ true);
raceMap.onRaceSelectionChange(Collections.singletonList(startAnalysisDTO.regattaAndRaceIdentifier)); raceMap.onRaceSelectionChange(Collections.singletonList(startAnalysisDTO.regattaAndRaceIdentifier));
raceMap.getSettings().setZoomSettings(new RaceMapZoomSettings(zoomTypes, false)); raceMap.getSettings().setZoomSettings(new RaceMapZoomSettings(zoomTypes, false));
raceMap.getSettings().setHelpLinesSettings(getHelpLineSettings()); raceMap.getSettings().setHelpLinesSettings(getHelpLineSettings());
@@ -4,7 +4,7 @@ import com.sap.sailing.domain.common.impl.MeterDistance;
public enum BoatClassMasterdata { public enum BoatClassMasterdata {
_18Footer ("18Footer", true, 8.90, 2.00, BoatHullType.MONOHULL, true, "18.Footer", "18ft", "18ft Skiff"), _18Footer ("18Footer", true, 8.90, 2.00, BoatHullType.MONOHULL, true, "18.Footer", "18ft", "18ft Skiff", "18. Footer"),
_2_4M ("2.4 Meter", true, 4.11, 0.81, BoatHullType.MONOHULL, false, "2.4M", "2.4mR", "2.4 Metre", "2.4-metre"), _2_4M ("2.4 Meter", true, 4.11, 0.81, BoatHullType.MONOHULL, false, "2.4M", "2.4mR", "2.4 Metre", "2.4-metre"),
_5O5 ("5O5", true, 5.03, 1.88, BoatHullType.MONOHULL, true, "505", "5o5", "505er", "5o5er"), _5O5 ("5O5", true, 5.03, 1.88, BoatHullType.MONOHULL, true, "505", "5o5", "505er", "5o5er"),
_12M ("12 Meter", true, 5.97, 1.43, BoatHullType.MONOHULL, true, "12M", "12mR", "12SQM", "12-metre", "12 metre"), _12M ("12 Meter", true, 5.97, 1.43, BoatHullType.MONOHULL, true, "12M", "12mR", "12SQM", "12-metre", "12 metre"),
@@ -31,7 +31,7 @@ public enum BoatClassMasterdata {
FINN ("Finn", true, 4.50, 1.51, BoatHullType.MONOHULL, false), FINN ("Finn", true, 4.50, 1.51, BoatHullType.MONOHULL, false),
FLYING_PHANTOM ("Flying Phantom", true, 5.52, 3.00, BoatHullType.CATAMARAN, true), FLYING_PHANTOM ("Flying Phantom", true, 5.52, 3.00, BoatHullType.CATAMARAN, true),
FOLKBOAT ("Folkboat", true, 7.68, 2.20, BoatHullType.MONOHULL, false, "Folke", "Folkeboot"), FOLKBOAT ("Folkboat", true, 7.68, 2.20, BoatHullType.MONOHULL, false, "Folke", "Folkeboot"),
FUN ("FUN", true, 7.20, 2.45, BoatHullType.MONOHULL, true, "FUN O.D.", "FUN OD"), FUN ("FUN", true, 7.20, 2.45, BoatHullType.MONOHULL, true, "FUN O.D.", "FUN OD", "Open FUN"),
F_16 ("Formula 16", true, 5.00, 2.50, BoatHullType.CATAMARAN, true, "F16", "F-16"), F_16 ("Formula 16", true, 5.00, 2.50, BoatHullType.CATAMARAN, true, "F16", "F-16"),
HOBIE_16 ("Hobie 16", true, 5.05, 2.41, BoatHullType.CATAMARAN, false, "H16"), HOBIE_16 ("Hobie 16", true, 5.05, 2.41, BoatHullType.CATAMARAN, false, "H16"),
H_BOAT ("H-Boat", true, 8.28, 2.18, BoatHullType.MONOHULL, true, "HB"), H_BOAT ("H-Boat", true, 8.28, 2.18, BoatHullType.MONOHULL, true, "HB"),
@@ -27,9 +27,10 @@ public enum WindSourceType {
TRACK_BASED_ESTIMATION(false, 0.5, /* useSpeed */ false), TRACK_BASED_ESTIMATION(false, 0.5, /* useSpeed */ false),
/** /**
* Inferred from the race course layout if the course is known to have its first leg be an upwind leg * Inferred from the race course layout if the course is known to have its first leg be an upwind leg. This
* source has very low confidence and must be superseded by any other wind source.
*/ */
COURSE_BASED(false, 0.3, /* useSpeed */ false), COURSE_BASED(false, 0.01, /* useSpeed */ false),
/** /**
* Wind estimation combined from all other wind sources, using <code>TrackedRace.getWind(...)</code>, based on * Wind estimation combined from all other wind sources, using <code>TrackedRace.getWind(...)</code>, based on
@@ -6,7 +6,7 @@ package com.sap.sailing.domain.common.racelog;
* *
*/ */
public enum RaceLogRaceStatus { public enum RaceLogRaceStatus {
UNKNOWN(0), UNSCHEDULED(1), SCHEDULED(2), STARTPHASE(3), RUNNING(4), FINISHING(5), FINISHED(6); UNKNOWN(0), UNSCHEDULED(1), PRESCHEDULED(2), SCHEDULED(3), STARTPHASE(4), RUNNING(5), FINISHING(6), FINISHED(7);
/** the order number represents the natural order of the states */ /** the order number represents the natural order of the states */
private int orderNumber; private int orderNumber;
@@ -34,13 +34,13 @@ public class DependentStartTimeFinderTest {
private AbstractLogEventAuthor author; private AbstractLogEventAuthor author;
private TimePoint nowMock; private TimePoint nowMock;
private RaceLogResolver raceLogResolver; private RaceLogResolver raceLogResolver;
@Before @Before
public void setUp() { public void setUp() {
author = new LogEventAuthorImpl("Test", 1); author = new LogEventAuthorImpl("Test", 1);
raceLogA = new RaceLogImpl("raceLogA"); raceLogA = new RaceLogImpl("raceLogA");
raceLogB = new RaceLogImpl("raceLogB"); raceLogB = new RaceLogImpl("raceLogB");
raceLogC = new RaceLogImpl("raceLogC"); raceLogC = new RaceLogImpl("raceLogC");
@@ -63,108 +63,137 @@ public class DependentStartTimeFinderTest {
@Test @Test
public void testDependentStartTimeUpdate() { public void testDependentStartTimeUpdate() {
raceLogC.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12, final MillisecondsDurationImpl cAfterB = new MillisecondsDurationImpl(5000);
new SimpleRaceLogIdentifierImpl("B", "", ""), new MillisecondsDurationImpl(5000))); raceLogC.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12,
new SimpleRaceLogIdentifierImpl("B", "", ""), cAfterB));
StartTimeFinder finder = new StartTimeFinder(raceLogResolver, raceLogC); StartTimeFinder finder = new StartTimeFinder(raceLogResolver, raceLogC);
//Tests for correct behaviour, when race depending on has no starttime set // Tests for correct behaviour, when race depending on has no start time set
assertNull(finder.analyze().getStartTime()); assertNull(finder.analyze().getStartTime());
raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12, final MillisecondsDurationImpl bAfterA = new MillisecondsDurationImpl(6000);
new SimpleRaceLogIdentifierImpl("A", "", ""), new MillisecondsDurationImpl(5000))); raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12,
new SimpleRaceLogIdentifierImpl("A", "", ""), bAfterA));
finder = new StartTimeFinder(raceLogResolver, raceLogB);
StartTimeFinderResult result = finder.analyze(); finder = new StartTimeFinder(raceLogResolver, raceLogB);
StartTimeFinderResult result = finder.analyze();
List<SimpleRaceLogIdentifier> expectedDependingOnRaces = new ArrayList<SimpleRaceLogIdentifier>();
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("A", "", "")); List<SimpleRaceLogIdentifier> expectedDependingOnRaces = new ArrayList<>();
assertNull(result.getStartTime()); expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("A", "", ""));
assertEquals(expectedDependingOnRaces, result.getRacesDependingOn()); assertNull(result.getStartTime());
assertEquals(bAfterA, result.getStartTimeDiff());
finder = new StartTimeFinder(raceLogResolver, raceLogC); assertEquals(expectedDependingOnRaces, result.getRacesDependingOn());
//Tests for correct behaviour, when race depending on has a DependentStartTimeEvent and its parent start time is unknown // assertEquals(5000, result.getStartTimeDiff().asMillis());
expectedDependingOnRaces = new ArrayList<SimpleRaceLogIdentifier>();
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("B", "", "")); finder = new StartTimeFinder(raceLogResolver, raceLogC);
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("A", "", "")); // Tests for correct behaviour, when race depending on has a DependentStartTimeEvent and its parent start time
// is unknown
result = finder.analyze(); expectedDependingOnRaces = new ArrayList<>();
assertNull(result.getStartTime()); expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("B", "", ""));
assertEquals(expectedDependingOnRaces, result.getRacesDependingOn()); expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("A", "", ""));
MillisecondsTimePoint now = MillisecondsTimePoint.now(); result = finder.analyze();
raceLogA.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(5000))); assertNull(result.getStartTime());
assertEquals(cAfterB, result.getStartTimeDiff());
finder = new StartTimeFinder(raceLogResolver, raceLogB); assertEquals(expectedDependingOnRaces, result.getRacesDependingOn());
assertEquals(10000, finder.analyze().getStartTime().asMillis());
finder = new StartTimeFinder(raceLogResolver, raceLogC); MillisecondsTimePoint now = MillisecondsTimePoint.now();
assertEquals(15000, finder.analyze().getStartTime().asMillis()); raceLogA.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(5000)));
//Test correct behaviour, when middle element changes finder = new StartTimeFinder(raceLogResolver, raceLogB);
raceLogB.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(15000))); result = finder.analyze();
finder = new StartTimeFinder(raceLogResolver, raceLogA); assertEquals(11000, result.getStartTime().asMillis());
assertEquals(5000, finder.analyze().getStartTime().asMillis()); assertEquals(6000, result.getStartTimeDiff().asMillis());
finder = new StartTimeFinder(raceLogResolver, raceLogB);
assertEquals(15000, finder.analyze().getStartTime().asMillis()); finder = new StartTimeFinder(raceLogResolver, raceLogC);
finder = new StartTimeFinder(raceLogResolver, raceLogC); result = finder.analyze();
assertEquals(20000, finder.analyze().getStartTime().asMillis()); assertEquals(16000, result.getStartTime().asMillis());
assertEquals(5000, result.getStartTimeDiff().asMillis());
// Test correct behaviour, when middle element changes
raceLogB.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(15000)));
finder = new StartTimeFinder(raceLogResolver, raceLogA);
result = finder.analyze();
assertEquals(5000, result.getStartTime().asMillis());
assertNull(result.getStartTimeDiff());
finder = new StartTimeFinder(raceLogResolver, raceLogB);
result = finder.analyze();
assertEquals(15000, result.getStartTime().asMillis());
assertNull(result.getStartTimeDiff());
finder = new StartTimeFinder(raceLogResolver, raceLogC);
result = finder.analyze();
assertEquals(20000, result.getStartTime().asMillis());
assertEquals(5000, result.getStartTimeDiff().asMillis());
} }
@Test @Test
public void testDependentStartTimeCycle() { public void testDependentStartTimeCycle() {
final MillisecondsDurationImpl cAfterB = new MillisecondsDurationImpl(6000);
raceLogC.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12, raceLogC.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12,
new SimpleRaceLogIdentifierImpl("B", "", ""), new MillisecondsDurationImpl(5000))); new SimpleRaceLogIdentifierImpl("B", "", ""), cAfterB));
raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12,
new SimpleRaceLogIdentifierImpl("A", "", ""), new MillisecondsDurationImpl(5000)));
raceLogA.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12,
new SimpleRaceLogIdentifierImpl("C", "", ""), new MillisecondsDurationImpl(5000)));
final MillisecondsDurationImpl bAfterA = new MillisecondsDurationImpl(7000);
//Check that all resolve to null in case of a cycle raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12,
StartTimeFinder finder = new StartTimeFinder(raceLogResolver, raceLogC); new SimpleRaceLogIdentifierImpl("A", "", ""), bAfterA));
assertNull(finder.analyze().getStartTime());
final MillisecondsDurationImpl aAfterC = new MillisecondsDurationImpl(8000);
finder = new StartTimeFinder(raceLogResolver, raceLogB); raceLogA.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12,
assertNull(finder.analyze().getStartTime()); new SimpleRaceLogIdentifierImpl("C", "", ""), aAfterC));
finder = new StartTimeFinder(raceLogResolver, raceLogA); // Check that all resolve to null in case of a cycle
assertNull(finder.analyze().getStartTime()); StartTimeFinder finder = new StartTimeFinder(raceLogResolver, raceLogC);
assertNull(finder.analyze().getStartTime());
//Check that all resolve correctly after changing some element in cycle assertEquals(cAfterB, finder.analyze().getStartTimeDiff());
MillisecondsTimePoint now = MillisecondsTimePoint.now();
raceLogB.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, finder = new StartTimeFinder(raceLogResolver, raceLogB);
new MillisecondsTimePoint(5000))); assertNull(finder.analyze().getStartTime());
assertEquals(bAfterA, finder.analyze().getStartTimeDiff());
//now A -> C -> B
finder = new StartTimeFinder(raceLogResolver, raceLogA); finder = new StartTimeFinder(raceLogResolver, raceLogA);
//Tests for correct behaviour, when race depending on has a DependentStartTimeEvent and its parent start time is unknown assertNull(finder.analyze().getStartTime());
List<SimpleRaceLogIdentifier> expectedDependingOnRaces = new ArrayList<SimpleRaceLogIdentifier>(); assertEquals(aAfterC, finder.analyze().getStartTimeDiff());
expectedDependingOnRaces = new ArrayList<SimpleRaceLogIdentifier>();
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("C", "", "")); // Check that all resolve correctly after changing some element in cycle
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("B", "", "")); MillisecondsTimePoint now = MillisecondsTimePoint.now();
raceLogB.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(5000)));
StartTimeFinderResult result = finder.analyze();
assertEquals(15000, result.getStartTime().asMillis()); // now A -> C -> B
assertEquals(expectedDependingOnRaces, result.getRacesDependingOn()); finder = new StartTimeFinder(raceLogResolver, raceLogA);
// Tests for correct behaviour, when race depending on has a DependentStartTimeEvent and its parent start time
//now C -> B // is unknown
finder = new StartTimeFinder(raceLogResolver, raceLogC); List<SimpleRaceLogIdentifier> expectedDependingOnRaces;
//Tests for correct behaviour, when race depending on has a DependentStartTimeEvent and its parent start time is unknown expectedDependingOnRaces = new ArrayList<>();
expectedDependingOnRaces = new ArrayList<SimpleRaceLogIdentifier>(); expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("C", "", ""));
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("B", "", "")); expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("B", "", ""));
result = finder.analyze(); StartTimeFinderResult result = finder.analyze();
assertEquals(10000, result.getStartTime().asMillis()); assertEquals(19000, result.getStartTime().asMillis());
assertEquals(expectedDependingOnRaces, result.getRacesDependingOn()); assertEquals(8000, result.getStartTimeDiff().asMillis());
assertEquals(expectedDependingOnRaces, result.getRacesDependingOn());
//now B
finder = new StartTimeFinder(raceLogResolver, raceLogB); // now C -> B
//Tests for correct behaviour, when race depending on has a DependentStartTimeEvent and its parent start time is unknown finder = new StartTimeFinder(raceLogResolver, raceLogC);
expectedDependingOnRaces = new ArrayList<SimpleRaceLogIdentifier>(); // Tests for correct behaviour, when race depending on has a DependentStartTimeEvent and its parent start time
// is unknown
result = finder.analyze(); expectedDependingOnRaces = new ArrayList<>();
assertEquals(5000, result.getStartTime().asMillis()); expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("B", "", ""));
assertEquals(expectedDependingOnRaces, result.getRacesDependingOn());
result = finder.analyze();
assertEquals(11000, result.getStartTime().asMillis());
assertEquals(6000, result.getStartTimeDiff().asMillis());
assertEquals(expectedDependingOnRaces, result.getRacesDependingOn());
// now B
finder = new StartTimeFinder(raceLogResolver, raceLogB);
// Tests for correct behaviour, when race depending on has a DependentStartTimeEvent and its parent start time
// is unknown
expectedDependingOnRaces = new ArrayList<>();
result = finder.analyze();
assertEquals(5000, result.getStartTime().asMillis());
assertNull(result.getStartTimeDiff());
assertEquals(expectedDependingOnRaces, result.getRacesDependingOn());
} }
} }
@@ -13,13 +13,12 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult;
import com.sap.sse.common.TimePoint; import com.sap.sse.common.TimePoint;
public class StartTimeFinderTest extends public class StartTimeFinderTest extends PassAwareRaceLogAnalyzerTest<StartTimeFinder, StartTimeFinderResult> {
PassAwareRaceLogAnalyzerTest<StartTimeFinder, StartTimeFinderResult> {
@Override @Override
protected StartTimeFinder createAnalyzer(RaceLog raceLog) { protected StartTimeFinder createAnalyzer(RaceLog raceLog) {
@@ -30,7 +29,7 @@ public class StartTimeFinderTest extends
protected TargetPair getTargetEventsAndResultForPassAwareTests(int passId, AbstractLogEventAuthor author) { protected TargetPair getTargetEventsAndResultForPassAwareTests(int passId, AbstractLogEventAuthor author) {
RaceLogStartTimeEvent event = createEvent(RaceLogStartTimeEvent.class, 1, passId, author); RaceLogStartTimeEvent event = createEvent(RaceLogStartTimeEvent.class, 1, passId, author);
when(event.getStartTime()).thenReturn(mock(TimePoint.class)); when(event.getStartTime()).thenReturn(mock(TimePoint.class));
return new TargetPair(Arrays.asList(event), new StartTimeFinderResult(event.getStartTime())); return new TargetPair(Arrays.asList(event), new StartTimeFinderResult(event.getStartTime(), null));
} }
@Test @Test
@@ -1,8 +1,10 @@
package com.sap.sailing.domain.abstractlog.race; package com.sap.sailing.domain.abstractlog.race;
import java.io.Serializable;
import com.sap.sse.common.Util.Triple; import com.sap.sse.common.Util.Triple;
public interface SimpleRaceLogIdentifier { public interface SimpleRaceLogIdentifier extends Serializable {
String getRegattaLikeParentName(); String getRegattaLikeParentName();
String getRaceColumnName(); String getRaceColumnName();
@@ -1,6 +1,7 @@
package com.sap.sailing.domain.abstractlog.race.analyzing.impl; package com.sap.sailing.domain.abstractlog.race.analyzing.impl;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@@ -16,33 +17,37 @@ public class DependentStartTimeResolver {
public DependentStartTimeResolver(RaceLogResolver raceLogResolver) { public DependentStartTimeResolver(RaceLogResolver raceLogResolver) {
this.raceLogResolver = raceLogResolver; this.raceLogResolver = raceLogResolver;
} }
public StartTimeFinderResult resolve(RaceLogDependentStartTimeEvent event) { public StartTimeFinderResult resolve(RaceLogDependentStartTimeEvent event) {
List<SimpleRaceLogIdentifier> dependingOnRaces = new ArrayList<SimpleRaceLogIdentifier>(); List<SimpleRaceLogIdentifier> dependingOnRaces = Collections.emptyList();
return internalResolve(event, dependingOnRaces); return internalResolve(event, dependingOnRaces);
} }
StartTimeFinderResult internalResolve(RaceLogDependentStartTimeEvent event, Iterable<SimpleRaceLogIdentifier> dependingOnRaces) { StartTimeFinderResult internalResolve(RaceLogDependentStartTimeEvent event,Iterable<SimpleRaceLogIdentifier> dependingOnRaces) {
SimpleRaceLogIdentifier identifier = event.getDependentOnRaceIdentifier(); SimpleRaceLogIdentifier identifier = event.getDependentOnRaceIdentifier();
Duration startTimeDifference = event.getStartTimeDifference(); Duration startTimeDifference = event.getStartTimeDifference();
RaceLog raceLog = raceLogResolver.resolve(identifier); RaceLog raceLog = raceLogResolver.resolve(identifier);
List<SimpleRaceLogIdentifier> extendedDependingOnRaces = new ArrayList<>();
Util.addAll(dependingOnRaces, extendedDependingOnRaces);
extendedDependingOnRaces.add(identifier);
final StartTimeFinderResult result; final StartTimeFinderResult result;
if (containsCycle(extendedDependingOnRaces)) { if (raceLog == null) {
result = new StartTimeFinderResult(extendedDependingOnRaces, null); result = new StartTimeFinderResult(dependingOnRaces, null, startTimeDifference);
} else { } else {
StartTimeFinder dependentStartTimeFinder = new StartTimeFinder(raceLogResolver, raceLog); List<SimpleRaceLogIdentifier> extendedDependingOnRaces = new ArrayList<>();
StartTimeFinderResult resultOfDependentRace = dependentStartTimeFinder.analyze(extendedDependingOnRaces); Util.addAll(dependingOnRaces, extendedDependingOnRaces);
if (resultOfDependentRace.getStartTime() == null) { extendedDependingOnRaces.add(identifier);
result = resultOfDependentRace; if (containsCycle(extendedDependingOnRaces)) {
result = new StartTimeFinderResult(extendedDependingOnRaces, null, null);
} else { } else {
result = new StartTimeFinderResult(resultOfDependentRace.getRacesDependingOn(), StartTimeFinder dependentStartTimeFinder = new StartTimeFinder(raceLogResolver, raceLog);
resultOfDependentRace.getStartTime() == null ? null : resultOfDependentRace.getStartTime() StartTimeFinderResult resultOfDependentRace = dependentStartTimeFinder.analyze(extendedDependingOnRaces);
.plus(startTimeDifference)); if (resultOfDependentRace.getStartTime() == null) {
resultOfDependentRace.setStartTimeDiff(startTimeDifference);
result = resultOfDependentRace;
} else {
result = new StartTimeFinderResult(resultOfDependentRace.getRacesDependingOn(),
resultOfDependentRace.getStartTime().plus(startTimeDifference), startTimeDifference);
}
} }
} }
return result; return result;
@@ -44,15 +44,14 @@ public class RaceStatusAnalyzer extends RaceLogAnalyzer<RaceLogRaceStatus> {
@Override @Override
protected RaceLogRaceStatus performAnalysis() { protected RaceLogRaceStatus performAnalysis() {
ArrayListNavigableSet<RaceLogRaceStatusEvent> statusEvents = new ArrayListNavigableSet<RaceLogRaceStatusEvent>(RaceLogRaceStatusEventComparator.INSTANCE); ArrayListNavigableSet<RaceLogRaceStatusEvent> statusEvents = new ArrayListNavigableSet<>(RaceLogRaceStatusEventComparator.INSTANCE);
for(RaceLogEvent event: getPassEvents()) { for(RaceLogEvent event: getPassEvents()) {
if(event instanceof RaceLogRaceStatusEvent) { if(event instanceof RaceLogRaceStatusEvent) {
statusEvents.add((RaceLogRaceStatusEvent) event); statusEvents.add((RaceLogRaceStatusEvent) event);
} }
} }
for (RaceLogRaceStatusEvent event : statusEvents.descendingSet()) { for (RaceLogRaceStatusEvent event : statusEvents.descendingSet()) {
RaceLogRaceStatusEvent statusEvent = (RaceLogRaceStatusEvent) event; event.accept(eventDispatcher);
statusEvent.accept(eventDispatcher);
return eventDispatcher.nextStatus; return eventDispatcher.nextStatus;
} }
@@ -79,7 +78,7 @@ public class RaceStatusAnalyzer extends RaceLogAnalyzer<RaceLogRaceStatus> {
private void setRaceLogStatusBasedOnStartTime(TimePoint startTime) { private void setRaceLogStatusBasedOnStartTime(TimePoint startTime) {
if (startTime == null) { if (startTime == null) {
nextStatus = RaceLogRaceStatus.UNKNOWN; nextStatus = RaceLogRaceStatus.PRESCHEDULED;
return; return;
} }
TimePoint now = clock.now(); TimePoint now = clock.now();
@@ -29,13 +29,13 @@ public class StartTimeFinder extends RaceLogAnalyzer<StartTimeFinderResult> {
for (RaceLogEvent event : getPassEventsDescending()) { for (RaceLogEvent event : getPassEventsDescending()) {
if (event instanceof RaceLogStartTimeEvent) { if (event instanceof RaceLogStartTimeEvent) {
TimePoint startTime = ((RaceLogStartTimeEvent) event).getStartTime(); TimePoint startTime = ((RaceLogStartTimeEvent) event).getStartTime();
return new StartTimeFinderResult(dependingOnRaces, startTime); return new StartTimeFinderResult(dependingOnRaces, startTime, null);
} else if (event instanceof RaceLogDependentStartTimeEvent) { } else if (event instanceof RaceLogDependentStartTimeEvent) {
DependentStartTimeResolver dependentStartTimeResolver = new DependentStartTimeResolver(resolver); DependentStartTimeResolver dependentStartTimeResolver = new DependentStartTimeResolver(resolver);
return dependentStartTimeResolver.internalResolve((RaceLogDependentStartTimeEvent) event, dependingOnRaces); return dependentStartTimeResolver.internalResolve((RaceLogDependentStartTimeEvent) event, dependingOnRaces);
} }
} }
return new StartTimeFinderResult(dependingOnRaces, null); return new StartTimeFinderResult(dependingOnRaces, null, null);
} finally { } finally {
log.unlockAfterRead(); log.unlockAfterRead();
} }
@@ -1,29 +1,25 @@
package com.sap.sailing.domain.abstractlog.race.analyzing.impl; package com.sap.sailing.domain.abstractlog.race.analyzing.impl;
import java.util.ArrayList; import java.util.Collections;
import java.util.List;
import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint; import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util; import com.sap.sse.common.Util;
public class StartTimeFinderResult { public class StartTimeFinderResult {
private final Iterable<SimpleRaceLogIdentifier> racesDependingOn; private final Iterable<SimpleRaceLogIdentifier> racesDependingOn;
private final TimePoint startTime; private final TimePoint startTime;
private Duration startTimeDiff;
public StartTimeFinderResult(final Iterable<SimpleRaceLogIdentifier> racesDependingOn, final TimePoint startTime) { public StartTimeFinderResult(Iterable<SimpleRaceLogIdentifier> racesDependingOn, TimePoint startTime, Duration startTimeDiff) {
this.racesDependingOn = racesDependingOn;
this.startTime = startTime; this.startTime = startTime;
this.startTimeDiff = startTimeDiff;
this.racesDependingOn = racesDependingOn;
} }
public StartTimeFinderResult(TimePoint startTime) { public StartTimeFinderResult(TimePoint startTime, Duration startTimeDiff) {
racesDependingOn = new ArrayList<SimpleRaceLogIdentifier>(); this(/* racesDependingOn */ Collections.<SimpleRaceLogIdentifier>emptyList(), startTime, startTimeDiff);
this.startTime = startTime;
}
public StartTimeFinderResult(List<SimpleRaceLogIdentifier> racesDependingOn, TimePoint startTime) {
this.racesDependingOn = racesDependingOn;
this.startTime = startTime;
} }
public Iterable<SimpleRaceLogIdentifier> getRacesDependingOn() { public Iterable<SimpleRaceLogIdentifier> getRacesDependingOn() {
@@ -34,11 +30,16 @@ public class StartTimeFinderResult {
return startTime; return startTime;
} }
public Duration getStartTimeDiff() {
return startTimeDiff;
}
public void setStartTimeDiff(Duration startTimeDiff) {
this.startTimeDiff = startTimeDiff;
}
public boolean isDependentStartTime() { public boolean isDependentStartTime() {
if (racesDependingOn == null) { return racesDependingOn != null && !Util.isEmpty(racesDependingOn);
return false;
}
return Util.isEmpty(racesDependingOn);
} }
@Override @Override
@@ -47,6 +48,7 @@ public class StartTimeFinderResult {
int result = 1; int result = 1;
result = prime * result + ((racesDependingOn == null) ? 0 : racesDependingOn.hashCode()); result = prime * result + ((racesDependingOn == null) ? 0 : racesDependingOn.hashCode());
result = prime * result + ((startTime == null) ? 0 : startTime.hashCode()); result = prime * result + ((startTime == null) ? 0 : startTime.hashCode());
result = prime * result + ((startTimeDiff == null) ? 0 : startTimeDiff.hashCode());
return result; return result;
} }
@@ -69,6 +71,11 @@ public class StartTimeFinderResult {
return false; return false;
} else if (!startTime.equals(other.startTime)) } else if (!startTime.equals(other.startTime))
return false; return false;
if (startTimeDiff == null) {
if (other.startTimeDiff != null)
return false;
} else if (!startTimeDiff.equals(other.startTimeDiff))
return false;
return true; return true;
} }
} }
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.abstractlog.race.impl;
import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
public class SimpleRaceLogIdentifierImpl implements SimpleRaceLogIdentifier { public class SimpleRaceLogIdentifierImpl implements SimpleRaceLogIdentifier {
private static final long serialVersionUID = 5377117723950808853L;
protected final String regattaLikeParentName; protected final String regattaLikeParentName;
protected final String raceColumnName; protected final String raceColumnName;
protected final String fleetName; protected final String fleetName;
@@ -187,4 +187,9 @@ public interface RaceState extends ReadonlyRaceState {
void setAdditionalScoringInformationEnabled(TimePoint creationTimePoint, boolean enable, AdditionalScoringInformationType informationType); void setAdditionalScoringInformationEnabled(TimePoint creationTimePoint, boolean enable, AdditionalScoringInformationType informationType);
boolean isAdditionalScoringInformationEnabled(AdditionalScoringInformationType informationType); boolean isAdditionalScoringInformationEnabled(AdditionalScoringInformationType informationType);
/**
* forces a RaceStateUpdate
*/
void forceUpdate();
} }
@@ -1,5 +1,6 @@
package com.sap.sailing.domain.abstractlog.race.state.impl; package com.sap.sailing.domain.abstractlog.race.state.impl;
import java.util.Collections;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -17,6 +18,7 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceStatusAnalyzer
import com.sap.sailing.domain.abstractlog.race.scoring.AdditionalScoringInformationType; import com.sap.sailing.domain.abstractlog.race.scoring.AdditionalScoringInformationType;
import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent;
import com.sap.sailing.domain.abstractlog.race.state.RaceState; import com.sap.sailing.domain.abstractlog.race.state.RaceState;
import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProcedure; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProcedure;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProcedureFactory; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProcedureFactory;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProcedurePrerequisite; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProcedurePrerequisite;
@@ -42,6 +44,10 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState {
private final AbstractLogEventAuthor author; private final AbstractLogEventAuthor author;
private final RaceLogEventFactory factory; private final RaceLogEventFactory factory;
public static ReadonlyRaceState create(RaceLogResolver raceLogResolver, RaceLog raceLog) {
return create(raceLogResolver, raceLog, /* forRaceLogIdentifier */ null, Collections.<SimpleRaceLogIdentifier, ReadonlyRaceState>emptyMap());
}
/** /**
* Creates a {@link RaceState} with the initial racing procedure type set to a fallback value and an empty configuration. * Creates a {@link RaceState} with the initial racing procedure type set to a fallback value and an empty configuration.
*/ */
@@ -63,9 +69,11 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState {
this(raceLogResolver, raceLog, author, eventFactory, new RaceStatusAnalyzer.StandardClock(), procedureFactory); this(raceLogResolver, raceLog, author, eventFactory, new RaceStatusAnalyzer.StandardClock(), procedureFactory);
} }
private RaceStateImpl(RaceLogResolver raceLogResolver, RaceLog raceLog, AbstractLogEventAuthor author, RaceLogEventFactory eventFactory, RaceStatusAnalyzer.Clock analyzersClock, private RaceStateImpl(RaceLogResolver raceLogResolver, RaceLog raceLog, AbstractLogEventAuthor author,
RaceLogEventFactory eventFactory, RaceStatusAnalyzer.Clock analyzersClock,
RacingProcedureFactory procedureFactory) { RacingProcedureFactory procedureFactory) {
super(raceLogResolver, raceLog, analyzersClock, procedureFactory, /* update */ true); super(raceLogResolver, raceLog, /* forRaceLogIdentifier */ null, analyzersClock, procedureFactory,
Collections.<SimpleRaceLogIdentifier, ReadonlyRaceState>emptyMap(), /* update */ true);
this.author = author; this.author = author;
this.factory = eventFactory; this.factory = eventFactory;
} }
@@ -221,4 +229,10 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState {
return event != null; return event != null;
} }
@Override
public void forceUpdate() {
super.update();
registerListenerOnDependentRaceIfDependentStartTime(Collections.<SimpleRaceLogIdentifier, ReadonlyRaceState>emptyMap());
}
} }
@@ -1,11 +1,16 @@
package com.sap.sailing.domain.abstractlog.race.state.impl; package com.sap.sailing.domain.abstractlog.race.state.impl;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import com.sap.sailing.domain.abstractlog.race.CompetitorResults; import com.sap.sailing.domain.abstractlog.race.CompetitorResults;
import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.RaceLogChangedListener; import com.sap.sailing.domain.abstractlog.race.RaceLogChangedListener;
import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent;
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent;
import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.ConfirmedFinishPositioningListFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.ConfirmedFinishPositioningListFinder;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishPositioningListFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishPositioningListFinder;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishedTimeFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishedTimeFinder;
@@ -15,10 +20,10 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastWindFixFinder;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.ProtestStartTimeFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.ProtestStartTimeFinder;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceStatusAnalyzer; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceStatusAnalyzer;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceStatusAnalyzer.Clock; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceStatusAnalyzer.Clock;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RacingProcedureTypeAnalyzer; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RacingProcedureTypeAnalyzer;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult;
import com.sap.sailing.domain.abstractlog.race.impl.WeakRaceLogChangedVisitor; import com.sap.sailing.domain.abstractlog.race.impl.WeakRaceLogChangedVisitor;
import com.sap.sailing.domain.abstractlog.race.state.RaceStateChangedListener; import com.sap.sailing.domain.abstractlog.race.state.RaceStateChangedListener;
import com.sap.sailing.domain.abstractlog.race.state.RaceStateEvent; import com.sap.sailing.domain.abstractlog.race.state.RaceStateEvent;
@@ -49,21 +54,41 @@ import com.sap.sse.common.Util;
*/ */
public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedListener { public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedListener {
public static ReadonlyRaceState create(RaceLogResolver raceLogResolver, RaceLog raceLog) {
return create(raceLogResolver, raceLog, /* forRaceLogIdentifier */null,
Collections.<SimpleRaceLogIdentifier, ReadonlyRaceState> emptyMap());
}
/** /**
* Creates a {@link ReadonlyRaceState}. * Creates a {@link ReadonlyRaceState}.
*
* @param forRaceLogIdentifier
* If known, callers can specify the simple race log identifier for the race log to be wrapped by this
* new race state. This can help avoid endless recursions because this race state can be passed along
* together with the identifier so that when again along a dependent call chain a race state is required
* for that race log identifier, this one can be used.
*/ */
public static ReadonlyRaceState create(RaceLogResolver raceLogResolver, RaceLog raceLog, public static ReadonlyRaceState create(RaceLogResolver raceLogResolver, RaceLog raceLog,
ConfigurationLoader<RegattaConfiguration> configurationLoader) { SimpleRaceLogIdentifier forRaceLogIdentifier,
return new ReadonlyRaceStateImpl(raceLogResolver, raceLog, new ReadonlyRacingProcedureFactory( ConfigurationLoader<RegattaConfiguration> configurationLoader,
configurationLoader)); Map<SimpleRaceLogIdentifier, ReadonlyRaceState> dependentRaceStates) {
return new ReadonlyRaceStateImpl(raceLogResolver, raceLog, forRaceLogIdentifier, new ReadonlyRacingProcedureFactory(
configurationLoader), dependentRaceStates);
} }
/** /**
* Creates a {@link ReadonlyRaceState} with an empty configuration ( {@link EmptyRegattaConfiguration} ). * Creates a {@link ReadonlyRaceState} with an empty configuration ( {@link EmptyRegattaConfiguration} ).
*
* @param forRaceLogIdentifier
* If known, callers can specify the simple race log identifier for the race log to be wrapped by this
* new race state. This can help avoid endless recursions because this race state can be passed along
* together with the identifier so that when again along a dependent call chain a race state is required
* for that race log identifier, this one can be used.
*/ */
public static ReadonlyRaceState create(RaceLogResolver raceLogResolver, RaceLog raceLog) { public static ReadonlyRaceState create(RaceLogResolver raceLogResolver, RaceLog raceLog,
return new ReadonlyRaceStateImpl(raceLogResolver, raceLog, new ReadonlyRacingProcedureFactory( SimpleRaceLogIdentifier forRaceLogIdentifier, Map<SimpleRaceLogIdentifier, ReadonlyRaceState> dependentRaceStates) {
new EmptyRegattaConfiguration())); return new ReadonlyRaceStateImpl(raceLogResolver, raceLog, forRaceLogIdentifier, new ReadonlyRacingProcedureFactory(
new EmptyRegattaConfiguration()), dependentRaceStates);
} }
/** /**
@@ -127,18 +152,26 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
private RaceStateChangedListener raceStateToObserveListener; private RaceStateChangedListener raceStateToObserveListener;
private ReadonlyRaceStateImpl(RaceLogResolver raceLogResolver, RaceLog raceLog, private ReadonlyRaceStateImpl(RaceLogResolver raceLogResolver, RaceLog raceLog,
RacingProcedureFactory procedureFactory) { SimpleRaceLogIdentifier forRaceLogIdentifier, RacingProcedureFactory procedureFactory,
this(raceLogResolver, raceLog, new RaceStatusAnalyzer.StandardClock(), procedureFactory, /* update */true); Map<SimpleRaceLogIdentifier, ReadonlyRaceState> dependentRaceStates) {
this(raceLogResolver, raceLog, forRaceLogIdentifier, new RaceStatusAnalyzer.StandardClock(),
procedureFactory, dependentRaceStates, /* update */true);
} }
/** /**
* @param raceLogResolver * @param forRaceLogIdentifier
* If known, callers can specify the simple race log identifier for the race log to be wrapped by this
* new race state. This can help avoid endless recursions because this race state can be passed along
* together with the identifier so that when again along a dependent call chain a race state is required
* for that race log identifier, this one can be used.
* @param update * @param update
* if <code>true</code>, the race state will be updated whenever the underlying <code>raceLog</code> * if <code>true</code>, the race state will be updated whenever the underlying <code>raceLog</code>
* changes. * changes.
*/ */
protected ReadonlyRaceStateImpl(RaceLogResolver raceLogResolver, RaceLog raceLog, Clock analyzersClock, protected ReadonlyRaceStateImpl(RaceLogResolver raceLogResolver, RaceLog raceLog,
RacingProcedureFactory procedureFactory, boolean update) { SimpleRaceLogIdentifier forRaceLogIdentifier, Clock analyzersClock,
RacingProcedureFactory procedureFactory,
Map<SimpleRaceLogIdentifier, ReadonlyRaceState> dependentRaceStates, boolean update) {
this.raceLog = raceLog; this.raceLog = raceLog;
this.raceLogResolver = raceLogResolver; this.raceLogResolver = raceLogResolver;
this.procedureFactory = procedureFactory; this.procedureFactory = procedureFactory;
@@ -178,8 +211,18 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
// We known that recreateRacingProcedure calls update() when done, therefore this RaceState // We known that recreateRacingProcedure calls update() when done, therefore this RaceState
// will be fully initialized after this line // will be fully initialized after this line
recreateRacingProcedure(); recreateRacingProcedure();
final Map<SimpleRaceLogIdentifier, ReadonlyRaceState> dependentRaceStatesAndMe;
if (forRaceLogIdentifier != null) {
dependentRaceStatesAndMe = new HashMap<>(dependentRaceStates);
dependentRaceStatesAndMe.put(forRaceLogIdentifier, this);
} else {
dependentRaceStatesAndMe = dependentRaceStates;
}
registerListenerOnDependentRaceIfDependentStartTime(dependentRaceStatesAndMe);
}
// Check wether the latest known StartTimeEvent is a non-dependent or dependent start time in case of a protected void registerListenerOnDependentRaceIfDependentStartTime(Map<SimpleRaceLogIdentifier, ReadonlyRaceState> dependentRaceStates) {
// Check whether the latest known StartTimeEvent is a non-dependent or dependent start time in case of a
// dependent startTime setup listeners // dependent startTime setup listeners
this.raceLog.lockForRead(); this.raceLog.lockForRead();
try { try {
@@ -187,7 +230,7 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
if (event instanceof RaceLogStartTimeEvent) { if (event instanceof RaceLogStartTimeEvent) {
break; break;
} else if (event instanceof RaceLogDependentStartTimeEvent) { } else if (event instanceof RaceLogDependentStartTimeEvent) {
setupListenersOnDependentRace(event); setupListenersOnDependentRace(event, dependentRaceStates);
break; break;
} }
} }
@@ -319,7 +362,7 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
@Override @Override
public void eventAdded(RaceLogEvent event) { public void eventAdded(RaceLogEvent event) {
if (event instanceof RaceLogDependentStartTimeEvent) { if (event instanceof RaceLogDependentStartTimeEvent) {
setupListenersOnDependentRace(event); setupListenersOnDependentRace(event, Collections.<SimpleRaceLogIdentifier, ReadonlyRaceState>emptyMap());
} else if (event instanceof RaceLogStartTimeEvent) { } else if (event instanceof RaceLogStartTimeEvent) {
if (raceStateToObserve != null) { if (raceStateToObserve != null) {
raceStateToObserve.removeChangedListener(raceStateToObserveListener); raceStateToObserve.removeChangedListener(raceStateToObserveListener);
@@ -329,15 +372,25 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
update(); update();
} }
private void setupListenersOnDependentRace(RaceLogEvent event) { private void setupListenersOnDependentRace(RaceLogEvent event, Map<SimpleRaceLogIdentifier, ReadonlyRaceState> dependentRaceStates) {
if (raceStateToObserve != null) { if (raceStateToObserve != null) {
// Remove previous listeners // Remove previous listeners
raceStateToObserve.removeChangedListener(raceStateToObserveListener); raceStateToObserve.removeChangedListener(raceStateToObserveListener);
raceStateToObserve = null;
} }
RaceLogDependentStartTimeEvent dependentStartTimeEvent = (RaceLogDependentStartTimeEvent) event; RaceLogDependentStartTimeEvent dependentStartTimeEvent = (RaceLogDependentStartTimeEvent) event;
RaceLog resolvedRaceLog = raceLogResolver.resolve(dependentStartTimeEvent.getDependentOnRaceIdentifier()); final SimpleRaceLogIdentifier dependentOnRaceIdentifier = dependentStartTimeEvent.getDependentOnRaceIdentifier();
raceStateToObserve = ReadonlyRaceStateImpl.create(raceLogResolver, resolvedRaceLog); if (dependentRaceStates.containsKey(dependentOnRaceIdentifier)) {
raceStateToObserve.addChangedListener(raceStateToObserveListener); raceStateToObserve = dependentRaceStates.get(dependentOnRaceIdentifier);
raceStateToObserve.addChangedListener(raceStateToObserveListener);
} else {
RaceLog resolvedRaceLog = raceLogResolver.resolve(dependentOnRaceIdentifier);
if (resolvedRaceLog != null) {
raceStateToObserve = ReadonlyRaceStateImpl.create(raceLogResolver, resolvedRaceLog,
dependentOnRaceIdentifier, dependentRaceStates);
raceStateToObserve.addChangedListener(raceStateToObserveListener);
}
}
} }
@Override @Override
@@ -350,7 +403,7 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
return false; return false;
} }
private void update() { protected void update() {
RacingProcedureType type = racingProcedureAnalyzer.analyze(); RacingProcedureType type = racingProcedureAnalyzer.analyze();
if (!Util.equalsWithNull(cachedRacingProcedureType, type) && type != RacingProcedureType.UNKNOWN) { if (!Util.equalsWithNull(cachedRacingProcedureType, type) && type != RacingProcedureType.UNKNOWN) {
cachedRacingProcedureType = type; cachedRacingProcedureType = type;
@@ -139,7 +139,6 @@ import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Timed; import com.sap.sse.common.Timed;
import com.sap.sse.common.Util; import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair; import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.impl.MillisecondsDurationImpl;
import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.concurrent.LockUtil; import com.sap.sse.concurrent.LockUtil;
import com.sap.sse.concurrent.NamedReentrantReadWriteLock; import com.sap.sse.concurrent.NamedReentrantReadWriteLock;
@@ -3669,7 +3668,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
if (polarDataService == null) { if (polarDataService == null) {
throw new NotEnoughDataHasBeenAddedException("Target time estimation failed. No polar service available."); throw new NotEnoughDataHasBeenAddedException("Target time estimation failed. No polar service available.");
} }
Duration durationOfAllLegs = new MillisecondsDurationImpl(0); Duration durationOfAllLegs = Duration.NULL;
for (TrackedLeg leg : trackedLegs.values()) { for (TrackedLeg leg : trackedLegs.values()) {
Duration durationOfLeg = leg.getEstimatedTimeToComplete(polarDataService, timepoint); Duration durationOfLeg = leg.getEstimatedTimeToComplete(polarDataService, timepoint);
durationOfAllLegs = durationOfAllLegs.plus(durationOfLeg); durationOfAllLegs = durationOfAllLegs.plus(durationOfLeg);
@@ -11,6 +11,6 @@
</listAttribute> </listAttribute>
<stringAttribute key="projectName" value="com.sap.sailing.gwt.ui"/> <stringAttribute key="projectName" value="com.sap.sailing.gwt.ui"/>
<booleanAttribute key="showLaunchOutput" value="false"/> <booleanAttribute key="showLaunchOutput" value="false"/>
<stringAttribute key="url" value="http://127.0.0.1:8888/gwt/Home.html"/> <stringAttribute key="url" value="http://127.0.0.1:8888/gwt/AdminConsole.html"/>
<stringAttribute key="urlQueryParams" value=""/> <stringAttribute key="urlQueryParams" value=""/>
</launchConfiguration> </launchConfiguration>
@@ -0,0 +1,695 @@
/** Add css rules here for your application. */
/*
body #calendar:after
content: " ";
display: block;
height: 0;
clear: both;
visibility: hidden;
*/
* {
font-family: 'Open Sans', sans-serif;
font-size: 12px;
}
iframe {
display: block;
width: 100%;
height: 100%;
border: none;
overflow-y: auto;
overflow-x: hidden;
}
.clear {
clear: both;
font-size: 1px;
height: 0px;
line-height: 0px;
margin: -1px 0 0;
width: 100%;
}
.cover {
left: -1000px;
overflow: hidden;
position: absolute;
top: -1000px;
}
body {
background: white;
font-family: 'Open Sans', Arial, Verdana, sans-serif;
line-height: 1;
font-size: 14px;
font-weight: 400;
margin: 0;
}
table td, select, button {
font-family: 'Open Sans', Arial, Verdana, sans-serif;
line-height: 1;
font-size: 14px;
}
.contentOuterPanel {
background: #dddcdc;
margin: 0 12px 0 12px;
padding: 12px;
}
/** Example rules used by the template application (remove for your app) */
h1 {
font-size: 2em;
font-family: 'Open Sans', Arial, Verdana, sans-serif;
font-weight: 700;
color: #777777;
margin: 40px 0px 70px;
text-align: center;
}
table {
border-collapse: separate;
}
.CombinedWindPanelParentDiv {
padding-top: 34px;
padding-left: 10px;
}
.TrueNorthIndicatorPanelParentDiv {
padding-top: 10px;
padding-left: 10px;
}
.MapSimulationLegendParentDiv {
padding-bottom: 10px;
padding-right: 10px;
pointer-events: none;
}
.MapSimulationLegend {
pointer-events: all;
}
.RaceMap-HeaderPanel {
height: 60px;
width: 100%;
background-color: #333;
opacity: .5;
}
.leaderboardLabel {
border-bottom: 2px solid #007dc0;
padding: 0 0 6px 0;
font-weight: 700;
}
.refreshAndSettings {
background: #f2f2f2;
border-bottom: 2px solid #fff;
border-top: 2px solid #fff;
height: 30px;
}
.refreshAndSettings table td {
padding: 0 10px 0 0;
}
.refreshAndSettings table table td {
padding: 0 0 0 0;
}
.race-name {
line-height: 1.0;
}
.openColumn {
position: relative;
vertical-align: middle;
}
img.openColumn {
display: block;
margin: 3px auto 3px auto !important;
}
.breadcrumbPanel {
height: 30px;
margin: 0 12px 13px 12px;
}
.mainPanel {
width: 100%;
}
.raceBoardNavigation {
float: left;
margin: 9px 0 0 12px;
font-family: 'Open Sans', Arial, Verdana, sans-serif;
font-weight: 300;
}
.raceBoardControls {
float: right;
margin: 9px 0 0 12px;
font-family: 'Open Sans', Arial, Verdana, sans-serif;
font-weight: 300;
}
.raceBoardNavigation-navigationitem {
color: #dddcdc;
text-transform: uppercase;
font-weight: 500;
margin: 0 12px 0 0;
padding: 0 0 5px 0;
}
.raceBoardNavigation-navigationitem:hover {
border-bottom: 4px solid #f0ab00;
color: #dddcdc;
text-decoration: none;
}
.raceBoardNavigation-navigationitem:active {
border-bottom: 4px solid #f0ab00;
color: #dddcdc;
text-decoration: none;
}
.competitorInfo-Canvas {
pointer-events: none;
}
.gwt-DialogBox {
z-index: 20;
}
.abstractChartPanel-importantMessageOfChart {
font-family: 'Open Sans', Arial, Verdana, sans-serif;
font-weight: 600;
font-size: 20px;
height: 70px;
margin: 0 auto;
padding: 49px 0 0 80px;
width: 300px;
color: #7c7c7c;
background: url(images/important-message.png) left center no-repeat;
}
.breadcrumbPanel-NextArrow {
display: none;
}
.errorLabel {
color: #FF0000;
}
.raceBoardNavigation-settingsButtonPanel {
float: right;
margin: 9px 12px 0 0;
}
.raceBoardNavigation-settingsButton {
background: url(images/settings_white.png),
url(images/btn-cta-orangeleft.png);
background-position: center, center 0;
background-repeat: no-repeat, repeat-x;
width: 27px;
height: 23px;
margin: 0 12px 0 1px;
-webkit-border-radius: 0px 3px 3px 0px;
-moz-border-radius: 0px 3px 3px 0px;
-o-border-radius: 0px 3px 3px 0px;
-ms-border-radius: 0px 3px 3px 0px;
border-radius: 0px 3px 3px 0px;
}
.raceBoardNavigation-settingsButton:hover {
background-image: url(images/settings_white.png),
url(images/btn-cta-orangeleft.png);
background-position: center, center -30px;
background-repeat: no-repeat, repeat-x;
cursor: pointer;
}
.raceBoardNavigation-filterButton:hover {
background-image: url(images/filter_white.png),
url(images/btn-cta-orangeleft.png);
background-position: center, center -30px;
background-repeat: no-repeat, repeat-x;
cursor: pointer;
}
.raceBoardNavigation-innerElement {
background: url("images/btn-cta-orangeleft.png") repeat-x scroll center
0 transparent;
color: #FFFFFF;
cursor: pointer;
font-family: 'Open Sans', Verdana, Arial, sans-serif;
font-weight: 600;
font-size: 14px;
margin: 0 0 0 0;
padding: 2px 7px 2px 3px;
height: 18px;
display: inline-block;
text-decoration: none;
border-radius: 5px 0 0 5px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25);
border-bottom: 1px solid rgba(0, 0, 0, 0.25);
}
.raceBoardNavigation-innerElement:active {
top: 1px;
position: relative;
}
.raceBoardNavigation-innerElement:hover {
background: url("images/btn-cta-orangeleft.png") repeat-x scroll center
-30px transparent;
cursor: pointer;
}
.raceBoardNavigation-innerElement label {
cursor: pointer;
}
.raceBoardNavigation-standaloneElement {
background: url("images/btn-cta-orangeleft.png") repeat-x scroll center
0 transparent;
color: #FFFFFF;
cursor: pointer;
font-family: 'Open Sans', Verdana, Arial, sans-serif;
font-weight: 600;
font-size: 14px;
margin: 0 0 0 0;
padding: 2px 7px 2px 3px;
height: 23px;
display: inline-block;
text-decoration: none;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25);
border-bottom: 1px solid rgba(0, 0, 0, 0.25);
border-radius: 5px 5px 5px 5px;
}
.raceBoardNavigation-standaloneElement:active {
top: 1px;
position: relative;
}
.raceBoardNavigation-standaloneElement:hover {
background: url("images/btn-cta-orangeleft.png") repeat-x scroll center
-30px transparent;
cursor: pointer;
}
.raceBoardNavigation-standaloneElement label {
cursor: pointer;
}
.timePanelButton {
float: left;
margin: 0 0 0 5px;
}
.timePanelButton-SlowDown {
background-color: red !important;
}
.timePanelButton-SpeedUp {
background-color: green !important;
}
.playPauseButton {
padding: 0;
float: left;
width: 32px;
height: 28px;
background: url(images/viewicons/@1x/img/SAP_RV_Play_INACTIVE.png)
center no-repeat;
cursor: pointer;
border: 1px solid #cecece;
border-radius: 4px;
outline: 0;
}
.playPauseButton:hover {
cursor: pointer;
background-color: #cecece;
}
.playPauseButtonPause {
background: url(images/viewicons/@2x/img/SAP_RV_Pause_INACTIVE.png) 2px
0 no-repeat;
outline: 0;
background-size: contain;
}
.playPauseButtonPause:hover {
cursor: pointer;
}
.backToLivePlayButton {
width: 42px;
height: 38px;
font-size: 8px;
white-space: normal;
border-radius: 4px;
border: none;
margin-right: 23px;
margin-top: 5px;
margin-bottom: 5px;
z-index: 1;
}
.backToLivePlayButton-Inactive {
color: #6dc021;
background-color: white;
font-weight: bold;
}
.backToLivePlayButton-Active {
background-color: #6dc021;
color: white;
font-weight: normal;
}
.backToLivePlayButton:hover {
border: 2px solid gray;
}
.backToLivePlayButton:focus {
outline: 0 !important;
}
.dockLayoutPanel div[style="position: absolute; overflow: hidden; left: 0px; right: 0px; bottom: 0px; height: 90px;"]
{
z-index: 10;
}
.browserOptimizedMessage {
padding: 15px 0px;
}
.trackingQuality-circle {
width: 8px;
height: 8px;
border-radius: 50%;
float: left;
}
.circleYellow {
background: #fbba00;
}
.circleGreen {
background: #8ab54e;
}
.circleRed {
background: #f01010;
}
.busyIndicator-Simple {
position: absolute;
top: 0.7em;
right: 7.4em;
}
.busyIndicator-Circle {
}
.raceBoard-TitlePanel {
position: relative;
top: 10px;
z-index: 10;
color: #fff;
margin-left: auto;
margin-right: auto;
}
.raceBoard-TitlePanel-RaceNameLabel {
font-size: 32px;
font-weight: bold;
padding: 7px;
}
.raceBoard-Logo {
position: absolute;
top: 6px;
left: 10px;
z-index: 10;
cursor: pointer;
}
.SideBySideComponentViewer-MainPanel {
top: 12px;
}
.TimePanel-ShowExtended-Button {
width: 29px;
height: 28px;
float: left;
cursor: pointer;
border-radius: 4px;
border: 1px solid #ececec;
}
.TimePanel-ShowExtended-Button-Open {
background: white url(images/arrows_bottom_black.png) center no-repeat;
}
.TimePanel-ShowExtended-Button-Closed {
background: white url(images/arrows_top_black.png) center no-repeat;
}
.TimePanel-ShowExtended-Button:hover {
background-color: #cecece;
}
.TimePanel-ShowExtended-Button:focus {
outline: 0 !important;
}
.RaceBoard-globalNavigation-Link {
display: inline;
margin-right: 3px;
}
.RaceBoard-globalNavigation-Link a {
color: #fff;
cursor: pointer;
}
.RaceBoard-globalNavigation-Link+.RaceBoard-globalNavigation-Link:before
{
content: ' \00bb\00a0';
}
.TimePanel-settingsButtonStyle {
position: absolute;
right: 0px;
z-index: 1;
border: none;
}
.TimePanel-settingsButtonStyle:focus {
outline: 0 !important;
}
.TimePanel-settingsButtonStyle:hover {
border: 1px solid gray;
}
.gwt-SplitLayoutPanel-NorthSouthToggleButton-Closed-multiCompetitorRaceChart
{
background-color: white;
background-image:
url(images/viewicons/@1x/img/SAP_RV_CompetitorCharts_INACTIVE.png),
url(images/arrows_top_black_small.png);
background-repeat: no-repeat, no-repeat;
background-position: 5% 50%, 95% 50%
}
.gwt-SplitLayoutPanel-NorthSouthToggleButton-Open-multiCompetitorRaceChart
{
background-color: white;
background-image:
url(images/viewicons/@1x/img/SAP_RV_CompetitorCharts_GHOSTED.png),
url(images/arrows_bottom_black_small.png);
background-repeat: no-repeat, no-repeat;
background-position: 5% 50%, 95% 50%
}
.gwt-SplitLayoutPanel-NorthSouthToggleButton-Closed-windChart {
background-color: white;
background-image:
url(images/viewicons/@1x/img/SAP_RV_CompetitorCharts_INACTIVE.png),
url(images/arrows_top_black_small.png);
background-repeat: no-repeat, no-repeat;
background-position: 5% 50%, 95% 50%
}
.gwt-SplitLayoutPanel-NorthSouthToggleButton-Open-windChart {
background-color: white;
background-image:
url(images/viewicons/@1x/img/SAP_RV_CompetitorCharts_GHOSTED.png),
url(images/arrows_bottom_black_small.png);
background-repeat: no-repeat, no-repeat;
background-position: 5% 50%, 95% 50%
}
.gwt-SplitLayoutPanel-EastToggleButton-Open-leaderboard {
background-color: white;
background-image:
url(images/viewicons/@1x/img/SAP_RV_Leaderboard_GHOSTED.png),
url(images/arrows_top_black_small.png);
background-repeat: no-repeat, no-repeat;
background-position: 4% 50%, 96% 50%
}
.gwt-SplitLayoutPanel-EastToggleButton-Closed-leaderboard {
background-color: white;
background-image:
url(images/viewicons/@1x/img/SAP_RV_Leaderboard_INACTIVE.png),
url(images/arrows_bottom_black_small.png);
background-repeat: no-repeat, no-repeat;
background-position: 4% 50%, 96% 50%
}
.gwt-SplitLayoutPanel-NorthSouthToggleButton-Closed-media,
.gwt-SplitLayoutPanel-NorthSouthToggleButton-Open-media {
background-color: white;
background-image:
url(images/viewicons/@1x/img/SAP_RV_AudioVideo_INACTIVE.png);
background-repeat: no-repeat, no-repeat;
background-position: 10% 50%, 90% 50%
}
.gwt-SplitLayoutPanel-NorthSouthToggleButton-mediaplaying {
background-image:
url(images/viewicons/@1x/img/SAP_RV_AudioVideo_GHOSTED.png);
}
.gwt-SplitLayoutPanel-NorthSouthToggleButton-Small-media {
background-position: 5% 50%, 100% 50% !important;
margin-left: 0px !important;
padding: 2px 35px !important;
}
@external gwt-ToggleButton-up, gwt-ToggleButton-down, gwt-ToggleButton-up-hovering, gwt-ToggleButton-down-hovering;
.gwt-ToggleButton-up, .gwt-ToggleButton-up-hovering {
background: url(images/unlock.png) center no-repeat;
margin-left: 5px;
}
.gwt-ToggleButton-down, .gwt-ToggleButton-down-hovering {
background: url(images/lock.png) center no-repeat;
margin-left: 5px;
}
.RegattaRaceInformation-Header {
font-family: 'Open Sans', Arial, Verdana, sans-serif;
position: relative;
left: 140px;
top: 11px;
}
.RegattaRaceInformation-Header .RaceName-Label {
display: inline;
color: white;
margin-right: 10px;
font-size: 36px;
}
.RegattaRaceInformation-Header .RaceSeriesAndFleet-Label {
display: inline;
color: white;
font-size: 15px;
}
.RegattaAndRaceTime-Header {
position: absolute;
right: 10px;
top: 13px;
text-align: right;
color: white;
}
.RegattaAndRaceTime-Header .RegattaName-Anchor {
font-size: 15px;
color: white;
text-decoration: none;
padding-left: 25px;
background-image: url(images/home.png);
background-repeat: no-repeat;
background-size: 17px;
background-position: 4px 1px;
}
.RegattaAndRaceTime-Header .RegattaName-Anchor:hover {
text-decoration: underline;
}
.RegattaAndRaceTime-Header .RaceTime-Label {
font-size: 15px;
margin-top: 5px;
}
.VideoPopup-Close-Button {
border: none;
}
.Media-Select-Button {
font-size: 15px;
font-size: 1rem;
display: inline-block;
font-weight: 400;
color: #111;
border: none;
padding: 0.5em 0.3em 0.5em 0.8em;
background-color: #fff;
-webkit-transition: background-color 0.2s;
-moz-transition: background-color 0.2s;
-o-transition: background-color 0.2s;
-ms-transition: background-color 0.2s;
transition: background-color 0.2s;
width: 100%;
max-width: 25em;
text-align: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.Media-Select-Button:hover, .Media-Select-Button:focus {
background-color: #f0ab00;
}
.Media-Select-Button-playing {
color: #999;
}
.Media-Select-Button-playing:hover, .Media-Select-Button-playing:focus {
color: #fff;
background-color: #ccc;
}
.Media-Select-Popup .dialogMiddleCenterInner {
padding: 0;
}
.Media-Select-Popup .Caption {
padding: 4px 10px;
}
@@ -0,0 +1,41 @@
<!doctype html>
<html>
<head>
<!--[if lt IE 9]>
<meta http-equiv="REFRESH" content="0; url=http://www.sapsailing.com/browser-info.html">
<![endif]-->
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>SAP Sailing Analytics Race Board</title>
<meta content='width = device-width, initial-scale = 1.0, user-scalable = yes' name='viewport'>
<meta content='yes' name='apple-mobile-web-app-capable'>
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
<!-- <link href='iphone-splash-screen.png' rel='apple-touch-startup-image'> -->
<link href='images/sap-sailing-app-icon.png' rel='apple-touch-icon'>
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
<!--<link href='http://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700,300italic,400italic,500italic,700italic' rel='stylesheet' type='text/css'>-->
<!-- <link href='http://fonts.googleapis.com/css?family=Open+Sans+Condensed:700,300,300italic' rel='stylesheet' type='text/css'>-->
<link rel="stylesheet" type="text/css" href="/sailing-reset-2.0.cache.css">
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
<link rel="stylesheet" type="text/css" href="EmbeddedMapAndWindChart.css">
<script type="text/javascript" src="js/jquery-1.5.2.min.js"></script>
<script type="text/javascript" language="javascript" src="com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart/com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart.nocache.js"></script>
</head>
<body>
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
<!-- RECOMMENDED if your web app will not function without JavaScript enabled -->
<noscript>
<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
Your web browser must have JavaScript enabled
in order for this application to display correctly.
</div>
</noscript>
</body>
</html>
@@ -54,7 +54,7 @@
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/> <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> <stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/> <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/Home.html com.sap.sailing.gwt.ui.Search -startupUrl /gwt/Home.html com.sap.sailing.gwt.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.ui.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.VideoPopup"/> <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/Home.html com.sap.sailing.gwt.ui.Search -startupUrl /gwt/Home.html com.sap.sailing.gwt.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/EmbeddedMapAndWindChart.html com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.ui.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.VideoPopup"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/> <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m -XX:MaxPermSize=512m -Xdebug -Xrunjdwp:transport=dt_socket,address=7999,server=y"/> <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m -XX:MaxPermSize=512m -Xdebug -Xrunjdwp:transport=dt_socket,address=7999,server=y"/>
</launchConfiguration> </launchConfiguration>
@@ -1,76 +1,77 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="com.google.gdt.eclipse.suite.webapp"> <launchConfiguration type="com.google.gdt.eclipse.suite.webapp">
<booleanAttribute key="com.google.gdt.eclipse.core.RUN_SERVER" value="false"/> <booleanAttribute key="com.google.gdt.eclipse.core.RUN_SERVER" value="false"/>
<stringAttribute key="com.google.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.GWTShell"/> <stringAttribute key="com.google.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.GWTShell"/>
<booleanAttribute key="com.google.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/> <booleanAttribute key="com.google.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
<listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES"> <listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES">
<listEntry value="com.sap.sailing.gwt.ui.RaceBoard"/> <listEntry value="com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart"/>
<listEntry value="com.sap.sailing.gwt.ui.DataMining"/> <listEntry value="com.sap.sailing.gwt.ui.RaceBoard"/>
<listEntry value="com.sap.sailing.gwt.ui.LeaderboardEditing"/> <listEntry value="com.sap.sailing.gwt.ui.DataMining"/>
<listEntry value="com.sap.sailing.gwt.ui.Spectator"/> <listEntry value="com.sap.sailing.gwt.ui.LeaderboardEditing"/>
<listEntry value="com.sap.sailing.gwt.regattaoverview.RegattaOverview"/> <listEntry value="com.sap.sailing.gwt.ui.Spectator"/>
<listEntry value="com.sap.sailing.gwt.ui.PolarSheets"/> <listEntry value="com.sap.sailing.gwt.regattaoverview.RegattaOverview"/>
<listEntry value="com.sap.sailing.gwt.ui.Leaderboard"/> <listEntry value="com.sap.sailing.gwt.ui.PolarSheets"/>
<listEntry value="com.sap.sailing.gwt.ui.Simulator"/> <listEntry value="com.sap.sailing.gwt.ui.Leaderboard"/>
<listEntry value="com.sap.sailing.gwt.ui.YoutubePopup"/> <listEntry value="com.sap.sailing.gwt.ui.Simulator"/>
<listEntry value="com.sap.sailing.gwt.AutoPlay"/> <listEntry value="com.sap.sailing.gwt.ui.YoutubePopup"/>
<listEntry value="com.sap.sailing.gwt.ui.AdminConsole"/> <listEntry value="com.sap.sailing.gwt.AutoPlay"/>
<listEntry value="com.sap.sailing.gwt.home.Home"/> <listEntry value="com.sap.sailing.gwt.ui.AdminConsole"/>
<listEntry value="com.sap.sailing.gwt.ui.VideoPopup"/> <listEntry value="com.sap.sailing.gwt.home.Home"/>
</listAttribute> <listEntry value="com.sap.sailing.gwt.ui.VideoPopup"/>
<booleanAttribute key="com.google.gwt.eclipse.core.SUPERDEVMODE_ENABLED" value="true"/> </listAttribute>
<stringAttribute key="com.google.gwt.eclipse.core.URL" value="/gwt/Home.html"/> <booleanAttribute key="com.google.gwt.eclipse.core.SUPERDEVMODE_ENABLED" value="true"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> <stringAttribute key="com.google.gwt.eclipse.core.URL" value="/gwt/Home.html"/>
<listEntry value="/com.sap.sailing.gwt.ui"/> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
</listAttribute> <listEntry value="/com.sap.sailing.gwt.ui"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> </listAttribute>
<listEntry value="4"/> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
</listAttribute> <listEntry value="4"/>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups"> </listAttribute>
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/> <listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/> <listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
</listAttribute> <listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="false"/> </listAttribute>
<listAttribute key="org.eclipse.jdt.launching.CLASSPATH"> <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="false"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6&quot; javaProject=&quot;com.sap.sailing.gwt.ui&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/> <listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6&quot; javaProject=&quot;com.sap.sailing.gwt.ui&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt.theme/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt.theme/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.googlecode.java-diff-utils/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.googlecode.java-diff-utils/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.json.simple/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.json.simple/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.udpconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.mongodb/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.udpconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.mongodb/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.operationaltransformation/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.replication/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.operationaltransformation/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.replication/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.moxieapps.gwt.highcharts/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.geocoding/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.moxieapps.gwt.highcharts/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.geocoding/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.google.gwt.osgi/lib/gwt-user.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;com.sap.sailing.gwt.ui&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.google.gwt.osgi/lib/gwt-user.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;com.sap.sailing.gwt.ui&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt.adminconsole/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt.adminconsole/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
</listAttribute> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/> </listAttribute>
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/> <stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/> <stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-superDevMode -incremental -workDir &quot;${project_loc:com.sap.sailing.gwt.ui}/.tmp/gwt-work&quot; -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/Home.html com.sap.sailing.gwt.home.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.regattaoverview.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup com.sap.sailing.gwt.home.Desktop com.sap.sailing.gwt.home.Home com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.ui.PolarSheets com.sap.sailing.gwt.regattaoverview.RegattaOverview com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.ui.RaceBoard"/> <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/> <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-superDevMode -incremental -workDir &quot;${project_loc:com.sap.sailing.gwt.ui}/.tmp/gwt-work&quot; -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/Home.html com.sap.sailing.gwt.home.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/EmbeddedMapAndWindChart com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.regattaoverview.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup com.sap.sailing.gwt.home.Desktop com.sap.sailing.gwt.home.Home com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.ui.PolarSheets com.sap.sailing.gwt.regattaoverview.RegattaOverview com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.ui.RaceBoard com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms1024m -Xmx3072m"/> <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
</launchConfiguration> <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms1024m -Xmx3072m"/>
</launchConfiguration>
+76 -76
View File
@@ -1,76 +1,76 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="com.google.gdt.eclipse.suite.webapp"> <launchConfiguration type="com.google.gdt.eclipse.suite.webapp">
<booleanAttribute key="com.google.gdt.eclipse.core.RUN_SERVER" value="false"/> <booleanAttribute key="com.google.gdt.eclipse.core.RUN_SERVER" value="false"/>
<stringAttribute key="com.google.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.GWTShell"/> <stringAttribute key="com.google.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.GWTShell"/>
<booleanAttribute key="com.google.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/> <booleanAttribute key="com.google.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
<booleanAttribute key="com.google.gwt.eclipse.core.CODE_SERVER_PORT_AUTO" value="true"/> <booleanAttribute key="com.google.gwt.eclipse.core.CODE_SERVER_PORT_AUTO" value="true"/>
<listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES"> <listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES">
<listEntry value="com.sap.sailing.gwt.ui.RaceBoard"/> <listEntry value="com.sap.sailing.gwt.ui.RaceBoard"/>
<listEntry value="com.sap.sailing.gwt.ui.DataMining"/> <listEntry value="com.sap.sailing.gwt.ui.DataMining"/>
<listEntry value="com.sap.sailing.gwt.ui.LeaderboardEditing"/> <listEntry value="com.sap.sailing.gwt.ui.LeaderboardEditing"/>
<listEntry value="com.sap.sailing.gwt.ui.Spectator"/> <listEntry value="com.sap.sailing.gwt.ui.Spectator"/>
<listEntry value="com.sap.sailing.gwt.regattaoverview.RegattaOverview"/> <listEntry value="com.sap.sailing.gwt.regattaoverview.RegattaOverview"/>
<listEntry value="com.sap.sailing.gwt.ui.PolarSheets"/> <listEntry value="com.sap.sailing.gwt.ui.PolarSheets"/>
<listEntry value="com.sap.sailing.gwt.ui.Leaderboard"/> <listEntry value="com.sap.sailing.gwt.ui.Leaderboard"/>
<listEntry value="com.sap.sailing.gwt.ui.Simulator"/> <listEntry value="com.sap.sailing.gwt.ui.Simulator"/>
<listEntry value="com.sap.sailing.gwt.ui.YoutubePopup"/> <listEntry value="com.sap.sailing.gwt.ui.YoutubePopup"/>
<listEntry value="com.sap.sailing.gwt.AutoPlay"/> <listEntry value="com.sap.sailing.gwt.AutoPlay"/>
<listEntry value="com.sap.sailing.gwt.ui.AdminConsole"/> <listEntry value="com.sap.sailing.gwt.ui.AdminConsole"/>
<listEntry value="com.sap.sailing.gwt.home.Home"/> <listEntry value="com.sap.sailing.gwt.home.Home"/>
<listEntry value="com.sap.sailing.gwt.ui.VideoPopup"/> <listEntry value="com.sap.sailing.gwt.ui.VideoPopup"/>
</listAttribute> </listAttribute>
<stringAttribute key="com.google.gwt.eclipse.core.URL" value="/gwt/Home.html"/> <stringAttribute key="com.google.gwt.eclipse.core.URL" value="/gwt/Home.html"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/com.sap.sailing.gwt.ui"/> <listEntry value="/com.sap.sailing.gwt.ui"/>
</listAttribute> </listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/> <listEntry value="4"/>
</listAttribute> </listAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups"> <listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/> <listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/> <listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
</listAttribute> </listAttribute>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="false"/> <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="false"/>
<listAttribute key="org.eclipse.jdt.launching.CLASSPATH"> <listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6&quot; javaProject=&quot;com.sap.sailing.gwt.ui&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6&quot; javaProject=&quot;com.sap.sailing.gwt.ui&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt.theme/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt.theme/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.googlecode.java-diff-utils/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.googlecode.java-diff-utils/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.json.simple/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.json.simple/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.udpconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.udpconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.mongodb/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.mongodb/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.operationaltransformation/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.operationaltransformation/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.replication/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.replication/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.moxieapps.gwt.highcharts/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.moxieapps.gwt.highcharts/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.geocoding/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.geocoding/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.google.gwt.osgi/lib/gwt-user.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.google.gwt.osgi/lib/gwt-user.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;com.sap.sailing.gwt.ui&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;com.sap.sailing.gwt.ui&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt.adminconsole/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt.adminconsole/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
</listAttribute> </listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/> <stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/>
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/> <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> <stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/> <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -incremental -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort auto -startupUrl /gwt/Home.html com.sap.sailing.gwt.home.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.regattaoverview.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup com.sap.sailing.gwt.home.Home com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.ui.PolarSheets com.sap.sailing.gwt.regattaoverview.RegattaOverview com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.ui.RaceBoard"/> <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -incremental -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort auto -startupUrl /gwt/Home.html com.sap.sailing.gwt.home.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.regattaoverview.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup com.sap.sailing.gwt.home.Home com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.ui.PolarSheets com.sap.sailing.gwt.regattaoverview.RegattaOverview com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.ui.RaceBoard"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/> <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m -Dgwt-usearchives=false -Dgwt.persistentunitcache=false"/> <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m -Dgwt-usearchives=false -Dgwt.persistentunitcache=false"/>
</launchConfiguration> </launchConfiguration>
+4 -1
View File
@@ -50,5 +50,8 @@ bin.includes = META-INF/,\
Home.html,\ Home.html,\
HomeDesktop.html,\ HomeDesktop.html,\
HomeMobile.html,\ HomeMobile.html,\
SettingsDialog.css SettingsDialog.css,\
EmbeddedMapAndWindChart.css,\
EmbeddedMapAndWindChart.html,\
com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart/
output.. = WEB-INF/classes/ output.. = WEB-INF/classes/
+1
View File
@@ -130,6 +130,7 @@
<module>com.sap.sailing.gwt.ui.Leaderboard</module> <module>com.sap.sailing.gwt.ui.Leaderboard</module>
<module>com.sap.sailing.gwt.ui.LeaderboardEditing</module> <module>com.sap.sailing.gwt.ui.LeaderboardEditing</module>
<module>com.sap.sailing.gwt.ui.RaceBoard</module> <module>com.sap.sailing.gwt.ui.RaceBoard</module>
<module>com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart</module>
<module>com.sap.sailing.gwt.ui.Spectator</module> <module>com.sap.sailing.gwt.ui.Spectator</module>
<module>com.sap.sailing.gwt.ui.DataMining</module> <module>com.sap.sailing.gwt.ui.DataMining</module>
<module>com.sap.sailing.gwt.ui.VideoPopup</module> <module>com.sap.sailing.gwt.ui.VideoPopup</module>
@@ -1,26 +0,0 @@
package com.sap.sailing.gwt.ui.actions;
import java.util.Date;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.shared.CoursePositionsDTO;
import com.sap.sse.gwt.client.async.AsyncAction;
public class GetCoursePositionsAction implements AsyncAction<CoursePositionsDTO> {
private final SailingServiceAsync sailingService;
private final RegattaAndRaceIdentifier raceIdentifier;
private final Date date;
public GetCoursePositionsAction(SailingServiceAsync sailingService, RegattaAndRaceIdentifier raceIdentifier, Date date) {
this.sailingService = sailingService;
this.raceIdentifier = raceIdentifier;
this.date = date;
}
@Override
public void execute(AsyncCallback<CoursePositionsDTO> callback) {
sailingService.getCoursePositions(raceIdentifier, date, callback);
}
}
@@ -157,7 +157,7 @@ public class EventDetailsComposite extends Composite {
} }
videoURLList.setValues(videoURLStringsAsList); videoURLList.setValues(videoURLStringsAsList);
List<String> leaderboardGroupNamesAsList = new ArrayList<>(); List<String> leaderboardGroupNamesAsList = new ArrayList<>();
for(LeaderboardGroupDTO leaderboardGroupDTO: event.getLeaderboardGroups()) { for (LeaderboardGroupDTO leaderboardGroupDTO : event.getLeaderboardGroups()) {
leaderboardGroupNamesAsList.add(leaderboardGroupDTO.getName()); leaderboardGroupNamesAsList.add(leaderboardGroupDTO.getName());
} }
leaderboardGroupList.setValues(leaderboardGroupNamesAsList); leaderboardGroupList.setValues(leaderboardGroupNamesAsList);
@@ -21,6 +21,13 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
private RegattaAndRaceIdentifier selectedRace; private RegattaAndRaceIdentifier selectedRace;
private boolean autoAdjustPlayMode; private boolean autoAdjustPlayMode;
private RaceTimesInfoDTO lastRaceTimesInfo; private RaceTimesInfoDTO lastRaceTimesInfo;
/**
* When a marker update is required but min/max are not yet initialized, this flag is set. If later
* {@link #setMinMax(Date, Date, boolean)} is invoked and this flag is set, a {@link #redrawAllMarkers(RaceTimesInfoDTO)}
* will be issued and the flag is cleared.
*/
private boolean redrawAllMarkersPendingForMinMaxBeingInitialized;
public RaceTimePanel(Timer timer, TimeRangeWithZoomProvider timeRangeProvider, StringMessages stringMessages, public RaceTimePanel(Timer timer, TimeRangeWithZoomProvider timeRangeProvider, StringMessages stringMessages,
RaceTimesInfoProvider raceTimesInfoProvider, boolean canReplayWhileLiveIsPossible) { RaceTimesInfoProvider raceTimesInfoProvider, boolean canReplayWhileLiveIsPossible) {
@@ -105,7 +112,7 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
// maybe show a special state for this like "Race did not start yet" // maybe show a special state for this like "Race did not start yet"
} }
} }
lastRaceTimesInfo = raceTimesInfo; lastRaceTimesInfo = raceTimesInfo; // TODO bug 3122: when not redrawn yet because min/max not initialized yet, further redraw is disabled by this.
} }
@Override @Override
@@ -181,6 +188,15 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
} }
} }
@Override
public void setMinMax(Date min, Date max, boolean fireEvent) {
super.setMinMax(min, max, fireEvent);
if (redrawAllMarkersPendingForMinMaxBeingInitialized && timeSlider.isMinMaxInitialized()) {
redrawAllMarkers(lastRaceTimesInfo);
redrawAllMarkersPendingForMinMaxBeingInitialized = false;
}
}
/** /**
* When in {@link PlayModes#Replay} mode, tries to put the {@link #timer} to the time point when the last leg was * When in {@link PlayModes#Replay} mode, tries to put the {@link #timer} to the time point when the last leg was
* finished first. If this time point is not (yet?) known, tries to put the {@link #timer} to the * finished first. If this time point is not (yet?) known, tries to put the {@link #timer} to the
@@ -239,8 +255,12 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
requiresMarkerUpdate = true; requiresMarkerUpdate = true;
} }
} }
if (requiresMarkerUpdate && timeSlider.isMinMaxInitialized()) { if (requiresMarkerUpdate) {
redrawAllMarkers(newRaceTimesInfo); if (timeSlider.isMinMaxInitialized()) { // TODO bug 3122 later, the lastRaceTimesInfo will be updated even if not redrawn because min/max not initialized
redrawAllMarkers(newRaceTimesInfo);
} else {
redrawAllMarkersPendingForMinMaxBeingInitialized = true;
}
} }
} }
@@ -9,7 +9,7 @@ package com.sap.sailing.gwt.ui.client;
*/ */
public interface RequiresDataInitialization { public interface RequiresDataInitialization {
public void initializeData(boolean showMapControls); public void initializeData(boolean showMapControls, boolean showHeaderPanel);
public boolean isDataInitialized(); public boolean isDataInitialized();
} }
@@ -614,4 +614,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS
ArrayList<LeaderboardGroupDTO> getLeaderboardGroupsByEventId(UUID id); ArrayList<LeaderboardGroupDTO> getLeaderboardGroupsByEventId(UUID id);
boolean doesRegattaLogContainCompetitors(String name) throws DoesNotHaveRegattaLogException; boolean doesRegattaLogContainCompetitors(String name) throws DoesNotHaveRegattaLogException;
RegattaAndRaceIdentifier getRaceIdentifier(String regattaLikeName, String raceColumnName, String fleetName);
} }
@@ -719,4 +719,6 @@ public interface SailingServiceAsync extends BuildVersionRetriever, FileStorageM
void getLeaderboardGroupsByEventId(UUID id, AsyncCallback<ArrayList<LeaderboardGroupDTO>> callback); void getLeaderboardGroupsByEventId(UUID id, AsyncCallback<ArrayList<LeaderboardGroupDTO>> callback);
void doesRegattaLogContainCompetitors(String name, AsyncCallback<Boolean> regattaLogCallBack); void doesRegattaLogContainCompetitors(String name, AsyncCallback<Boolean> regattaLogCallBack);
void getRaceIdentifier(String regattaLikeName, String raceColumnName, String fleetName, AsyncCallback<RegattaAndRaceIdentifier> asyncCallback);
} }
@@ -1340,5 +1340,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, c
String selectCompetitor(); String selectCompetitor();
String points(); String points();
String numberOfRacesShort(); String numberOfRacesShort();
String courseGeometry();
String degreesToWind(String diff);
String miniLeeaderboardLegendText(); String miniLeeaderboardLegendText();
} }
@@ -881,7 +881,7 @@ errorRunningDataMiningQuery=An error occured running the query
hideToolbar=Hide toolbar hideToolbar=Hide toolbar
showSeriesLeaderboards=Show series leaderboards showSeriesLeaderboards=Show series leaderboards
showOverallLeaderboard=Show overall leaderboard showOverallLeaderboard=Show overall leaderboard
lineAngleToWindAndAdvantage=length: {0}m; angle to wind: {1}deg; {2} side has {3}m advantage lineAngleToWindAndAdvantage=length: {0}m\nangle to wind: {1}deg\n{2} side has {3}m advantage
doYouReallyWantToRemoveEvents=Do you really want to remove the events? doYouReallyWantToRemoveEvents=Do you really want to remove the events?
doYouReallyWantToRemoveEvent=Do you really want to remove event {0}? doYouReallyWantToRemoveEvent=Do you really want to remove event {0}?
line=Line line=Line
@@ -1309,4 +1309,6 @@ hoursAgo={0} h ago
selectCompetitor=Please select one competitor selectCompetitor=Please select one competitor
points=Points points=Points
numberOfRacesShort=# Races numberOfRacesShort=# Races
courseGeometry=Course Geometry
degreesToWind={0}° to wind
miniLeeaderboardLegendText=Shows the points along with the number of races per competitor miniLeeaderboardLegendText=Shows the points along with the number of races per competitor
@@ -877,7 +877,7 @@ errorRunningDataMiningQuery=Es ist ein Felher bei der Datenabfrage aufgetreten
hideToolbar=Toolbar ausblenden hideToolbar=Toolbar ausblenden
showSeriesLeaderboards=Ergebnisse der Serie anzeigen showSeriesLeaderboards=Ergebnisse der Serie anzeigen
showOverallLeaderboard=Gesamtergebnisse anzeigen showOverallLeaderboard=Gesamtergebnisse anzeigen
lineAngleToWindAndAdvantage=Länge: {0}m; Winkel zum Wind: {1}°; {2}-Seite ist {3}m bevorteilt lineAngleToWindAndAdvantage=Länge: {0}m\nWinkel zum Wind: {1}°\n{2}-Seite ist {3}m bevorteilt
doYouReallyWantToRemoveEvents=Möchten Sie diese Veranstaltungen wirklich entfernen? doYouReallyWantToRemoveEvents=Möchten Sie diese Veranstaltungen wirklich entfernen?
doYouReallyWantToRemoveEvent=Möchten Sie wirklich die Veranstaltung {0} entfernen? doYouReallyWantToRemoveEvent=Möchten Sie wirklich die Veranstaltung {0} entfernen?
line=Linie line=Linie
@@ -1299,4 +1299,6 @@ hoursAgo=vor {0} h
selectCompetitor=Bitte einen Teilnehmer auswählen selectCompetitor=Bitte einen Teilnehmer auswählen
points=Punkte points=Punkte
numberOfRacesShort=# Rennen numberOfRacesShort=# Rennen
courseGeometry=Kursgeometrie
degreesToWind={0}° zum Wind
miniLeeaderboardLegendText=Es werden die Punkte und die Anzahl Rennen je Team angezeigt miniLeeaderboardLegendText=Es werden die Punkte und die Anzahl Rennen je Team angezeigt
@@ -870,7 +870,7 @@ errorRunningDataMiningQuery=Ошибка при выполнении запро
hideToolbar=Скрыть панель инструментов hideToolbar=Скрыть панель инструментов
showSeriesLeaderboards=Показать таблицу лидеров серии showSeriesLeaderboards=Показать таблицу лидеров серии
showOverallLeaderboard=Показать общую таблицу лидеров showOverallLeaderboard=Показать общую таблицу лидеров
lineAngleToWindAndAdvantage=длина: {0}м; угол к ветру: {1}градус; {2} борт {3}м имеет преимущество lineAngleToWindAndAdvantage=длина: {0}м\nугол к ветру: {1}градус\n{2} борт {3}м имеет преимущество
doYouReallyWantToRemoveEvents=Вы действительно хотите удалить все события? doYouReallyWantToRemoveEvents=Вы действительно хотите удалить все события?
doYouReallyWantToRemoveEvent=Вы действительно хотите удалить событие {0}? doYouReallyWantToRemoveEvent=Вы действительно хотите удалить событие {0}?
line=Строка line=Строка
@@ -1246,4 +1246,6 @@ hoursAgo={0} h часов назад
selectCompetitor=Please select one competitor selectCompetitor=Please select one competitor
points=Points points=Points
numberOfRacesShort=# Races numberOfRacesShort=# Races
courseGeometry=Course Geometry
degreesToWind={0}° to wind
miniLeeaderboardLegendText=Shows points along with the number of races per competitor miniLeeaderboardLegendText=Shows points along with the number of races per competitor
@@ -391,7 +391,7 @@ listRaces=List Races
dropReplicaConnection=Drop connection dropReplicaConnection=Drop connection
errorTryingToObtainOverallLeaderboards=Error trying to obtain overall leaderboards: {0} errorTryingToObtainOverallLeaderboards=Error trying to obtain overall leaderboards: {0}
distanceTraveled=行驶距离 distanceTraveled=行驶距离
lineAngleToWindAndAdvantage=length: {0}m; angle to wind: {1}deg; {2} side has {3}m advantage lineAngleToWindAndAdvantage=length: {0}m\nangle to wind: {1}deg\n{2} side has {3}m advantage
mapDevices=Map Devices to Competitors and Marks mapDevices=Map Devices to Competitors and Marks
scoringSchemeHighPointFirstGetsTenOrEight=High Point, winner gets 10 points (or 8) scoringSchemeHighPointFirstGetsTenOrEight=High Point, winner gets 10 points (or 8)
playModeLive=Live playModeLive=Live
@@ -1295,4 +1295,6 @@ openLeaderboard=Open Leaderboard
selectCompetitor=Please select one competitor selectCompetitor=Please select one competitor
points=Points points=Points
numberOfRacesShort=# Races numberOfRacesShort=# Races
courseGeometry=Course Geometry
degreesToWind={0}° to wind
miniLeeaderboardLegendText=Shows points along with the number of races per competitor miniLeeaderboardLegendText=Shows points along with the number of races per competitor
@@ -20,6 +20,9 @@ import com.google.gwt.user.client.ui.RequiresResize;
import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.client.TimePanelCssResources.TimePanelCss; import com.sap.sailing.gwt.ui.client.TimePanelCssResources.TimePanelCss;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.gwt.client.controls.slider.SliderBar; import com.sap.sse.gwt.client.controls.slider.SliderBar;
import com.sap.sse.gwt.client.controls.slider.TimeSlider; import com.sap.sse.gwt.client.controls.slider.TimeSlider;
import com.sap.sse.gwt.client.player.PlayStateListener; import com.sap.sse.gwt.client.player.PlayStateListener;
@@ -331,9 +334,13 @@ public class TimePanel<T extends TimePanelSettings> extends SimplePanel implemen
if (timeRangeProvider.isZoomed()) { if (timeRangeProvider.isZoomed()) {
timeSlider.setCurrentValue(new Double(newTime.getTime()), false); timeSlider.setCurrentValue(new Double(newTime.getTime()), false);
} else { } else {
if (getFromTime() == null || getToTime() == null) {
initializeTimeRange(oldTime, newTime);
}
if (getFromTime() != null && getToTime() != null) { if (getFromTime() != null && getToTime() != null) {
// handle the case where time advances beyond slider's end. // handle the case where time advances beyond slider's end.
if (newTime.after(getToTime())) { if (newTime.after(getToTime())) {
// in live mode, expand the range
switch (timer.getPlayMode()) { switch (timer.getPlayMode()) {
case Live: case Live:
Date newMaxTime = new Date(newTime.getTime()); Date newMaxTime = new Date(newTime.getTime());
@@ -343,6 +350,7 @@ public class TimePanel<T extends TimePanelSettings> extends SimplePanel implemen
setMinMax(getFromTime(), newMaxTime, /* fireEvent */ false); // no event because we guarantee that time is between min/max setMinMax(getFromTime(), newMaxTime, /* fireEvent */ false); // no event because we guarantee that time is between min/max
break; break;
case Replay: case Replay:
// in replay, stop playing when the end of the range has been reached
timer.pause(); timer.pause();
break; break;
} }
@@ -362,6 +370,22 @@ public class TimePanel<T extends TimePanelSettings> extends SimplePanel implemen
} }
} }
/**
* When the time range is not yet properly initialized and we get a time change, adjust the time range so that old and
* new time are in range. A margin of one minute is used before and after. This method assumes that at least one of the
* two time points passed as parameters has a value other than <code>null</code>. Should the other be <code>null</code>,
* it is ignored. No assumptions are made about the temporal relation of the two time points to each other; in other
* words, <code>oldTime</code> may also be after <code>newTime<code> which could, e.g., be the case for a timer running
* backwards.
*/
private void initializeTimeRange(Date oldTime, Date newTime) {
TimePoint from = Util.getEarliestOfTimePoints(getFromTime()==null?null:new MillisecondsTimePoint(getFromTime()), oldTime==null?null:new MillisecondsTimePoint(oldTime));
from = Util.getEarliestOfTimePoints(from, newTime==null?null:new MillisecondsTimePoint(newTime));
TimePoint to = Util.getEarliestOfTimePoints(getToTime()==null?null:new MillisecondsTimePoint(getToTime()), oldTime==null?null:new MillisecondsTimePoint(oldTime));
from = Util.getEarliestOfTimePoints(to, newTime==null?null:new MillisecondsTimePoint(newTime));
timeRangeProvider.setTimeRange(from==null?null:from.asDate(), to==null?null:to.asDate());
}
protected String getTimeToStartLabelText(Date time) { protected String getTimeToStartLabelText(Date time) {
return null; return null;
} }
@@ -396,16 +420,12 @@ public class TimePanel<T extends TimePanelSettings> extends SimplePanel implemen
assert min != null && max != null; assert min != null && max != null;
boolean changed = false; boolean changed = false;
if (!max.equals(timeRangeProvider.getToTime())) { if (!max.equals(timeRangeProvider.getToTime()) || !min.equals(timeRangeProvider.getFromTime())) {
changed = true; changed = true;
timeSlider.setMaxValue(new Double(max.getTime()), fireEvent); timeSlider.setMinAndMaxValue(new Double(min.getTime()),new Double(max.getTime()), fireEvent);
}
if (!min.equals(timeRangeProvider.getFromTime())) {
changed = true;
timeSlider.setMinValue(new Double(min.getTime()), fireEvent);
} }
if (changed) { if (changed) {
if(!timeRangeProvider.isZoomed()) { if (!timeRangeProvider.isZoomed()) {
timeRangeProvider.setTimeRange(min, max, this); timeRangeProvider.setTimeRange(min, max, this);
} }
@@ -595,4 +615,8 @@ public class TimePanel<T extends TimePanelSettings> extends SimplePanel implemen
public String getDependentCssClassName() { public String getDependentCssClassName() {
return "timePanel"; return "timePanel";
} }
public Button getBackToLiveButton() {
return backToLivePlayButton;
}
} }
@@ -44,6 +44,7 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.WindSource; import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.impl.ColorMapImpl; import com.sap.sailing.domain.common.impl.ColorMapImpl;
import com.sap.sailing.gwt.ui.actions.GetWindInfoAction; import com.sap.sailing.gwt.ui.actions.GetWindInfoAction;
import com.sap.sailing.gwt.ui.client.RaceSelectionChangeListener;
import com.sap.sailing.gwt.ui.client.RaceSelectionProvider; import com.sap.sailing.gwt.ui.client.RaceSelectionProvider;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.StringMessages;
@@ -86,7 +87,9 @@ public class WindChart extends AbstractRaceChart implements Component<WindChartS
* @param raceSelectionProvider * @param raceSelectionProvider
* if <code>null</code>, this chart won't update its contents automatically upon race selection change; * if <code>null</code>, this chart won't update its contents automatically upon race selection change;
* otherwise, whenever the selection changes, the wind data of the race selected now is loaded from the * otherwise, whenever the selection changes, the wind data of the race selected now is loaded from the
* server and displayed in this chart. If no race is selected, the chart is cleared. * server and displayed in this chart. If no race is selected, the chart is cleared. The caller of this
* constructor must ensure to trigger {@link RaceSelectionChangeListener#onRaceSelectionChange(List)} at
* least once to ensure that this chart sets its {@link AbstractRaceChart#selectedRaceIdentifier} field.
*/ */
public WindChart(SailingServiceAsync sailingService, RaceSelectionProvider raceSelectionProvider, Timer timer, public WindChart(SailingServiceAsync sailingService, RaceSelectionProvider raceSelectionProvider, Timer timer,
TimeRangeWithZoomProvider timeRangeWithZoomProvider, WindChartSettings settings, final StringMessages stringMessages, TimeRangeWithZoomProvider timeRangeWithZoomProvider, WindChartSettings settings, final StringMessages stringMessages,
@@ -518,38 +521,35 @@ public class WindChart extends AbstractRaceChart implements Component<WindChartS
*/ */
@Override @Override
public void timeChanged(Date newTime, Date oldTime) { public void timeChanged(Date newTime, Date oldTime) {
if(!isVisible()) { if (isVisible()) {
return; updateTimePlotLine(newTime);
} switch (timer.getPlayMode()) {
case Live:
updateTimePlotLine(newTime); {
// is date before first cache entry or is cache empty?
switch(timer.getPlayMode()) {
case Live:
{
// is date before first cache entry or is cache empty?
if (timeOfEarliestRequestInMillis == null || newTime.getTime() < timeOfEarliestRequestInMillis) {
loadData(timeRangeWithZoomProvider.getFromTime(), newTime, /* append */ true);
} else if (newTime.getTime() > timeOfLatestRequestInMillis) {
loadData(new Date(timeOfLatestRequestInMillis), timeRangeWithZoomProvider.getToTime(), /* append */true);
}
// otherwise the cache spans across date and so we don't need to load anything
break;
}
case Replay:
{
if (timeOfLatestRequestInMillis == null) {
// pure replay mode
loadData(timeRangeWithZoomProvider.getFromTime(), timeRangeWithZoomProvider.getToTime(), /* append */false);
} else {
// replay mode during live play
if (timeOfEarliestRequestInMillis == null || newTime.getTime() < timeOfEarliestRequestInMillis) { if (timeOfEarliestRequestInMillis == null || newTime.getTime() < timeOfEarliestRequestInMillis) {
loadData(timeRangeWithZoomProvider.getFromTime(), newTime, /* append */ true); loadData(timeRangeWithZoomProvider.getFromTime(), newTime, /* append */ true);
} else if (newTime.getTime() > timeOfLatestRequestInMillis) { } else if (newTime.getTime() > timeOfLatestRequestInMillis) {
loadData(new Date(timeOfLatestRequestInMillis), newTime, /* append */true); loadData(new Date(timeOfLatestRequestInMillis), timeRangeWithZoomProvider.getToTime(), /* append */true);
} }
// otherwise the cache spans across date and so we don't need to load anything
break;
}
case Replay:
{
if (timeOfLatestRequestInMillis == null) {
// pure replay mode
loadData(timeRangeWithZoomProvider.getFromTime(), timeRangeWithZoomProvider.getToTime(), /* append */false);
} else {
// replay mode during live play
if (timeOfEarliestRequestInMillis == null || newTime.getTime() < timeOfEarliestRequestInMillis) {
loadData(timeRangeWithZoomProvider.getFromTime(), newTime, /* append */ true);
} else if (newTime.getTime() > timeOfLatestRequestInMillis) {
loadData(new Date(timeOfLatestRequestInMillis), newTime, /* append */true);
}
}
break;
} }
break;
} }
} }
} }
@@ -100,16 +100,19 @@ import com.sap.sailing.gwt.ui.client.shared.filter.QuickRankProvider;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapHelpLinesSettings.HelpLineTypes; import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapHelpLinesSettings.HelpLineTypes;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapZoomSettings.ZoomTypes; import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapZoomSettings.ZoomTypes;
import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil;
import com.sap.sailing.gwt.ui.shared.ControlPointDTO;
import com.sap.sailing.gwt.ui.shared.CoursePositionsDTO; import com.sap.sailing.gwt.ui.shared.CoursePositionsDTO;
import com.sap.sailing.gwt.ui.shared.GPSFixDTO; import com.sap.sailing.gwt.ui.shared.GPSFixDTO;
import com.sap.sailing.gwt.ui.shared.LegInfoDTO; import com.sap.sailing.gwt.ui.shared.LegInfoDTO;
import com.sap.sailing.gwt.ui.shared.ManeuverDTO; import com.sap.sailing.gwt.ui.shared.ManeuverDTO;
import com.sap.sailing.gwt.ui.shared.MarkDTO; import com.sap.sailing.gwt.ui.shared.MarkDTO;
import com.sap.sailing.gwt.ui.shared.QuickRankDTO; import com.sap.sailing.gwt.ui.shared.QuickRankDTO;
import com.sap.sailing.gwt.ui.shared.RaceCourseDTO;
import com.sap.sailing.gwt.ui.shared.RaceMapDataDTO; import com.sap.sailing.gwt.ui.shared.RaceMapDataDTO;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
import com.sap.sailing.gwt.ui.shared.SidelineDTO; import com.sap.sailing.gwt.ui.shared.SidelineDTO;
import com.sap.sailing.gwt.ui.shared.SpeedWithBearingDTO; import com.sap.sailing.gwt.ui.shared.SpeedWithBearingDTO;
import com.sap.sailing.gwt.ui.shared.WaypointDTO;
import com.sap.sailing.gwt.ui.shared.WindDTO; import com.sap.sailing.gwt.ui.shared.WindDTO;
import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO; import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO;
import com.sap.sailing.gwt.ui.shared.WindTrackInfoDTO; import com.sap.sailing.gwt.ui.shared.WindTrackInfoDTO;
@@ -118,6 +121,7 @@ import com.sap.sailing.gwt.ui.shared.racemap.GoogleMapStyleHelper;
import com.sap.sailing.gwt.ui.shared.racemap.RaceSimulationOverlay; import com.sap.sailing.gwt.ui.shared.racemap.RaceSimulationOverlay;
import com.sap.sailing.gwt.ui.shared.racemap.WindStreamletsRaceboardOverlay; import com.sap.sailing.gwt.ui.shared.racemap.WindStreamletsRaceboardOverlay;
import com.sap.sse.common.Util; import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.Util.Triple; import com.sap.sse.common.Util.Triple;
import com.sap.sse.common.filter.Filter; import com.sap.sse.common.filter.Filter;
import com.sap.sse.common.filter.FilterSet; import com.sap.sse.common.filter.FilterSet;
@@ -209,11 +213,24 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
private AdvantageLineMouseOverMapHandler advantageLineMouseOverHandler; private AdvantageLineMouseOverMapHandler advantageLineMouseOverHandler;
/** /**
* Polyline for the course middle line. * Polylines for the course middle lines; keys are the two control points delimiting the leg for which the
* {@link Polyline} value shows the course middle line. As only one course middle line is shown even if there
* are multiple legs using the same control points in different directions, using a {@link Set} makes this
* independent of the order of the two control points. If no course middle line is currently being shown for
* a pair of control points, the map will not contain a value for this pair.
*/ */
private Polyline courseMiddleLine; private final Map<Set<ControlPointDTO>, Polyline> courseMiddleLines;
private Map<SidelineDTO, Polygon> courseSidelines; private final Map<SidelineDTO, Polygon> courseSidelines;
/**
* When the {@link HelpLineTypes#COURSEGEOMETRY} option is selected, little markers will be displayed on the
* lines that show the tooltip text in a little info box linked to the line. When the line is removed by
* {@link #showOrRemoveOrUpdateLine(Polyline, boolean, Position, Position, LineInfoProvider, String)}, these
* overlays need to be removed as well. Also, when the {@link HelpLineTypes#COURSEGEOMETRY} setting is
* deactivated, all these overlays need to go.
*/
private final Map<Polyline, SmallTransparentInfoOverlay> infoOverlaysForLinesForCourseGeometry;
/** /**
* Wind data used to display the advantage line. Retrieved by a {@link GetWindInfoAction} execution and used in * Wind data used to display the advantage line. Retrieved by a {@link GetWindInfoAction} execution and used in
@@ -382,7 +399,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
public RaceMap(SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor, public RaceMap(SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor,
ErrorReporter errorReporter, Timer timer, CompetitorSelectionProvider competitorSelection, ErrorReporter errorReporter, Timer timer, CompetitorSelectionProvider competitorSelection,
StringMessages stringMessages, boolean showMapControls, boolean showViewStreamlets, boolean showViewSimulation, StringMessages stringMessages, boolean showMapControls, boolean showViewStreamlets, boolean showViewSimulation,
RegattaAndRaceIdentifier raceIdentifier, CombinedWindPanelStyle combinedWindPanelStyle) { RegattaAndRaceIdentifier raceIdentifier, CombinedWindPanelStyle combinedWindPanelStyle, boolean showHeaderPanel) {
this.setSize("100%", "100%"); this.setSize("100%", "100%");
this.showMapControls = showMapControls; this.showMapControls = showMapControls;
this.stringMessages = stringMessages; this.stringMessages = stringMessages;
@@ -394,7 +411,9 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
timer.addTimeListener(this); timer.addTimeListener(this);
raceMapImageManager = new RaceMapImageManager(); raceMapImageManager = new RaceMapImageManager();
markDTOs = new HashMap<String, MarkDTO>(); markDTOs = new HashMap<String, MarkDTO>();
courseSidelines = new HashMap<SidelineDTO, Polygon>(); courseSidelines = new HashMap<>();
courseMiddleLines = new HashMap<>();
infoOverlaysForLinesForCourseGeometry = new HashMap<>();
boatOverlays = new HashMap<CompetitorDTO, BoatOverlay>(); boatOverlays = new HashMap<CompetitorDTO, BoatOverlay>();
competitorInfoOverlays = new HashMap<CompetitorDTO, CompetitorInfoOverlay>(); competitorInfoOverlays = new HashMap<CompetitorDTO, CompetitorInfoOverlay>();
windSensorOverlays = new HashMap<WindSource, WindSensorOverlay>(); windSensorOverlays = new HashMap<WindSource, WindSensorOverlay>();
@@ -414,7 +433,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
headerPanel.setStyleName("RaceMap-HeaderPanel"); headerPanel.setStyleName("RaceMap-HeaderPanel");
panelForLeftHeaderLabels = new AbsolutePanel(); panelForLeftHeaderLabels = new AbsolutePanel();
panelForRightHeaderLabels = new AbsolutePanel(); panelForRightHeaderLabels = new AbsolutePanel();
initializeData(showMapControls); initializeData(showMapControls, showHeaderPanel);
combinedWindPanel = new CombinedWindPanel(raceMapImageManager, combinedWindPanelStyle, stringMessages, coordinateSystem); combinedWindPanel = new CombinedWindPanel(raceMapImageManager, combinedWindPanelStyle, stringMessages, coordinateSystem);
combinedWindPanel.setVisible(false); combinedWindPanel.setVisible(false);
trueNorthIndicatorPanel = new TrueNorthIndicatorPanel(this, raceMapImageManager, combinedWindPanelStyle, stringMessages, coordinateSystem); trueNorthIndicatorPanel = new TrueNorthIndicatorPanel(this, raceMapImageManager, combinedWindPanelStyle, stringMessages, coordinateSystem);
@@ -483,8 +502,8 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
public void execute() { public void execute() {
if (map != null) { if (map != null) {
map.setOptions(mapOptions); map.setOptions(mapOptions);
final LatLngBounds newBounds = getDefaultZoomBounds(); // ensure zooming to what the settings tell, or defaults if what the settings tell isn't possible right now
zoomMapToNewBounds(newBounds); mapFirstZoomDone = false;
trueNorthIndicatorPanel.redraw(); trueNorthIndicatorPanel.redraw();
orientationChangeInProgress = false; orientationChangeInProgress = false;
} }
@@ -492,7 +511,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
}); });
} }
private void loadMapsAPIV3(final boolean showMapControls) { private void loadMapsAPIV3(final boolean showMapControls, final boolean showHeaderPanel) {
boolean sensor = true; boolean sensor = true;
// load all the libs for use in the maps // load all the libs for use in the maps
@@ -506,8 +525,10 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
MapOptions mapOptions = getMapOptions(showMapControls, /* wind up */ false); MapOptions mapOptions = getMapOptions(showMapControls, /* wind up */ false);
map = new MapWidget(mapOptions); map = new MapWidget(mapOptions);
RaceMap.this.add(map, 0, 0); RaceMap.this.add(map, 0, 0);
Image sapLogo = createSAPLogo(); if (showHeaderPanel) {
RaceMap.this.add(sapLogo); Image sapLogo = createSAPLogo();
RaceMap.this.add(sapLogo);
}
map.setControls(ControlPosition.LEFT_TOP, combinedWindPanel); map.setControls(ControlPosition.LEFT_TOP, combinedWindPanel);
combinedWindPanel.getParent().addStyleName("CombinedWindPanelParentDiv"); combinedWindPanel.getParent().addStyleName("CombinedWindPanelParentDiv");
map.setControls(ControlPosition.LEFT_TOP, trueNorthIndicatorPanel); map.setControls(ControlPosition.LEFT_TOP, trueNorthIndicatorPanel);
@@ -592,19 +613,26 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
simulationOverlay.addToMap(); simulationOverlay.addToMap();
simulationOverlay.setVisible(false); simulationOverlay.setVisible(false);
} }
if (showHeaderPanel) {
createHeaderPanel(map); createHeaderPanel(map);
}
createSettingsButton(map); createSettingsButton(map);
// Data has been initialized // Data has been initialized
RaceMap.this.isMapInitialized = true; RaceMap.this.isMapInitialized = true;
RaceMap.this.redraw(); RaceMap.this.redraw();
trueNorthIndicatorPanel.redraw(); trueNorthIndicatorPanel.redraw();
showAdditionalControls(map);
} }
}; };
LoadApi.go(onLoad, loadLibraries, sensor, "key="+GoogleMapAPIKey.V3_APIKey); LoadApi.go(onLoad, loadLibraries, sensor, "key="+GoogleMapAPIKey.V3_APIKey);
} }
/**
* Subclasses may define additional stuff to be shown on the map.
*/
protected void showAdditionalControls(MapWidget map) {
}
private void setHasPolar() { private void setHasPolar() {
GetPolarAction getPolar = new GetPolarAction(sailingService, raceIdentifier); GetPolarAction getPolar = new GetPolarAction(sailingService, raceIdentifier);
@@ -753,7 +781,6 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
getRaceMapDataCallback(oldTime, newTime, fromAndToAndOverlap.getC(), competitorsToShow, requestID)); getRaceMapDataCallback(oldTime, newTime, fromAndToAndOverlap.getC(), competitorsToShow, requestID));
// draw the wind into the map, get the combined wind // draw the wind into the map, get the combined wind
// TODO bug2057 also fetch wind for LEG_MIDDLE for all legs because this needs to be the basis for the advantage line display
List<String> windSourceTypeNames = new ArrayList<String>(); List<String> windSourceTypeNames = new ArrayList<String>();
windSourceTypeNames.add(WindSourceType.EXPEDITION.name()); windSourceTypeNames.add(WindSourceType.EXPEDITION.name());
windSourceTypeNames.add(WindSourceType.COMBINED.name()); windSourceTypeNames.add(WindSourceType.COMBINED.name());
@@ -879,7 +906,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
updateCoordinateSystemFromSettings(); updateCoordinateSystemFromSettings();
} }
showCourseSidelinesOnMap(raceMapDataDTO.courseSidelines); showCourseSidelinesOnMap(raceMapDataDTO.courseSidelines);
showStartAndFinishLines(raceMapDataDTO.coursePositions); showStartAndFinishAndCourseMiddleLines(raceMapDataDTO.coursePositions);
showStartLineToFirstMarkTriangle(raceMapDataDTO.coursePositions); showStartLineToFirstMarkTriangle(raceMapDataDTO.coursePositions);
// even though the wind data is retrieved by a separate call, re-draw the advantage line because it needs to // even though the wind data is retrieved by a separate call, re-draw the advantage line because it needs to
// adjust to new boat positions // adjust to new boat positions
@@ -1169,10 +1196,10 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
// this only works because the quickRanks are sorted // this only works because the quickRanks are sorted
for (Entry<CompetitorDTO, Integer> competitorsByWindwardDistanceTraveledAndOneBasedLegNumber : for (Entry<CompetitorDTO, Integer> competitorsByWindwardDistanceTraveledAndOneBasedLegNumber :
competitorsInOrderOfWindwardDistanceTraveledWithOneBasedLegNumber.entrySet()) { competitorsInOrderOfWindwardDistanceTraveledWithOneBasedLegNumber.entrySet()) {
if (Util.contains(competitorsToShow, competitorsByWindwardDistanceTraveledAndOneBasedLegNumber.getKey())) { if (Util.contains(competitorsToShow, competitorsByWindwardDistanceTraveledAndOneBasedLegNumber.getKey()) &&
competitorsByWindwardDistanceTraveledAndOneBasedLegNumber.getValue() != null) {
leadingCompetitorDTO = competitorsByWindwardDistanceTraveledAndOneBasedLegNumber.getKey(); leadingCompetitorDTO = competitorsByWindwardDistanceTraveledAndOneBasedLegNumber.getKey();
legOfLeaderCompetitor = competitorsByWindwardDistanceTraveledAndOneBasedLegNumber.getValue() == null ? legOfLeaderCompetitor = competitorsByWindwardDistanceTraveledAndOneBasedLegNumber.getValue();
0 : competitorsByWindwardDistanceTraveledAndOneBasedLegNumber.getValue();
return new com.sap.sse.common.Util.Pair<Integer, CompetitorDTO>(legOfLeaderCompetitor, leadingCompetitorDTO); return new com.sap.sse.common.Util.Pair<Integer, CompetitorDTO>(legOfLeaderCompetitor, leadingCompetitorDTO);
} }
} }
@@ -1297,254 +1324,264 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
private final StringBuilder leewardStartLineMarkToFirstMarkLineText = new StringBuilder(); private final StringBuilder leewardStartLineMarkToFirstMarkLineText = new StringBuilder();
private void showStartLineToFirstMarkTriangle(final CoursePositionsDTO courseDTO){ private void showStartLineToFirstMarkTriangle(final CoursePositionsDTO courseDTO){
if (settings.getHelpLinesSettings().isVisible(HelpLineTypes.STARTLINETOFIRSTMARKTRIANGLE) final List<Position> startMarkPositions = courseDTO.getStartMarkPositions();
&& courseDTO.startMarkPositions.size() > 1 && courseDTO.waypointPositions.size() > 1) { final Position windwardStartLinePosition = startMarkPositions.get(0);
LatLng windwardStartLinePoint = coordinateSystem.toLatLng(courseDTO.startMarkPositions.get(0)); final Position leewardStartLinePosition = startMarkPositions.get(1);
LatLng leewardStartLinePoint = coordinateSystem.toLatLng(courseDTO.startMarkPositions.get(1)); final Position firstMarkPosition = courseDTO.waypointPositions.get(1);
LatLng firstMarkPoint = coordinateSystem.toLatLng(courseDTO.waypointPositions.get(1)); windwardStartLineMarkToFirstMarkLineText.replace(0, windwardStartLineMarkToFirstMarkLineText.length(),
windwardStartLineMarkToFirstMarkLineText.replace(0, windwardStartLineMarkToFirstMarkLineText.length(), stringMessages.startLineToFirstMarkTriangle(numberFormatOneDecimal
stringMessages.startLineToFirstMarkTriangle(numberFormatOneDecimal .format(windwardStartLinePosition.getDistance(firstMarkPosition)
.format(courseDTO.startMarkPositions.get(0).getDistance(courseDTO.waypointPositions.get(1)) .getMeters())));
.getMeters()))); leewardStartLineMarkToFirstMarkLineText.replace(0, leewardStartLineMarkToFirstMarkLineText.length(),
leewardStartLineMarkToFirstMarkLineText.replace(0, leewardStartLineMarkToFirstMarkLineText.length(), stringMessages.startLineToFirstMarkTriangle(numberFormatOneDecimal
stringMessages.startLineToFirstMarkTriangle(numberFormatOneDecimal .format(leewardStartLinePosition.getDistance(firstMarkPosition)
.format(courseDTO.startMarkPositions.get(1).getDistance(courseDTO.waypointPositions.get(1)) .getMeters())));
.getMeters()))); final LineInfoProvider windwardStartLineMarkToFirstMarkLineInfoProvider = new LineInfoProvider() {
if (windwardStartLineMarkToFirstMarkLine == null && leewardStartLineMarkToFirstMarkLine == null) { @Override
PolylineOptions options = PolylineOptions.newInstance(); public String getLineInfo() {
options.setGeodesic(true); return windwardStartLineMarkToFirstMarkLineText.toString();
options.setStrokeColor("grey");
options.setStrokeWeight(1);
options.setStrokeOpacity(1.0);
MVCArray<LatLng> windwardLinePoints = MVCArray.newInstance();
windwardLinePoints.insertAt(0, windwardStartLinePoint);
windwardLinePoints.insertAt(1, firstMarkPoint);
MVCArray<LatLng> leewardLinePoints = MVCArray.newInstance();
leewardLinePoints.insertAt(0, leewardStartLinePoint);
leewardLinePoints.insertAt(1, firstMarkPoint);
windwardStartLineMarkToFirstMarkLine = Polyline.newInstance(options);
windwardStartLineMarkToFirstMarkLine.setPath(windwardLinePoints);
windwardStartLineMarkToFirstMarkLine.addMouseOverHandler(new MouseOverMapHandler() {
@Override
public void onEvent(MouseOverMapEvent event) {
map.setTitle(windwardStartLineMarkToFirstMarkLineText.toString());
}
});
windwardStartLineMarkToFirstMarkLine.addMouseOutMoveHandler(new MouseOutMapHandler() {
@Override
public void onEvent(MouseOutMapEvent event) {
map.setTitle("");
}
});
leewardStartLineMarkToFirstMarkLine = Polyline.newInstance(options);
leewardStartLineMarkToFirstMarkLine.setPath(leewardLinePoints);
leewardStartLineMarkToFirstMarkLine.addMouseOverHandler(new MouseOverMapHandler() {
@Override
public void onEvent(MouseOverMapEvent event) {
map.setTitle(leewardStartLineMarkToFirstMarkLineText.toString());
}
});
leewardStartLineMarkToFirstMarkLine.addMouseOutMoveHandler(new MouseOutMapHandler() {
@Override
public void onEvent(MouseOutMapEvent event) {
map.setTitle("");
}
});
windwardStartLineMarkToFirstMarkLine.setMap(map);
leewardStartLineMarkToFirstMarkLine.setMap(map);
} else {
windwardStartLineMarkToFirstMarkLine.getPath().removeAt(1);
windwardStartLineMarkToFirstMarkLine.getPath().removeAt(0);
windwardStartLineMarkToFirstMarkLine.getPath().insertAt(0, windwardStartLinePoint);
windwardStartLineMarkToFirstMarkLine.getPath().insertAt(1, firstMarkPoint);
leewardStartLineMarkToFirstMarkLine.getPath().removeAt(1);
leewardStartLineMarkToFirstMarkLine.getPath().removeAt(0);
leewardStartLineMarkToFirstMarkLine.getPath().insertAt(0, leewardStartLinePoint);
leewardStartLineMarkToFirstMarkLine.getPath().insertAt(1, firstMarkPoint);
} }
} else { };
if (windwardStartLineMarkToFirstMarkLine != null) { final LineInfoProvider leewardStartLineMarkToFirstMarkLineInfoProvider = new LineInfoProvider() {
windwardStartLineMarkToFirstMarkLine.setMap(null); @Override
windwardStartLineMarkToFirstMarkLine = null; public String getLineInfo() {
return leewardStartLineMarkToFirstMarkLineText.toString();
} }
if (leewardStartLineMarkToFirstMarkLine != null) { };
leewardStartLineMarkToFirstMarkLine.setMap(null); windwardStartLineMarkToFirstMarkLine = showOrRemoveOrUpdateLine(windwardStartLineMarkToFirstMarkLine, /* showLine */
leewardStartLineMarkToFirstMarkLine = null; (settings.getHelpLinesSettings().isVisible(HelpLineTypes.STARTLINETOFIRSTMARKTRIANGLE))
} && startMarkPositions.size() > 1 && courseDTO.waypointPositions.size() > 1,
} windwardStartLinePosition, firstMarkPosition, windwardStartLineMarkToFirstMarkLineInfoProvider,
"grey");
leewardStartLineMarkToFirstMarkLine = showOrRemoveOrUpdateLine(leewardStartLineMarkToFirstMarkLine, /* showLine */
(settings.getHelpLinesSettings().isVisible(HelpLineTypes.STARTLINETOFIRSTMARKTRIANGLE))
&& startMarkPositions.size() > 1 && courseDTO.waypointPositions.size() > 1,
leewardStartLinePosition, firstMarkPosition, leewardStartLineMarkToFirstMarkLineInfoProvider,
"grey");
} }
private final StringBuilder startLineAdvantageText = new StringBuilder(); private final StringBuilder startLineAdvantageText = new StringBuilder();
private final StringBuilder finishLineAdvantageText = new StringBuilder(); private final StringBuilder finishLineAdvantageText = new StringBuilder();
final LineInfoProvider startLineInfoProvider = new LineInfoProvider() {
@Override
public String getLineInfo() {
return stringMessages.startLine()+startLineAdvantageText;
}
};
final LineInfoProvider finishLineInfoProvider = new LineInfoProvider() {
@Override
public String getLineInfo() {
return stringMessages.finishLine()+finishLineAdvantageText;
}
};
private void showStartAndFinishLines(final CoursePositionsDTO courseDTO) { private void showStartAndFinishAndCourseMiddleLines(final CoursePositionsDTO courseDTO) {
if (map != null && courseDTO != null && lastRaceTimesInfo != null) { if (map != null && courseDTO != null && courseDTO.course != null && courseDTO.course.waypoints != null &&
com.sap.sse.common.Util.Pair<Integer, CompetitorDTO> leadingVisibleCompetitorInfo = getFarthestAheadVisibleCompetitorWithOneBasedLegNumber(getCompetitorsToShow()); !courseDTO.course.waypoints.isEmpty()) {
int legOfLeadingCompetitor = leadingVisibleCompetitorInfo == null ? -1 : leadingVisibleCompetitorInfo.getA();
int numberOfLegs = lastRaceTimesInfo.legInfos.size();
// draw the start line // draw the start line
updateCountdownCanvas(courseDTO.startMarkPositions); final WaypointDTO startWaypoint = courseDTO.course.waypoints.get(0);
if (legOfLeadingCompetitor <= 1 && updateCountdownCanvas(startWaypoint);
settings.getHelpLinesSettings().isVisible(HelpLineTypes.STARTLINE) && courseDTO.startMarkPositions != null && courseDTO.startMarkPositions.size() == 2) { final int numberOfStartWaypointMarks = courseDTO.getStartMarkPositions() == null ? 0 : courseDTO.getStartMarkPositions().size();
LatLng startLinePoint1 = coordinateSystem.toLatLng(courseDTO.startMarkPositions.get(0)); final Position startLineLeftPosition = numberOfStartWaypointMarks == 0 ? null : courseDTO.getStartMarkPositions().get(0);
LatLng startLinePoint2 = coordinateSystem.toLatLng(courseDTO.startMarkPositions.get(1)); final Position startLineRightPosition = numberOfStartWaypointMarks < 2 ? null : courseDTO.getStartMarkPositions().get(1);
if (courseDTO.startLineAngleToCombinedWind != null) { if (courseDTO.startLineAngleToCombinedWind != null) {
startLineAdvantageText.replace(0, startLineAdvantageText.length(), " "+stringMessages.lineAngleToWindAndAdvantage( startLineAdvantageText.replace(0, startLineAdvantageText.length(), " "+stringMessages.lineAngleToWindAndAdvantage(
NumberFormat.getFormat("0.0").format(courseDTO.startLineLengthInMeters), NumberFormat.getFormat("0.0").format(courseDTO.startLineLengthInMeters),
NumberFormat.getFormat("0.0").format(Math.abs(courseDTO.startLineAngleToCombinedWind)), NumberFormat.getFormat("0.0").format(Math.abs(courseDTO.startLineAngleToCombinedWind)),
courseDTO.startLineAdvantageousSide.name().charAt(0)+courseDTO.startLineAdvantageousSide.name().substring(1).toLowerCase(), courseDTO.startLineAdvantageousSide.name().charAt(0)+courseDTO.startLineAdvantageousSide.name().substring(1).toLowerCase(),
NumberFormat.getFormat("0.0").format(courseDTO.startLineAdvantageInMeters))); NumberFormat.getFormat("0.0").format(courseDTO.startLineAdvantageInMeters)));
} else {
startLineAdvantageText.delete(0, startLineAdvantageText.length());
}
if (startLine == null) {
PolylineOptions options = PolylineOptions.newInstance();
options.setClickable(true);
options.setGeodesic(true);
options.setStrokeColor("#FFFFFF");
options.setStrokeWeight(1);
options.setStrokeOpacity(1.0);
MVCArray<LatLng> pointsAsArray = MVCArray.newInstance();
pointsAsArray.insertAt(0, startLinePoint1);
pointsAsArray.insertAt(1, startLinePoint2);
startLine = Polyline.newInstance(options);
startLine.setPath(pointsAsArray);
startLine.addMouseOverHandler(new MouseOverMapHandler() {
@Override
public void onEvent(MouseOverMapEvent event) {
map.setTitle(stringMessages.startLine()+startLineAdvantageText);
}
});
startLine.addMouseOutMoveHandler(new MouseOutMapHandler() {
@Override
public void onEvent(MouseOutMapEvent event) {
map.setTitle("");
}
});
startLine.setMap(map);
} else {
startLine.getPath().removeAt(1);
startLine.getPath().removeAt(0);
startLine.getPath().insertAt(0, startLinePoint1);
startLine.getPath().insertAt(1, startLinePoint2);
}
} else { } else {
if (startLine != null) { startLineAdvantageText.delete(0, startLineAdvantageText.length());
startLine.setMap(null);
startLine = null;
}
} }
startLine = showOrRemoveOrUpdateLine(startLine, /* showLine */ numberOfStartWaypointMarks == 2 &&
((courseDTO.currentLegNumber <= 1 &&
settings.getHelpLinesSettings().isVisible(HelpLineTypes.STARTLINE)) ||
settings.getHelpLinesSettings().isVisible(HelpLineTypes.COURSEGEOMETRY)),
startLineLeftPosition, startLineRightPosition, startLineInfoProvider, "#ffffff");
// draw the finish line // draw the finish line
if (legOfLeadingCompetitor > 0 && legOfLeadingCompetitor == numberOfLegs && final int numberOfFinishWaypointMarks = courseDTO.getFinishMarkPositions() == null ? 0 : courseDTO.getFinishMarkPositions().size();
settings.getHelpLinesSettings().isVisible(HelpLineTypes.FINISHLINE) && courseDTO.finishMarkPositions != null && courseDTO.finishMarkPositions.size() == 2) { final Position finishLineLeftPosition = numberOfFinishWaypointMarks == 0 ? null : courseDTO.getFinishMarkPositions().get(0);
LatLng finishLinePoint1 = coordinateSystem.toLatLng(courseDTO.finishMarkPositions.get(0)); final Position finishLineRightPosition = numberOfFinishWaypointMarks < 2 ? null : courseDTO.getFinishMarkPositions().get(1);
LatLng finishLinePoint2 = coordinateSystem.toLatLng(courseDTO.finishMarkPositions.get(1)); if (courseDTO.finishLineAngleToCombinedWind != null) {
if (courseDTO.startLineAngleToCombinedWind != null) { finishLineAdvantageText.replace(0, finishLineAdvantageText.length(), " "+stringMessages.lineAngleToWindAndAdvantage(
finishLineAdvantageText.replace(0, finishLineAdvantageText.length(), " "+stringMessages.lineAngleToWindAndAdvantage( NumberFormat.getFormat("0.0").format(courseDTO.finishLineLengthInMeters),
NumberFormat.getFormat("0.0").format(courseDTO.finishLineLengthInMeters), NumberFormat.getFormat("0.0").format(Math.abs(courseDTO.finishLineAngleToCombinedWind)),
NumberFormat.getFormat("0.0").format(Math.abs(courseDTO.finishLineAngleToCombinedWind)), courseDTO.finishLineAdvantageousSide.name().charAt(0)+courseDTO.finishLineAdvantageousSide.name().substring(1).toLowerCase(),
courseDTO.finishLineAdvantageousSide.name().charAt(0)+courseDTO.finishLineAdvantageousSide.name().substring(1).toLowerCase(), NumberFormat.getFormat("0.0").format(courseDTO.finishLineAdvantageInMeters)));
NumberFormat.getFormat("0.0").format(courseDTO.finishLineAdvantageInMeters))); } else {
} else { finishLineAdvantageText.delete(0, finishLineAdvantageText.length());
finishLineAdvantageText.delete(0, finishLineAdvantageText.length());
}
if (finishLine == null) {
PolylineOptions options = PolylineOptions.newInstance();
options.setClickable(true);
options.setGeodesic(true);
options.setStrokeColor("#000000");
options.setStrokeWeight(1);
options.setStrokeOpacity(1.0);
MVCArray<LatLng> pointsAsArray = MVCArray.newInstance();
pointsAsArray.insertAt(0, finishLinePoint1);
pointsAsArray.insertAt(1, finishLinePoint2);
finishLine = Polyline.newInstance(options);
finishLine.setPath(pointsAsArray);
finishLine.addMouseOverHandler(new MouseOverMapHandler() {
@Override
public void onEvent(MouseOverMapEvent event) {
map.setTitle(stringMessages.finishLine()+finishLineAdvantageText);
}
});
finishLine.addMouseOutMoveHandler(new MouseOutMapHandler() {
@Override
public void onEvent(MouseOutMapEvent event) {
map.setTitle("");
}
});
finishLine.setMap(map);
} else {
finishLine.getPath().removeAt(1);
finishLine.getPath().removeAt(0);
finishLine.getPath().insertAt(0, finishLinePoint1);
finishLine.getPath().insertAt(1, finishLinePoint2);
}
} }
else { finishLine = showOrRemoveOrUpdateLine(finishLine, /* showLine */ numberOfFinishWaypointMarks == 2 &&
if (finishLine != null) { (courseDTO.currentLegNumber == courseDTO.totalLegsCount &&
finishLine.setMap(null); settings.getHelpLinesSettings().isVisible(HelpLineTypes.FINISHLINE))
finishLine = null; || settings.getHelpLinesSettings().isVisible(HelpLineTypes.COURSEGEOMETRY),
} finishLineLeftPosition, finishLineRightPosition, finishLineInfoProvider, "#000000");
// 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
// start waypoint index to do so; when for an equal control point pair multiple decisions with different
// outcome are made, a decision to show the line overrules the decision to not show it (OR-semantics)
final Map<Set<ControlPointDTO>, Pair<Boolean, Integer>> keysAlreadyHandled = new HashMap<>();
for (int zeroBasedIndexOfStartWaypoint = 0; zeroBasedIndexOfStartWaypoint<courseDTO.waypointPositions.size()-1; zeroBasedIndexOfStartWaypoint++) {
final Set<ControlPointDTO> key = getCourseMiddleLinesKey(courseDTO, zeroBasedIndexOfStartWaypoint);
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);
keysAlreadyHandled.put(key, new Pair<>(showCourseMiddleLine, zeroBasedIndexOfStartWaypoint));
} }
// draw the course middle line Set<Set<ControlPointDTO>> keysToConsider = new HashSet<>(keysAlreadyHandled.keySet());
if (legOfLeadingCompetitor > 0 && courseDTO.waypointPositions.size() > legOfLeadingCompetitor && keysToConsider.addAll(courseMiddleLines.keySet());
settings.getHelpLinesSettings().isVisible(HelpLineTypes.COURSEMIDDLELINE)) { for (final Set<ControlPointDTO> key : keysToConsider) {
Position position1DTO = courseDTO.waypointPositions.get(legOfLeadingCompetitor-1); final int zeroBasedIndexOfStartWaypoint = keysAlreadyHandled.containsKey(key) ?
Position position2DTO = courseDTO.waypointPositions.get(legOfLeadingCompetitor); keysAlreadyHandled.get(key).getB() : 0; // if not handled, the line will be removed, so the waypoint index doesn't matter
LatLng courseMiddleLinePoint1 = coordinateSystem.toLatLng(position1DTO); final Pair<Boolean, Integer> showLineAndZeroBasedIndexOfStartWaypoint = keysAlreadyHandled.get(key);
LatLng courseMiddleLinePoint2 = coordinateSystem.toLatLng(position2DTO); final boolean showCourseMiddleLine = showLineAndZeroBasedIndexOfStartWaypoint != null && showLineAndZeroBasedIndexOfStartWaypoint.getA();
if (courseMiddleLine == null) { courseMiddleLines.put(key, showOrRemoveCourseMiddleLine(courseDTO, courseMiddleLines.get(key), zeroBasedIndexOfStartWaypoint, showCourseMiddleLine));
PolylineOptions options = PolylineOptions.newInstance();
options.setClickable(true);
options.setGeodesic(true);
options.setStrokeColor("#2268a0");
options.setStrokeWeight(1);
options.setStrokeOpacity(1.0);
MVCArray<LatLng> pointsAsArray = MVCArray.newInstance();
pointsAsArray.insertAt(0, courseMiddleLinePoint1);
pointsAsArray.insertAt(1, courseMiddleLinePoint2);
courseMiddleLine = Polyline.newInstance(options);
courseMiddleLine.setPath(pointsAsArray);
courseMiddleLine.addMouseOverHandler(new MouseOverMapHandler() {
@Override
public void onEvent(MouseOverMapEvent event) {
map.setTitle(stringMessages.courseMiddleLine());
}
});
courseMiddleLine.addMouseOutMoveHandler(new MouseOutMapHandler() {
@Override
public void onEvent(MouseOutMapEvent event) {
map.setTitle("");
}
});
courseMiddleLine.setMap(map);
} else {
courseMiddleLine.getPath().removeAt(1);
courseMiddleLine.getPath().removeAt(0);
courseMiddleLine.getPath().insertAt(0, courseMiddleLinePoint1);
courseMiddleLine.getPath().insertAt(1, courseMiddleLinePoint2);
}
} }
else { }
if (courseMiddleLine != null) { }
courseMiddleLine.setMap(null);
courseMiddleLine = null; /**
* Given a zero-based index into <code>courseDTO</code>'s {@link RaceCourseDTO#waypoints waypoints list} that denotes the start
* waypoint of the leg in question, returns a key that can be used for the {@link #courseMiddleLines} map, consisting of a set
* that holds the two {@link ControlPointDTO}s representing the start and finish control point of that leg.
*/
private Set<ControlPointDTO> getCourseMiddleLinesKey(final CoursePositionsDTO courseDTO,
final int zeroBasedIndexOfStartWaypoint) {
ControlPointDTO startControlPoint = courseDTO.course.waypoints.get(zeroBasedIndexOfStartWaypoint).controlPoint;
ControlPointDTO endControlPoint = courseDTO.course.waypoints.get(zeroBasedIndexOfStartWaypoint+1).controlPoint;
final Set<ControlPointDTO> key = new HashSet<>();
key.add(startControlPoint);
key.add(endControlPoint);
return key;
}
/**
* @param showLine
* tells whether or not to show the line; if the <code>lineToShowOrRemoveOrUpdate</code> references a
* line but the line shall not be shown, the line is removed from the map; conversely, if the line is not
* yet shown but shall be, a new line is created, added to the map and returned. If the line is shown and
* shall continue to be shown, the line is returned after updating its vertex coordinates.
* @return <code>null</code> if the line is not shown; the polyline object representing the line being displayed
* otherwise
*/
private Polyline showOrRemoveCourseMiddleLine(final CoursePositionsDTO courseDTO, Polyline lineToShowOrRemoveOrUpdate,
final int zeroBasedIndexOfStartWaypoint, final boolean showLine) {
final Position position1DTO = courseDTO.waypointPositions.get(zeroBasedIndexOfStartWaypoint);
final Position position2DTO = courseDTO.waypointPositions.get(zeroBasedIndexOfStartWaypoint+1);
final LineInfoProvider lineInfoProvider = new LineInfoProvider() {
@Override
public String getLineInfo() {
final StringBuilder sb = new StringBuilder();
sb.append(stringMessages.courseMiddleLine());
sb.append('\n');
sb.append(NumberFormat.getFormat("0").format(
Math.abs(position1DTO.getDistance(position2DTO).getMeters()))+stringMessages.metersUnit());
if (lastCombinedWindTrackInfoDTO != null) {
final WindTrackInfoDTO windTrackAtLegMiddle = lastCombinedWindTrackInfoDTO.getCombinedWindOnLegMiddle(zeroBasedIndexOfStartWaypoint);
if (windTrackAtLegMiddle != null && windTrackAtLegMiddle.windFixes != null && !windTrackAtLegMiddle.windFixes.isEmpty()) {
WindDTO windAtLegMiddle = windTrackAtLegMiddle.windFixes.get(0);
final double legBearingDeg = position1DTO.getBearingGreatCircle(position2DTO).getDegrees();
final String diff = NumberFormat.getFormat("0.0").format(
Math.min(Math.abs(windAtLegMiddle.dampenedTrueWindBearingDeg-legBearingDeg),
Math.abs(windAtLegMiddle.dampenedTrueWindFromDeg-legBearingDeg)));
sb.append(", ");
sb.append(stringMessages.degreesToWind(diff));
}
} }
return sb.toString();
}
};
return showOrRemoveOrUpdateLine(lineToShowOrRemoveOrUpdate, showLine, position1DTO, position2DTO, lineInfoProvider, "#2268a0");
}
private interface LineInfoProvider {
String getLineInfo();
}
/**
* @param showLine
* tells whether or not to show the line; if the <code>lineToShowOrRemoveOrUpdate</code> references a
* line but the line shall not be shown, the line is removed from the map; conversely, if the line is not
* yet shown but shall be, a new line is created, added to the map and returned. If the line is shown and
* shall continue to be shown, the line is returned after updating its vertex coordinates.
* @return <code>null</code> if the line is not shown; the polyline object representing the line being displayed
* otherwise
*/
private Polyline showOrRemoveOrUpdateLine(Polyline lineToShowOrRemoveOrUpdate, final boolean showLine,
final Position position1DTO, final Position position2DTO, final LineInfoProvider lineInfoProvider, String lineColorRGB) {
if (showLine) {
LatLng courseMiddleLinePoint1 = coordinateSystem.toLatLng(position1DTO);
LatLng courseMiddleLinePoint2 = coordinateSystem.toLatLng(position2DTO);
final MVCArray<LatLng> pointsAsArray;
if (lineToShowOrRemoveOrUpdate == null) {
PolylineOptions options = PolylineOptions.newInstance();
options.setClickable(true);
options.setGeodesic(true);
options.setStrokeColor(lineColorRGB);
options.setStrokeWeight(1);
options.setStrokeOpacity(1.0);
pointsAsArray = MVCArray.newInstance();
lineToShowOrRemoveOrUpdate = Polyline.newInstance(options);
lineToShowOrRemoveOrUpdate.setPath(pointsAsArray);
lineToShowOrRemoveOrUpdate.addMouseOverHandler(new MouseOverMapHandler() {
@Override
public void onEvent(MouseOverMapEvent event) {
map.setTitle(lineInfoProvider.getLineInfo());
}
});
lineToShowOrRemoveOrUpdate.addMouseOutMoveHandler(new MouseOutMapHandler() {
@Override
public void onEvent(MouseOutMapEvent event) {
map.setTitle("");
}
});
lineToShowOrRemoveOrUpdate.setMap(map);
} else {
pointsAsArray = lineToShowOrRemoveOrUpdate.getPath();
pointsAsArray.removeAt(1);
pointsAsArray.removeAt(0);
}
adjustInfoOverlayForVisibleLine(lineToShowOrRemoveOrUpdate, position1DTO, position2DTO, lineInfoProvider);
pointsAsArray.insertAt(0, courseMiddleLinePoint1);
pointsAsArray.insertAt(1, courseMiddleLinePoint2);
} else {
if (lineToShowOrRemoveOrUpdate != null) {
lineToShowOrRemoveOrUpdate.setMap(null);
adjustInfoOverlayForRemovedLine(lineToShowOrRemoveOrUpdate);
lineToShowOrRemoveOrUpdate = null;
}
}
return lineToShowOrRemoveOrUpdate;
}
private void adjustInfoOverlayForRemovedLine(Polyline lineToShowOrRemoveOrUpdate) {
SmallTransparentInfoOverlay infoOverlay = infoOverlaysForLinesForCourseGeometry.remove(lineToShowOrRemoveOrUpdate);
if (infoOverlay != null) {
infoOverlay.removeFromMap();
}
}
private void adjustInfoOverlayForVisibleLine(Polyline lineToShowOrRemoveOrUpdate, final Position position1DTO,
final Position position2DTO, final LineInfoProvider lineInfoProvider) {
SmallTransparentInfoOverlay infoOverlay = infoOverlaysForLinesForCourseGeometry.get(lineToShowOrRemoveOrUpdate);
if (getSettings().getHelpLinesSettings().isVisible(HelpLineTypes.COURSEGEOMETRY)) {
if (infoOverlay == null) {
infoOverlay = new SmallTransparentInfoOverlay(map, RaceMapOverlaysZIndexes.INFO_OVERLAY_ZINDEX, lineInfoProvider.getLineInfo(), coordinateSystem);
infoOverlaysForLinesForCourseGeometry.put(lineToShowOrRemoveOrUpdate, infoOverlay);
infoOverlay.addToMap();
} else {
infoOverlay.setInfoText(lineInfoProvider.getLineInfo());
}
infoOverlay.setPosition(position1DTO.translateGreatCircle(position1DTO.getBearingGreatCircle(position2DTO),
position1DTO.getDistance(position2DTO).scale(0.5)), /* transition time */ -1);
infoOverlay.draw();
} else {
if (infoOverlay != null) {
infoOverlay.removeFromMap();
infoOverlaysForLinesForCourseGeometry.remove(lineToShowOrRemoveOrUpdate);
} }
} }
} }
@@ -1554,9 +1591,9 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
* still in the pre-start phase, show a {@link SmallTransparentInfoOverlay} at the * still in the pre-start phase, show a {@link SmallTransparentInfoOverlay} at the
* start line that shows the count down. * start line that shows the count down.
*/ */
private void updateCountdownCanvas(List<Position> startMarkPositions) { private void updateCountdownCanvas(WaypointDTO startWaypoint) {
if (!settings.isShowSelectedCompetitorsInfo() || startMarkPositions == null || startMarkPositions.isEmpty() if (!settings.isShowSelectedCompetitorsInfo() || startWaypoint == null || Util.isEmpty(startWaypoint.controlPoint.getMarks())
|| lastRaceTimesInfo.startOfRace == null || timer.getTime().after(lastRaceTimesInfo.startOfRace)) { || lastRaceTimesInfo == null || lastRaceTimesInfo.startOfRace == null || timer.getTime().after(lastRaceTimesInfo.startOfRace)) {
if (countDownOverlay != null) { if (countDownOverlay != null) {
countDownOverlay.removeFromMap(); countDownOverlay.removeFromMap();
countDownOverlay = null; countDownOverlay = null;
@@ -1572,7 +1609,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
} else { } else {
countDownOverlay.setInfoText(countDownText); countDownOverlay.setInfoText(countDownText);
} }
countDownOverlay.setPosition(startMarkPositions.get(startMarkPositions.size() - 1), -1); countDownOverlay.setPosition(startWaypoint.controlPoint.getMarks().iterator().next().position, /* transition time */ -1);
countDownOverlay.draw(); countDownOverlay.draw();
} }
} }
@@ -1610,7 +1647,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
|| !BoundsUtil.contains((currentMapBounds = map.getBounds()), newBounds) || !BoundsUtil.contains((currentMapBounds = map.getBounds()), newBounds)
|| graticuleAreaRatio(currentMapBounds, newBounds) > 10) { || graticuleAreaRatio(currentMapBounds, newBounds) > 10) {
// only change bounds if the new bounds don't fit into the current map zoom // only change bounds if the new bounds don't fit into the current map zoom
List<ZoomTypes> oldZoomSettings = settings.getZoomSettings().getTypesToConsiderOnZoom(); Iterable<ZoomTypes> oldZoomSettings = settings.getZoomSettings().getTypesToConsiderOnZoom();
setAutoZoomInProgress(true); setAutoZoomInProgress(true);
autoZoomLatLngBounds = newBounds; autoZoomLatLngBounds = newBounds;
int newZoomLevel = getZoomLevel(autoZoomLatLngBounds); int newZoomLevel = getZoomLevel(autoZoomLatLngBounds);
@@ -2358,8 +2395,8 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
} }
@Override @Override
public void initializeData(boolean showMapControls) { public void initializeData(boolean showMapControls, boolean showHeaderPanel) {
loadMapsAPIV3(showMapControls); loadMapsAPIV3(showMapControls, showHeaderPanel);
} }
@Override @Override
@@ -1,16 +1,18 @@
package com.sap.sailing.gwt.ui.client.shared.racemap; package com.sap.sailing.gwt.ui.client.shared.racemap;
import java.util.Collection; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import com.sap.sse.common.Util;
public class RaceMapHelpLinesSettings { public class RaceMapHelpLinesSettings {
/** /**
* Types of help lines on the map * Types of help lines on the map
*/ */
public enum HelpLineTypes { public enum HelpLineTypes {
STARTLINE, FINISHLINE, ADVANTAGELINE, COURSEMIDDLELINE, BUOYZONE, BOATTAILS, STARTLINETOFIRSTMARKTRIANGLE STARTLINE, FINISHLINE, ADVANTAGELINE, COURSEMIDDLELINE, BUOYZONE, BOATTAILS, STARTLINETOFIRSTMARKTRIANGLE, COURSEGEOMETRY
} }
private final Set<HelpLineTypes> visibleHelpLines; private final Set<HelpLineTypes> visibleHelpLines;
@@ -27,14 +29,19 @@ public class RaceMapHelpLinesSettings {
visibleHelpLines.add(HelpLineTypes.BOATTAILS); visibleHelpLines.add(HelpLineTypes.BOATTAILS);
} }
public RaceMapHelpLinesSettings(Collection<HelpLineTypes> visibleHelpLines) { public RaceMapHelpLinesSettings(Iterable<HelpLineTypes> visibleHelpLines) {
this.visibleHelpLines = new HashSet<HelpLineTypes>(visibleHelpLines); this.visibleHelpLines = new HashSet<>();
Util.addAll(visibleHelpLines, this.visibleHelpLines);
} }
public boolean isVisible(HelpLineTypes helpLineType) { public boolean isVisible(HelpLineTypes helpLineType) {
return visibleHelpLines.contains(helpLineType); return visibleHelpLines.contains(helpLineType);
} }
public Iterable<HelpLineTypes> getVisibleHelpLineTypes() {
return Collections.unmodifiableCollection(visibleHelpLines);
}
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
@@ -47,6 +47,23 @@ public class RaceMapSettings extends AbstractSettings {
this.helpLinesSettings = new RaceMapHelpLinesSettings(); this.helpLinesSettings = new RaceMapHelpLinesSettings();
} }
/**
* "Copy constructor" that produces a new settings object that equals the one passed as argument
*/
public RaceMapSettings(RaceMapSettings settings) {
this.buoyZoneRadiusInMeters = settings.buoyZoneRadiusInMeters;
this.helpLinesSettings = new RaceMapHelpLinesSettings(settings.getHelpLinesSettings().getVisibleHelpLineTypes());
this.maneuverTypesToShow = settings.maneuverTypesToShow;
this.showDouglasPeuckerPoints = settings.showDouglasPeuckerPoints;
this.showOnlySelectedCompetitors = settings.showOnlySelectedCompetitors;
this.showSelectedCompetitorsInfo = settings.showSelectedCompetitorsInfo;
this.showSimulationOverlay = settings.showSimulationOverlay;
this.showWindStreamletOverlay = settings.showWindStreamletOverlay;
this.tailLengthInMilliseconds = settings.tailLengthInMilliseconds;
this.windUp = settings.windUp;
this.zoomSettings = new RaceMapZoomSettings(settings.zoomSettings.getTypesToConsiderOnZoom(), settings.zoomSettings.isZoomToSelectedCompetitors());
}
/** /**
* @return 0 if the tails are not visible {@link #getTailLengthInMilliseconds()} otherwise * @return 0 if the tails are not visible {@link #getTailLengthInMilliseconds()} otherwise
*/ */
@@ -98,7 +98,7 @@ public class RaceMapSettingsDialogComponent implements SettingsDialogComponent<R
for (ZoomTypes zoomType : ZoomTypes.values()) { for (ZoomTypes zoomType : ZoomTypes.values()) {
if (zoomType != ZoomTypes.NONE) { if (zoomType != ZoomTypes.NONE) {
CheckBox cb = dialog.createCheckbox(RaceMapSettingsTypeFormatter.formatZoomType(zoomType, stringMessages)); CheckBox cb = dialog.createCheckbox(RaceMapSettingsTypeFormatter.formatZoomType(zoomType, stringMessages));
cb.setValue(initialSettings.getZoomSettings().getTypesToConsiderOnZoom().contains(zoomType), false); cb.setValue(Util.contains(initialSettings.getZoomSettings().getTypesToConsiderOnZoom(), zoomType), false);
checkboxAndZoomType.add(new Util.Pair<CheckBox, ZoomTypes>(cb, zoomType)); checkboxAndZoomType.add(new Util.Pair<CheckBox, ZoomTypes>(cb, zoomType));
zoomSettingsBoxesPanel.add(cb); zoomSettingsBoxesPanel.add(cb);
@@ -195,6 +195,7 @@ public class RaceMapSettingsDialogComponent implements SettingsDialogComponent<R
vp.add(createHelpLineCheckBox(dialog, HelpLineTypes.ADVANTAGELINE)); vp.add(createHelpLineCheckBox(dialog, HelpLineTypes.ADVANTAGELINE));
vp.add(createHelpLineCheckBox(dialog, HelpLineTypes.COURSEMIDDLELINE)); vp.add(createHelpLineCheckBox(dialog, HelpLineTypes.COURSEMIDDLELINE));
vp.add(createHelpLineCheckBox(dialog, HelpLineTypes.STARTLINETOFIRSTMARKTRIANGLE)); vp.add(createHelpLineCheckBox(dialog, HelpLineTypes.STARTLINETOFIRSTMARKTRIANGLE));
vp.add(createHelpLineCheckBox(dialog, HelpLineTypes.COURSEGEOMETRY));
return vp; return vp;
} }
@@ -37,6 +37,8 @@ public class RaceMapSettingsTypeFormatter {
return stringConstants.boatTails(); return stringConstants.boatTails();
case STARTLINETOFIRSTMARKTRIANGLE: case STARTLINETOFIRSTMARKTRIANGLE:
return stringConstants.startFirstMarkTriangle(); return stringConstants.startFirstMarkTriangle();
case COURSEGEOMETRY:
return stringConstants.courseGeometry();
} }
return null; return null;
} }
@@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.google.gwt.maps.client.base.LatLngBounds; import com.google.gwt.maps.client.base.LatLngBounds;
import com.sap.sse.common.Util;
/** /**
* @author Lennart Hensler (D054527) * @author Lennart Hensler (D054527)
@@ -29,7 +30,7 @@ public class RaceMapZoomSettings {
} }
}; };
private ArrayList<ZoomTypes> typesToConsiderOnZoom; private Iterable<ZoomTypes> typesToConsiderOnZoom;
private boolean zoomToSelectedCompetitors; private boolean zoomToSelectedCompetitors;
/** /**
@@ -37,13 +38,14 @@ public class RaceMapZoomSettings {
* The attribute <code>zoomToSelectedCompetitors</code> will be <code>false</code>. * The attribute <code>zoomToSelectedCompetitors</code> will be <code>false</code>.
*/ */
public RaceMapZoomSettings() { public RaceMapZoomSettings() {
typesToConsiderOnZoom = new ArrayList<ZoomTypes>(); final List<ZoomTypes> myTypesToConsiderOnZoom = new ArrayList<>();
typesToConsiderOnZoom = myTypesToConsiderOnZoom;
// Other zoom types such as BOATS, TAILS or WINDSENSORS are not currently used as default zoom types. // Other zoom types such as BOATS, TAILS or WINDSENSORS are not currently used as default zoom types.
typesToConsiderOnZoom.add(ZoomTypes.BUOYS); myTypesToConsiderOnZoom.add(ZoomTypes.BUOYS);
zoomToSelectedCompetitors = false; zoomToSelectedCompetitors = false;
} }
public RaceMapZoomSettings(ArrayList<ZoomTypes> typesToConsiderOnZoom, boolean zoomToSelected) { public RaceMapZoomSettings(Iterable<ZoomTypes> typesToConsiderOnZoom, boolean zoomToSelected) {
this.typesToConsiderOnZoom = typesToConsiderOnZoom; this.typesToConsiderOnZoom = typesToConsiderOnZoom;
this.zoomToSelectedCompetitors = zoomToSelected; this.zoomToSelectedCompetitors = zoomToSelected;
} }
@@ -67,12 +69,14 @@ public class RaceMapZoomSettings {
return newBounds; return newBounds;
} }
public List<ZoomTypes> getTypesToConsiderOnZoom() { public Iterable<ZoomTypes> getTypesToConsiderOnZoom() {
return typesToConsiderOnZoom; return typesToConsiderOnZoom;
} }
public void setTypesToConsiderOnZoom(List<ZoomTypes> typesToConsiderOnZoom) { public void setTypesToConsiderOnZoom(Iterable<ZoomTypes> typesToConsiderOnZoom) {
this.typesToConsiderOnZoom = new ArrayList<ZoomTypes>(typesToConsiderOnZoom); List<ZoomTypes> newTypesToConsiderOnZoom = new ArrayList<>();
Util.addAll(typesToConsiderOnZoom, newTypesToConsiderOnZoom);
this.typesToConsiderOnZoom = newTypesToConsiderOnZoom;
} }
public void setZoomToSelectedCompetitors(boolean zoomToSelectedCompetitors) { public void setZoomToSelectedCompetitors(boolean zoomToSelectedCompetitors) {
@@ -84,7 +88,7 @@ public class RaceMapZoomSettings {
} }
public boolean containsZoomType(ZoomTypes zoomType) { public boolean containsZoomType(ZoomTypes zoomType) {
return typesToConsiderOnZoom.contains(zoomType); return Util.contains(typesToConsiderOnZoom, zoomType);
} }
@Override @Override
@@ -42,32 +42,45 @@ public class SmallTransparentInfoOverlay extends CanvasOverlayV3 {
infoBoxWidth = 20; infoBoxWidth = 20;
infoBoxHeight = 20; infoBoxHeight = 20;
cornerRadius = 4; cornerRadius = 4;
if (getCanvas() != null) { if (getCanvas() != null) {
getCanvas().setWidth(String.valueOf(canvasWidth)); getCanvas().setWidth(String.valueOf(canvasWidth));
getCanvas().setHeight(String.valueOf(canvasHeight)); getCanvas().setHeight(String.valueOf(canvasHeight));
getCanvas().setCoordinateSpaceWidth(canvasWidth); getCanvas().setCoordinateSpaceWidth(canvasWidth);
getCanvas().setCoordinateSpaceHeight(canvasHeight); getCanvas().setCoordinateSpaceHeight(canvasHeight);
} }
// setCanvasSize(canvasWidth, canvasHeight);
} }
@Override @Override
protected void draw() { protected void draw() {
final int LINE_SPACING = 3;
final int BOTTOM_MARGIN = 8;
final int LEFT_MARGIN = 8;
final int RIGHT_MARGIN = 9;
final int POLE_LENGTH = 25;
if (mapProjection != null && position != null) { if (mapProjection != null && position != null) {
LatLng latLngPosition = coordinateSystem.toLatLng(position); LatLng latLngPosition = coordinateSystem.toLatLng(position);
Context2d context2d = getCanvas().getContext2d(); Context2d context2d = getCanvas().getContext2d();
CssColor grayTransparentColor = CssColor.make("rgba(255,255,255,0.75)"); CssColor grayTransparentColor = CssColor.make("rgba(255,255,255,0.75)");
final int fontSizeInPx = 12+2*Math.max(0, map.getZoom()-15);
context2d.setFont("12px bold Verdana sans-serif"); final int LINE_HEIGHT = fontSizeInPx+LINE_SPACING;
TextMetrics measureText = context2d.measureText(infoText); context2d.setFont(""+fontSizeInPx+"px Roboto, Arial, sans-serif");
double textWidth = measureText.getWidth(); // context2d.setFont(""+fontSizeInPx+"px bold Verdana sans-serif");
double textWidth = 0;
canvasWidth = (int) textWidth + 17; infoBoxHeight = BOTTOM_MARGIN;
for (final String line : infoText.split("\n")) {
TextMetrics measureText = context2d.measureText(line);
if (measureText.getWidth() > textWidth) {
textWidth = measureText.getWidth();
}
infoBoxHeight += LINE_HEIGHT;
}
canvasWidth = (int) textWidth + LEFT_MARGIN + RIGHT_MARGIN;
infoBoxWidth = canvasWidth; infoBoxWidth = canvasWidth;
canvasHeight = infoBoxHeight + POLE_LENGTH;
getCanvas().setWidth(String.valueOf(canvasWidth)); getCanvas().setWidth(String.valueOf(canvasWidth));
getCanvas().setCoordinateSpaceWidth(canvasWidth); getCanvas().setCoordinateSpaceWidth(canvasWidth);
getCanvas().setHeight(String.valueOf(canvasHeight));
getCanvas().setCoordinateSpaceHeight(canvasHeight);
// Change origin and dimensions to match true size (a stroke makes the shape a bit larger) // Change origin and dimensions to match true size (a stroke makes the shape a bit larger)
context2d.setFillStyle(grayTransparentColor); context2d.setFillStyle(grayTransparentColor);
@@ -86,7 +99,13 @@ public class SmallTransparentInfoOverlay extends CanvasOverlayV3 {
context2d.beginPath(); context2d.beginPath();
context2d.setFillStyle("black"); context2d.setFillStyle("black");
context2d.fillText(infoText, 8, 14); // context2d.setFont(""+fontSizeInPx+"px bold Verdana sans-serif");
context2d.setFont(""+fontSizeInPx+"px Roboto, Arial, sans-serif");
int y = LINE_HEIGHT;
for (final String line : infoText.split("\n")) {
context2d.fillText(line, LEFT_MARGIN, y);
y += LINE_HEIGHT;
}
context2d.stroke(); context2d.stroke();
Point objectPositionInPx = mapProjection.fromLatLngToDivPixel(latLngPosition); Point objectPositionInPx = mapProjection.fromLatLngToDivPixel(latLngPosition);
@@ -0,0 +1,216 @@
package com.sap.sailing.gwt.ui.raceboard;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.controls.ControlPosition;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.DockLayoutPanel.Direction;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.sap.sailing.domain.common.LeaderboardNameConstants;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.dto.CompetitorDTO;
import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint;
import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel;
import com.sap.sailing.gwt.ui.client.CompetitorSelectionProvider;
import com.sap.sailing.gwt.ui.client.LogoAndTitlePanel;
import com.sap.sailing.gwt.ui.client.RaceSelectionModel;
import com.sap.sailing.gwt.ui.client.TimePanel;
import com.sap.sailing.gwt.ui.client.TimePanelSettings;
import com.sap.sailing.gwt.ui.client.shared.charts.WindChart;
import com.sap.sailing.gwt.ui.client.shared.charts.WindChartSettings;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMap;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapHelpLinesSettings;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapHelpLinesSettings.HelpLineTypes;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapResources;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapSettings;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapZoomSettings;
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapZoomSettings.ZoomTypes;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sse.common.Duration;
import com.sap.sse.common.Util;
import com.sap.sse.common.filter.Filter;
import com.sap.sse.common.filter.FilterSet;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.player.TimeRangeWithZoomModel;
import com.sap.sse.gwt.client.player.TimeRangeWithZoomProvider;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
import com.sap.sse.gwt.shared.GwtHttpRequestUtils;
public class EmbeddedMapAndWindChartEntryPoint extends AbstractSailingEntryPoint {
private static final String PARAM_REGATTA_LIKE_NAME = "regattaLikeName";
private static final String PARAM_RACE_COLUMN_NAME = "raceColumnName";
private static final String PARAM_FLEET_NAME = "fleetName";
private static final String PARAM_EVENT_ID = "eventId";
private String regattaLikeName;
private String raceColumnName;
private String fleetName;
private UUID eventId;
private static final RaceMapResources raceMapResources = GWT.create(RaceMapResources.class);
private static final int DEFAULT_WIND_CHART_HEIGHT = 200;
@Override
protected void doOnModuleLoad() {
super.doOnModuleLoad();
// read mandatory parameters
regattaLikeName = Window.Location.getParameter(PARAM_REGATTA_LIKE_NAME);
raceColumnName = Window.Location.getParameter(PARAM_RACE_COLUMN_NAME);
fleetName = Window.Location.getParameter(PARAM_FLEET_NAME);
String eventIdParamValue = Window.Location.getParameter(PARAM_EVENT_ID);
if (eventIdParamValue != null && !eventIdParamValue.isEmpty()) {
eventId = UUID.fromString(eventIdParamValue);
}
if (regattaLikeName == null || regattaLikeName.isEmpty() || raceColumnName == null || raceColumnName.isEmpty() ||
fleetName == null || fleetName.isEmpty()) {
createErrorPage("This page requires a valid regatta, race column and fleet name to identify the race to show.");
return;
}
// read optional parameters
final boolean showWindChart = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_WINDCHART, true /* default*/);
final boolean showViewStreamlets = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_STREAMLETS, false /* default*/);
final boolean showViewSimulation = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_SIMULATION, true /* default*/);
final boolean showMapControls = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_MAPCONTROLS, true /* default*/);
if (eventId != null) {
sailingService.getEventById(eventId, /* withStatisticalData */ false, new AsyncCallback<EventDTO>() {
@Override
public void onSuccess(EventDTO eventDTO) {
checkUrlParameters(eventDTO, showWindChart, showMapControls, showViewStreamlets, showViewSimulation);
}
@Override
public void onFailure(Throwable t) {
reportError("Error trying to create the raceboard: " + t.getMessage());
}
});
} else {
checkUrlParameters(/* event */ null, showWindChart, showMapControls, showViewStreamlets, showViewSimulation);
}
}
private void createErrorPage(String message) {
final DockLayoutPanel vp = new DockLayoutPanel(Unit.PX);
LogoAndTitlePanel logoAndTitlePanel = new LogoAndTitlePanel(getStringMessages(), this, getUserService());
logoAndTitlePanel.addStyleName("LogoAndTitlePanel");
RootLayoutPanel.get().add(vp);
vp.addNorth(logoAndTitlePanel, 100);
vp.add(new Label(message));
}
private void checkUrlParameters(final EventDTO event, final boolean showWindChart,
final boolean showMapControls, final boolean showViewStreamlets, final boolean showViewSimulation) {
if (eventId != null && event == null) {
createErrorPage(getStringMessages().noSuchEvent());
}
sailingService.getRaceIdentifier(regattaLikeName, raceColumnName, fleetName, new AsyncCallback<RegattaAndRaceIdentifier>() {
@Override
public void onFailure(Throwable caught) {
createErrorPage("Could not obtain a race with name " + raceColumnName + " for fleet "+fleetName+" for a regatta with name " + regattaLikeName+
": "+caught.getMessage());
}
@Override
public void onSuccess(final RegattaAndRaceIdentifier selectedRaceIdentifier) {
if (selectedRaceIdentifier == null) {
createErrorPage("Could not obtain a race with name " + raceColumnName + " for fleet "+fleetName+" for a regatta with name " + regattaLikeName);
} else {
final StringBuilder title = new StringBuilder(regattaLikeName);
title.append('/');
title.append(raceColumnName);
if (!fleetName.equals(LeaderboardNameConstants.DEFAULT_FLEET_NAME)) {
title.append('/');
title.append(fleetName);
}
Window.setTitle(title.toString());
final RaceSelectionModel raceSelectionModel = new RaceSelectionModel();
final List<RegattaAndRaceIdentifier> raceList = Collections.singletonList(selectedRaceIdentifier);
raceSelectionModel.setSelection(raceList);
final long refreshInterval = Duration.ONE_SECOND.times(3).asMillis();
final Timer timer = new Timer(PlayModes.Live);
AsyncActionsExecutor asyncActionsExecutor = new AsyncActionsExecutor();
final TimeRangeWithZoomProvider timeRangeWithZoomProvider = new TimeRangeWithZoomModel();
// Use a TimePanel to manage wind chart zoom, although the TimePanel itself is not being displayed;
// let the time panel always return to "live" mode if the user wants that
final TimePanel<TimePanelSettings> timePanel = new TimePanel<TimePanelSettings>(
timer, timeRangeWithZoomProvider, getStringMessages(), /* canReplayWhileLive */ false) {
protected boolean isLiveModeToBeMadePossible() {
return true;
}
};
final Button backToLivePlayButton = timePanel.getBackToLiveButton();
final TimePanelSettings timePanelSettings = timePanel.getSettings();
timePanelSettings.setRefreshInterval(refreshInterval);
timePanel.updateSettings(timePanelSettings);
raceMapResources.combinedWindPanelStyle().ensureInjected();
final CompetitorSelectionProvider competitorSelection = createEmptyFilterCompetitorModel(); // show no competitors
final RaceMap raceMap = new RaceMap(sailingService, asyncActionsExecutor, /* errorReporter */ EmbeddedMapAndWindChartEntryPoint.this, timer,
competitorSelection, getStringMessages(), showMapControls, showViewStreamlets,
showViewSimulation, selectedRaceIdentifier, raceMapResources.combinedWindPanelStyle(), /* showHeaderPanel */ false) {
@Override
protected void showAdditionalControls(MapWidget map) {
backToLivePlayButton.removeFromParent();
map.setControls(ControlPosition.RIGHT_BOTTOM, backToLivePlayButton);
}
};
final RaceMapSettings mapSettings = new RaceMapSettings(raceMap.getSettings());
mapSettings.setZoomSettings(new RaceMapZoomSettings(Arrays.asList(ZoomTypes.BUOYS), /* zoom to selection */ false));
Set<HelpLineTypes> helpLineTypes = new HashSet<>();
Util.addAll(mapSettings.getHelpLinesSettings().getVisibleHelpLineTypes(), helpLineTypes);
helpLineTypes.add(HelpLineTypes.COURSEGEOMETRY);
mapSettings.setHelpLinesSettings(new RaceMapHelpLinesSettings(helpLineTypes));
mapSettings.setWindUp(true);
raceMap.updateSettings(mapSettings);
raceMap.onRaceSelectionChange(raceList);
final WindChart windChart;
if (showWindChart) {
windChart = new WindChart(sailingService, raceSelectionModel, timer,
timeRangeWithZoomProvider, new WindChartSettings(), getStringMessages(),
asyncActionsExecutor, /* errorReporter */
EmbeddedMapAndWindChartEntryPoint.this, /* compactChart */ true);
windChart.onRaceSelectionChange(raceList);
} else {
windChart = null;
}
createRaceBoardInOneScreenMode(raceMap, windChart);
}
}
});
}
private CompetitorSelectionProvider createEmptyFilterCompetitorModel() {
final CompetitorSelectionModel result = new CompetitorSelectionModel(/* hasMultiSelection */ true);
final FilterSet<CompetitorDTO, Filter<CompetitorDTO>> filterSet = result.getOrCreateCompetitorsFilterSet("Empty");
filterSet.addFilter(new Filter<CompetitorDTO>() {
@Override public boolean matches(CompetitorDTO object) { return false; }
@Override public String getName() { return "Never matching filter"; }
});
return result;
}
private void createRaceBoardInOneScreenMode(final RaceMap raceMap, final WindChart windChart) {
final TouchSplitLayoutPanel p = new TouchSplitLayoutPanel(/* horizontal splitter width */ 3, /* vertical splitter height */ 25);
RootLayoutPanel.get().add(p);
if (windChart != null) {
windChart.setVisible(true);
p.insert(windChart.getEntryWidget(), windChart, Direction.SOUTH, DEFAULT_WIND_CHART_HEIGHT);
p.setWidgetVisibility(windChart.getEntryWidget(), windChart, /* hidden */ false, DEFAULT_WIND_CHART_HEIGHT);
}
p.insert(raceMap.getEntryWidget(), raceMap, Direction.CENTER, 400);
p.addStyleName("dockLayoutPanel");
}
}
@@ -17,7 +17,6 @@ import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootLayoutPanel; import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.dto.RaceDTO; import com.sap.sailing.domain.common.dto.RaceDTO;
import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint; import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint;
@@ -138,10 +137,12 @@ public class RaceBoardEntryPoint extends AbstractSailingEntryPoint {
} }
private void createErrorPage(String message) { private void createErrorPage(String message) {
final DockLayoutPanel vp = new DockLayoutPanel(Unit.PX);
LogoAndTitlePanel logoAndTitlePanel = new LogoAndTitlePanel(getStringMessages(), this, getUserService()); LogoAndTitlePanel logoAndTitlePanel = new LogoAndTitlePanel(getStringMessages(), this, getUserService());
logoAndTitlePanel.addStyleName("LogoAndTitlePanel"); logoAndTitlePanel.addStyleName("LogoAndTitlePanel");
RootPanel.get().add(logoAndTitlePanel); RootLayoutPanel.get().add(vp);
RootPanel.get().add(new Label(message)); vp.addNorth(logoAndTitlePanel, 100);
vp.add(new Label(message));
} }
private void checkUrlParameters(List<String> leaderboardNames, LeaderboardGroupDTO leaderboardGroup, private void checkUrlParameters(List<String> leaderboardNames, LeaderboardGroupDTO leaderboardGroup,
@@ -194,7 +195,6 @@ public class RaceBoardEntryPoint extends AbstractSailingEntryPoint {
RaceTimesInfoProvider raceTimesInfoProvider = new RaceTimesInfoProvider(sailingService, asyncActionsExecutor, this, singletonList, 5000l /* requestInterval*/); RaceTimesInfoProvider raceTimesInfoProvider = new RaceTimesInfoProvider(sailingService, asyncActionsExecutor, this, singletonList, 5000l /* requestInterval*/);
RaceBoardPanel raceBoardPanel = new RaceBoardPanel(sailingService, mediaService, getUserService(), asyncActionsExecutor, timer, raceSelectionModel, RaceBoardPanel raceBoardPanel = new RaceBoardPanel(sailingService, mediaService, getUserService(), asyncActionsExecutor, timer, raceSelectionModel,
leaderboardName, leaderboardGroupName, event, raceboardViewConfig, RaceBoardEntryPoint.this, getStringMessages(), userAgent, raceTimesInfoProvider, showMapControls); leaderboardName, leaderboardGroupName, event, raceboardViewConfig, RaceBoardEntryPoint.this, getStringMessages(), userAgent, raceTimesInfoProvider, showMapControls);
raceBoardPanel.fillRegattas(regattas);
createRaceBoardInOneScreenMode(raceBoardPanel, raceboardViewConfig); createRaceBoardInOneScreenMode(raceBoardPanel, raceboardViewConfig);
} }
@@ -35,7 +35,6 @@ import com.sap.sailing.gwt.ui.client.RaceSelectionChangeListener;
import com.sap.sailing.gwt.ui.client.RaceSelectionProvider; import com.sap.sailing.gwt.ui.client.RaceSelectionProvider;
import com.sap.sailing.gwt.ui.client.RaceTimePanel; import com.sap.sailing.gwt.ui.client.RaceTimePanel;
import com.sap.sailing.gwt.ui.client.RaceTimesInfoProvider; import com.sap.sailing.gwt.ui.client.RaceTimesInfoProvider;
import com.sap.sailing.gwt.ui.client.RegattasDisplayer;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.media.MediaPlayerManagerComponent; import com.sap.sailing.gwt.ui.client.media.MediaPlayerManagerComponent;
@@ -54,7 +53,6 @@ import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel;
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings;
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettingsFactory; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettingsFactory;
import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sse.common.filter.FilterSet; import com.sap.sse.common.filter.FilterSet;
import com.sap.sse.common.settings.AbstractSettings; import com.sap.sse.common.settings.AbstractSettings;
import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.ErrorReporter;
@@ -77,7 +75,7 @@ import com.sap.sse.security.ui.client.UserService;
* @author Frank Mittag, Axel Uhl (d043530) * @author Frank Mittag, Axel Uhl (d043530)
* *
*/ */
public class RaceBoardPanel extends SimplePanel implements RegattasDisplayer, RaceSelectionChangeListener, LeaderboardUpdateListener, PopupPositionProvider { public class RaceBoardPanel extends SimplePanel implements RaceSelectionChangeListener, LeaderboardUpdateListener, PopupPositionProvider {
private final SailingServiceAsync sailingService; private final SailingServiceAsync sailingService;
private final MediaServiceAsync mediaService; private final MediaServiceAsync mediaService;
private final EventDTO event; private final EventDTO event;
@@ -86,11 +84,6 @@ public class RaceBoardPanel extends SimplePanel implements RegattasDisplayer, Ra
private final RaceBoardViewConfiguration raceboardViewConfiguration; private final RaceBoardViewConfiguration raceboardViewConfiguration;
private String raceBoardName; private String raceBoardName;
/**
* Updated upon each {@link #fillRegattas(List)}
*/
private final Map<RaceIdentifier, RaceDTO> racesByIdentifier;
private final List<ComponentViewer> componentViewers; private final List<ComponentViewer> componentViewers;
private RaceTimePanel timePanel; private RaceTimePanel timePanel;
private final Timer timer; private final Timer timer;
@@ -146,7 +139,6 @@ public class RaceBoardPanel extends SimplePanel implements RegattasDisplayer, Ra
this.currentRaceHasBeenSelectedOnce = false; this.currentRaceHasBeenSelectedOnce = false;
this.leaderboardName = leaderboardName; this.leaderboardName = leaderboardName;
raceSelectionProvider.addRaceSelectionChangeListener(this); raceSelectionProvider.addRaceSelectionChangeListener(this);
racesByIdentifier = new HashMap<RaceIdentifier, RaceDTO>();
selectedRaceIdentifier = raceSelectionProvider.getSelectedRaces().iterator().next(); selectedRaceIdentifier = raceSelectionProvider.getSelectedRaces().iterator().next();
this.setRaceBoardName(selectedRaceIdentifier.getRaceName()); this.setRaceBoardName(selectedRaceIdentifier.getRaceName());
this.asyncActionsExecutor = asyncActionsExecutor; this.asyncActionsExecutor = asyncActionsExecutor;
@@ -163,7 +155,8 @@ public class RaceBoardPanel extends SimplePanel implements RegattasDisplayer, Ra
raceMapResources.combinedWindPanelStyle().ensureInjected(); raceMapResources.combinedWindPanelStyle().ensureInjected();
raceMap = new RaceMap(sailingService, asyncActionsExecutor, errorReporter, timer, raceMap = new RaceMap(sailingService, asyncActionsExecutor, errorReporter, timer,
competitorSelectionModel, stringMessages, showMapControls, getConfiguration().isShowViewStreamlets(), getConfiguration().isShowViewSimulation(), selectedRaceIdentifier, raceMapResources.combinedWindPanelStyle()); competitorSelectionModel, stringMessages, showMapControls, getConfiguration().isShowViewStreamlets(), getConfiguration().isShowViewSimulation(),
selectedRaceIdentifier, raceMapResources.combinedWindPanelStyle(), /* showHeaderPanel */ true);
CompetitorFilterPanel competitorSearchTextBox = new CompetitorFilterPanel(competitorSelectionModel, stringMessages, raceMap, CompetitorFilterPanel competitorSearchTextBox = new CompetitorFilterPanel(competitorSelectionModel, stringMessages, raceMap,
new LeaderboardFetcher() { new LeaderboardFetcher() {
@Override @Override
@@ -336,18 +329,6 @@ public class RaceBoardPanel extends SimplePanel implements RegattasDisplayer, Ra
return errorReporter; return errorReporter;
} }
@Override
public void fillRegattas(Iterable<RegattaDTO> regattas) {
racesByIdentifier.clear();
for (RegattaDTO regatta : regattas) {
for (RaceDTO race : regatta.races) {
if (race != null && race.getRaceIdentifier() != null) {
racesByIdentifier.put(race.getRaceIdentifier(), race);
}
}
}
}
@Override @Override
public void onRaceSelectionChange(List<RegattaAndRaceIdentifier> selectedRaces) { public void onRaceSelectionChange(List<RegattaAndRaceIdentifier> selectedRaces) {
} }
@@ -772,7 +772,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
private MarkDTO convertToMarkDTO(Mark mark, Position position) { private MarkDTO convertToMarkDTO(Mark mark, Position position) {
MarkDTO markDTO; MarkDTO markDTO;
if(position != null) { if (position != null) {
markDTO = new MarkDTO(mark.getId().toString(), mark.getName(), position.getLatDeg(), position.getLngDeg()); markDTO = new MarkDTO(mark.getId().toString(), mark.getName(), position.getLatDeg(), position.getLngDeg());
} else { } else {
markDTO = new MarkDTO(mark.getId().toString(), mark.getName()); markDTO = new MarkDTO(mark.getId().toString(), mark.getName());
@@ -902,7 +902,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
CourseBase lastCourse = state.getCourseDesign(); CourseBase lastCourse = state.getCourseDesign();
if (lastCourse != null) { if (lastCourse != null) {
raceInfoDTO.lastCourseDesign = convertCourseDesignToRaceCourseDTO(lastCourse); raceInfoDTO.lastCourseDesign = convertToRaceCourseDTO(lastCourse, /* trackedRace */ null, /* timePoint */ null);
raceInfoDTO.lastCourseName = lastCourse.getName(); raceInfoDTO.lastCourseName = lastCourse.getName();
} }
@@ -952,20 +952,6 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
raceInfoDTO.startProcedureDTO = info; raceInfoDTO.startProcedureDTO = info;
} }
private RaceCourseDTO convertCourseDesignToRaceCourseDTO(CourseBase lastCourseDesign) {
RaceCourseDTO result = new RaceCourseDTO(Collections.<WaypointDTO> emptyList());
if (lastCourseDesign != null) {
List<WaypointDTO> waypointDTOs = new ArrayList<WaypointDTO>();
for (Waypoint waypoint : lastCourseDesign.getWaypoints()) {
ControlPointDTO controlPointDTO = convertToControlPointDTO(waypoint.getControlPoint());
WaypointDTO waypointDTO = new WaypointDTO(waypoint.getName(), controlPointDTO, waypoint.getPassingInstructions());
waypointDTOs.add(waypointDTO);
}
result = new RaceCourseDTO(waypointDTOs);
}
return result;
}
private List<RaceWithCompetitorsDTO> convertToRaceDTOs(Regatta regatta) { private List<RaceWithCompetitorsDTO> convertToRaceDTOs(Regatta regatta) {
List<RaceWithCompetitorsDTO> result = new ArrayList<RaceWithCompetitorsDTO>(); List<RaceWithCompetitorsDTO> result = new ArrayList<RaceWithCompetitorsDTO>();
for (RaceDefinition r : regatta.getAllRaces()) { for (RaceDefinition r : regatta.getAllRaces()) {
@@ -1864,6 +1850,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
result.totalLegsCount = trackedRace.getRace().getCourse().getLegs().size(); result.totalLegsCount = trackedRace.getRace().getCourse().getLegs().size();
result.currentLegNumber = trackedRace.getLastLegStarted(dateAsTimePoint); result.currentLegNumber = trackedRace.getLastLegStarted(dateAsTimePoint);
result.marks = new HashSet<MarkDTO>(); result.marks = new HashSet<MarkDTO>();
result.course = convertToRaceCourseDTO(trackedRace.getRace().getCourse(), trackedRace, dateAsTimePoint);
// now make sure we don't duplicate the MarkDTO objects but instead use the ones from the RaceCourseDTO
// object and amend them with the Position
result.waypointPositions = new ArrayList<>(); result.waypointPositions = new ArrayList<>();
Set<Mark> marks = new HashSet<Mark>(); Set<Mark> marks = new HashSet<Mark>();
Course course = trackedRace.getRace().getCourse(); Course course = trackedRace.getRace().getCourse();
@@ -1876,11 +1865,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
marks.add(b); marks.add(b);
} }
} }
for (Mark mark : marks) { for (final WaypointDTO waypointDTO : result.course.waypoints) {
GPSFixTrack<Mark, GPSFix> track = trackedRace.getOrCreateTrack(mark); for (final MarkDTO markDTO : waypointDTO.controlPoint.getMarks()) {
Position positionAtDate = track.getEstimatedPosition(dateAsTimePoint, /* extrapolate */false); if (markDTO.position != null) {
if (positionAtDate != null) { result.marks.add(markDTO);
result.marks.add(convertToMarkDTO(mark, positionAtDate)); }
} }
} }
@@ -1889,8 +1878,6 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
if (firstWaypoint != null && Util.size(firstWaypoint.getMarks()) == 2) { if (firstWaypoint != null && Util.size(firstWaypoint.getMarks()) == 2) {
final LineDetails markPositionDTOsAndLineAdvantage = trackedRace.getStartLine(dateAsTimePoint); final LineDetails markPositionDTOsAndLineAdvantage = trackedRace.getStartLine(dateAsTimePoint);
if (markPositionDTOsAndLineAdvantage != null) { if (markPositionDTOsAndLineAdvantage != null) {
final List<Position> startMarkPositionDTOs = getMarkPositionDTOs(dateAsTimePoint, trackedRace, firstWaypoint);
result.startMarkPositions = startMarkPositionDTOs;
result.startLineLengthInMeters = markPositionDTOsAndLineAdvantage.getLength().getMeters(); result.startLineLengthInMeters = markPositionDTOsAndLineAdvantage.getLength().getMeters();
Bearing absoluteAngleDifferenceToTrueWind = markPositionDTOsAndLineAdvantage Bearing absoluteAngleDifferenceToTrueWind = markPositionDTOsAndLineAdvantage
.getAbsoluteAngleDifferenceToTrueWind(); .getAbsoluteAngleDifferenceToTrueWind();
@@ -1906,8 +1893,6 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
if (lastWaypoint != null && Util.size(lastWaypoint.getMarks()) == 2) { if (lastWaypoint != null && Util.size(lastWaypoint.getMarks()) == 2) {
final LineDetails markPositionDTOsAndLineAdvantage = trackedRace.getFinishLine(dateAsTimePoint); final LineDetails markPositionDTOsAndLineAdvantage = trackedRace.getFinishLine(dateAsTimePoint);
if (markPositionDTOsAndLineAdvantage != null) { if (markPositionDTOsAndLineAdvantage != null) {
final List<Position> finishMarkPositionDTOs = getMarkPositionDTOs(dateAsTimePoint, trackedRace, lastWaypoint);
result.finishMarkPositions = finishMarkPositionDTOs;
result.finishLineLengthInMeters = markPositionDTOsAndLineAdvantage.getLength().getMeters(); result.finishLineLengthInMeters = markPositionDTOsAndLineAdvantage.getLength().getMeters();
Bearing absoluteAngleDifferenceToTrueWind = markPositionDTOsAndLineAdvantage Bearing absoluteAngleDifferenceToTrueWind = markPositionDTOsAndLineAdvantage
.getAbsoluteAngleDifferenceToTrueWind(); .getAbsoluteAngleDifferenceToTrueWind();
@@ -1952,32 +1937,22 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
private ControlPointDTO convertToControlPointDTO(ControlPoint controlPoint, TrackedRace trackedRace, TimePoint timePoint) { private ControlPointDTO convertToControlPointDTO(ControlPoint controlPoint, TrackedRace trackedRace, TimePoint timePoint) {
ControlPointDTO result; ControlPointDTO result;
final TimePoint timePointToUse = trackedRace == null ? null :
timePoint == null ? MillisecondsTimePoint.now().minus(trackedRace.getDelayToLiveInMillis()) : timePoint;
if (controlPoint instanceof ControlPointWithTwoMarks) { if (controlPoint instanceof ControlPointWithTwoMarks) {
final Mark left = ((ControlPointWithTwoMarks) controlPoint).getLeft(); final Mark left = ((ControlPointWithTwoMarks) controlPoint).getLeft();
final Position leftPos = trackedRace.getOrCreateTrack(left).getEstimatedPosition(timePoint, /* extrapolate */ false); final Position leftPos = timePointToUse == null ? null : trackedRace.getOrCreateTrack(left).getEstimatedPosition(timePointToUse, /* extrapolate */ false);
final Mark right = ((ControlPointWithTwoMarks) controlPoint).getRight(); final Mark right = ((ControlPointWithTwoMarks) controlPoint).getRight();
final Position rightPos = trackedRace.getOrCreateTrack(right).getEstimatedPosition(timePoint, /* extrapolate */ false); final Position rightPos = timePointToUse == null ? null : trackedRace.getOrCreateTrack(right).getEstimatedPosition(timePointToUse, /* extrapolate */ false);
result = new GateDTO(controlPoint.getId().toString(), controlPoint.getName(), convertToMarkDTO(left, leftPos), convertToMarkDTO(right, rightPos)); result = new GateDTO(controlPoint.getId().toString(), controlPoint.getName(), convertToMarkDTO(left, leftPos), convertToMarkDTO(right, rightPos));
} else { } else {
final Position posOfFirst = trackedRace.getOrCreateTrack(controlPoint.getMarks().iterator().next()). final Position posOfFirst = timePointToUse == null ? null : trackedRace.getOrCreateTrack(controlPoint.getMarks().iterator().next()).
getEstimatedPosition(timePoint, /* extrapolate */ false); getEstimatedPosition(timePointToUse, /* extrapolate */ false);
result = new MarkDTO(controlPoint.getId().toString(), controlPoint.getName(), posOfFirst == null ? -1 : posOfFirst.getLatDeg(), posOfFirst == null ? -1 : posOfFirst.getLngDeg()); result = new MarkDTO(controlPoint.getId().toString(), controlPoint.getName(), posOfFirst == null ? -1 : posOfFirst.getLatDeg(), posOfFirst == null ? -1 : posOfFirst.getLngDeg());
} }
return result; return result;
} }
private ControlPointDTO convertToControlPointDTO(ControlPoint controlPoint) {
ControlPointDTO result;
if (controlPoint instanceof ControlPointWithTwoMarks) {
final Mark left = ((ControlPointWithTwoMarks) controlPoint).getLeft();
final Mark right = ((ControlPointWithTwoMarks) controlPoint).getRight();
result = new GateDTO(controlPoint.getId().toString(), controlPoint.getName(), convertToMarkDTO(left, null), convertToMarkDTO(right, null));
} else {
result = new MarkDTO(controlPoint.getId().toString(), controlPoint.getName());
}
return result;
}
private ControlPoint getOrCreateControlPoint(ControlPointDTO dto) { private ControlPoint getOrCreateControlPoint(ControlPointDTO dto) {
String idAsString = dto.getIdAsString(); String idAsString = dto.getIdAsString();
if (idAsString == null) { if (idAsString == null) {
@@ -2017,19 +1992,6 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
} }
} }
private List<Position> getMarkPositionDTOs(
TimePoint timePoint, TrackedRace trackedRace, Waypoint waypoint) {
List<Position> markPositionDTOs = new ArrayList<>();
for (Mark startMark : waypoint.getMarks()) {
final Position estimatedMarkPosition = trackedRace.getOrCreateTrack(startMark)
.getEstimatedPosition(timePoint, /* extrapolate */false);
if (estimatedMarkPosition != null) {
markPositionDTOs.add(estimatedMarkPosition);
}
}
return markPositionDTOs;
}
/** /**
* @param timePoint * @param timePoint
* <code>null</code> means "live" and is then replaced by "now" minus the tracked race's * <code>null</code> means "live" and is then replaced by "now" minus the tracked race's
@@ -4041,7 +4003,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
Map<String, List<RegattaOverviewEntryDTO>> entriesPerFleet = new HashMap<String, List<RegattaOverviewEntryDTO>>(); Map<String, List<RegattaOverviewEntryDTO>> entriesPerFleet = new HashMap<String, List<RegattaOverviewEntryDTO>>();
for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { for (RaceColumn raceColumn : leaderboard.getRaceColumns()) {
getRegattaOverviewEntries(showOnlyRacesOfSameDay, dayToCheck, usedCourseArea, getRegattaOverviewEntries(showOnlyRacesOfSameDay, dayToCheck, usedCourseArea,
leaderboard, boatClass.getName(), regattaName, LeaderboardNameConstants.DEFAULT_SERIES_NAME, raceColumn, entriesPerFleet); leaderboard, boatClass == null ? "" : boatClass.getName(), regattaName, LeaderboardNameConstants.DEFAULT_SERIES_NAME, raceColumn, entriesPerFleet);
} }
result.addAll(getRegattaOverviewEntriesToBeShown(showOnlyCurrentlyRunningRaces, entriesPerFleet)); result.addAll(getRegattaOverviewEntriesToBeShown(showOnlyCurrentlyRunningRaces, entriesPerFleet));
} }
@@ -5090,36 +5052,56 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
raceLog.add(event); raceLog.add(event);
} }
private WaypointDTO convertToWaypointDTO(Waypoint waypoint, Map<Serializable, ControlPointDTO> controlPointCache) { /**
* @param trackedRace
* if <code>null</code>, no position data will be attached to the {@link MarkDTO}s
* @param timePoint
* if <code>trackedRace</code> is not <code>null</code>, specifies the time point for which to determine
* the mark positions and attach to the {@link MarkDTO}s. If <code>null<c/code>, the current time point
* will be used as default.
*/
private WaypointDTO convertToWaypointDTO(Waypoint waypoint, Map<Serializable, ControlPointDTO> controlPointCache, TrackedRace trackedRace, TimePoint timePoint) {
ControlPointDTO cp = controlPointCache.get(waypoint.getControlPoint().getId()); ControlPointDTO cp = controlPointCache.get(waypoint.getControlPoint().getId());
if (cp == null) { if (cp == null) {
cp = convertToControlPointDTO(waypoint.getControlPoint()); cp = convertToControlPointDTO(waypoint.getControlPoint(), trackedRace, timePoint);
controlPointCache.put(waypoint.getControlPoint().getId(), cp); controlPointCache.put(waypoint.getControlPoint().getId(), cp);
} }
return new WaypointDTO(waypoint.getName(), cp, waypoint.getPassingInstructions()); return new WaypointDTO(waypoint.getName(), cp, waypoint.getPassingInstructions());
} }
private RaceCourseDTO convertToRaceCourseDTO(CourseBase course) { /**
List<WaypointDTO> waypointDTOs = new ArrayList<WaypointDTO>(); * @param course
Map<Serializable, ControlPointDTO> controlPointCache = new HashMap<>(); * the course to convert
RaceCourseDTO result = new RaceCourseDTO(waypointDTOs); * @param trackedRace
for (Waypoint waypoint : course.getWaypoints()) { * if <code>null</code>, no position data will be attached to the {@link MarkDTO}s
waypointDTOs.add(convertToWaypointDTO(waypoint, controlPointCache)); * @param timePoint
* if <code>trackedRace</code> is not <code>null</code>, specifies the time point for which to determine
* the mark positions and attach to the {@link MarkDTO}s. If <code>null<c/code>, the current time point
* will be used as default.
*/
private RaceCourseDTO convertToRaceCourseDTO(CourseBase course, TrackedRace trackedRace, TimePoint timePoint) {
final RaceCourseDTO result;
if (course != null) {
List<WaypointDTO> waypointDTOs = new ArrayList<WaypointDTO>();
Map<Serializable, ControlPointDTO> controlPointCache = new HashMap<>();
for (Waypoint waypoint : course.getWaypoints()) {
waypointDTOs.add(convertToWaypointDTO(waypoint, controlPointCache, trackedRace, timePoint));
}
result = new RaceCourseDTO(waypointDTOs);
} else {
result = new RaceCourseDTO(Collections.<WaypointDTO> emptyList());
} }
return result; return result;
} }
@Override @Override
public RaceCourseDTO getLastCourseDefinitionInRaceLog(String leaderboardName, String raceColumnName, public RaceCourseDTO getLastCourseDefinitionInRaceLog(String leaderboardName, String raceColumnName, String fleetName) {
String fleetName) {
RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName);
CourseBase lastPublishedCourse = new LastPublishedCourseDesignFinder(raceLog).analyze(); CourseBase lastPublishedCourse = new LastPublishedCourseDesignFinder(raceLog).analyze();
if (lastPublishedCourse == null) { if (lastPublishedCourse == null) {
lastPublishedCourse = new CourseDataImpl(""); lastPublishedCourse = new CourseDataImpl("");
} }
return convertToRaceCourseDTO(lastPublishedCourse, /* trackedRace */ null, /* timePoint */ null);
return convertToRaceCourseDTO(lastPublishedCourse);
} }
@Override @Override
@@ -5765,4 +5747,23 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
return true; return true;
} }
} }
@Override
public RegattaAndRaceIdentifier getRaceIdentifier(String regattaLikeName, String raceColumnName, String fleetName) {
RegattaAndRaceIdentifier result = null;
final Leaderboard leaderboard = getService().getLeaderboardByName(regattaLikeName);
if (leaderboard != null) {
final RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName);
if (raceColumn != null) {
final Fleet fleet = raceColumn.getFleetByName(fleetName);
if (fleet != null) {
final TrackedRace trackedRace = raceColumn.getTrackedRace(fleet);
if (trackedRace != null) {
result = trackedRace.getRaceIdentifier();
}
}
}
}
return result;
}
} }
@@ -1,5 +1,6 @@
package com.sap.sailing.gwt.ui.shared; package com.sap.sailing.gwt.ui.shared;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@@ -8,9 +9,8 @@ import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.Position;
public class CoursePositionsDTO implements IsSerializable { public class CoursePositionsDTO implements IsSerializable {
public RaceCourseDTO course;
public List<Position> waypointPositions; public List<Position> waypointPositions;
public List<Position> startMarkPositions;
public List<Position> finishMarkPositions;
public Set<MarkDTO> marks; public Set<MarkDTO> marks;
public int totalLegsCount; public int totalLegsCount;
@@ -35,4 +35,24 @@ public class CoursePositionsDTO implements IsSerializable {
public NauticalSide finishLineAdvantageousSide; public NauticalSide finishLineAdvantageousSide;
public Double finishLineAdvantageInMeters; public Double finishLineAdvantageInMeters;
public Double finishLineLengthInMeters; public Double finishLineLengthInMeters;
public List<Position> getStartMarkPositions() {
final List<Position> result = new ArrayList<>();
if (course != null && course.waypoints != null && !course.waypoints.isEmpty()) {
for (final MarkDTO mark : course.waypoints.get(0).controlPoint.getMarks()) {
result.add(mark.position);
}
}
return result;
}
public List<Position> getFinishMarkPositions() {
final List<Position> result = new ArrayList<>();
if (course != null && course.waypoints != null && !course.waypoints.isEmpty()) {
for (final MarkDTO mark : course.waypoints.get(course.waypoints.size()-1).controlPoint.getMarks()) {
result.add(mark.position);
}
}
return result;
}
} }
@@ -27,4 +27,45 @@ public class GateDTO extends ControlPointDTO {
public Iterable<MarkDTO> getMarks() { public Iterable<MarkDTO> getMarks() {
return Arrays.asList(left, right); return Arrays.asList(left, right);
} }
@Override
public int hashCode() {
final int prime = 31;
int result = prime * getIdAsString().hashCode() * getName().hashCode();
result = prime * result + ((left == null) ? 0 : left.hashCode());
result = prime * result + ((right == null) ? 0 : right.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (getClass() != obj.getClass())
return false;
GateDTO other = (GateDTO) obj;
if (getIdAsString() == null) {
if (other.getIdAsString() != null)
return false;
} else if (!getIdAsString().equals(other.getIdAsString()))
return false;
if (getName() == null) {
if (other.getName() != null)
return false;
} else if (!getName().equals(other.getName()))
return false;
if (left == null) {
if (other.left != null)
return false;
} else if (!left.equals(other.left))
return false;
if (right == null) {
if (other.right != null)
return false;
} else if (!right.equals(other.right))
return false;
return true;
}
} }
@@ -3,6 +3,7 @@ package com.sap.sailing.gwt.ui.shared;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -21,7 +22,21 @@ public class RaceCourseDTO implements IsSerializable {
} }
public RaceCourseDTO(List<WaypointDTO> waypoints) { public RaceCourseDTO(List<WaypointDTO> waypoints) {
this(waypoints, null); this(waypoints, getMarksFromWaypoints(waypoints));
}
private static List<MarkDTO> getMarksFromWaypoints(List<WaypointDTO> waypoints) {
final LinkedHashSet<MarkDTO> marks = new LinkedHashSet<>();
for (final WaypointDTO waypoint : waypoints) {
for (final MarkDTO m : waypoint.controlPoint.getMarks()) {
marks.add(m);
}
}
final List<MarkDTO> result = new ArrayList<>();
for (final MarkDTO m : marks) {
result.add(m);
}
return result;
} }
public RaceCourseDTO(List<WaypointDTO> waypoints, List<MarkDTO> allMarks) { public RaceCourseDTO(List<WaypointDTO> waypoints, List<MarkDTO> allMarks) {
@@ -181,6 +181,7 @@ public class RaceContext {
case FINISHING: case FINISHING:
case RUNNING: case RUNNING:
case SCHEDULED: case SCHEDULED:
case PRESCHEDULED:
case STARTPHASE: case STARTPHASE:
case UNKNOWN: case UNKNOWN:
break; break;
@@ -26,7 +26,7 @@ public class SimpleCompetitorDTO extends NamedDTO implements Serializable {
final Nationality nationality = competitor.getTeam().getNationality(); final Nationality nationality = competitor.getTeam().getNationality();
CountryCode countryCode = nationality == null ? null : nationality.getCountryCode(); CountryCode countryCode = nationality == null ? null : nationality.getCountryCode();
this.sailID = competitor.getBoat().getSailID(); this.sailID = competitor.getBoat().getSailID();
this.twoLetterIsoCountryCode = countryCode.getTwoLetterISOCode(); this.twoLetterIsoCountryCode = countryCode == null ? null : countryCode.getTwoLetterISOCode();
this.flagImageURL = competitor.getFlagImage() == null ? null : competitor.getFlagImage().toString(); this.flagImageURL = competitor.getFlagImage() == null ? null : competitor.getFlagImage().toString();
} }
@@ -360,7 +360,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
this.replayPathCanvasOverlays = null; this.replayPathCanvasOverlays = null;
this.raceCourseCanvasOverlay = null; this.raceCourseCanvasOverlay = null;
this.timeListeners = new LinkedList<TimeListenerWithStoppingCriteria>(); this.timeListeners = new LinkedList<TimeListenerWithStoppingCriteria>();
this.initializeData(showMapControls); this.initializeData(showMapControls, /* showHeaderPanel */ true);
this.parent = parent; this.parent = parent;
} }
@@ -1000,7 +1000,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
} }
@Override @Override
public void initializeData(boolean showMapControls) { public void initializeData(boolean showMapControls, boolean showHeaderPanel) {
loadMapsAPIV3(); loadMapsAPIV3();
} }
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.7.0//EN" "http://gwtproject.org/doctype/2.7.0/gwt-module.dtd">
<module>
<inherits name='com.sap.sailing.gwt.ui.CommonConfigs'/>
<!-- Other module inherits -->
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sse.SSECommon" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sse.gwt.AdminConsole" />
<inherits name="com.sap.sse.security.ui.LoginPanel" />
<!-- Google Maps API -->
<inherits name='com.google.gwt.ajaxloader.AjaxLoader' />
<inherits name='com.google.gwt.maps.Maps' />
<!-- Highcharts API -->
<inherits name="com.sap.sse.gwt.Highcharts_Autoinject" />
<!-- Bootstrap API -->
<inherits name="com.github.gwtbootstrap.BootstrapNoResources" />
<inherits name='com.github.gwtbootstrap.datetimepicker.DatetimepickerNoResources' />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.raceboard.EmbeddedMapAndWindChartEntryPoint'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<extend-property name="locale" values="ru"/>
<inherits name='com.sap.sailing.gwt.ui.SourceCommon' />
<inherits name='com.sap.sailing.gwt.ui.SourceClient' />
<inherits name='com.sap.sailing.gwt.ui.SourceShared' />
<inherits name='com.sap.sailing.gwt.ui.SourceControl' />
<inherits name="com.sap.sailing.gwt.ui.SourceRaceboard"/>
<inherits name="com.sap.sailing.gwt.ui.SourceLeaderboard" />
<inherits name="com.sap.sailing.gwt.ui.SourceAdminConsole" />
<inherits name='com.sap.sse.gwt.CommonControlCSS_Autoinject'/>
</module>
@@ -43,7 +43,7 @@ public class Manage2SailEventResultsParserImpl implements Manage2SailEventResult
result.setName((String) jsonRoot.get("Name")); result.setName((String) jsonRoot.get("Name"));
result.setXrrUrl(parseURL(jsonRoot, "XrrUrl")); result.setXrrUrl(parseURL(jsonRoot, "XrrUrl"));
JSONObject jsonTracking = (JSONObject) jsonRoot.get("Tracking"); JSONObject jsonTracking = (JSONObject) jsonRoot.get("Tracking");
if(jsonTracking != null) { if (jsonTracking != null) {
result.setTrackingDataHost((String) jsonTracking.get("Host")); result.setTrackingDataHost((String) jsonTracking.get("Host"));
result.setTrackingDataPort(parseInteger(jsonTracking, "Port")); result.setTrackingDataPort(parseInteger(jsonTracking, "Port"));
} }
@@ -45,6 +45,7 @@ import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.HasValue; import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.RequiresResize; import com.google.gwt.user.client.ui.RequiresResize;
import com.sap.sse.common.Util;
/** /**
* A widget that allows the user to select a value within a range of possible values using a sliding bar that responds * A widget that allows the user to select a value within a range of possible values using a sliding bar that responds
@@ -704,9 +705,10 @@ public class SliderBar extends FocusPanel implements RequiresResize, HasValue<Do
* the current value * the current value
*/ */
public void setMaxValue(Double maxValue, boolean fireEvent) { public void setMaxValue(Double maxValue, boolean fireEvent) {
this.maxValue = maxValue; if (!Util.equalsWithNull(maxValue, this.maxValue)) {
drawTickLabels(); this.maxValue = maxValue;
resetCurrentValue(fireEvent); onMinMaxValueChanged(fireEvent);
}
} }
/** /**
@@ -716,8 +718,40 @@ public class SliderBar extends FocusPanel implements RequiresResize, HasValue<Do
* the current value * the current value
*/ */
public void setMinValue(Double minValue, boolean fireEvent) { public void setMinValue(Double minValue, boolean fireEvent) {
this.minValue = minValue; if (!Util.equalsWithNull(minValue, this.minValue)) {
drawTickLabels(); this.minValue = minValue;
onMinMaxValueChanged(fireEvent);
}
}
/**
* Set the minimum and maximum value
*
* @param minValue
* the current value for min
* @param maxValue
* the current valuefor max
*/
public void setMinAndMaxValue(Double minValue, Double maxValue, boolean fireEvent) {
boolean changed = false;
if (!Util.equalsWithNull(minValue, this.minValue)) {
this.minValue = minValue;
changed = true;
}
if (!Util.equalsWithNull(maxValue, this.maxValue)) {
this.maxValue = maxValue;
changed = true;
}
if (changed) {
onMinMaxValueChanged(fireEvent);
}
}
/**
* Handle value changes of min and/or max value
*/
protected void onMinMaxValueChanged(boolean fireEvent) {
redraw();
resetCurrentValue(fireEvent); resetCurrentValue(fireEvent);
} }
@@ -1037,6 +1071,7 @@ public class SliderBar extends FocusPanel implements RequiresResize, HasValue<Do
int lineWidth = lineElement.getOffsetWidth(); int lineWidth = lineElement.getOffsetWidth();
if (numMarkers > 0) { if (numMarkers > 0) {
Element lastMarkerLabel = null; Element lastMarkerLabel = null;
Marker lastMarker = null;
int lastMarkerLabelOffsetLeft = 0; int lastMarkerLabelOffsetLeft = 0;
// Create the labels or make them visible // Create the labels or make them visible
for (int i = 0; i < numMarkers; i++) { for (int i = 0; i < numMarkers; i++) {
@@ -1076,9 +1111,9 @@ public class SliderBar extends FocusPanel implements RequiresResize, HasValue<Do
// hide last marker label if it is too close to the one just created // hide last marker label if it is too close to the one just created
if (lastMarkerLabelOffsetLeft > 0 && (labelLeftOffset-lastMarkerLabelOffsetLeft) <= 20) { if (lastMarkerLabelOffsetLeft > 0 && (labelLeftOffset-lastMarkerLabelOffsetLeft) <= 20) {
if (lastMarkerLabel != null) { if (lastMarkerLabel != null && lastMarker != null) {
lastMarkerLabel.setPropertyString("className", "gwt-SliderBar-markerlabel-tooClose"); lastMarkerLabel.setPropertyString("className", "gwt-SliderBar-markerlabel-tooClose");
lastMarkerLabel.setPropertyString("innerHTML", "M"); // no space for more lastMarkerLabel.setPropertyString("innerHTML", lastMarker.name); // no space for more
int currentMarkerOffsetLeft = labelLeftOffset; int currentMarkerOffsetLeft = labelLeftOffset;
try { try {
currentMarkerOffsetLeft = Integer.parseInt(markerElements.get(i).getStyle().getLeft().replace("px", "")); currentMarkerOffsetLeft = Integer.parseInt(markerElements.get(i).getStyle().getLeft().replace("px", ""));
@@ -1088,6 +1123,7 @@ public class SliderBar extends FocusPanel implements RequiresResize, HasValue<Do
lastMarkerLabel.getStyle().setLeft(currentMarkerOffsetLeft-8, Unit.PX); lastMarkerLabel.getStyle().setLeft(currentMarkerOffsetLeft-8, Unit.PX);
} }
} }
lastMarker = marker;
lastMarkerLabel = label; lastMarkerLabel = label;
lastMarkerLabelOffsetLeft = labelLeftOffset; lastMarkerLabelOffsetLeft = labelLeftOffset;
} }
@@ -3,12 +3,12 @@ package com.sap.sse.gwt.client.controls.slider;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.google.gwt.user.client.DOM;
import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Display; import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Position; import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.Style.Visibility; import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.user.client.DOM;
import com.sap.sse.gwt.client.controls.slider.TimeTicksCalculator.NormalizedInterval; import com.sap.sse.gwt.client.controls.slider.TimeTicksCalculator.NormalizedInterval;
import com.sap.sse.gwt.client.controls.slider.TimeTicksCalculator.TickPosition; import com.sap.sse.gwt.client.controls.slider.TimeTicksCalculator.TickPosition;
@@ -182,7 +182,7 @@ public class TimeSlider extends SliderBar {
return; return;
Element knobElement = knobImage.getElement(); Element knobElement = knobImage.getElement();
if(curValue >= minValue && curValue <= maxValue) { if (curValue != null && minValue != null && maxValue != null && curValue >= minValue && curValue <= maxValue) {
// Move the knob to the correct position // Move the knob to the correct position
int lineWidth = lineElement.getOffsetWidth(); int lineWidth = lineElement.getOffsetWidth();
int knobWidth = knobElement.getOffsetWidth(); int knobWidth = knobElement.getOffsetWidth();
@@ -199,21 +199,35 @@ public class TimeSlider extends SliderBar {
} }
public void setMaxValue(Double maxValue, boolean fireEvent) { public void setMaxValue(Double maxValue, boolean fireEvent) {
if(!isZoomed) { if (!isZoomed) {
super.setMaxValue(maxValue, fireEvent); super.setMaxValue(maxValue, fireEvent);
} else { } else {
this.maxValue = maxValue; this.maxValue = maxValue;
} }
calculateTicks();
} }
public void setMinValue(Double minValue, boolean fireEvent) { public void setMinValue(Double minValue, boolean fireEvent) {
if(!isZoomed) { if (!isZoomed) {
super.setMinValue(minValue, fireEvent); super.setMinValue(minValue, fireEvent);
} else { } else {
this.minValue = minValue; this.minValue = minValue;
}
}
@Override
public void setMinAndMaxValue(Double minValue, Double maxValue, boolean fireEvent) {
if (!isZoomed) {
super.setMinAndMaxValue(minValue, maxValue, fireEvent);
} else {
this.minValue = minValue;
this.maxValue = maxValue;
} }
}
@Override
protected void onMinMaxValueChanged(boolean fireEvent) {
calculateTicks(); calculateTicks();
super.onMinMaxValueChanged(fireEvent);
} }
public void setStepSize(double stepSize, boolean fireEvent) { public void setStepSize(double stepSize, boolean fireEvent) {
@@ -1,49 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="com.google.gdt.eclipse.suite.webapp"> <launchConfiguration type="com.google.gdt.eclipse.suite.webapp">
<booleanAttribute key="com.google.gdt.eclipse.core.RUN_SERVER" value="false"/> <booleanAttribute key="com.google.gdt.eclipse.core.RUN_SERVER" value="false"/>
<stringAttribute key="com.google.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.GWTShell"/> <stringAttribute key="com.google.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.GWTShell"/>
<booleanAttribute key="com.google.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/> <booleanAttribute key="com.google.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
<stringAttribute key="com.google.gwt.eclipse.core.CODE_SERVER_PORT" value="9875"/> <stringAttribute key="com.google.gwt.eclipse.core.CODE_SERVER_PORT" value="9875"/>
<booleanAttribute key="com.google.gwt.eclipse.core.CODE_SERVER_PORT_AUTO" value="true"/> <booleanAttribute key="com.google.gwt.eclipse.core.CODE_SERVER_PORT_AUTO" value="true"/>
<listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES"> <listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES">
<listEntry value="com.sap.sse.security.ui.UserManagement"/> <listEntry value="com.sap.sse.security.ui.UserManagement"/>
</listAttribute> </listAttribute>
<booleanAttribute key="com.google.gwt.eclipse.core.SUPERDEVMODE_ENABLED" value="true"/> <booleanAttribute key="com.google.gwt.eclipse.core.SUPERDEVMODE_ENABLED" value="true"/>
<stringAttribute key="com.google.gwt.eclipse.core.URL" value="/security/ui/Login.html"/> <stringAttribute key="com.google.gwt.eclipse.core.URL" value="/security/ui/Login.html"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/com.sap.sse.security.ui"/> <listEntry value="/com.sap.sse.security.ui"/>
</listAttribute> </listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/> <listEntry value="4"/>
</listAttribute> </listAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups"> <listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/> <listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/> <listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
</listAttribute> </listAttribute>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="false"/> <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="false"/>
<listAttribute key="org.eclipse.jdt.launching.CLASSPATH"> <listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6&quot; javaProject=&quot;com.sap.sse.security.ui&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6&quot; javaProject=&quot;com.sap.sse.security.ui&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.ui/src/main/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.ui/src/main/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.googlecode.java-diff-utils/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.googlecode.java-diff-utils/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.json.simple/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.json.simple/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.operationaltransformation/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.operationaltransformation/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.replication/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.replication/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.moxieapps.gwt.highcharts/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.moxieapps.gwt.highcharts/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.google.gwt.osgi/lib/gwt-user.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.google.gwt.osgi/lib/gwt-user.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;com.sap.sse.security.ui&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;com.sap.sse.security.ui&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt.adminconsole/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt.adminconsole/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/> <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
</listAttribute> </listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/> <stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/>
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/> <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> <stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/> <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-superDevMode -incremental -workDir &quot;${project_loc:com.sap.sse.security.ui}/.tmp/gwt-work&quot; -war &quot;${project_loc:com.sap.sse.security.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort auto -startupUrl /security/ui/Login.html com.sap.sse.security.ui.Login -startupUrl /security/ui/EditProfile.html com.sap.sse.security.ui.EditProfile -startupUrl /security/ui/EmailValidation.html com.sap.sse.security.ui.EmailValidation -startupUrl /security/ui/UserManagement.html com.sap.sse.security.ui.UserManagement"/> <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-superDevMode -incremental -workDir &quot;${project_loc:com.sap.sse.security.ui}/.tmp/gwt-work&quot; -war &quot;${project_loc:com.sap.sse.security.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort auto -startupUrl /security/ui/Login.html com.sap.sse.security.ui.Login -startupUrl /security/ui/EditProfile.html com.sap.sse.security.ui.EditProfile -startupUrl /security/ui/EmailValidation.html com.sap.sse.security.ui.EmailValidation -startupUrl /security/ui/UserManagement.html com.sap.sse.security.ui.UserManagement"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sse.security.ui"/> <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sse.security.ui"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms1024m -Xmx3072m"/> <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms1024m -Xmx3072m"/>
</launchConfiguration> </launchConfiguration>
Binary file not shown.

After

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 562 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 641 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/dark_sap_gray_black_30" android:state_selected="true"/>
<item android:drawable="@color/dark_black"/>
</selector>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/light_sap_gray_black_30" android:state_selected="true"/>
<item android:drawable="@color/light_black"/>
</selector>
@@ -4,5 +4,5 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:datePickerMode="spinner" android:datePickerMode="spinner"
android:scaleX="1.55" android:scaleX="@integer/picker_scale"
android:scaleY="1.55"/> android:scaleY="@integer/picker_scale"/>
@@ -4,6 +4,6 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:scaleX="1.55" android:scaleX="@integer/picker_scale"
android:scaleY="1.55" android:scaleY="@integer/picker_scale"
android:timePickerMode="spinner"/> android:timePickerMode="spinner"/>
@@ -4,5 +4,5 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:calendarViewShown="false" android:calendarViewShown="false"
android:scaleX="1.55" android:scaleX="@integer/picker_scale"
android:scaleY="1.55"/> android:scaleY="@integer/picker_scale"/>
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?sap_gray_black_30"
android:orientation="vertical"
android:padding="@dimen/default_padding_half">
<TextView
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?textLarge"
tools:text="Singapore"/>
<TextView
android:id="@android:id/text2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?textNormal"
android:visibility="gone"
tools:text="Day 2"
tools:visibility="visible"/>
</LinearLayout>
@@ -20,6 +20,6 @@
android:layout_gravity="center" android:layout_gravity="center"
android:paddingLeft="@dimen/default_padding" android:paddingLeft="@dimen/default_padding"
android:paddingRight="@dimen/default_padding" android:paddingRight="@dimen/default_padding"
android:scaleX="1.55" android:scaleX="@integer/picker_scale"
android:scaleY="1.55"/> android:scaleY="@integer/picker_scale"/>
</LinearLayout> </LinearLayout>
@@ -25,7 +25,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:src="?chevron_left_24dp" android:src="?chevron_left_24dp"
android:visibility="gone"/> android:visibility="gone"
tools:visibility="visible"/>
<ImageView <ImageView
android:id="@+id/header_flag" android:id="@+id/header_flag"
@@ -112,8 +113,8 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="11" android:layout_weight="11"
android:scaleX="1.55" android:scaleX="@integer/picker_scale"
android:scaleY="1.55"> android:scaleY="@integer/picker_scale">
<include <include
android:id="@+id/time_picker" android:id="@+id/time_picker"
@@ -71,47 +71,53 @@
android:src="?marker_race"/> android:src="?marker_race"/>
<LinearLayout <LinearLayout
android:id="@+id/race_flag" android:id="@+id/additional_info"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:layout_centerVertical="true" android:layout_centerVertical="true">
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:orientation="vertical">
<ImageView <ImageView
android:id="@+id/current_flag" android:id="@+id/has_dependent_races"
android:layout_width="40dp"
android:layout_height="25dp"
android:layout_gravity="center_horizontal"
android:scaleType="centerInside"
tools:src="@drawable/alpha_flag"/>
<LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:layout_gravity="center_vertical"
android:layout_margin="5dp"
android:src="?link_24dp"
android:visibility="gone"
tools:visibility="visible"/>
<LinearLayout
android:id="@+id/race_flag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<ImageView <ImageView
android:id="@+id/arrow_direction" android:id="@+id/current_flag"
android:layout_width="wrap_content" android:layout_width="40dp"
android:layout_height="wrap_content" android:layout_height="25dp"
tools:src="?arrow_down"/> android:layout_gravity="center_horizontal"
android:scaleType="centerInside"
tools:src="@drawable/alpha_flag"/>
<TextView <TextView
android:id="@+id/flag_timer" android:id="@+id/flag_timer"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:drawableLeft="?arrow_down"
android:textAppearance="?textXSmall" android:textAppearance="?textXSmall"
tools:text="01:12"/> tools:text="01:12"/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<TextView <LinearLayout
android:id="@+id/race_name"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentLeft="true" android:layout_alignParentLeft="true"
@@ -119,12 +125,28 @@
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/default_margin" android:layout_marginLeft="@dimen/default_margin"
android:layout_marginStart="@dimen/default_margin" android:layout_marginStart="@dimen/default_margin"
android:layout_toLeftOf="@id/race_flag" android:layout_toLeftOf="@id/additional_info"
android:layout_toStartOf="@id/race_flag" android:layout_toStartOf="@id/additional_info"
android:orientation="vertical" android:orientation="vertical">
android:singleLine="true"
android:textAppearance="?textNormal" <TextView
tools:text="Race 3"/> android:id="@+id/race_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?textNormal"
tools:text="Race 3"/>
<TextView
android:id="@+id/depends_on"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?textXSmall"
android:visibility="gone"
tools:text="5 minutes after ABC"
tools:visibility="visible"/>
</LinearLayout>
</RelativeLayout> </RelativeLayout>
<ImageView <ImageView
@@ -8,7 +8,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:scaleType="centerCrop" android:scaleType="centerCrop"
android:src="@color/constant_black" /> android:src="@color/constant_black"/>
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -27,7 +27,7 @@
android:layout_margin="@dimen/default_margin" android:layout_margin="@dimen/default_margin"
android:background="@drawable/round_button" android:background="@drawable/round_button"
android:padding="10dp" android:padding="10dp"
android:src="@drawable/ic_power_settings_new_white_48dp" /> android:src="@drawable/ic_power_settings_new_white_48dp"/>
<TextView <TextView
android:id="@+id/regatta_data" android:id="@+id/regatta_data"
@@ -36,24 +36,23 @@
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:layout_toLeftOf="@id/nav_button" android:layout_toLeftOf="@id/nav_button"
android:layout_toStartOf="@id/nav_button" android:layout_toStartOf="@id/nav_button"
tools:text="Marina Bay / Viewer"
android:textSize="@dimen/textSize_32"
android:paddingLeft="@dimen/default_padding_half" android:paddingLeft="@dimen/default_padding_half"
android:paddingRight="@dimen/default_padding_half" android:paddingRight="@dimen/default_padding_half"
android:textColor="@color/constant_white" android:textColor="@color/constant_white"
/> android:textSize="@dimen/textSize_32"
tools:text="Marina Bay / Viewer"/>
<TextView <TextView
android:id="@+id/regatta_course" android:id="@+id/regatta_course"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_above="@id/regatta_data"
android:layout_toLeftOf="@id/nav_button" android:layout_toLeftOf="@id/nav_button"
android:layout_toStartOf="@id/nav_button" android:layout_toStartOf="@id/nav_button"
android:layout_above="@id/regatta_data"
android:paddingLeft="@dimen/default_padding_half" android:paddingLeft="@dimen/default_padding_half"
android:paddingRight="@dimen/default_padding_half" android:paddingRight="@dimen/default_padding_half"
android:singleLine="true" android:singleLine="true"
android:textColor="@color/constant_white" android:textColor="@color/constant_white"
tools:text="Extreme Sailing Series 2015 Act 1 Singapore" android:textSize="@dimen/textSize_32"
android:textSize="@dimen/textSize_32" /> tools:text="Extreme Sailing Series 2015 Act 1 Singapore"/>
</RelativeLayout> </RelativeLayout>
@@ -20,7 +20,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:text="@string/races_current" android:text="@string/races_current"
android:textColor="?sap_light_gray" android:textColor="?sap_yellow_1"
android:textSize="@dimen/textSize_20" android:textSize="@dimen/textSize_20"
android:textStyle="bold"/> android:textStyle="bold"/>
@@ -49,10 +49,10 @@
android:dividerHeight="1dp"/> android:dividerHeight="1dp"/>
<ProgressBar <ProgressBar
android:id="@+id/progress"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:id="@+id/progress"
android:visibility="gone"/> android:visibility="gone"/>
</RelativeLayout> </RelativeLayout>
</RelativeLayout> </RelativeLayout>
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/race_content_header" android:id="@+id/race_content_header"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?sap_gray"> android:background="?sap_gray">
@@ -14,14 +15,14 @@
android:gravity="center" android:gravity="center"
android:textColor="?white" android:textColor="?white"
android:textSize="@dimen/textSize_40" android:textSize="@dimen/textSize_40"
tools:text="@string/time" /> tools:text="@string/time"/>
<ImageView <ImageView
android:id="@+id/time_marker" android:id="@+id/time_marker"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/thin_line" android:layout_height="@dimen/thin_line"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:src="?marker" /> android:src="?marker"/>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -43,19 +44,36 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:textAppearance="?textSmall" android:textAppearance="?textSmall"
tools:text="@string/time_start" /> tools:text="@string/time_start"/>
<ImageView <LinearLayout
android:id="@+id/time_start_lock"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginRight="@dimen/default_margin_half" android:layout_marginRight="@dimen/default_margin_half"
android:layout_toLeftOf="@+id/time_start" android:layout_toLeftOf="@+id/time_start"
android:layout_toStartOf="@+id/time_start" android:layout_toStartOf="@+id/time_start"
android:src="?lock_outline" android:orientation="horizontal">
android:visibility="gone" />
<ImageView
android:id="@+id/time_start_lock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="?lock_outline"
android:visibility="gone"
tools:visibility="visible"/>
<ImageView
android:id="@+id/linked_race"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="?link_24dp"
android:visibility="gone"
tools:visibility="visible"/>
</LinearLayout>
</RelativeLayout> </RelativeLayout>
<RelativeLayout <RelativeLayout
@@ -76,7 +94,8 @@
android:gravity="center" android:gravity="center"
android:textAppearance="?textSmall" android:textAppearance="?textSmall"
android:visibility="invisible" android:visibility="invisible"
tools:text="@string/time" /> tools:text="@string/time"
tools:visibility="visible"/>
</RelativeLayout> </RelativeLayout>
<RelativeLayout <RelativeLayout
@@ -93,7 +112,8 @@
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:text="@string/time_finish" android:text="@string/time_finish"
android:textAppearance="?textSmall" android:textAppearance="?textSmall"
android:visibility="invisible" /> android:visibility="invisible"
tools:visibility="visible"/>
</RelativeLayout> </RelativeLayout>
</LinearLayout> </LinearLayout>
</RelativeLayout> </RelativeLayout>
@@ -82,8 +82,8 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="75dp" android:layout_marginLeft="75dp"
android:scaleX="1.55" android:scaleX="@integer/picker_scale"
android:scaleY="1.55" /> android:scaleY="@integer/picker_scale" />
</LinearLayout> </LinearLayout>
@@ -4,5 +4,5 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:scaleX="1.55" android:scaleX="@integer/picker_scale"
android:scaleY="1.55"/> android:scaleY="@integer/picker_scale"/>
@@ -80,8 +80,8 @@
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_marginBottom="@dimen/default_margin_twice" android:layout_marginBottom="@dimen/default_margin_twice"
android:layout_marginTop="@dimen/default_margin_twice" android:layout_marginTop="@dimen/default_margin_twice"
android:scaleX="1.55" android:scaleX="@integer/picker_scale"
android:scaleY="1.55"/> android:scaleY="@integer/picker_scale"/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
@@ -123,8 +123,8 @@
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_marginBottom="@dimen/default_margin_twice" android:layout_marginBottom="@dimen/default_margin_twice"
android:layout_marginTop="@dimen/default_margin_twice" android:layout_marginTop="@dimen/default_margin_twice"
android:scaleX="1.55" android:scaleX="@integer/picker_scale"
android:scaleY="1.55"/> android:scaleY="@integer/picker_scale"/>
</LinearLayout> </LinearLayout>
<TextView <TextView
@@ -34,67 +34,209 @@
android:text="@string/set_time" android:text="@string/set_time"
android:textAppearance="?textNormal"/> android:textAppearance="?textNormal"/>
</LinearLayout> </LinearLayout>
<View
android:id="@+id/line_top"
android:layout_width="match_parent"
android:layout_height="@dimen/thick_line"
android:layout_alignParentBottom="true"
android:background="?black"/>
</RelativeLayout> </RelativeLayout>
<RelativeLayout <LinearLayout
android:id="@+id/buttonBar" android:id="@+id/tab_button"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/selector_header_height"> android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="?black"
android:orientation="horizontal"
android:visibility="gone"
tools:visibility="visible">
<LinearLayout <Button
android:layout_width="wrap_content" android:id="@+id/absolute"
style="?android:attr/borderlessButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerInParent="true" android:layout_weight="1"
android:layout_marginTop="@dimen/default_margin_half" android:text="@string/dependent_races_absolute"
android:orientation="horizontal"> android:textAllCaps="true"
android:textColor="?sap_yellow_1"
android:textSize="@dimen/textSize_26"/>
<Button <Button
android:id="@+id/minute_inc" android:id="@+id/relative"
android:layout_width="wrap_content" style="?android:attr/borderlessButtonStyle"
android:layout_height="wrap_content" android:layout_width="0dp"
android:layout_gravity="center_vertical" android:layout_height="wrap_content"
android:background="?button_filled_bordered" android:layout_weight="1"
android:drawableLeft="?chevron_left_36dp" android:text="@string/dependent_races_relative"
android:paddingRight="@dimen/default_padding_half" android:textAllCaps="true"
android:textAppearance="?textLarge" android:textColor="?sap_light_gray"
android:textColor="?white" android:textSize="@dimen/textSize_26"/>
tools:text="@string/race_start_time_in"/> </LinearLayout>
<TextView <FrameLayout
android:id="@+id/start_countdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="@dimen/default_margin"
android:layout_marginRight="@dimen/default_margin"
android:textAppearance="?textXLarge"
android:visibility="visible"
tools:text="@string/race_start_time_in"/>
<Button
android:id="@+id/minute_dec"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="?button_filled_bordered"
android:drawableRight="?chevron_right_36dp"
android:paddingLeft="@dimen/default_padding_half"
android:textAppearance="?textLarge"
android:textColor="?white"
tools:text="@string/race_start_time_in"/>
</LinearLayout>
</RelativeLayout>
<View
android:id="@+id/line_top"
android:layout_width="match_parent"
android:layout_height="@dimen/thick_line"
android:layout_below="@id/buttonBar"
android:background="?black"/>
<include
layout="@layout/race_time_picker"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_below="@id/buttonBar"/> android:layout_above="@id/tab_button"
android:layout_below="@id/header">
<RelativeLayout
android:id="@+id/time_absolute"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?sap_gray_black_30"
android:visibility="gone"
tools:visibility="visible">
<RelativeLayout
android:id="@+id/buttonBar"
android:layout_width="match_parent"
android:layout_height="@dimen/selector_header_height"
android:layout_alignParentTop="true">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginTop="@dimen/default_margin_half"
android:orientation="horizontal">
<Button
android:id="@+id/minute_inc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="?button_filled_bordered"
android:drawableLeft="?chevron_left_36dp"
android:paddingRight="@dimen/default_padding_half"
android:textAppearance="?textLarge"
android:textColor="?white"
tools:text="@string/race_start_time_in"/>
<TextView
android:id="@+id/start_countdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="@dimen/default_margin"
android:layout_marginRight="@dimen/default_margin"
android:textAppearance="?textXLarge"
android:visibility="visible"
tools:text="@string/race_start_time_in"/>
<Button
android:id="@+id/minute_dec"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="?button_filled_bordered"
android:drawableRight="?chevron_right_36dp"
android:paddingLeft="@dimen/default_padding_half"
android:textAppearance="?textLarge"
android:textColor="?white"
tools:text="@string/race_start_time_in"/>
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:id="@+id/start_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:scaleX="@integer/picker_scale"
android:scaleY="@integer/picker_scale">
<NumberPicker
android:id="@+id/start_date_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:descendantFocusability="blocksDescendants"/>
<include
android:id="@+id/start_time_picker"
layout="@layout/time_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"/>
</LinearLayout>
<Button
android:id="@+id/set_start_time_absolute"
style="?attr/buttonSolidSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerInParent="true"
android:layout_margin="@dimen/default_margin_twice"
android:maxWidth="200dp"
android:text="@string/race_set_time"/>
<TextView
android:id="@+id/debug_time"
style="?textSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:visibility="gone"
tools:text="12:12:12"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/time_relative"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?sap_gray_black_30"
android:visibility="gone"
tools:visibility="visible">
<LinearLayout
android:id="@+id/relative_input"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
<NumberPicker
android:id="@+id/time_offset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/default_margin"
android:layout_marginTop="@dimen/default_margin"
android:scaleX="@integer/picker_scale"
android:scaleY="@integer/picker_scale"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:padding="@dimen/default_padding"
android:text="@string/minutes_after"
android:textAppearance="?textLarge"/>
<Spinner
android:id="@+id/dependent_race"
android:layout_width="470dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:dropDownWidth="wrap_content"
android:prompt="@string/dependent_races_prompt"
android:spinnerMode="dropdown"/>
</LinearLayout>
<Button
android:id="@+id/set_start_time_relative"
style="?attr/buttonSolidSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/relative_input"
android:layout_centerInParent="true"
android:maxWidth="200dp"
android:text="@string/race_set_time"/>
</RelativeLayout>
</FrameLayout>
</RelativeLayout> </RelativeLayout>
@@ -10,7 +10,7 @@
android:orientation="vertical"> android:orientation="vertical">
<RelativeLayout <RelativeLayout
android:id="@+id/header" android:id="@+id/header_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/selector_header_height" android:layout_height="@dimen/selector_header_height"
android:background="?sap_gray"> android:background="?sap_gray">
@@ -54,8 +54,9 @@
android:src="?wind_on" android:src="?wind_on"
android:visibility="gone"/> android:visibility="gone"/>
<LinearLayout <TextView
android:id="@+id/header_text" android:id="@+id/header_text"
android:drawableLeft="?chevron_left_24dp"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentLeft="true" android:layout_alignParentLeft="true"
@@ -65,28 +66,18 @@
android:layout_marginStart="@dimen/default_margin" android:layout_marginStart="@dimen/default_margin"
android:layout_toLeftOf="@id/wind_off" android:layout_toLeftOf="@id/wind_off"
android:layout_toStartOf="@id/wind_off" android:layout_toStartOf="@id/wind_off"
android:orientation="horizontal"> android:layout_gravity="center_vertical"
android:orientation="horizontal"
android:text="@string/wind"
android:textAppearance="?textNormal" />
<ImageView
android:id="@+id/header_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="?chevron_left_24dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/wind"
android:textAppearance="?textNormal"/>
</LinearLayout>
</RelativeLayout> </RelativeLayout>
<RelativeLayout <RelativeLayout
android:id="@+id/content_layout"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_below="@id/header" android:layout_below="@id/header_layout"
android:background="?sap_gray_black_30" android:background="?sap_gray_black_30"
android:orientation="vertical" android:orientation="vertical"
android:paddingLeft="@dimen/default_padding" android:paddingLeft="@dimen/default_padding"
@@ -140,10 +131,11 @@
android:visibility="visible"/> android:visibility="visible"/>
<com.sap.sailing.racecommittee.app.ui.views.CompassView <com.sap.sailing.racecommittee.app.ui.views.CompassView
android:id="@+id/compassView" android:id="@+id/compass_view"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerInParent="true"/> android:layout_centerInParent="true"/>
</RelativeLayout> </RelativeLayout>
<RelativeLayout <RelativeLayout
@@ -169,15 +161,20 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:scaleX="1.55" android:scaleX="@integer/picker_scale"
android:scaleY="1.55"/> android:scaleY="@integer/picker_scale"/>
</RelativeLayout> </RelativeLayout>
<RelativeLayout <RelativeLayout
android:id="@+id/layout_map" android:id="@+id/layout_position"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:layout_marginEnd="@dimen/default_margin"
android:layout_marginLeft="@dimen/default_margin"
android:layout_marginRight="@dimen/default_margin"
android:layout_marginStart="@dimen/default_margin"
android:orientation="vertical">
<TextView <TextView
android:id="@+id/position_header" android:id="@+id/position_header"
@@ -189,77 +186,119 @@
android:textAppearance="?textSmall"/> android:textAppearance="?textSmall"/>
<RelativeLayout <RelativeLayout
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/position_header"> android:layout_below="@+id/position_header">
<FrameLayout <TextView
android:id="@+id/windMap" android:id="@+id/position_latitude"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="@layout/welcome"/>
<RelativeLayout
android:id="@+id/address"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/default_margin" android:layout_margin="@dimen/default_margin"
android:background="?white" android:text="@string/wind_latitude"
android:orientation="horizontal" android:textAppearance="?textSmall"/>
android:visibility="gone"
tools:visibility="visible">
<ImageButton <TextView
android:id="@+id/address_search" android:id="@+id/position_longitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="@android:color/transparent"
android:padding="@dimen/default_padding_half"
android:src="?search_24dp_invert"/>
<EditText
android:id="@+id/address_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/default_margin_half"
android:layout_marginStart="@dimen/default_margin_half"
android:layout_toLeftOf="@id/address_search"
android:layout_toStartOf="@id/address_search"
android:hint="@string/wind_address_hint"
android:padding="@dimen/default_padding_half"
android:singleLine="true"
android:textAppearance="?textNormal"
android:textColor="?white_invert"
android:textColorHint="?sap_light_gray"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/dark_layer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="wrap_content"
android:layout_margin="@dimen/default_margin"
android:layout_below="@+id/position_latitude"
android:text="@string/wind_longitude"
android:textAppearance="?textSmall"/>
<View <TextView
android:layout_width="match_parent" android:id="@+id/position_accuracy"
android:layout_height="match_parent" android:layout_width="match_parent"
android:background="@color/constant_black_transparent"/> android:layout_height="wrap_content"
android:layout_margin="@dimen/default_margin"
android:layout_below="@+id/position_longitude"
android:text="@string/wind_accuracy"
android:textAppearance="?textSmall"/>
<Button
android:id="@+id/position_show"
style="?attr/buttonSolidNormal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/position_accuracy"
android:layout_centerHorizontal="true"
android:text="@string/wind_map_button_show"/>
<Button
android:id="@+id/enter_position"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@drawable/button_border_light"
android:padding="@dimen/default_padding"
android:text="@string/wind_enter_position"
android:textAllCaps="true"
android:textAppearance="?textNormal"
android:textColor="?white"/>
</RelativeLayout>
</RelativeLayout> </RelativeLayout>
</RelativeLayout> </RelativeLayout>
</LinearLayout> </LinearLayout>
</RelativeLayout> </RelativeLayout>
<RelativeLayout
android:id="@+id/map_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/content_layout"
android:visibility="gone">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<WebView
android:id="@+id/web_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<!-- the following layout is for a future implementation -->
<!--<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:visibility="gone">
<Button
style="?attr/buttonSolidNormal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Overall"/>
<Button
style="?attr/buttonSolidNormal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#1"/>
<Button
style="?attr/buttonSolidNormal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#2"/>
<Button
style="?attr/buttonSolidNormal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#3"/>
</LinearLayout>-->
</LinearLayout>
<Button
android:id="@+id/position_hide"
style="?attr/buttonSolidNormal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginRight="@dimen/wind_hide_button_right_margin"
android:layout_marginEnd="@dimen/wind_hide_button_right_margin"
android:layout_marginTop="@dimen/wind_hide_button_top_margin"
android:text="@string/wind_map_button_hide"/>
</RelativeLayout>
</RelativeLayout> </RelativeLayout>
@@ -300,7 +300,7 @@
<string name="time_down">Runter in #TIME#</string> <string name="time_down">Runter in #TIME#</string>
<string name="time_up">Hoch in #TIME#</string> <string name="time_up">Hoch in #TIME#</string>
<string name="time_finish">Ende N/A</string> <string name="time_finish">Ende N/A</string>
<string name="time_start">Start #TIME#</string> <string name="time_start">Start %s</string>
<string name="time">#TIME#</string> <string name="time">#TIME#</string>
<string name="set_signal">Signal setzen</string> <string name="set_signal">Signal setzen</string>
<string name="flag_ap_desc">Rennen verschieben</string> <string name="flag_ap_desc">Rennen verschieben</string>
@@ -323,13 +323,13 @@
<string name="race_reset_cancel">Nein danke</string> <string name="race_reset_cancel">Nein danke</string>
<string name="race_reset_message">Möchten Sie wirklich das Rennen inklusive aller Einstellungen und getätigten Aktionen zurücksetzen? Das kann nicht rückgängig gemacht werden!</string> <string name="race_reset_message">Möchten Sie wirklich das Rennen inklusive aller Einstellungen und getätigten Aktionen zurücksetzen? Das kann nicht rückgängig gemacht werden!</string>
<string name="race_set_time">Zeit setzen</string> <string name="race_set_time">Zeit setzen</string>
<string name="race_start_time_in">-#TIME#</string> <string name="race_start_time_in">-%s</string>
<string name="race_start_time_ago">#TIME#</string> <string name="race_start_time_ago">%s</string>
<string name="tomorrow">Morgen</string> <string name="tomorrow">Morgen</string>
<string name="race_begin_finish_header">Beginn des Zieleinlaufs</string> <string name="race_begin_finish_header">Beginn des Zieleinlaufs</string>
<string name="race_begin_finish_current">Aktuelle Zeit verwenden</string> <string name="race_begin_finish_current">Aktuelle Zeit verwenden</string>
<string name="race_begin_finish_custom">Angegebene Zeit verwenden</string> <string name="race_begin_finish_custom">Angegebene Zeit verwenden</string>
<string name="wind_sensor"><![CDATA[um #AT# / von #FROM#° / #SPEED# kn]]></string> <string name="wind_sensor"><![CDATA[um %1$s / von %2$.0f° / %3$.1f kn]]></string>
<string name="wind_no_data">Keine Daten</string> <string name="wind_no_data">Keine Daten</string>
<string name="wind_panel"><![CDATA[von %1$.0f°\n%2$.1f kn]]></string> <string name="wind_panel"><![CDATA[von %1$.0f°\n%2$.1f kn]]></string>
<string name="settings_category_developer">Entwickler Optionen</string> <string name="settings_category_developer">Entwickler Optionen</string>
@@ -341,7 +341,7 @@
<string name="gate_start_set_pathfinder">Pathfinder setzen</string> <string name="gate_start_set_pathfinder">Pathfinder setzen</string>
<string name="gate_start_set">Gate Time setzen</string> <string name="gate_start_set">Gate Time setzen</string>
<string name="race_setup_confirm">Setup bestätigen</string> <string name="race_setup_confirm">Setup bestätigen</string>
<string name="race_end_finish_header">Ende des Zieleinlaufs</string> <string name="race_end_finish_header">Ende des Zieleinlaufs (Beginn Zieleinlauf: %s)</string>
<string name="race_summary_finish_begin">Beginn des Zieleinlaufs</string> <string name="race_summary_finish_begin">Beginn des Zieleinlaufs</string>
<string name="race_summary_finish_duration">Dauer des Zieleinlaufs</string> <string name="race_summary_finish_duration">Dauer des Zieleinlaufs</string>
<string name="race_summary_finish_end">Ende des Zieleinlaufs</string> <string name="race_summary_finish_end">Ende des Zieleinlaufs</string>
@@ -372,7 +372,7 @@
<string name="delete_file_title">Datei löschen</string> <string name="delete_file_title">Datei löschen</string>
<string name="degrees">Grad</string> <string name="degrees">Grad</string>
<string name="start_time">Startzeit</string> <string name="start_time">Startzeit</string>
<string name="start_time_value">Um #TIME# in #COUNTDOWN#</string> <string name="start_time_value">Um %1$s in %2$s</string>
<!--Extracted locales --> <!--Extracted locales -->
<string name="selected_course_area_lost">Die ausgewählte Kursumgebung ist nicht mehr verfügbar.</string> <string name="selected_course_area_lost">Die ausgewählte Kursumgebung ist nicht mehr verfügbar.</string>
@@ -419,13 +419,27 @@
<string name="change_cancel">Abbrechen</string> <string name="change_cancel">Abbrechen</string>
<string name="change_message">Nach den Wettfahrtregeln sind diese Daten im aktuellen Rennenstatus nicht veränderbar.\nSie könnten jedoch die falschen Eingaben korrigieren.</string> <string name="change_message">Nach den Wettfahrtregeln sind diese Daten im aktuellen Rennenstatus nicht veränderbar.\nSie könnten jedoch die falschen Eingaben korrigieren.</string>
<string name="change_title">Warnung</string> <string name="change_title">Warnung</string>
<string name="send_mail">Sende Email...</string> <string name="send_mail">Sende Email…</string>
<string name="data_reload_title">Daten wurden extern verändert</string> <string name="data_reload_title">Daten wurden extern verändert</string>
<string name="data_reload_message">Daten müssen neu geladen werden. Eventueller Datenverlust ist möglich.</string> <string name="data_reload_message">Daten müssen neu geladen werden. Eventueller Datenverlust ist möglich.</string>
<string name="preference_allow_dependent_races_header">Relative Startzeit</string>
<string name="preference_allow_dependent_races_description">Aktiviert relative Startzeiten zwischen Rennen</string>
<string name="preference_dependent_races_offset_header">Standard Offset der relativen Startzeit (Minuten)</string>
<string name="error_finished_time">Die ausgewählte Zielzeit liegt vor der Zeit, der ersten Schiffeinfahrt. Bitte überprüfe die Uhrzeit.</string> <string name="error_finished_time">Die ausgewählte Zielzeit liegt vor der Zeit, der ersten Schiffeinfahrt. Bitte überprüfe die Uhrzeit.</string>
<string name="error_finishing_time">Die ausgewählte Zeit is vor dem Rennstart. Bitte überprüfe die Uhrzeit.</string> <string name="error_finishing_time">Die ausgewählte Zeit is vor dem Rennstart. Bitte überprüfe die Uhrzeit.</string>
<string name="error_time_in_future">Die ausgewählte Zeit liegt in der Zukunft. Bitte überprüfe die Uhrzeit.</string> <string name="error_time_in_future">Die ausgewählte Zeit liegt in der Zukunft. Bitte überprüfe die Uhrzeit.</string>
<string name="error_wrong_race_state">Der RaceState hat nicht den korrekten Status (benötigt: %1$s - aktuell: %2$s)</string> <string name="error_wrong_race_state">Der RaceState hat nicht den korrekten Status (benötigt: %1$s - aktuell: %2$s)</string>
<string name="wind_map_button_show">Windkarte</string>
<string name="wind_map_button_hide">Schließen</string>
<string name="wind_latitude">Breite</string>
<string name="wind_longitude">Länge</string>
<string name="wind_accuracy">Genauigkeit</string>
<string name="dependent_races_absolute">Absolute Startzeit</string>
<string name="dependent_races_relative">Relative Startzeit</string>
<string name="dependent_races_prompt">Bitte Rennen auswählen</string>
<string name="minutes_after">Minuten nach</string>
<string name="minutes_after_long">%1$.0f Minuten nach %2$s</string>
<string name="wind_accuracy_ago">alt</string>
</resources> </resources>
@@ -19,6 +19,7 @@
<attr name="buttonSolidXSmall" format="reference"/> <attr name="buttonSolidXSmall" format="reference"/>
<attr name="buttonSolidSmall" format="reference"/> <attr name="buttonSolidSmall" format="reference"/>
<attr name="buttonSolidNormal" format="reference"/> <attr name="buttonSolidNormal" format="reference"/>
<attr name="text" format="reference"/>
<attr name="textXXSmall" format="reference"/> <attr name="textXXSmall" format="reference"/>
<attr name="textXSmall" format="reference"/> <attr name="textXSmall" format="reference"/>
<attr name="textSmall" format="reference"/> <attr name="textSmall" format="reference"/>
@@ -53,6 +54,7 @@
<attr name="course_updown_64dp" format="reference"/> <attr name="course_updown_64dp" format="reference"/>
<attr name="dns_48dp" format="reference"/> <attr name="dns_48dp" format="reference"/>
<attr name="hearing_48dp" format="reference"/> <attr name="hearing_48dp" format="reference"/>
<attr name="link_24dp" format="reference"/>
<attr name="lock_outline" format="reference"/> <attr name="lock_outline" format="reference"/>
<attr name="marker" format="reference"/> <attr name="marker" format="reference"/>
<attr name="marker_race" format="reference"/> <attr name="marker_race" format="reference"/>
@@ -63,6 +65,7 @@
<attr name="swipe_idle" format="reference"/> <attr name="swipe_idle" format="reference"/>
<attr name="swipe_left" format="reference"/> <attr name="swipe_left" format="reference"/>
<attr name="swipe_right" format="reference"/> <attr name="swipe_right" format="reference"/>
<attr name="tab_widget" format="reference"/>
<attr name="value_next" format="reference"/> <attr name="value_next" format="reference"/>
<attr name="value_prev" format="reference"/> <attr name="value_prev" format="reference"/>
<attr name="wind_on" format="reference"/> <attr name="wind_on" format="reference"/>
@@ -48,5 +48,10 @@
<dimen name="bigger_over_flow_width">64dp</dimen> <dimen name="bigger_over_flow_width">64dp</dimen>
<dimen name="bigger_over_flow_height">32dp</dimen> <dimen name="bigger_over_flow_height">32dp</dimen>
<dimen name="wind_hide_button_right_margin">76dp</dimen>
<dimen name="wind_hide_button_top_margin">20dp</dimen>
<item name="picker_scale" format="float" type="integer">1.55</item>
</resources> </resources>
@@ -81,6 +81,11 @@
<string name="app_folder" translatable="false">racecommittee</string> <string name="app_folder" translatable="false">racecommittee</string>
<bool name="preference_isSendingActive_default">false</bool> <bool name="preference_isSendingActive_default">false</bool>
<string name="preference_allow_dependent_races_key" translatable="false">dependentRaces</string>
<bool name="preference_allow_dependent_races_default">true</bool>
<string name="preference_dependent_races_offset_key" translatable="false">dependentRacesOffset</string>
<integer name="preference_dependent_races_offset_default">5</integer>
<string name="preference_allow_demo_key" translatable="false">allow_demo</string> <string name="preference_allow_demo_key" translatable="false">allow_demo</string>
<bool name="preference_allow_demo_default">false</bool> <bool name="preference_allow_demo_default">false</bool>
Loaded 100 of 141 files, more files were not shown because too many files have changed in this diff. Show more