Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 72 additions & 3 deletions lib/dotcom/schedule_finder/upcoming_departures.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ defmodule Dotcom.ScheduleFinder.UpcomingDepartures do

@predictions_repo Application.compile_env!(:dotcom, :repo_modules)[:predictions]
@schedules_repo Application.compile_env!(:dotcom, :repo_modules)[:schedules]
@stops_repo Application.compile_env!(:dotcom, :repo_modules)[:stops]

defmodule UpcomingDeparture do
@moduledoc """
Expand All @@ -23,10 +24,13 @@ defmodule Dotcom.ScheduleFinder.UpcomingDepartures do

defstruct [
:arrival_status,
:arrival_substatus,
:headsign,
:platform_name,
:route,
:trip_details,
:trip_id
:trip_id,
:trip_name
]

defmodule TripDetails do
Expand Down Expand Up @@ -137,16 +141,35 @@ defmodule Dotcom.ScheduleFinder.UpcomingDepartures do
route_type: route_type,
now: now
}),
arrival_substatus:
arrival_substatus(%{
predicted_schedule: predicted_schedule,
route_type: route_type
}),
headsign: trip.headsign,
platform_name: platform_name(predicted_schedule),
route: PredictedSchedule.route(predicted_schedule),
trip_details: trip_details,
trip_id: trip.id
trip_id: trip.id,
trip_name: if(route_type == :commuter_rail, do: trip.name, else: nil)
}
end

defp seconds_between(nil, _now), do: nil
defp seconds_between(prediction_time, now), do: DateTime.diff(prediction_time, now, :second)

defp platform_name(predicted_schedule) do
predicted_schedule
|> PredictedSchedule.platform_stop_id()
|> @stops_repo.get()
|> Kernel.then(& &1.platform_name)
|> case do
nil -> nil
"Commuter Rail" -> nil
name -> name |> String.trim("Commuter Rail - ")
end
end

defp trip_details(predictions_by_trip_id, trip_id, stop_id) do
other_stops = other_stops(predictions_by_trip_id |> Map.get(trip_id))

Expand Down Expand Up @@ -193,6 +216,14 @@ defmodule Dotcom.ScheduleFinder.UpcomingDepartures do
}),
do: :hidden

defp arrival_status(%{
predicted_schedule: %PredictedSchedule{prediction: prediction},
route_type: :commuter_rail
})
when prediction != nil do
{:time, prediction.departure_time}
end

defp arrival_status(%{
predicted_schedule: %PredictedSchedule{prediction: prediction},
route_type: route_type,
Expand All @@ -211,7 +242,14 @@ defmodule Dotcom.ScheduleFinder.UpcomingDepartures do

defp arrival_status(%{
predicted_schedule: %PredictedSchedule{schedule: schedule},
route_type: _route_type
route_type: :commuter_rail
})
when schedule != nil do
{:scheduled, schedule.departure_time}
end

defp arrival_status(%{
predicted_schedule: %PredictedSchedule{schedule: schedule}
})
when schedule != nil do
{:scheduled, prediction_time(schedule)}
Expand Down Expand Up @@ -251,4 +289,35 @@ defmodule Dotcom.ScheduleFinder.UpcomingDepartures do
do: :approaching

defp realtime_arrival_status(%{arrival_seconds: seconds}), do: {:arrival_seconds, seconds}

defp arrival_substatus(%{route_type: route_type}) when route_type != :commuter_rail, do: nil

defp arrival_substatus(%{
predicted_schedule: %PredictedSchedule{prediction: nil}
}),
do: :scheduled

defp arrival_substatus(%{
predicted_schedule: %PredictedSchedule{prediction: %Prediction{status: status}}
})
when status != nil,
do: {:status, status |> String.split(" ") |> Enum.map_join(" ", &String.capitalize/1)}

defp arrival_substatus(%{
predicted_schedule: %PredictedSchedule{schedule: nil}
}),
do: :on_time

defp arrival_substatus(%{
predicted_schedule: %PredictedSchedule{schedule: schedule, prediction: prediction}
}) do
scheduled_time = schedule.departure_time
predicted_time = prediction.departure_time

if DateTime.diff(scheduled_time, predicted_time, :second) |> abs() < 60 do
:on_time
else
{:scheduled_at, scheduled_time}
end
end
end
50 changes: 46 additions & 4 deletions lib/dotcom_web/live/schedule_finder_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -461,11 +461,22 @@ defmodule DotcomWeb.ScheduleFinderLive do
summary_class="flex items-center border-gray-lightest py-3 px-2 gap-2 group-open:bg-gray-lightest hover:bg-brand-primary-lightest group-open:hover:bg-brand-primary-lightest"
>
<:heading>
<div class="w-full flex gap-2">
<RouteComponents.route_icon size="small" route={upcoming_departure.route} />
<div>{upcoming_departure.headsign}</div>
<div class="ml-auto">
<div class="w-full flex items-center">
<div class="grid grid-cols-[max-content_max-content] gap-x-1.5 gap-y-1 items-center">
<RouteComponents.route_icon size="small" route={upcoming_departure.route} />
<div>{upcoming_departure.headsign}</div>

<div />
<div :if={upcoming_departure.trip_name} class="leading-none text-[0.75rem]">
Train {upcoming_departure.trip_name}
<span>
&bull; {upcoming_departure.platform_name || "Track TBA"}
</span>
</div>
</div>
<div class="ml-auto flex flex-col items-end">
<.prediction_time_display arrival_status={upcoming_departure.arrival_status} />
<.prediction_substatus_display arrival_substatus={upcoming_departure.arrival_substatus} />
</div>
</div>
</:heading>
Expand Down Expand Up @@ -567,11 +578,42 @@ defmodule DotcomWeb.ScheduleFinderLive do
defp realtime_text({:departure_seconds, seconds}),
do: seconds_to_localized_minutes(seconds)

defp realtime_text({:time, time}),
do: format!(time, :hour_12_minutes)

defp realtime_text(:approaching), do: ~t"Approaching"
defp realtime_text(:arriving), do: ~t"Arriving"
defp realtime_text(:boarding), do: ~t"Boarding"
defp realtime_text(:now), do: ~t"Now"

defp prediction_substatus_display(%{arrival_substatus: nil} = assigns), do: ~H""

defp prediction_substatus_display(%{arrival_substatus: {:scheduled_at, time}} = assigns) do
assigns = assigns |> assign(:time, time)

~H"""
<span class="text-[0.75rem] line-through">{format!(@time, :hour_12_minutes)}</span>
"""
end

defp prediction_substatus_display(%{arrival_substatus: {:status, status}} = assigns) do
assigns = assigns |> assign(:status, status)

~H"""
<span class="text-[0.75rem]">{@status}</span>
"""
end

defp prediction_substatus_display(assigns) do
~H"""
<span class="text-[0.75rem]">{substatus_text(@arrival_substatus)}</span>
"""
end

defp substatus_text(:on_time), do: ~t"On Time"
defp substatus_text(:scheduled), do: ~t"Scheduled"
defp substatus_text(text), do: text

defp remaining_service(%{route_type: route_type} = assigns) when route_type in [0, 1] do
~H"""
<div class="flex justify-center bg-gray-lightest w-full py-3">
Expand Down
14 changes: 14 additions & 0 deletions lib/predicted_schedule.ex
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,20 @@ defmodule PredictedSchedule do
def stop(%PredictedSchedule{schedule: %Schedule{stop: stop}}), do: stop
def stop(%PredictedSchedule{prediction: %Prediction{stop: stop}}), do: stop

@doc """
Returns the stop for a given PredictedSchedule
"""
def platform_stop_id(%PredictedSchedule{
prediction: %Prediction{platform_stop_id: platform_stop_id}
}),
do: platform_stop_id

@spec platform_stop_id(PredictedSchedule.t()) :: Stops.Stop.id_t()
def platform_stop_id(%PredictedSchedule{
schedule: %Schedule{platform_stop_id: platform_stop_id}
}),
do: platform_stop_id

@doc """
Returns the route for a given PredictedSchedule.
"""
Expand Down
Loading