Skip to content
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

streamline prediction destination code #827

Merged
merged 1 commit into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 32 additions & 54 deletions lib/content/message/predictions.ex
Original file line number Diff line number Diff line change
Expand Up @@ -88,34 +88,23 @@ defmodule Content.Message.Predictions do
do: {nil, nil},
else: do_crowding(prediction, sign)

case Content.Utilities.destination_for_prediction(
prediction.route_id,
prediction.direction_id,
prediction.destination_stop_id
) do
{:ok, destination} ->
%__MODULE__{
destination: destination,
minutes: minutes,
approximate?: approximate?,
route_id: prediction.route_id,
stop_id: prediction.stop_id,
trip_id: prediction.trip_id,
direction_id: prediction.direction_id,
width: width,
new_cars?: sign.location_engine.for_vehicle(prediction.vehicle_id) |> new_cars?(),
station_code: station_code,
zone: zone,
platform: platform,
certainty: certainty,
crowding_data_confidence: crowding_data_confidence,
crowding_description: crowding_description
}

{:error, _} ->
Logger.warn("no_destination_for_prediction #{inspect(prediction)}")
nil
end
%__MODULE__{
destination: Content.Utilities.destination_for_prediction(prediction),
minutes: minutes,
approximate?: approximate?,
route_id: prediction.route_id,
stop_id: prediction.stop_id,
trip_id: prediction.trip_id,
direction_id: prediction.direction_id,
width: width,
new_cars?: sign.location_engine.for_vehicle(prediction.vehicle_id) |> new_cars?(),
station_code: station_code,
zone: zone,
platform: platform,
certainty: certainty,
crowding_data_confidence: crowding_data_confidence,
crowding_description: crowding_description
}
end

