Skip to content

Commit

Permalink
refactor(Notify bus op if first leg is bus leg):
Browse files Browse the repository at this point in the history
  • Loading branch information
br648 committed Oct 24, 2024
1 parent 466f6b5 commit 89d5074
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,7 @@ public static TripInstruction alignTravelerToTrip(
Locale locale = travelerPosition.locale;

if (isApproachingEndOfLeg(travelerPosition)) {
if (isBusLeg(travelerPosition.nextLeg) && isWithinOperationalNotifyWindow(travelerPosition)) {
BusOperatorActions
.getDefault()
.handleSendNotificationAction(tripStatus, travelerPosition);
if (sendBusNotification(travelerPosition, isStartOfTrip, tripStatus)) {
// Regardless of whether the notification is sent or qualifies, provide a 'wait for bus' instruction.
return new WaitForTransitInstruction(travelerPosition.nextLeg, travelerPosition.currentTime, locale);
}
Expand All @@ -157,6 +154,32 @@ public static TripInstruction alignTravelerToTrip(
return null;
}

/**
* Send bus notification if the first leg is a bus leg or approaching a bus leg and within the notify window.
*/
public static boolean sendBusNotification(
TravelerPosition travelerPosition,
boolean isStartOfTrip,
TripStatus tripStatus
) {
if (shouldNotifyBusOperator(travelerPosition, isStartOfTrip)) {
BusOperatorActions
.getDefault()
.handleSendNotificationAction(tripStatus, travelerPosition);
return true;
}
return false;
}

/**
* Given the traveler's position and leg type, check if bus notification should be sent.
*/
public static boolean shouldNotifyBusOperator(TravelerPosition travelerPosition, boolean isStartOfTrip) {
return (isStartOfTrip)
? isBusLeg(travelerPosition.expectedLeg) && isWithinOperationalNotifyWindow(travelerPosition.currentTime, travelerPosition.expectedLeg)
: isBusLeg(travelerPosition.nextLeg) && isWithinOperationalNotifyWindow(travelerPosition);
}

/**
* Align the traveler's position to the nearest transit stop or destination.
*/
Expand Down Expand Up @@ -218,15 +241,19 @@ public static boolean isAtEndOfLeg(TravelerPosition travelerPosition) {
return getDistanceToEndOfLeg(travelerPosition) <= TRIP_INSTRUCTION_IMMEDIATE_RADIUS;
}

public static boolean isWithinOperationalNotifyWindow(TravelerPosition travelerPosition) {
return isWithinOperationalNotifyWindow(travelerPosition.currentTime, travelerPosition.nextLeg);
}

/**
* Make sure the traveler is on schedule or ahead of schedule (but not too far) to be within an operational window
* for the bus service.
*/
public static boolean isWithinOperationalNotifyWindow(TravelerPosition travelerPosition) {
var busDepartureTime = getBusDepartureTime(travelerPosition.nextLeg);
public static boolean isWithinOperationalNotifyWindow(Instant currentTime, Leg busLeg) {
var busDepartureTime = getBusDepartureTime(busLeg);
return
(travelerPosition.currentTime.equals(busDepartureTime) || travelerPosition.currentTime.isBefore(busDepartureTime)) &&
ACCEPTABLE_AHEAD_OF_SCHEDULE_IN_MINUTES >= getMinutesAheadOfDeparture(travelerPosition.currentTime, busDepartureTime);
(currentTime.equals(busDepartureTime) || currentTime.isBefore(busDepartureTime)) &&
ACCEPTABLE_AHEAD_OF_SCHEDULE_IN_MINUTES >= getMinutesAheadOfDeparture(currentTime, busDepartureTime);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ public TravelerPosition(Leg expectedLeg, Coordinates currentPosition) {

/** Used for unit testing. */
public TravelerPosition(Leg nextLeg, Instant currentTime) {
this (null, nextLeg, currentTime);
}

/** Used for unit testing. */
public TravelerPosition(Leg expectedLeg, Leg nextLeg, Instant currentTime) {
this.expectedLeg = expectedLeg;
this.nextLeg = nextLeg;
this.currentTime = currentTime;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ void canNotifyBusOperatorOnlyOnce() throws InterruptedException, JsonProcessingE

@ParameterizedTest
@MethodSource("createWithinOperationalNotifyWindowTrace")
void isWithinOperationalNotifyWindow(boolean expected, TravelerPosition travelerPosition,String message) {
void isWithinOperationalNotifyWindow(boolean expected, TravelerPosition travelerPosition, String message) {
assertEquals(expected, TravelerLocator.isWithinOperationalNotifyWindow(travelerPosition), message);
}

Expand Down Expand Up @@ -188,6 +188,45 @@ private static Stream<Arguments> createWithinOperationalNotifyWindowTrace() {
);
}

@ParameterizedTest
@MethodSource("createShouldNotifyBusOperatorTrace")
void shouldNotifyBusOperator(boolean expected, TravelerPosition travelerPosition, boolean isStartOfTrip, String message) {
assertEquals(expected, TravelerLocator.shouldNotifyBusOperator(travelerPosition, isStartOfTrip), message);
}

private static Stream<Arguments> createShouldNotifyBusOperatorTrace() {
var walkLeg = walkToBusTransition.legs.get(0);
var busLeg = walkToBusTransition.legs.get(1);
var busDepartureTime = getBusDepartureTime(busLeg);

return Stream.of(
Arguments.of(
true,
new TravelerPosition(busLeg, busDepartureTime),
false,
"Traveler approaching a bus leg, should notify."
),
Arguments.of(
false,
new TravelerPosition(walkLeg, busDepartureTime),
false,
"Traveler approaching a walk leg, should not notify."
),
Arguments.of(
true,
new TravelerPosition(busLeg, null, busDepartureTime),
true,
"Traveler at the start of a trip which starts with a bus leg, should notify."
),
Arguments.of(
false,
new TravelerPosition(walkLeg, null, busDepartureTime),
true,
"Traveler at the start of a trip which starts with a walk leg, should not notify."
)
);
}

private static OtpUser createOtpUser() {
MobilityProfile mobilityProfile = new MobilityProfile();
mobilityProfile.mobilityMode = "WChairE";
Expand Down

0 comments on commit 89d5074

Please sign in to comment.