Skip to content

Commit

Permalink
OL crowding read loop selection (#678)
Browse files Browse the repository at this point in the history
* Add locations feed engine

* Add unit test for 'deletion' logic

* Add a few more tests

* remmove io puts

* fix typedef

* Begin reading in multi_carriage_details field

* Calculate crowding data confidence level

* Branch arrival and approaching audio logic based on crowding data confidence level

* Add a todo for where to incorporate read loop selection logic

* Clean up calculation logic

* adjust mapping logic to match actual schema

* Add main crowding determination logic

* Start passing crowding description to Arriving and Approaching messages

* Add read loop selection logic

* Add logging of crowding announcements

* remove old unneeded module attributes

* Clean up

* Condense logging code
  • Loading branch information
PaulJKim authored Aug 31, 2023
1 parent 72220b4 commit 84cf9d7
Show file tree
Hide file tree
Showing 3 changed files with 228 additions and 8 deletions.
2 changes: 2 additions & 0 deletions lib/signs/realtime.ex
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ defmodule Signs.Realtime do
:current_time_fn,
announced_arrivals: [],
announced_approachings: [],
announced_approachings_with_crowding: [],
announced_passthroughs: [],
uses_shuttles: true
]
Expand Down Expand Up @@ -63,6 +64,7 @@ defmodule Signs.Realtime do
read_period_seconds: non_neg_integer(),
announced_arrivals: [Predictions.Prediction.trip_id()],
announced_approachings: [Predictions.Prediction.trip_id()],
announced_approachings_with_crowding: [Predictions.Prediction.trip_id()],
announced_passthroughs: [Predictions.Prediction.trip_id()],
uses_shuttles: boolean()
}
Expand Down
61 changes: 53 additions & 8 deletions lib/signs/utilities/audio.ex
Original file line number Diff line number Diff line change
Expand Up @@ -146,16 +146,24 @@ defmodule Signs.Utilities.Audio do
{[], sign.announced_approachings, sign.announced_arrivals},
fn audio, {new_audios, new_approaching_trips, new_arriving_trips} ->
case audio do
# TODO: Add a check for whether high-confidence crowding info is present and whether it has already been announced with an approaching message
%Audio.TrainIsArriving{trip_id: trip_id} when not is_nil(trip_id) ->
if audio.trip_id in sign.announced_arrivals do
{new_audios, new_approaching_trips, new_arriving_trips}
else
{new_audios ++ [audio], new_approaching_trips,
[audio.trip_id | new_arriving_trips]}
%Audio.TrainIsArriving{trip_id: trip_id, crowding_description: crowding_description}
when not is_nil(trip_id) ->
cond do
# If we've already announced the arrival, don't announce it
audio.trip_id in sign.announced_arrivals ->
{new_audios, new_approaching_trips, new_arriving_trips}

# If the arrival has high-confidence crowding info but we've already announced crowding with the approaching message, announce it without crowding
crowding_description && audio.trip_id in sign.announced_approachings_with_crowding ->
{new_audios ++ [%{audio | crowding_description: nil}], new_approaching_trips,
[audio.trip_id | new_arriving_trips]}

# else, announce normally
true ->
{new_audios ++ [audio], new_approaching_trips,
[audio.trip_id | new_arriving_trips]}
end

# TODO: Start tracking trip_ids where we announce high-confidence crowding info with Approaching
%Audio.Approaching{trip_id: trip_id} when not is_nil(trip_id) ->
if audio.trip_id in sign.announced_approachings do
{new_audios, new_approaching_trips, new_arriving_trips}
Expand All @@ -170,9 +178,21 @@ defmodule Signs.Utilities.Audio do
end
)

new_announced_approaching_with_crowding =
for %Audio.Approaching{trip_id: trip_id, crowding_description: crowding_description} <-
new_audios,
not is_nil(trip_id) and not is_nil(crowding_description) do
trip_id
end

sign = %{
sign
| announced_approachings: Enum.take(new_approaching_trips, @announced_history_length),
announced_approachings_with_crowding:
Enum.take(
new_announced_approaching_with_crowding ++ sign.announced_approachings_with_crowding,
@announced_history_length
),
announced_arrivals: Enum.take(new_arriving_trips, @announced_history_length)
}

Expand All @@ -182,10 +202,35 @@ defmodule Signs.Utilities.Audio do
else
new_audios
end
|> tap(&log_crowding(&1, sign.id))

{new_audios, sign}
end

defp log_crowding(new_audios, sign_id) do
Enum.each(new_audios, fn
%{
trip_id: trip_id,
crowding_description: crowding_description,
route_id: "Orange",
__struct__: audio_type
}
when audio_type in [Audio.Approaching, Audio.TrainIsArriving] ->
announcement_type =
case audio_type do
Audio.Approaching -> "approaching"
Audio.TrainIsArriving -> "arrival"
end

Logger.info(
"crowding_log: announcement_type=#{announcement_type} trip_id=#{trip_id} sign_id=#{sign_id} crowding_description=#{inspect(crowding_description)}"
)

_ ->
nil
end)
end

