Skip to content

Commit

Permalink
Merge branch 'main' into pk/migrate-from-rtr-to-gtfs-rt
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulJKim committed Nov 25, 2024
2 parents 79d976d + f9909ac commit 1974248
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 75 deletions.
3 changes: 2 additions & 1 deletion lib/content/audio.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ defprotocol Content.Audio do

@type language :: :english | :spanish
@type value :: canned_message() | ad_hoc_message() | nil
@type tts_value :: {audio :: String.t(), visual :: Content.Message.pages() | nil}
@type tts_value ::
{audio :: String.t() | {:spanish, String.t()}, visual :: Content.Message.pages() | nil}

@doc "Converts an audio struct to the mid/vars params for the PA system"
@spec to_params(Content.Audio.t()) :: value()
Expand Down
24 changes: 12 additions & 12 deletions lib/content/audio/no_service.ex
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,20 @@ defmodule Content.Audio.NoService do
use_shuttle?: use_shuttle?,
use_routes?: use_routes?
}) do
shuttle = if(use_shuttle?, do: " Use shuttle.", else: "")

cond do
use_routes? ->
suffix =
cond do
use_shuttle? -> " Use shuttle."
# Hardcoded for Union Square
"No Train Service. Use routes 86, 87, or 91"

destination ->
{:ok, destination_text} = PaEss.Utilities.destination_to_ad_hoc_string(destination)
"No #{destination_text} service.#{shuttle}"
use_routes? -> " Use routes 86, 87, or 91"
true -> ""
end

