Merge branch 'master' into bug2564

This commit is contained in:
Axel Uhl committed 2016-11-29 18:11:19 +01:00
commit f2b586ea4b
35 files changed
+386 -121

No files matched your search

@@ -1464,7 +1464,13 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
private RaceLogEvent loadRaceLogProtestStartTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, Integer passId, List<Competitor> competitors, DBObject dbObject) {
TimePoint protestStartTime = loadTimePoint(dbObject, FieldNames.RACE_LOG_PROTEST_START_TIME);
return new RaceLogProtestStartTimeEventImpl(createdAt, logicalTimePoint, author, id, passId, protestStartTime);
TimePoint protestEndTime = loadTimePoint(dbObject, FieldNames.RACE_LOG_PROTEST_END_TIME);
if (protestEndTime == null) {
// fallback old data
protestEndTime = protestStartTime.plus(Duration.ONE_MINUTE.times(90));
}
TimeRange protestTime = new TimeRangeImpl(protestStartTime, protestEndTime);
return new RaceLogProtestStartTimeEventImpl(createdAt, logicalTimePoint, author, id, passId, protestTime);
}
private RaceLogEvent loadRaceLogStartProcedureChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author,
@@ -97,8 +97,8 @@ public enum FieldNames {
WAYPOINT_PASSINGINSTRUCTIONS, CONTROLPOINT, CONTROLPOINT_CLASS, MARK_ID, MARK_COLOR, MARK_NAME, MARK_PATTERN, MARK_SHAPE, MARK_TYPE,
CONTROLPOINT_VALUE, CONTROLPOINTWITHTWOMARKS_ID, CONTROLPOINTWITHTWOMARKS_NAME, CONTROLPOINTWITHTWOMARKS_LEFT, CONTROLPOINTWITHTWOMARKS_RIGHT,
RACE_LOG_POSITIONED_COMPETITORS, RACE_LOG_PATHFINDER_ID, RACE_LOG_GATE_LINE_OPENING_TIME, RACE_LOG_GOLF_DOWN_TIME, RACE_LOG_START_PROCEDURE_TYPE,
RACE_LOG_PROTEST_START_TIME, RACE_LOG_COURSE_DESIGN_NAME, RACE_LOG_REVOKED_EVENT_ID, RACE_LOG_REVOKED_EVENT_TYPE, RACE_LOG_REVOKED_EVENT_SHORT_INFO,
RACE_LOG_REVOKED_REASON, RACE_LOG_DEVICE_MAPPING_EVENT_ID,
RACE_LOG_PROTEST_START_TIME, RACE_LOG_PROTEST_END_TIME, RACE_LOG_COURSE_DESIGN_NAME, RACE_LOG_REVOKED_EVENT_ID, RACE_LOG_REVOKED_EVENT_TYPE,
RACE_LOG_REVOKED_EVENT_SHORT_INFO, RACE_LOG_REVOKED_REASON, RACE_LOG_DEVICE_MAPPING_EVENT_ID,
RACE_LOG_CLOSING_TIMEPOINT, TIMEPOINT_OF_FIXED_MARKPASSING, INDEX_OF_PASSED_WAYPOINT,INDEX_OF_FIRST_SUPPRESSED_WAYPOINT, MARK, RACE_LOG_COMPETITOR_ID,
RACE_LOG_DEPDENDENT_ON_FLEET, RACE_LOG_DEPDENDENT_ON_RACECOLUMN, RACE_LOG_DEPDENDENT_ON_REGATTALIKE,
RACE_LOG_START_TIME_DIFFERENCE_IN_MS, RACE_LOG_FINISHING_TIME_AS_MILLIS,
@@ -924,7 +924,8 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
DBObject result = new BasicDBObject();
storeRaceLogEventProperties(event, result);
result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogProtestStartTimeEvent.class.getSimpleName());
storeTimePoint(event.getProtestStartTime(), result, FieldNames.RACE_LOG_PROTEST_START_TIME);
storeTimePoint(event.getProtestTime().from(), result, FieldNames.RACE_LOG_PROTEST_START_TIME);
storeTimePoint(event.getProtestTime().to(), result, FieldNames.RACE_LOG_PROTEST_END_TIME);
return result;
}
@@ -13,21 +13,21 @@ 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.RaceLogProtestStartTimeEvent;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.ProtestStartTimeFinder;
import com.sap.sse.common.TimePoint;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.ProtestTimeFinder;
import com.sap.sse.common.TimeRange;
public class ProtestStartTimeFinderTest extends PassAwareRaceLogAnalyzerTest<ProtestStartTimeFinder, TimePoint> {
public class ProtestStartTimeFinderTest extends PassAwareRaceLogAnalyzerTest<ProtestTimeFinder, TimeRange> {
@Override
protected ProtestStartTimeFinder createAnalyzer(RaceLog raceLog) {
return new ProtestStartTimeFinder(raceLog);
protected ProtestTimeFinder createAnalyzer(RaceLog raceLog) {
return new ProtestTimeFinder(raceLog);
}
@Override
protected TargetPair getTargetEventsAndResultForPassAwareTests(int passId, AbstractLogEventAuthor author) {
RaceLogProtestStartTimeEvent event = createEvent(RaceLogProtestStartTimeEvent.class, 1, passId, author);
when(event.getProtestStartTime()).thenReturn(mock(TimePoint.class));
return new TargetPair(Arrays.asList(event), event.getProtestStartTime());
when(event.getProtestTime()).thenReturn(mock(TimeRange.class));
return new TargetPair(Arrays.asList(event), event.getProtestTime());
}
@Test
@@ -40,13 +40,13 @@ public class ProtestStartTimeFinderTest extends PassAwareRaceLogAnalyzerTest<Pro
@Test
public void testMostRecent() {
RaceLogProtestStartTimeEvent event1 = createEvent(RaceLogProtestStartTimeEvent.class, 1);
when(event1.getProtestStartTime()).thenReturn(mock(TimePoint.class));
when(event1.getProtestTime()).thenReturn(mock(TimeRange.class));
RaceLogProtestStartTimeEvent event2 = createEvent(RaceLogProtestStartTimeEvent.class, 2);
when(event2.getProtestStartTime()).thenReturn(mock(TimePoint.class));
when(event2.getProtestTime()).thenReturn(mock(TimeRange.class));
raceLog.add(event1);
raceLog.add(event2);
assertEquals(event2.getProtestStartTime(), analyzer.analyze());
assertEquals(event2.getProtestTime(), analyzer.analyze());
}
}
@@ -1,6 +1,6 @@
package com.sap.sailing.domain.abstractlog.race;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.TimeRange;
/**
* Indicates that the protest start time for the related race has changed.
@@ -9,7 +9,9 @@ import com.sap.sse.common.TimePoint;
public interface RaceLogProtestStartTimeEvent extends RaceLogEvent {
/**
* Returns the start time of the race's protest time.
* Returns the time range of the race's protest time. The result is never {@code null}
* and the {@link TimeRange} returned always has a valid {@link TimeRange#from() start}
* and {@link TimeRange#to() end}.
*/
TimePoint getProtestStartTime();
TimeRange getProtestTime();
}
@@ -3,19 +3,20 @@ package com.sap.sailing.domain.abstractlog.race.analyzing.impl;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
import com.sap.sailing.domain.abstractlog.race.RaceLogProtestStartTimeEvent;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.TimeRange;
public class ProtestStartTimeFinder extends RaceLogAnalyzer<TimePoint> {
public class ProtestTimeFinder extends RaceLogAnalyzer<TimeRange> {
public ProtestStartTimeFinder(RaceLog raceLog) {
public ProtestTimeFinder(RaceLog raceLog) {
super(raceLog);
}
@Override
protected TimePoint performAnalysis() {
protected TimeRange performAnalysis() {
for (RaceLogEvent event : getPassEventsDescending()) {
if (event instanceof RaceLogProtestStartTimeEvent) {
return ((RaceLogProtestStartTimeEvent) event).getProtestStartTime();
RaceLogProtestStartTimeEvent protestEvent = (RaceLogProtestStartTimeEvent) event;
return protestEvent.getProtestTime();
}
}
return null;
@@ -6,21 +6,23 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
import com.sap.sailing.domain.abstractlog.race.RaceLogProtestStartTimeEvent;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.TimeRange;
public class RaceLogProtestStartTimeEventImpl extends RaceLogEventImpl implements RaceLogProtestStartTimeEvent {
private static final long serialVersionUID = -1800827552916395996L;
private final TimePoint protestStartTime;
private final TimeRange protestTime;
public RaceLogProtestStartTimeEventImpl(TimePoint createdAt, TimePoint pTimePoint, AbstractLogEventAuthor author,
Serializable pId, int pPassId, TimePoint protestStartTime) {
Serializable pId, int pPassId, TimeRange protestTime) {
super(createdAt, pTimePoint, author, pId, pPassId);
this.protestStartTime = protestStartTime;
assert protestTime != null && protestTime.from() != null && protestTime.to() != null;
this.protestTime = protestTime;
}
public RaceLogProtestStartTimeEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId,
TimePoint protestStartTime) {
this(now(), logicalTimePoint, author, randId(), pPassId, protestStartTime);
TimeRange protestTime) {
this(now(), logicalTimePoint, author, randId(), pPassId, protestTime);
}
@Override
@@ -29,13 +31,13 @@ public class RaceLogProtestStartTimeEventImpl extends RaceLogEventImpl implement
}
@Override
public TimePoint getProtestStartTime() {
return protestStartTime;
public TimeRange getProtestTime() {
return protestTime;
}
@Override
public String getShortInfo() {
return "protestStartTime=" + protestStartTime;
return "protestStartTime=" + protestTime.from() + ", protestEndTime=" + protestTime.to();
}
}
@@ -19,6 +19,7 @@ import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.TimeRange;
/**
* Extension to the {@link ReadonlyRaceState} allowing write-access to the state of a race.
@@ -142,9 +143,9 @@ public interface RaceState extends ReadonlyRaceState {
void setFinishedTime(TimePoint now);
/**
* Sets the protest (start) time.
* Sets the protest time.
*/
void setProtestTime(TimePoint now, TimePoint protestStartTime);
void setProtestTime(TimePoint now, TimeRange protestTime);
/**
* Signals the abort of this race.
@@ -14,6 +14,7 @@ import com.sap.sailing.domain.base.configuration.RegattaConfiguration;
import com.sap.sailing.domain.common.Wind;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.TimeRange;
/**
* This interface gives you reading access to the state of a race. You can query various properties of the race
@@ -134,7 +135,7 @@ public interface ReadonlyRaceState extends RaceStateEventProcessor {
/**
* If there is a protest time set, returns the most recent one. Otherwise <code>null</code>.
*/
TimePoint getProtestTime();
TimeRange getProtestTime();
/**
* If there is a course set, returns the most recent one. Otherwise <code>null</code>.
@@ -45,6 +45,7 @@ import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.TimeRange;
/**
* Write-enabled {@link RaceState}.
@@ -169,8 +170,9 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState {
}
@Override
public void setProtestTime(TimePoint now, TimePoint timePoint) {
raceLog.add(new RaceLogProtestStartTimeEventImpl(now, author, raceLog.getCurrentPassId(), timePoint));
public void setProtestTime(TimePoint now, TimeRange protestTime) {
assert protestTime != null && protestTime.from() != null && protestTime.to() != null;
raceLog.add(new RaceLogProtestStartTimeEventImpl(now, author, raceLog.getCurrentPassId(), protestTime));
}
@Override
@@ -18,7 +18,7 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishedTimeFinder
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishingTimeFinder;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastPublishedCourseDesignFinder;
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.ProtestTimeFinder;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceStatusAnalyzer;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceStatusAnalyzer.Clock;
@@ -42,6 +42,7 @@ import com.sap.sailing.domain.common.Wind;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.TimeRange;
import com.sap.sse.common.Util;
/**
@@ -116,7 +117,7 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
private final StartTimeFinder startTimeAnalyzer;
private final FinishingTimeFinder finishingTimeAnalyzer;
private final FinishedTimeFinder finishedTimeAnalyzer;
private final ProtestStartTimeFinder protestTimeAnalyzer;
private final ProtestTimeFinder protestTimeAnalyzer;
private final FinishPositioningListFinder finishPositioningListAnalyzer;
private final ConfirmedFinishPositioningListFinder confirmedFinishPositioningListAnalyzer;
@@ -141,7 +142,7 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
private StartTimeFinderResult cachedStartTimeFinderResult;
private TimePoint cachedFinishingTime;
private TimePoint cachedFinishedTime;
private TimePoint cachedProtestTime;
private TimeRange cachedProtest;
private CompetitorResults cachedPositionedCompetitors;
private CompetitorResults cachedConfirmedPositionedCompetitors;
private CourseBase cachedCourseDesign;
@@ -184,7 +185,7 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
this.startTimeAnalyzer = new StartTimeFinder(raceLogResolver, raceLog);
this.finishingTimeAnalyzer = new FinishingTimeFinder(raceLog);
this.finishedTimeAnalyzer = new FinishedTimeFinder(raceLog);
this.protestTimeAnalyzer = new ProtestStartTimeFinder(raceLog);
this.protestTimeAnalyzer = new ProtestTimeFinder(raceLog);
this.finishPositioningListAnalyzer = new FinishPositioningListFinder(raceLog);
this.confirmedFinishPositioningListAnalyzer = new ConfirmedFinishPositioningListFinder(raceLog);
this.courseDesignerAnalyzer = new LastPublishedCourseDesignFinder(raceLog, /* onlyCoursesWithValidWaypointList */ false);
@@ -318,8 +319,8 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
}
@Override
public TimePoint getProtestTime() {
return cachedProtestTime;
public TimeRange getProtestTime() {
return cachedProtest;
}
@Override
@@ -459,9 +460,9 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
changedListeners.onFinishedTimeChanged(this);
}
TimePoint protestTime = protestTimeAnalyzer.analyze();
if (!Util.equalsWithNull(cachedProtestTime, protestTime)) {
cachedProtestTime = protestTime;
TimeRange protest = protestTimeAnalyzer.analyze();
if (!Util.equalsWithNull(cachedProtest, protest)) {
cachedProtest = protest;
changedListeners.onProtestTimeChanged(this);
}
@@ -65,6 +65,7 @@ import com.sap.sailing.gwt.server.HomeServiceUtil;
import com.sap.sailing.server.RacingEventService;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.TimeRange;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.media.MediaType;
@@ -287,8 +288,8 @@ public class RaceContext {
}
switch (state.getStatus()) {
case FINISHED:
TimePoint protestStartTime = state.getProtestTime();
if (protestStartTime != null) {
TimeRange protestTime = state.getProtestTime();
if (protestTime != null) {
lastUpperFlag = Flags.BRAVO;
lastLowerFlag = Flags.NONE;
lastFlagsAreDisplayed = true;
@@ -51,8 +51,10 @@ public class RaceDetailPanel extends SimplePanel {
private final Label startDateLabel = new Label();
private final Label finishTimeLabel = new Label();
private final Label finishDurationLabel = new Label();
private final Label protestTimeLabel = new Label();
private final Label protestDateLabel = new Label();
private final Label protestStartTimeLabel = new Label();
private final Label protestFinishTimeLabel = new Label();
private final Label protestStartDateLabel = new Label();
private final Label protestFinishDateLabel = new Label();
private final Label updateTimeLabel = new Label();
private final Label updateDateLabel = new Label();
private final Label vesselPositionLabel = new Label();
@@ -88,17 +90,20 @@ public class RaceDetailPanel extends SimplePanel {
int cellSpacing = 3;
Grid basicsGrid = new Grid(3, 3);
Grid basicsGrid = new Grid(4, 3);
basicsGrid.setCellSpacing(cellSpacing);
basicsGrid.setWidget(0, 0, new Label(stringMessages.startAt()));
basicsGrid.setWidget(1, 0, new Label(stringMessages.finishAt()));
basicsGrid.setWidget(2, 0, new Label(stringMessages.protestEndsAt()));
basicsGrid.setWidget(2, 0, new Label(stringMessages.protestStartsAt()));
basicsGrid.setWidget(3, 0, new Label(stringMessages.protestEndsAt()));
basicsGrid.setWidget(0, 1, startTimeLabel);
basicsGrid.setWidget(1, 1, finishTimeLabel);
basicsGrid.setWidget(2, 1, protestTimeLabel);
basicsGrid.setWidget(2, 1, protestStartTimeLabel);
basicsGrid.setWidget(3, 1, protestFinishTimeLabel);
basicsGrid.setWidget(0, 2, startDateLabel);
basicsGrid.setWidget(1, 2, finishDurationLabel);
basicsGrid.setWidget(2, 2, protestDateLabel);
basicsGrid.setWidget(2, 2, protestStartDateLabel);
basicsGrid.setWidget(3, 2, protestFinishDateLabel);
Grid managementGrid = new Grid(3, 3);
managementGrid.setCellSpacing(cellSpacing);
@@ -167,13 +172,21 @@ public class RaceDetailPanel extends SimplePanel {
}
finishDurationLabel.setText(finishDurationText);
String protestTimeText = data.raceInfo.protestFinishTime == null ? "-" : timeFormatter
.format(data.raceInfo.protestFinishTime);
protestTimeLabel.setText(protestTimeText);
String protestStartTimeText = data.raceInfo.protestStartTime == null ? "-" : timeFormatter
.format(data.raceInfo.protestStartTime);
protestStartTimeLabel.setText(protestStartTimeText);
String protestDateText = data.raceInfo.protestFinishTime == null ? "" : dateFormatter
String protestFinishTimeText = data.raceInfo.protestFinishTime == null ? "-" : timeFormatter
.format(data.raceInfo.protestFinishTime);
protestDateLabel.setText(protestDateText);
protestFinishTimeLabel.setText(protestFinishTimeText);
String protestStartDateText = data.raceInfo.protestStartTime == null ? "" : dateFormatter
.format(data.raceInfo.protestStartTime);
protestStartDateLabel.setText(protestStartDateText);
String protestFinishDateText = data.raceInfo.protestFinishTime == null ? "" : dateFormatter
.format(data.raceInfo.protestFinishTime);
protestFinishDateLabel.setText(protestFinishDateText);
String updateTimeText = data.raceInfo.lastUpdateTime == null ? "-" : timeFormatter
.format(data.raceInfo.lastUpdateTime);
@@ -83,9 +83,8 @@ public class RegattaOverviewEntryPoint extends AbstractSailingEntryPoint {
}
private void toggleDetailPanel(boolean visibile) {
containerPanel.setWidgetSize(detailPanel, visibile ? 110 : 0);
containerPanel.setWidgetSize(detailPanel, visibile ? 125 : 0);
containerPanel.animate(500);
// containerPanel.setWidgetHidden(detailPanel, !visibile);
}
private void createAndAddRegattaPanel(UUID eventId, boolean ignoreLocalSettings) {
@@ -811,6 +811,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
String showingDetailsOfRace(String raceName);
String startAt();
String finishAt();
String protestStartsAt();
String protestEndsAt();
String unknown();
String raceLog();
@@ -793,6 +793,7 @@ earlyStarters=Early starters
showingDetailsOfRace=Showing details for race {0}
startAt=Start at
finishAt=Finish at
protestStartsAt=Protest starts at
protestEndsAt=Protest ends at
unknown=Unknown
raceLog=Race log
@@ -786,6 +786,7 @@ earlyStarters=Frühstarter
showingDetailsOfRace=Informationen zu Rennen {0}
startAt=Start
finishAt=Rennende
protestStartsAt=Protestzeit beginnt
protestEndsAt=Protestzeit endet
unknown=Unbekannt
raceLog=RaceLog
@@ -943,14 +943,17 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
if (raceInfoDTO.lastStatus.equals(RaceLogRaceStatus.FINISHED)) {
TimePoint protestStartTime = state.getProtestTime();
if (protestStartTime != null) {
final Duration protestDuration = Duration.ONE_MINUTE.times(90); // 90 min protest duration; see bug 3089 (make protest time variable)
raceInfoDTO.protestFinishTime = protestStartTime.plus(protestDuration).asDate();
raceInfoDTO.lastUpperFlag = Flags.BRAVO;
raceInfoDTO.lastLowerFlag = Flags.NONE;
raceInfoDTO.lastFlagsAreDisplayed = true;
raceInfoDTO.lastFlagsDisplayedStateChanged = true;
if (state.getProtestTime() != null) {
final TimePoint protestEndTime = state.getProtestTime().to();
if (protestEndTime != null) {
final TimePoint protestStartTime = state.getProtestTime().from();
raceInfoDTO.protestStartTime = protestStartTime == null ? null : protestStartTime.asDate();
raceInfoDTO.protestFinishTime = protestEndTime.asDate();
raceInfoDTO.lastUpperFlag = Flags.BRAVO;
raceInfoDTO.lastLowerFlag = Flags.NONE;
raceInfoDTO.lastFlagsAreDisplayed = true;
raceInfoDTO.lastFlagsDisplayedStateChanged = true;
}
}
}
@@ -45,6 +45,7 @@ public class RaceInfoDTO implements IsSerializable {
public RaceLogRaceStatus lastStatus;
public Date startTime;
public Date finishedTime;
public Date protestStartTime;
public Date protestFinishTime;
public Date lastUpdateTime;
public Flags lastUpperFlag;
@@ -4,6 +4,14 @@
<div id="mainContent">
<h4 class="articleHeadline">What's New - SAP Sailing Race Manager</h4>
<div class="innerContent">
<h5 class="articleSubheadline">November 2016</h5>
<ul class="bulletList">
<li>The protest time is now more configurable. You can set the start time and
the duration. The default protest duration is 90 min and the last duration is
stored in the settings, so you don't need to change it the next time.</li>
</ul>
<h5 class="articleSubheadline">October 2016</h5>
<ul class="bulletList">
@@ -17,8 +17,11 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.impl.FleetImpl;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimeRange;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.impl.TimeRangeImpl;
public class TestRaceLogRemovalInRegatta extends AbstractTestStoringAndRetrievingRaceLogInRegatta {
private final String blueFleetName = "Blue";
@@ -51,7 +54,8 @@ public class TestRaceLogRemovalInRegatta extends AbstractTestStoringAndRetrievin
Fleet blueFleet = qualification.getFleetByName(blueFleetName);
RaceLog yellowLog = qualification.getRaceColumnByName(raceColumnName).getRaceLog(yellowFleet);
RaceLog blueLog = qualification.getRaceColumnByName(raceColumnName).getRaceLog(blueFleet);
RaceLogProtestStartTimeEvent expectedEventYellow = new RaceLogProtestStartTimeEventImpl(now, author, 0, MillisecondsTimePoint.now());
TimeRange protestTime = new TimeRangeImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now().plus(Duration.ONE_MINUTE.times(90)));
RaceLogProtestStartTimeEvent expectedEventYellow = new RaceLogProtestStartTimeEventImpl(now, author, 0, protestTime);
yellowLog.add(expectedEventYellow);
RaceLogStartTimeEvent expectedEventBlue = new RaceLogStartTimeEventImpl(now, author, 0, MillisecondsTimePoint.now());
blueLog.add(expectedEventBlue);
@@ -81,8 +81,10 @@ import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.TimeRange;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.impl.TimeRangeImpl;
public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoDBTest {
@@ -121,8 +123,10 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD
}
@Test
public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogProtestStartTimeEvent() {
RaceLogProtestStartTimeEvent expectedEvent = new RaceLogProtestStartTimeEventImpl(now, author, 0, MillisecondsTimePoint.now());
public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogProtestStartTimeEvent() {
TimePoint now = MillisecondsTimePoint.now();
TimeRange protestTime = new TimeRangeImpl(now, now.plus(Duration.ONE_MINUTE.times(90)));
RaceLogProtestStartTimeEvent expectedEvent = new RaceLogProtestStartTimeEventImpl(now, author, 0, protestTime);
addAndStoreRaceLogEvent(leaderboard, raceColumnName, expectedEvent);
RaceLog loadedRaceLog = retrieveRaceLog();
loadedRaceLog.lockForRead();
@@ -132,7 +136,8 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD
assertEquals(expectedEvent.getLogicalTimePoint(), actualEvent.getLogicalTimePoint());
assertEquals(expectedEvent.getPassId(), actualEvent.getPassId());
assertEquals(expectedEvent.getId(), actualEvent.getId());
assertEquals(expectedEvent.getProtestStartTime(), actualEvent.getProtestStartTime());
assertEquals(expectedEvent.getProtestTime().from(), actualEvent.getProtestTime().from());
assertEquals(expectedEvent.getProtestTime().to(), actualEvent.getProtestTime().to());
assertEquals(1, Util.size(loadedRaceLog.getFixes()));
} finally {
loadedRaceLog.unlockAfterRead();
@@ -141,7 +146,9 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD
@Test
public void testThatRemoveRaceColumnAlsoRemovesPersistentRaceLog() {
RaceLogProtestStartTimeEvent expectedEvent = new RaceLogProtestStartTimeEventImpl(now, author, 0, MillisecondsTimePoint.now());
TimePoint now = MillisecondsTimePoint.now();
TimeRange protestTime = new TimeRangeImpl(now, now.plus(Duration.ONE_MINUTE.times(90)));
RaceLogProtestStartTimeEvent expectedEvent = new RaceLogProtestStartTimeEventImpl(now, author, 0, protestTime);
Fleet defaultFleet = leaderboard.getFleet(null);
RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName);
raceColumn.getRaceLog(defaultFleet).add(expectedEvent);
@@ -167,7 +174,9 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD
when(service.getMongoObjectFactory()).thenReturn(mongoObjectFactory);
when(service.getLeaderboardByName(leaderboardName)).thenReturn(leaderboard);
doCallRealMethod().when(service).renameLeaderboardColumn(Matchers.anyString(), Matchers.anyString(), Matchers.anyString());
RaceLogProtestStartTimeEvent expectedEvent = new RaceLogProtestStartTimeEventImpl(now, author, 0, MillisecondsTimePoint.now());
TimePoint now = MillisecondsTimePoint.now();
TimeRange protestTime = new TimeRangeImpl(now, now.plus(Duration.ONE_MINUTE.times(90)));
RaceLogProtestStartTimeEvent expectedEvent = new RaceLogProtestStartTimeEventImpl(now, author, 0, protestTime);
Fleet defaultFleet = leaderboard.getFleet(null);
RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName);
raceColumn.getRaceLog(defaultFleet).add(expectedEvent);
@@ -63,8 +63,12 @@ import com.sap.sailing.domain.persistence.impl.FieldNames;
import com.sap.sailing.domain.persistence.impl.MongoObjectFactoryImpl;
import com.sap.sailing.domain.persistence.impl.TripleSerializer;
import com.sap.sse.common.Color;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.TimeRange;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.impl.TimeRangeImpl;
public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStoringAndRetrievingRaceLogInRegatta {
public TestStoringAndRetrievingRaceLogInRegatta() throws UnknownHostException, MongoException {
@@ -96,8 +100,10 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin
}
@Test
public void testStoreAndRetrieveRegattaWithRaceLogProtestStartTimeEvent() {
RaceLogProtestStartTimeEvent expectedEvent = new RaceLogProtestStartTimeEventImpl(now, author, 0, MillisecondsTimePoint.now());
public void testStoreAndRetrieveRegattaWithRaceLogProtestStartTimeEvent() {
TimePoint now = MillisecondsTimePoint.now();
TimeRange protestTime = new TimeRangeImpl(now, now.plus(Duration.ONE_MINUTE.times(90)));
RaceLogProtestStartTimeEvent expectedEvent = new RaceLogProtestStartTimeEventImpl(now, author, 0, protestTime);
addAndStoreRaceLogEvent(regatta, raceColumnName, expectedEvent);
RaceLog loadedRaceLog = retrieveRaceLog();
loadedRaceLog.lockForRead();
@@ -107,7 +113,8 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin
assertEquals(expectedEvent.getLogicalTimePoint(), actualEvent.getLogicalTimePoint());
assertEquals(expectedEvent.getPassId(), actualEvent.getPassId());
assertEquals(expectedEvent.getId(), actualEvent.getId());
assertEquals(expectedEvent.getProtestStartTime(), actualEvent.getProtestStartTime());
assertEquals(expectedEvent.getProtestTime().from(), actualEvent.getProtestTime().from());
assertEquals(expectedEvent.getProtestTime().to(), actualEvent.getProtestTime().to());
assertEquals(1, Util.size(loadedRaceLog.getFixes()));
} finally {
loadedRaceLog.unlockAfterRead();
@@ -13,7 +13,9 @@ import com.sap.sailing.server.gateway.deserialization.JsonDeserializationExcepti
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogProtestStartTimeEventSerializer;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.TimeRange;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.impl.TimeRangeImpl;
public class RaceLogProtestStartTimeEventDeserializer extends BaseRaceLogEventDeserializer {
@@ -24,9 +26,10 @@ public class RaceLogProtestStartTimeEventDeserializer extends BaseRaceLogEventDe
@Override
protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author,
TimePoint timePoint, int passId, List<Competitor> competitors) throws JsonDeserializationException {
Long protestStartTime = (Long) object.get(RaceLogProtestStartTimeEventSerializer.FIELD_PROTEST_START_TIME);
return new RaceLogProtestStartTimeEventImpl(createdAt, timePoint, author, id,
passId, new MillisecondsTimePoint(protestStartTime));
Long protestStart = (Long) object.get(RaceLogProtestStartTimeEventSerializer.FIELD_PROTEST_START_TIME);
Long protestEnd = (Long) object.get(RaceLogProtestStartTimeEventSerializer.FIELD_PROTEST_END_TIME);
TimeRange protestTime = new TimeRangeImpl(new MillisecondsTimePoint(protestStart), new MillisecondsTimePoint(protestEnd));
return new RaceLogProtestStartTimeEventImpl(createdAt, timePoint, author, id, passId, protestTime);
}
}
@@ -11,6 +11,7 @@ public class RaceLogProtestStartTimeEventSerializer extends BaseRaceLogEventSeri
public static final String VALUE_CLASS = RaceLogProtestStartTimeEvent.class.getSimpleName();
public static final String FIELD_PROTEST_START_TIME = "protestStartTime";
public static final String FIELD_PROTEST_END_TIME = "protestEndTime";
public RaceLogProtestStartTimeEventSerializer(JsonSerializer<Competitor> competitorSerializer) {
super(competitorSerializer);
@@ -25,7 +26,8 @@ public class RaceLogProtestStartTimeEventSerializer extends BaseRaceLogEventSeri
public JSONObject serialize(RaceLogEvent object) {
RaceLogProtestStartTimeEvent event = (RaceLogProtestStartTimeEvent) object;
JSONObject result = super.serialize(event);
result.put(FIELD_PROTEST_START_TIME, event.getProtestStartTime().asMillis());
result.put(FIELD_PROTEST_START_TIME, event.getProtestTime().from().asMillis());
result.put(FIELD_PROTEST_END_TIME, event.getProtestTime().to().asMillis());
return result;
}
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<EditText
android:id="@+id/protest_duration"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:inputType="number"
android:textColor="?black" />
</FrameLayout>
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
@@ -10,22 +10,57 @@
android:id="@+id/protest_time_races_list"
android:layout_width="400dp"
android:layout_height="match_parent"
android:verticalSpacing="2dp"/>
android:verticalSpacing="2dp" />
<RelativeLayout
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleX="@integer/picker_scale"
android:scaleY="@integer/picker_scale"
android:layout_marginLeft="@dimen/default_margin_twice"
android:paddingRight="@dimen/default_padding"
android:paddingLeft="@dimen/default_padding">
android:orientation="vertical">
<include
android:id="@+id/protest_time_time_picker"
layout="@layout/time_picker"
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</RelativeLayout>
android:layout_marginLeft="@dimen/default_margin_twice"
android:paddingLeft="@dimen/default_padding"
android:paddingRight="@dimen/default_padding"
android:scaleX="@integer/picker_scale"
android:scaleY="@integer/picker_scale">
<include
android:id="@+id/protest_time_time_picker"
layout="@layout/time_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</RelativeLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:orientation="horizontal">
<TextView
android:id="@+id/protest_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textAppearance="?attr/textXSmall"
tools:text="@string/protest_duration" />
<ImageView
android:id="@+id/change_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:src="?attr/create" />
</LinearLayout>
<TextView
android:id="@+id/protest_end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?attr/textXSmall"
tools:text="@string/protest_end_time" />
</LinearLayout>
</LinearLayout>
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout 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"
@@ -27,7 +26,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="?attr/chevron_left_24dp"/>
android:src="?attr/chevron_left_24dp" />
<TextView
android:id="@+id/header_caption"
@@ -35,7 +34,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/protest_dialog_title"
android:textAppearance="?attr/textHeader"/>
android:textAppearance="?attr/textHeader" />
</LinearLayout>
<View
@@ -43,7 +42,7 @@
android:layout_width="match_parent"
android:layout_height="@dimen/header_line"
android:layout_alignParentBottom="true"
android:background="?attr/black"/>
android:background="?attr/black" />
</RelativeLayout>
<RelativeLayout
@@ -60,7 +59,7 @@
android:layout_width="match_parent"
android:layout_height="@dimen/thin_line"
android:layout_alignParentTop="true"
android:background="?attr/sap_gray"/>
android:background="?attr/sap_gray" />
<Button
android:id="@+id/choose"
@@ -71,7 +70,7 @@
android:layout_marginBottom="@dimen/default_margin_half"
android:layout_marginTop="@dimen/default_margin_half"
android:text="@string/choose"
android:textSize="@dimen/textSize_18"/>
android:textSize="@dimen/textSize_18" />
</RelativeLayout>
<RelativeLayout
@@ -93,7 +92,7 @@
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:src="?attr/button_prev"/>
android:src="?attr/button_prev" />
<ImageView
android:id="@+id/nav_next"
@@ -101,7 +100,7 @@
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="?attr/button_next"/>
android:src="?attr/button_next" />
<LinearLayout
android:layout_width="wrap_content"
@@ -114,13 +113,13 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
tools:src="@drawable/ic_dot"/>
tools:src="@drawable/ic_dot" />
<ImageView
android:id="@+id/dot_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:src="@drawable/ic_dot"/>
tools:src="@drawable/ic_dot" />
</LinearLayout>
</RelativeLayout>
@@ -138,26 +137,71 @@
android:layout_height="match_parent"
android:verticalSpacing="2dp"
android:visibility="gone"
tools:visibility="gone"/>
tools:visibility="gone" />
<RelativeLayout
android:id="@+id/protest_time_time_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleX="@integer/picker_scale"
android:scaleY="@integer/picker_scale"
android:visibility="gone"
tools:visibility="gone">
tools:visibility="visible">
<include
android:id="@+id/protest_time_time_picker"
layout="@layout/time_picker"
<RelativeLayout
android:id="@+id/time_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:paddingLeft="@dimen/default_padding"
android:paddingRight="@dimen/default_padding"/>
android:layout_centerVertical="true"
android:layout_centerHorizontal="true">
<include
android:id="@+id/protest_time_time_picker"
layout="@layout/time_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingLeft="@dimen/default_padding"
android:paddingRight="@dimen/default_padding"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/protest_time_time_picker"
android:layout_centerHorizontal="true"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:orientation="horizontal">
<TextView
android:id="@+id/protest_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textAppearance="?attr/textXSmall"
tools:text="@string/protest_duration" />
<ImageView
android:id="@+id/change_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:src="?attr/create" />
</LinearLayout>
<TextView
android:id="@+id/protest_end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?attr/textXSmall"
tools:text="@string/protest_end_time" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
</FrameLayout>
</RelativeLayout>
@@ -66,6 +66,9 @@
<string name="protest_dialog_title">Beginn der Protestzeit</string>
<string name="finished_dialog_title">Rennende setzen</string>
<string name="protest_start_time">Protestzeit beginnt: %s</string>
<string name="protest_duration">Protestdauer: %d Min</string>
<string name="protest_end_time">Protestzeit endet: %s</string>
<string name="protest_duration_dialog_title">Dauer in Minuten</string>
<string name="no_pathfinder_selected">Kein Pathfinder gesetzt</string>
<string name="set_line_opening_time">Gate Launch</string>
<string name="no_line_opening_time_selected">Keine Zeit gesetzt</string>
@@ -439,6 +442,7 @@
<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="preference_allow_edit_race_factor_header">Rennfaktor ändern</string>
<string name="preference_protest_time_header">Protestzeit Dauer (Minuten)</string>
<string name="preference_allow_edit_race_factor_description">Rennleiter können den Rennfaktor je Rennen ändern</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>
@@ -100,6 +100,8 @@
<integer name="preference_dependent_races_offset_default">5</integer>
<string name="preference_allow_edit_race_factor_key" translatable="false">raceFactor</string>
<bool name="preference_allow_edit_race_factor_default">true</bool>
<string name="preference_protest_time_duration_key">protestTimeDuration</string>
<integer name="preference_protest_time_duration_default">90</integer>
<string name="preference_allow_demo_key" translatable="false">allow_demo</string>
<bool name="preference_allow_demo_default">false</bool>
@@ -81,6 +81,9 @@
<string name="protest_dialog_title">Protest start time</string>
<string name="finished_dialog_title">Set the time when the race finished</string>
<string name="protest_start_time">Protest start time: %s</string>
<string name="protest_duration">Protest duration: %d min</string>
<string name="protest_end_time">Protest end time: %s</string>
<string name="protest_duration_dialog_title">Duration in Minutes</string>
<string name="no_pathfinder_selected">No Pathfinder selected</string>
<string name="set_line_opening_time">Gate Launch</string>
<string name="no_line_opening_time_selected">No time selected</string>
@@ -461,8 +464,9 @@
<string name="data_reload_message">Data has 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="preference_dependent_races_offset_header">Default Relative Start Time Offset (Minutes)</string>
<string name="preference_allow_edit_race_factor_header">Race factor change</string>
<string name="preference_protest_time_header">Protest Time Duration (Minutes)</string>
<string name="preference_allow_edit_race_factor_description">Race managers can change the race factor per race</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>
@@ -40,6 +40,12 @@
android:key="@string/preference_allow_edit_race_factor_key"
android:summary="@string/preference_allow_edit_race_factor_description"
android:title="@string/preference_allow_edit_race_factor_header" />
<com.sap.sailing.racecommittee.app.ui.views.IntegerEditTextPreference
android:defaultValue="@integer/preference_protest_time_duration_default"
android:key="@string/preference_protest_time_duration_key"
android:numeric="integer"
android:title="@string/preference_protest_time_header"/>
</PreferenceCategory>
<PreferenceCategory android:title="RRS26">
@@ -474,6 +474,15 @@ public class AppPreferences {
.getInteger(R.integer.preference_dependent_races_offset_default));
}
public int getProtestTimeDuration() {
return helper.getInt(context.getString(R.string.preference_protest_time_duration_key), context.getResources()
.getInteger(R.integer.preference_protest_time_duration_default));
}
public void setProtestTimeDuration(int value) {
helper.getEditor().putInt(context.getString(R.string.preference_protest_time_duration_key), value).commit();
}
public String getTheme() {
return helper.getString(context.getString(R.string.preference_theme_key), context.getResources().getString(R.string.preference_theme_default));
}
@@ -7,6 +7,8 @@ import java.util.List;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Build;
@@ -18,8 +20,11 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.TimePicker;
import com.sap.sailing.android.shared.util.BitmapHelper;
@@ -30,14 +35,18 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishedTimeFinder
import com.sap.sailing.domain.base.racegroup.RaceGroupSeriesFleet;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
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.DataManager;
import com.sap.sailing.racecommittee.app.data.ReadonlyDataManager;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
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.TimeRange;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.impl.TimeRangeImpl;
public class ProtestTimeDialogFragment extends AttachedDialogFragment implements View.OnClickListener {
@@ -51,9 +60,12 @@ public class ProtestTimeDialogFragment extends AttachedDialogFragment implements
private List<ManagedRace> races;
private ListView mRacesList;
private TimePicker mTimePicker;
private TextView mProtestDuration;
private TextView mProtestEndTime;
private View customView;
private View mHome;
private Button mChoose;
private AppPreferences mPreferences;
public ProtestTimeDialogFragment() {
races = new ArrayList<>();
@@ -88,6 +100,7 @@ public class ProtestTimeDialogFragment extends AttachedDialogFragment implements
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mPreferences = AppPreferences.on(getActivity());
View layout = super.onCreateView(inflater, container, savedInstanceState);
if (customView == null) {
layout = inflater.inflate(R.layout.protest_time_fragment, container, false);
@@ -146,6 +159,14 @@ public class ProtestTimeDialogFragment extends AttachedDialogFragment implements
});
}
mProtestDuration = ViewHelper.get(layout, R.id.protest_duration);
mProtestEndTime = ViewHelper.get(layout, R.id.protest_end);
View changeDuration = ViewHelper.get(layout, R.id.change_duration);
if (changeDuration != null) {
changeDuration.setOnClickListener(new DurationChangeListener());
}
updateProtestRange();
viewPanel(MOVE_NONE);
}
return layout;
@@ -189,12 +210,20 @@ public class ProtestTimeDialogFragment extends AttachedDialogFragment implements
}
private View setupView() {
mPreferences = AppPreferences.on(getActivity());
LayoutInflater inflater = LayoutInflater.from(getActivity());
View view = inflater.inflate(R.layout.protest_time_dialog, null);
mRacesList = (ListView) view.findViewById(R.id.protest_time_races_list);
setupRacesList(mRacesList);
mTimePicker = (TimePicker) view.findViewById(R.id.protest_time_time_picker);
setupTimePicker(mTimePicker);
mProtestDuration = (TextView) view.findViewById(R.id.protest_duration);
mProtestEndTime = (TextView) view.findViewById(R.id.protest_end);
View changeDuration = view.findViewById(R.id.change_duration);
if (changeDuration != null) {
changeDuration.setOnClickListener(new DurationChangeListener());
}
updateProtestRange();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
// TODO: @Samuel -> please check, why we did this, because I can't remember
@@ -249,6 +278,13 @@ public class ProtestTimeDialogFragment extends AttachedDialogFragment implements
timePicker.setCurrentHour(hours);
timePicker.setCurrentMinute(minutes);
timePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
@Override
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
updateProtestRange();
}
});
ThemeHelper.setPickerColor(getActivity(), timePicker, ThemeHelper.getColor(getActivity(), R.attr.white), ThemeHelper
.getColor(getActivity(), R.attr.sap_yellow_1));
}
@@ -270,9 +306,11 @@ public class ProtestTimeDialogFragment extends AttachedDialogFragment implements
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
private void setAndAnnounceProtestTime() {
List<ManagedRace> selectedRaces = getSelectedRaces();
TimePoint protestTime = TimeUtils.getTime(mTimePicker);
TimePoint startTime = TimeUtils.getTime(mTimePicker);
TimePoint now = MillisecondsTimePoint.now();
for (ManagedRace race : selectedRaces) {
Duration duration = Duration.ONE_MINUTE.times(AppPreferences.on(getActivity()).getProtestTimeDuration());
TimeRange protestTime = new TimeRangeImpl(startTime, startTime.plus(duration));
race.getState().setProtestTime(now, protestTime);
}
if (mHome != null) {
@@ -306,7 +344,6 @@ public class ProtestTimeDialogFragment extends AttachedDialogFragment implements
viewPanel(MOVE_UP);
break;
}
}
protected void viewPanel(int direction) {
@@ -353,6 +390,18 @@ public class ProtestTimeDialogFragment extends AttachedDialogFragment implements
}
}
private void updateProtestRange() {
int duration = mPreferences.getProtestTimeDuration();
if (mProtestDuration != null) {
mProtestDuration.setText(getString(R.string.protest_duration, duration));
}
if (mProtestEndTime != null) {
TimePoint startTime = TimeUtils.getTime(mTimePicker);
TimePoint endTime = startTime.plus(Duration.ONE_MINUTE.times(duration));
mProtestEndTime.setText(getString(R.string.protest_end_time, TimeUtils.formatTime(endTime)));
}
}
private static class ProtestTimeAdapter extends ArrayAdapter<ManagedRaceItem> {
public ProtestTimeAdapter(Context context, List<ManagedRace> objects) {
@@ -360,7 +409,7 @@ public class ProtestTimeDialogFragment extends AttachedDialogFragment implements
}
private static List<ManagedRaceItem> wrap(List<ManagedRace> races) {
List<ManagedRaceItem> wrapped = new ArrayList<ManagedRaceItem>();
List<ManagedRaceItem> wrapped = new ArrayList<>();
for (ManagedRace race : races) {
wrapped.add(new ManagedRaceItem(race));
}
@@ -384,4 +433,28 @@ public class ProtestTimeDialogFragment extends AttachedDialogFragment implements
return String.format("%s - %s", group.getDisplayName(true), race.getRaceColumnName());
}
}
private class DurationChangeListener implements View.OnClickListener {
@Override
public void onClick(View v) {
FrameLayout layout = (FrameLayout) LayoutInflater.from(v.getContext()).inflate(R.layout.protest_duration, null);
final EditText duration = (EditText) layout.findViewById(R.id.protest_duration);
duration.setText(String.valueOf(mPreferences.getProtestTimeDuration()));
duration.setSelection(duration.length());
AlertDialog.Builder builder = new AlertDialog.Builder(new ContextWrapper(v.getContext()), R.style.AppTheme_AlertDialog);
builder.setTitle(v.getContext().getString(R.string.protest_duration_dialog_title));
builder.setView(layout);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int value = Integer.parseInt(duration.getText().toString());
mPreferences.setProtestTimeDuration(value);
updateProtestRange();
}
});
builder.setNegativeButton(android.R.string.cancel, null);
builder.show();
}
}
}
@@ -77,6 +77,7 @@ public class RegattaPreferenceFragment extends BasePreferenceFragment {
setupRacingProcedureTypePreference();
setupCourseDesignerTypePreference();
setupDependentRacesPreference();
setupProtestTimePreference();
}
private void setupRacingProcedureTypePreference() {
@@ -117,6 +118,10 @@ public class RegattaPreferenceFragment extends BasePreferenceFragment {
bindPreferenceSummaryToInteger(findPreference(R.string.preference_dependent_races_offset_key));
}
private void setupProtestTimePreference() {
bindPreferenceSummaryToInteger(findPreference(R.string.preference_protest_time_duration_key));
}
private void setupRRS26StartmodeFlagsList() {
MultiSelectListPreference preference = findPreference(R.string.preference_racing_procedure_rrs26_startmode_flags_key);
List<String> flags = new ArrayList<>();