Merge branch 'bug3124' into tw2015

Conflicts:
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceContext.java
This commit is contained in:
Axel Uhl committed 2015-07-17 23:23:03 +02:00
commit 5813348521
85 files changed
+2017 -851

No files matched your search

@@ -6,7 +6,7 @@ package com.sap.sailing.domain.common.racelog;
*
*/
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 */
private int orderNumber;
@@ -34,13 +34,13 @@ public class DependentStartTimeFinderTest {
private AbstractLogEventAuthor author;
private TimePoint nowMock;
private RaceLogResolver raceLogResolver;
@Before
public void setUp() {
author = new LogEventAuthorImpl("Test", 1);
raceLogA = new RaceLogImpl("raceLogA");
raceLogB = new RaceLogImpl("raceLogB");
raceLogC = new RaceLogImpl("raceLogC");
@@ -63,108 +63,137 @@ public class DependentStartTimeFinderTest {
@Test
public void testDependentStartTimeUpdate() {
raceLogC.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12,
new SimpleRaceLogIdentifierImpl("B", "", ""), new MillisecondsDurationImpl(5000)));
final MillisecondsDurationImpl cAfterB = new MillisecondsDurationImpl(5000);
raceLogC.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12,
new SimpleRaceLogIdentifierImpl("B", "", ""), cAfterB));
StartTimeFinder finder = new StartTimeFinder(raceLogResolver, raceLogC);
//Tests for correct behaviour, when race depending on has no starttime set
assertNull(finder.analyze().getStartTime());
raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12,
new SimpleRaceLogIdentifierImpl("A", "", ""), new MillisecondsDurationImpl(5000)));
finder = new StartTimeFinder(raceLogResolver, raceLogB);
StartTimeFinderResult result = finder.analyze();
List<SimpleRaceLogIdentifier> expectedDependingOnRaces = new ArrayList<SimpleRaceLogIdentifier>();
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("A", "", ""));
assertNull(result.getStartTime());
assertEquals(expectedDependingOnRaces, result.getRacesDependingOn());
finder = new StartTimeFinder(raceLogResolver, raceLogC);
//Tests for correct behaviour, when race depending on has a DependentStartTimeEvent and its parent start time is unknown
expectedDependingOnRaces = new ArrayList<SimpleRaceLogIdentifier>();
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("B", "", ""));
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("A", "", ""));
result = finder.analyze();
assertNull(result.getStartTime());
assertEquals(expectedDependingOnRaces, result.getRacesDependingOn());
MillisecondsTimePoint now = MillisecondsTimePoint.now();
raceLogA.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(5000)));
finder = new StartTimeFinder(raceLogResolver, raceLogB);
assertEquals(10000, finder.analyze().getStartTime().asMillis());
finder = new StartTimeFinder(raceLogResolver, raceLogC);
assertEquals(15000, finder.analyze().getStartTime().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);
assertEquals(5000, finder.analyze().getStartTime().asMillis());
finder = new StartTimeFinder(raceLogResolver, raceLogB);
assertEquals(15000, finder.analyze().getStartTime().asMillis());
finder = new StartTimeFinder(raceLogResolver, raceLogC);
assertEquals(20000, finder.analyze().getStartTime().asMillis());
StartTimeFinder finder = new StartTimeFinder(raceLogResolver, raceLogC);
// Tests for correct behaviour, when race depending on has no start time set
assertNull(finder.analyze().getStartTime());
final MillisecondsDurationImpl bAfterA = new MillisecondsDurationImpl(6000);
raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12,
new SimpleRaceLogIdentifierImpl("A", "", ""), bAfterA));
finder = new StartTimeFinder(raceLogResolver, raceLogB);
StartTimeFinderResult result = finder.analyze();
List<SimpleRaceLogIdentifier> expectedDependingOnRaces = new ArrayList<>();
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("A", "", ""));
assertNull(result.getStartTime());
assertEquals(bAfterA, result.getStartTimeDiff());
assertEquals(expectedDependingOnRaces, result.getRacesDependingOn());
// assertEquals(5000, result.getStartTimeDiff().asMillis());
finder = new StartTimeFinder(raceLogResolver, raceLogC);
// Tests for correct behaviour, when race depending on has a DependentStartTimeEvent and its parent start time
// is unknown
expectedDependingOnRaces = new ArrayList<>();
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("B", "", ""));
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("A", "", ""));
result = finder.analyze();
assertNull(result.getStartTime());
assertEquals(cAfterB, result.getStartTimeDiff());
assertEquals(expectedDependingOnRaces, result.getRacesDependingOn());
MillisecondsTimePoint now = MillisecondsTimePoint.now();
raceLogA.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(5000)));
finder = new StartTimeFinder(raceLogResolver, raceLogB);
result = finder.analyze();
assertEquals(11000, result.getStartTime().asMillis());
assertEquals(6000, result.getStartTimeDiff().asMillis());
finder = new StartTimeFinder(raceLogResolver, raceLogC);
result = finder.analyze();
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
public void testDependentStartTimeCycle() {
final MillisecondsDurationImpl cAfterB = new MillisecondsDurationImpl(6000);
raceLogC.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12,
new SimpleRaceLogIdentifierImpl("B", "", ""), new MillisecondsDurationImpl(5000)));
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)));
new SimpleRaceLogIdentifierImpl("B", "", ""), cAfterB));
//Check that all resolve to null in case of a cycle
StartTimeFinder finder = new StartTimeFinder(raceLogResolver, raceLogC);
assertNull(finder.analyze().getStartTime());
finder = new StartTimeFinder(raceLogResolver, raceLogB);
assertNull(finder.analyze().getStartTime());
finder = new StartTimeFinder(raceLogResolver, raceLogA);
assertNull(finder.analyze().getStartTime());
//Check that all resolve correctly after changing some element in cycle
MillisecondsTimePoint now = MillisecondsTimePoint.now();
raceLogB.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12,
new MillisecondsTimePoint(5000)));
//now A -> C -> B
finder = new StartTimeFinder(raceLogResolver, raceLogA);
//Tests for correct behaviour, when race depending on has a DependentStartTimeEvent and its parent start time is unknown
List<SimpleRaceLogIdentifier> expectedDependingOnRaces = new ArrayList<SimpleRaceLogIdentifier>();
expectedDependingOnRaces = new ArrayList<SimpleRaceLogIdentifier>();
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("C", "", ""));
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("B", "", ""));
StartTimeFinderResult result = finder.analyze();
assertEquals(15000, result.getStartTime().asMillis());
assertEquals(expectedDependingOnRaces, result.getRacesDependingOn());
//now C -> B
finder = new StartTimeFinder(raceLogResolver, raceLogC);
//Tests for correct behaviour, when race depending on has a DependentStartTimeEvent and its parent start time is unknown
expectedDependingOnRaces = new ArrayList<SimpleRaceLogIdentifier>();
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("B", "", ""));
result = finder.analyze();
assertEquals(10000, result.getStartTime().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<SimpleRaceLogIdentifier>();
result = finder.analyze();
assertEquals(5000, result.getStartTime().asMillis());
assertEquals(expectedDependingOnRaces, result.getRacesDependingOn());
final MillisecondsDurationImpl bAfterA = new MillisecondsDurationImpl(7000);
raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12,
new SimpleRaceLogIdentifierImpl("A", "", ""), bAfterA));
final MillisecondsDurationImpl aAfterC = new MillisecondsDurationImpl(8000);
raceLogA.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12,
new SimpleRaceLogIdentifierImpl("C", "", ""), aAfterC));
// Check that all resolve to null in case of a cycle
StartTimeFinder finder = new StartTimeFinder(raceLogResolver, raceLogC);
assertNull(finder.analyze().getStartTime());
assertEquals(cAfterB, finder.analyze().getStartTimeDiff());
finder = new StartTimeFinder(raceLogResolver, raceLogB);
assertNull(finder.analyze().getStartTime());
assertEquals(bAfterA, finder.analyze().getStartTimeDiff());
finder = new StartTimeFinder(raceLogResolver, raceLogA);
assertNull(finder.analyze().getStartTime());
assertEquals(aAfterC, finder.analyze().getStartTimeDiff());
// Check that all resolve correctly after changing some element in cycle
MillisecondsTimePoint now = MillisecondsTimePoint.now();
raceLogB.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(5000)));
// now A -> C -> B
finder = new StartTimeFinder(raceLogResolver, raceLogA);
// Tests for correct behaviour, when race depending on has a DependentStartTimeEvent and its parent start time
// is unknown
List<SimpleRaceLogIdentifier> expectedDependingOnRaces;
expectedDependingOnRaces = new ArrayList<>();
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("C", "", ""));
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("B", "", ""));
StartTimeFinderResult result = finder.analyze();
assertEquals(19000, result.getStartTime().asMillis());
assertEquals(8000, result.getStartTimeDiff().asMillis());
assertEquals(expectedDependingOnRaces, result.getRacesDependingOn());
// now C -> B
finder = new StartTimeFinder(raceLogResolver, raceLogC);
// Tests for correct behaviour, when race depending on has a DependentStartTimeEvent and its parent start time
// is unknown
expectedDependingOnRaces = new ArrayList<>();
expectedDependingOnRaces.add(new SimpleRaceLogIdentifierImpl("B", "", ""));
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.RaceLogEvent;
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.StartTimeFinder;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult;
import com.sap.sse.common.TimePoint;
public class StartTimeFinderTest extends
PassAwareRaceLogAnalyzerTest<StartTimeFinder, StartTimeFinderResult> {
public class StartTimeFinderTest extends PassAwareRaceLogAnalyzerTest<StartTimeFinder, StartTimeFinderResult> {
@Override
protected StartTimeFinder createAnalyzer(RaceLog raceLog) {
@@ -30,7 +29,7 @@ public class StartTimeFinderTest extends
protected TargetPair getTargetEventsAndResultForPassAwareTests(int passId, AbstractLogEventAuthor author) {
RaceLogStartTimeEvent event = createEvent(RaceLogStartTimeEvent.class, 1, passId, author);
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
@@ -1,6 +1,7 @@
package com.sap.sailing.domain.abstractlog.race.analyzing.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -16,33 +17,37 @@ public class DependentStartTimeResolver {
public DependentStartTimeResolver(RaceLogResolver raceLogResolver) {
this.raceLogResolver = raceLogResolver;
}
public StartTimeFinderResult resolve(RaceLogDependentStartTimeEvent event) {
List<SimpleRaceLogIdentifier> dependingOnRaces = new ArrayList<SimpleRaceLogIdentifier>();
List<SimpleRaceLogIdentifier> dependingOnRaces = Collections.emptyList();
return internalResolve(event, dependingOnRaces);
}
StartTimeFinderResult internalResolve(RaceLogDependentStartTimeEvent event, Iterable<SimpleRaceLogIdentifier> dependingOnRaces) {
StartTimeFinderResult internalResolve(RaceLogDependentStartTimeEvent event,Iterable<SimpleRaceLogIdentifier> dependingOnRaces) {
SimpleRaceLogIdentifier identifier = event.getDependentOnRaceIdentifier();
Duration startTimeDifference = event.getStartTimeDifference();
RaceLog raceLog = raceLogResolver.resolve(identifier);
List<SimpleRaceLogIdentifier> extendedDependingOnRaces = new ArrayList<>();
Util.addAll(dependingOnRaces, extendedDependingOnRaces);
extendedDependingOnRaces.add(identifier);
final StartTimeFinderResult result;
if (containsCycle(extendedDependingOnRaces)) {
result = new StartTimeFinderResult(extendedDependingOnRaces, null);
if (raceLog == null) {
result = new StartTimeFinderResult(dependingOnRaces, null, startTimeDifference);
} else {
StartTimeFinder dependentStartTimeFinder = new StartTimeFinder(raceLogResolver, raceLog);
StartTimeFinderResult resultOfDependentRace = dependentStartTimeFinder.analyze(extendedDependingOnRaces);
if (resultOfDependentRace.getStartTime() == null) {
result = resultOfDependentRace;
List<SimpleRaceLogIdentifier> extendedDependingOnRaces = new ArrayList<>();
Util.addAll(dependingOnRaces, extendedDependingOnRaces);
extendedDependingOnRaces.add(identifier);
if (containsCycle(extendedDependingOnRaces)) {
result = new StartTimeFinderResult(extendedDependingOnRaces, null, null);
} else {
result = new StartTimeFinderResult(resultOfDependentRace.getRacesDependingOn(),
resultOfDependentRace.getStartTime() == null ? null : resultOfDependentRace.getStartTime()
.plus(startTimeDifference));
StartTimeFinder dependentStartTimeFinder = new StartTimeFinder(raceLogResolver, raceLog);
StartTimeFinderResult resultOfDependentRace = dependentStartTimeFinder.analyze(extendedDependingOnRaces);
if (resultOfDependentRace.getStartTime() == null) {
resultOfDependentRace.setStartTimeDiff(startTimeDifference);
result = resultOfDependentRace;
} else {
result = new StartTimeFinderResult(resultOfDependentRace.getRacesDependingOn(),
resultOfDependentRace.getStartTime().plus(startTimeDifference), startTimeDifference);
}
}
}
return result;
@@ -44,15 +44,14 @@ public class RaceStatusAnalyzer extends RaceLogAnalyzer<RaceLogRaceStatus> {
@Override
protected RaceLogRaceStatus performAnalysis() {
ArrayListNavigableSet<RaceLogRaceStatusEvent> statusEvents = new ArrayListNavigableSet<RaceLogRaceStatusEvent>(RaceLogRaceStatusEventComparator.INSTANCE);
ArrayListNavigableSet<RaceLogRaceStatusEvent> statusEvents = new ArrayListNavigableSet<>(RaceLogRaceStatusEventComparator.INSTANCE);
for(RaceLogEvent event: getPassEvents()) {
if(event instanceof RaceLogRaceStatusEvent) {
statusEvents.add((RaceLogRaceStatusEvent) event);
}
}
for (RaceLogRaceStatusEvent event : statusEvents.descendingSet()) {
RaceLogRaceStatusEvent statusEvent = (RaceLogRaceStatusEvent) event;
statusEvent.accept(eventDispatcher);
event.accept(eventDispatcher);
return eventDispatcher.nextStatus;
}
@@ -79,7 +78,7 @@ public class RaceStatusAnalyzer extends RaceLogAnalyzer<RaceLogRaceStatus> {
private void setRaceLogStatusBasedOnStartTime(TimePoint startTime) {
if (startTime == null) {
nextStatus = RaceLogRaceStatus.UNKNOWN;
nextStatus = RaceLogRaceStatus.PRESCHEDULED;
return;
}
TimePoint now = clock.now();
@@ -29,13 +29,13 @@ public class StartTimeFinder extends RaceLogAnalyzer<StartTimeFinderResult> {
for (RaceLogEvent event : getPassEventsDescending()) {
if (event instanceof RaceLogStartTimeEvent) {
TimePoint startTime = ((RaceLogStartTimeEvent) event).getStartTime();
return new StartTimeFinderResult(dependingOnRaces, startTime);
return new StartTimeFinderResult(dependingOnRaces, startTime, null);
} else if (event instanceof RaceLogDependentStartTimeEvent) {
DependentStartTimeResolver dependentStartTimeResolver = new DependentStartTimeResolver(resolver);
return dependentStartTimeResolver.internalResolve((RaceLogDependentStartTimeEvent) event, dependingOnRaces);
}
}
return new StartTimeFinderResult(dependingOnRaces, null);
return new StartTimeFinderResult(dependingOnRaces, null, null);
} finally {
log.unlockAfterRead();
}
@@ -1,29 +1,25 @@
package com.sap.sailing.domain.abstractlog.race.analyzing.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
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.Util;
public class StartTimeFinderResult {
private final Iterable<SimpleRaceLogIdentifier> racesDependingOn;
private final TimePoint startTime;
private Duration startTimeDiff;
public StartTimeFinderResult(final Iterable<SimpleRaceLogIdentifier> racesDependingOn, final TimePoint startTime) {
this.racesDependingOn = racesDependingOn;
public StartTimeFinderResult(Iterable<SimpleRaceLogIdentifier> racesDependingOn, TimePoint startTime, Duration startTimeDiff) {
this.startTime = startTime;
this.startTimeDiff = startTimeDiff;
this.racesDependingOn = racesDependingOn;
}
public StartTimeFinderResult(TimePoint startTime) {
racesDependingOn = new ArrayList<SimpleRaceLogIdentifier>();
this.startTime = startTime;
}
public StartTimeFinderResult(List<SimpleRaceLogIdentifier> racesDependingOn, TimePoint startTime) {
this.racesDependingOn = racesDependingOn;
this.startTime = startTime;
public StartTimeFinderResult(TimePoint startTime, Duration startTimeDiff) {
this(/* racesDependingOn */ Collections.<SimpleRaceLogIdentifier>emptyList(), startTime, startTimeDiff);
}
public Iterable<SimpleRaceLogIdentifier> getRacesDependingOn() {
@@ -34,11 +30,16 @@ public class StartTimeFinderResult {
return startTime;
}
public Duration getStartTimeDiff() {
return startTimeDiff;
}
public void setStartTimeDiff(Duration startTimeDiff) {
this.startTimeDiff = startTimeDiff;
}
public boolean isDependentStartTime() {
if (racesDependingOn == null) {
return false;
}
return Util.isEmpty(racesDependingOn);
return racesDependingOn != null && !Util.isEmpty(racesDependingOn);
}
@Override
@@ -47,6 +48,7 @@ public class StartTimeFinderResult {
int result = 1;
result = prime * result + ((racesDependingOn == null) ? 0 : racesDependingOn.hashCode());
result = prime * result + ((startTime == null) ? 0 : startTime.hashCode());
result = prime * result + ((startTimeDiff == null) ? 0 : startTimeDiff.hashCode());
return result;
}
@@ -69,6 +71,11 @@ public class StartTimeFinderResult {
return false;
} else if (!startTime.equals(other.startTime))
return false;
if (startTimeDiff == null) {
if (other.startTimeDiff != null)
return false;
} else if (!startTimeDiff.equals(other.startTimeDiff))
return false;
return true;
}
}
@@ -187,4 +187,9 @@ public interface RaceState extends ReadonlyRaceState {
void setAdditionalScoringInformationEnabled(TimePoint creationTimePoint, boolean enable, AdditionalScoringInformationType informationType);
boolean isAdditionalScoringInformationEnabled(AdditionalScoringInformationType informationType);
/**
* forces a RaceStateUpdate
*/
void forceUpdate();
}
@@ -1,5 +1,6 @@
package com.sap.sailing.domain.abstractlog.race.state.impl;
import java.util.Collections;
import java.util.UUID;
import java.util.logging.Level;
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.RaceLogAdditionalScoringInformationEvent;
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.RacingProcedureFactory;
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 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.
*/
@@ -63,9 +69,11 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState {
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) {
super(raceLogResolver, raceLog, analyzersClock, procedureFactory, /* update */ true);
super(raceLogResolver, raceLog, /* forRaceLogIdentifier */ null, analyzersClock, procedureFactory,
Collections.<SimpleRaceLogIdentifier, ReadonlyRaceState>emptyMap(), /* update */ true);
this.author = author;
this.factory = eventFactory;
}
@@ -221,4 +229,10 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState {
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;
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.RaceLog;
import com.sap.sailing.domain.abstractlog.race.RaceLogChangedListener;
import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent;
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
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.FinishPositioningListFinder;
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.RaceLogResolver;
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.RacingProcedureTypeAnalyzer;
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.state.RaceStateChangedListener;
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 static ReadonlyRaceState create(RaceLogResolver raceLogResolver, RaceLog raceLog) {
return create(raceLogResolver, raceLog, /* forRaceLogIdentifier */null,
Collections.<SimpleRaceLogIdentifier, ReadonlyRaceState> emptyMap());
}
/**
* 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,
ConfigurationLoader<RegattaConfiguration> configurationLoader) {
return new ReadonlyRaceStateImpl(raceLogResolver, raceLog, new ReadonlyRacingProcedureFactory(
configurationLoader));
SimpleRaceLogIdentifier forRaceLogIdentifier,
ConfigurationLoader<RegattaConfiguration> 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} ).
*
* @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) {
return new ReadonlyRaceStateImpl(raceLogResolver, raceLog, new ReadonlyRacingProcedureFactory(
new EmptyRegattaConfiguration()));
public static ReadonlyRaceState create(RaceLogResolver raceLogResolver, RaceLog raceLog,
SimpleRaceLogIdentifier forRaceLogIdentifier, Map<SimpleRaceLogIdentifier, ReadonlyRaceState> dependentRaceStates) {
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 ReadonlyRaceStateImpl(RaceLogResolver raceLogResolver, RaceLog raceLog,
RacingProcedureFactory procedureFactory) {
this(raceLogResolver, raceLog, new RaceStatusAnalyzer.StandardClock(), procedureFactory, /* update */true);
SimpleRaceLogIdentifier forRaceLogIdentifier, RacingProcedureFactory procedureFactory,
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
* if <code>true</code>, the race state will be updated whenever the underlying <code>raceLog</code>
* changes.
*/
protected ReadonlyRaceStateImpl(RaceLogResolver raceLogResolver, RaceLog raceLog, Clock analyzersClock,
RacingProcedureFactory procedureFactory, boolean update) {
protected ReadonlyRaceStateImpl(RaceLogResolver raceLogResolver, RaceLog raceLog,
SimpleRaceLogIdentifier forRaceLogIdentifier, Clock analyzersClock,
RacingProcedureFactory procedureFactory,
Map<SimpleRaceLogIdentifier, ReadonlyRaceState> dependentRaceStates, boolean update) {
this.raceLog = raceLog;
this.raceLogResolver = raceLogResolver;
this.procedureFactory = procedureFactory;
@@ -178,8 +211,18 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
// We known that recreateRacingProcedure calls update() when done, therefore this RaceState
// will be fully initialized after this line
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
this.raceLog.lockForRead();
try {
@@ -187,7 +230,7 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
if (event instanceof RaceLogStartTimeEvent) {
break;
} else if (event instanceof RaceLogDependentStartTimeEvent) {
setupListenersOnDependentRace(event);
setupListenersOnDependentRace(event, dependentRaceStates);
break;
}
}
@@ -319,7 +362,7 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
@Override
public void eventAdded(RaceLogEvent event) {
if (event instanceof RaceLogDependentStartTimeEvent) {
setupListenersOnDependentRace(event);
setupListenersOnDependentRace(event, Collections.<SimpleRaceLogIdentifier, ReadonlyRaceState>emptyMap());
} else if (event instanceof RaceLogStartTimeEvent) {
if (raceStateToObserve != null) {
raceStateToObserve.removeChangedListener(raceStateToObserveListener);
@@ -329,15 +372,25 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
update();
}
private void setupListenersOnDependentRace(RaceLogEvent event) {
private void setupListenersOnDependentRace(RaceLogEvent event, Map<SimpleRaceLogIdentifier, ReadonlyRaceState> dependentRaceStates) {
if (raceStateToObserve != null) {
// Remove previous listeners
raceStateToObserve.removeChangedListener(raceStateToObserveListener);
raceStateToObserve = null;
}
RaceLogDependentStartTimeEvent dependentStartTimeEvent = (RaceLogDependentStartTimeEvent) event;
RaceLog resolvedRaceLog = raceLogResolver.resolve(dependentStartTimeEvent.getDependentOnRaceIdentifier());
raceStateToObserve = ReadonlyRaceStateImpl.create(raceLogResolver, resolvedRaceLog);
raceStateToObserve.addChangedListener(raceStateToObserveListener);
final SimpleRaceLogIdentifier dependentOnRaceIdentifier = dependentStartTimeEvent.getDependentOnRaceIdentifier();
if (dependentRaceStates.containsKey(dependentOnRaceIdentifier)) {
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
@@ -350,7 +403,7 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
return false;
}
private void update() {
protected void update() {
RacingProcedureType type = racingProcedureAnalyzer.analyze();
if (!Util.equalsWithNull(cachedRacingProcedureType, type) && type != RacingProcedureType.UNKNOWN) {
cachedRacingProcedureType = type;
@@ -261,6 +261,7 @@ public class RaceContext {
case FINISHING:
case RUNNING:
case SCHEDULED:
case PRESCHEDULED:
case STARTPHASE:
case UNKNOWN:
break;
@@ -1,49 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="com.google.gdt.eclipse.suite.webapp">
<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"/>
<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"/>
<booleanAttribute key="com.google.gwt.eclipse.core.CODE_SERVER_PORT_AUTO" value="true"/>
<listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES">
<listEntry value="com.sap.sse.security.ui.UserManagement"/>
</listAttribute>
<booleanAttribute key="com.google.gwt.eclipse.core.SUPERDEVMODE_ENABLED" value="true"/>
<stringAttribute key="com.google.gwt.eclipse.core.URL" value="/security/ui/Login.html"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/com.sap.sse.security.ui"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
</listAttribute>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="false"/>
<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 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.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.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;/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.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.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 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.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
</listAttribute>
<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"/>
<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.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.VM_ARGUMENTS" value="-Xms1024m -Xmx3072m"/>
</launchConfiguration>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="com.google.gdt.eclipse.suite.webapp">
<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"/>
<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"/>
<booleanAttribute key="com.google.gwt.eclipse.core.CODE_SERVER_PORT_AUTO" value="true"/>
<listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES">
<listEntry value="com.sap.sse.security.ui.UserManagement"/>
</listAttribute>
<booleanAttribute key="com.google.gwt.eclipse.core.SUPERDEVMODE_ENABLED" value="true"/>
<stringAttribute key="com.google.gwt.eclipse.core.URL" value="/security/ui/Login.html"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/com.sap.sse.security.ui"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
</listAttribute>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="false"/>
<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 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.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.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;/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.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.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 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.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
</listAttribute>
<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"/>
<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.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.VM_ARGUMENTS" value="-Xms1024m -Xmx3072m"/>
</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_height="match_parent"
android:datePickerMode="spinner"
android:scaleX="1.55"
android:scaleY="1.55"/>
android:scaleX="@integer/picker_scale"
android:scaleY="@integer/picker_scale"/>
@@ -4,6 +4,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleX="1.55"
android:scaleY="1.55"
android:scaleX="@integer/picker_scale"
android:scaleY="@integer/picker_scale"
android:timePickerMode="spinner"/>
@@ -4,5 +4,5 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:calendarViewShown="false"
android:scaleX="1.55"
android:scaleY="1.55"/>
android:scaleX="@integer/picker_scale"
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:paddingLeft="@dimen/default_padding"
android:paddingRight="@dimen/default_padding"
android:scaleX="1.55"
android:scaleY="1.55"/>
android:scaleX="@integer/picker_scale"
android:scaleY="@integer/picker_scale"/>
</LinearLayout>
@@ -25,7 +25,8 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="?chevron_left_24dp"
android:visibility="gone"/>
android:visibility="gone"
tools:visibility="visible"/>
<ImageView
android:id="@+id/header_flag"
@@ -112,8 +113,8 @@
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="11"
android:scaleX="1.55"
android:scaleY="1.55">
android:scaleX="@integer/picker_scale"
android:scaleY="@integer/picker_scale">
<include
android:id="@+id/time_picker"
@@ -71,47 +71,53 @@
android:src="?marker_race"/>
<LinearLayout
android:id="@+id/race_flag"
android:id="@+id/additional_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:orientation="vertical">
android:layout_centerVertical="true">
<ImageView
android:id="@+id/current_flag"
android:layout_width="40dp"
android:layout_height="25dp"
android:layout_gravity="center_horizontal"
android:scaleType="centerInside"
tools:src="@drawable/alpha_flag"/>
<LinearLayout
android:id="@+id/has_dependent_races"
android:layout_width="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
android:id="@+id/arrow_direction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:src="?arrow_down"/>
android:id="@+id/current_flag"
android:layout_width="40dp"
android:layout_height="25dp"
android:layout_gravity="center_horizontal"
android:scaleType="centerInside"
tools:src="@drawable/alpha_flag"/>
<TextView
android:id="@+id/flag_timer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:drawableLeft="?arrow_down"
android:textAppearance="?textXSmall"
tools:text="01:12"/>
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/race_name"
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
@@ -119,12 +125,28 @@
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/default_margin"
android:layout_marginStart="@dimen/default_margin"
android:layout_toLeftOf="@id/race_flag"
android:layout_toStartOf="@id/race_flag"
android:orientation="vertical"
android:singleLine="true"
android:textAppearance="?textNormal"
tools:text="Race 3"/>
android:layout_toLeftOf="@id/additional_info"
android:layout_toStartOf="@id/additional_info"
android:orientation="vertical">
<TextView
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>
<ImageView
@@ -8,7 +8,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@color/constant_black" />
android:src="@color/constant_black"/>
<View
android:layout_width="match_parent"
@@ -27,7 +27,7 @@
android:layout_margin="@dimen/default_margin"
android:background="@drawable/round_button"
android:padding="10dp"
android:src="@drawable/ic_power_settings_new_white_48dp" />
android:src="@drawable/ic_power_settings_new_white_48dp"/>
<TextView
android:id="@+id/regatta_data"
@@ -36,24 +36,23 @@
android:layout_alignParentBottom="true"
android:layout_toLeftOf="@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:paddingRight="@dimen/default_padding_half"
android:textColor="@color/constant_white"
/>
android:textSize="@dimen/textSize_32"
tools:text="Marina Bay / Viewer"/>
<TextView
android:id="@+id/regatta_course"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/regatta_data"
android:layout_toLeftOf="@id/nav_button"
android:layout_toStartOf="@id/nav_button"
android:layout_above="@id/regatta_data"
android:paddingLeft="@dimen/default_padding_half"
android:paddingRight="@dimen/default_padding_half"
android:singleLine="true"
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>
@@ -20,7 +20,7 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/races_current"
android:textColor="?sap_light_gray"
android:textColor="?sap_yellow_1"
android:textSize="@dimen/textSize_20"
android:textStyle="bold"/>
@@ -49,10 +49,10 @@
android:dividerHeight="1dp"/>
<ProgressBar
android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:id="@+id/progress"
android:visibility="gone"/>
</RelativeLayout>
</RelativeLayout>
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
<RelativeLayout
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_height="match_parent"
android:background="?sap_gray">
@@ -14,14 +15,14 @@
android:gravity="center"
android:textColor="?white"
android:textSize="@dimen/textSize_40"
tools:text="@string/time" />
tools:text="@string/time"/>
<ImageView
android:id="@+id/time_marker"
android:layout_width="match_parent"
android:layout_height="@dimen/thin_line"
android:layout_alignParentBottom="true"
android:src="?marker" />
android:src="?marker"/>
<LinearLayout
android:layout_width="match_parent"
@@ -43,19 +44,36 @@
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:textAppearance="?textSmall"
tools:text="@string/time_start" />
tools:text="@string/time_start"/>
<ImageView
android:id="@+id/time_start_lock"
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginRight="@dimen/default_margin_half"
android:layout_toLeftOf="@+id/time_start"
android:layout_toStartOf="@+id/time_start"
android:src="?lock_outline"
android:visibility="gone" />
android:orientation="horizontal">
<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
@@ -76,7 +94,8 @@
android:gravity="center"
android:textAppearance="?textSmall"
android:visibility="invisible"
tools:text="@string/time" />
tools:text="@string/time"
tools:visibility="visible"/>
</RelativeLayout>
<RelativeLayout
@@ -93,7 +112,8 @@
android:layout_alignParentStart="true"
android:text="@string/time_finish"
android:textAppearance="?textSmall"
android:visibility="invisible" />
android:visibility="invisible"
tools:visibility="visible"/>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
@@ -82,8 +82,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="75dp"
android:scaleX="1.55"
android:scaleY="1.55" />
android:scaleX="@integer/picker_scale"
android:scaleY="@integer/picker_scale" />
</LinearLayout>
@@ -4,5 +4,5 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleX="1.55"
android:scaleY="1.55"/>
android:scaleX="@integer/picker_scale"
android:scaleY="@integer/picker_scale"/>
@@ -80,8 +80,8 @@
android:layout_gravity="center_horizontal"
android:layout_marginBottom="@dimen/default_margin_twice"
android:layout_marginTop="@dimen/default_margin_twice"
android:scaleX="1.55"
android:scaleY="1.55"/>
android:scaleX="@integer/picker_scale"
android:scaleY="@integer/picker_scale"/>
</LinearLayout>
</LinearLayout>
@@ -123,8 +123,8 @@
android:layout_gravity="center_horizontal"
android:layout_marginBottom="@dimen/default_margin_twice"
android:layout_marginTop="@dimen/default_margin_twice"
android:scaleX="1.55"
android:scaleY="1.55"/>
android:scaleX="@integer/picker_scale"
android:scaleY="@integer/picker_scale"/>
</LinearLayout>
<TextView
@@ -34,67 +34,209 @@
android:text="@string/set_time"
android:textAppearance="?textNormal"/>
</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
android:id="@+id/buttonBar"
<LinearLayout
android:id="@+id/tab_button"
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
android:layout_width="wrap_content"
<Button
android:id="@+id/absolute"
style="?android:attr/borderlessButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginTop="@dimen/default_margin_half"
android:orientation="horizontal">
android:layout_weight="1"
android:text="@string/dependent_races_absolute"
android:textAllCaps="true"
android:textColor="?sap_yellow_1"
android:textSize="@dimen/textSize_26"/>
<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"/>
<Button
android:id="@+id/relative"
style="?android:attr/borderlessButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/dependent_races_relative"
android:textAllCaps="true"
android:textColor="?sap_light_gray"
android:textSize="@dimen/textSize_26"/>
</LinearLayout>
<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>
<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"
<FrameLayout
android:layout_width="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>
@@ -161,8 +161,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:scaleX="1.55"
android:scaleY="1.55"/>
android:scaleX="@integer/picker_scale"
android:scaleY="@integer/picker_scale"/>
</RelativeLayout>
@@ -300,7 +300,7 @@
<string name="time_down">Runter in #TIME#</string>
<string name="time_up">Hoch in #TIME#</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="set_signal">Signal setzen</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_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_start_time_in">-#TIME#</string>
<string name="race_start_time_ago">#TIME#</string>
<string name="race_start_time_in">-%s</string>
<string name="race_start_time_ago">%s</string>
<string name="tomorrow">Morgen</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_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_panel"><![CDATA[von %1$.0f°\n%2$.1f kn]]></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">Gate Time setzen</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_duration">Dauer 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="degrees">Grad</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 -->
<string name="selected_course_area_lost">Die ausgewählte Kursumgebung ist nicht mehr verfügbar.</string>
@@ -419,10 +419,13 @@
<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_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_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_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>
@@ -432,6 +435,11 @@
<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>
@@ -19,6 +19,7 @@
<attr name="buttonSolidXSmall" format="reference"/>
<attr name="buttonSolidSmall" format="reference"/>
<attr name="buttonSolidNormal" format="reference"/>
<attr name="text" format="reference"/>
<attr name="textXXSmall" format="reference"/>
<attr name="textXSmall" format="reference"/>
<attr name="textSmall" format="reference"/>
@@ -53,6 +54,7 @@
<attr name="course_updown_64dp" format="reference"/>
<attr name="dns_48dp" format="reference"/>
<attr name="hearing_48dp" format="reference"/>
<attr name="link_24dp" format="reference"/>
<attr name="lock_outline" format="reference"/>
<attr name="marker" format="reference"/>
<attr name="marker_race" format="reference"/>
@@ -63,6 +65,7 @@
<attr name="swipe_idle" format="reference"/>
<attr name="swipe_left" format="reference"/>
<attr name="swipe_right" format="reference"/>
<attr name="tab_widget" format="reference"/>
<attr name="value_next" format="reference"/>
<attr name="value_prev" format="reference"/>
<attr name="wind_on" format="reference"/>
@@ -52,4 +52,6 @@
<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>
@@ -81,6 +81,11 @@
<string name="app_folder" translatable="false">racecommittee</string>
<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">false</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>
<bool name="preference_allow_demo_default">false</bool>
@@ -246,8 +246,8 @@
<string name="race_start_in_4_minutes">4 Minutes</string>
<string name="race_start_in_2_minutes">2 Minutes</string>
<string name="race_start_in_1_minute">1 Minute</string>
<string name="race_start_time_in">-#TIME#</string>
<string name="race_start_time_ago">#TIME#</string>
<string name="race_start_time_in">-%s</string>
<string name="race_start_time_ago">%s</string>
<string name="race_set_time">Set Time</string>
<string name="race_reset_course">Reset course</string>
<string name="no_course_active">No course active</string>
@@ -322,13 +322,13 @@
<string name="wind_enter_position">Set Your Position</string>
<string name="wind_kn">kn</string>
<string name="wind_address_hint">Enter Address</string>
<string name="wind_sensor"><![CDATA[at #AT# / from #FROM#° / #SPEED# kn]]></string>
<string name="wind_sensor"><![CDATA[at %1$s / from %2$.0f° / %3$.1f kn]]></string>
<string name="wind_panel"><![CDATA[from %1$.0f°\n%2$.1f kn]]></string>
<string name="wind_no_data">No Data</string>
<string name="time_up">Up in #TIME#</string>
<string name="time_down">Down in #TIME#</string>
<string name="time_start">Start #TIME#</string>
<string name="time_start">Start %s</string>
<string name="time_finish">Finish N/A</string>
<string name="time">#TIME#</string>
<string name="set_signal">Set Signal</string>
@@ -352,7 +352,7 @@
<string name="race_reset_cancel">No Thanks</string>
<string name="race_reset_message">Do you really want to reset this race including all settings and actions that have be made? This can not be undone.</string>
<string name="race_begin_finish_header">Begin Finish</string>
<string name="race_end_finish_header">End Finish</string>
<string name="race_end_finish_header">End Finish (Begin Finish: %s)</string>
<string name="race_begin_finish_current">Use Current Time</string>
<string name="race_begin_finish_custom">Use Custom Time</string>
<string name="race_setup_confirm">Confirm Setup</string>
@@ -393,7 +393,7 @@
<string name="delete_file_title">Delete file</string>
<string name="delete_file">This will delete the picture</string>
<string name="start_time">Start Time</string>
<string name="start_time_value">At #TIME# in #COUNTDOWN#</string>
<string name="start_time_value">At %1$s in %2$s</string>
<!--Extracted locales -->
<string name="selected_course_area_lost">The selected course area was lost.</string>
@@ -440,9 +440,12 @@
<string name="change_cancel">Cancel</string>
<string name="change_message">According to the racing rules this data is not changeable in the current\nrace state. You may proceed nevertheless to correct wrong inputs.</string>
<string name="change_title">Warning</string>
<string name="send_mail">Send mail...</string>
<string name="send_mail">Send mail…</string>
<string name="data_reload_title">Data has changed externally</string>
<string name="data_reload_message">Data have to be reloaded. Possible data loss is possible.</string>
<string name="preference_allow_dependent_races_header">Relative Start Time (Minutes)</string>
<string name="preference_allow_dependent_races_description">Enable Relative Start Time between Races</string>
<string name="preference_dependent_races_offset_header">Default Relative Start Time Offset</string>
<string name="error_finished_time">The given finish time is earlier than the first finisher time. Please recheck the time.</string>
<string name="error_finishing_time">The selected time is before the race start.</string>
<string name="error_time_in_future">The given time is in future. Please recheck the time.</string>
@@ -452,6 +455,11 @@
<string name="wind_latitude">Latitude</string>
<string name="wind_longitude">Longitude</string>
<string name="wind_accuracy">Accuracy</string>
<string name="dependent_races_absolute">Absolute Start Time</string>
<string name="dependent_races_relative">Relative Start Time</string>
<string name="dependent_races_prompt">Please select the race</string>
<string name="minutes_after">Minutes after</string>
<string name="minutes_after_long">%1$.0f Minutes after %2$s</string>
<string name="wind_accuracy_ago">ago</string>
</resources>
@@ -7,6 +7,7 @@
<style name="AppTheme.Dark.Base" parent="Theme.AppCompat.NoActionBar">
<item name="windowActionModeOverlay">true</item>
<item name="android:actionOverflowButtonStyle">@style/OverFlow</item>
<item name="android:tabWidgetStyle">@style/AppTheme.Dark.TabWidget</item>
<item name="colorPrimary">@color/dark_colorPrimary</item>
<item name="colorPrimaryDark">@color/dark_colorPrimaryDark</item>
@@ -34,6 +35,7 @@
<item name="buttonSolidXSmall">@style/AppTheme.Dark.Button.XSmall</item>
<item name="buttonSolidSmall">@style/AppTheme.Dark.Button.Small</item>
<item name="buttonSolidNormal">@style/AppTheme.Dark.Button.Normal</item>
<item name="text">@style/AppTheme.Dark.Text</item>
<item name="textXXSmall">@style/AppTheme.Dark.Text.XXSmall</item>
<item name="textXSmall">@style/AppTheme.Dark.Text.XSmall</item>
<item name="textSmall">@style/AppTheme.Dark.Text.Small</item>
@@ -67,6 +69,7 @@
<item name="course_updown_64dp">@drawable/course_updown_64dp_dark</item>
<item name="dns_48dp">@drawable/ic_dns_white_48dp</item>
<item name="hearing_48dp">@drawable/ic_hearing_white_48dp</item>
<item name="link_24dp">@drawable/ic_link_white_24dp</item>
<item name="lock_outline">@drawable/lock_outline_dark</item>
<item name="marker">@drawable/marker_dark</item>
<item name="marker_race">@drawable/marker_race_dark</item>
@@ -77,6 +80,7 @@
<item name="swipe_idle">@drawable/swipe_idle_dark</item>
<item name="swipe_left">@drawable/swipe_left_dark</item>
<item name="swipe_right">@drawable/swipe_right_dark</item>
<item name="tab_widget">@drawable/tabwidget_dark</item>
<item name="value_next">@drawable/value_next_dark</item>
<item name="value_prev">@drawable/value_prev_dark</item>
<item name="wind_off">@drawable/wind_off_dark</item>
@@ -171,4 +175,13 @@
<item name="android:gravity">center_horizontal</item>
</style>
<style name="AppTheme.Dark.TabWidget" parent="@android:style/Widget.TabWidget">
<item name="android:textAppearance">@style/AppTheme.Light.TabWidgetText</item>
</style>
<style name="AppTheme.Dark.TabWidgetText" parent="@android:style/TextAppearance.Widget.TabWidget">
<item name="android:textSize">@dimen/textSize_32</item>
<item name="android:textColor">?white</item>
</style>
</resources>
@@ -7,6 +7,7 @@
<style name="AppTheme.Light.Base" parent="Theme.AppCompat.NoActionBar">
<item name="windowActionModeOverlay">true</item>
<item name="android:actionOverflowButtonStyle">@style/OverFlow</item>
<item name="android:tabWidgetStyle">@style/AppTheme.Light.TabWidget</item>
<item name="colorPrimary">@color/light_colorPrimary</item>
<item name="colorPrimaryDark">@color/light_colorPrimaryDark</item>
@@ -37,6 +38,7 @@
<item name="buttonSolidXSmall">@style/AppTheme.Light.Button.XSmall</item>
<item name="buttonSolidSmall">@style/AppTheme.Light.Button.Small</item>
<item name="buttonSolidNormal">@style/AppTheme.Light.Button.Normal</item>
<item name="text">@style/AppTheme.Light.Text</item>
<item name="textXXSmall">@style/AppTheme.Light.Text.XXSmall</item>
<item name="textXSmall">@style/AppTheme.Light.Text.XSmall</item>
<item name="textSmall">@style/AppTheme.Light.Text.Small</item>
@@ -70,6 +72,7 @@
<item name="course_updown_64dp">@drawable/course_updown_64dp_light</item>
<item name="dns_48dp">@drawable/ic_dns_black_48dp</item>
<item name="hearing_48dp">@drawable/ic_hearing_black_48dp</item>
<item name="link_24dp">@drawable/ic_link_black_24dp</item>
<item name="lock_outline">@drawable/lock_outline_light</item>
<item name="marker">@drawable/marker_light</item>
<item name="marker_race">@drawable/marker_race_light</item>
@@ -80,6 +83,7 @@
<item name="swipe_idle">@drawable/swipe_idle_light</item>
<item name="swipe_left">@drawable/swipe_left_light</item>
<item name="swipe_right">@drawable/swipe_right_light</item>
<item name="tab_widget">@drawable/tabwidget_light</item>
<item name="value_next">@drawable/value_next_light</item>
<item name="value_prev">@drawable/value_prev_light</item>
<item name="wind_off">@drawable/wind_off_light</item>
@@ -181,4 +185,13 @@
<item name="android:windowBackground">@null</item>
</style>
<style name="AppTheme.Light.TabWidget" parent="@android:style/Widget.TabWidget">
<item name="android:textAppearance">@style/AppTheme.Light.TabWidgetText</item>
</style>
<style name="AppTheme.Light.TabWidgetText" parent="@android:style/TextAppearance.Widget.TabWidget">
<item name="android:textSize">@dimen/textSize_32</item>
<item name="android:textColor">?white</item>
</style>
</resources>
@@ -1,118 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/settings_category_general" >
<PreferenceCategory android:title="@string/settings_category_general">
<ListPreference
android:key="@string/preference_racing_procedure_override_key"
android:defaultValue="@string/preference_racing_procedure_override_default"
android:key="@string/preference_racing_procedure_override_key"
android:summary="@string/override_default_start_procedure_type_select_description"
android:title="@string/override_default_start_procedure_type_select_header" />
<ListPreference
android:key="@string/preference_course_designer_override_key"
android:defaultValue="@string/preference_course_designer_override_default"
android:summary="@string/empty"
android:title="@string/override_default_course_designer_type_select_header" />
</PreferenceCategory>
<PreferenceCategory android:title="RRS26" >
android:title="@string/override_default_start_procedure_type_select_header"/>
<ListPreference
android:defaultValue="@string/preference_course_designer_override_default"
android:key="@string/preference_course_designer_override_key"
android:title="@string/override_default_course_designer_type_select_header"/>
<CheckBoxPreference
android:defaultValue="@bool/preference_allow_dependent_races_default"
android:key="@string/preference_allow_dependent_races_key"
android:summary="@string/preference_allow_dependent_races_description"
android:title="@string/preference_allow_dependent_races_header"/>
<com.sap.sailing.racecommittee.app.ui.views.IntegerEditTextPreference
android:defaultValue="@integer/preference_dependent_races_offset_default"
android:key="@string/preference_dependent_races_offset_key"
android:numeric="integer"
android:title="@string/preference_dependent_races_offset_header"/>
</PreferenceCategory>
<PreferenceCategory android:title="RRS26">
<ListPreference
android:defaultValue="@string/preference_racing_procedure_classflag_default"
android:key="@string/preference_racing_procedure_rrs26_classflag_key"
android:defaultValue="@string/preference_racing_procedure_classflag_default"
android:title="@string/preference_racing_procedure_classflag_header"
android:summary="@string/empty" />
android:summary="@string/empty"
android:title="@string/preference_racing_procedure_classflag_header"/>
<CheckBoxPreference
android:key="@string/preference_racing_procedure_rrs26_hasxray_key"
android:defaultValue="@bool/preference_racing_procedure_rrs26_hasxray_default"
android:title="@string/preference_racing_procedure_hasxray_header"
android:summary="@string/preference_racing_procedure_hasxray_description" />
<com.sap.sailing.racecommittee.app.ui.views.FixedMultiSelectListPreference
android:key="@string/preference_racing_procedure_rrs26_startmode_flags_key"
android:defaultValue="@array/preference_racing_procedure_rrs26_startmode_flags_default"
android:title="@string/preference_racing_procedure_rrs26_startmode_flags_header"
android:summary="@string/empty" />
android:key="@string/preference_racing_procedure_rrs26_hasxray_key"
android:summary="@string/preference_racing_procedure_hasxray_description"
android:title="@string/preference_racing_procedure_hasxray_header"/>
<com.sap.sailing.racecommittee.app.ui.views.FixedMultiSelectListPreference
android:defaultValue="@array/preference_racing_procedure_rrs26_startmode_flags_default"
android:key="@string/preference_racing_procedure_rrs26_startmode_flags_key"
android:summary="@string/empty"
android:title="@string/preference_racing_procedure_rrs26_startmode_flags_header"/>
</PreferenceCategory>
<PreferenceCategory android:title="Gate Start" >
<PreferenceCategory android:title="Gate Start">
<ListPreference
android:defaultValue="@string/preference_racing_procedure_classflag_default"
android:key="@string/preference_racing_procedure_gatestart_classflag_key"
android:defaultValue="@string/preference_racing_procedure_classflag_default"
android:title="@string/preference_racing_procedure_classflag_header"
android:summary="@string/empty" />
android:summary="@string/empty"
android:title="@string/preference_racing_procedure_classflag_header"/>
<CheckBoxPreference
android:key="@string/preference_racing_procedure_gatestart_hasxray_key"
android:defaultValue="@bool/preference_racing_procedure_gatestart_hasxray_default"
android:title="@string/preference_racing_procedure_hasxray_header"
android:summary="@string/preference_racing_procedure_hasxray_description" />
android:key="@string/preference_racing_procedure_gatestart_hasxray_key"
android:summary="@string/preference_racing_procedure_hasxray_description"
android:title="@string/preference_racing_procedure_hasxray_header"/>
<CheckBoxPreference
android:key="@string/preference_racing_procedure_gatestart_haspathfinder_key"
android:defaultValue="@bool/preference_racing_procedure_gatestart_haspathfinder_default"
android:title="@string/preference_racing_procedure_gatestart_haspathfinder_header"
android:summary="@string/preference_racing_procedure_gatestart_haspathfinder_description" />
android:key="@string/preference_racing_procedure_gatestart_haspathfinder_key"
android:summary="@string/preference_racing_procedure_gatestart_haspathfinder_description"
android:title="@string/preference_racing_procedure_gatestart_haspathfinder_header"/>
<CheckBoxPreference
android:key="@string/preference_racing_procedure_gatestart_hasadditionalgolfdowntime_key"
android:defaultValue="@bool/preference_racing_procedure_gatestart_hasadditionalgolfdowntime_default"
android:title="@string/preference_racing_procedure_gatestart_hasadditionalgolfdowntime_header"
android:summary="@string/preference_racing_procedure_gatestart_hasadditionalgolfdowntime_description" />
android:key="@string/preference_racing_procedure_gatestart_hasadditionalgolfdowntime_key"
android:summary="@string/preference_racing_procedure_gatestart_hasadditionalgolfdowntime_description"
android:title="@string/preference_racing_procedure_gatestart_hasadditionalgolfdowntime_header"/>
</PreferenceCategory>
<PreferenceCategory android:title="ESS Start" >
<PreferenceCategory android:title="ESS Start">
<ListPreference
android:defaultValue="@string/preference_racing_procedure_classflag_default"
android:key="@string/preference_racing_procedure_ess_classflag_key"
android:defaultValue="@string/preference_racing_procedure_classflag_default"
android:title="@string/preference_racing_procedure_classflag_header"
android:summary="@string/empty" />
android:summary="@string/empty"
android:title="@string/preference_racing_procedure_classflag_header"/>
<CheckBoxPreference
android:key="@string/preference_racing_procedure_ess_hasxray_key"
android:defaultValue="@bool/preference_racing_procedure_ess_hasxray_default"
android:title="@string/preference_racing_procedure_hasxray_header"
android:summary="@string/preference_racing_procedure_hasxray_description" />
android:key="@string/preference_racing_procedure_ess_hasxray_key"
android:summary="@string/preference_racing_procedure_hasxray_description"
android:title="@string/preference_racing_procedure_hasxray_header"/>
</PreferenceCategory>
<PreferenceCategory android:title="Basic Start" >
<PreferenceCategory android:title="Basic Start">
<ListPreference
android:defaultValue="@string/preference_racing_procedure_classflag_default"
android:key="@string/preference_racing_procedure_basic_classflag_key"
android:defaultValue="@string/preference_racing_procedure_classflag_default"
android:title="@string/preference_racing_procedure_classflag_header"
android:summary="@string/empty" />
android:summary="@string/empty"
android:title="@string/preference_racing_procedure_classflag_header"/>
<CheckBoxPreference
android:key="@string/preference_racing_procedure_basic_hasxray_key"
android:defaultValue="@bool/preference_racing_procedure_basic_hasxray_default"
android:title="@string/preference_racing_procedure_hasxray_header"
android:summary="@string/preference_racing_procedure_hasxray_description" />
android:key="@string/preference_racing_procedure_basic_hasxray_key"
android:summary="@string/preference_racing_procedure_hasxray_description"
android:title="@string/preference_racing_procedure_hasxray_header"/>
</PreferenceCategory>
<PreferenceCategory android:title="League Start" >
<PreferenceCategory android:title="League Start">
<ListPreference
android:key="@string/preference_racing_procedure_league_classflag_key"
android:defaultValue="@string/preference_racing_procedure_classflag_default"
android:title="@string/preference_racing_procedure_classflag_header"
android:summary="@string/empty" />
android:key="@string/preference_racing_procedure_league_classflag_key"
android:summary="@string/empty"
android:title="@string/preference_racing_procedure_classflag_header"/>
<CheckBoxPreference
android:key="@string/preference_racing_procedure_league_hasxray_key"
android:defaultValue="@bool/preference_racing_procedure_league_hasxray_default"
android:title="@string/preference_racing_procedure_hasxray_header"
android:summary="@string/preference_racing_procedure_hasxray_description" />
android:key="@string/preference_racing_procedure_league_hasxray_key"
android:summary="@string/preference_racing_procedure_hasxray_description"
android:title="@string/preference_racing_procedure_hasxray_header"/>
</PreferenceCategory>
</PreferenceScreen>
@@ -7,8 +7,6 @@ public class AppConstants {
//TODO replace it later with BuildConfig.APPLICATION_ID (Eclipse didn't know it)
private final static String PACKAGE_NAME = "com.sap.sailing.racecommittee.app";
public final static String DEFAULT = "Default";
// Intent extra fields
public final static String COURSE_AREA_UUID_KEY = "courseUuid";
public final static String RACE_ID_KEY = "raceUuid";
@@ -99,8 +99,7 @@ public class AppPreferences {
}
public List<String> getByNameCourseDesignerCourseNames() {
Set<String> values = preferences.getStringSet(
key(R.string.preference_course_designer_by_name_course_names_key), new HashSet<String>());
Set<String> values = preferences.getStringSet(key(R.string.preference_course_designer_by_name_course_names_key), new HashSet<String>());
return new ArrayList<String>(values);
}
@@ -317,8 +316,7 @@ public class AppPreferences {
public void setGateStartHasAdditionalGolfDownTime(boolean hasAdditionalGolfDownTime) {
preferences
.edit()
.putBoolean(key(R.string.preference_racing_procedure_gatestart_hasadditionalgolfdowntime_key),
hasAdditionalGolfDownTime).commit();
.putBoolean(key(R.string.preference_racing_procedure_gatestart_hasadditionalgolfdowntime_key), hasAdditionalGolfDownTime).commit();
}
public void setGateStartHasPathfinder(boolean hasPathfinder) {
@@ -435,6 +433,16 @@ public class AppPreferences {
context.getResources().getBoolean(R.bool.preference_offline_default));
}
public boolean isDependentRacesAllowed() {
return preferences.getBoolean(context.getString(R.string.preference_allow_dependent_races_key),
context.getResources().getBoolean(R.bool.preference_allow_dependent_races_default));
}
public int getDependentRacesOffset() {
return preferences.getInt(context.getString(R.string.preference_dependent_races_offset_key),
context.getResources().getInteger(R.integer.preference_dependent_races_offset_default));
}
public String getTheme() {
return preferences.getString(context.getString(R.string.preference_theme_key),
context.getResources().getString(R.string.preference_theme_default));
@@ -24,6 +24,15 @@ public class ManagedRacesDataHandler extends DataHandler<Collection<ManagedRace>
@Override
public void onResult(Collection<ManagedRace> data) {
manager.addRaces(data);
calcRaceState(data);
}
private void calcRaceState(Collection<ManagedRace> data) {
for (ManagedRace race : data) {
race.calculateRaceState();
}
for (ManagedRace race : data) {
race.getState().forceUpdate();
}
}
}
@@ -10,8 +10,6 @@ import org.json.simple.JSONValue;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.state.RaceState;
import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.SeriesBase;
import com.sap.sailing.domain.base.configuration.ConfigurationLoader;
@@ -20,7 +18,6 @@ import com.sap.sailing.domain.base.racegroup.RaceCell;
import com.sap.sailing.domain.base.racegroup.RaceGroup;
import com.sap.sailing.domain.base.racegroup.RaceRow;
import com.sap.sailing.domain.base.racegroup.SeriesWithRows;
import com.sap.sailing.racecommittee.app.data.AndroidRaceLogResolver;
import com.sap.sailing.racecommittee.app.domain.FleetIdentifier;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.domain.ManagedRaceIdentifier;
@@ -28,6 +25,7 @@ import com.sap.sailing.racecommittee.app.domain.configuration.impl.MergingRegatt
import com.sap.sailing.racecommittee.app.domain.impl.FleetIdentifierImpl;
import com.sap.sailing.racecommittee.app.domain.impl.ManagedRaceIdentifierImpl;
import com.sap.sailing.racecommittee.app.domain.impl.ManagedRaceImpl;
import com.sap.sailing.racecommittee.app.utils.ManagedRaceCalculator;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.Helpers;
@@ -55,7 +53,6 @@ public class ManagedRacesDataParser implements DataParser<Collection<ManagedRace
RaceGroup group = deserializer.deserialize(json);
addManagedRaces(managedRaces, group);
}
return managedRaces;
}
@@ -80,8 +77,7 @@ public class ManagedRacesDataParser implements DataParser<Collection<ManagedRace
}
FleetIdentifier fleetIdentifier = new FleetIdentifierImpl(fleet, series, raceGroup);
ManagedRaceIdentifier identifier = new ManagedRaceIdentifierImpl(name, fleetIdentifier);
RaceState state = RaceStateImpl.create(new AndroidRaceLogResolver(), raceLog, author, configurationLoader);
return new ManagedRaceImpl(identifier, state);
return new ManagedRaceImpl(identifier, new ManagedRaceCalculator(raceLog, author, configurationLoader));
}
}
@@ -1,5 +1,8 @@
package com.sap.sailing.racecommittee.app.domain;
import java.util.Collection;
import java.util.List;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.state.RaceState;
import com.sap.sailing.domain.base.Competitor;
@@ -10,11 +13,8 @@ import com.sap.sse.common.Named;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.WithID;
import java.util.Collection;
import java.util.List;
public interface ManagedRace extends ManagedRaceIdentifier, Named, WithID {
/**
* @return the identifier of the race.
*/
@@ -27,28 +27,28 @@ public interface ManagedRace extends ManagedRaceIdentifier, Named, WithID {
/**
* Shortcut to {@link RaceState#getRaceLog()} of {@link ManagedRace#getState()}.
*
*
* @return the log of the race.
*/
RaceLog getRaceLog();
/**
* Shortcut to {@link RaceState#getStatus()} of {@link ManagedRace#getState()}.
*
*
* @return the status of the race's state.
*/
RaceLogRaceStatus getStatus();
/**
* the current course of the race
*
*
* @return the course of the race
*/
CourseBase getCourseDesign();
/**
* returns the list of competitors for this race
*
*
* @return list of competitors
*/
Collection<Competitor> getCompetitors();
@@ -67,13 +67,12 @@ public interface ManagedRace extends ManagedRaceIdentifier, Named, WithID {
/**
* sets the list of competitors for a race. As the competitors are retrieved later from the backend, the list of
* competitors has to be settable.
*
*
* @param competitors
* the retrieved list of competitors for this race
*/
void setCompetitors(Collection<Competitor> competitors);
/**
* sets the list of mapItems ( buoys, other boats ) for a race. As the mapItems are retrieved later from the backend, the list of
* mapItems has to be settable.
@@ -83,6 +82,13 @@ public interface ManagedRace extends ManagedRaceIdentifier, Named, WithID {
*/
void setMapMarkers(List<MapMarker> markers);
/**
* Returns true if {@link RaceState} has been calculated and set
*
* @return true, if {@link RaceState} has been set
*/
boolean calculateRaceState();
/**
* sets the finished time, if the finished time is after the finishing time; check the {@link Result} for error message
*
@@ -1,5 +1,9 @@
package com.sap.sailing.racecommittee.app.domain.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishingTimeFinder;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder;
@@ -15,31 +19,33 @@ import com.sap.sailing.racecommittee.app.data.AndroidRaceLogResolver;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.domain.ManagedRaceIdentifier;
import com.sap.sailing.racecommittee.app.domain.MapMarker;
import com.sap.sailing.racecommittee.app.utils.ManagedRaceCalculator;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class ManagedRaceImpl implements ManagedRace {
private static final long serialVersionUID = -4936566684992524001L;
// private static final String TAG = ManagedRace.class.getName();
private final RaceState state;
private final ManagedRaceIdentifier identifier;
private RaceState state;
private Collection<Competitor> competitors;
private List<MapMarker> mapMarkers;
private CourseBase courseOnServer;
private ManagedRaceCalculator calculator;
public ManagedRaceImpl(ManagedRaceIdentifier identifier, RaceState state) {
this.state = state;
this.identifier = identifier;
this.competitors = new ArrayList<Competitor>();
this.competitors = new ArrayList<>();
this.courseOnServer = null;
}
public ManagedRaceImpl(ManagedRaceIdentifier identifier, ManagedRaceCalculator calculator) {
this.identifier = identifier;
this.competitors = new ArrayList<>();
this.courseOnServer = null;
this.calculator = calculator;
}
@Override
public RaceState getState() {
return state;
@@ -82,7 +88,7 @@ public class ManagedRaceImpl implements ManagedRace {
@Override
public RaceLog getRaceLog() {
return state.getRaceLog();
return state == null ? null : state.getRaceLog();
}
@Override
@@ -101,10 +107,20 @@ public class ManagedRaceImpl implements ManagedRace {
}
@Override
public List<MapMarker> getMapMarkers(){
public void setCompetitors(Collection<Competitor> competitors) {
this.competitors = competitors;
}
@Override
public List<MapMarker> getMapMarkers() {
return mapMarkers;
}
@Override
public void setMapMarkers(List<MapMarker> markers) {
this.mapMarkers = markers;
}
@Override
public CourseBase getCourseOnServer() {
return courseOnServer;
@@ -116,13 +132,13 @@ public class ManagedRaceImpl implements ManagedRace {
}
@Override
public void setCompetitors(Collection<Competitor> competitors) {
this.competitors = competitors;
}
@Override
public void setMapMarkers(List<MapMarker> markers) {
this.mapMarkers = markers;
public boolean calculateRaceState() {
boolean calculated = false;
if (state == null && calculator != null) {
state = calculator.calculateRaceState();
calculated = true;
}
return calculated;
}
@Override
@@ -1,11 +1,10 @@
package com.sap.sailing.racecommittee.app.domain.impl;
import android.text.TextUtils;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.SeriesBase;
import com.sap.sailing.domain.base.racegroup.RaceGroup;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.domain.common.LeaderboardNameConstants;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sse.common.Util;
@@ -26,6 +25,10 @@ public class RaceGroupSeriesFleet {
fleetOrder = getFleetIndex(series.getFleets(), race.getFleet());
}
private static int getSeriesIndex(ManagedRace race, SeriesBase series) {
return Util.indexOf(race.getRaceGroup().getSeries(), series);
}
public RaceGroup getRaceGroup() {
return raceGroup;
}
@@ -59,10 +62,10 @@ public class RaceGroupSeriesFleet {
if (!useDisplayName || TextUtils.isEmpty(name)) {
name = raceGroup.getName();
}
if (series != null && !series.getName().equals(AppConstants.DEFAULT)) {
if (series != null && !series.getName().equals(LeaderboardNameConstants.DEFAULT_SERIES_NAME)) {
name += " - " + series.getName();
}
if (fleet != null && !fleet.getName().equals(AppConstants.DEFAULT)) {
if (fleet != null && !fleet.getName().equals(LeaderboardNameConstants.DEFAULT_FLEET_NAME)) {
name += " - " + fleet.getName();
}
return name;
@@ -130,8 +133,4 @@ public class RaceGroupSeriesFleet {
private int getFleetIndex(Iterable<? extends Fleet> fleets, Fleet fleet) {
return Util.indexOf(fleets, fleet);
}
private static int getSeriesIndex(ManagedRace race, SeriesBase series) {
return Util.indexOf(race.getRaceGroup().getSeries(), series);
}
}
@@ -9,12 +9,12 @@ import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AlertDialog;
import android.support.v7.internal.widget.TintImageView;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.*;
import android.widget.ProgressBar;
import android.widget.TextView;
@@ -46,6 +46,7 @@ import com.sap.sailing.racecommittee.app.ui.fragments.raceinfo.RaceFlagViewerFra
import com.sap.sailing.racecommittee.app.ui.fragments.raceinfo.RaceInfoListener;
import com.sap.sailing.racecommittee.app.ui.fragments.raceinfo.RaceSummaryFragment;
import com.sap.sailing.racecommittee.app.utils.BitmapHelper;
import com.sap.sailing.racecommittee.app.utils.RaceHelper;
import com.sap.sailing.racecommittee.app.utils.ThemeHelper;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
@@ -68,7 +69,6 @@ public class RacingActivity extends SessionActivity implements RaceInfoListener,
private Wind mWind;
private RaceListFragment mRaceList;
private ManagedRace mSelectedRace;
private CourseArea mCourseArea;
private TimePoint startTime;
private Serializable getCourseAreaIdFromIntent() {
@@ -152,7 +152,7 @@ public class RacingActivity extends SessionActivity implements RaceInfoListener,
throw new IllegalStateException("There was no course area id transmitted...");
}
ExLog.i(this, this.getClass().toString(), "trying to load courseArea via id: " + courseAreaId);
mCourseArea = dataManager.getDataStore().getCourseArea(courseAreaId);
CourseArea courseArea = dataManager.getDataStore().getCourseArea(courseAreaId);
Serializable eventId = getEventIdFromIntent();
if (eventId == null) {
@@ -166,14 +166,14 @@ public class RacingActivity extends SessionActivity implements RaceInfoListener,
startActivity(intent);
finish();
} else {
if (mCourseArea != null) {
loadRaces(mCourseArea);
if (courseArea != null) {
loadRaces(courseArea);
ExLog.i(this, this.getClass().toString(), "did load courseArea!");
} else {
ExLog.i(this, this.getClass().toString(), "courseArea == null :(");
Toast.makeText(this, getString(R.string.racing_course_area_missing), Toast.LENGTH_LONG).show();
}
loadNavDrawer(mCourseArea);
loadNavDrawer(courseArea);
loadWelcomeFragment();
}
}
@@ -253,7 +253,7 @@ public class RacingActivity extends SessionActivity implements RaceInfoListener,
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mWind = (Wind) savedInstanceState.getSerializable(WIND);
@@ -359,20 +359,8 @@ public class RacingActivity extends SessionActivity implements RaceInfoListener,
}
private void setupActionBar(ManagedRace race) {
String title = race.getRaceGroup().getDisplayName();
if (TextUtils.isEmpty(title)) {
title = race.getRaceGroup().getName();
}
if (race.getSeries() != null && !race.getSeries().getName().equals(AppConstants.DEFAULT)) {
title += " / " + race.getSeries().getName();
}
if (race.getFleet() != null && !race.getFleet().getName().equals(AppConstants.DEFAULT)) {
title += " / " + race.getFleet().getName();
}
title += " / " + race.getRaceName();
if (getSupportActionBar() != null) {
getSupportActionBar().setTitle(title);
getSupportActionBar().setTitle(RaceHelper.getRaceName(race, " / "));
}
}
@@ -384,7 +372,7 @@ public class RacingActivity extends SessionActivity implements RaceInfoListener,
builder.setPositiveButton(getString(R.string.race_reset_confirm), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ExLog.i(RacingActivity.this, LogEvent.RACE_RESET_YES, mSelectedRace.getId().toString());
ExLog.i(RacingActivity.this, LogEvent.RACE_RESET_YES, mSelectedRace.getId());
ExLog.w(RacingActivity.this, TAG, String.format("Race %s is selected for reset.", mSelectedRace.getId()));
mSelectedRace.getState().setAdvancePass(MillisecondsTimePoint.now());
}
@@ -393,7 +381,7 @@ public class RacingActivity extends SessionActivity implements RaceInfoListener,
@Override
public void onClick(DialogInterface dialog, int which) {
if (mSelectedRace != null) {
ExLog.i(RacingActivity.this, LogEvent.RACE_RESET_NO, mSelectedRace.getId().toString());
ExLog.i(RacingActivity.this, LogEvent.RACE_RESET_NO, mSelectedRace.getId());
}
dialog.cancel();
}
@@ -416,7 +404,7 @@ public class RacingActivity extends SessionActivity implements RaceInfoListener,
@Override
public void onGlobalLayout() {
// Find the overflow button
final ArrayList<View> outViews = new ArrayList<View>();
final ArrayList<View> outViews = new ArrayList<>();
decorView.findViewsWithText(outViews, overflowDescription, View.FIND_VIEWS_WITH_CONTENT_DESCRIPTION);
if (outViews.isEmpty()) {
return;
@@ -493,7 +481,7 @@ public class RacingActivity extends SessionActivity implements RaceInfoListener,
setProgressSpinnerVisibility(false);
AlertDialog.Builder builder = new AlertDialog.Builder(RacingActivity.this, R.style.AppTheme_AlertDialog);
builder.setMessage(String.format(getString(R.string.generic_load_failure), ex.getMessage())).setTitle(getString(R.string.loading_failure))
.setIcon(R.drawable.ic_warning_grey600_36dp).setCancelable(true)
.setIcon(R.drawable.ic_warning_grey_600_36dp).setCancelable(true)
.setPositiveButton(getString(R.string.retry), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
setProgressSpinnerVisibility(true);
@@ -0,0 +1,190 @@
package com.sap.sailing.racecommittee.app.ui.adapters;
import java.util.ArrayList;
import android.content.Context;
import android.database.DataSetObserver;
import android.support.annotation.LayoutRes;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import com.sap.sailing.android.shared.util.ViewHolder;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.utils.RaceHelper;
import com.sap.sailing.racecommittee.app.utils.ThemeHelper;
public class DependentRaceSpinnerAdapter implements SpinnerAdapter {
private static final int HEADER = 0;
private static final int DATA = 1;
private Context mContext;
private int mLayout;
private int mSelectedItem = -1;
private ArrayList<RaceData> mData;
public DependentRaceSpinnerAdapter(Context context, @LayoutRes int layout) {
mContext = context;
mLayout = layout;
mData = new ArrayList<>();
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
View layout = convertView;
if (layout == null) {
layout = LayoutInflater.from(mContext).inflate(mLayout, parent, false);
}
TextView mainText = ViewHolder.get(layout, android.R.id.text1);
if (mainText != null) {
mainText.setText(mData.get(position).getMainText());
}
TextView subTextView = ViewHolder.get(layout, android.R.id.text2);
String subText = mData.get(position).getSubText();
if (subTextView != null) {
if (getItemViewType(position) == HEADER) {
layout.setBackgroundColor(ThemeHelper.getColor(mContext, R.attr.sap_gray_black_20));
if (subText != null) {
subTextView.setTextColor(ThemeHelper.getColor(mContext, R.attr.sap_light_gray));
subTextView.setText(subText);
subTextView.setVisibility(View.VISIBLE);
} else {
subTextView.setVisibility(View.GONE);
}
layout.setClickable(true);
if (mainText != null) {
mainText.setTextColor(ThemeHelper.getColor(mContext, R.attr.sap_light_gray));
}
} else {
if (mSelectedItem == position) {
layout.setBackgroundColor(ThemeHelper.getColor(mContext, R.attr.sap_light_gray));
} else {
layout.setBackgroundColor(ThemeHelper.getColor(mContext, R.attr.sap_gray_black_30));
}
subTextView.setVisibility(View.GONE);
layout.setClickable(false);
if (mainText != null) {
mainText.setTextColor(ThemeHelper.getColor(mContext, R.attr.white));
}
}
}
return layout;
}
@Override
public void registerDataSetObserver(DataSetObserver observer) {
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View layout = convertView;
if (layout == null) {
layout = LayoutInflater.from(mContext).inflate(mLayout, parent, false);
}
TextView text = ViewHolder.get(layout, android.R.id.text1);
if (text != null && mData.get(position).getRace() != null) {
String raceName = mData.get(position).getRace().getName();
String additional = RaceHelper.getFleetSeries(mData.get(position).getRace());
if (!TextUtils.isEmpty(additional)) {
additional += " - ";
}
additional += RaceHelper.getRaceGroupName(mData.get(position).getRace());
if (!TextUtils.isEmpty(additional)) {
raceName += " (" + additional + ")";
}
text.setText(raceName);
}
return layout;
}
@Override
public int getItemViewType(int position) {
if (mData.get(position).getRace() == null) {
return HEADER;
}
return DATA;
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public boolean isEmpty() {
return (mData.size() == 0);
}
public void add(RaceData data) {
mData.add(data);
}
public void setSelected(int position) {
mSelectedItem = position;
}
public ManagedRace getRaceAtPosition(int position) {
return mData.get(position).getRace();
}
public static class RaceData {
private String mText1;
private String mText2;
private ManagedRace mRace;
public RaceData(String mainText, String subText, ManagedRace race) {
mText1 = mainText;
mText2 = subText;
mRace = race;
}
public String getMainText() {
return mText1;
}
public String getSubText() {
return mText2;
}
public ManagedRace getRace() {
return mRace;
}
}
}
@@ -1,5 +1,8 @@
package com.sap.sailing.racecommittee.app.ui.adapters.racelist;
import java.text.SimpleDateFormat;
import java.util.List;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
@@ -14,8 +17,12 @@ import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.sap.sailing.android.shared.logging.ExLog;
import com.sap.sailing.android.shared.util.ViewHolder;
import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
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.state.RaceState;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.FlagPoleState;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProcedure;
@@ -23,18 +30,19 @@ import com.sap.sailing.domain.common.racelog.FlagPole;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.data.AndroidRaceLogResolver;
import com.sap.sailing.racecommittee.app.data.DataManager;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.ui.adapters.racelist.RaceFilter.FilterSubscriber;
import com.sap.sailing.racecommittee.app.ui.utils.FlagsResources;
import com.sap.sailing.racecommittee.app.utils.BitmapHelper;
import com.sap.sailing.racecommittee.app.utils.RaceHelper;
import com.sap.sailing.racecommittee.app.utils.ThemeHelper;
import com.sap.sailing.racecommittee.app.utils.TimeUtils;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import java.text.SimpleDateFormat;
import java.util.List;
public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> implements FilterSubscriber {
private final static String TAG = ManagedRaceListAdapter.class.getName();
@@ -53,13 +61,14 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
private TextView race_finished;
private LinearLayout race_scheduled;
private TextView race_unscheduled;
private TextView depends_on;
private ImageView current_flag;
private TextView race_name;
private TextView flag_timer;
private ImageView arrow_direction;
private TextView boat_class;
private TextView fleet_series;
private ImageView protest_image;
private ImageView has_dependent_races;
private SimpleDateFormat dateFormat;
private RaceListDataType mSelectedRace;
@@ -70,7 +79,7 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
mShownViewItems = viewItems;
mInflater = LayoutInflater.from(getContext());
mResources = getContext().getResources();
dateFormat = new SimpleDateFormat("HH:mm", getContext().getResources().getConfiguration().locale);
dateFormat = new SimpleDateFormat("kk:mm", getContext().getResources().getConfiguration().locale);
}
@Override
@@ -129,17 +138,7 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
regatta = header.getRaceGroup().getName();
}
boat_class.setText(regatta);
String fleetSeries = "";
if (header.getFleet() != null && !header.getFleet().getName().equals(AppConstants.DEFAULT)) {
fleetSeries += header.getFleet().getName();
}
if (header.getSeries() != null && !header.getSeries().getName().equals(AppConstants.DEFAULT)) {
if (!TextUtils.isEmpty(fleetSeries)) {
fleetSeries += " - ";
}
fleetSeries += header.getSeries().getName();
}
fleet_series.setText(fleetSeries);
fleet_series.setText(RaceHelper.getFleetSeries(header.getFleet(), header.getSeries()));
protest_image.setImageDrawable(FlagsResources.getFlagDrawable(getContext(), Flags.BRAVO.name(), FLAG_SIZE));
protest_image.setOnClickListener(new View.OnClickListener() {
@Override
@@ -156,8 +155,16 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
if (mSelectedRace != null && mSelectedRace.equals(race)) {
setMarker(1 - getLevel());
convertView.setBackgroundColor(ThemeHelper.getColor(getContext(), R.attr.sap_gray_black_20));
if (race.isUpdateIndicatorVisible()) {
race.setUpdateIndicatorVisible(false);
}
} else {
convertView.setBackgroundColor(ThemeHelper.getColor(getContext(), R.attr.sap_gray));
if (race.isUpdateIndicatorVisible()) {
update_badge.setVisibility(View.VISIBLE);
}
}
}
@@ -182,6 +189,11 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
}
time.setTextSize(textSize);
}
StartTimeFinder stf = new StartTimeFinder(new AndroidRaceLogResolver(), race.getRace().getRaceLog());
StartTimeFinderResult result = stf.analyze();
if (result != null && result.isDependentStartTime()) {
has_dependent_races.setVisibility(View.VISIBLE);
}
}
if (state.getFinishedTime() != null) {
time.setVisibility(View.GONE);
@@ -189,8 +201,28 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
race_finished.setText(mResources.getString(R.string.race_finished, dateFormat.format(state.getFinishedTime().asDate())));
}
if (state.getStartTime() == null && state.getFinishedTime() == null) {
race_scheduled.setVisibility(View.GONE);
race_unscheduled.setVisibility(View.VISIBLE);
switch (race.getRace().getStatus()) {
case PRESCHEDULED:
race_scheduled.setVisibility(View.GONE);
race_unscheduled.setVisibility(View.GONE);
if (depends_on != null) {
StartTimeFinder stf = new StartTimeFinder(new AndroidRaceLogResolver(), race.getRace().getRaceLog());
StartTimeFinderResult result = stf.analyze();
if (result != null && result.isDependentStartTime()) {
SimpleRaceLogIdentifier identifier = Util.get(result.getRacesDependingOn(), 0);
ManagedRace tmp = DataManager.create(getContext()).getDataStore().getRace(identifier);
depends_on.setText(getContext()
.getString(R.string.minutes_after_long, result.getStartTimeDiff().asMinutes(), RaceHelper
.getRaceName(tmp, " / ")));
depends_on.setVisibility(View.VISIBLE);
}
}
break;
default:
race_scheduled.setVisibility(View.GONE);
race_unscheduled.setVisibility(View.VISIBLE);
}
} else {
if (race_name != null) {
race_name.setTextColor(ThemeHelper.getColor(getContext(), R.attr.white));
@@ -198,10 +230,6 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
}
}
if (race.isUpdateIndicatorVisible()) {
update_badge.setVisibility(View.VISIBLE);
}
updateFlag(race.getRace(), now);
}
return convertView;
@@ -229,26 +257,27 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
mSelectedRace = id;
}
private void findViews(View convertView) {
marker = ViewHolder.get(convertView, R.id.race_marker);
arrow_direction = ViewHolder.get(convertView, R.id.arrow_direction);
current_flag = ViewHolder.get(convertView, R.id.current_flag);
update_badge = ViewHolder.get(convertView, R.id.update_badge);
race_flag = ViewHolder.get(convertView, R.id.race_flag);
time = ViewHolder.get(convertView, R.id.time);
race_name = ViewHolder.get(convertView, R.id.race_name);
race_finished = ViewHolder.get(convertView, R.id.race_finshed);
race_started = ViewHolder.get(convertView, R.id.race_started);
race_scheduled = ViewHolder.get(convertView, R.id.race_scheduled);
race_unscheduled = ViewHolder.get(convertView, R.id.race_unscheduled);
flag_timer = ViewHolder.get(convertView, R.id.flag_timer);
protest_image = ViewHolder.get(convertView, R.id.protest_image);
boat_class = ViewHolder.get(convertView, R.id.boat_class);
fleet_series = ViewHolder.get(convertView, R.id.fleet_series);
private void findViews(View layout) {
marker = ViewHolder.get(layout, R.id.race_marker);
current_flag = ViewHolder.get(layout, R.id.current_flag);
update_badge = ViewHolder.get(layout, R.id.update_badge);
race_flag = ViewHolder.get(layout, R.id.race_flag);
time = ViewHolder.get(layout, R.id.time);
race_name = ViewHolder.get(layout, R.id.race_name);
race_finished = ViewHolder.get(layout, R.id.race_finshed);
race_started = ViewHolder.get(layout, R.id.race_started);
race_scheduled = ViewHolder.get(layout, R.id.race_scheduled);
race_unscheduled = ViewHolder.get(layout, R.id.race_unscheduled);
flag_timer = ViewHolder.get(layout, R.id.flag_timer);
protest_image = ViewHolder.get(layout, R.id.protest_image);
boat_class = ViewHolder.get(layout, R.id.boat_class);
fleet_series = ViewHolder.get(layout, R.id.fleet_series);
has_dependent_races = ViewHolder.get(layout, R.id.has_dependent_races);
depends_on = ViewHolder.get(layout, R.id.depends_on);
}
private void resetValues(View convertView) {
if (convertView != null) {
private void resetValues(View layout) {
if (layout != null) {
if (update_badge != null) {
update_badge.setVisibility(View.GONE);
}
@@ -273,6 +302,13 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
if (race_name != null) {
race_name.setTextColor(ThemeHelper.getColor(getContext(), R.attr.sap_light_gray));
}
if (has_dependent_races != null) {
has_dependent_races.setVisibility(View.GONE);
}
if (depends_on != null) {
depends_on.setTextColor(ThemeHelper.getColor(getContext(), R.attr.sap_light_gray));
depends_on.setVisibility(View.GONE);
}
setMarker(0);
}
}
@@ -314,20 +350,20 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
if (isNext != 0) {
flag = FlagsResources.getFlagDrawable(getContext(), currentFlag.name(), FLAG_SIZE);
switch (isNext) {
case 1:
if (nextPole.isDisplayed()) {
case 1:
if (nextPole.isDisplayed()) {
arrow = BitmapHelper.getAttrDrawable(getContext(), R.attr.arrow_up);
} else {
arrow = BitmapHelper.getAttrDrawable(getContext(), R.attr.arrow_down);
}
break;
case 2:
arrow = BitmapHelper.getAttrDrawable(getContext(), R.attr.arrow_up);
} else {
arrow = BitmapHelper.getAttrDrawable(getContext(), R.attr.arrow_down);
}
break;
break;
case 2:
arrow = BitmapHelper.getAttrDrawable(getContext(), R.attr.arrow_up);
break;
default:
ExLog.i(getContext(), TAG, "unknown flag");
default:
ExLog.i(getContext(), TAG, "unknown flag");
}
timer = TimeUtils.formatDuration(now, poleState.getNextStateValidFrom());
}
@@ -354,8 +390,8 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
private void showFlag(LayerDrawable flag, Drawable arrow, String timer) {
if (flag != null && arrow != null && timer != null) {
current_flag.setImageDrawable(flag);
arrow_direction.setImageDrawable(arrow);
flag_timer.setText(timer);
flag_timer.setCompoundDrawablesWithIntrinsicBounds(arrow, null, null, null);
race_flag.setVisibility(View.VISIBLE);
}
}
@@ -123,7 +123,7 @@ public class RaceInfoFragment extends RaceFragment implements RaceInfoListener {
prepareResetRaceView();
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.AppTheme_AlertDialog);
builder.setView(resetRaceDialogView).setTitle(R.string.race_reset_confirmation_title)
.setIcon(R.drawable.ic_warning_grey600_36dp).setCancelable(true)
.setIcon(R.drawable.ic_warning_grey_600_36dp).setCancelable(true)
.setPositiveButton(getString(R.string.race_reset_reset_button), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
ExLog.i(getActivity(), LogEvent.RACE_RESET_YES, getRace().getId().toString());
@@ -59,15 +59,14 @@ import com.sap.sailing.racecommittee.app.ui.comparators.RaceListDataTypeComparat
import com.sap.sailing.racecommittee.app.ui.comparators.RegattaSeriesFleetComparator;
import com.sap.sailing.racecommittee.app.ui.fragments.dialogs.ProtestTimeDialogFragment;
import com.sap.sailing.racecommittee.app.utils.BitmapHelper;
import com.sap.sailing.racecommittee.app.utils.RaceHelper;
import com.sap.sailing.racecommittee.app.utils.StringHelper;
import com.sap.sailing.racecommittee.app.utils.ThemeHelper;
import com.sap.sailing.racecommittee.app.utils.TickListener;
import com.sap.sailing.racecommittee.app.utils.TickSingleton;
import com.sap.sse.common.TimePoint;
public class RaceListFragment
extends LoggableFragment
implements OnItemClickListener, OnItemSelectedListener, TickListener, OnScrollListener {
public class RaceListFragment extends LoggableFragment implements OnItemClickListener, OnItemSelectedListener, TickListener, OnScrollListener {
private final static String TAG = RaceListFragment.class.getName();
private final static String LAYOUT = "layout";
@@ -123,12 +122,8 @@ public class RaceListFragment
public static void showProtest(Context context, ManagedRace race) {
Intent intent = new Intent(AppConstants.INTENT_ACTION_SHOW_PROTEST);
String extra = race.getRaceGroup().getName();
if (!race.getSeries().getName().equals(AppConstants.DEFAULT)) {
extra += " - " + race.getSeries().getName();
}
if (!race.getFleet().getName().equals(AppConstants.DEFAULT)) {
extra += " - " + race.getFleet().getName();
}
extra += RaceHelper.getSeriesName(race.getSeries());
extra += RaceHelper.getFleetName(race.getFleet());
intent.putExtra(AppConstants.INTENT_ACTION_EXTRA, extra);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}
@@ -472,42 +467,6 @@ public class RaceListFragment
}
}
public enum FilterMode {
ACTIVE(R.string.race_list_filter_show_active), ALL(R.string.race_list_filter_show_all);
private String displayName;
FilterMode(int resId) {
this.displayName = RaceApplication.getStringContext().getString(resId);
}
@Override
public String toString() {
return displayName;
}
}
public interface RaceListCallbacks {
void onRaceListItemSelected(RaceListDataType selectedItem);
}
private class IntentReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (AppConstants.INTENT_ACTION_SHOW_PROTEST.equals(intent.getAction())) {
String raceGroupName = intent.getExtras().getString(AppConstants.INTENT_ACTION_EXTRA);
if (raceGroupName != null) {
showProtestTimeDialog(raceGroupName);
} else {
ExLog.e(getActivity(), TAG, "INTENT_ACTION_SHOW_PROTEST does not carry an INTENT_ACTION_EXTRA with the race group name!");
}
}
}
}
private void showProtestTimeDialog(String raceGroupName) {
// Find the race group for which the
for (RaceGroupSeriesFleet raceGroupSeriesFleet : mRacesByGroup.keySet()) {
@@ -535,5 +494,38 @@ public class RaceListFragment
return false;
}
public enum FilterMode {
ACTIVE(R.string.race_list_filter_show_active), ALL(R.string.race_list_filter_show_all);
private String displayName;
FilterMode(int resId) {
this.displayName = RaceApplication.getStringContext().getString(resId);
}
@Override
public String toString() {
return displayName;
}
}
public interface RaceListCallbacks {
void onRaceListItemSelected(RaceListDataType selectedItem);
}
private class IntentReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (AppConstants.INTENT_ACTION_SHOW_PROTEST.equals(intent.getAction())) {
String raceGroupName = intent.getExtras().getString(AppConstants.INTENT_ACTION_EXTRA);
if (raceGroupName != null) {
showProtestTimeDialog(raceGroupName);
} else {
ExLog.e(getActivity(), TAG, "INTENT_ACTION_SHOW_PROTEST does not carry an INTENT_ACTION_EXTRA with the race group name!");
}
}
}
}
}
@@ -24,7 +24,8 @@ public abstract class RaceInfoFragmentChooser {
public RaceFragment choose(Context context, ManagedRace managedRace) {
switch (managedRace.getStatus()) {
case UNSCHEDULED:
return createInfoFragment(StartTimeFragment.newInstance(1), managedRace);
return createInfoFragment(StartTimeFragment.newInstance(StartTimeFragment.MODE_1), managedRace);
case PRESCHEDULED:
case SCHEDULED:
case STARTPHASE:
return createInfoFragment(context, getStartphaseFragment(), managedRace);
@@ -35,6 +35,6 @@ public class LoadFailedDialog extends FragmentAttachedDialogFragment {
getString(R.string.generic_load_failure),
getArguments().getString(ARGS_ERROR_MSG)))
.setTitle(getString(R.string.loading_failure))
.setIcon(R.drawable.ic_warning_grey600_36dp);
.setIcon(R.drawable.ic_warning_grey_600_36dp);
}
}
@@ -1,11 +1,16 @@
package com.sap.sailing.racecommittee.app.ui.fragments.panels;
import android.content.*;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.sap.sailing.android.shared.logging.ExLog;
import com.sap.sailing.android.shared.util.ViewHolder;
import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState;
@@ -131,9 +136,22 @@ public class FlagPanelFragment extends BasePanelFragment {
changeVisibility(mRecallFlags, View.VISIBLE);
changeVisibility(mCourseFlags, View.GONE);
changeVisibility(mMoreFlags, View.VISIBLE);
uncheckMarker(mCourseFlags);
break;
case PRESCHEDULED:
changeVisibility(mPostponeFlags, View.VISIBLE);
changeVisibility(mAbandonFlags, View.GONE);
changeVisibility(mRecallFlags, View.GONE);
changeVisibility(mCourseFlags, View.GONE);
changeVisibility(mMoreFlags, View.GONE);
uncheckMarker(mAbandonFlags);
uncheckMarker(mCourseFlags);
uncheckMarker(mMoreFlags);
break;
case SCHEDULED:
case STARTPHASE:
changeVisibility(mPostponeFlags, View.VISIBLE);
@@ -141,6 +159,7 @@ public class FlagPanelFragment extends BasePanelFragment {
changeVisibility(mRecallFlags, View.GONE);
changeVisibility(mCourseFlags, View.GONE);
changeVisibility(mMoreFlags, View.GONE);
uncheckMarker(mAbandonFlags);
uncheckMarker(mRecallFlags);
uncheckMarker(mMoreFlags);
@@ -154,6 +173,7 @@ public class FlagPanelFragment extends BasePanelFragment {
changeVisibility(mRecallFlags, View.VISIBLE);
changeVisibility(mCourseFlags, View.GONE);
changeVisibility(mMoreFlags, View.VISIBLE);
uncheckMarker(mCourseFlags);
break;
@@ -165,6 +185,7 @@ public class FlagPanelFragment extends BasePanelFragment {
changeVisibility(mRecallFlags, View.GONE);
changeVisibility(mCourseFlags, View.GONE);
changeVisibility(mMoreFlags, View.GONE);
uncheckMarker(mRecallFlags);
uncheckMarker(mCourseFlags);
uncheckMarker(mMoreFlags);
@@ -178,6 +199,7 @@ public class FlagPanelFragment extends BasePanelFragment {
changeVisibility(mRecallFlags, View.VISIBLE);
changeVisibility(mCourseFlags, View.GONE);
changeVisibility(mMoreFlags, View.VISIBLE);
uncheckMarker(mCourseFlags);
break;
@@ -187,6 +209,7 @@ public class FlagPanelFragment extends BasePanelFragment {
changeVisibility(mRecallFlags, View.GONE);
changeVisibility(mCourseFlags, View.GONE);
changeVisibility(mMoreFlags, View.GONE);
uncheckMarker(mPostponeFlags);
uncheckMarker(mAbandonFlags);
uncheckMarker(mRecallFlags);
@@ -1,6 +1,10 @@
package com.sap.sailing.racecommittee.app.ui.fragments.panels;
import android.content.*;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater;
@@ -8,6 +12,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.sap.sailing.android.shared.logging.ExLog;
import com.sap.sailing.android.shared.util.ViewHolder;
import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState;
@@ -168,6 +173,13 @@ public class SetupPanelFragment extends BasePanelFragment {
changeVisibility(mWindLock, View.GONE);
break;
case PRESCHEDULED:
changeVisibility(mStartProcedureLock, View.GONE);
changeVisibility(mStartModeLock, View.GONE);
changeVisibility(mCourseLock, View.GONE);
changeVisibility(mWindLock, View.GONE);
break;
case SCHEDULED:
changeVisibility(mStartProcedureLock, View.GONE);
changeVisibility(mStartModeLock, View.GONE);
@@ -1,28 +1,41 @@
package com.sap.sailing.racecommittee.app.ui.fragments.panels;
import android.content.*;
import java.text.SimpleDateFormat;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.sap.sailing.android.shared.logging.ExLog;
import com.sap.sailing.android.shared.util.ViewHolder;
import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
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.state.ReadonlyRaceState;
import com.sap.sailing.domain.abstractlog.race.state.impl.BaseRaceStateChangedListener;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.data.AndroidRaceLogResolver;
import com.sap.sailing.racecommittee.app.data.DataManager;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.ui.fragments.raceinfo.StartTimeFragment;
import com.sap.sailing.racecommittee.app.utils.TickListener;
import com.sap.sailing.racecommittee.app.utils.RaceHelper;
import com.sap.sailing.racecommittee.app.utils.TickSingleton;
import com.sap.sailing.racecommittee.app.utils.TimeUtils;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import java.text.SimpleDateFormat;
public class TimePanelFragment extends BasePanelFragment implements TickListener {
public class TimePanelFragment extends BasePanelFragment {
public final static String TOGGLED = "toggled";
@@ -36,6 +49,8 @@ public class TimePanelFragment extends BasePanelFragment implements TickListener
private TextView mHeaderTime;
private TextView mTimeStart;
private TextView mTimeFinish;
private ImageView mLinkIcon;
private Boolean mLinkedRace = null;
public TimePanelFragment() {
mReceiver = new IntentReceiver();
@@ -64,6 +79,8 @@ public class TimePanelFragment extends BasePanelFragment implements TickListener
mTimeFinish = ViewHolder.get(layout, R.id.time_finish);
mHeaderTime = ViewHolder.get(layout, R.id.timer_text);
mTimeStart = ViewHolder.get(layout, R.id.time_start);
mLinkIcon = ViewHolder.get(layout, R.id.linked_race);
if (getArguments().getBoolean(TOGGLED, false)) {
toggleMarker(layout, R.id.time_marker);
}
@@ -75,7 +92,6 @@ public class TimePanelFragment extends BasePanelFragment implements TickListener
public void onResume() {
super.onResume();
TickSingleton.INSTANCE.registerListener(this);
notifyTick(MillisecondsTimePoint.now());
checkStatus();
@@ -111,8 +127,12 @@ public class TimePanelFragment extends BasePanelFragment implements TickListener
if (getRace() != null && getRace().getState() != null) {
TimePoint startTime = getRace().getState().getStartTime();
if (mTimeStart != null && startTime != null) {
mTimeStart.setText(getString(R.string.time_start).replace("#TIME#", dateFormat.format(startTime.asDate())));
if (mTimeStart != null) {
if (startTime != null) {
mTimeStart.setText(getString(R.string.time_start, dateFormat.format(startTime.asDate())));
} else {
mTimeStart.setText(getString(R.string.time_start, "N/A"));
}
}
if (mTimeFinish != null) {
@@ -129,9 +149,26 @@ public class TimePanelFragment extends BasePanelFragment implements TickListener
resId = R.string.race_start_time_ago;
time = TimeUtils.formatDurationSince(now.minus(startTime.asMillis()).asMillis());
}
mHeaderTime.setText(getString(resId).replace("#TIME#", time));
mHeaderTime.setText(getString(resId, time));
}
}
if (mLinkedRace == null) {
StartTimeFinder stf = new StartTimeFinder(new AndroidRaceLogResolver(), getRace().getRaceLog());
StartTimeFinderResult result = stf.analyze();
if (result != null) {
mLinkedRace = result.isDependentStartTime();
if (mLinkedRace && mHeaderTime != null) {
SimpleRaceLogIdentifier identifier = Util.get(result.getRacesDependingOn(), 0);
ManagedRace race = DataManager.create(getActivity()).getDataStore().getRace(identifier);
mHeaderTime.setText(getString(R.string.minutes_after_long, result.getStartTimeDiff().asMinutes(), RaceHelper.getRaceName(race, " / ")));
}
}
}
if (mLinkedRace != null && mLinkIcon != null) {
mLinkIcon.setVisibility(mLinkedRace ? View.VISIBLE : View.GONE);
}
}
private void uncheckMarker(View view) {
@@ -145,33 +182,37 @@ public class TimePanelFragment extends BasePanelFragment implements TickListener
private void checkStatus() {
switch (getRace().getStatus()) {
case UNSCHEDULED:
changeVisibility(mTimeLock, View.GONE);
break;
case UNSCHEDULED:
changeVisibility(mTimeLock, View.GONE);
break;
case SCHEDULED:
changeVisibility(mTimeLock, View.GONE);
break;
case PRESCHEDULED:
changeVisibility(mTimeLock, View.GONE);
break;
case STARTPHASE:
changeVisibility(mTimeLock, View.GONE);
break;
case SCHEDULED:
changeVisibility(mTimeLock, View.GONE);
break;
case RUNNING:
changeVisibility(mTimeLock, View.VISIBLE);
break;
case STARTPHASE:
changeVisibility(mTimeLock, View.GONE);
break;
case FINISHING:
changeVisibility(mTimeLock, View.VISIBLE);
break;
case RUNNING:
changeVisibility(mTimeLock, View.VISIBLE);
break;
case FINISHED:
changeVisibility(mTimeLock, View.VISIBLE);
break;
case FINISHING:
changeVisibility(mTimeLock, View.VISIBLE);
break;
default:
changeVisibility(mTimeLock, View.VISIBLE);
break;
case FINISHED:
changeVisibility(mTimeLock, View.VISIBLE);
break;
default:
changeVisibility(mTimeLock, View.VISIBLE);
break;
}
}
@@ -199,17 +240,17 @@ public class TimePanelFragment extends BasePanelFragment implements TickListener
private void toggleFragment() {
sendIntent(AppConstants.INTENT_ACTION_TOGGLE, AppConstants.INTENT_ACTION_EXTRA, AppConstants.INTENT_ACTION_TOGGLE_TIME);
switch (toggleMarker(container, markerId)) {
case 0:
sendIntent(AppConstants.INTENT_ACTION_SHOW_MAIN_CONTENT);
break;
case 0:
sendIntent(AppConstants.INTENT_ACTION_SHOW_MAIN_CONTENT);
break;
case 1:
replaceFragment(StartTimeFragment.newInstance(2));
break;
case 1:
replaceFragment(StartTimeFragment.newInstance(StartTimeFragment.MODE_TIME_PANEL));
break;
default:
ExLog.i(getActivity(), TAG, "Unknown return value");
break;
default:
ExLog.i(getActivity(), TAG, "Unknown return value");
break;
}
disableToggle(container, markerId);
}
@@ -252,5 +293,12 @@ public class TimePanelFragment extends BasePanelFragment implements TickListener
checkStatus();
uncheckMarker(mView);
}
@Override
public void onStartTimeChanged(ReadonlyRaceState state) {
super.onStartTimeChanged(state);
mLinkedRace = null;
}
}
}
@@ -105,6 +105,7 @@ public class RegattaPreferenceFragment extends BasePreferenceFragment {
private void setupGeneral() {
setupRacingProcedureTypePreference();
setupCourseDesignerTypePreference();
setupDependentRacesPreference();
}
private void setupRacingProcedureTypePreference() {
@@ -139,6 +140,10 @@ public class RegattaPreferenceFragment extends BasePreferenceFragment {
bindPreferenceSummaryToValue(preference);
}
private void setupDependentRacesPreference() {
bindPreferenceSummaryToInteger(findPreference(R.string.preference_dependent_races_offset_key));
}
private void setupRRS26StartmodeFlagsList() {
MultiSelectListPreference preference = findPreference(R.string.preference_racing_procedure_rrs26_startmode_flags_key);
List<String> flags = new ArrayList<>();
@@ -15,7 +15,6 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.NumberPicker;
import android.widget.TextView;
import com.sap.sailing.android.shared.util.ViewHolder;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.gate.GateStartRacingProcedure;
import com.sap.sailing.racecommittee.app.AppConstants;
@@ -70,8 +69,7 @@ public class GateStartFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View layout = LayoutInflater.from(getActivity()).inflate(
R.layout.race_schedule_procedure_gate_start_pathfinder, container, false);
final View layout = LayoutInflater.from(getActivity()).inflate(R.layout.race_schedule_procedure_gate_start_pathfinder, container, false);
mNat = ViewHolder.get(layout, R.id.pathfinder_nat);
mNum = ViewHolder.get(layout, R.id.pathfinder_num);
@@ -201,8 +199,7 @@ public class GateStartFragment {
private void enableSetButton(View view, View button) {
if (view != null && view.getTag(R.id.pathfinder_nat) != null && view.getTag(R.id.pathfinder_num) != null) {
button.setEnabled(
(Boolean) view.getTag(R.id.pathfinder_nat) && (Boolean) view.getTag(R.id.pathfinder_num));
button.setEnabled((Boolean) view.getTag(R.id.pathfinder_nat) && (Boolean) view.getTag(R.id.pathfinder_num));
}
}
}
@@ -235,8 +232,7 @@ public class GateStartFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = LayoutInflater.from(getActivity())
.inflate(R.layout.race_schedule_procedure_gate_start_timing, container, false);
View layout = LayoutInflater.from(getActivity()).inflate(R.layout.race_schedule_procedure_gate_start_timing, container, false);
View caption = ViewHolder.get(layout, R.id.header_text);
if (caption != null) {
@@ -244,8 +240,7 @@ public class GateStartFragment {
@Override
public void onClick(View v) {
replaceFragment(Pathfinder
.newInstance(getArguments().getString(NAT, null), getArguments().getString(NUM, null)));
replaceFragment(Pathfinder.newInstance(getArguments().getString(NAT, null), getArguments().getString(NUM, null)));
}
});
}
@@ -279,8 +274,10 @@ public class GateStartFragment {
mTimeLaunch = (NumberPicker) getActivity().findViewById(R.id.time_launch);
mTimeGolf = (NumberPicker) getActivity().findViewById(R.id.time_golf);
mProcedure = getRaceState().getTypedRacingProcedure();
ThemeHelper.setPickerTextColor(getActivity(), mTimeLaunch, ThemeHelper.getColor(getActivity(), R.attr.white));
ThemeHelper.setPickerTextColor(getActivity(), mTimeGolf, ThemeHelper.getColor(getActivity(), R.attr.white));
ThemeHelper.setPickerColor(getActivity(), mTimeLaunch, ThemeHelper.getColor(getActivity(), R.attr.white), ThemeHelper
.getColor(getActivity(), R.attr.sap_yellow_1));
ThemeHelper.setPickerColor(getActivity(), mTimeGolf, ThemeHelper.getColor(getActivity(), R.attr.white), ThemeHelper
.getColor(getActivity(), R.attr.sap_yellow_1));
setTimeLaunchWidget();
setTimeGolfWidget();
@@ -1,5 +1,9 @@
package com.sap.sailing.racecommittee.app.ui.fragments.raceinfo;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.TextUtils;
@@ -8,8 +12,11 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.sap.sailing.android.shared.logging.ExLog;
import com.sap.sailing.android.shared.util.ViewHolder;
import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
import com.sap.sailing.domain.abstractlog.race.impl.SimpleRaceLogIdentifierImpl;
import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState;
import com.sap.sailing.domain.abstractlog.race.state.impl.BaseRaceStateChangedListener;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.rrs26.RRS26RacingProcedure;
@@ -17,26 +24,33 @@ import com.sap.sailing.domain.common.Wind;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.data.DataManager;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.domain.impl.FleetIdentifierImpl;
import com.sap.sailing.racecommittee.app.ui.activities.RacingActivity;
import com.sap.sailing.racecommittee.app.ui.fragments.RaceFragment;
import com.sap.sailing.racecommittee.app.ui.utils.FlagsResources;
import com.sap.sailing.racecommittee.app.utils.BitmapHelper;
import com.sap.sailing.racecommittee.app.utils.RaceHelper;
import com.sap.sailing.racecommittee.app.utils.TimeUtils;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
public class MainScheduleFragment extends BaseFragment implements View.OnClickListener {
public static final String START_TIME = "startTime";
public static final String DEPENDENT_RACE = "dependentRace";
public static final String START_TIME_DIFF = "startTimeDiff";
private static final String TAG = MainScheduleFragment.class.getName();
private TextView mStartTimeTextView;
private String mStartTimeString;
private String mRaceId;
private TimePoint mStartTime;
private Duration mStartTimeDiff;
private TextView mWindValue;
private RacingProcedureType mRacingProcedureType;
@@ -162,8 +176,8 @@ public class MainScheduleFragment extends BaseFragment implements View.OnClickLi
}
private void initStartTime() {
TimePoint timePoint = (TimePoint) getArguments().getSerializable(START_TIME);
RacingActivity activity = (RacingActivity) getActivity();
TimePoint timePoint = (TimePoint) getArguments().getSerializable(START_TIME);
if (timePoint == null && activity != null) {
timePoint = activity.getStartTime();
}
@@ -174,6 +188,14 @@ public class MainScheduleFragment extends BaseFragment implements View.OnClickLi
mStartTime = timePoint;
mStartTimeString = mDateFormat.format(timePoint.asDate());
}
mStartTimeDiff = (Duration) getArguments().getSerializable(START_TIME_DIFF);
mRaceId = (String) getArguments().getSerializable(DEPENDENT_RACE);
if (mRaceId != null && mStartTimeDiff != null) {
ManagedRace race = DataManager.create(getActivity()).getDataStore().getRace(mRaceId);
mStartTimeString = getString(R.string.minutes_after_long, mStartTimeDiff.asMinutes(), RaceHelper.getRaceName(race, " / "));
}
}
@Override
@@ -205,7 +227,7 @@ public class MainScheduleFragment extends BaseFragment implements View.OnClickLi
break;
case R.id.start_time:
openFragment(StartTimeFragment.newInstance(getArguments().getSerializable(START_TIME)));
openFragment(StartTimeFragment.newInstance(getArguments()));
break;
case R.id.wind:
@@ -226,7 +248,13 @@ public class MainScheduleFragment extends BaseFragment implements View.OnClickLi
}
TimePoint now = MillisecondsTimePoint.now();
getRaceState().setRacingProcedure(now, mRacingProcedureType);
getRaceState().forceNewStartTime(now, mStartTime);
if (mStartTimeDiff == null && mRaceId == null) {
getRaceState().forceNewStartTime(now, mStartTime);
} else {
Util.Triple<String, String, String> triple = FleetIdentifierImpl.unescape(mRaceId);
SimpleRaceLogIdentifier identifier = new SimpleRaceLogIdentifierImpl(triple.getA(), triple.getB(), triple.getC());
getRaceState().forceNewDependentStartTime(now, mStartTimeDiff, identifier);
}
if (procedure != null) {
procedure.setStartModeFlag(MillisecondsTimePoint.now(), flag);
}
@@ -237,17 +265,18 @@ public class MainScheduleFragment extends BaseFragment implements View.OnClickLi
super.notifyTick(now);
if (mStartTimeTextView != null && !TextUtils.isEmpty(mStartTimeString)) {
String startTimeValue = getString(R.string.start_time_value).replace("#TIME#", mStartTimeString)
.replace("#COUNTDOWN#", calcCountdown(now));
mStartTimeTextView.setText(startTimeValue);
if (mRaceId == null && mStartTimeDiff == null) {
String startTimeValue = getString(R.string.start_time_value, mStartTimeString, calcCountdown(now));
mStartTimeTextView.setText(startTimeValue);
} else {
mStartTimeTextView.setText(mStartTimeString);
}
}
if (mWindValue != null && getRace() != null && getRaceState() != null && getRaceState().getWindFix() != null) {
String sensorData = getString(R.string.wind_sensor);
Wind wind = getRaceState().getWindFix();
sensorData = sensorData.replace("#AT#", mDateFormat.format(wind.getTimePoint().asDate()));
sensorData = sensorData.replace("#FROM#", String.format("%.0f", wind.getFrom().getDegrees()));
sensorData = sensorData.replace("#SPEED#", String.format("%.1f", wind.getKnots()));
String sensorData = getString(R.string.wind_sensor, mDateFormat.format(wind.getTimePoint().asDate()), wind.getFrom().getDegrees(), wind
.getKnots());
mWindValue.setText(sensorData);
}
}
@@ -269,9 +298,12 @@ public class MainScheduleFragment extends BaseFragment implements View.OnClickLi
} else {
fragment.setArguments(getRecentArguments());
}
if (mStartTime != null) {
fragment.getArguments().putSerializable(START_TIME, mStartTime);
}
Bundle args = fragment.getArguments();
args.putSerializable(START_TIME, mStartTime);
args.putSerializable(START_TIME_DIFF, mStartTimeDiff);
args.putSerializable(DEPENDENT_RACE, mRaceId);
getFragmentManager().beginTransaction().replace(R.id.racing_view_container, fragment).commitAllowingStateLoss();
}
@@ -108,15 +108,11 @@ public class MoreFlagsFragment extends BaseFragment implements MoreFlagItemClick
mDateFormat = new SimpleDateFormat("HH:mm:ss", getResources().getConfiguration().locale);
View header = ViewHolder.get(layout, R.id.header_text);
if (header != null) {
// header.setOnClickListener(this);
}
mTimePicker = ViewHolder.get(layout, R.id.time_picker);
if (mTimePicker != null) {
Calendar calendar = Calendar.getInstance();
ThemeHelper.setPickerTextColor(getActivity(), mTimePicker, ThemeHelper.getColor(getActivity(), R.attr.white));
ThemeHelper.setPickerColor(getActivity(), mTimePicker, ThemeHelper.getColor(getActivity(), R.attr.white), ThemeHelper
.getColor(getActivity(), R.attr.sap_yellow_1));
mTimePicker.setIs24HourView(true);
mTimePicker.setCurrentHour(calendar.get(Calendar.HOUR_OF_DAY));
}
@@ -133,26 +129,41 @@ public class MoreFlagsFragment extends BaseFragment implements MoreFlagItemClick
finishCustom.setOnClickListener(this);
}
return layout;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
switch (getArguments().getInt(START_MODE, 0)) {
case 1: // Race-State: Finishing -> End Finishing
ImageView flag = ViewHolder.get(layout, R.id.header_flag);
View header = ViewHolder.get(getView(), R.id.header_text);
if (header != null) {
header.setOnClickListener(this);
}
View back = ViewHolder.get(getView(), R.id.header_back);
if (back != null) {
back.setVisibility(View.VISIBLE);
}
ImageView flag = ViewHolder.get(getView(), R.id.header_flag);
if (flag != null) {
int resId = R.drawable.flag_blue_48dp;
Drawable drawable = BitmapHelper.getDrawable(getActivity(), resId);
flag.setImageDrawable(drawable);
}
TextView headline = ViewHolder.get(layout, R.id.header_headline);
TextView headline = ViewHolder.get(getView(), R.id.header_headline);
if (headline != null) {
headline.setText(getString(R.string.race_end_finish_header));
headline.setText(getString(R.string.race_end_finish_header, mDateFormat.format(getRaceState().getFinishingTime().asMillis())));
}
break;
default: // Race-State: Running -> Start Finishing
break;
}
return layout;
}
@Override
@@ -181,7 +192,7 @@ public class MoreFlagsFragment extends BaseFragment implements MoreFlagItemClick
break;
default:
// currently unused, because of no other button
sendIntent(AppConstants.INTENT_ACTION_SHOW_MAIN_CONTENT);
break;
}
}
@@ -9,7 +9,6 @@ import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -18,13 +17,13 @@ import android.widget.ImageView;
import android.widget.Toast;
import com.sap.sailing.android.shared.logging.ExLog;
import com.sap.sailing.android.shared.util.ViewHolder;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.AppPreferences;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.ui.adapters.finishing.FinishListPhotoAdapter;
import com.sap.sailing.racecommittee.app.ui.views.DividerItemDecoration;
import com.sap.sailing.racecommittee.app.utils.CameraHelper;
import com.sap.sailing.racecommittee.app.utils.MailHelper;
import com.sap.sailing.racecommittee.app.utils.RaceHelper;
import com.sap.sailing.racecommittee.app.utils.StringHelper;
import java.io.File;
@@ -173,35 +172,16 @@ public class PhotoListFragment extends BaseFragment {
private String getSubject() {
String author = StringHelper.on(getActivity()).getAuthor(preferences.getAuthor().getName());
return getString(R.string.results_mail_subject, author, getRaceName());
return getString(R.string.results_mail_subject, author, RaceHelper.getRaceName(getRace()));
}
private String getBody() {
StringBuilder builder = new StringBuilder();
builder.append(getString(R.string.results_mail_body, getRaceName()));
builder.append(getString(R.string.results_mail_body, RaceHelper.getRaceName(getRace())));
builder.append(getString(R.string.results_mail_body_race_group, getRace().getRaceGroup().getName()));
builder.append(getString(R.string.results_mail_body_boat_class, getRace().getRaceGroup().getBoatClass().getName()));
builder.append(getString(R.string.results_mail_body_start, mDateFormat.format(getRaceState().getStartTime().asDate())));
builder.append(getString(R.string.results_mail_body_finish, mDateFormat.format(getRaceState().getFinishedTime().asDate())));
return builder.toString();
}
private String getRaceName() {
String name = getRace().getRaceGroup().getDisplayName();
if (TextUtils.isEmpty(name)) {
name = getRace().getRaceGroup().getName();
}
if (!getRace().getSeries().getName().equals(AppConstants.DEFAULT)) {
name += " - " + getRace().getSeries().getName();
}
if (!getRace().getFleet().getName().equals(AppConstants.DEFAULT)) {
name += " - " + getRace().getFleet().getName();
}
name += " - " + getRace().getName();
return name;
}
}
@@ -131,7 +131,7 @@ public class RaceFlagViewerFragment extends BaseFragment {
}
}
} else {
if (mLayout != null && mFlagCache.nextPole != null) {
if (mFlagCache.nextPole != null) {
for (int i = 0; i < mLayout.getChildCount(); i++) {
ImageView flagImage = ViewHolder.get(mLayout.getChildAt(i), R.id.flag);
Flags flags = (Flags) flagImage.getTag();
@@ -108,7 +108,8 @@ public class RaceTimeChangeFragment extends BaseFragment implements View.OnClick
default:
// use default values
}
ThemeHelper.setPickerTextColor(getActivity(), mDatePicker, ThemeHelper.getColor(getActivity(), R.attr.white));
ThemeHelper.setPickerColor(getActivity(), mDatePicker, ThemeHelper.getColor(getActivity(), R.attr.white), ThemeHelper
.getColor(getActivity(), R.attr.sap_yellow_1));
TimeUtils.initDatePicker(getActivity(), mDatePicker, calendar, mPastDays, mFutureDays, false);
mDatePicker.setValue(Math.abs(mPastDays));
mDatePicker.setTag(calendar);
@@ -119,7 +120,8 @@ public class RaceTimeChangeFragment extends BaseFragment implements View.OnClick
mTimePicker = (TimePicker) layout.findViewById(R.id.time_picker);
if (mTimePicker != null) {
ThemeHelper.setPickerTextColor(getActivity(), mTimePicker, ThemeHelper.getColor(getActivity(), R.attr.white));
ThemeHelper.setPickerColor(getActivity(), mTimePicker, ThemeHelper.getColor(getActivity(), R.attr.white), ThemeHelper
.getColor(getActivity(), R.attr.sap_yellow_1));
mTimePicker.setIs24HourView(true);
mTimePicker.setCurrentHour(calendar.get(Calendar.HOUR_OF_DAY));
mTimePicker.setCurrentMinute(calendar.get(Calendar.MINUTE));
@@ -127,7 +129,8 @@ public class RaceTimeChangeFragment extends BaseFragment implements View.OnClick
mSecondPicker = (NumberPicker) layout.findViewById(R.id.second_picker);
if (mSecondPicker != null) {
ThemeHelper.setPickerTextColor(getActivity(), mTimePicker, ThemeHelper.getColor(getActivity(), R.attr.white));
ThemeHelper.setPickerColor(getActivity(), mTimePicker, ThemeHelper.getColor(getActivity(), R.attr.white), ThemeHelper
.getColor(getActivity(), R.attr.sap_yellow_1));
mSecondPicker.setVisibility(View.VISIBLE);
mSecondPicker.setMinValue(0);
mSecondPicker.setMaxValue(59);
@@ -1,39 +1,80 @@
package com.sap.sailing.racecommittee.app.ui.fragments.raceinfo;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.NumberPicker;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.TimePicker;
import com.sap.sailing.android.shared.util.ViewHolder;
import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
import com.sap.sailing.domain.abstractlog.race.impl.SimpleRaceLogIdentifierImpl;
import com.sap.sailing.domain.abstractlog.race.state.RaceStateChangedListener;
import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState;
import com.sap.sailing.domain.abstractlog.race.state.impl.BaseRaceStateChangedListener;
import com.sap.sailing.domain.common.impl.NaturalComparator;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.AppPreferences;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.data.DataStore;
import com.sap.sailing.racecommittee.app.data.OnlineDataManager;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.domain.impl.FleetIdentifierImpl;
import com.sap.sailing.racecommittee.app.domain.impl.RaceGroupSeriesFleet;
import com.sap.sailing.racecommittee.app.ui.adapters.DependentRaceSpinnerAdapter;
import com.sap.sailing.racecommittee.app.ui.adapters.DependentRaceSpinnerAdapter.RaceData;
import com.sap.sailing.racecommittee.app.ui.fragments.RaceFragment;
import com.sap.sailing.racecommittee.app.utils.BitmapHelper;
import com.sap.sailing.racecommittee.app.utils.RaceHelper;
import com.sap.sailing.racecommittee.app.utils.ThemeHelper;
import com.sap.sailing.racecommittee.app.utils.TimeUtils;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsDurationImpl;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import java.io.Serializable;
import java.util.Calendar;
public class StartTimeFragment extends BaseFragment
implements View.OnClickListener, NumberPicker.OnValueChangeListener, TimePicker.OnTimeChangedListener {
public static final int MODE_SETUP = 0;
public static final int MODE_1 = 1;
public static final int MODE_TIME_PANEL = 2;
private static final String START_MODE = "startMode";
private static final int FUTURE_DAYS = 25;
private static final int PAST_DAYS = -3;
private static final int MAX_DIFF_MIN = 60;
private static final String ZERO_TIME = "-00:00:00";
private static final int ABSOLUTE = 0;
private static final int RELATIVE = 1;
private View mAbsolute;
private View mRelative;
private Button mAbsoluteButton;
private Button mRelativeButton;
private NumberPicker mDatePicker;
private NumberPicker mTimeOffset;
private Spinner mDependentRace;
private TimePicker mTimePicker;
private TextView mCountdown;
private TextView mDebugTime;
@@ -43,7 +84,10 @@ public class StartTimeFragment extends BaseFragment
private Calendar mTimeLeft;
private Calendar mTimeRight;
private Calendar mCalendar;
private String mRaceId;
private Duration mStartTimeOffset;
private boolean mListenerIgnore = true;
private DependentRaceSpinnerAdapter mAdapter;
/**
* Listens for start time changes
@@ -62,11 +106,11 @@ public class StartTimeFragment extends BaseFragment
return fragment;
}
public static StartTimeFragment newInstance(Serializable timePoint) {
StartTimeFragment fragment = newInstance(0);
if (timePoint != null) {
Bundle args = fragment.getArguments();
args.putSerializable(MainScheduleFragment.START_TIME, timePoint);
public static StartTimeFragment newInstance(Bundle extraArgs) {
StartTimeFragment fragment = newInstance(MODE_SETUP);
Bundle args = fragment.getArguments();
if (extraArgs != null) {
args.putAll(extraArgs);
}
return fragment;
}
@@ -75,6 +119,36 @@ public class StartTimeFragment extends BaseFragment
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.race_schedule_start_time, container, false);
mAbsolute = ViewHolder.get(layout, R.id.time_absolute);
mRelative = ViewHolder.get(layout, R.id.time_relative);
if (preferences.isDependentRacesAllowed()) {
View view = ViewHolder.get(layout, R.id.tab_button);
if (view != null) {
view.setVisibility(View.VISIBLE);
}
mAbsoluteButton = ViewHolder.get(layout, R.id.absolute);
if (mAbsoluteButton != null) {
mAbsoluteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showTab(ABSOLUTE);
}
});
}
mRelativeButton = ViewHolder.get(layout, R.id.relative);
if (mRelativeButton != null) {
mRelativeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showTab(RELATIVE);
}
});
}
}
mCountdown = ViewHolder.get(layout, R.id.start_countdown);
mMinuteInc = ViewHolder.get(layout, R.id.minute_inc);
if (mMinuteInc != null) {
@@ -86,13 +160,17 @@ public class StartTimeFragment extends BaseFragment
mMinuteDec.setOnClickListener(this);
}
Button setStart = ViewHolder.get(layout, R.id.set_date_time);
if (setStart != null) {
setStart.setOnClickListener(this);
View setStartAbsolute = ViewHolder.get(layout, R.id.set_start_time_absolute);
if (setStartAbsolute != null) {
setStartAbsolute.setOnClickListener(this);
}
View setStartRelative = ViewHolder.get(layout, R.id.set_start_time_relative);
if (setStartRelative != null) {
setStartRelative.setOnClickListener(this);
}
mDebugTime = ViewHolder.get(layout, R.id.debug_time);
return layout;
}
@@ -122,32 +200,10 @@ public class StartTimeFragment extends BaseFragment
}
};
Calendar time = Calendar.getInstance();
if (getArguments() != null) {
int startMode = getArguments().getInt(START_MODE, 0);
switch (startMode) {
case 0:
mStartTime = (TimePoint) getArguments().getSerializable(MainScheduleFragment.START_TIME);
if (mStartTime != null) {
time.setTime(mStartTime.asDate());
}
break;
case 2:
if (getRace() != null && getRaceState() != null) {
mStartTime = getRaceState().getStartTime();
time.setTime(mStartTime.asDate());
}
break;
default:
break;
}
}
if (getView() != null) {
if (getArguments() != null) {
switch (getArguments().getInt(START_MODE, 0)) {
case 1:
switch (getArguments().getInt(START_MODE, MODE_SETUP)) {
case MODE_1:
View header = ViewHolder.get(getView(), R.id.header_text);
if (header != null) {
header.setOnClickListener(this);
@@ -158,47 +214,144 @@ public class StartTimeFragment extends BaseFragment
}
break;
case 2:
case MODE_TIME_PANEL:
if (getRace() != null && getRaceState() != null) {
mStartTime = getRaceState().getStartTime();
if (mStartTime != null) {
time.setTime(mStartTime.asDate());
}
}
View frame = ViewHolder.get(getView(), R.id.header);
if (frame != null) {
frame.setVisibility(View.GONE);
}
break;
default:
default: // MODE_SETUP
mStartTime = (TimePoint) getArguments().getSerializable(MainScheduleFragment.START_TIME);
if (mStartTime != null) {
time.setTime(mStartTime.asDate());
}
mStartTimeOffset = (Duration) getArguments().getSerializable(MainScheduleFragment.START_TIME_DIFF);
mRaceId = (String) getArguments().getSerializable(MainScheduleFragment.DEPENDENT_RACE);
View syncButtons = ViewHolder.get(getView(), R.id.buttonBar);
if (syncButtons != null) {
syncButtons.setVisibility(View.GONE);
}
break;
}
}
mDatePicker = ViewHolder.get(getView(), R.id.date_picker);
if (mDatePicker != null) {
ThemeHelper.setPickerTextColor(getActivity(), mDatePicker, ThemeHelper.getColor(getActivity(), R.attr.white));
mDatePicker.setOnValueChangedListener(this);
TimeUtils.initDatePicker(getActivity(), mDatePicker, time, PAST_DAYS, FUTURE_DAYS);
mDatePicker.setValue(Math.abs(PAST_DAYS));
if (mRaceId == null && mStartTimeOffset == null) {
showTab(ABSOLUTE);
} else {
showTab(RELATIVE);
}
mTimePicker = ViewHolder.get(getView(), R.id.time_picker);
if (mTimePicker != null) {
ThemeHelper.setPickerTextColor(getActivity(), mTimePicker, ThemeHelper.getColor(getActivity(), R.attr.white));
mTimePicker.setOnTimeChangedListener(this);
mTimePicker.setIs24HourView(true);
int hours = time.get(Calendar.HOUR_OF_DAY);
int minutes = time.get(Calendar.MINUTE);
if (getArguments() != null && getArguments().getInt(START_MODE, 0) != 2
&& getArguments().getSerializable(MainScheduleFragment.START_TIME) == null) {
// In 10 minutes from now, but always a 5-minute-mark.
time.add(Calendar.MINUTE, 10);
hours = time.get(Calendar.HOUR_OF_DAY);
minutes = time.get(Calendar.MINUTE);
minutes = (int) (Math.ceil((minutes / 5.0)) * 5.0);
if (minutes >= 60) {
hours++;
initViewsAbsolute(time);
initViewsRelative();
}
}
private void initViewsRelative() {
mTimeOffset = ViewHolder.get(getView(), R.id.time_offset);
if (mTimeOffset != null) {
ThemeHelper.setPickerColor(getActivity(), mTimeOffset, ThemeHelper.getColor(getActivity(), R.attr.white), ThemeHelper
.getColor(getActivity(), R.attr.sap_yellow_1));
mTimeOffset.setMinValue(0);
mTimeOffset.setMaxValue(MAX_DIFF_MIN);
mTimeOffset.setWrapSelectorWheel(false);
mTimeOffset.setValue((mStartTimeOffset == null) ? preferences.getDependentRacesOffset() : (int) mStartTimeOffset.asMinutes());
}
mDependentRace = ViewHolder.get(getView(), R.id.dependent_race);
if (mDependentRace != null) {
int position = 1;
mAdapter = new DependentRaceSpinnerAdapter(getActivity(), R.layout.dependent_race_item);
DataStore manager = OnlineDataManager.create(getActivity()).getDataStore();
Map<RaceGroupSeriesFleet, List<ManagedRace>> mGroupHeaders = new LinkedHashMap<>();
List<ManagedRace> sortedRaces = new ArrayList<>(manager.getRaces());
Collections.sort(sortedRaces, new Comparator<ManagedRace>() {
@Override
public int compare(ManagedRace lhs, ManagedRace rhs) {
return new NaturalComparator().compare(lhs.getId(), rhs.getId());
}
});
for (ManagedRace race : sortedRaces) {
RaceGroupSeriesFleet container = new RaceGroupSeriesFleet(race);
if (!mGroupHeaders.containsKey(container)) {
mGroupHeaders.put(container, new LinkedList<ManagedRace>());
}
mGroupHeaders.get(container).add(race);
}
for (RaceGroupSeriesFleet races : mGroupHeaders.keySet()) {
RaceData header = new RaceData(RaceHelper.getRaceGroupName(races.getRaceGroup()), RaceHelper
.getFleetSeries(races.getFleet(), races.getSeries()), null);
mAdapter.add(header);
for (ManagedRace race : mGroupHeaders.get(races)) {
// not current race
if (getRace() != null && !race.getId().equals(getRace().getId())) {
if (mRaceId != null && race.getId().equals(mRaceId)) {
position = mAdapter.getCount();
}
RaceData items = new RaceData(race.getRaceName(), null, race);
mAdapter.add(items);
}
}
mTimePicker.setCurrentHour(hours);
mTimePicker.setCurrentMinute(minutes);
mTimePicker.setTag(time.get(Calendar.SECOND));
}
mDependentRace.setAdapter(mAdapter);
mDependentRace.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
mAdapter.setSelected(position);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
mAdapter.setSelected(-1);
}
});
mDependentRace.setSelection(position);
}
}
private void initViewsAbsolute(Calendar time) {
mDatePicker = ViewHolder.get(getView(), R.id.start_date_picker);
if (mDatePicker != null) {
ThemeHelper.setPickerColor(getActivity(), mDatePicker, ThemeHelper.getColor(getActivity(), R.attr.white), ThemeHelper
.getColor(getActivity(), R.attr.sap_yellow_1));
mDatePicker.setOnValueChangedListener(this);
TimeUtils.initDatePicker(getActivity(), mDatePicker, time, PAST_DAYS, FUTURE_DAYS);
mDatePicker.setValue(Math.abs(PAST_DAYS));
}
mTimePicker = ViewHolder.get(getView(), R.id.start_time_picker);
if (mTimePicker != null) {
ThemeHelper.setPickerColor(getActivity(), mTimePicker, ThemeHelper.getColor(getActivity(), R.attr.white), ThemeHelper
.getColor(getActivity(), R.attr.sap_yellow_1));
mTimePicker.setOnTimeChangedListener(this);
mTimePicker.setIs24HourView(true);
int hours = time.get(Calendar.HOUR_OF_DAY);
int minutes = time.get(Calendar.MINUTE);
if (getArguments() != null && getArguments().getInt(START_MODE, MODE_SETUP) != MODE_TIME_PANEL && mRaceId == null
&& mStartTimeOffset == null) {
// In 10 minutes from now, but always a 5-minute-mark.
time.add(Calendar.MINUTE, 10);
hours = time.get(Calendar.HOUR_OF_DAY);
minutes = time.get(Calendar.MINUTE);
minutes = (int) (Math.ceil((minutes / 5.0)) * 5.0);
if (minutes >= 60) {
hours++;
}
}
mTimePicker.setCurrentHour(hours);
mTimePicker.setCurrentMinute(minutes);
mTimePicker.setTag(time.get(Calendar.SECOND));
}
}
@@ -206,62 +359,113 @@ public class StartTimeFragment extends BaseFragment
public void notifyTick(TimePoint now) {
super.notifyTick(now);
int resId;
TimePoint timePoint;
String time;
String timeLeft;
String timeRight;
if (mStartTime == null) {
mStartTime = getPickerTime();
}
if (mStartTime.after(now)) {
resId = R.string.race_start_time_in;
timePoint = mStartTime.minus(now.asMillis());
setButtonTime(timePoint, false);
time = TimeUtils.formatDurationUntil(timePoint.asMillis());
timeLeft = TimeUtils.formatDurationUntil(mTimeLeft.getTimeInMillis());
timeRight = TimeUtils.formatDurationUntil(mTimeRight.getTimeInMillis());
if (timeRight.equals(time)) {
mTimeRight.add(Calendar.MINUTE, 1);
if (mAbsolute.getVisibility() == View.VISIBLE) {
int resId;
TimePoint timePoint;
String time;
String timeLeft;
String timeRight;
if (mStartTime == null) {
mStartTime = getPickerTime();
}
if (mStartTime.after(now)) {
resId = R.string.race_start_time_in;
timePoint = mStartTime.minus(now.asMillis());
setButtonTime(timePoint, false);
time = TimeUtils.formatDurationUntil(timePoint.asMillis());
timeLeft = TimeUtils.formatDurationUntil(mTimeLeft.getTimeInMillis());
timeRight = TimeUtils.formatDurationUntil(mTimeRight.getTimeInMillis());
}
} else {
resId = R.string.race_start_time_ago;
timePoint = now.minus(mStartTime.asMillis());
setButtonTime(timePoint, true);
time = TimeUtils.formatDurationSince(timePoint.asMillis());
timeLeft = TimeUtils.formatDurationSince(mTimeLeft.getTimeInMillis());
timeRight = TimeUtils.formatDurationSince(mTimeRight.getTimeInMillis());
if (timeRight.equals(time)) {
mTimeRight.add(Calendar.MINUTE, -1);
if (timeRight.equals(time)) {
mTimeRight.add(Calendar.MINUTE, 1);
timeRight = TimeUtils.formatDurationUntil(mTimeRight.getTimeInMillis());
}
} else {
resId = R.string.race_start_time_ago;
timePoint = now.minus(mStartTime.asMillis());
setButtonTime(timePoint, true);
time = TimeUtils.formatDurationSince(timePoint.asMillis());
timeLeft = TimeUtils.formatDurationSince(mTimeLeft.getTimeInMillis());
timeRight = TimeUtils.formatDurationSince(mTimeRight.getTimeInMillis());
if (timeRight.equals(time)) {
mTimeRight.add(Calendar.MINUTE, -1);
timeRight = TimeUtils.formatDurationSince(mTimeRight.getTimeInMillis());
}
}
if (mCountdown != null) {
String countdown = getString(resId, time);
mCountdown.setText(countdown);
mCountdown.setTag(resId);
}
if (mMinuteDec != null) {
String countdown = getString(resId, timeLeft);
if (ZERO_TIME.equals(countdown)) {
countdown = countdown.substring(1);
}
mMinuteDec.setText(countdown);
}
if (mMinuteInc != null) {
String countdown = getString(resId, timeRight);
if (ZERO_TIME.equals(countdown)) {
countdown = countdown.substring(1);
}
mMinuteInc.setText(countdown);
}
if (mDebugTime != null) {
mDebugTime.setText(mStartTime.asDate().toString());
}
}
}
if (mCountdown != null) {
String countdown = getString(resId).replace("#TIME#", time);
mCountdown.setText(countdown);
mCountdown.setTag(resId);
private void showTab(int tab) {
int colorGrey = ThemeHelper.getColor(getActivity(), R.attr.sap_light_gray);
int colorOrange = ThemeHelper.getColor(getActivity(), R.attr.sap_yellow_1);
if (mAbsolute != null) {
mAbsolute.setVisibility(View.GONE);
}
if (mRelative != null) {
mRelative.setVisibility(View.GONE);
}
if (mAbsoluteButton != null) {
mAbsoluteButton.setTextColor(colorGrey);
BitmapHelper.setBackground(mAbsoluteButton, null);
}
if (mRelativeButton != null) {
mRelativeButton.setTextColor(colorGrey);
BitmapHelper.setBackground(mRelativeButton, null);
}
if (mMinuteDec != null) {
String countdown = getString(resId).replace("#TIME#", timeLeft);
if (countdown.equals("-00:00:00")) {
countdown = "00:00:00";
int id;
if (AppConstants.LIGHT_THEME.equals(AppPreferences.on(getActivity()).getTheme())) {
id = R.drawable.nav_drawer_tab_button_light;
} else {
id = R.drawable.nav_drawer_tab_button_dark;
}
Drawable drawable = BitmapHelper.getDrawable(getActivity(), id);
switch (tab) {
case RELATIVE:
if (mRelative != null) {
mRelative.setVisibility(View.VISIBLE);
}
mMinuteDec.setText(countdown);
}
if (mMinuteInc != null) {
String countdown = getString(resId).replace("#TIME#", timeRight);
if (countdown.equals("-00:00:00")) {
countdown = "00:00:00";
if (mRelativeButton != null) {
mRelativeButton.setTextColor(colorOrange);
BitmapHelper.setBackground(mRelativeButton, drawable);
}
mMinuteInc.setText(countdown);
}
break;
if (mDebugTime != null) {
mDebugTime.setText(mStartTime.asDate().toString());
default: // ABSOLUTE
if (mAbsolute != null) {
mAbsolute.setVisibility(View.VISIBLE);
}
if (mAbsoluteButton != null) {
mAbsoluteButton.setTextColor(colorOrange);
BitmapHelper.setBackground(mAbsoluteButton, drawable);
}
break;
}
}
@@ -315,10 +519,15 @@ public class StartTimeFragment extends BaseFragment
setPickerTime();
break;
case R.id.set_date_time:
case R.id.set_start_time_absolute:
changeFragment(mStartTime);
break;
case R.id.set_start_time_relative:
ManagedRace race = mAdapter.getRaceAtPosition(mDependentRace.getSelectedItemPosition());
changeFragment(MillisecondsTimePoint.now(), new MillisecondsDurationImpl(mTimeOffset.getValue() * 60 * 1000), race.getId());
break;
case R.id.header_text:
changeFragment();
break;
@@ -351,39 +560,62 @@ public class StartTimeFragment extends BaseFragment
int days = TimeUtils.daysBetween(today, newTime) + Math.abs(PAST_DAYS);
mDatePicker.setValue(days);
mTimePicker.setCurrentHour(newTime.get(Calendar.HOUR_OF_DAY));
mTimePicker.setCurrentMinute(newTime.get(Calendar.MINUTE));
if (mDatePicker != null) {
mDatePicker.setValue(days);
}
if (mTimePicker != null) {
mTimePicker.setCurrentHour(newTime.get(Calendar.HOUR_OF_DAY));
mTimePicker.setCurrentMinute(newTime.get(Calendar.MINUTE));
}
}
private TimePoint getPickerTime() {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, mDatePicker.getValue() + PAST_DAYS);
calendar.set(Calendar.HOUR_OF_DAY, mTimePicker.getCurrentHour());
calendar.set(Calendar.MINUTE, mTimePicker.getCurrentMinute());
if (mDatePicker != null) {
calendar.add(Calendar.DAY_OF_MONTH, mDatePicker.getValue() + PAST_DAYS);
}
if (mTimePicker != null) {
calendar.set(Calendar.HOUR_OF_DAY, mTimePicker.getCurrentHour());
calendar.set(Calendar.MINUTE, mTimePicker.getCurrentMinute());
}
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return new MillisecondsTimePoint(calendar.getTime());
}
private void changeFragment() {
changeFragment(null);
changeFragment(null, null, null);
}
private void changeFragment(TimePoint startTime) {
changeFragment(startTime, null, null);
}
private void changeFragment(TimePoint startTime, Duration startTimeDiff, String raceId) {
int viewId = R.id.racing_view_container;
TimePoint now = MillisecondsTimePoint.now();
RaceFragment fragment = MainScheduleFragment.newInstance();
Bundle args = getRecentArguments();
RacingProcedureType procedureType = getRaceState().getTypedRacingProcedure().getType();
getRaceState().setRacingProcedure(MillisecondsTimePoint.now(), procedureType);
getRaceState().setRacingProcedure(now, procedureType);
if (getArguments() != null && startTime != null) {
if (getArguments().getInt(START_MODE, 0) != 0) {
getRaceState().forceNewStartTime(MillisecondsTimePoint.now(), startTime);
if (getArguments().getInt(START_MODE, MODE_SETUP) != MODE_SETUP) {
if (startTimeDiff == null && raceId == null) {
// absolute start time
getRaceState().forceNewStartTime(now, startTime);
} else {
// relative start time
Util.Triple<String, String, String> triple = FleetIdentifierImpl.unescape(raceId);
SimpleRaceLogIdentifier identifier = new SimpleRaceLogIdentifierImpl(triple.getA(), triple.getB(), triple.getC());
getRaceState().forceNewDependentStartTime(now, startTimeDiff, identifier);
}
fragment = RaceFlagViewerFragment.newInstance();
viewId = R.id.race_frame;
}
args.putAll(getArguments());
args.putSerializable(MainScheduleFragment.START_TIME, startTime);
args.putSerializable(MainScheduleFragment.START_TIME_DIFF, startTimeDiff);
args.putSerializable(MainScheduleFragment.DEPENDENT_RACE, raceId);
}
fragment.setArguments(args);
getFragmentManager().beginTransaction().replace(viewId, fragment).commit();
@@ -57,8 +57,7 @@ public class BitmapHelper {
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
@@ -100,8 +99,7 @@ public class BitmapHelper {
public static void setBackground(View view, Drawable drawable) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.setBackground(drawable);
}
else{
} else {
view.setBackgroundDrawable(drawable);
}
}
@@ -120,7 +118,7 @@ public class BitmapHelper {
}
public static Drawable getTintedDrawable(Context context, @DrawableRes int drawableResId, @ColorRes int color) {
Drawable drawable = BitmapHelper.getDrawable(context, drawableResId);
Drawable drawable = getDrawable(context, drawableResId);
drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
return drawable;
}
@@ -0,0 +1,26 @@
package com.sap.sailing.racecommittee.app.utils;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.state.RaceState;
import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl;
import com.sap.sailing.domain.base.configuration.ConfigurationLoader;
import com.sap.sailing.domain.base.configuration.RegattaConfiguration;
import com.sap.sailing.racecommittee.app.data.AndroidRaceLogResolver;
public class ManagedRaceCalculator {
private RaceLog raceLog;
private AbstractLogEventAuthor author;
private ConfigurationLoader<RegattaConfiguration> configuration;
public ManagedRaceCalculator(RaceLog raceLog, AbstractLogEventAuthor author, ConfigurationLoader<RegattaConfiguration> configuration) {
this.raceLog = raceLog;
this.author = author;
this.configuration = configuration;
}
public RaceState calculateRaceState(){
return RaceStateImpl.create(new AndroidRaceLogResolver(), raceLog, author, configuration);
}
}
@@ -0,0 +1,114 @@
package com.sap.sailing.racecommittee.app.utils;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.SeriesBase;
import com.sap.sailing.domain.base.racegroup.RaceGroup;
import com.sap.sailing.domain.common.LeaderboardNameConstants;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
public class RaceHelper {
public static String getRaceName(@Nullable ManagedRace race) {
return getRaceName(race, null);
}
public static String getRaceName(@Nullable ManagedRace race, @Nullable String delimiter) {
if (TextUtils.isEmpty(delimiter)) {
delimiter = " - ";
}
String raceName = "";
if (race != null) {
raceName = getRaceGroupName(race);
raceName += getSeriesName(race.getSeries(), delimiter);
raceName += getFleetName(race.getFleet(), delimiter);
raceName += delimiter + race.getRaceName();
}
return raceName;
}
public static String getRaceGroupName(@Nullable ManagedRace race) {
String raceGroupName = "";
if (race != null) {
raceGroupName = getRaceGroupName(race.getRaceGroup());
}
return raceGroupName;
}
public static String getRaceGroupName(@Nullable RaceGroup raceGroup) {
String raceGroupName = "";
if (raceGroup != null) {
raceGroupName = raceGroup.getDisplayName();
if (TextUtils.isEmpty(raceGroupName)) {
raceGroupName = raceGroup.getName();
}
}
return raceGroupName;
}
public static String getFleetSeries(@Nullable ManagedRace race) {
String fleetSeries = "";
if (race != null) {
fleetSeries = getFleetSeries(race.getFleet(), race.getSeries());
}
return fleetSeries;
}
public static String getFleetSeries(@Nullable Fleet fleet, @Nullable SeriesBase series) {
return getFleetSeries(fleet, series, null);
}
public static String getFleetSeries(@Nullable Fleet fleet, @Nullable SeriesBase series, @Nullable String delimiter) {
if (TextUtils.isEmpty(delimiter)) {
delimiter = " - ";
}
String fleetSeries = "";
fleetSeries += getFleetName(fleet, "");
if (!TextUtils.isEmpty(fleetSeries)) {
fleetSeries += delimiter;
}
fleetSeries += getSeriesName(series, "");
return fleetSeries;
}
public static String getSeriesName(@Nullable SeriesBase series) {
return getSeriesName(series, null);
}
public static String getSeriesName(@Nullable SeriesBase series, @Nullable String delimiter) {
if (delimiter == null) {
delimiter = " - ";
}
String seriesName = "";
if (series != null && !LeaderboardNameConstants.DEFAULT_SERIES_NAME.equals(series.getName())) {
seriesName = delimiter + series.getName();
}
return seriesName;
}
public static String getFleetName(@Nullable Fleet fleet) {
return getFleetName(fleet, null);
}
public static String getFleetName(@Nullable Fleet fleet, @Nullable String delimiter) {
if (delimiter == null) {
delimiter = " - ";
}
String fleetName = "";
if (fleet != null && !LeaderboardNameConstants.DEFAULT_FLEET_NAME.equals(fleet.getName())) {
fleetName = delimiter + fleet.getName();
}
return fleetName;
}
}
@@ -1,7 +1,6 @@
package com.sap.sailing.racecommittee.app.utils;
import android.content.Context;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.R;
@@ -14,8 +13,7 @@ public class StringHelper {
}
public static StringHelper on(Context context) {
StringHelper helper = new StringHelper(context);
return helper;
return new StringHelper(context);
}
public String getAuthor(String author) {
@@ -1,11 +1,10 @@
package com.sap.sailing.racecommittee.app.utils;
import java.lang.reflect.Field;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Paint;
import android.graphics.drawable.ColorDrawable;
import android.support.annotation.AttrRes;
import android.support.annotation.ColorRes;
import android.util.TypedValue;
@@ -13,12 +12,14 @@ import android.view.View;
import android.widget.EditText;
import android.widget.NumberPicker;
import android.widget.TimePicker;
import com.sap.sailing.android.shared.logging.ExLog;
import com.sap.sailing.android.shared.util.ViewHolder;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.AppPreferences;
import com.sap.sailing.racecommittee.app.R;
import java.lang.reflect.Field;
public class ThemeHelper {
private static final String TAG = ThemeHelper.class.getName();
@@ -32,21 +33,19 @@ public class ThemeHelper {
}
}
public static boolean setPickerTextColor(Context context, TimePicker timePicker, @ColorRes int color) {
Resources system = Resources.getSystem();
int hourId = system.getIdentifier("hour", "id", "android");
int minuteId = system.getIdentifier("minute", "id", "android");
NumberPicker hourPicker = (NumberPicker) timePicker.findViewById(hourId);
NumberPicker minutePicker = (NumberPicker) timePicker.findViewById(minuteId);
if (hourPicker != null && setPickerTextColor(context, hourPicker, color)) {
if (minutePicker != null && setPickerTextColor(context, minutePicker, color)) {
return true;
}
public static void setPickerTextColor(Context context, TimePicker timePicker, @ColorRes int color) {
NumberPicker hourPicker = getHourPicker(timePicker);
if (hourPicker != null) {
setPickerTextColor(context, hourPicker, color);
}
NumberPicker minutePicker = getMinutePicker(timePicker);
if (minutePicker != null) {
setPickerTextColor(context, minutePicker, color);
}
return false;
}
public static boolean setPickerTextColor(Context context, NumberPicker numberPicker, @ColorRes int color) {
public static void setPickerTextColor(Context context, NumberPicker numberPicker, @ColorRes int color) {
final int count = numberPicker.getChildCount();
for (int i = 0; i < count; i++) {
View child = numberPicker.getChildAt(i);
@@ -57,7 +56,6 @@ public class ThemeHelper {
((Paint) selectorWheelPaintField.get(numberPicker)).setColor(color);
((EditText) child).setTextColor(color);
numberPicker.invalidate();
return true;
} catch (NoSuchFieldException e) {
ExLog.w(context, TAG, "NoSuchFieldException - " + e.getMessage());
} catch (IllegalAccessException e) {
@@ -67,7 +65,43 @@ public class ThemeHelper {
}
}
}
return false;
}
public static void setPickerDividerColor(Context context, TimePicker timePicker, @ColorRes int color) {
NumberPicker hourPicker = getHourPicker(timePicker);
if (hourPicker != null) {
setPickerDividerColor(context, hourPicker, color);
}
NumberPicker minutePicker = getMinutePicker(timePicker);
if (minutePicker != null) {
setPickerDividerColor(context, minutePicker, color);
}
}
public static void setPickerDividerColor(Context context, NumberPicker numberPicker, @ColorRes int color) {
try {
ColorDrawable drawable = new ColorDrawable(color);
Field selectionDivider = numberPicker.getClass().getDeclaredField("mSelectionDivider");
selectionDivider.setAccessible(true);
selectionDivider.set(numberPicker, drawable);
} catch (NoSuchFieldException e) {
ExLog.w(context, TAG, "NoSuchFieldException - " + e.getMessage());
} catch (IllegalArgumentException e) {
ExLog.w(context, TAG, "IllegalArgumentException - " + e.getMessage());
} catch (IllegalAccessException e) {
ExLog.w(context, TAG, "IllegalAccessException - " + e.getMessage());
}
}
public static void setPickerColor(Context context, TimePicker timePicker, @ColorRes int textColor, @ColorRes int dividerColor) {
setPickerTextColor(context, timePicker, textColor);
setPickerDividerColor(context, timePicker, dividerColor);
}
public static void setPickerColor(Context context, NumberPicker numberPicker, @ColorRes int textColor, @ColorRes int dividerColor) {
setPickerTextColor(context, numberPicker, textColor);
setPickerDividerColor(context, numberPicker, dividerColor);
}
public static @ColorRes int getColor(Context context, @AttrRes int colorId) {
@@ -79,4 +113,16 @@ public class ThemeHelper {
}
return color;
}
private static NumberPicker getHourPicker(TimePicker timePicker) {
Resources system = Resources.getSystem();
int hourId = system.getIdentifier("hour", "id", "android");
return ViewHolder.get(timePicker, hourId);
}
private static NumberPicker getMinutePicker(TimePicker timePicker) {
Resources system = Resources.getSystem();
int minuteId = system.getIdentifier("minute", "id", "android");
return ViewHolder.get(timePicker, minuteId);
}
}