@spec sort_audio([Content.Audio.t()]) :: [Content.Audio.t()]
defp sort_audio(audios) do
Enum.sort_by(audios, fn audio ->
Expand Down
173 changes: 173 additions & 0 deletions test/signs/utilities/audio_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -823,5 +823,178 @@ defmodule Signs.Utilities.AudioTest do

assert log =~ "message_to_audio_warning Utilities.Audio generic_paging_mismatch"
end

test "Announce approaching with crowding when condfidence high" do
sign = %{
@sign
| current_content_top: %Message.Predictions{
destination: :oak_grove,
minutes: :approaching,
route_id: "Orange",
crowding_data_confidence: :high,
crowding_description: {:front, :some_crowding}
},
current_content_bottom: %Content.Message.Empty{}
}

{audios, _} = from_sign(sign)

assert [
%Content.Audio.Approaching{
destination: :oak_grove,
crowding_description: {:front, :some_crowding}
}
] = audios
end

test "Announce approaching without crowding when condfidence low" do
sign = %{
@sign
| current_content_top: %Message.Predictions{
destination: :oak_grove,
minutes: :approaching,
route_id: "Orange",
crowding_data_confidence: :low,
crowding_description: {:front, :some_crowding}
},
current_content_bottom: %Content.Message.Empty{}
}

{audios, _} = from_sign(sign)

assert [
%Content.Audio.Approaching{
destination: :oak_grove,
crowding_description: nil
}
] = audios
end

test "Track announced approachings with crowding" do
sign = %{
@sign
| current_content_top: %Message.Predictions{
destination: :oak_grove,
minutes: :approaching,
route_id: "Orange",
crowding_data_confidence: :high,
crowding_description: {:front, :some_crowding},
trip_id: "trip1"
},
current_content_bottom: %Content.Message.Empty{}
}

{audios, sign} = from_sign(sign)

assert [
%Content.Audio.Approaching{
destination: :oak_grove,
crowding_description: {:front, :some_crowding}
}
] = audios

assert(["trip1"] = sign.announced_approachings_with_crowding)
end

test "Don't track announced approachings without crowding" do
sign = %{
@sign
| current_content_top: %Message.Predictions{
destination: :oak_grove,
minutes: :approaching,
route_id: "Orange",
crowding_data_confidence: :low,
crowding_description: {:front, :some_crowding},
trip_id: "trip1"
},
current_content_bottom: %Content.Message.Empty{}
}

{audios, sign} = from_sign(sign)

assert [
%Content.Audio.Approaching{
destination: :oak_grove,
crowding_description: nil
}
] = audios

assert([] = sign.announced_approachings_with_crowding)
end

test "Announce arrival with crowding if not already announced" do
sign = %{
@sign
| current_content_top: %Message.Predictions{
destination: :oak_grove,
minutes: :arriving,
route_id: "Orange",
crowding_data_confidence: :high,
crowding_description: {:front, :some_crowding},
trip_id: "trip2"
},
current_content_bottom: %Content.Message.Empty{},
announced_approachings_with_crowding: ["trip1"]
}

{audios, _} = from_sign(sign)

assert [
%Content.Audio.TrainIsArriving{
destination: :oak_grove,
crowding_description: {:front, :some_crowding}
}
] = audios
end

test "Don't announce arrival with crowding if confidence low" do
sign = %{
@sign
| current_content_top: %Message.Predictions{
destination: :oak_grove,
minutes: :arriving,
route_id: "Orange",
crowding_data_confidence: :low,
crowding_description: {:front, :some_crowding},
trip_id: "trip2"
},
current_content_bottom: %Content.Message.Empty{},
announced_approachings_with_crowding: ["trip1"]
}

{audios, _} = from_sign(sign)

assert [
%Content.Audio.TrainIsArriving{
destination: :oak_grove,
crowding_description: nil
}
] = audios
end

test "Don't announce arrival with crowding if already announced with approaching" do
sign = %{
@sign
| current_content_top: %Message.Predictions{
destination: :oak_grove,
minutes: :arriving,
route_id: "Orange",
crowding_data_confidence: :high,
crowding_description: {:front, :some_crowding},
trip_id: "trip1"
},
current_content_bottom: %Content.Message.Empty{},
announced_approachings_with_crowding: ["trip1"]
}

{audios, _} = from_sign(sign)

assert [
%Content.Audio.TrainIsArriving{
destination: :oak_grove,
crowding_description: nil
}
] = audios
end
end
end

0 comments on commit 84cf9d7

Please sign in to comment.