Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

introduce Message structs #873

Merged
merged 1 commit into from
Jan 21, 2025
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
13 changes: 13 additions & 0 deletions lib/message.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
defprotocol Message do
@doc "render a single line of content, may include line-level paging"
@spec to_single_line(Message.t()) :: Content.Message.t()
def to_single_line(message)

@doc "render two lines of content, must not include line-level paging"
@spec to_full_page(Message.t()) :: {Content.Message.t(), Content.Message.t()}
def to_full_page(message)

@doc "render two lines of content, may include line-level paging"
@spec to_multi_line(Message.t()) :: {Content.Message.t(), Content.Message.t()}
def to_multi_line(message)
end
67 changes: 67 additions & 0 deletions lib/message/alert.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
defmodule Message.Alert do
@enforce_keys [:route, :destination, :status, :uses_shuttles?, :union_square?]
defstruct @enforce_keys

@type t :: %__MODULE__{
destination: PaEss.destination(),
route: String.t() | nil,
status: Engine.Alerts.Fetcher.stop_status(),
uses_shuttles?: boolean(),
union_square?: boolean()
}

defimpl Message do
def to_single_line(
%Message.Alert{status: :shuttles_closed_station, uses_shuttles?: true} = message
) do
%Content.Message.Alert.NoServiceUseShuttle{
route: message.route,
destination: message.destination
}
end

def to_single_line(
%Message.Alert{status: :shuttles_closed_station, uses_shuttles?: false} = message
) do
%Content.Message.Alert.DestinationNoService{
route: message.route,
destination: message.destination
}
end

def to_single_line(%Message.Alert{status: status} = message)
when status in [:suspension_closed_station, :station_closure] do
%Content.Message.Alert.DestinationNoService{
route: message.route,
destination: message.destination
}
end

def to_full_page(%Message.Alert{union_square?: true} = message) do
{%Content.Message.Alert.NoService{route: message.route, destination: message.destination},
%Content.Message.Alert.UseRoutes{}}
end

def to_full_page(
%Message.Alert{status: :shuttles_closed_station, uses_shuttles?: true} = message
) do
{%Content.Message.Alert.NoService{route: message.route, destination: message.destination},
%Content.Message.Alert.UseShuttleBus{}}
end

def to_full_page(
%Message.Alert{status: :shuttles_closed_station, uses_shuttles?: false} = message
) do
{%Content.Message.Alert.NoService{route: message.route, destination: message.destination},
%Content.Message.Empty{}}
end

def to_full_page(%Message.Alert{status: status} = message)
when status in [:suspension_closed_station, :station_closure] do
{%Content.Message.Alert.NoService{route: message.route, destination: message.destination},
%Content.Message.Empty{}}
end

def to_multi_line(%Message.Alert{} = message), do: to_full_page(message)
end
end
22 changes: 22 additions & 0 deletions lib/message/custom.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
defmodule Message.Custom do
@enforce_keys [:top, :bottom]
defstruct @enforce_keys

@type t :: %__MODULE__{
top: String.t(),
bottom: String.t()
}

defimpl Message do
def to_single_line(%Message.Custom{}) do
raise "Cannot render custom message on one line"
end

def to_full_page(%Message.Custom{} = message) do
{Content.Message.Custom.new(message.top, :top),
Content.Message.Custom.new(message.bottom, :bottom)}
end

def to_multi_line(%Message.Custom{} = message), do: to_full_page(message)
end
end
17 changes: 17 additions & 0 deletions lib/message/empty.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
defmodule Message.Empty do
defstruct []

@type t :: %__MODULE__{}

defimpl Message do
def to_single_line(%Message.Empty{}) do
%Content.Message.Empty{}
end

def to_full_page(%Message.Empty{}) do
{%Content.Message.Empty{}, %Content.Message.Empty{}}
end

def to_multi_line(%Message.Empty{} = message), do: to_full_page(message)
end
end
25 changes: 25 additions & 0 deletions lib/message/first_train.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
defmodule Message.FirstTrain do
@enforce_keys [:destination, :scheduled]
defstruct @enforce_keys

@type t :: %__MODULE__{
destination: PaEss.destination(),
scheduled: DateTime.t()
}

defimpl Message do
def to_single_line(%Message.FirstTrain{destination: destination, scheduled: scheduled}) do
%Content.Message.EarlyAm.DestinationScheduledTime{
destination: destination,
scheduled_time: scheduled
}
end

def to_full_page(%Message.FirstTrain{destination: destination, scheduled: scheduled}) do
{%Content.Message.EarlyAm.DestinationTrain{destination: destination},
%Content.Message.EarlyAm.ScheduledTime{scheduled_time: scheduled}}
end

