Merge branch 'master' into bug5773

This commit is contained in:
Udo Wessels committed 2023-08-04 15:09:43 +02:00
commit c9faeb161d
18 files changed
+160 -23

No files matched your search

@@ -16,7 +16,8 @@ public enum RacingProcedureType {
ESS("\"Extreme Sailing Series\"-Start"),
BASIC("Basic Countdown Start"),
LEAGUE("League Start"),
RRS26_3MIN("Fix Line Start with 3min Sequence (RRS26/3)");
RRS26_3MIN("Fix Line Start with 3min Sequence (RRS26/3)"),
SWC_4MIN("Sailing World Cup Start with 4min Sequence (Kites, Surfers)");
private String displayName;
@@ -210,5 +210,4 @@ public class MediaDBImpl implements MediaDB {
updateCommand.append("$set", new Document(DbNames.Fields.ASSIGNED_RACES.name(), assignedRacesDb));
getVideoCollection().updateOne(updateQuery, updateCommand);
}
}
@@ -0,0 +1,39 @@
package com.sap.sailing.domain.racelog.test;
import static org.junit.Assert.assertEquals;
import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.ReadonlyRacingProcedure;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.impl.RacingProcedureFactoryImpl;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.line.ConfigurableStartModeFlagRacingProcedure;
import com.sap.sailing.domain.base.configuration.impl.EmptyRegattaConfiguration;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
public class RacingProceduresWithStartModeFlagTest {
private RacingProcedureFactoryImpl racingProcedureFactory;
private RaceLogImpl raceLog;
@Before
public void setUp() {
this.racingProcedureFactory = new RacingProcedureFactoryImpl(/* author */ null, new EmptyRegattaConfiguration());
this.raceLog = new RaceLogImpl(UUID.randomUUID());
}
@Test
public void testRacingProcedureWithStartModeFlagDetection() {
for (final RacingProcedureType type : RacingProcedureType.values()) {
if (type != RacingProcedureType.UNKNOWN) {
final ReadonlyRacingProcedure racingProcedure = racingProcedureFactory.createRacingProcedure(type, raceLog, /* raceLogResolver */ null);
assertEquals("Racing procedure type "+type.name()+" was "+((racingProcedure instanceof ConfigurableStartModeFlagRacingProcedure) ? "" : "not ")+
"considered one with configurable start mode flag but should have",
RacingProcedureType.RRS26.equals(type) || RacingProcedureType.RRS26_3MIN.equals(type) || RacingProcedureType.SWC.equals(type) || RacingProcedureType.SWC_4MIN.equals(type),
racingProcedure instanceof ConfigurableStartModeFlagRacingProcedure);
}
}
}
}
@@ -1,10 +1,15 @@
package com.sap.sailing.domain.abstractlog.race.analyzing.impl;
import java.util.List;
import java.util.UUID;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent;
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.impl.RacingProcedureFactoryImpl;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.line.ConfigurableStartModeFlagRacingProcedure;
import com.sap.sailing.domain.base.configuration.impl.EmptyRegattaConfiguration;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
@@ -32,7 +37,9 @@ public class StartModeFlagFinder extends RaceLogAnalyzer<Flags> {
@Override
protected Flags performAnalysis() {
RacingProcedureType type = procedureAnalyzer.analyze();
if (!(RacingProcedureType.RRS26.equals(type) || RacingProcedureType.RRS26_3MIN.equals(type) || RacingProcedureType.SWC.equals(type))) {
if (type == RacingProcedureType.UNKNOWN ||
!(new RacingProcedureFactoryImpl(/* author */ null, new EmptyRegattaConfiguration()).createRacingProcedure(type, new RaceLogImpl(UUID.randomUUID()), /* raceLogResolver */ null)
instanceof ConfigurableStartModeFlagRacingProcedure)) {
return null;
}
for (RaceLogEvent event : getPassEventsDescending()) {
@@ -15,6 +15,7 @@ import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.league.impl
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.line.impl.RRS26RacingProcedureImpl;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.line.impl.RRS26ThreeMinutesRacingProcedureImpl;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.line.impl.SWCRacingProcedureImpl;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.line.impl.ShortSWCRacingProcedureImpl;
import com.sap.sailing.domain.base.configuration.ConfigurationLoader;
import com.sap.sailing.domain.base.configuration.RegattaConfiguration;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
@@ -53,6 +54,8 @@ public class ReadonlyRacingProcedureFactory implements RacingProcedureFactory {
return new RRS26ThreeMinutesRacingProcedureImpl(raceLog, author, loadedConfiguration.getRRS26Configuration(), raceLogResolver);
case SWC:
return new SWCRacingProcedureImpl(raceLog, author, loadedConfiguration.getSWCStartConfiguration(), raceLogResolver);
case SWC_4MIN:
return new ShortSWCRacingProcedureImpl(raceLog, author, loadedConfiguration.getSWCStartConfiguration(), raceLogResolver);
case BASIC:
return new BasicRacingProcedureImpl(raceLog, author, loadedConfiguration.getBasicConfiguration(), raceLogResolver);
case LEAGUE:
@@ -23,12 +23,12 @@ import java.util.List;
public class SWCRacingProcedureImpl extends ConfigurableStartModeFlagRacingProcedureImpl implements SWCRacingProcedure {
private final static Duration CLASS_AND_STARTMODE_UP_INTERVAL = Duration.ONE_MINUTE.times(6); // 6 minutes before start
private final static Duration CLASS_AND_STARTMODE_DOWN_INTERVAL = Duration.ONE_MINUTE; // 1 minute after start
private final static Duration FIVE_MINUTES_FLAG_UP_INTERVAL = Duration.ONE_MINUTE.times(5); // 5 minutes before start
private final static Duration FOUR_MINUTES_FLAG_UP_INTERVAL = Duration.ONE_MINUTE.times(4); // 4 minutes before start
private final static Duration THREE_MINUTES_FLAG_UP_INTERVAL = Duration.ONE_MINUTE.times(3); // 3 minutes before start
private final static Duration TWO_MINUTES_FLAG_UP_INTERVAL = Duration.ONE_MINUTE.times(2); // 2 minutes before start
private final static Duration ONE_MINUTE_FLAG_UP_INTERVAL = Duration.ONE_MINUTE; // 1 minutes before start
protected final static Duration CLASS_AND_STARTMODE_DOWN_INTERVAL = Duration.ONE_MINUTE; // 1 minute after start
protected final static Duration FIVE_MINUTES_FLAG_UP_INTERVAL = Duration.ONE_MINUTE.times(5); // 5 minutes before start
protected final static Duration FOUR_MINUTES_FLAG_UP_INTERVAL = Duration.ONE_MINUTE.times(4); // 4 minutes before start
protected final static Duration THREE_MINUTES_FLAG_UP_INTERVAL = Duration.ONE_MINUTE.times(3); // 3 minutes before start
protected final static Duration TWO_MINUTES_FLAG_UP_INTERVAL = Duration.ONE_MINUTE.times(2); // 2 minutes before start
protected final static Duration ONE_MINUTE_FLAG_UP_INTERVAL = Duration.ONE_MINUTE; // 1 minutes before start
public SWCRacingProcedureImpl(RaceLog raceLog, AbstractLogEventAuthor author,
SWCStartConfiguration configuration, RaceLogResolver raceLogResolver) {
@@ -0,0 +1,70 @@
package com.sap.sailing.domain.abstractlog.race.state.racingprocedure.line.impl;
import java.util.Arrays;
import java.util.Collections;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
import com.sap.sailing.domain.abstractlog.race.state.RaceStateEvent;
import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateEventImpl;
import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateEvents;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.FlagPoleState;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.line.SWCRacingProcedure;
import com.sap.sailing.domain.base.configuration.procedures.SWCStartConfiguration;
import com.sap.sailing.domain.common.racelog.FlagPole;
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;
public class ShortSWCRacingProcedureImpl extends SWCRacingProcedureImpl implements SWCRacingProcedure {
private final static Duration CLASS_AND_STARTMODE_UP_INTERVAL_4MIN = Duration.ONE_MINUTE.times(4); // 6 minutes before start
public ShortSWCRacingProcedureImpl(RaceLog raceLog, AbstractLogEventAuthor author,
SWCStartConfiguration configuration, RaceLogResolver raceLogResolver) {
super(raceLog, author, configuration, raceLogResolver);
}
@Override
protected Duration getStartPhaseStartModeUpInterval() {
return CLASS_AND_STARTMODE_UP_INTERVAL_4MIN;
}
@Override
public RacingProcedureType getType() {
return RacingProcedureType.SWC_4MIN;
}
@Override
public Iterable<RaceStateEvent> createStartStateEvents(TimePoint startTime) {
return Arrays.<RaceStateEvent>asList(
new RaceStateEventImpl(startTime.minus(CLASS_AND_STARTMODE_UP_INTERVAL_4MIN), RaceStateEvents.SWC_CLASS_AND_STARTMODE_UP),
new RaceStateEventImpl(startTime.minus(THREE_MINUTES_FLAG_UP_INTERVAL), RaceStateEvents.SWC_THREE_UP),
new RaceStateEventImpl(startTime.minus(TWO_MINUTES_FLAG_UP_INTERVAL), RaceStateEvents.SWC_TWO_UP),
new RaceStateEventImpl(startTime.minus(ONE_MINUTE_FLAG_UP_INTERVAL), RaceStateEvents.SWC_ONE_UP),
new RaceStateEventImpl(startTime, RaceStateEvents.START),
new RaceStateEventImpl(startTime, RaceStateEvents.SWC_GREEN_UP),
new RaceStateEventImpl(startTime.plus(CLASS_AND_STARTMODE_DOWN_INTERVAL), RaceStateEvents.SWC_CLASS_AND_STARTMODE_DOWN));
}
@Override
public FlagPoleState getActiveFlags(TimePoint startTime, TimePoint now) {
if (now.before(startTime.minus(CLASS_AND_STARTMODE_UP_INTERVAL_4MIN))) {
return new FlagPoleState(
Collections.singletonList(new FlagPole(cachedStartmodeFlag, false)),
null,
Collections.singletonList(new FlagPole(cachedStartmodeFlag, true)),
startTime.minus(CLASS_AND_STARTMODE_UP_INTERVAL_4MIN));
} else if (now.before(startTime.minus(THREE_MINUTES_FLAG_UP_INTERVAL))) {
return new FlagPoleState(
Arrays.asList(new FlagPole(cachedStartmodeFlag, true), new FlagPole(Flags.SWC_THREE, false)),
startTime.minus(CLASS_AND_STARTMODE_UP_INTERVAL_4MIN),
Arrays.asList(new FlagPole(cachedStartmodeFlag, true), new FlagPole(Flags.SWC_THREE, true)),
startTime.minus(THREE_MINUTES_FLAG_UP_INTERVAL));
} else {
return super.getActiveFlags(startTime, now);
}
}
}
@@ -191,7 +191,7 @@ public abstract class AbstractScoringSchemeImpl implements ScoringScheme {
/**
* Looks backwards starting at the last race until the first score difference is found, including the discarded
* scored. This implements Racing Rules of Sailing (RRS) section A8.2:
* scores. This implements Racing Rules of Sailing (RRS) section A8.2:
* <p>
*
* <em>"A8.2 If a tie remains between two or more boats, they shall be ranked in order of their scores in the last
@@ -4,6 +4,11 @@
<div id="mainContent">
<h4 class="articleHeadline">What's New - SAP Sailing Race Manager</h4>
<div class="innerContent">
<h5 class="articleSubheadline">August 2023</h5>
<ul class="bulletList">
<li>Added a new racing procedure <tt>SWC_4MIN</tt> for kites and windsurfers with a shortened four-minute
start sequence with green flag for one minute after start.</li>
</ul>
<h5 class="articleSubheadline">July 2023</h5>
<ul class="bulletList">
<li>Added "SCA" as an invalid result marker (IRM) / redress code.</li>
@@ -210,7 +210,8 @@ public class RaceDetailPanel extends SimplePanel {
switch (data.raceInfo.startProcedure) {
case RRS26:
case RRS26_3MIN:
case SWC:
case SWC:
case SWC_4MIN:
LineStartInfoDTO rrsInfo = (LineStartInfoDTO) data.raceInfo.startProcedureDTO;
if (rrsInfo != null) {
if (rrsInfo.startModeFlag != null) {
@@ -1123,6 +1123,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
case RRS26:
case RRS26_3MIN:
case SWC:
case SWC_4MIN:
ConfigurableStartModeFlagRacingProcedure linestart = state.getTypedReadonlyRacingProcedure();
info = new LineStartInfoDTO(linestart.getStartModeFlag());
case UNKNOWN:
@@ -73,7 +73,6 @@ class MediaLibrary {
}
Collection<MediaTrack> findMediaTracksInTimeRange(TimePoint startTime, TimePoint endTime) {
LockUtil.lockForRead(lock);
try {
List<MediaTrack> result = new ArrayList<MediaTrack>();
@@ -302,5 +301,4 @@ class MediaLibrary {
public MediaTrack lookupMediaTrack(MediaTrack mediaTrack) {
return resolveClone(mediaTrack);
}
}
@@ -3985,7 +3985,6 @@ Replicator {
mediaDB.updateRace(mediaTrack.dbId, mediaTrack.assignedRaces);
mediaLibrary.assignedRacesChanged(mediaTrack);
replicate(new UpdateMediaTrackRacesOperation(mediaTrack));
}
@Override
@@ -23,6 +23,11 @@
<div class="mainContent">
<h2 class="releaseHeadline">Release Notes - Administration Console</h2>
<div class="innerContent">
<h2 class="articleSubheadline">August 2023</h2>
<ul class="bulletList">
<li>Added a new racing procedure <tt>SWC_4MIN</tt> for kites and windsurfers with a shortened four-minute
start sequence with green flag for one minute after start.</li>
</ul>
<h2 class="articleSubheadline">July 2023</h2>
<ul class="bulletList">
<li>Score updates received through the race log, e.g., from the SAP Sailing Race Manager app or from the
@@ -85,6 +85,7 @@ public class SecuredServerImpl implements SecuredServer {
final int statusCode = response.getStatusLine().getStatusCode();
Object jsonParseResult;
if (statusCode == Response.Status.NO_CONTENT.getStatusCode()
|| Response.Status.fromStatusCode(statusCode) == null
|| Response.Status.fromStatusCode(statusCode).getFamily() != Family.SUCCESSFUL) {
jsonParseResult = null;
} else {
+6 -1
View File
@@ -51,7 +51,12 @@ if [ "${useRestApi}" = "1" ]; then
AUTH=""
fi
HEADERS=$( mktemp )
CURL_OUTPUT=$( curl -sL --dump-header "${HEADERS}" -H 'Content-Type: multipart/form-data' "${NEWSERVER}/sailingserver/api/v1/compareservers" -d "server2=${OLDSERVER}" ${AUTH} 2>${WGET_ERR} )
LEADERBOARD_GROUPS=""
while [ -n "$3" ]; do
LEADERBOARD_GROUPS="${LEADERBOARD_GROUPS} -d leaderboardgroupUUID[]=$3"
shift
done
CURL_OUTPUT=$( curl -sL --dump-header "${HEADERS}" -H 'Content-Type: multipart/form-data' "${NEWSERVER}/sailingserver/api/v1/compareservers" -d "server2=${OLDSERVER}" ${AUTH} ${LEADERBOARD_GROUPS} 2>${WGET_ERR} )
echo "${CURL_OUTPUT}" | jq
HTTP_STATUS=$( cat "${HEADERS}" | grep "^HTTP\/[0-9.]* [0-9]\{3\}" | tail -1 | sed -e 's/^HTTP\/[0-9.]* \([0-9]\{3\}\).*$/\1/' )
rm -f "${HEADERS}"
@@ -234,6 +234,7 @@ public class AppPreferences {
case RRS26_3MIN:
return key(R.string.preference_racing_procedure_rrs26_classflag_key);
case SWC:
case SWC_4MIN:
return key(R.string.preference_racing_procedure_swc_classflag_key);
case GateStart:
return key(R.string.preference_racing_procedure_gatestart_classflag_key);
@@ -259,6 +260,7 @@ public class AppPreferences {
case RRS26_3MIN:
return key(R.string.preference_racing_procedure_rrs26_hasxray_key);
case SWC:
case SWC_4MIN:
return key(R.string.preference_racing_procedure_swc_hasxray_key);
case GateStart:
return key(R.string.preference_racing_procedure_gatestart_hasxray_key);
@@ -284,6 +286,7 @@ public class AppPreferences {
case RRS26_3MIN:
return key(R.string.preference_racing_procedure_rrs26_resultentryenabled_key);
case SWC:
case SWC_4MIN:
return key(R.string.preference_racing_procedure_swc_resultentryenabled_key);
case GateStart:
return key(R.string.preference_racing_procedure_gatestart_resultentryenabled_key);
@@ -47,26 +47,26 @@ public class PreferencesRegattaConfigurationLoader implements ConfigurationLoade
@Override
public RegattaConfiguration load() {
// Default
configuration.setDefaultRacingProcedureType(preferences.getDefaultRacingProcedureType());
configuration.setDefaultCourseDesignerMode(preferences.getDefaultCourseDesignerMode());
configuration.setDefaultProtestTimeDuration(
Duration.ONE_MINUTE.times(preferences.getProtestTimeDurationInMinutes()));
// RRS26
RRS26ConfigurationImpl rrs26 = new RRS26ConfigurationImpl();
rrs26.setClassFlag(preferences.getRacingProcedureClassFlag(RacingProcedureType.RRS26));
rrs26.setHasIndividualRecall(preferences.getRacingProcedureHasIndividualRecall(RacingProcedureType.RRS26));
rrs26.setResultEntryEnabled(preferences.getRacingProcedureIsResultEntryEnabled(RacingProcedureType.RRS26));
rrs26.setStartModeFlags(new ArrayList<>(preferences.getRRS26StartmodeFlags()));
configuration.setRRS26Configuration(rrs26);
// SWC
SWCStartConfigurationImpl swcStart = new SWCStartConfigurationImpl();
swcStart.setClassFlag(preferences.getRacingProcedureClassFlag(RacingProcedureType.SWC));
swcStart.setHasIndividualRecall(preferences.getRacingProcedureHasIndividualRecall(RacingProcedureType.SWC));
swcStart.setResultEntryEnabled(preferences.getRacingProcedureIsResultEntryEnabled(RacingProcedureType.SWC));
swcStart.setStartModeFlags(new ArrayList<>(preferences.getSWCStartmodeFlags()));
configuration.setSWCStartConfiguration(swcStart);
// Gate Start
GateStartConfigurationImpl gateStart = new GateStartConfigurationImpl();
gateStart.setClassFlag(preferences.getRacingProcedureClassFlag(RacingProcedureType.GateStart));
gateStart.setHasIndividualRecall(
@@ -76,25 +76,25 @@ public class PreferencesRegattaConfigurationLoader implements ConfigurationLoade
gateStart.setHasPathfinder(preferences.getGateStartHasPathfinder());
gateStart.setHasAdditionalGolfDownTime(preferences.getGateStartHasAdditionalGolfDownTime());
configuration.setGateStartConfiguration(gateStart);
// Extreme Sailing Series
ESSConfigurationImpl ess = new ESSConfigurationImpl();
ess.setClassFlag(preferences.getRacingProcedureClassFlag(RacingProcedureType.ESS));
ess.setHasIndividualRecall(preferences.getRacingProcedureHasIndividualRecall(RacingProcedureType.ESS));
ess.setResultEntryEnabled(preferences.getRacingProcedureIsResultEntryEnabled(RacingProcedureType.ESS));
configuration.setESSConfiguration(ess);
// Basic
RacingProcedureConfigurationImpl basic = new RacingProcedureConfigurationImpl();
basic.setClassFlag(preferences.getRacingProcedureClassFlag(RacingProcedureType.BASIC));
basic.setHasIndividualRecall(preferences.getRacingProcedureHasIndividualRecall(RacingProcedureType.BASIC));
basic.setResultEntryEnabled(preferences.getRacingProcedureIsResultEntryEnabled(RacingProcedureType.BASIC));
configuration.setBasicConfiguration(basic);
// League Start
LeagueConfigurationImpl league = new LeagueConfigurationImpl();
league.setClassFlag(preferences.getRacingProcedureClassFlag(RacingProcedureType.LEAGUE));
league.setHasIndividualRecall(preferences.getRacingProcedureHasIndividualRecall(RacingProcedureType.LEAGUE));
league.setResultEntryEnabled(preferences.getRacingProcedureIsResultEntryEnabled(RacingProcedureType.LEAGUE));
configuration.setLeagueConfiguration(league);
// clone the result
return configuration.clone();
}