Skip to content

Commit

Permalink
move crowding to its own module
Browse files Browse the repository at this point in the history
  • Loading branch information
panentheos committed Nov 1, 2024
1 parent 58b1c28 commit 74259be
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 95 deletions.
93 changes: 0 additions & 93 deletions lib/pa_ess/utilities.ex
Original file line number Diff line number Diff line change
Expand Up @@ -717,99 +717,6 @@ defmodule PaEss.Utilities do
|> Enum.map(fn [top, bottom] -> {top, bottom, 3} end)
end

@spec crowding_description(Predictions.Prediction.t(), Signs.Realtime.t()) ::
{:front | :back | :middle | :front_and_back | :train_level,
:not_crowded | :some_crowding | :crowded | :unknown_crowding}
| nil
def crowding_description(_, %{source_config: {_, _}}), do: nil

def crowding_description(%{route_id: "Orange"} = prediction, sign) do
case sign.location_engine.for_vehicle(prediction.vehicle_id) do
%Locations.Location{
stop_id: stop_id,
status: status,
multi_carriage_details: carriage_details
}
when stop_id == prediction.stop_id and status in [:incoming_at, :in_transit_to] ->
get_crowding_description(carriage_details)

_ ->
nil
end
end

def crowding_description(_, _), do: nil

defp get_crowding_description([_, _, _, _, _, _] = carriage_details) do
crowding_levels =
Enum.map(carriage_details, &occupancy_percentage_to_crowding_level(&1.occupancy_percentage))

min_crowding_level = Enum.min(crowding_levels)

relative_crowding_levels =
for crowding_level <- crowding_levels do
if crowding_level == min_crowding_level,
do: :e,
else: :f
end

{get_emptier_location(
{Enum.count(relative_crowding_levels, &Kernel.==(&1, :e)), relative_crowding_levels}
), crowding_level_to_atom(min_crowding_level)}
end

defp get_crowding_description(_), do: nil

defp occupancy_percentage_to_crowding_level(occupancy_percentage) do
cond do
occupancy_percentage <= 12 -> 1
occupancy_percentage <= 40 -> 2
occupancy_percentage > 40 -> 3
occupancy_percentage == nil -> 4
end
end

defp crowding_level_to_atom(crowding_level) do
case crowding_level do
1 -> :not_crowded
2 -> :some_crowding
3 -> :crowded
4 -> :unknown_crowding
end
end

defp get_emptier_location(car_crowding_levels) do
case car_crowding_levels do
{1, [_, _, :f, :f, :f, :f]} -> :front
{1, [:f, :f, :f, :f, _, _]} -> :back
{1, [:f, :f, _, _, :f, :f]} -> :middle
{2, [_, _, _, :f, :f, :f]} -> :front
{2, [_, :f, :f, _, :f, :f]} -> :front
{2, [:f, :f, :f, _, _, _]} -> :back
{2, [:f, :f, _, :f, :f, _]} -> :back
{2, [_, _, :f, :f, _, _]} -> :front_and_back
{2, _} -> :middle
{3, [:f, _, _, _, _, :f]} -> :middle
{3, [_, _, _, _, :f, :f]} -> :front
{3, [:f, :f, _, _, _, _]} -> :back
{3, [:f, _, :f, _, :f, _]} -> :train_level
{3, [_, :f, _, :f, _, :f]} -> :train_level
{3, _} -> :front_and_back
{4, [:f, _, _, _, _, :f]} -> :middle
{4, [_, _, _, _, _, :f]} -> :front
{4, [_, _, _, :f, :f, _]} -> :front
{4, [:f, _, _, _, _, _]} -> :back
{4, [_, :f, :f, _, _, _]} -> :back
{4, [_, _, :f, :f, _, _]} -> :front_and_back
{4, _} -> :train_level
{5, [_, _, _, _, _, :f]} -> :front
{5, [:f, _, _, _, _, _]} -> :back
{5, _} -> :train_level
{6, _} -> :train_level
_ -> :train_level
end
end

@spec prediction_new_cars?(Predictions.Prediction.t(), Signs.Realtime.t()) :: boolean()
def prediction_new_cars?(prediction, sign) do
case sign.location_engine.for_vehicle(prediction.vehicle_id) do
Expand Down
4 changes: 2 additions & 2 deletions lib/signs/utilities/audio.ex
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ defmodule Signs.Utilities.Audio do
announce_arriving?(sign, message) ->
crowding =
if message.prediction.trip_id not in sign.announced_approachings_with_crowding do
PaEss.Utilities.crowding_description(message.prediction, sign)
Signs.Utilities.Crowding.crowding_description(message.prediction, sign)
end

