Skip to content

Commit

Permalink
add visual equivalent for rail TTS audio (#755)
Browse files Browse the repository at this point in the history
  • Loading branch information
panentheos authored May 31, 2024
1 parent 6fc3738 commit 6974e00
Show file tree
Hide file tree
Showing 18 changed files with 109 additions and 26 deletions.
2 changes: 1 addition & 1 deletion lib/content/audio.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ defprotocol Content.Audio do
@doc "Converts an audio struct to the mid/vars params for the PA system"
@spec to_params(Content.Audio.t()) :: value()
def to_params(audio)
@spec to_tts(Content.Audio.t()) :: String.t()
@spec to_tts(Content.Audio.t()) :: {String.t(), [{String.t(), String.t(), integer()}] | nil}
def to_tts(audio)
end
7 changes: 6 additions & 1 deletion lib/content/audio/approaching.ex
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ defmodule Content.Audio.Approaching do
case {destination_var(audio.destination, audio.platform, audio.route_id),
crowding_description} do
{nil, _} ->
{:ad_hoc, {Content.Audio.to_tts(audio), :audio_visual}}
{:ad_hoc, {tts_text(audio), :audio_visual}}

{var, nil} ->
Utilities.take_message([var], :audio_visual)
Expand Down Expand Up @@ -82,6 +82,11 @@ defmodule Content.Audio.Approaching do
end

def to_tts(%Content.Audio.Approaching{} = audio) do
text = tts_text(audio)
{text, PaEss.Utilities.paginate_text(text)}
end

defp tts_text(%Content.Audio.Approaching{} = audio) do
train = Utilities.train_description(audio.destination, audio.route_id)
crowding = PaEss.Utilities.crowding_text(audio.crowding_description)

Expand Down
5 changes: 4 additions & 1 deletion lib/content/audio/boarding_button.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ defmodule Content.Audio.BoardingButton do
end

def to_tts(%Content.Audio.BoardingButton{}) do
"Attention Passengers: To board the next train, please push the button on either side of the door."
text =
"Attention Passengers: To board the next train, please push the button on either side of the door."

{text, PaEss.Utilities.paginate_text(text)}
end
end
end
6 changes: 5 additions & 1 deletion lib/content/audio/closure.ex
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,14 @@ defmodule Content.Audio.Closure do

# Hardcoded for Union Square
def to_params(%Content.Audio.Closure{alert: :use_routes_alert, routes: []} = audio) do
{:ad_hoc, {Content.Audio.to_tts(audio), :audio}}
{:ad_hoc, {tts_text(audio), :audio}}
end

def to_tts(%Content.Audio.Closure{} = audio) do
{tts_text(audio), nil}
end

defp tts_text(%Content.Audio.Closure{} = audio) do
if audio.alert == :use_routes_alert do
# Hardcoded for Union Square
"No Train Service. Use routes 86, 87, or 91"
Expand Down
2 changes: 1 addition & 1 deletion lib/content/audio/custom.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ defmodule Content.Audio.Custom do
end

def to_tts(%Content.Audio.Custom{} = audio) do
audio.message
{audio.message, nil}
end
end
end
2 changes: 1 addition & 1 deletion lib/content/audio/first_train_scheduled.ex
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ defmodule Content.Audio.FirstTrainScheduled do
def to_tts(%Content.Audio.FirstTrainScheduled{} = audio) do
train = PaEss.Utilities.train_description(audio.destination, nil)
time = Content.Utilities.render_datetime_as_time(audio.scheduled_time)
"The first #{train} is scheduled to arrive at #{time}"
{"The first #{train} is scheduled to arrive at #{time}", nil}
end
end
end
6 changes: 5 additions & 1 deletion lib/content/audio/following_train.ex
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,18 @@ defmodule Content.Audio.FollowingTrain do
end

def to_tts(%Content.Audio.FollowingTrain{} = audio) do
{tts_text(audio), nil}
end

defp tts_text(%Content.Audio.FollowingTrain{} = audio) do
train = Utilities.train_description(audio.destination, audio.route_id)
arrives_or_departs = if audio.verb == :arrives, do: "arrives", else: "departs"
min_or_mins = if audio.minutes == 1, do: "minute", else: "minutes"
"The following #{train} #{arrives_or_departs} in #{audio.minutes} #{min_or_mins}"
end

defp do_ad_hoc_message(audio) do
{:ad_hoc, {Content.Audio.to_tts(audio), :audio}}
{:ad_hoc, {tts_text(audio), :audio}}
end

@spec green_line_with_branch_params(
Expand Down
6 changes: 5 additions & 1 deletion lib/content/audio/next_train_countdown.ex
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ defmodule Content.Audio.NextTrainCountdown do
end

def to_tts(%Content.Audio.NextTrainCountdown{} = audio) do
{tts_text(audio), nil}
end

defp tts_text(%Content.Audio.NextTrainCountdown{} = audio) do
train = Utilities.train_description(audio.destination, audio.route_id)
arrives_or_departs = if audio.verb == :arrives, do: "arrives", else: "departs"
min_or_mins = if audio.minutes == 1, do: "minute", else: "minutes"
Expand Down Expand Up @@ -123,7 +127,7 @@ defmodule Content.Audio.NextTrainCountdown do
end

defp do_ad_hoc_message(audio) do
{:ad_hoc, {Content.Audio.to_tts(audio), :audio}}
{:ad_hoc, {tts_text(audio), :audio}}
end

@spec green_line_with_branch_params(
Expand Down
6 changes: 5 additions & 1 deletion lib/content/audio/no_service_to_destination.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@ defmodule Content.Audio.NoServiceToDestination do

defimpl Content.Audio do
def to_params(%Content.Audio.NoServiceToDestination{} = audio) do
{:ad_hoc, {Content.Audio.to_tts(audio), :audio}}
{:ad_hoc, {tts_text(audio), :audio}}
end

def to_tts(%Content.Audio.NoServiceToDestination{} = audio) do
{tts_text(audio), nil}
end

defp tts_text(%Content.Audio.NoServiceToDestination{} = audio) do
{:ok, destination_text} = PaEss.Utilities.destination_to_ad_hoc_string(audio.destination)
shuttle = if(audio.use_shuttle, do: " Use shuttle.", else: "")
"No #{destination_text} service.#{shuttle}"
Expand Down
7 changes: 6 additions & 1 deletion lib/content/audio/passthrough.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,19 @@ defmodule Content.Audio.Passthrough do
def to_params(audio) do
case destination_var(audio.destination, audio.route_id) do
nil ->
{:ad_hoc, {Content.Audio.to_tts(audio), :audio_visual}}
{:ad_hoc, {tts_text(audio), :audio_visual}}

var ->
{:canned, {"103", [var], :audio_visual}}
end
end

def to_tts(%Content.Audio.Passthrough{} = audio) do
text = tts_text(audio)
{text, PaEss.Utilities.paginate_text(text)}
end

defp tts_text(%Content.Audio.Passthrough{} = audio) do
train = PaEss.Utilities.train_description(audio.destination, audio.route_id)
"The next #{train} does not take customers. Please stand back from the yellow line."
end
Expand Down
14 changes: 9 additions & 5 deletions lib/content/audio/service_ended.ex
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ defmodule Content.Audio.ServiceEnded do
Utilities.take_message([@platform_closed, destination_var, @service_ended], :audio)

{:error, :unknown} ->
to_tts(audio)
{:ad_hoc, {tts_text(audio), :audio}}
end
end

Expand All @@ -50,15 +50,19 @@ defmodule Content.Audio.ServiceEnded do
Utilities.take_message([destination_var, @service_ended], :audio)

{:error, :unknown} ->
to_tts(audio)
{:ad_hoc, {tts_text(audio), :audio}}
end
end

def to_tts(%Content.Audio.ServiceEnded{location: :station}) do
def to_tts(%Content.Audio.ServiceEnded{} = audio) do
{tts_text(audio), nil}
end

defp tts_text(%Content.Audio.ServiceEnded{location: :station}) do
"This station is closed. Service has ended for the night."
end

def to_tts(%Content.Audio.ServiceEnded{location: :platform, destination: destination}) do
defp tts_text(%Content.Audio.ServiceEnded{location: :platform, destination: destination}) do
{:ok, destination_string} = Utilities.destination_to_ad_hoc_string(destination)

service_ended =
Expand All @@ -69,7 +73,7 @@ defmodule Content.Audio.ServiceEnded do
"This platform is closed. #{service_ended}"
end

def to_tts(%Content.Audio.ServiceEnded{location: :direction, destination: destination}) do
defp tts_text(%Content.Audio.ServiceEnded{location: :direction, destination: destination}) do
{:ok, destination_string} = Utilities.destination_to_ad_hoc_string(destination)

"#{destination_string} service has ended for the night."
Expand Down
6 changes: 5 additions & 1 deletion lib/content/audio/stopped_train.ex
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,17 @@ defmodule Content.Audio.StoppedTrain do
end

def to_tts(%Content.Audio.StoppedTrain{} = audio) do
{tts_text(audio), nil}
end

defp tts_text(%Content.Audio.StoppedTrain{} = audio) do
train = Utilities.train_description(audio.destination, audio.route_id)
stop_or_stops = if audio.stops_away == 1, do: "stop", else: "stops"
"The next #{train} is stopped #{audio.stops_away} #{stop_or_stops} away"
end

defp do_ad_hoc_message(audio) do
{:ad_hoc, {Content.Audio.to_tts(audio), :audio}}
{:ad_hoc, {tts_text(audio), :audio}}
end

defp stops_away_var(1), do: "535"
Expand Down
3 changes: 2 additions & 1 deletion lib/content/audio/track_change.ex
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ defmodule Content.Audio.TrackChange do
"70199" -> "E"
end

"Track change: The next #{train} is now boarding on the #{platform} platform"
text = "Track change: The next #{train} is now boarding on the #{platform} platform"
{text, PaEss.Utilities.paginate_text(text)}
end

defp track_change_message(msg_id) do
Expand Down
7 changes: 6 additions & 1 deletion lib/content/audio/train_is_arriving.ex
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ defmodule Content.Audio.TrainIsArriving do
) do
case {dest_param(audio), crowding_description} do
{nil, _} ->
{:ad_hoc, {Content.Audio.to_tts(audio), :audio_visual}}
{:ad_hoc, {tts_text(audio), :audio_visual}}

{var, nil} ->
Utilities.take_message([var], :audio_visual)
Expand All @@ -50,6 +50,11 @@ defmodule Content.Audio.TrainIsArriving do
end

def to_tts(%Content.Audio.TrainIsArriving{} = audio) do
text = tts_text(audio)
{text, PaEss.Utilities.paginate_text(text)}
end

defp tts_text(%Content.Audio.TrainIsArriving{} = audio) do
train = Utilities.train_description(audio.destination, audio.route_id)
crowding = PaEss.Utilities.crowding_text(audio.crowding_description)
"Attention passengers: The next #{train} is now arriving.#{crowding}"
Expand Down
8 changes: 6 additions & 2 deletions lib/content/audio/train_is_boarding.ex
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,18 @@ defmodule Content.Audio.TrainIsBoarding do
end
end

def to_tts(audio) do
def to_tts(%Content.Audio.TrainIsBoarding{} = audio) do
{tts_text(audio), nil}
end

defp tts_text(%Content.Audio.TrainIsBoarding{} = audio) do
train = PaEss.Utilities.train_description(audio.destination, audio.route_id)
track = if(audio.track_number, do: " on track #{audio.track_number}", else: ".")
"The next #{train} is now boarding#{track}"
end

defp do_ad_hoc_message(audio) do
{:ad_hoc, {Content.Audio.to_tts(audio), :audio}}
{:ad_hoc, {tts_text(audio), :audio}}
end

defp do_to_params(%{destination: destination, route_id: "Green-" <> _branch}, destination_var)
Expand Down
16 changes: 10 additions & 6 deletions lib/content/audio/vehicles_to_destination.ex
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,19 @@ defmodule Content.Audio.VehiclesToDestination do
if low_var && high_var && destination do
{:canned, {message_id(audio), [low_var, high_var], :audio}}
else
{:ad_hoc, {Content.Audio.to_tts(audio), :audio}}
{:ad_hoc, {tts_text(audio), :audio}}
end
end

def to_tts(%Content.Audio.VehiclesToDestination{
headway_range: {range_low, range_high},
destination: destination,
routes: routes
}) do
def to_tts(%Content.Audio.VehiclesToDestination{} = audio) do
{tts_text(audio), nil}
end

defp tts_text(%Content.Audio.VehiclesToDestination{
headway_range: {range_low, range_high},
destination: destination,
routes: routes
}) do
trains =
case {destination, routes} do
{destination, nil} ->
Expand Down
24 changes: 24 additions & 0 deletions lib/pa_ess/utilities.ex
Original file line number Diff line number Diff line change
Expand Up @@ -697,4 +697,28 @@ defmodule PaEss.Utilities do

def audio_take({:route, route}), do: @route_take_lookup[route]
def audio_take(atom) when is_atom(atom), do: @atom_take_lookup[atom]

@spec paginate_text(String.t(), integer()) :: [{String.t(), String.t(), integer()}]
def paginate_text(text, max_length \\ 24) do
String.split(text)
|> Stream.chunk_while(
nil,
fn word, acc ->
if is_nil(acc) do
{:cont, word}
else
new_acc = acc <> " " <> word

if String.length(new_acc) > max_length do
{:cont, acc, word}
else
{:cont, new_acc}
end
end
end,
fn acc -> {:cont, acc, nil} end
)
|> Stream.chunk_every(2, 2, [""])
|> Enum.map(fn [top, bottom] -> {top, bottom, 3} end)
end
end
8 changes: 8 additions & 0 deletions test/pa_ess/utilities_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,12 @@ defmodule Content.Audio.UtilitiesTest do
assert replace_abbreviations("SvC, OK") == "Service, OK"
end
end

test "paginate_text" do
assert [{"Attention passengers:", "the next Braintree train", 3}, {"is now arriving", "", 3}] =
paginate_text("Attention passengers: the next Braintree train is now arriving", 24)

assert [{"too-long", "word", 3}] = paginate_text(" too-long word ", 5)
assert [{"fits", "", 3}] = paginate_text("fits", 24)
end
end

0 comments on commit 6974e00

Please sign in to comment.