@spec terminal(
Expand All @@ -137,32 +126,21 @@ defmodule Content.Message.Predictions do
x -> compute_minutes(x, prediction.departure_certainty)
end

case Content.Utilities.destination_for_prediction(
prediction.route_id,
prediction.direction_id,
prediction.destination_stop_id
) do
{:ok, destination} ->
%__MODULE__{
destination: destination,
minutes: minutes,
approximate?: approximate?,
route_id: prediction.route_id,
stop_id: prediction.stop_id,
trip_id: prediction.trip_id,
direction_id: prediction.direction_id,
width: width,
new_cars?: sign.location_engine.for_vehicle(prediction.vehicle_id) |> new_cars?(),
station_code: station_code,
zone: zone,
terminal?: true,
certainty: prediction.departure_certainty
}

{:error, _} ->
Logger.warn("no_destination_for_prediction #{inspect(prediction)}")
nil
end
%__MODULE__{
destination: Content.Utilities.destination_for_prediction(prediction),
minutes: minutes,
approximate?: approximate?,
route_id: prediction.route_id,
stop_id: prediction.stop_id,
trip_id: prediction.trip_id,
direction_id: prediction.direction_id,
width: width,
new_cars?: sign.location_engine.for_vehicle(prediction.vehicle_id) |> new_cars?(),
station_code: station_code,
zone: zone,
terminal?: true,
certainty: prediction.departure_certainty
}
end

defp compute_minutes(sec, certainty) do
Expand Down
33 changes: 11 additions & 22 deletions lib/content/message/stopped_train.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,28 +27,17 @@ defmodule Content.Message.StoppedTrain do

@spec from_prediction(Predictions.Prediction.t()) :: t() | nil
def from_prediction(%{boarding_status: status} = prediction) when not is_nil(status) do
case Content.Utilities.destination_for_prediction(
prediction.route_id,
prediction.direction_id,
prediction.destination_stop_id
) do
{:ok, destination} ->
stops_away = parse_stops_away(prediction.boarding_status)

%__MODULE__{
destination: destination,
stops_away: stops_away,
certainty: prediction.arrival_certainty || prediction.departure_certainty,
stop_id: prediction.stop_id,
trip_id: prediction.trip_id,
route_id: prediction.route_id,
direction_id: prediction.direction_id
}

{:error, _} ->
Logger.warn("no_destination_for_prediction #{inspect(prediction)}")
nil
end
stops_away = parse_stops_away(prediction.boarding_status)

%__MODULE__{
destination: Content.Utilities.destination_for_prediction(prediction),
stops_away: stops_away,
certainty: prediction.arrival_certainty || prediction.departure_certainty,
stop_id: prediction.stop_id,
trip_id: prediction.trip_id,
route_id: prediction.route_id,
direction_id: prediction.direction_id
}
end

defp parse_stops_away(str) do
Expand Down
129 changes: 76 additions & 53 deletions lib/content/utilities.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,21 @@ defmodule Content.Utilities do
|> Enum.max()
end

@spec destination_for_prediction(String.t(), 0 | 1, String.t()) ::
{:ok, PaEss.destination()} | {:error, :not_found}
def destination_for_prediction("Mattapan", 0, _), do: {:ok, :mattapan}
def destination_for_prediction("Mattapan", 1, _), do: {:ok, :ashmont}
def destination_for_prediction("Orange", 0, _), do: {:ok, :forest_hills}
def destination_for_prediction("Orange", 1, _), do: {:ok, :oak_grove}
def destination_for_prediction("Blue", 0, _), do: {:ok, :bowdoin}
def destination_for_prediction("Blue", 1, _), do: {:ok, :wonderland}
def destination_for_prediction("Red", 1, _), do: {:ok, :alewife}

def destination_for_prediction("Red", 0, last_stop_id)
when last_stop_id in ["70085", "70086", "70087", "70089", "70091", "70093"],
do: {:ok, :ashmont}

def destination_for_prediction("Red", 0, last_stop_id)
when last_stop_id in [
@spec destination_for_prediction(Predictions.Prediction.t()) :: PaEss.destination()
def destination_for_prediction(%{route_id: "Mattapan", direction_id: 0}), do: :mattapan
def destination_for_prediction(%{route_id: "Mattapan", direction_id: 1}), do: :ashmont
def destination_for_prediction(%{route_id: "Orange", direction_id: 0}), do: :forest_hills
def destination_for_prediction(%{route_id: "Orange", direction_id: 1}), do: :oak_grove
def destination_for_prediction(%{route_id: "Blue", direction_id: 0}), do: :bowdoin
def destination_for_prediction(%{route_id: "Blue", direction_id: 1}), do: :wonderland
def destination_for_prediction(%{route_id: "Red", direction_id: 1}), do: :alewife

def destination_for_prediction(%{route_id: "Red", direction_id: 0, destination_stop_id: stop_id})
when stop_id in ["70085", "70086", "70087", "70089", "70091", "70093"],
do: :ashmont

def destination_for_prediction(%{route_id: "Red", direction_id: 0, destination_stop_id: stop_id})
when stop_id in [
"70095",
"70096",
"70097",
Expand All @@ -45,43 +44,67 @@ defmodule Content.Utilities do
"Braintree-01",
"Braintree-02"
],
do: {:ok, :braintree}

def destination_for_prediction("Red", 0, _), do: {:ok, :southbound}

def destination_for_prediction(_, 0, "70151"), do: {:ok, :kenmore}
def destination_for_prediction(_, 0, "71151"), do: {:ok, :kenmore}
def destination_for_prediction(_, 0, "70202"), do: {:ok, :government_center}
def destination_for_prediction(_, 0, "70201"), do: {:ok, :government_center}
def destination_for_prediction(_, 0, "70175"), do: {:ok, :reservoir}
def destination_for_prediction(_, 0, "70107"), do: {:ok, :boston_college}
def destination_for_prediction(_, 0, "70237"), do: {:ok, :cleveland_circle}
def destination_for_prediction(_, 0, "70161"), do: {:ok, :riverside}
def destination_for_prediction(_, 0, "70260"), do: {:ok, :heath_street}

def destination_for_prediction(_, 1, "70205"), do: {:ok, :north_station}
def destination_for_prediction(_, 1, "70511"), do: {:ok, :medford_tufts}
def destination_for_prediction(_, 1, "70503"), do: {:ok, :union_square}
def destination_for_prediction(_, 1, "70501"), do: {:ok, :lechmere}
def destination_for_prediction(_, 1, "70201"), do: {:ok, :government_center}
def destination_for_prediction(_, 1, "70200"), do: {:ok, :park_street}
def destination_for_prediction(_, 1, "71199"), do: {:ok, :park_street}
def destination_for_prediction(_, 1, "70150"), do: {:ok, :kenmore}
def destination_for_prediction(_, 1, "71150"), do: {:ok, :kenmore}
def destination_for_prediction(_, 1, "70174"), do: {:ok, :reservoir}

def destination_for_prediction(_, _, "Government Center-Brattle"), do: {:ok, :government_center}

def destination_for_prediction("Green-B", 0, _), do: {:ok, :boston_college}
def destination_for_prediction("Green-C", 0, _), do: {:ok, :cleveland_circle}
def destination_for_prediction("Green-D", 0, _), do: {:ok, :riverside}
def destination_for_prediction("Green-E", 0, _), do: {:ok, :heath_street}
def destination_for_prediction("Green-B", 1, _), do: {:ok, :government_center}
def destination_for_prediction("Green-C", 1, _), do: {:ok, :government_center}
def destination_for_prediction("Green-D", 1, _), do: {:ok, :union_square}
def destination_for_prediction("Green-E", 1, _), do: {:ok, :medford_tufts}

def destination_for_prediction(_, _, _), do: {:error, :not_found}
do: :braintree

def destination_for_prediction(%{route_id: "Red", direction_id: 0}), do: :southbound

def destination_for_prediction(%{direction_id: 0, destination_stop_id: "70151"}), do: :kenmore
def destination_for_prediction(%{direction_id: 0, destination_stop_id: "71151"}), do: :kenmore

def destination_for_prediction(%{direction_id: 0, destination_stop_id: "70202"}),
do: :government_center

def destination_for_prediction(%{direction_id: 0, destination_stop_id: "70201"}),
do: :government_center

def destination_for_prediction(%{direction_id: 0, destination_stop_id: "70175"}), do: :reservoir

def destination_for_prediction(%{direction_id: 0, destination_stop_id: "70107"}),
do: :boston_college

def destination_for_prediction(%{direction_id: 0, destination_stop_id: "70237"}),
do: :cleveland_circle

def destination_for_prediction(%{direction_id: 0, destination_stop_id: "70161"}), do: :riverside

def destination_for_prediction(%{direction_id: 0, destination_stop_id: "70260"}),
do: :heath_street

def destination_for_prediction(%{direction_id: 1, destination_stop_id: "70205"}),
do: :north_station

def destination_for_prediction(%{direction_id: 1, destination_stop_id: "70511"}),
do: :medford_tufts

def destination_for_prediction(%{direction_id: 1, destination_stop_id: "70503"}),
do: :union_square

def destination_for_prediction(%{direction_id: 1, destination_stop_id: "70501"}), do: :lechmere

def destination_for_prediction(%{direction_id: 1, destination_stop_id: "70201"}),
do: :government_center

def destination_for_prediction(%{direction_id: 1, destination_stop_id: "70200"}),
do: :park_street

def destination_for_prediction(%{direction_id: 1, destination_stop_id: "71199"}),
do: :park_street

def destination_for_prediction(%{direction_id: 1, destination_stop_id: "70150"}), do: :kenmore
def destination_for_prediction(%{direction_id: 1, destination_stop_id: "71150"}), do: :kenmore
def destination_for_prediction(%{direction_id: 1, destination_stop_id: "70174"}), do: :reservoir

def destination_for_prediction(%{destination_stop_id: "Government Center-Brattle"}),
do: :government_center

def destination_for_prediction(%{route_id: "Green-B", direction_id: 0}), do: :boston_college
def destination_for_prediction(%{route_id: "Green-C", direction_id: 0}), do: :cleveland_circle
def destination_for_prediction(%{route_id: "Green-D", direction_id: 0}), do: :riverside
def destination_for_prediction(%{route_id: "Green-E", direction_id: 0}), do: :heath_street
def destination_for_prediction(%{route_id: "Green-B", direction_id: 1}), do: :government_center
def destination_for_prediction(%{route_id: "Green-C", direction_id: 1}), do: :government_center
def destination_for_prediction(%{route_id: "Green-D", direction_id: 1}), do: :union_square
def destination_for_prediction(%{route_id: "Green-E", direction_id: 1}), do: :medford_tufts

@spec stop_track_number(String.t()) :: track_number() | nil
def stop_track_number("Alewife-01"), do: 1
Expand Down
40 changes: 12 additions & 28 deletions lib/signs/utilities/predictions.ex
Original file line number Diff line number Diff line change
Expand Up @@ -134,35 +134,19 @@ defmodule Signs.Utilities.Predictions do
end)
|> Enum.sort_by(fn prediction -> prediction.seconds_until_passthrough end)
|> Enum.flat_map(fn prediction ->
route_id = prediction.route_id

case Content.Utilities.destination_for_prediction(
route_id,
prediction.direction_id,
prediction.destination_stop_id
) do
{:ok, :southbound} when route_id == "Red" ->
[
%Content.Audio.Passthrough{
destination: :ashmont,
trip_id: prediction.trip_id,
route_id: prediction.route_id
}
]

{:ok, destination} ->
[
%Content.Audio.Passthrough{
destination: destination,
trip_id: prediction.trip_id,
route_id: prediction.route_id
}
]
destination =
case Content.Utilities.destination_for_prediction(prediction) do
:southbound -> :ashmont
destination -> destination
end

_ ->
Logger.info("no_passthrough_audio_for_prediction prediction=#{inspect(prediction)}")
[]
end
[
%Content.Audio.Passthrough{
destination: destination,
trip_id: prediction.trip_id,
route_id: prediction.route_id
}
]
end)
|> Enum.take(1)
end
Expand Down
55 changes: 0 additions & 55 deletions test/content/messages/predictions_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,6 @@ defmodule Content.Message.PredictionsTest do
:ok
end

test "logs a warning when we cant find a headsign" do
prediction = %Predictions.Prediction{
seconds_until_arrival: 0,
direction_id: 1,
route_id: "NON-ROUTE",
stopped?: false,
stops_away: 1,
destination_stop_id: "70261"
}

log =
capture_log([level: :warn], fn ->
assert is_nil(Content.Message.Predictions.non_terminal(prediction, "test", "m", @sign))
end)

assert log =~ "no_destination_for_prediction"
end

test "puts ARR on the sign when train is 0 seconds away, but not boarding" do
prediction = %Predictions.Prediction{
seconds_until_arrival: 0,
Expand Down Expand Up @@ -288,43 +270,6 @@ defmodule Content.Message.PredictionsTest do
:ok
end

test "logs a warning when we cant find a headsign, even if it should be boarding" do
prediction = %Predictions.Prediction{
seconds_until_departure: 0,
direction_id: 1,
route_id: "NON-ROUTE",
destination_stop_id: "70261",
stopped?: false,
stops_away: 0,
boarding_status: "Boarding"
}

log =
capture_log([level: :warn], fn ->
assert is_nil(Content.Message.Predictions.terminal(prediction, "test", "m", @sign))
end)

assert log =~ "no_destination_for_prediction"
end

test "logs a warning when we cant find a headsign" do
prediction = %Predictions.Prediction{
seconds_until_departure: 0,
direction_id: 1,
route_id: "NON-ROUTE",
stopped?: false,
stops_away: 1,
destination_stop_id: "70261"
}

log =
capture_log([level: :warn], fn ->
assert is_nil(Content.Message.Predictions.terminal(prediction, "test", "m", @sign))
end)

assert log =~ "no_destination_for_prediction"
end

test "puts boarding on the sign when train is supposed to be boarding according to rtr" do
prediction = %Predictions.Prediction{
seconds_until_departure: 75,
Expand Down
Loading
Loading