{Audio.TrainIsArriving.from_message(message, crowding),
Expand All @@ -211,7 +211,7 @@ defmodule Signs.Utilities.Audio do
message.prediction.trip_id not in sign.announced_approachings &&
announce_arriving?(sign, message) &&
message.prediction.route_id in @heavy_rail_routes ->
crowding = PaEss.Utilities.crowding_description(message.prediction, sign)
crowding = Signs.Utilities.Crowding.crowding_description(message.prediction, sign)
new_cars? = PaEss.Utilities.prediction_new_cars?(message.prediction, sign)

{Audio.Approaching.from_message(message, crowding, new_cars?),
Expand Down
94 changes: 94 additions & 0 deletions lib/signs/utilities/crowding.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
defmodule Signs.Utilities.Crowding do
@spec crowding_description(Predictions.Prediction.t(), Signs.Realtime.t()) ::
{:front | :back | :middle | :front_and_back | :train_level,
:not_crowded | :some_crowding | :crowded | :unknown_crowding}
| nil
def crowding_description(_, %{source_config: {_, _}}), do: nil

def crowding_description(%{route_id: "Orange"} = prediction, sign) do
case sign.location_engine.for_vehicle(prediction.vehicle_id) do
%Locations.Location{
stop_id: stop_id,
status: status,
multi_carriage_details: carriage_details
}
when stop_id == prediction.stop_id and status in [:incoming_at, :in_transit_to] ->
get_crowding_description(carriage_details)

_ ->
nil
end
end

def crowding_description(_, _), do: nil

defp get_crowding_description([_, _, _, _, _, _] = carriage_details) do
crowding_levels =
Enum.map(carriage_details, &occupancy_percentage_to_crowding_level(&1.occupancy_percentage))

min_crowding_level = Enum.min(crowding_levels)

relative_crowding_levels =
for crowding_level <- crowding_levels do
if crowding_level == min_crowding_level,
do: :e,
else: :f
end

{get_emptier_location(
{Enum.count(relative_crowding_levels, &Kernel.==(&1, :e)), relative_crowding_levels}
), crowding_level_to_atom(min_crowding_level)}
end

defp get_crowding_description(_), do: nil

defp occupancy_percentage_to_crowding_level(occupancy_percentage) do
cond do
occupancy_percentage <= 12 -> 1
occupancy_percentage <= 40 -> 2
occupancy_percentage > 40 -> 3
occupancy_percentage == nil -> 4
end
end

defp crowding_level_to_atom(crowding_level) do
case crowding_level do
1 -> :not_crowded
2 -> :some_crowding
3 -> :crowded
4 -> :unknown_crowding
end
end

defp get_emptier_location(car_crowding_levels) do
case car_crowding_levels do
{1, [_, _, :f, :f, :f, :f]} -> :front
{1, [:f, :f, :f, :f, _, _]} -> :back
{1, [:f, :f, _, _, :f, :f]} -> :middle
{2, [_, _, _, :f, :f, :f]} -> :front
{2, [_, :f, :f, _, :f, :f]} -> :front
{2, [:f, :f, :f, _, _, _]} -> :back
{2, [:f, :f, _, :f, :f, _]} -> :back
{2, [_, _, :f, :f, _, _]} -> :front_and_back
{2, _} -> :middle
{3, [:f, _, _, _, _, :f]} -> :middle
{3, [_, _, _, _, :f, :f]} -> :front
{3, [:f, :f, _, _, _, _]} -> :back
{3, [:f, _, :f, _, :f, _]} -> :train_level
{3, [_, :f, _, :f, _, :f]} -> :train_level
{3, _} -> :front_and_back
{4, [:f, _, _, _, _, :f]} -> :middle
{4, [_, _, _, _, _, :f]} -> :front
{4, [_, _, _, :f, :f, _]} -> :front
{4, [:f, _, _, _, _, _]} -> :back
{4, [_, :f, :f, _, _, _]} -> :back
{4, [_, _, :f, :f, _, _]} -> :front_and_back
{4, _} -> :train_level
{5, [_, _, _, _, _, :f]} -> :front
{5, [:f, _, _, _, _, _]} -> :back
{5, _} -> :train_level
{6, _} -> :train_level
_ -> :train_level
end
end
end

0 comments on commit 74259be

Please sign in to comment.