Skip to content

Commit

Permalink
πŸŽπŸš«πŸ’° Surface prediction 'uncertainty' values through v3 API (#698)
Browse files Browse the repository at this point in the history
* publish uncertainty values with predictions

* update prediction docs to account for swiftly values
  • Loading branch information
bfauble authored Dec 21, 2023
1 parent 553dbf5 commit d206680
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 2 deletions.
4 changes: 4 additions & 0 deletions apps/api_web/lib/api_web/views/prediction_view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ defmodule ApiWeb.PredictionView do

attributes([
:arrival_time,
:arrival_uncertainty,
:departure_time,
:departure_uncertainty,
:direction_id,
:schedule_relationship,
:status,
Expand Down Expand Up @@ -40,7 +42,9 @@ defmodule ApiWeb.PredictionView do
def attributes(%Model.Prediction{} = p, conn) do
attributes = %{
arrival_time: format_time(p.arrival_time),
arrival_uncertainty: p.arrival_uncertainty,
departure_time: format_time(p.departure_time),
departure_uncertainty: p.departure_uncertainty,
direction_id: p.direction_id,
schedule_relationship: schedule_relationship(p),
status: p.status,
Expand Down
4 changes: 4 additions & 0 deletions apps/api_web/test/api_web/views/prediction_view_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ defmodule ApiWeb.PredictionViewTest do
vehicle_id: "vehicle",
direction_id: 0,
arrival_time: nil,
arrival_uncertainty: nil,
departure_time: @datetime,
departure_uncertainty: 60,
schedule_relationship: :added,
status: "All Aboard",
stop_sequence: 5
Expand Down Expand Up @@ -76,7 +78,9 @@ defmodule ApiWeb.PredictionViewTest do
assert rendered["data"]["attributes"] == %{
"direction_id" => 0,
"arrival_time" => nil,
"arrival_uncertainty" => nil,
"departure_time" => "2016-06-07T00:00:00-04:00",
"departure_uncertainty" => 60,
"status" => "All Aboard",
"schedule_relationship" => "ADDED",
"stop_sequence" => 5,
Expand Down
31 changes: 31 additions & 0 deletions apps/model/lib/model/prediction.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ defmodule Model.Prediction do
:direction_id,
:route_pattern_id,
:arrival_time,
:arrival_uncertainty,
:departure_time,
:departure_uncertainty,
:stop_sequence,
:schedule_relationship,
:status,
Expand All @@ -40,13 +42,40 @@ defmodule Model.Prediction do
"""
@type schedule_relationship :: :added | :cancelled | :no_data | :skipped | :unscheduled | nil

@typedoc """
Uncertainty value for the arrival time prediction.
Bus and Commuter Rail
See [entities tripUpdate stop_time_updates arrival uncertainty](https://swiftly-inc.stoplight.io/docs/realtime-standalone/613d1d7f1eae3-gtfs-rt-trip-updates)
| Value | Description |
|------------------|-------------|
| < 300 or omitted | Valid real-time prediction |
| 300 | Real-time prediction not available. This code is primarily used when a vehicle has not yet been assigned to the trip, (i.e. because the block has not started yet). It is a schedule-based prediction, but Swiftly adjusts the schedule-based prediction time using observed historical travel times to make predictions more accurate than the schedule |
| 301 | Valid real-time prediction, though the bus appears to be stalled or significantly delayed and predictions are not as accurate |
| > 301 | Likely invalid prediction, recommend not showing anything (and not showing scheduled time), very rare situation |
Subway
See [GTFS `Realtime` `FeedMessage` `FeedEntity` `TripUpdate` `StopTimeUpdate` `arrival`](https://github.com/google/transit/blob/master/gtfs-realtime/spec/en/reference.md#message-stoptimeupdate).
| Value | Description |
|--------|-------------|
| 60 | A trip that has already started |
| 120 | A terminal/reverse trip departure for a trip that has NOT started and a train is awaiting departure at the origin |
| 360 | A terminal/reverse trip for a trip that has NOT started and a train is completing a previous trip |
"""
@type uncertainty_values :: non_neg_integer | nil

@typedoc """
* `:arrival_time` - When the vehicle is now predicted to arrive. `nil` if the first stop (`stop_id`) on the the trip
(`trip_id`). See
[GTFS `Realtime` `FeedMessage` `FeedEntity` `TripUpdate` `StopTimeUpdate` `arrival`](https://github.com/google/transit/blob/master/gtfs-realtime/spec/en/reference.md#message-stoptimeupdate).
* `:arrival_uncertainty` - Value representing the uncertainty of arrival prediction (`arrival_time`). See
[entities tripUpdate stop_time_updates arrival uncertainty](https://swiftly-inc.stoplight.io/docs/realtime-standalone/613d1d7f1eae3-gtfs-rt-trip-updates)
[GTFS `Realtime` `FeedMessage` `FeedEntity` `TripUpdate` `StopTimeUpdate` `arrival`](https://github.com/google/transit/blob/master/gtfs-realtime/spec/en/reference.md#message-stoptimeupdate).
* `:departure_time` - When the vehicle is now predicted to depart. `nil` if the last stop (`stop_id`) on the trip
(`trip_id`). See
[GTFS `Realtime` `FeedMessage` `FeedEntity` `TripUpdate` `StopTimeUpdate` `departure`](https://github.com/google/transit/blob/master/gtfs-realtime/spec/en/reference.md#message-stoptimeupdate).
* `:departure_uncertainty` - Value representing the uncertainty of departure prediction (`departure_time`). See
[entities tripUpdate stop_time_updates departure uncertainty](https://swiftly-inc.stoplight.io/docs/realtime-standalone/613d1d7f1eae3-gtfs-rt-trip-updates)
[GTFS `Realtime` `FeedMessage` `FeedEntity` `TripUpdate` `StopTimeUpdate` `departure`](https://github.com/google/transit/blob/master/gtfs-realtime/spec/en/reference.md#message-stoptimeupdate).
* `:direction_id` - Which direction along `route_id` the `trip_id` is going. See
[GTFS `trips.txt` `direction_id`](https://github.com/google/transit/blob/master/gtfs/spec/en/reference.md#tripstxt).
* `:route_id` - The route `trip_id` is on doing in `direction_id`. See
Expand All @@ -67,7 +96,9 @@ defmodule Model.Prediction do
"""
@type t :: %__MODULE__{
arrival_time: DateTime.t() | nil,
arrival_uncertainty: uncertainty_values,
departure_time: DateTime.t() | nil,
departure_uncertainty: uncertainty_values,
direction_id: Model.Direction.id(),
route_id: Model.Route.id(),
route_pattern_id: Model.RoutePattern.id(),
Expand Down
8 changes: 8 additions & 0 deletions apps/parse/lib/parse/trip_updates.ex
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ defmodule Parse.TripUpdates do
| stop_id: copy(update.stop_id),
stop_sequence: update.stop_sequence,
arrival_time: parse_stop_time_event(update.arrival),
arrival_uncertainty: parse_uncertainty(update.arrival),
departure_time: parse_stop_time_event(update.departure),
departure_uncertainty: parse_uncertainty(update.departure),
schedule_relationship:
stop_time_relationship(update.schedule_relationship, base.schedule_relationship)
}
Expand All @@ -55,6 +57,12 @@ defmodule Parse.TripUpdates do
nil
end

defp parse_uncertainty(%{uncertainty: uncertainty}) when is_integer(uncertainty) do
uncertainty
end

defp parse_uncertainty(_), do: nil

defp vehicle_id(%{id: id}), do: id
defp vehicle_id(_), do: nil

Expand Down
12 changes: 10 additions & 2 deletions apps/parse/test/parse/trip_updates_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@ defmodule Parse.TripUpdatesTest do
update = %{
"stop_id" => "place-north",
"stop_sequence" => 6,
"arrival" => %{
"time" => 1_502_290_000
},
"departure" => %{
"time" => 1_502_290_500
"time" => 1_502_290_500,
"uncertainty" => 60
}
}

Expand Down Expand Up @@ -54,7 +58,8 @@ defmodule Parse.TripUpdatesTest do
stop_id: "stop",
stop_sequence: 5,
arrival: %{
time: 1
time: 1,
uncertainty: 60
},
departure: nil,
schedule_relationship: :SCHEDULED
Expand All @@ -74,6 +79,9 @@ defmodule Parse.TripUpdatesTest do
vehicle_id: "vehicle",
stop_sequence: 5,
arrival_time: %DateTime{},
arrival_uncertainty: 60,
departure_time: nil,
departure_uncertainty: nil,
revenue: :REVENUE
} = actual
end
Expand Down

0 comments on commit d206680

Please sign in to comment.