true ->
line = if(route, do: "#{route} Line", else: "train")
"There is no #{line} service at this station.#{shuttle}"
if destination do
{:ok, destination_text} = PaEss.Utilities.destination_to_ad_hoc_string(destination)
"No #{destination_text} service.#{suffix}"
else
line = if(route, do: "#{route} Line", else: "train")
"There is no #{line} service at this station.#{suffix}"
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/content/message/predictions.ex
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ defmodule Content.Message.Predictions do
def new(%Predictions.Prediction{} = prediction, terminal?, special_sign) do
sec =
if terminal? do
prediction.seconds_until_departure - 60
prediction.seconds_until_departure
else
prediction.seconds_until_arrival || prediction.seconds_until_departure
end
Expand Down
17 changes: 15 additions & 2 deletions lib/pa_ess/updater.ex
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,12 @@ defmodule PaEss.Updater do
|> Enum.map(fn {{text, pages}, tag, log_meta} ->
[
sign_id: id,
audio: inspect(text),
audio:
case text do
{:spanish, text} -> text
text -> text
end
|> inspect(),
visual: format_pages(pages) |> Jason.encode!(),
tag: inspect(tag),
legacy: !scu_migrated?
Expand Down Expand Up @@ -150,7 +155,15 @@ defmodule PaEss.Updater do
watts_url = Application.get_env(:realtime_signs, :watts_url)
watts_api_key = Application.get_env(:realtime_signs, :watts_api_key)

http_poster.post("#{watts_url}/tts", %{text: text, voice_id: "Matthew"} |> Jason.encode!(), [
{voice_id, text} =
case text do
{:spanish, text} -> {"Mia", ~s(<prosody rate="90%">#{text}</prosody>)}
text -> {"Matthew", text}
end

text = ~s(<speak><amazon:effect name="drc">#{text}</amazon:effect></speak>)

http_poster.post("#{watts_url}/tts", %{text: text, voice_id: voice_id} |> Jason.encode!(), [
{"Content-type", "application/json"},
{"x-api-key", watts_api_key}
])
Expand Down
8 changes: 4 additions & 4 deletions lib/signs/bus.ex
Original file line number Diff line number Diff line change
Expand Up @@ -690,22 +690,22 @@ defmodule Signs.Bus do
{duration, duration_spanish} =
case bridge_status_minutes(bridge_status, current_time) do
minutes when minutes < 2 ->
{"We expect it to be lowered soon.", "Esperamos que se baje pronto."}
{"We expect it to be lowered soon.", "Esperamos que cierre pronto."}

minutes ->
{"We expect this to last for at least #{minutes} more minutes.",
"Esperamos que esto dure al menos #{minutes} minutos más."}
"Permanecerá abierto aproximadamente #{minutes} minutos."}
end

english_text =
"The Chelsea Street bridge is raised. #{duration} SL3 buses may be delayed, detoured, or turned back."

spanish_text =
"El puente de Chelsea Street está levantado. #{duration_spanish} Los autobuses SL3 pueden sufrir retrasos, desvíos o dar marcha atrás."
"El puente levadizo de Chelsea está abierto. #{duration_spanish} Autobuses S.L. tres pueden experimentar retrasos, ser desviados o devueltos."

[
{english_text, PaEss.Utilities.paginate_text(english_text)},
{spanish_text, PaEss.Utilities.paginate_text(spanish_text)}
{{:spanish, spanish_text}, PaEss.Utilities.paginate_text(spanish_text)}
]
else
[]
Expand Down
16 changes: 10 additions & 6 deletions lib/signs/utilities/messages.ex
Original file line number Diff line number Diff line change
Expand Up @@ -239,33 +239,37 @@ defmodule Signs.Utilities.Messages do
end
end

defp alert_messages(alert_status, %{pa_ess_loc: "GUNS"}, _) do
defp alert_messages(alert_status, %{pa_ess_loc: "GUNS"}, config) do
route = Signs.Utilities.SourceConfig.single_route(config)
destination = config.headway_destination

if alert_status in [:none, :alert_along_route],
do: nil,
else: {%Alert.NoService{}, %Alert.UseRoutes{}}
else: {%Alert.NoService{route: route, destination: destination}, %Alert.UseRoutes{}}
end

defp alert_messages(alert_status, sign, config) do
route = Signs.Utilities.SourceConfig.single_route(config)
destination = config.headway_destination

case {alert_status, sign.uses_shuttles} do
{:shuttles_transfer_station, _} ->
{%Content.Message.Empty{}, %Content.Message.Empty{}}

{:shuttles_closed_station, true} ->
{%Alert.NoService{route: route}, %Alert.UseShuttleBus{}}
{%Alert.NoService{route: route, destination: destination}, %Alert.UseShuttleBus{}}

{:shuttles_closed_station, false} ->
{%Alert.NoService{route: route}, %Content.Message.Empty{}}
{%Alert.NoService{route: route, destination: destination}, %Content.Message.Empty{}}

{:suspension_transfer_station, _} ->
{%Content.Message.Empty{}, %Content.Message.Empty{}}

{:suspension_closed_station, _} ->
{%Alert.NoService{route: route}, %Content.Message.Empty{}}
{%Alert.NoService{route: route, destination: destination}, %Content.Message.Empty{}}

{:station_closure, _} ->
{%Alert.NoService{route: route}, %Content.Message.Empty{}}
{%Alert.NoService{route: route, destination: destination}, %Content.Message.Empty{}}

_ ->
nil
Expand Down
21 changes: 3 additions & 18 deletions test/content/messages/predictions_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ defmodule Content.Message.PredictionsTest do
describe "terminal new/3" do
test "puts boarding on the sign when train is supposed to be boarding according to rtr" do
prediction = %Predictions.Prediction{
seconds_until_departure: 75,
seconds_until_departure: 15,
direction_id: 1,
route_id: "Mattapan",
destination_stop_id: "70261",
Expand All @@ -217,7 +217,7 @@ defmodule Content.Message.PredictionsTest do

test "does not put boarding on the sign too early when train is stopped at terminal" do
prediction = %Predictions.Prediction{
seconds_until_departure: 95,
seconds_until_departure: 35,
direction_id: 1,
route_id: "Mattapan",
destination_stop_id: "70261",
Expand All @@ -230,21 +230,6 @@ defmodule Content.Message.PredictionsTest do
assert Content.Message.to_string(msg) == "Ashmont 1 min"
end

test "offsets the prediction by 60 seconds" do
prediction = %Predictions.Prediction{
seconds_until_departure: 209,
direction_id: 1,
route_id: "Mattapan",
destination_stop_id: "70261",
stopped_at_predicted_stop?: true,
boarding_status: "Stopped at station"
}

msg = Content.Message.Predictions.new(prediction, true, nil)

assert Content.Message.to_string(msg) == "Ashmont 2 min"
end

test "puts 1 min on the sign when train is not boarding, but is predicted to depart in less than a minute when offset" do
prediction = %Predictions.Prediction{
seconds_until_departure: 70,
Expand All @@ -261,7 +246,7 @@ defmodule Content.Message.PredictionsTest do
test "pages track information when available" do
prediction = %Predictions.Prediction{
stop_id: "Forest Hills-02",
seconds_until_departure: 180,
seconds_until_departure: 120,
direction_id: 1,
route_id: "Orange",
stopped_at_predicted_stop?: true
Expand Down
34 changes: 20 additions & 14 deletions test/signs/bus_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -313,13 +313,16 @@ defmodule Signs.BusTest do
{"SL3 buses may be", "delayed, detoured, or", 3},
{"turned back.", "", 3}
]},
{"El puente de Chelsea Street está levantado. Esperamos que esto dure al menos 4 minutos más. Los autobuses SL3 pueden sufrir retrasos, desvíos o dar marcha atrás.",
[
{"El puente de Chelsea", "Street está levantado.", 3},
{"Esperamos que esto dure", "al menos 4 minutos más.", 3},
{"Los autobuses SL3 pueden", "sufrir retrasos, desvíos", 3},
{"o dar marcha atrás.", "", 3}
]}
{
{:spanish,
"El puente levadizo de Chelsea está abierto. Permanecerá abierto aproximadamente 4 minutos. Autobuses S.L. tres pueden experimentar retrasos, ser desviados o devueltos."},
[
{"El puente levadizo de", "Chelsea está abierto.", 3},
{"Permanecerá abierto", "aproximadamente 4", 3},
{"minutos. Autobuses S.L.", "tres pueden experimentar", 3},
{"retrasos, ser desviados", "o devueltos.", 3}
]
}
]
)

Expand Down Expand Up @@ -347,13 +350,16 @@ defmodule Signs.BusTest do
{"SL3 buses may be", "delayed, detoured, or", 3},
{"turned back.", "", 3}
]},
{"El puente de Chelsea Street está levantado. Esperamos que esto dure al menos 4 minutos más. Los autobuses SL3 pueden sufrir retrasos, desvíos o dar marcha atrás.",
[
{"El puente de Chelsea", "Street está levantado.", 3},
{"Esperamos que esto dure", "al menos 4 minutos más.", 3},
{"Los autobuses SL3 pueden", "sufrir retrasos, desvíos", 3},
{"o dar marcha atrás.", "", 3}
]}
{
{:spanish,
"El puente levadizo de Chelsea está abierto. Permanecerá abierto aproximadamente 4 minutos. Autobuses S.L. tres pueden experimentar retrasos, ser desviados o devueltos."},
[
{"El puente levadizo de", "Chelsea está abierto.", 3},
{"Permanecerá abierto", "aproximadamente 4", 3},
{"minutos. Autobuses S.L.", "tres pueden experimentar", 3},
{"retrasos, ser desviados", "o devueltos.", 3}
]
}
]
)

Expand Down
58 changes: 41 additions & 17 deletions test/signs/realtime_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -275,34 +275,54 @@ defmodule Signs.RealtimeTest do

test "when sign is at a station closed by shuttles and there are no predictions, it says so" do
expect(Engine.Alerts.Mock, :max_stop_status, fn _, _ -> :shuttles_closed_station end)
expect_messages({"No Red Line", "Use shuttle bus"})
expect_messages({"No Southbound svc", "Use shuttle bus"})

expect_audios([{:canned, {"199", ["3005"], :audio}}], [
{"There is no Red Line service at this station. Use shuttle.", nil}
expect_audios([{:ad_hoc, {"No Southbound service. Use shuttle.", :audio}}], [
{"No Southbound service. Use shuttle.", nil}
])

Signs.Realtime.handle_info(:run_loop, @sign)
end

test "when sign is at a station closed and there are no predictions, but shuttles do not run at this station" do
expect(Engine.Alerts.Mock, :max_stop_status, fn _, _ -> :shuttles_closed_station end)
expect_messages({"No Red Line", ""})
expect_audios([@no_service_audio], [{"There is no Red Line service at this station.", nil}])
expect_messages({"No Southbound svc", ""})

expect_audios([{:ad_hoc, {"No Southbound service.", :audio}}], [
{"No Southbound service.", nil}
])

Signs.Realtime.handle_info(:run_loop, %{@sign | uses_shuttles: false})
end

test "when sign is at a station closed due to suspension and there are no predictions, it says so" do
expect(Engine.Alerts.Mock, :max_stop_status, fn _, _ -> :suspension_closed_station end)
expect_messages({"No Red Line", ""})
expect_audios([@no_service_audio], [{"There is no Red Line service at this station.", nil}])
expect_messages({"No Southbound svc", ""})

expect_audios([{:ad_hoc, {"No Southbound service.", :audio}}], [
{"No Southbound service.", nil}
])

Signs.Realtime.handle_info(:run_loop, @sign)
end

test "when sign is at a closed station and there are no predictions, it says so" do
expect(Engine.Alerts.Mock, :max_stop_status, fn _, _ -> :station_closure end)
expect_messages({"No Southbound svc", ""})

expect_audios([{:ad_hoc, {"No Southbound service.", :audio}}], [
{"No Southbound service.", nil}
])

assert {_, %{announced_alert: true}} = Signs.Realtime.handle_info(:run_loop, @sign)
end

test "mezzanine sign with alert" do
expect(Engine.Alerts.Mock, :max_stop_status, fn _, _ -> :station_closure end)
expect(Engine.Alerts.Mock, :max_stop_status, fn _, _ -> :station_closure end)
expect_messages({"No Red Line", ""})
expect_audios([@no_service_audio], [{"There is no Red Line service at this station.", nil}])
assert {_, %{announced_alert: true}} = Signs.Realtime.handle_info(:run_loop, @sign)
Signs.Realtime.handle_info(:run_loop, @mezzanine_sign)
end

test "multi-route mezzanine sign with alert" do
Expand Down Expand Up @@ -384,8 +404,12 @@ defmodule Signs.RealtimeTest do
end)

expect(Engine.Alerts.Mock, :max_stop_status, fn _, _ -> :station_closure end)
expect_messages({"No Red Line", ""})
expect_audios([@no_service_audio], [{"There is no Red Line service at this station.", nil}])
expect_messages({"No Southbound svc", ""})

expect_audios([{:ad_hoc, {"No Southbound service.", :audio}}], [
{"No Southbound service.", nil}
])

Signs.Realtime.handle_info(:run_loop, @sign)
end

Expand Down Expand Up @@ -566,7 +590,7 @@ defmodule Signs.RealtimeTest do
]
end)

expect_messages({"Boston Col 3 min", "Clvlnd Cir 4 min"})
expect_messages({"Boston Col 4 min", "Clvlnd Cir 5 min"})
Signs.Realtime.handle_info(:run_loop, @terminal_sign)
end

Expand Down Expand Up @@ -925,10 +949,10 @@ defmodule Signs.RealtimeTest do

test "reads alerts" do
expect(Engine.Alerts.Mock, :max_stop_status, fn _, _ -> :shuttles_closed_station end)
expect_messages({"No Red Line", "Use shuttle bus"})
expect_messages({"No Southbound svc", "Use shuttle bus"})

expect_audios([{:canned, {"199", ["3005"], :audio}}], [
{"There is no Red Line service at this station. Use shuttle.", nil}
expect_audios([{:ad_hoc, {"No Southbound service. Use shuttle.", :audio}}], [
{"No Southbound service. Use shuttle.", nil}
])

Signs.Realtime.handle_info(:run_loop, %{@sign | tick_read: 0, announced_alert: true})
Expand Down Expand Up @@ -1598,10 +1622,10 @@ defmodule Signs.RealtimeTest do
text_zone: "x"
}

expect_messages({"No train service", "Use Routes 86, 87, or 91"})
expect_messages({"No Southbound svc", "Use Routes 86, 87, or 91"})

expect_audios([{:ad_hoc, {"No Train Service. Use routes 86, 87, or 91", :audio}}], [
{"No Train Service. Use routes 86, 87, or 91", nil}
expect_audios([{:ad_hoc, {"No Southbound service. Use routes 86, 87, or 91", :audio}}], [
{"No Southbound service. Use routes 86, 87, or 91", nil}
])

Signs.Realtime.handle_info(:run_loop, sign)
Expand Down

0 comments on commit 1974248

Please sign in to comment.