def to_multi_line(%Message.FirstTrain{} = message), do: to_full_page(message)
end
end
23 changes: 23 additions & 0 deletions lib/message/headway.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
defmodule Message.Headway do
@enforce_keys [:route, :destination, :range]
defstruct @enforce_keys

@type t :: %__MODULE__{
destination: PaEss.destination() | nil,
range: {non_neg_integer(), non_neg_integer()},
route: String.t() | nil
}

defimpl Message do
def to_single_line(%Message.Headway{destination: destination, range: range, route: route}) do
%Content.Message.Headways.Paging{destination: destination, range: range, route: route}
end

def to_full_page(%Message.Headway{destination: destination, range: range, route: route}) do
{%Content.Message.Headways.Top{destination: destination, route: route},
%Content.Message.Headways.Bottom{range: range}}
end

def to_multi_line(%Message.Headway{} = message), do: to_full_page(message)
end
end
42 changes: 42 additions & 0 deletions lib/message/predictions.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
defmodule Message.Predictions do
@enforce_keys [:predictions, :terminal?, :special_sign]
defstruct @enforce_keys

@type t :: %__MODULE__{
predictions: [Predictions.Prediction.t()],
terminal?: boolean(),
special_sign: :jfk_mezzanine | :bowdoin_eastbound | nil
}

defimpl Message do
def to_single_line(%Message.Predictions{predictions: [top | _]} = message) do
prediction_message(top, message.terminal?, message.special_sign)
end

def to_full_page(
%Message.Predictions{predictions: [top | _], special_sign: :jfk_mezzanine} = message
) do
{minutes, _} = PaEss.Utilities.prediction_minutes(top, message.terminal?)

{prediction_message(top, message.terminal?, nil),
%Content.Message.PlatformPredictionBottom{stop_id: top.stop_id, minutes: minutes}}
end

def to_multi_line(%Message.Predictions{predictions: [top]} = message) do
{prediction_message(top, message.terminal?, message.special_sign), %Content.Message.Empty{}}
end

def to_multi_line(%Message.Predictions{predictions: [top, bottom]} = message) do
{prediction_message(top, message.terminal?, message.special_sign),
prediction_message(bottom, message.terminal?, message.special_sign)}
end

defp prediction_message(prediction, terminal?, special_sign) do
if PaEss.Utilities.prediction_stopped?(prediction, terminal?) do
Content.Message.StoppedTrain.new(prediction, terminal?, special_sign)
else
Content.Message.Predictions.new(prediction, terminal?, special_sign)
end
end
end
end
27 changes: 27 additions & 0 deletions lib/message/service_ended.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule Message.ServiceEnded do
@enforce_keys [:route, :destination]
defstruct @enforce_keys

@type t :: %__MODULE__{
destination: PaEss.destination() | nil,
route: String.t() | nil
}

defimpl Message do
def to_single_line(%Message.ServiceEnded{route: route, destination: destination}) do
%Content.Message.LastTrip.NoService{destination: destination, route: route}
end

def to_full_page(%Message.ServiceEnded{destination: nil, route: route}) do
{%Content.Message.LastTrip.StationClosed{route: route},
%Content.Message.LastTrip.ServiceEnded{destination: nil}}
end

def to_full_page(%Message.ServiceEnded{destination: destination}) do
{%Content.Message.LastTrip.PlatformClosed{destination: destination},
%Content.Message.LastTrip.ServiceEnded{destination: destination}}
end

def to_multi_line(%Message.ServiceEnded{} = message), do: to_full_page(message)
end
end
20 changes: 2 additions & 18 deletions lib/signs/utilities/headways.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,14 @@ defmodule Signs.Utilities.Headways do
alias Signs.Utilities.SourceConfig
require Logger

@spec headway_messages(SourceConfig.config(), DateTime.t()) ::
Signs.Realtime.sign_messages() | nil
def headway_messages(config, current_time) do
case fetch_headways(config.headway_group, config.sources, current_time) do
nil ->
nil

headways ->
{%Content.Message.Headways.Top{
destination: config.headway_destination,
route: SourceConfig.single_route(config)
}, %Content.Message.Headways.Bottom{range: {headways.range_low, headways.range_high}}}
end
end

@spec headway_message(SourceConfig.config(), DateTime.t()) ::
Signs.Realtime.line_content() | nil
@spec headway_message(SourceConfig.config(), DateTime.t()) :: Message.t() | nil
def headway_message(config, current_time) do
case fetch_headways(config.headway_group, config.sources, current_time) do
nil ->
nil

headways ->
%Content.Message.Headways.Paging{
%Message.Headway{
destination: config.headway_destination,
range: {headways.range_low, headways.range_high},
route: SourceConfig.single_route(config)
Expand Down
Loading
Loading