-
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 15 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 |
---|---|---|
@@ -0,0 +1,150 @@ | ||
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.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; | ||
public TravelerPosition travelerPosition; | ||
public Locale observerLocale; | ||
public TripMonitorNotification tripMonitorNotification; | ||
|
||
public LegTransitionNotification( | ||
String travelerName, | ||
NotificationType notificationType, | ||
TravelerPosition travelerPosition, | ||
Locale observerLocale | ||
) { | ||
this.travelerName = travelerName; | ||
this.notificationType = notificationType; | ||
this.travelerPosition = travelerPosition; | ||
this.observerLocale = observerLocale; | ||
this.tripMonitorNotification = createTripMonitorNotification(notificationType); | ||
} | ||
|
||
/** | ||
* Create {@link TripMonitorNotification} for leg transition based on notification type. | ||
*/ | ||
@Nullable | ||
private TripMonitorNotification createTripMonitorNotification(NotificationType notificationType) { | ||
String body; | ||
switch (notificationType) { | ||
case ARRIVED_AND_MODE_CHANGE_NOTIFICATION: | ||
body = String.format( | ||
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), | ||
travelerName, | ||
travelerPosition.expectedLeg.from.name | ||
); | ||
break; | ||
case ARRIVED_NOTIFICATION: | ||
body = String.format( | ||
Message.ARRIVED_NOTIFICATION.get(observerLocale), | ||
travelerName, | ||
travelerPosition.expectedLeg.to.name | ||
); | ||
break; | ||
default: | ||
body = null; | ||
} | ||
return (body != null) ? new TripMonitorNotification(notificationType, body) : null; | ||
} | ||
|
||
/** | ||
* Get a list of users that should be notified of a traveler's leg transition. | ||
*/ | ||
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; | ||
} | ||
|
||
/** | ||
* 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 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); | ||
} | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* 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
.