Skip to content

Commit

Permalink
Dont show irrelevant alerts (#2299)
Browse files Browse the repository at this point in the history
* dont show irrelevant alerts

* tests

* format

* add parking closure
  • Loading branch information
anthonyshull authored Jan 3, 2025
1 parent 5fe3e8f commit 61da9a0
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 33 deletions.
92 changes: 59 additions & 33 deletions lib/dotcom/trip_plan/alerts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,40 @@ defmodule Dotcom.TripPlan.Alerts do
* at the times they'll be travelling
"""

alias Alerts.Alert
alias Alerts.InformedEntity, as: IE
alias Alerts.{Alert, InformedEntity}
alias Dotcom.TripPlan.{Itinerary, Leg, TransitDetail}

def by_mode_and_stops(alerts, leg) do
{route_alerts, stop_alerts} =
alerts
|> Enum.split_with(fn alert ->
alert.informed_entity.entities
|> Enum.all?(fn
%{stop: nil} -> true
_ -> false
end)
end)

%{from: from_stop_ids, to: to_stop_ids} = Leg.stop_ids(leg)

entities_from = mode_entities_with_stop_ids(leg.mode, from_stop_ids)
from = Alerts.Match.match(stop_alerts, entities_from)

entities_to = mode_entities_with_stop_ids(leg.mode, to_stop_ids)
to = Alerts.Match.match(stop_alerts, entities_to)

%{
route: route_alerts,
from: from,
to: to
}
end

@spec from_itinerary(Itinerary.t()) :: [Alerts.Alert.t()]
def from_itinerary(itinerary) do
itinerary.start
|> Alerts.Repo.all()
|> Enum.reject(&reject_irrelevant_alert(&1, itinerary.accessible?))
|> Alerts.Match.match(
entities(itinerary),
itinerary.start
Expand All @@ -25,8 +51,9 @@ defmodule Dotcom.TripPlan.Alerts do
@doc "Filters a list of Alerts to those relevant to the Itinerary"
@spec filter_for_itinerary([Alert.t()], Itinerary.t()) :: [Alert.t()]
def filter_for_itinerary(alerts, itinerary) do
Alerts.Match.match(
alerts,
alerts
|> Enum.reject(&reject_irrelevant_alert(&1, itinerary.accessible?))
|> Alerts.Match.match(
Enum.concat(intermediate_entities(itinerary), entities(itinerary)),
itinerary.start
)
Expand All @@ -42,13 +69,31 @@ defmodule Dotcom.TripPlan.Alerts do
)
end

# Reject an alert that is not relevant to a trip plan:
# - accessibility issue (see `reject_accessibility_alert`)
# - bike issue
# - facility issue
# - parking closure
# - parking issue
defp reject_irrelevant_alert(alert, accessible?) do
reject_accessibility_alert(alert, accessible?) ||
Enum.member?(~w[bike_issue facility_issue parking_closure parking_issue]a, alert.effect)
end

# Reject an alert that is not relevant to a trip plan *unless* we want an accessible trip:
# - elevator closure
# - escalator closure
defp reject_accessibility_alert(alert, accessible?) do
not accessible? && (alert.effect == :elevator_closure || alert.effect == :escalator_closure)
end

defp intermediate_entities(itinerary) do
itinerary
|> Itinerary.intermediate_stop_ids()
|> Enum.map(&%IE{stop: &1})
|> Enum.map(&%InformedEntity{stop: &1})
end

@spec entities(Itinerary.t()) :: [IE.t()]
@spec entities(Itinerary.t()) :: [InformedEntity.t()]
defp entities(itinerary) do
itinerary
|> Enum.flat_map(&leg_entities(&1))
Expand Down Expand Up @@ -84,36 +129,17 @@ defmodule Dotcom.TripPlan.Alerts do
trip.direction_id
end

[%IE{route_type: route_type, route: route.id, trip: trip_id, direction_id: direction_id}]
[
%InformedEntity{
route_type: route_type,
route: route.id,
trip: trip_id,
direction_id: direction_id
}
]
end

defp mode_entities(_) do
[]
end

def by_mode_and_stops(alerts, leg) do
{route_alerts, stop_alerts} =
alerts
|> Enum.split_with(fn alert ->
alert.informed_entity.entities
|> Enum.all?(fn
%{stop: nil} -> true
_ -> false
end)
end)

%{from: from_stop_ids, to: to_stop_ids} = Leg.stop_ids(leg)

entities_from = mode_entities_with_stop_ids(leg.mode, from_stop_ids)
from = Alerts.Match.match(stop_alerts, entities_from)

entities_to = mode_entities_with_stop_ids(leg.mode, to_stop_ids)
to = Alerts.Match.match(stop_alerts, entities_to)

%{
route: route_alerts,
from: from,
to: to
}
end
end
50 changes: 50 additions & 0 deletions test/dotcom/trip_plan/alerts_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,56 @@ defmodule Dotcom.TripPlan.AlertsTest do
bad_alert = Alert.update(good_alert, active_period: [invalid_active_period(itinerary)])
assert_only_good_alert(good_alert, bad_alert, itinerary)
end

test "rejects an accessibility alert", %{itinerary: itinerary, route_id: route_id} do
expect(MBTA.Api.Mock, :get_json, fn "/trips/" <> id, [] ->
%JsonApi{
data: [
Api.build(:trip_item, %{id: id})
]
}
end)

good_alert =
Alert.new(
active_period: [valid_active_period(itinerary)],
effect: :no_service,
informed_entity: [%InformedEntity{route: route_id}]
)

bad_alert = Alert.update(good_alert, effect: :elevator_closure)

assert_only_good_alert(good_alert, bad_alert, itinerary)
end

test "keeps an accesibility alert if the itinerary is accessible", %{
itinerary: itinerary,
route_id: route_id
} do
expect(MBTA.Api.Mock, :get_json, fn "/trips/" <> id, [] ->
%JsonApi{
data: [
Api.build(:trip_item, %{id: id})
]
}
end)

first_alert =
Alert.new(
active_period: [valid_active_period(itinerary)],
effect: :no_service,
informed_entity: [%InformedEntity{route: route_id}]
)

second_alert = Alert.update(first_alert, effect: :elevator_closure)

accessible_itinerary = Map.put(itinerary, :accessible?, true)

assert filter_for_itinerary([first_alert, second_alert], accessible_itinerary) == [
first_alert,
second_alert
]
end
end

describe "by_mode_and_stops/2" do
Expand Down

0 comments on commit 61da9a0

Please sign in to comment.