feat(TripDetails): Remove predictions for already-visited stops#2932
feat(TripDetails): Remove predictions for already-visited stops#2932thecristen wants to merge 2 commits intomainfrom
Conversation
aaf10b8 to
4f353ee
Compare
joshlarson
left a comment
There was a problem hiding this comment.
Left a few style comments, and one about missing test coverage, but I wouldn't consider any of them blocking.
| current = current_stop_index(trip_stops, vehicle_info) | ||
|
|
||
| if is_nil(current) do | ||
| # finishing another trip -- show all the stops |
There was a problem hiding this comment.
Question: Will this ever happen? I think it can in test, because the factory typically creates a vehicle that doesn't align with any of the predictions, but when UpcomingDepartures.upcoming_departures/1 is contemplating vehicles, it already doesn't pass in the vehicle if it's associated with a different trip.
TripDetails.trip_details(%{
predicted_schedules: predicted_schedules_by_trip_id |> Map.get(trip_id, []),
trip_vehicle: if(vehicle && vehicle.trip_id == trip_id, do: vehicle)
})I don't actually feel strongly about "fixing" this, especially if doing so would be obnoxious wrt the tests... I'm mostly just curious.
| if vehicle_info.status == :stopped do | ||
| Enum.drop(upcoming_stops, 1) | ||
| else | ||
| upcoming_stops |
There was a problem hiding this comment.
Issue: I think there's missing test coverage here - replacing this whole if statement with Enum.drop(upcoming_stops, 1) doesn't cause any tests to fail.
test "does not drop the 'current' stop if the vehicle is :in_transit or :incoming" do
trip = Factories.Schedules.Trip.build(:trip)
stops = Faker.Util.sample_uniq(20, fn -> Factories.Stops.Stop.build(:stop) end)
predicted_schedules =
stops
|> Enum.with_index()
|> Enum.map(fn {stop, index} ->
%PredictedSchedule{
prediction:
Factories.Predictions.Prediction.build(:prediction,
trip: trip,
stop: stop,
stop_sequence: index
),
schedule:
Factories.Schedules.Schedule.build(:schedule,
trip: trip,
stop: stop,
stop_sequence: index
)
}
end)
current_index = Faker.random_between(5, 15)
{_earlier_stops, [current_stop | future_stops]} = stops |> Enum.split(current_index)
vehicle =
Factories.Vehicles.Vehicle.build(:vehicle,
status: Faker.Util.pick([:incoming, :in_transit]),
stop_id: current_stop.id,
stop_sequence: current_index,
trip_id: trip.id
)
trip_details =
TripDetails.trip_details(%{
predicted_schedules: predicted_schedules,
trip_vehicle: vehicle
})
assert trip_details.stops |> Enum.map(& &1.stop_id) == [
current_stop.id | Enum.map(future_stops, & &1.id)
]
assert trip_details.stops |> Enum.map(& &1.stop_name) == [
current_stop.name | Enum.map(future_stops, & &1.name)
]
end☝️ would do the trick, I think
| vehicle_info = | ||
| vehicle | ||
| |> vehicle_info() | ||
| def trip_details(%{predicted_schedules: predicted_schedules, trip_vehicle: vehicle}) do |
There was a problem hiding this comment.
Style Nit / Question: Why trip_vehicle rather than just vehicle?
| # finishing another trip -- show all the stops | ||
| trip_stops | ||
| else | ||
| upcoming_stops = Enum.take(trip_stops, current - length(trip_stops)) |
There was a problem hiding this comment.
Suggestion / Style Nit: Admittedly, this is largely aesthetics on my part, because I'm not the biggest fan of index arithmetic, but could this be accomplished using Enum.split_while/2? Something like 👇 ?
if Enum.any?(trip_stops, &vehicle_at_stop?(&1, vehicle_info)) do
{_past_stops, upcoming_stops} =
trip_stops
|> Enum.split_while(&(!vehicle_at_stop?(&1, vehicle_info)))
# Omit current trip_stop if the vehicle is stopped
if vehicle_info.status == :stopped do
Enum.drop(upcoming_stops, 1)
else
upcoming_stops
end
else
# finishing another trip -- show all the stops
trip_stops
end

Scope
Asana Ticket: [SF/UD] Trip Details: Hide predictions for stops that the vehicle has already visited
Implementation
A refactor I did to make this easier -- The vehicle used in
UpcomingDeparturesis already matched to the predicted schedule's stop and stop sequence -- if it also is on the predicted schedule's trip (as opposed to a prior trip or some such), we can pass it intoTripDetailsdirectly and do the rest.The actual task -- in the last commit, I adjust the logic to remove any prior trip stops based on the vehicle location (basically option B in the Asana ticket).
Screenshots
How to test
Since this was an intermittently-seen problem I'm not sure how to reliably reproduce, but I remember seeing it on the 9 bus semi-often...