-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OTP-1382 GMAP Push notifications for leg transition #275
base: dev
Are you sure you want to change the base?
Changes from 5 commits
7ba414d
7c466fc
21d9407
ee451f6
f9126c4
ad42160
75f44c8
926f994
128fb32
91d6619
c5582e1
2638f04
17363ac
bc20b84
4e788c5
22ed611
5159804
c05e011
8340c43
07ad8d8
36b26af
4366df5
b3ab1fd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,32 @@ | ||
package org.opentripplanner.middleware.models; | ||
|
||
import org.opentripplanner.middleware.i18n.Message; | ||
import org.opentripplanner.middleware.otp.response.Leg; | ||
import org.opentripplanner.middleware.persistence.Persistence; | ||
import org.opentripplanner.middleware.tripmonitor.jobs.CheckMonitoredTrip; | ||
import org.opentripplanner.middleware.tripmonitor.jobs.NotificationType; | ||
import org.opentripplanner.middleware.triptracker.TravelerPosition; | ||
import org.opentripplanner.middleware.triptracker.TripStatus; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import javax.annotation.Nullable; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.HashSet; | ||
import java.util.Locale; | ||
import java.util.Set; | ||
|
||
import static com.mongodb.client.model.Filters.eq; | ||
import static org.opentripplanner.middleware.tripmonitor.jobs.NotificationType.ARRIVED_AND_MODE_CHANGE_NOTIFICATION; | ||
import static org.opentripplanner.middleware.tripmonitor.jobs.NotificationType.ARRIVED_NOTIFICATION; | ||
import static org.opentripplanner.middleware.tripmonitor.jobs.NotificationType.DEPARTED_NOTIFICATION; | ||
import static org.opentripplanner.middleware.triptracker.TravelerLocator.hasRequiredTransitLeg; | ||
import static org.opentripplanner.middleware.triptracker.TravelerLocator.hasRequiredTripStatus; | ||
import static org.opentripplanner.middleware.triptracker.TravelerLocator.hasRequiredWalkLeg; | ||
import static org.opentripplanner.middleware.triptracker.TravelerLocator.isApproachingEndOfLeg; | ||
import static org.opentripplanner.middleware.triptracker.TravelerLocator.isAtStartOfLeg; | ||
|
||
public class LegTransitionNotification { | ||
private static final Logger LOG = LoggerFactory.getLogger(LegTransitionNotification.class); | ||
|
||
public String travelerName; | ||
public NotificationType notificationType; | ||
|
@@ -34,28 +51,27 @@ public LegTransitionNotification( | |
* Create {@link TripMonitorNotification} for leg transition based on notification type. | ||
*/ | ||
@Nullable | ||
public TripMonitorNotification createTripMonitorNotification(NotificationType notificationType) { | ||
private TripMonitorNotification createTripMonitorNotification(NotificationType notificationType) { | ||
String body; | ||
switch (notificationType) { | ||
case MODE_CHANGE_NOTIFICATION: | ||
case ARRIVED_AND_MODE_CHANGE_NOTIFICATION: | ||
body = String.format( | ||
Message.MODE_CHANGE_NOTIFICATION.get(travelerPosition.locale), | ||
getTravelerName(), | ||
travelerPosition.expectedLeg.mode, | ||
travelerPosition.nextLeg.mode | ||
Message.ARRIVED_AND_MODE_CHANGE_NOTIFICATION.get(observerLocale), | ||
travelerName, | ||
travelerPosition.expectedLeg.to.name | ||
); | ||
break; | ||
case DEPARTED_NOTIFICATION: | ||
body = String.format( | ||
Message.DEPARTED_NOTIFICATION.get(observerLocale), | ||
getTravelerName(), | ||
travelerName, | ||
travelerPosition.expectedLeg.from.name | ||
); | ||
break; | ||
case ARRIVED_NOTIFICATION: | ||
body = String.format( | ||
Message.ARRIVED_NOTIFICATION.get(travelerPosition.locale), | ||
getTravelerName(), | ||
Message.ARRIVED_NOTIFICATION.get(observerLocale), | ||
travelerName, | ||
travelerPosition.expectedLeg.to.name | ||
); | ||
break; | ||
|
@@ -66,38 +82,69 @@ public TripMonitorNotification createTripMonitorNotification(NotificationType no | |
} | ||
|
||
/** | ||
* Get the traveler's name if available, if not provide a generic traveler name. | ||
* Get a list of users that should be notified of a traveler's leg transition. | ||
*/ | ||
private String getTravelerName() { | ||
if (travelerName != null) { | ||
return travelerName; | ||
} else { | ||
return Message.TRIP_TRAVELER_GENERIC_NAME.get(observerLocale); | ||
public static Set<OtpUser> getLegTransitionNotifyUsers(MonitoredTrip trip) { | ||
Set<OtpUser> notifyUsers = new HashSet<>(); | ||
|
||
if (trip.ownedByPrimary() && trip.companion != null) { | ||
notifyUsers.add(Persistence.otpUsers.getOneFiltered(eq("email", trip.companion.email))); | ||
} else if (trip.ownedByCompanion() && trip.primary != null) { | ||
notifyUsers.add(Persistence.otpUsers.getById(trip.primary.userId)); | ||
} | ||
|
||
trip.observers.forEach(observer -> { | ||
if (observer.isConfirmed()) { | ||
br648 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
notifyUsers.add(Persistence.otpUsers.getOneFiltered(eq("email", observer.email))); | ||
} | ||
}); | ||
|
||
return notifyUsers; | ||
} | ||
|
||
/** | ||
* Create locale specific notifications. | ||
* If a traveler is on schedule and on either a walk or transit leg check for possible leg transition notification. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you meant to say "If a traveler is on the route (not deviated)"... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Insert comma before "check". |
||
*/ | ||
public static TripMonitorNotification[] createLegTransitionNotifications( | ||
List<NotificationType> legTransitionTypes, | ||
String travelerName, | ||
TravelerPosition travelerPosition, | ||
Locale observerLocale | ||
) { | ||
List<TripMonitorNotification> tripMonitorNotifications = new ArrayList<>(); | ||
// Create locale specific notifications. | ||
for (NotificationType legTransitionType : legTransitionTypes) { | ||
LegTransitionNotification legTransitionNotification = new LegTransitionNotification( | ||
travelerName, | ||
legTransitionType, | ||
travelerPosition, | ||
observerLocale | ||
); | ||
if (legTransitionNotification.tripMonitorNotification != null) { | ||
tripMonitorNotifications.add(legTransitionNotification.tripMonitorNotification); | ||
public static void checkForLegTransition(TripStatus tripStatus, TravelerPosition travelerPosition, MonitoredTrip trip) { | ||
if ( | ||
hasRequiredTripStatus(tripStatus) && | ||
(hasRequiredWalkLeg(travelerPosition) || hasRequiredTransitLeg(travelerPosition)) | ||
) { | ||
NotificationType notificationType = getLegTransitionNotificationType(travelerPosition); | ||
if (notificationType != null) { | ||
try { | ||
new CheckMonitoredTrip(trip).processLegTransition(notificationType, travelerPosition); | ||
} catch (CloneNotSupportedException e) { | ||
LOG.error("Error encountered while checking leg transition.", e); | ||
} | ||
} | ||
} | ||
return tripMonitorNotifications.toArray(new TripMonitorNotification[0]); | ||
} | ||
} | ||
|
||
/** | ||
* Depending on the traveler's proximity to the start/end of a leg return the appropriate notification type. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Insert comma before "return". |
||
*/ | ||
private static NotificationType getLegTransitionNotificationType(TravelerPosition travelerPosition) { | ||
if (isAtStartOfLeg(travelerPosition)) { | ||
return DEPARTED_NOTIFICATION; | ||
Comment on lines
+132
to
+133
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nitpick: Change the condition so that departing notifications are sent at the beginning of the trip only. I found one case where I set two coordinates, one close to the end of a leg, and the next one close to the beginning of the next leg, and I got two companion notifications, one for arriving at the end of the previous leg, and one for departing the next leg, which is redundant with the previous one and is thus unneeded noise. What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think for consistency we leave it as is. The observer would get a notification that the traveler has arrived but not one to tell them they have departed. The next notification would be the traveler arriving at the end of the next leg. Correct? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's what I observed. |
||
} else if (isApproachingEndOfLeg(travelerPosition)) { | ||
if (hasModeChanged(travelerPosition)) { | ||
return ARRIVED_AND_MODE_CHANGE_NOTIFICATION; | ||
} | ||
return ARRIVED_NOTIFICATION; | ||
} | ||
return null; | ||
} | ||
|
||
/** | ||
* The traveler is at the end of the current leg and the mode has changed between this and the next leg. | ||
*/ | ||
private static boolean hasModeChanged(TravelerPosition travelerPosition) { | ||
Leg nextLeg = travelerPosition.nextLeg; | ||
Leg expectedLeg = travelerPosition.expectedLeg; | ||
return | ||
isApproachingEndOfLeg(travelerPosition) && | ||
nextLeg != null && | ||
!nextLeg.mode.equalsIgnoreCase(expectedLeg.mode); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say just keep the old name
MODE_CHANGE_NOTIFICATION
.