diff --git a/assets/src/components/admin/inspector.tsx b/assets/src/components/admin/inspector.tsx index 80f23d9f1..40ff03d91 100644 --- a/assets/src/components/admin/inspector.tsx +++ b/assets/src/components/admin/inspector.tsx @@ -86,7 +86,7 @@ const Inspector: ComponentType = () => { - + > )} > @@ -305,10 +305,7 @@ const DataControls: ComponentType<{ ); }; -const AudioControls: ComponentType<{ - config: Config; - screen: ScreenWithId; -}> = ({ config, screen }) => { +const AudioControls: ComponentType<{ screen: ScreenWithId }> = ({ screen }) => { const [isPlaying, setIsPlaying] = useState(false); const [ssml, setSSML] = useState(null); const dialogRef = useRef(null); @@ -318,24 +315,9 @@ const AudioControls: ComponentType<{ [dialogRef, ssml], ); - let audioPath: string | null = null; - let v1ScreenId: string | null = null; - - if (AUDIO_SCREEN_TYPES.has(screen.config.app_id)) { - // Temporarily special-case Busway screens while V2 doesn't support audio - // yet, in a way that aligns with how they're configured in reality (using - // the audio endpoint of a corresponding V1 screen). - if (screen.config.app_id == "busway_v2") { - const maybeV1Id = screen.id.replace(/-V2$/, ""); - - if (maybeV1Id != screen.id && config.screens[maybeV1Id]) { - audioPath = `/audio/${maybeV1Id}`; - v1ScreenId = maybeV1Id; - } - } else { - audioPath = `/v2/audio/${screen.id}`; - } - } + const audioPath = AUDIO_SCREEN_TYPES.has(screen.config.app_id) + ? `/v2/audio/${screen.id}` + : null; return ( @@ -361,14 +343,6 @@ const AudioControls: ComponentType<{ - {v1ScreenId && ( - - - (from v1 screen {v1ScreenId}) - - - )} - header_instances(config, now, fetch_stop_name_fn) end, - fn -> departures_instances_fn.(config) end, + fn -> departures_instances_fn.(config, now) end, fn -> alert_instances_fn.(config) end, fn -> footer_instances(config) end, fn -> evergreen_content_instances_fn.(config) end, diff --git a/lib/screens/v2/candidate_generator/bus_shelter.ex b/lib/screens/v2/candidate_generator/bus_shelter.ex index f91e0153e..55ae61802 100644 --- a/lib/screens/v2/candidate_generator/bus_shelter.ex +++ b/lib/screens/v2/candidate_generator/bus_shelter.ex @@ -50,14 +50,14 @@ defmodule Screens.V2.CandidateGenerator.BusShelter do _opts, now \\ DateTime.utc_now(), fetch_stop_name_fn \\ &Stop.fetch_stop_name/1, - departures_instances_fn \\ &Widgets.Departures.departures_instances/1, + departures_instances_fn \\ &Widgets.Departures.departures_instances/2, alert_instances_fn \\ &Widgets.Alerts.alert_instances/1, evergreen_content_instances_fn \\ &Widgets.Evergreen.evergreen_content_instances/1, subway_status_instances_fn \\ &Widgets.SubwayStatus.subway_status_instances/2 ) do [ fn -> header_instances(config, now, fetch_stop_name_fn) end, - fn -> departures_instances_fn.(config) end, + fn -> departures_instances_fn.(config, now) end, fn -> alert_instances_fn.(config) end, fn -> footer_instances(config) end, fn -> subway_status_instances_fn.(config, now) end, diff --git a/lib/screens/v2/candidate_generator/busway.ex b/lib/screens/v2/candidate_generator/busway.ex index 77ab4fe7d..ffc48f399 100644 --- a/lib/screens/v2/candidate_generator/busway.ex +++ b/lib/screens/v2/candidate_generator/busway.ex @@ -12,7 +12,7 @@ defmodule Screens.V2.CandidateGenerator.Busway do defmodule Deps do @moduledoc false defstruct now: &DateTime.utc_now/0, - departures_instances: &Widgets.Departures.departures_instances/1 + departures_instances: &Widgets.Departures.departures_instances/2 end @behaviour CandidateGenerator @@ -31,9 +31,11 @@ defmodule Screens.V2.CandidateGenerator.Busway do @impl CandidateGenerator def candidate_instances(config, _opts, deps \\ %Deps{}) do + now = deps.now.() + [ - fn -> header_instances(config, deps.now.()) end, - fn -> deps.departures_instances.(config) end, + fn -> header_instances(config, now) end, + fn -> deps.departures_instances.(config, now) end, fn -> placeholder_instances() end ] |> Task.async_stream(& &1.(), timeout: 15_000) diff --git a/lib/screens/v2/candidate_generator/dup/departures.ex b/lib/screens/v2/candidate_generator/dup/departures.ex index c2e06a012..21e034b9a 100644 --- a/lib/screens/v2/candidate_generator/dup/departures.ex +++ b/lib/screens/v2/candidate_generator/dup/departures.ex @@ -124,7 +124,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.Departures do %DeparturesWidget{ screen: config, section_data: sections, - slot_names: [slot_id] + slot_names: [slot_id], + now: now } end end) diff --git a/lib/screens/v2/candidate_generator/gl_eink.ex b/lib/screens/v2/candidate_generator/gl_eink.ex index 7a93d3cf8..f09db5d6d 100644 --- a/lib/screens/v2/candidate_generator/gl_eink.ex +++ b/lib/screens/v2/candidate_generator/gl_eink.ex @@ -88,7 +88,9 @@ defmodule Screens.V2.CandidateGenerator.GlEink do ) do [ fn -> header_instances(config, now, fetch_destination_fn) end, - fn -> departures_instances_fn.(config, post_process_fn: &departures_post_processing/2) end, + fn -> + departures_instances_fn.(config, now, post_process_fn: &departures_post_processing/2) + end, fn -> alert_instances_fn.(config) end, fn -> footer_instances(config) end, fn -> line_map_instances(config, now) end, diff --git a/lib/screens/v2/candidate_generator/solari_large.ex b/lib/screens/v2/candidate_generator/solari_large.ex index 1a7360263..8b68d6907 100644 --- a/lib/screens/v2/candidate_generator/solari_large.ex +++ b/lib/screens/v2/candidate_generator/solari_large.ex @@ -27,11 +27,11 @@ defmodule Screens.V2.CandidateGenerator.SolariLarge do config, _opts, now \\ DateTime.utc_now(), - departures_instances_fn \\ &Widgets.Departures.departures_instances/1 + departures_instances_fn \\ &Widgets.Departures.departures_instances/2 ) do [ fn -> header_instances(config, now) end, - fn -> departures_instances_fn.(config) end, + fn -> departures_instances_fn.(config, now) end, fn -> placeholder_instances() end ] |> Task.async_stream(& &1.(), timeout: 15_000) diff --git a/lib/screens/v2/candidate_generator/widgets/departures.ex b/lib/screens/v2/candidate_generator/widgets/departures.ex index 3e394aa41..f507864a5 100644 --- a/lib/screens/v2/candidate_generator/widgets/departures.ex +++ b/lib/screens/v2/candidate_generator/widgets/departures.ex @@ -25,7 +25,8 @@ defmodule Screens.V2.CandidateGenerator.Widgets.Departures do departure_fetch_fn: Departure.fetch(), disabled_modes_fn: (-> RouteType.t()), post_process_fn: (Departure.result(), Screen.t() -> Departure.result() | :overnight), - route_fetch_fn: (Route.params() -> {:ok, [Route.t()]} | :error) + route_fetch_fn: (Route.params() -> {:ok, [Route.t()]} | :error), + now: DateTime.t() ] @type widget :: @@ -34,9 +35,8 @@ defmodule Screens.V2.CandidateGenerator.Widgets.Departures do | DeparturesWidget.t() | OvernightDepartures.t() - @spec departures_instances(Screen.t()) :: [widget()] @spec departures_instances(Screen.t(), options()) :: [widget()] - def departures_instances(%Screen{app_params: %app{}} = config, options \\ []) + def departures_instances(%Screen{app_params: %app{}} = config, now, options \\ []) when app in [BusEink, BusShelter, Busway, GlEink, SolariLarge] do disabled_modes = Keyword.get(options, :disabled_modes_fn, &Screens.Config.Cache.disabled_modes/0).() @@ -49,7 +49,8 @@ defmodule Screens.V2.CandidateGenerator.Widgets.Departures do disabled_modes, Keyword.get(options, :departure_fetch_fn, &Departure.fetch/2), Keyword.get(options, :post_process_fn, fn results, _config -> results end), - Keyword.get(options, :route_fetch_fn, &Route.fetch/1) + Keyword.get(options, :route_fetch_fn, &Route.fetch/1), + now ) end end @@ -60,7 +61,8 @@ defmodule Screens.V2.CandidateGenerator.Widgets.Departures do disabled_modes, departure_fetch_fn, post_process_fn, - route_fetch_fn + route_fetch_fn, + now ) do has_multiple_sections = match?([_, _ | _], sections) @@ -102,7 +104,7 @@ defmodule Screens.V2.CandidateGenerator.Widgets.Departures do } end) - %DeparturesWidget{screen: config, section_data: sections} + %DeparturesWidget{screen: config, section_data: sections, now: now} end [departures_instance] diff --git a/lib/screens/v2/screen_audio_data.ex b/lib/screens/v2/screen_audio_data.ex index eb6b69054..b99f590a1 100644 --- a/lib/screens/v2/screen_audio_data.ex +++ b/lib/screens/v2/screen_audio_data.ex @@ -7,7 +7,7 @@ defmodule Screens.V2.ScreenAudioData do alias Screens.V2.ScreenData.Parameters alias Screens.V2.WidgetInstance alias ScreensConfig.Screen - alias ScreensConfig.V2.{Audio, BusShelter, GlEink, PreFare} + alias ScreensConfig.V2.{Audio, BusShelter, Busway, GlEink, PreFare} @type screen_id :: String.t() @@ -23,7 +23,7 @@ defmodule Screens.V2.ScreenAudioData do {:ok, now} = DateTime.shift_zone(now, "America/New_York") case config do - %Screen{app_params: %app{}} when app not in [BusShelter, PreFare, GlEink] -> + %Screen{app_params: %app{}} when app not in [BusShelter, PreFare, GlEink, Busway] -> :error %Screen{app_params: %_app{audio: audio}} -> diff --git a/lib/screens/v2/widget_instance/departures.ex b/lib/screens/v2/widget_instance/departures.ex index e310e87b1..edad87938 100644 --- a/lib/screens/v2/widget_instance/departures.ex +++ b/lib/screens/v2/widget_instance/departures.ex @@ -15,9 +15,7 @@ defmodule Screens.V2.WidgetInstance.Departures do alias ScreensConfig.V2.Departures.Layout alias ScreensConfig.V2.FreeTextLine - defstruct screen: nil, - section_data: [], - slot_names: [] + defstruct screen: nil, section_data: [], slot_names: [], now: nil @type normal_section :: %{ type: :normal_section, @@ -62,7 +60,8 @@ defmodule Screens.V2.WidgetInstance.Departures do | overnight_section() | no_data_section() ), - slot_names: list(atom()) + slot_names: list(atom()), + now: DateTime.t() } # The maximum number of departures to send back to the client. @@ -72,12 +71,12 @@ defmodule Screens.V2.WidgetInstance.Departures do defimpl Screens.V2.WidgetInstance do def priority(_instance), do: [2] - def serialize(%Departures{section_data: section_data, screen: screen}) do + def serialize(%Departures{section_data: section_data, screen: screen, now: now}) do %{ sections: Enum.map( section_data, - &Departures.serialize_section(&1, screen, length(section_data) == 1) + &Departures.serialize_section(&1, screen, now, length(section_data) == 1) ) } end @@ -91,8 +90,8 @@ defmodule Screens.V2.WidgetInstance.Departures do def valid_candidate?(_instance), do: true - def audio_serialize(%Departures{section_data: section_data, screen: screen}) do - %{sections: Enum.map(section_data, &Departures.audio_serialize_section(&1, screen))} + def audio_serialize(%Departures{section_data: section_data, screen: screen, now: now}) do + %{sections: Enum.map(section_data, &Departures.audio_serialize_section(&1, screen, now))} end def audio_sort_key(_instance), do: [1] @@ -102,13 +101,13 @@ defmodule Screens.V2.WidgetInstance.Departures do def audio_view(_instance), do: ScreensWeb.V2.Audio.DeparturesView end - def serialize_section(section, screen, is_only_section \\ false) + def serialize_section(section, screen, now, is_only_section \\ false) - def serialize_section(%{type: :notice_section, text: text}, _screen, _) do + def serialize_section(%{type: :notice_section, text: text}, _screen, _now, _) do %{type: :notice_section, text: text} end - def serialize_section(%{type: :no_data_section, route: route}, _screen, _) do + def serialize_section(%{type: :no_data_section, route: route}, _screen, _now, _) do text = %FreeTextLine{ icon: Route.icon(route), text: ["Updates unavailable"] @@ -120,6 +119,7 @@ defmodule Screens.V2.WidgetInstance.Departures do def serialize_section( %{type: :headway_section, route: route, time_range: {lo, hi}, headsign: headsign}, _screen, + _now, is_only_section ) do pill_color = Route.color(route) @@ -165,13 +165,14 @@ defmodule Screens.V2.WidgetInstance.Departures do def serialize_section( %{type: :normal_section, rows: departures, layout: layout, header: header}, screen, + now, _ ) do rows = departures |> Enum.take(@max_departures) |> group_consecutive_departures(screen) - |> Enum.map(&serialize_row(&1, screen)) + |> Enum.map(&serialize_row(&1, screen, now)) %{ type: :normal_section, @@ -181,7 +182,7 @@ defmodule Screens.V2.WidgetInstance.Departures do } end - def serialize_section(%{type: :overnight_section, routes: routes}, _, _) do + def serialize_section(%{type: :overnight_section, routes: routes}, _, _now, _) do route_pill = routes |> Enum.map(&Route.icon/1) @@ -199,11 +200,15 @@ defmodule Screens.V2.WidgetInstance.Departures do %{type: :overnight_section, text: FreeTextLine.to_json(text)} end - def audio_serialize_section(%{type: :notice_section, text: text}, _screen) do + def audio_serialize_section(%{type: :notice_section, text: text}, _screen, _now) do %{type: :notice_section, text: FreeTextLine.to_plaintext(text)} end - def audio_serialize_section(%{type: :normal_section, rows: departures, header: header}, screen) do + def audio_serialize_section( + %{type: :normal_section, rows: departures, header: header}, + screen, + now + ) do header = case header do %{read_as: header} when is_binary(header) -> header @@ -213,8 +218,8 @@ defmodule Screens.V2.WidgetInstance.Departures do serialized_departure_groups = departures - |> group_all_departures(2) - |> Enum.map(&audio_serialize_departure_group(&1, screen)) + |> group_all_departures(now, screen.app_id) + |> Enum.map(&audio_serialize_departure_group(&1, screen, now)) %{ type: :normal_section, @@ -223,12 +228,12 @@ defmodule Screens.V2.WidgetInstance.Departures do } end - defp audio_serialize_departure_group({:notice, %{text: text}}, _) do + defp audio_serialize_departure_group({:notice, %{text: text}}, _, _now) do {:notice, FreeTextLine.to_plaintext(text)} end - defp audio_serialize_departure_group({:normal, departures}, screen) do - {:normal, serialize_row(departures, screen, &RoutePill.serialize_for_audio_departure/4)} + defp audio_serialize_departure_group({:normal, departures}, screen, now) do + {:normal, serialize_row(departures, screen, now, &RoutePill.serialize_for_audio_departure/4)} end @doc """ @@ -258,19 +263,21 @@ defmodule Screens.V2.WidgetInstance.Departures do end) end - @doc """ - Groups all departures of the same route and headsign, limiting each group to `max_entries_per_group` entries. - `notice` rows are never grouped. + # Groups all departures of the same route and headsign. + # `notice` rows are never grouped. - The list is ordered by the occurrence of the _first_ departure of each group--later departures can "leap frog" - ahead of other ones of a different route/headsign if there's an earlier departure of the same route/headsign. - """ - @spec group_all_departures(list(Departure.t() | notice), integer) :: + # The list is ordered by the occurrence of the _first_ departure of each group--later departures can "leap frog" + # ahead of other ones of a different route/headsign if there's an earlier departure of the same route/headsign. + @spec group_all_departures( + list(Departure.t() | notice), + DateTime.t(), + Screen.app_id() + ) :: list( {:normal, list(Departure.t())} | {:notice, notice} ) - def group_all_departures(departures, max_entries_per_group) do + defp group_all_departures(departures, now, app_id) do departures |> Util.group_by_with_order(fn %{text: %FreeTextLine{}} -> make_ref() @@ -281,17 +288,33 @@ defmodule Screens.V2.WidgetInstance.Departures do {:notice, notice} {_key, departure_group} -> - {:normal, Enum.take(departure_group, max_entries_per_group)} + departures = + if app_id == :busway_v2 do + filter_departure_group(departure_group, now) + else + Enum.take(departure_group, 2) + end + + {:normal, departures} end) end + defp filter_departure_group([first_departure | _] = departure_group, now) do + if first_departure |> Departure.time() |> DateTime.diff(now, :minute) <= 2 do + Enum.take(departure_group, 2) + else + [first_departure] + end + end + defp serialize_row( departures_or_notice, screen, + now, route_pill_serializer \\ &RoutePill.serialize_for_departure/4 ) - defp serialize_row([%Departure{} | _] = departures, screen, route_pill_serializer) do + defp serialize_row([%Departure{} | _] = departures, screen, now, route_pill_serializer) do departure_id_string = departures |> Enum.map(&Departure.id/1) @@ -305,12 +328,12 @@ defmodule Screens.V2.WidgetInstance.Departures do type: :departure_row, route: serialize_route(departures, route_pill_serializer), headsign: serialize_headsign(departures, screen), - times_with_crowding: serialize_times_with_crowding(departures, screen), + times_with_crowding: serialize_times_with_crowding(departures, screen, now), inline_alerts: serialize_inline_alerts(departures) } end - defp serialize_row([%{text: %FreeTextLine{} = text}], _screen, _pill_serializer) do + defp serialize_row([%{text: %FreeTextLine{} = text}], _screen, _now, _pill_serializer) do %{ type: :notice_row, text: FreeTextLine.to_json(text) @@ -354,7 +377,7 @@ defmodule Screens.V2.WidgetInstance.Departures do %{headsign: headsign, variation: variation} end - def serialize_times_with_crowding(departures, screen, now \\ DateTime.utc_now()) do + def serialize_times_with_crowding(departures, screen, now) do Enum.map(departures, &serialize_time_with_crowding(&1, screen, now)) end diff --git a/lib/screens/v2/widget_instance/serializer/route_pill.ex b/lib/screens/v2/widget_instance/serializer/route_pill.ex index 888ab30f4..b396c6748 100644 --- a/lib/screens/v2/widget_instance/serializer/route_pill.ex +++ b/lib/screens/v2/widget_instance/serializer/route_pill.ex @@ -31,6 +31,7 @@ defmodule Screens.V2.WidgetInstance.Serializer.RoutePill do } @type audio_route :: %{ + id: Route.id(), route_text: String.t(), vehicle_type: :train | :bus | :trolley | :ferry | nil, track_number: pos_integer() | nil @@ -98,6 +99,7 @@ defmodule Screens.V2.WidgetInstance.Serializer.RoutePill do end %{ + id: route_id, route_text: route_name, vehicle_type: vehicle_type, track_number: track_number diff --git a/lib/screens_web/views/v2/audio/departures_view.ex b/lib/screens_web/views/v2/audio/departures_view.ex index 03618985a..a1650e8f7 100644 --- a/lib/screens_web/views/v2/audio/departures_view.ex +++ b/lib/screens_web/views/v2/audio/departures_view.ex @@ -64,8 +64,14 @@ defmodule ScreensWeb.V2.Audio.DeparturesView do ~E|<%= content %>| end - defp render_time_with_crowding({%{crowding: crowding, time: time}, _}, route, _headsign) do - route_headsign_rendered = render_route_headsign(route, nil) + defp render_time_with_crowding({%{crowding: crowding, time: time}, _}, route, headsign) do + route_headsign_rendered = + if String.starts_with?(route.id, "Green") do + render_route_headsign(route, headsign) + else + render_route_headsign(route, nil) + end + crowding_rendered = render_crowding_level(crowding) preposition = preposition_for_time_type(time.type) @@ -96,10 +102,14 @@ defmodule ScreensWeb.V2.Audio.DeparturesView do {route_text, &render_route/1}, {vehicle_type || "trip", fn v -> ~E|<%= v %>| end}, {headsign, fn h -> ~E|to <%= render_headsign(h) %>| end}, - {track_number, fn tn -> ~E|on track <%= tn %>| end} + {track_number, fn tn -> render_track_number(tn, vehicle_type) end} ]) end + defp render_track_number(nil, _), do: ~E"" + defp render_track_number(track_number, :bus), do: ~E|at berth <%= track_number %>| + defp render_track_number(track_number, _), do: ~E|on track <%= track_number %>| + defp render_route(route_text) do cond do String.contains?(route_text, "/") and match?([_, _], String.split(route_text, "/")) -> diff --git a/mix.exs b/mix.exs index 876f4b876..329df727a 100644 --- a/mix.exs +++ b/mix.exs @@ -86,7 +86,7 @@ defmodule Screens.MixProject do {:telemetry_metrics, "~> 0.4"}, {:screens_config, git: "https://github.com/mbta/screens-config-lib.git", - ref: "25fb47c58fc0b485c8c6df78fe94914292856903"}, + ref: "2c67758bca5ec61d08e4194aa19bf289cb4ec6ef"}, {:nebulex, "~> 2.6"}, {:remote_ip, "~> 1.2"}, {:hackney_telemetry, "~> 0.2.0"}, diff --git a/mix.lock b/mix.lock index dde705056..992dfd483 100644 --- a/mix.lock +++ b/mix.lock @@ -3,7 +3,7 @@ "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, "castore": {:hex, :castore, "1.0.8", "dedcf20ea746694647f883590b82d9e96014057aff1d44d03ec90f36a5c0dc6e", [:mix], [], "hexpm", "0b2b66d2ee742cb1d9cb8c8be3b43c3a70ee8651f37b75a8b982e036752983f1"}, "certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"}, - "cldr_utils": {:hex, :cldr_utils, "2.28.0", "ce309d11b79fc13e1f22f808b5e3c1647102b01b11734ca8cb0296ca6d406fe4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.5", [hex: :certifi, repo: "hexpm", optional: true]}, {:decimal, "~> 1.9 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "e7ac4bcea0fdbc11b5295ef30dd7b18d0922512399361af06a97198e57d23742"}, + "cldr_utils": {:hex, :cldr_utils, "2.28.2", "f500667164a9043369071e4f9dcef31f88b8589b2e2c07a1eb9f9fa53cb1dce9", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.5", [hex: :certifi, repo: "hexpm", optional: true]}, {:decimal, "~> 1.9 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "c506eb1a170ba7cdca59b304ba02a56795ed119856662f6b1a420af80ec42551"}, "combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"}, "connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"}, "corsica": {:hex, :corsica, "2.1.3", "dccd094ffce38178acead9ae743180cdaffa388f35f0461ba1e8151d32e190e6", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "616c08f61a345780c2cf662ff226816f04d8868e12054e68963e95285b5be8bc"}, @@ -13,24 +13,22 @@ "credo": {:hex, :credo, "1.7.7", "771445037228f763f9b2afd612b6aa2fd8e28432a95dbbc60d8e03ce71ba4446", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8bc87496c9aaacdc3f90f01b7b0582467b69b4bd2441fe8aae3109d843cc2f2e"}, "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "dialyxir": {:hex, :dialyxir, "1.4.3", "edd0124f358f0b9e95bfe53a9fcf806d615d8f838e2202a9f430d59566b6b53b", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "bf2cfb75cd5c5006bec30141b131663299c661a864ec7fbbc72dfa557487a986"}, - "digital_token": {:hex, :digital_token, "0.6.0", "13e6de581f0b1f6c686f7c7d12ab11a84a7b22fa79adeb4b50eec1a2d278d258", [:mix], [{:cldr_utils, "~> 2.17", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "2455d626e7c61a128b02a4a8caddb092548c3eb613ac6f6a85e4cbb6caddc4d1"}, + "digital_token": {:hex, :digital_token, "1.0.0", "454a4444061943f7349a51ef74b7fb1ebd19e6a94f43ef711f7dae88c09347df", [:mix], [{:cldr_utils, "~> 2.17", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "8ed6f5a8c2fa7b07147b9963db506a1b4c7475d9afca6492136535b064c9e9e6"}, "ehmon": {:git, "https://github.com/mbta/ehmon.git", "1fb603262bd02d74a16183bd8f344dcace9d7561", []}, "erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"}, "ex_aws": {:hex, :ex_aws, "2.5.5", "5dc378eff99c3c46c917b7a96a75ad0d4c300ab7250df668d0819bcd18c0213d", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8 or ~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:mime, "~> 1.2 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:req, "~> 0.3", [hex: :req, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ed7ee39c56012c56600e021953c6487ecce9c49320ec3b4655a15d785f221ca6"}, "ex_aws_polly": {:hex, :ex_aws_polly, "0.5.0", "277662ce3f4203eef352ae0ea37df1feb54c291d8717cc6c241575e25c861c4c", [:mix], [{:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: false]}], "hexpm", "a021192995409c103b927c75d1d1d2e892f2bb23a0c0063bc85355907b600ca3"}, "ex_aws_s3": {:hex, :ex_aws_s3, "2.5.4", "87aaf4a2f24a48f516d7f5aaced9d128dd5d0f655c4431f9037a11a85c71109c", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "c06e7f68b33f7c0acba1361dbd951c79661a28f85aa2e0582990fccca4425355"}, - "ex_cldr": {:hex, :ex_cldr, "2.39.2", "4a3a77797da8f900369822ea9353adfa035a5bbbbfff09b2d3d1b6fa461768e3", [:mix], [{:cldr_utils, "~> 2.25", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:gettext, "~> 0.19", [hex: :gettext, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: true]}], "hexpm", "02fd8913ef28d1b2a4190fd8016c2dec1f2291c9ce56c17d7649848c0261a6eb"}, - "ex_cldr_currencies": {:hex, :ex_cldr_currencies, "2.16.1", "29317f533cb5ec046d04523256cca4090291e9157028f28731395149b06ff8b2", [:mix], [{:ex_cldr, "~> 2.38", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "095d5e973bf0ee066dd1153990d10cb6fa6d8ff0e028295bdce7a7821c70a0e4"}, + "ex_cldr": {:hex, :ex_cldr, "2.40.1", "c1fcb0cd9d2a70d28f4540a99f32127e7f1813e0db109d65ab29dea5337ae266", [:mix], [{:cldr_utils, "~> 2.28", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:gettext, "~> 0.19", [hex: :gettext, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: true]}], "hexpm", "509810702e8e81991851d9426ffe6b34b48b7b9baa12922e7b3fb8f6368606f3"}, + "ex_cldr_currencies": {:hex, :ex_cldr_currencies, "2.16.3", "1ec6444b5d0c0aabba5a3bc321d73f1c9c751c6add92e7fb7775ccc071d96bd8", [:mix], [{:ex_cldr, "~> 2.38", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "4d1b5f8449fdf0ece6a2e5c7401ad8fcfde77ee6ea480bddc16e266dfa2b570c"}, "ex_cldr_messages": {:hex, :ex_cldr_messages, "1.0.2", "9909829e8cdb4eeb6d5b4dbe76b8e07ae39d2d2254fb943ff74dd9ace55a9120", [:mix], [{:ex_cldr_dates_times, "~> 2.13", [hex: :ex_cldr_dates_times, repo: "hexpm", optional: true]}, {:ex_cldr_lists, "~> 2.10", [hex: :ex_cldr_lists, repo: "hexpm", optional: true]}, {:ex_cldr_numbers, "~> 2.28", [hex: :ex_cldr_numbers, repo: "hexpm", optional: false]}, {:ex_cldr_units, "~> 3.12", [hex: :ex_cldr_units, repo: "hexpm", optional: true]}, {:ex_doc, "~> 0.20", [hex: :ex_doc, repo: "hexpm", optional: true]}, {:ex_money, "~> 5.9", [hex: :ex_money, repo: "hexpm", optional: true]}, {:gettext, "~> 0.19", [hex: :gettext, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "3805a92f5ff64ee951f3a0174a85221af0117276ac794638df25b845edf431fa"}, - "ex_cldr_numbers": {:hex, :ex_cldr_numbers, "2.33.1", "49dc6e77e6d9ad22660aaa2480a7408ad3aedfbe517e4e83e5fe3a7bf5345770", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:digital_token, "~> 0.3 or ~> 1.0", [hex: :digital_token, repo: "hexpm", optional: false]}, {:ex_cldr, "~> 2.38", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_currencies, "~> 2.16", [hex: :ex_cldr_currencies, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "c003bfaa3fdee6bab5195f128b94038c2ce1cf4879a759eef431dd075d9a5dac"}, - "expo": {:hex, :expo, "1.0.1", "f9e2f984f5b8d195815d52d0ba264798c12c8d2f2606f76fa4c60e8ebe39474d", [:mix], [], "hexpm", "f250b33274e3e56513644858c116f255d35c767c2b8e96a512fe7839ef9306a1"}, - "file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"}, - "gen_stage": {:hex, :gen_stage, "1.2.1", "19d8b5e9a5996d813b8245338a28246307fd8b9c99d1237de199d21efc4c76a1", [:mix], [], "hexpm", "83e8be657fa05b992ffa6ac1e3af6d57aa50aace8f691fcf696ff02f8335b001"}, + "ex_cldr_numbers": {:hex, :ex_cldr_numbers, "2.33.3", "9fedcf279a17d19abdf8872738472326e82378d90ec2dd9756a0c84558c86b36", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:digital_token, "~> 0.3 or ~> 1.0", [hex: :digital_token, repo: "hexpm", optional: false]}, {:ex_cldr, "~> 2.38", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_currencies, "~> 2.16", [hex: :ex_cldr_currencies, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "4a0d90d06710c1499528d5f536c539379a73a68d4679c55375198a798d138442"}, + "expo": {:hex, :expo, "1.1.0", "f7b9ed7fb5745ebe1eeedf3d6f29226c5dd52897ac67c0f8af62a07e661e5c75", [:mix], [], "hexpm", "fbadf93f4700fb44c331362177bdca9eeb8097e8b0ef525c9cc501cb9917c960"}, + "file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"}, "gettext": {:hex, :gettext, "0.26.1", "38e14ea5dcf962d1fc9f361b63ea07c0ce715a8ef1f9e82d3dfb8e67e0416715", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "01ce56f188b9dc28780a52783d6529ad2bc7124f9744e571e1ee4ea88bf08734"}, "guardian": {:hex, :guardian, "2.3.2", "78003504b987f2b189d76ccf9496ceaa6a454bb2763627702233f31eb7212881", [:mix], [{:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "b189ff38cd46a22a8a824866a6867ca8722942347f13c33f7d23126af8821b52"}, "hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"}, "hackney_telemetry": {:hex, :hackney_telemetry, "0.2.0", "111d982254cb89b2314c7e2a502fd48f69b7503780ab963ad2934e0f6b483a97", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5dad525dcf50374171c8972a5ff9c7e474195208f257e82bd04d36a56de8061d"}, - "hpax": {:hex, :hpax, "1.0.0", "28dcf54509fe2152a3d040e4e3df5b265dcb6cb532029ecbacf4ce52caea3fd2", [:mix], [], "hexpm", "7f1314731d711e2ca5fdc7fd361296593fc2542570b3105595bb0bc6d0fad601"}, "httpoison": {:hex, :httpoison, "2.2.1", "87b7ed6d95db0389f7df02779644171d7319d319178f6680438167d7b69b1f3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "51364e6d2f429d80e14fe4b5f8e39719cacd03eb3f9a9286e61e216feac2d2df"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, @@ -40,13 +38,12 @@ "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"}, "mimerl": {:hex, :mimerl, "1.3.0", "d0cd9fc04b9061f82490f6581e0128379830e78535e017f7780f37fea7545726", [:rebar3], [], "hexpm", "a1e15a50d1887217de95f0b9b0793e32853f7c258a5cd227650889b38839fe9d"}, - "mint": {:hex, :mint, "1.6.2", "af6d97a4051eee4f05b5500671d47c3a67dac7386045d87a904126fd4bbcea2e", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "5ee441dffc1892f1ae59127f74afe8fd82fda6587794278d924e4d90ea3d63f9"}, "mix_test_watch": {:hex, :mix_test_watch, "1.2.0", "1f9acd9e1104f62f280e30fc2243ae5e6d8ddc2f7f4dc9bceb454b9a41c82b42", [:mix], [{:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "278dc955c20b3fb9a3168b5c2493c2e5cffad133548d307e0a50c7f2cfbf34f6"}, "nebulex": {:hex, :nebulex, "2.6.3", "78af348ed9f8a338871b41e0b6de718c1808e627ce03fbe86598cbda2bdda2f5", [:mix], [{:decorator, "~> 1.4", [hex: :decorator, repo: "hexpm", optional: true]}, {:shards, "~> 1.1", [hex: :shards, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "09cdcbb62f8463ffcec7cae4936425ce91e25d92a6cd37e48b5dda7c851958d5"}, "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"}, "nimble_ownership": {:hex, :nimble_ownership, "1.0.0", "3f87744d42c21b2042a0aa1d48c83c77e6dd9dd357e425a038dd4b49ba8b79a1", [:mix], [], "hexpm", "7c16cc74f4e952464220a73055b557a273e8b1b7ace8489ec9d86e9ad56cb2cc"}, "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"}, - "oidcc": {:hex, :oidcc, "3.2.0", "f80a4826a946ce07dc8cbd8212392b4ff436ae3c4b4cd6680fa0d84d0ff2fec1", [:mix, :rebar3], [{:jose, "~> 1.11", [hex: :jose, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.2", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_registry, "~> 0.3.1", [hex: :telemetry_registry, repo: "hexpm", optional: false]}], "hexpm", "38fd9092ab5d5d10c71b8011b019316411afe466bef07ba57f57ec3f919278c3"}, + "oidcc": {:hex, :oidcc, "3.2.4", "0bbe0f6059682dcb3bb70f682ede606779ea7b73337803a05c7d8eb3ae76acc0", [:mix, :rebar3], [{:jose, "~> 1.11", [hex: :jose, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.2", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_registry, "~> 0.3.1", [hex: :telemetry_registry, repo: "hexpm", optional: false]}], "hexpm", "984956348f6f833577b7a6cb72b325936cab3fd1c9cf28d7d54773d3ea48a20a"}, "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "phoenix": {:hex, :phoenix, "1.7.14", "a7d0b3f1bc95987044ddada111e77bd7f75646a08518942c72a8440278ae7825", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "c7859bc56cc5dfef19ecfc240775dae358cbaa530231118a9e014df392ace61a"}, "phoenix_html": {:hex, :phoenix_html, "4.1.1", "4c064fd3873d12ebb1388425a8f2a19348cef56e7289e1998e2d2fa758aa982e", [:mix], [], "hexpm", "f2f2df5a72bc9a2f510b21497fd7d2b86d932ec0598f0210fed4114adc546c6f"}, @@ -63,7 +60,7 @@ "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, "remote_ip": {:hex, :remote_ip, "1.2.0", "fb078e12a44414f4cef5a75963c33008fe169b806572ccd17257c208a7bc760f", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "2ff91de19c48149ce19ed230a81d377186e4412552a597d6a5137373e5877cb7"}, "retry": {:hex, :retry, "0.18.0", "dc58ebe22c95aa00bc2459f9e0c5400e6005541cf8539925af0aa027dc860543", [:mix], [], "hexpm", "9483959cc7bf69c9e576d9dfb2b678b71c045d3e6f39ab7c9aa1489df4492d73"}, - "screens_config": {:git, "https://github.com/mbta/screens-config-lib.git", "25fb47c58fc0b485c8c6df78fe94914292856903", [ref: "25fb47c58fc0b485c8c6df78fe94914292856903"]}, + "screens_config": {:git, "https://github.com/mbta/screens-config-lib.git", "2c67758bca5ec61d08e4194aa19bf289cb4ec6ef", [ref: "2c67758bca5ec61d08e4194aa19bf289cb4ec6ef"]}, "sentry": {:hex, :sentry, "10.7.1", "33392222d80ccff99c503f972998d2858b4c1e5aca2219a34269b68dacba8e7d", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_ownership, "~> 0.3.0 or ~> 1.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "56291312397bf2b6afab6cf4f7aa1f27413b0eb2ceeb63b8aab2d7658aaea882"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, "stream_data": {:hex, :stream_data, "1.1.1", "fd515ca95619cca83ba08b20f5e814aaf1e5ebff114659dc9731f966c9226246", [:mix], [], "hexpm", "45d0cd46bd06738463fd53f22b70042dbb58c384bb99ef4e7576e7bb7d3b8c8c"}, diff --git a/test/screens/v2/candidate_generator/bus_eink_test.exs b/test/screens/v2/candidate_generator/bus_eink_test.exs index 9ba9d6533..ba409599a 100644 --- a/test/screens/v2/candidate_generator/bus_eink_test.exs +++ b/test/screens/v2/candidate_generator/bus_eink_test.exs @@ -54,7 +54,7 @@ defmodule Screens.V2.CandidateGenerator.BusEinkTest do describe "candidate_instances/3" do test "returns expected header", %{config: config} do - departures_instances_fn = fn _ -> [] end + departures_instances_fn = fn _, _ -> [] end alerts_instances_fn = fn _ -> [] end fetch_stop_fn = fn "1722" -> "1624 Blue Hill Ave @ Mattapan Sq" end now = ~U[2020-04-06T10:00:00Z] diff --git a/test/screens/v2/candidate_generator/bus_shelter_test.exs b/test/screens/v2/candidate_generator/bus_shelter_test.exs index 0c7c92961..66c74e0c0 100644 --- a/test/screens/v2/candidate_generator/bus_shelter_test.exs +++ b/test/screens/v2/candidate_generator/bus_shelter_test.exs @@ -74,7 +74,7 @@ defmodule Screens.V2.CandidateGenerator.BusShelterTest do describe "candidate_instances/3" do test "returns expected header and footer", %{config: config} do - departures_instances_fn = fn _ -> [] end + departures_instances_fn = fn _, _ -> [] end alert_instances_fn = fn _ -> [] end fetch_stop_fn = fn "1216" -> "Columbus Ave @ Dimock St" end now = ~U[2020-04-06T10:00:00Z] @@ -111,7 +111,7 @@ defmodule Screens.V2.CandidateGenerator.BusShelterTest do config = put_in(config.app_params.header, %V2.Header.CurrentStopName{stop_name: "Walnut Ave"}) - departures_instances_fn = fn _ -> [] end + departures_instances_fn = fn _, _ -> [] end alert_instances_fn = fn _ -> [] end fetch_stop_fn = fn "1216" -> raise "This should not be called!" end now = ~U[2020-04-06T10:00:00Z] diff --git a/test/screens/v2/candidate_generator/busway_test.exs b/test/screens/v2/candidate_generator/busway_test.exs index 2d35ee7e0..09219078f 100644 --- a/test/screens/v2/candidate_generator/busway_test.exs +++ b/test/screens/v2/candidate_generator/busway_test.exs @@ -17,7 +17,7 @@ defmodule Screens.V2.CandidateGenerator.BuswayTest do app_id: :solari_test_v2 } - deps = %Busway.Deps{departures_instances: fn _ -> [] end} + deps = %Busway.Deps{departures_instances: fn _, _ -> [] end} %{config: config, deps: deps} end @@ -44,7 +44,7 @@ defmodule Screens.V2.CandidateGenerator.BuswayTest do test "includes departures instances", %{config: config, deps: deps} do no_data = %DeparturesNoData{screen: config, show_alternatives?: true} - deps = struct!(deps, departures_instances: fn ^config -> [no_data] end) + deps = struct!(deps, departures_instances: fn ^config, _ -> [no_data] end) assert no_data in Busway.candidate_instances(config, [], deps) end diff --git a/test/screens/v2/candidate_generator/dup/departures_test.exs b/test/screens/v2/candidate_generator/dup/departures_test.exs index 597065a12..9f55ca079 100644 --- a/test/screens/v2/candidate_generator/dup/departures_test.exs +++ b/test/screens/v2/candidate_generator/dup/departures_test.exs @@ -347,7 +347,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_zero] + slot_names: [:main_content_zero], + now: now }, %DeparturesWidget{ screen: config, @@ -397,7 +398,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_one] + slot_names: [:main_content_one], + now: now }, %DeparturesWidget{ screen: config, @@ -437,7 +439,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_two] + slot_names: [:main_content_two], + now: now } ] @@ -520,7 +523,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_zero] + slot_names: [:main_content_zero], + now: now }, %DeparturesWidget{ screen: config, @@ -570,7 +574,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_one] + slot_names: [:main_content_one], + now: now }, %DeparturesWidget{ screen: config, @@ -620,7 +625,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_two] + slot_names: [:main_content_two], + now: now } ] @@ -706,7 +712,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_zero] + slot_names: [:main_content_zero], + now: now }, %DeparturesWidget{ screen: config, @@ -756,7 +763,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_one] + slot_names: [:main_content_one], + now: now }, %DeparturesWidget{ screen: config, @@ -806,7 +814,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_two] + slot_names: [:main_content_two], + now: now } ] @@ -864,7 +873,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_zero] + slot_names: [:main_content_zero], + now: now }, %DeparturesWidget{ screen: config, @@ -887,7 +897,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_one] + slot_names: [:main_content_one], + now: now }, %DeparturesWidget{ screen: config, @@ -910,7 +921,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_two] + slot_names: [:main_content_two], + now: now } ] @@ -998,7 +1010,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_zero] + slot_names: [:main_content_zero], + now: now }, %DeparturesWidget{ screen: config, @@ -1051,7 +1064,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_one] + slot_names: [:main_content_one], + now: now }, %DeparturesWidget{ screen: config, @@ -1104,7 +1118,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_two] + slot_names: [:main_content_two], + now: now } ] @@ -1168,7 +1183,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do headsign: "Test A" } ], - slot_names: [:main_content_zero] + slot_names: [:main_content_zero], + now: now }, %DeparturesWidget{ screen: config, @@ -1180,7 +1196,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do headsign: "Test A" } ], - slot_names: [:main_content_one] + slot_names: [:main_content_one], + now: now }, %DeparturesWidget{ screen: config, @@ -1192,7 +1209,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do headsign: "Test A" } ], - slot_names: [:main_content_two] + slot_names: [:main_content_two], + now: now } ] @@ -1298,7 +1316,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_zero] + slot_names: [:main_content_zero], + now: now }, %DeparturesWidget{ screen: config, @@ -1351,7 +1370,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_one] + slot_names: [:main_content_one], + now: now }, %DeparturesWidget{ screen: config, @@ -1404,7 +1424,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_two] + slot_names: [:main_content_two], + now: now } ] @@ -1521,7 +1542,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_zero] + slot_names: [:main_content_zero], + now: now }, %DeparturesWidget{ screen: config, @@ -1544,7 +1566,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_one] + slot_names: [:main_content_one], + now: now }, %DeparturesWidget{ screen: config, @@ -1567,7 +1590,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_two] + slot_names: [:main_content_two], + now: now } ] @@ -1659,7 +1683,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do headsign: "Westbound" } ], - slot_names: [:main_content_reduced_zero] + slot_names: [:main_content_reduced_zero], + now: now }, %DeparturesWidget{ screen: config, @@ -1671,7 +1696,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do headsign: "Westbound" } ], - slot_names: [:main_content_reduced_one] + slot_names: [:main_content_reduced_one], + now: now }, %DeparturesWidget{ screen: config, @@ -1683,7 +1709,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do headsign: "Westbound" } ], - slot_names: [:main_content_reduced_two] + slot_names: [:main_content_reduced_two], + now: now } ] @@ -1757,7 +1784,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_zero] + slot_names: [:main_content_zero], + now: now }, %DeparturesWidget{ screen: config, @@ -1784,7 +1812,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_one] + slot_names: [:main_content_one], + now: now }, %DeparturesWidget{ screen: config, @@ -1811,7 +1840,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do route: %{id: "Green", type: :light_rail} } ], - slot_names: [:main_content_two] + slot_names: [:main_content_two], + now: now } ] @@ -1941,7 +1971,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_zero] + slot_names: [:main_content_zero], + now: now }, %DeparturesWidget{ screen: config, @@ -1964,7 +1995,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_one] + slot_names: [:main_content_one], + now: now }, %DeparturesWidget{ screen: config, @@ -1996,7 +2028,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_two] + slot_names: [:main_content_two], + now: now } ] @@ -2074,7 +2107,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_zero] + slot_names: [:main_content_zero], + now: now }, %DeparturesWidget{ screen: config, @@ -2097,7 +2131,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_one] + slot_names: [:main_content_one], + now: now }, %DeparturesWidget{ screen: config, @@ -2129,7 +2164,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_two] + slot_names: [:main_content_two], + now: now } ] @@ -2194,21 +2230,24 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do section_data: [ %{layout: %Layout{}, header: %SectionHeader{}, rows: [], type: :normal_section} ], - slot_names: [:main_content_zero] + slot_names: [:main_content_zero], + now: now }, %DeparturesWidget{ screen: config, section_data: [ %{layout: %Layout{}, header: %SectionHeader{}, rows: [], type: :normal_section} ], - slot_names: [:main_content_one] + slot_names: [:main_content_one], + now: now }, %DeparturesWidget{ screen: config, section_data: [ %{layout: %Layout{}, header: %SectionHeader{}, rows: [], type: :normal_section} ], - slot_names: [:main_content_two] + slot_names: [:main_content_two], + now: now } ] @@ -2265,21 +2304,24 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do section_data: [ %{layout: %Layout{}, header: %SectionHeader{}, rows: [], type: :normal_section} ], - slot_names: [:main_content_zero] + slot_names: [:main_content_zero], + now: now }, %DeparturesWidget{ screen: config, section_data: [ %{layout: %Layout{}, header: %SectionHeader{}, rows: [], type: :normal_section} ], - slot_names: [:main_content_one] + slot_names: [:main_content_one], + now: now }, %DeparturesWidget{ screen: config, section_data: [ %{layout: %Layout{}, header: %SectionHeader{}, rows: [], type: :normal_section} ], - slot_names: [:main_content_two] + slot_names: [:main_content_two], + now: now } ] @@ -2364,7 +2406,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_zero] + slot_names: [:main_content_zero], + now: now }, %DeparturesWidget{ screen: config, @@ -2387,7 +2430,8 @@ defmodule Screens.V2.CandidateGenerator.Dup.DeparturesTest do ] } ], - slot_names: [:main_content_one] + slot_names: [:main_content_one], + now: now }, %OvernightDepartures{screen: config, routes: [:bus], slot_names: [:main_content_two]} ] diff --git a/test/screens/v2/candidate_generator/solari_large_test.exs b/test/screens/v2/candidate_generator/solari_large_test.exs index b2b3b2c8f..e4c1c776c 100644 --- a/test/screens/v2/candidate_generator/solari_large_test.exs +++ b/test/screens/v2/candidate_generator/solari_large_test.exs @@ -32,7 +32,7 @@ defmodule Screens.V2.CandidateGenerator.SolariLargeTest do describe "candidate_instances/2" do test "returns expected header", %{config: config} do - departures_instances_fn = fn _ -> [] end + departures_instances_fn = fn _, _ -> [] end now = ~U[2020-04-06T10:00:00Z] opts = [] diff --git a/test/screens/v2/candidate_generator/widgets/departures_test.exs b/test/screens/v2/candidate_generator/widgets/departures_test.exs index 19f4e7d7a..afeafdd09 100644 --- a/test/screens/v2/candidate_generator/widgets/departures_test.exs +++ b/test/screens/v2/candidate_generator/widgets/departures_test.exs @@ -31,7 +31,7 @@ defmodule Screens.V2.CandidateGenerator.Widgets.DeparturesTest do } end - describe "departures_instances/1" do + describe "departures_instances/3" do defp build_config(section_route_ids) do %Screen{ app_params: %BusShelter{ @@ -62,6 +62,7 @@ defmodule Screens.V2.CandidateGenerator.Widgets.DeparturesTest do defp departures_instances(config, options) do Departures.departures_instances( config, + nil, Keyword.merge( [ departure_fetch_fn: fn _, _ -> :error end, diff --git a/test/screens/v2/widget_instance/departures_test.exs b/test/screens/v2/widget_instance/departures_test.exs index e23b726b6..cb36cef76 100644 --- a/test/screens/v2/widget_instance/departures_test.exs +++ b/test/screens/v2/widget_instance/departures_test.exs @@ -24,7 +24,7 @@ defmodule Screens.V2.WidgetInstance.DeparturesTest do end end - describe "serialize_section/2" do + describe "serialize_section/3" do setup do %{ bus_shelter_screen: %Screen{ @@ -33,19 +33,21 @@ defmodule Screens.V2.WidgetInstance.DeparturesTest do device_id: "TEST", name: "TEST", app_params: nil - } + }, + now: ~U[2020-01-01T00:00:00Z] } end - test "returns serialized normal_section", %{bus_shelter_screen: bus_shelter_screen} do + test "returns serialized normal_section", %{bus_shelter_screen: bus_shelter_screen, now: now} do section = %{type: :normal_section, rows: [], layout: %Layout{}, header: %Header{}} assert %{type: :normal_section, rows: []} = - Departures.serialize_section(section, bus_shelter_screen) + Departures.serialize_section(section, bus_shelter_screen, now) end test "returns serialized normal_section with a header if a header exists", %{ - bus_shelter_screen: bus_shelter_screen + bus_shelter_screen: bus_shelter_screen, + now: now } do section = %{ type: :normal_section, @@ -61,18 +63,19 @@ defmodule Screens.V2.WidgetInstance.DeparturesTest do assert %{ type: :normal_section, header: %{title: "Simple Test Header", arrow: :n, read_as: "Special read-as text"} - } = Departures.serialize_section(section, bus_shelter_screen) + } = Departures.serialize_section(section, bus_shelter_screen, now) end - test "returns serialized notice_section", %{bus_shelter_screen: bus_shelter_screen} do + test "returns serialized notice_section", %{bus_shelter_screen: bus_shelter_screen, now: now} do section = %{type: :notice_section, text: %{icon: :warning, text: []}} assert %{type: :notice_section, text: %{icon: :warning, text: []}} == - Departures.serialize_section(section, bus_shelter_screen) + Departures.serialize_section(section, bus_shelter_screen, now) end test "returns serialized normal_section with notice", %{ - bus_shelter_screen: bus_shelter_screen + bus_shelter_screen: bus_shelter_screen, + now: now } do section = %{ type: :normal_section, @@ -82,11 +85,11 @@ defmodule Screens.V2.WidgetInstance.DeparturesTest do } assert %{type: :normal_section, rows: [%{type: :notice_row, text: %{icon: nil, text: []}}]} = - Departures.serialize_section(section, bus_shelter_screen) + Departures.serialize_section(section, bus_shelter_screen, now) end end - describe "serialize_section/3" do + describe "serialize_section/4" do setup do %{ dup_screen: %Screen{ @@ -95,12 +98,14 @@ defmodule Screens.V2.WidgetInstance.DeparturesTest do device_id: "TEST", name: "TEST", app_params: nil - } + }, + now: ~U[2020-01-01T00:00:00Z] } end test "returns serialized normal_section for section with row with no scheduled time", %{ - dup_screen: dup_screen + dup_screen: dup_screen, + now: now } do section = %{ type: :normal_section, @@ -138,11 +143,12 @@ defmodule Screens.V2.WidgetInstance.DeparturesTest do ], type: :normal_section } = - Departures.serialize_section(section, dup_screen, true) + Departures.serialize_section(section, dup_screen, now, true) end test "returns serialized headway_section for one configured section", %{ - dup_screen: dup_screen + dup_screen: dup_screen, + now: now } do section = %{type: :headway_section, route: "Red", time_range: {1, 2}, headsign: "Test"} @@ -158,12 +164,13 @@ defmodule Screens.V2.WidgetInstance.DeparturesTest do } assert %{type: :headway_section, text: expected_text, layout: :full_screen} == - Departures.serialize_section(section, dup_screen, true) + Departures.serialize_section(section, dup_screen, now, true) end test "returns serialized headway_section for one configured section with Ashmont/Braintree headsign", %{ - dup_screen: dup_screen + dup_screen: dup_screen, + now: now } do section = %{ type: :headway_section, @@ -183,11 +190,12 @@ defmodule Screens.V2.WidgetInstance.DeparturesTest do } assert %{type: :headway_section, text: expected_text, layout: :full_screen} == - Departures.serialize_section(section, dup_screen, true) + Departures.serialize_section(section, dup_screen, now, true) end test "returns serialized headway_section for multiple configured sections", %{ - dup_screen: dup_screen + dup_screen: dup_screen, + now: now } do section = %{type: :headway_section, route: "Red", time_range: {1, 2}, headsign: "Test"} @@ -197,11 +205,12 @@ defmodule Screens.V2.WidgetInstance.DeparturesTest do } assert %{type: :headway_section, text: expected_text, layout: :row} == - Departures.serialize_section(section, dup_screen, false) + Departures.serialize_section(section, dup_screen, now, false) end test "returns serialized no_data_section for subway/light rail", %{ - dup_screen: dup_screen + dup_screen: dup_screen, + now: now } do section = %{type: :no_data_section, route: %{id: "Orange", type: :subway}} @@ -211,7 +220,7 @@ defmodule Screens.V2.WidgetInstance.DeparturesTest do } assert %{type: :no_data_section, text: expected_text} == - Departures.serialize_section(section, dup_screen, true) + Departures.serialize_section(section, dup_screen, now, true) section = %{type: :no_data_section, route: %{id: "Green", type: :light_rail}} @@ -221,11 +230,12 @@ defmodule Screens.V2.WidgetInstance.DeparturesTest do } assert %{type: :no_data_section, text: expected_text} == - Departures.serialize_section(section, dup_screen, true) + Departures.serialize_section(section, dup_screen, now, true) end test "returns serialized no_data_section for bus", %{ - dup_screen: dup_screen + dup_screen: dup_screen, + now: now } do section = %{type: :no_data_section, route: %{id: "555", type: :bus}} @@ -235,11 +245,12 @@ defmodule Screens.V2.WidgetInstance.DeparturesTest do } assert %{type: :no_data_section, text: expected_text} == - Departures.serialize_section(section, dup_screen, true) + Departures.serialize_section(section, dup_screen, now, true) end test "returns serialized no_data_section for SL", %{ - dup_screen: dup_screen + dup_screen: dup_screen, + now: now } do section = %{type: :no_data_section, route: %{short_name: "SL1", type: :bus}} @@ -249,11 +260,12 @@ defmodule Screens.V2.WidgetInstance.DeparturesTest do } assert %{type: :no_data_section, text: expected_text} == - Departures.serialize_section(section, dup_screen, true) + Departures.serialize_section(section, dup_screen, now, true) end test "returns serialized no_data_section for CR", %{ - dup_screen: dup_screen + dup_screen: dup_screen, + now: now } do section = %{type: :no_data_section, route: %{id: "CR-Test", type: :rail}} @@ -263,7 +275,7 @@ defmodule Screens.V2.WidgetInstance.DeparturesTest do } assert %{type: :no_data_section, text: expected_text} == - Departures.serialize_section(section, dup_screen, true) + Departures.serialize_section(section, dup_screen, now, true) end end @@ -928,7 +940,7 @@ defmodule Screens.V2.WidgetInstance.DeparturesTest do end end - describe "audio_serialize_section/2" do + describe "audio_serialize_section/3" do test "can serialize a :normal_section" do section = %{ type: :normal_section, @@ -936,11 +948,15 @@ defmodule Screens.V2.WidgetInstance.DeparturesTest do header: %Header{title: "Section Header"} } + screen = struct(Screen, %{app_id: :gl_eink_v2}) + + now = ~U[2020-01-01T00:00:00Z] + assert %{ type: :normal_section, departure_groups: [], header: "Section Header" - } = Departures.audio_serialize_section(section, nil) + } = Departures.audio_serialize_section(section, screen, now) end test "uses the `read_as` header property if available" do @@ -950,11 +966,190 @@ defmodule Screens.V2.WidgetInstance.DeparturesTest do header: %Header{title: "Section Header", read_as: "A special audio-only value"} } + screen = struct(Screen, %{app_id: :gl_eink_v2}) + + now = ~U[2020-01-01T00:00:00Z] + assert %{ type: :normal_section, departure_groups: [], header: "A special audio-only value" - } = Departures.audio_serialize_section(section, nil) + } = + Departures.audio_serialize_section( + section, + screen, + now + ) + end + + test "busway_v2 return 1 departure time if first departure is > 2 minutes away" do + now = ~U[2020-01-01T00:00:00Z] + + section = %{ + type: :normal_section, + rows: [ + %Departure{ + prediction: %Prediction{ + arrival_time: ~U[2020-01-01T00:05:00Z], + route: %Route{type: :subway}, + trip: %Trip{headsign: "Test"}, + stop: %Stop{id: "place-test"} + } + }, + %Departure{ + prediction: %Prediction{ + arrival_time: ~U[2020-01-01T02:01:00Z], + route: %Route{type: :subway}, + trip: %Trip{headsign: "Test"}, + stop: %Stop{id: "place-test"} + } + } + ], + header: %Header{title: "Section Header"} + } + + screen = struct(Screen, %{app_id: :busway_v2}) + + assert %{ + type: :normal_section, + departure_groups: [ + {:normal, + %{ + id: "1B2M2Y8AsgTpgAmY7PhCfg==", + type: :departure_row, + headsign: %{headsign: "Test", variation: nil}, + route: %{track_number: nil, vehicle_type: :train, route_text: nil}, + times_with_crowding: [ + %{id: nil, time: %{type: :minutes, minutes: 5}, crowding: nil} + ], + inline_alerts: [] + }} + ], + header: "Section Header" + } = Departures.audio_serialize_section(section, screen, now) + end + + test "busway_v2 return 2 departure times if first departure is <= 2 minutes away" do + now = ~U[2020-01-01T00:00:00Z] + + section = %{ + type: :normal_section, + rows: [ + %Departure{ + prediction: %Prediction{ + arrival_time: ~U[2020-01-01T00:01:00Z], + route: %Route{type: :subway}, + trip: %Trip{headsign: "Test"}, + stop: %Stop{id: "place-test"} + } + }, + %Departure{ + prediction: %Prediction{ + arrival_time: ~U[2020-01-01T00:02:00Z], + route: %Route{type: :subway}, + trip: %Trip{headsign: "Test"}, + stop: %Stop{id: "place-test"} + } + } + ], + header: %Header{title: "Section Header"} + } + + screen = struct(Screen, %{app_id: :busway_v2}) + + assert %{ + type: :normal_section, + departure_groups: [ + {:normal, + %{ + id: "1B2M2Y8AsgTpgAmY7PhCfg==", + type: :departure_row, + headsign: %{headsign: "Test", variation: nil}, + route: %{track_number: nil, vehicle_type: :train, route_text: nil}, + times_with_crowding: [ + %{id: nil, time: %{type: :minutes, minutes: 1}, crowding: nil}, + %{id: nil, time: %{type: :minutes, minutes: 2}, crowding: nil} + ], + inline_alerts: [] + }} + ], + header: "Section Header" + } = Departures.audio_serialize_section(section, screen, now) + end + + test "gl_eink_v2 and bus_shelter_v2 always return a max of 2 departures" do + now = ~U[2020-01-01T00:00:00Z] + + section = %{ + type: :normal_section, + rows: [ + %Departure{ + prediction: %Prediction{ + arrival_time: ~U[2020-01-01T00:05:00Z], + route: %Route{type: :subway}, + trip: %Trip{headsign: "Test"}, + stop: %Stop{id: "place-test"} + } + }, + %Departure{ + prediction: %Prediction{ + arrival_time: ~U[2020-01-01T00:06:00Z], + route: %Route{type: :subway}, + trip: %Trip{headsign: "Test"}, + stop: %Stop{id: "place-test"} + } + }, + %Departure{ + prediction: %Prediction{ + arrival_time: ~U[2020-01-01T00:07:00Z], + route: %Route{type: :subway}, + trip: %Trip{headsign: "Test"}, + stop: %Stop{id: "place-test"} + } + } + ], + header: %Header{title: "Section Header"} + } + + screen = struct(Screen, %{app_id: :gl_eink_v2}) + + assert %{ + type: :normal_section, + departure_groups: [ + {:normal, + %{ + type: :departure_row, + headsign: %{headsign: "Test", variation: nil}, + route: %{track_number: nil, vehicle_type: :train, route_text: nil}, + times_with_crowding: [ + %{id: nil, time: %{type: :minutes, minutes: 5}, crowding: nil}, + %{id: nil, time: %{type: :minutes, minutes: 6}, crowding: nil} + ], + inline_alerts: [] + }} + ], + header: "Section Header" + } = Departures.audio_serialize_section(section, screen, now) + + screen = struct(Screen, %{app_id: :bus_shelter_v2}) + + assert %{ + type: :normal_section, + departure_groups: [ + {:normal, + %{ + type: :departure_row, + headsign: %{headsign: "Test", variation: nil}, + route: %{track_number: nil, vehicle_type: :train, route_text: nil}, + times_with_crowding: [ + %{id: nil, time: %{type: :minutes, minutes: 5}, crowding: nil}, + %{id: nil, time: %{type: :minutes, minutes: 6}, crowding: nil} + ], + inline_alerts: [] + }} + ], + header: "Section Header" + } = Departures.audio_serialize_section(section, screen, now) end end diff --git a/test/screens_web/views/v2/audio/departures_view_test.exs b/test/screens_web/views/v2/audio/departures_view_test.exs index 89be0567f..7f1520aee 100644 --- a/test/screens_web/views/v2/audio/departures_view_test.exs +++ b/test/screens_web/views/v2/audio/departures_view_test.exs @@ -43,6 +43,135 @@ defmodule ScreensWeb.V2.Audio.DeparturesViewTest do end end + describe "normal sections" do + test "always read GL headsign" do + assigns = %{ + sections: [ + %{ + type: :normal_section, + header: nil, + departure_groups: [ + normal: %{ + type: :departure_row, + times_with_crowding: [ + %{ + id: "test1", + time: %{type: :minutes, minutes: 1}, + crowding: nil + }, + %{ + id: "test2", + time: %{type: :minutes, minutes: 6}, + crowding: nil + } + ], + route: %{ + id: "Green-B", + vehicle_type: :train, + track_number: nil, + route_text: "Green Line B" + }, + headsign: %{headsign: "Boston College", variation: nil}, + inline_alerts: [] + }, + normal: %{ + type: :departure_row, + times_with_crowding: [ + %{ + id: "test3", + time: %{type: :minutes, minutes: 1}, + crowding: nil + }, + %{ + id: "test4", + time: %{type: :minutes, minutes: 6}, + crowding: nil + } + ], + route: %{ + id: "Red", + vehicle_type: :train, + track_number: nil, + route_text: "Red Line" + }, + headsign: %{headsign: "Alewife", variation: nil}, + inline_alerts: [] + } + ] + } + ] + } + + assert render(assigns) =~ + "The next Green Line B train to Boston College arrives in 1 minute" + + assert render(assigns) =~ + "The following Green Line B train to Boston College arrives in 6 minutes" + + assert render(assigns) =~ + "The next Red Line train to Alewife arrives in 1 minute" + + assert render(assigns) =~ + "The following Red Line train arrives in 6 minutes" + end + + test "reads track_number as 'at berth' for bus and 'on track' for CR" do + assigns = %{ + sections: [ + %{ + type: :normal_section, + header: nil, + departure_groups: [ + normal: %{ + type: :departure_row, + times_with_crowding: [ + %{ + id: "test1", + time: %{type: :text, text: "BRD"}, + crowding: 1 + } + ], + route: %{id: "73", vehicle_type: :bus, track_number: "E", route_text: "73"}, + headsign: %{headsign: "Waverley", variation: nil}, + inline_alerts: [] + }, + normal: %{ + type: :departure_row, + times_with_crowding: [ + %{ + id: "test3", + time: %{ + type: :timestamp, + minute: 31, + hour: 12, + am_pm: :pm, + show_am_pm: false + }, + crowding: nil + } + ], + route: %{ + id: "CR-Needham", + vehicle_type: :train, + track_number: "5", + route_text: "Needham Line" + }, + headsign: %{headsign: "South Station", variation: nil}, + inline_alerts: [] + } + ] + } + ] + } + + assert render(assigns) =~ + "The next 73 bus to Waverley at berth E" + + assert render(assigns) =~ + "The next Needham Line train to South Station on track 5" + end + end + ## helpers defp render(data) do
{v1ScreenId}