Skip to content

Commit

Permalink
feat(ex/skate/ors): format directions as "short directions"
Browse files Browse the repository at this point in the history
  • Loading branch information
firestack committed Dec 2, 2024
1 parent c506a43 commit 3f74359
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 8 deletions.
10 changes: 2 additions & 8 deletions lib/skate/open_route_service_api.ex
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,8 @@ defmodule Skate.OpenRouteServiceAPI do
segments
|> Enum.flat_map(& &1["steps"])
|> Enum.map(fn attrs -> Map.update!(attrs, "type", &map_type/1) end)
|> Enum.filter(fn %{"type" => type} ->
type not in [:goal, :depart, :straight, :error]
end)
|> Enum.map(
&%{
instruction: &1["instruction"]
}
)
|> Enum.map(&Skate.OpenRouteServiceAPI.DirectionsFormatter.MBTA.English.format/1)
|> Enum.reject(&is_nil/1)
}}
end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
defmodule Skate.OpenRouteServiceAPI.DirectionsFormatter.MBTA.English do
@moduledoc """
Formats Directions from Open Route Service into MBTA English specific Directions Shorthand.
"""

@doc """
Formats a Open Route Service Direction Instruction Map into
- a Instruction, as a `Map` with a single `:instruction` key
- or `nil`, which represents discarded instructions
"""
def format(%{"type" => type, "name" => name} = attrs) do
case format_instruction(type, name, attrs) do
nil -> nil
instruction -> %{instruction: instruction}
end
end

# Converts ORS Instructions into string form, or `nil`
# Ignore noisy instructions
defp format_instruction(type, _name, _)
when type in [:goal, :depart, :straight, :error],
do: nil

# ORS uses `-` as a value when a direction doesn't have a name
# Reject instructions without a name
defp format_instruction(_type, "-", _),
do: nil

defp format_instruction(:left, name, _),
do: "L - #{name}"

defp format_instruction(:right, name, _),
do: "R - #{name}"

defp format_instruction(:slight_left, name, _),
do: "Slight L - #{name}"

defp format_instruction(:slight_right, name, _),
do: "Slight R - #{name}"

defp format_instruction(:keep_left, name, _),
do: "Keep L - #{name}"

defp format_instruction(:keep_right, name, _),
do: "Keep R - #{name}"

defp format_instruction(:sharp_left, name, _),
do: "L - #{name}"

defp format_instruction(:sharp_right, name, _),
do: "R - #{name}"

# There does not seem to be many `exit_roundabout` instructions, only `enter`
defp format_instruction(:enter_roundabout, name, %{"exit_number" => exit_number}),
do: "Roundabout - #{exit_number}#{ordinal_indicator(exit_number)} exit, #{name}"

# Fallback case, return the original instruction from ORS if we do not have an override
defp format_instruction(_, _, %{"instruction" => ors_instruction}), do: ors_instruction

# English Specific Ordinal Indicators
# > https://en.wikipedia.org/wiki/Ordinal_indicator#English
# > -st is used with numbers ending in 1
defp ordinal_indicator(1), do: "st"

# > -nd is used with numbers ending in 2
defp ordinal_indicator(2), do: "nd"

# > -rd is used with numbers ending in 3
defp ordinal_indicator(3), do: "rd"

# > As an exception to the above rules, numbers ending with 11, 12, and 13 use -th
# `11st, 12nd, 13rd`, do not exist
defp ordinal_indicator(n) when 11 <= n and n <= 13, do: "th"

# If the number is over 100, we need to check the last two digits for `11-13`
defp ordinal_indicator(n) when n >= 100, do: ordinal_indicator(rem(n, 100))

# If the number is over 10, but is not covered by the `11-13` condition above,
# We need to check the last digit for `1..3`
defp ordinal_indicator(n) when n >= 10, do: ordinal_indicator(rem(n, 10))

# > -th is used for all other numbers
defp ordinal_indicator(_), do: "th"
end

0 comments on commit 3f74359

Please sign in to comment.