mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-12 05:35:31 +00:00
Merge branch 'master' into windestimation
Change-Id: I1356ad8c307e20dfa114aa2438f6d1d3c5898793
This commit is contained in:
commit
b6dd97ef8b
179 files changed
+4656
-2688
No files matched your search
+22
-9
@@ -16,7 +16,9 @@ import com.sap.sailing.domain.base.RaceColumnListener;
|
||||
import com.sap.sailing.domain.base.impl.RaceColumnListenerWithDefaultAction;
|
||||
import com.sap.sailing.domain.common.LeaderboardNameConstants;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.common.RankingMetrics;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.ScoringScheme;
|
||||
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
|
||||
import com.sap.sailing.server.interfaces.RacingEventService;
|
||||
@@ -65,8 +67,8 @@ public class RaceLogScoringReplicator implements RaceColumnListenerWithDefaultAc
|
||||
|
||||
/**
|
||||
* Called when a {@link RaceLogFinishPositioningConfirmedEvent} was received by the {@link RaceLog}. Retrieves the
|
||||
* last {@link RaceLogFinishPositioningConfirmedEvent} from the racelog and applies the ranks and disqualifications
|
||||
* entered by the race committee to the score correstions as follows:
|
||||
* last {@link RaceLogFinishPositioningConfirmedEvent} from the {@link RaceLog} and applies the ranks and
|
||||
* disqualifications entered by the race committee to the score corrections as follows:
|
||||
* <ul>
|
||||
* <li>When no {@link CompetitorResult} object is received for a competitor, no change is applied to that
|
||||
* competitor's score corrections.</li>
|
||||
@@ -75,11 +77,13 @@ public class RaceLogScoringReplicator implements RaceColumnListenerWithDefaultAc
|
||||
* {@link MaxPointsReason}, any existing score correction (points) is removed for that competitor, otherwise, the
|
||||
* score correction (points) from the CompetitorResult object is applied if provided (in this case a rank provided
|
||||
* in the {@link CompetitorResult} object is ignored); if no {@link MaxPointsReason} is provided and only a rank but
|
||||
* no score is provided in the {@link CompetitorResult}, the scoring scheme will compute the score from the rank,
|
||||
* considering any {@link MaxPointsReason} provided in the result, and that score will be applied as a score
|
||||
* correction. If a {@link MaxPointsReason} but no explicit score is provided, the rank is ignored because
|
||||
* the scoring scheme is expected to compute the score from the {@link MaxPointsReason}; therefore, the score
|
||||
* correction (points) is cleared in this case so that the scoring scheme will be used for score calculation.</li>
|
||||
* no score is provided in the {@link CompetitorResult}, the scoring scheme will
|
||||
* {@link ScoringScheme#getScoreForRank(Leaderboard, RaceColumn, Competitor, int, java.util.concurrent.Callable, com.sap.sailing.domain.leaderboard.NumberOfCompetitorsInLeaderboardFetcher, TimePoint)
|
||||
* compute} the score from the rank, considering any {@link MaxPointsReason} provided in the result, and that score
|
||||
* will be applied as a score correction. If a {@link MaxPointsReason} but no explicit score is provided, the rank
|
||||
* is ignored because the scoring scheme is expected to compute the score from the {@link MaxPointsReason};
|
||||
* therefore, the score correction (points) is cleared in this case so that the scoring scheme will be used for
|
||||
* score calculation.</li>
|
||||
* <li>When a {@link CompetitorResult} object is received for a competitor, if it contains {@code null} for the
|
||||
* {@link MaxPointsReason}, any existing {@link MaxPointsReason} is removed for that competitor; otherwise, the
|
||||
* {@link MaxPointsReason} from the {@link CompetitorResult} object is applied, and if no explicit score is provided
|
||||
@@ -174,8 +178,17 @@ public class RaceLogScoringReplicator implements RaceColumnListenerWithDefaultAc
|
||||
// let scoring scheme calculate the penalty score dynamically
|
||||
scoreByRaceCommittee = null;
|
||||
} else {
|
||||
scoreByRaceCommittee = leaderboard.getScoringScheme().getScoreForRank(leaderboard, raceColumn, competitor,
|
||||
oneBasedRankByRaceCommittee, ()->numberOfCompetitorsInRace, leaderboard.getNumberOfCompetitorsInLeaderboardFetcher(), timePoint);
|
||||
// Check whether it's a non-one-design regatta. In that case, "rank by race committee" just means finish line
|
||||
// crossing order, but that's not relevant for the actual *ranking* in a handicapped regatta. Corrected/calculated
|
||||
// times are. Therefore, for handicap regattas, don't ask the scoring scheme to map the finishing order
|
||||
// to a score.
|
||||
if (leaderboard instanceof RegattaLeaderboard &&
|
||||
((RegattaLeaderboard) leaderboard).getRegatta().getRankingMetricType() != RankingMetrics.ONE_DESIGN) {
|
||||
scoreByRaceCommittee = null;
|
||||
} else {
|
||||
scoreByRaceCommittee = leaderboard.getScoringScheme().getScoreForRank(leaderboard, raceColumn, competitor,
|
||||
oneBasedRankByRaceCommittee, ()->numberOfCompetitorsInRace, leaderboard.getNumberOfCompetitorsInLeaderboardFetcher(), timePoint);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
scoreByRaceCommittee = optionalExplicitScore;
|
||||
|
||||
+28
-7
@@ -2,8 +2,9 @@ package com.sap.sailing.server.security;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
@@ -51,16 +52,21 @@ public class PermissionAwareRaceTrackingHandler extends DefaultRaceTrackingHandl
|
||||
defaultTenant = securityService.getDefaultTenantForCurrentUser();
|
||||
}
|
||||
|
||||
private <T> T decorate(RegattaAndRaceIdentifier regattaAndRaceIdentifier, Supplier<T> innerAction) {
|
||||
/**
|
||||
* Sets the ownership for a {@link SecuredDomainType#TRACKED_RACE} object identified by
|
||||
* {@code regattaAndRaceIdentifier} if no ownership exists for it yet; then, the permission to
|
||||
* create the object is checked. If granted, the {@code raceCreationAction} is executed and its
|
||||
* result is returned. Otherwise, the action is not executed, and if the ownership was set here,
|
||||
* it is removed again.
|
||||
*/
|
||||
private <T> T setOwnershipForRace(RegattaAndRaceIdentifier regattaAndRaceIdentifier, Callable<T> raceCreationAction) {
|
||||
SubjectThreadState subjectThreadState = new SubjectThreadState(subject);
|
||||
subjectThreadState.bind();
|
||||
try {
|
||||
return securityService.doWithTemporaryDefaultTenant(defaultTenant, () -> {
|
||||
return securityService.setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
|
||||
SecuredDomainType.TRACKED_RACE, regattaAndRaceIdentifier.getTypeRelativeObjectIdentifier(),
|
||||
regattaAndRaceIdentifier.toString(), () -> {
|
||||
return innerAction.get();
|
||||
});
|
||||
regattaAndRaceIdentifier.toString(), raceCreationAction);
|
||||
});
|
||||
} finally {
|
||||
subjectThreadState.restore();
|
||||
@@ -73,7 +79,7 @@ public class PermissionAwareRaceTrackingHandler extends DefaultRaceTrackingHandl
|
||||
long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed,
|
||||
DynamicRaceDefinitionSet raceDefinitionSetToUpdate, boolean useMarkPassingCalculator,
|
||||
RaceLogResolver raceLogResolver, Optional<ThreadLocalTransporter> threadLocalTransporter) {
|
||||
return decorate(new RegattaNameAndRaceName(trackedRegatta.getRegatta().getName(), raceDefinition.getName()),
|
||||
return setOwnershipForRace(new RegattaNameAndRaceName(trackedRegatta.getRegatta().getName(), raceDefinition.getName()),
|
||||
() -> super.createTrackedRace(trackedRegatta, raceDefinition, sidelines, windStore, delayToLiveInMillis,
|
||||
millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed,
|
||||
raceDefinitionSetToUpdate, useMarkPassingCalculator, raceLogResolver, threadLocalTransporter));
|
||||
@@ -82,7 +88,22 @@ public class PermissionAwareRaceTrackingHandler extends DefaultRaceTrackingHandl
|
||||
@Override
|
||||
public RaceDefinition createRaceDefinition(Regatta regatta, String name, Course course, BoatClass boatClass,
|
||||
Map<Competitor, Boat> competitorsAndTheirBoats, Serializable id) {
|
||||
return decorate(new RegattaNameAndRaceName(regatta.getName(), name),
|
||||
// TODO bug 5015: this is just a very basic hack that is not checking for competitor creation permission but for now only establishes an ownership when none exists
|
||||
SubjectThreadState subjectThreadState = new SubjectThreadState(subject);
|
||||
subjectThreadState.bind();
|
||||
try {
|
||||
for (final Entry<Competitor, Boat> e : competitorsAndTheirBoats.entrySet()) {
|
||||
if (securityService.getOwnership(e.getKey().getIdentifier()) == null) {
|
||||
securityService.setOwnership(e.getKey().getIdentifier(), securityService.getCurrentUser(), defaultTenant);
|
||||
}
|
||||
if (securityService.getOwnership(e.getValue().getIdentifier()) == null) {
|
||||
securityService.setOwnership(e.getValue().getIdentifier(), securityService.getCurrentUser(), defaultTenant);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
subjectThreadState.restore();
|
||||
}
|
||||
return setOwnershipForRace(new RegattaNameAndRaceName(regatta.getName(), name),
|
||||
() -> super.createRaceDefinition(regatta, name, course, boatClass, competitorsAndTheirBoats, id));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user