Updated SailingNotificationService and the associated messages

This commit is contained in:
Steffen Schaefer committed 2016-07-13 10:42:37 +02:00
1 parent 4252c2b270
commit a4c4713e42
3 files changed
+248 -51

No files matched your search

@@ -1,6 +1,24 @@
boatClassResultsSubject=New results for boat class {0} in regatta {1} of event {2}
boatClassResultsBody=New results for boat class {0} in regatta {1} of event {2} are available. See: {3}
boatClassUpcomingRaceSubject=A race for boat class {0} in regatta {1} of event {2} will start soon
boatClassUpcomingRaceBody=A race for boat class {0} in regatta {1} of event {2} will start at {4}. See: {3}
competitorResultsSubject=New results for competitor {0} in regatta {1} of event {2}
competitorResultsBody=New results for competitor {0} in regatta {1} of event {2} are available. See: {3}
raceInRegattaOfEvent=race {0} in regatta {1} of event {2}
raceInFleetInRegattaOfEvent={0} ({3}) in regatta {1} of event {2}
leaderboardOfEvent=leaderboard {0} of event {1}
boatClassRaceFinishingSubject=Race for boat class {0} finishes - new results available
# 0: boatClassName, 1: raceDescription, 2: link
boatClassRaceFinishingBody=New results for boat class {0} in {1} are available. See: {2}
boatClassScoreCorrectionSubject=New results are available for boat class {0}
# 0: boatClassName, 1: leaderboardDescription, 2: link
boatClassScoreCorrectionBody=New results for boat class {0} in {1} are available. See: {2}
competitorPassesFinishSubject=Competitor {0} passed finish line in a race
# 0: competitorName, 1: raceDescription, 2: link
competitorPassesFinishBody=Competitor {0} passed finish line in {1}. See: {2}
competitorScoreCorrectionSubject=New results are available for competitor {0}
# 0: competitorName, 1: leaderboardDescription, 2: link
boatClassScoreCorrectionBody=New results for competitor {0} in {1} are available. See: {2}
boatClassUpcomingRaceSubject=A race for boat class {0} will start soon
# 0: boatClassName, 1: raceDescription, 2: time, 3: link
boatClassUpcomingRaceBody=A race for boat class {0} in {1} will start approximately at {2}. See: {3}
@@ -1,16 +1,42 @@
package com.sap.sailing.server.notification;
import com.sap.sailing.domain.abstractlog.race.state.RaceState;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.TimePoint;
public interface SailingNotificationService {
void notifyUserOnBoatClassResults(BoatClass boatClass, String eventName, String regattaDisplayName, String link);
/**
* Called when {@link RaceState} changes state to finishing/finished (?).
*/
void notifyUserOnBoatClassRaceChangesStateToFinishing(BoatClass boatClass, TrackedRace trackedRace, Leaderboard leaderboard, RaceColumn raceColumn,
Fleet fleet);
/**
* Called on score correction for a race with BoatClass if the last score correction was more than one minute.
*/
void notifyUserOnBoatClassWhenScoreCorrectionsAreAvailable(BoatClass boatClass, Leaderboard leaderboard);
/**
* Called whenever a start time is set for a race with {@link BoatClass} through the race's {@link RaceState}.
*/
void notifyUserOnBoatClassUpcomingRace(BoatClass boatClass, Leaderboard leaderboard, RaceColumn raceColumn,
Fleet fleet, TimePoint when);
void notifyUserOnBoatClassUpcomingRace(BoatClass boatClass, String eventName, String regattaDisplayName,
TimePoint when, String link);
/**
* Triggered when a competitor passes the finishing waypoint of a race.
*/
void notifyUserOnCompetitorPassesFinish(Competitor competitor, TrackedRace trackedRace, Leaderboard leaderboard, RaceColumn raceColumn,
Fleet fleet);
void notifyUserOnCompetitorResults(Competitor competitor, String eventName, String regattaDisplayName, String link);
/**
* Triggered when a score correction is set for competitor on any leaderboard.
*/
void notifyUserOnCompetitorScoreCorrections(Competitor competitor, Leaderboard leaderboard);
}
@@ -3,17 +3,30 @@ package com.sap.sailing.server.notification.impl;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import java.util.function.BiConsumer;
import org.osgi.framework.BundleContext;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sailing.server.impl.preferences.BoatClassResultsNotificationSet;
import com.sap.sailing.server.impl.preferences.BoatClassUpcomingRaceNotificationSet;
import com.sap.sailing.server.impl.preferences.CompetitorResultsNotificationSet;
import com.sap.sailing.server.notification.SailingNotificationService;
import com.sap.sse.common.Stoppable;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.i18n.impl.ResourceBundleStringMessagesImpl;
import com.sap.sse.mail.queue.MailQueue;
@@ -22,6 +35,7 @@ public class SailingNotificationServiceImpl implements Stoppable, SailingNotific
private final Set<Stoppable> toStop = new HashSet<>();
private final MailQueue mailQueue;
private RacingEventService racingEventService;
private final ResourceBundleStringMessagesImpl messages;
private final BoatClassResultsNotificationSet boatClassResults;
@@ -43,59 +57,198 @@ public class SailingNotificationServiceImpl implements Stoppable, SailingNotific
toStop.forEach(Stoppable::stop);
}
@Override
public void notifyUserOnBoatClassResults(BoatClass boatClass, String eventName, String regattaDisplayName,
String link) {
mailQueue.addNotification(new NotificationSetNotification<BoatClass>(boatClass, boatClassResults) {
@Override
protected String constructSubject(BoatClass objectToNotifyAbout, Locale locale) {
return messages.get(locale, "boatClassResultsSubject", boatClass.getDisplayName(), regattaDisplayName,
eventName);
}
public void setRacingEventService(RacingEventServiceImpl racingEventService) {
this.racingEventService = racingEventService;
}
@Override
protected String constructBody(BoatClass objectToNotifyAbout, Locale locale) {
return messages.get(locale, "boatClassResultsBody", boatClass.getDisplayName(), regattaDisplayName,
eventName);
private Pair<Event, LeaderboardGroup> calculateAssociatedEventForLeaderboard(final Leaderboard leaderboard) {
Set<Event> foundEvents = new HashSet<>();
Set<LeaderboardGroup> foundLeaderboardGroups = new HashSet<>();
racingEventService.getAllEvents().forEach(event -> {
event.getLeaderboardGroups().forEach(leaderboardGroup -> {
if (Util.contains(leaderboardGroup.getLeaderboards(), leaderboard)) {
foundEvents.add(event);
foundLeaderboardGroups.add(leaderboardGroup);
}
});
});
int foundEventsCount = foundEvents.size();
if (foundEventsCount == 1) {
return new Pair<>(Util.get(foundEvents, 0), Util.get(foundLeaderboardGroups, 0));
} else if (foundEventsCount > 1 && foundLeaderboardGroups.size() == 1) {
// could be a series
LeaderboardGroup leaderboardGroup = Util.get(foundLeaderboardGroups, 0);
if (leaderboardGroup.hasOverallLeaderboard()) {
CourseArea defaultCourseArea = leaderboard.getDefaultCourseArea();
if (defaultCourseArea != null) {
for (Event event : foundEvents) {
if (Util.contains(event.getVenue().getCourseAreas(), defaultCourseArea)) {
return new Pair<>(event, leaderboardGroup);
}
}
}
}
}
// No associated event found or association is ambiguous
return null;
}
private void doWithEvent(Leaderboard leaderboard, BiConsumer<Event, LeaderboardGroup> consumer) {
if (racingEventService == null) {
// TODO log
return;
}
Pair<Event, LeaderboardGroup> eventAndLeaderboardGroup = calculateAssociatedEventForLeaderboard(leaderboard);
if (eventAndLeaderboardGroup != null) {
consumer.accept(eventAndLeaderboardGroup.getA(), eventAndLeaderboardGroup.getB());
}
}
private String calculateRaceDescription(Locale locale, Event event, Leaderboard leaderboard, RaceColumn raceColumn,
Fleet fleet) {
String raceName = raceColumn.getName();
String eventName = event.getName();
String leaderboardDisplayName = leaderboard.getDisplayName() != null ? leaderboard.getDisplayName()
: leaderboard.getName();
if (Util.size(raceColumn.getFleets()) > 1) {
return messages.get(locale, "raceInFleetInRegattaOfEvent", raceName, leaderboardDisplayName, eventName,
fleet.getName());
} else {
return messages.get(locale, "raceInRegattaOfEvent", raceName, leaderboardDisplayName, eventName);
}
}
private String calculateLeaderboardDescription(Locale locale, Event event, Leaderboard leaderboard) {
String eventName = event.getName();
String leaderboardDisplayName = leaderboard.getDisplayName() != null ? leaderboard.getDisplayName()
: leaderboard.getName();
return messages.get(locale, "leaderboardOfEvent", leaderboardDisplayName, eventName);
}
@Override
public void notifyUserOnBoatClassRaceChangesStateToFinishing(BoatClass boatClass, TrackedRace trackedRace,
Leaderboard leaderboard, RaceColumn raceColumn, Fleet fleet) {
doWithEvent(leaderboard, (event, leaderboardGroup) -> {
RegattaAndRaceIdentifier raceIdentifier = trackedRace.getRaceIdentifier();
// TODO where to get the base URL?
String link = "/gwt/RaceBoard.html?eventId=" + event.getId() + "&leaderboardName=" + leaderboard.getName()
+ "&leaderboardGroupName=" + leaderboardGroup.getName() + "&raceName="
+ raceIdentifier.getRaceName() + "&showMapControls=true&viewShowNavigationPanel=true&regattaName="
+ raceIdentifier.getRegattaName();
mailQueue.addNotification(new NotificationSetNotification<BoatClass>(boatClass, boatClassResults) {
@Override
protected String constructSubject(BoatClass objectToNotifyAbout, Locale locale) {
return messages.get(locale, "boatClassRaceFinishingSubject", boatClass.getDisplayName());
}
@Override
protected String constructBody(BoatClass objectToNotifyAbout, Locale locale) {
String raceDescription = calculateRaceDescription(locale, event, leaderboard, raceColumn, fleet);
return messages.get(locale, "boatClassRaceFinishingBody", boatClass.getDisplayName(),
raceDescription, link);
}
});
});
}
@Override
public void notifyUserOnBoatClassUpcomingRace(BoatClass boatClass, String eventName, String regattaDisplayName,
TimePoint when, String link) {
mailQueue.addNotification(new NotificationSetNotification<BoatClass>(boatClass, boatClassUpcomingRace) {
@Override
protected String constructSubject(BoatClass objectToNotifyAbout, Locale locale) {
return messages.get(locale, "boatClassUpcomingRaceSubject", boatClass.getDisplayName(),
regattaDisplayName, eventName);
}
public void notifyUserOnBoatClassWhenScoreCorrectionsAreAvailable(BoatClass boatClass, Leaderboard leaderboard) {
doWithEvent(leaderboard, (event, leaderboardGroup) -> {
// TODO where to get the base URL?
String link = "/gwt/Home.html#/regatta/races/:eventId=" + event.getId() + "&regattaId="
+ leaderboard.getName();
@Override
protected String constructBody(BoatClass objectToNotifyAbout, Locale locale) {
// TODO properly format time in the user's locale
String time = when.toString();
return messages.get(locale, "boatClassUpcomingRaceBody", boatClass.getDisplayName(), regattaDisplayName,
eventName, time);
}
mailQueue.addNotification(new NotificationSetNotification<BoatClass>(boatClass, boatClassResults) {
@Override
protected String constructSubject(BoatClass objectToNotifyAbout, Locale locale) {
return messages.get(locale, "boatClassScoreCorrectionSubject", boatClass.getDisplayName());
}
@Override
protected String constructBody(BoatClass objectToNotifyAbout, Locale locale) {
String leaderboardDescription = calculateLeaderboardDescription(locale, event, leaderboard);
return messages.get(locale, "boatClassScoreCorrectionBody", boatClass.getDisplayName(),
leaderboardDescription, link);
}
});
});
}
public void notifyUserOnBoatClassUpcomingRace(BoatClass boatClass, Leaderboard leaderboard, RaceColumn raceColumn,
Fleet fleet, TimePoint when) {
doWithEvent(leaderboard, (event, leaderboardGroup) -> {
// TODO where to get the base URL?
String link = "/gwt/Home.html#/regatta/races/:eventId="+event.getId()+"&regattaId=" + leaderboard.getName();
mailQueue.addNotification(new NotificationSetNotification<BoatClass>(boatClass, boatClassUpcomingRace) {
@Override
protected String constructSubject(BoatClass objectToNotifyAbout, Locale locale) {
return messages.get(locale, "boatClassUpcomingRaceSubject", boatClass.getDisplayName());
}
@Override
protected String constructBody(BoatClass objectToNotifyAbout, Locale locale) {
String raceDescription = calculateRaceDescription(locale, event, leaderboard, raceColumn, fleet);
// TODO properly format time in the user's locale
String time = when.toString();
return messages.get(locale, "boatClassUpcomingRaceBody", boatClass.getDisplayName(),
raceDescription, time, link);
}
});
});
}
@Override
public void notifyUserOnCompetitorResults(Competitor competitor, String eventName, String regattaDisplayName,
String link) {
mailQueue.addNotification(new NotificationSetNotification<Competitor>(competitor, competitorResults) {
@Override
protected String constructSubject(Competitor objectToNotifyAbout, Locale locale) {
return messages.get(locale, "competitorResultsSubject", competitor.getName(), regattaDisplayName,
eventName);
}
public void notifyUserOnCompetitorPassesFinish(Competitor competitor, TrackedRace trackedRace,
Leaderboard leaderboard, RaceColumn raceColumn, Fleet fleet) {
doWithEvent(leaderboard, (event, leaderboardGroup) -> {
RegattaAndRaceIdentifier raceIdentifier = trackedRace.getRaceIdentifier();
// TODO where to get the base URL?
String link = "/gwt/RaceBoard.html?eventId=" + event.getId() + "&leaderboardName=" + leaderboard.getName()
+ "&leaderboardGroupName=" + leaderboardGroup.getName() + "&raceName="
+ raceIdentifier.getRaceName() + "&showMapControls=true&viewShowNavigationPanel=true&regattaName="
+ raceIdentifier.getRegattaName();
@Override
protected String constructBody(Competitor objectToNotifyAbout, Locale locale) {
return messages.get(locale, "competitorResultsBody", competitor.getName(), regattaDisplayName,
eventName);
}
mailQueue.addNotification(new NotificationSetNotification<Competitor>(competitor, competitorResults) {
@Override
protected String constructSubject(Competitor objectToNotifyAbout, Locale locale) {
return messages.get(locale, "competitorPassesFinishSubject", competitor.getName());
}
@Override
protected String constructBody(Competitor objectToNotifyAbout, Locale locale) {
String raceDescription = calculateRaceDescription(locale, event, leaderboard, raceColumn, fleet);
return messages.get(locale, "competitorPassesFinishBody", competitor.getName(), raceDescription,
link);
}
});
});
}
@Override
public void notifyUserOnCompetitorScoreCorrections(Competitor competitor, Leaderboard leaderboard) {
doWithEvent(leaderboard, (event, leaderboardGroup) -> {
// TODO where to get the base URL?
String link = "/gwt/Home.html#/regatta/races/:eventId=" + event.getId() + "&regattaId="
+ leaderboard.getName();
mailQueue.addNotification(new NotificationSetNotification<Competitor>(competitor, competitorResults) {
@Override
protected String constructSubject(Competitor objectToNotifyAbout, Locale locale) {
return messages.get(locale, "boatClassScoreCorrectionSubject", competitor.getName());
}
@Override
protected String constructBody(Competitor objectToNotifyAbout, Locale locale) {
String leaderboardDescription = calculateLeaderboardDescription(locale, event, leaderboard);
return messages.get(locale, "boatClassScoreCorrectionBody", competitor.getName(),
leaderboardDescription, link);
}
});
});
}
}