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

feat(ex/skate/ors): format directions as "short directions" #2902

Merged
merged 3 commits into from
Dec 3, 2024
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
15 changes: 5 additions & 10 deletions lib/skate/open_route_service_api.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ defmodule Skate.OpenRouteServiceAPI do
],
directions: [
%{
instruction: "Turn right onto 1st Avenue"
instruction: "R - 1st Avenue"
},
%{
instruction: "Turn left onto 2nd Place"
instruction: "L - 2nd Place"
}
]
}
Expand Down Expand Up @@ -86,14 +86,9 @@ defmodule Skate.OpenRouteServiceAPI do
directions:
segments
|> Enum.flat_map(& &1["steps"])
|> Enum.filter(fn %{"type" => type} ->
map_type(type) not in [:goal, :depart, :straight, :error]
end)
|> Enum.map(
&%{
instruction: &1["instruction"]
}
)
|> Enum.map(fn attrs -> Map.update!(attrs, "type", &map_type/1) end)
|> 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))
firestack marked this conversation as resolved.
Show resolved Hide resolved

# 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
10 changes: 8 additions & 2 deletions test/skate/open_route_service_api_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,18 @@ defmodule Skate.OpenRouteServiceAPITest do
"steps" => [
%{
"instruction" => "not-in-results",
"name" => "not-in-results",
# Depart
"type" => 11
},
%{
"instruction" => "1",
"name" => "A Street",
"type" => 1
},
%{
"instruction" => "not-in-results",
"name" => "not-in-results",
# Goal
"type" => 10
}
Expand All @@ -102,16 +105,19 @@ defmodule Skate.OpenRouteServiceAPITest do
"steps" => [
%{
"instruction" => "not-in-results",
"name" => "not-in-results",
# Depart
"type" => 11
},
%{
"instruction" => "not-in-results",
"name" => "not-in-results",
# Straight
"type" => 6
},
%{
"instruction" => "2",
"name" => "B Drive",
"type" => 0
}
]
Expand All @@ -124,8 +130,8 @@ defmodule Skate.OpenRouteServiceAPITest do
assert {:ok,
%DirectionsResponse{
directions: [
%{instruction: "1"},
%{instruction: "2"}
%{instruction: "R - A Street"},
%{instruction: "L - B Drive"}
]
}} =
Skate.OpenRouteServiceAPI.directions([
Expand Down
15 changes: 9 additions & 6 deletions test/skate_web/controllers/detour_route_controller_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,22 @@ defmodule SkateWeb.DetourRouteControllerTest do
"steps" => [
%{
"instruction" => "1",
"type" => 1
"type" => 1,
"name" => "First Street"
},
%{
"instruction" => "2",
"type" => 0
"type" => 0,
"name" => "Second Street"
}
]
},
%{
"steps" => [
%{
"instruction" => "3",
"type" => 2
"type" => 2,
"name" => "Third Street"
}
]
}
Expand All @@ -94,9 +97,9 @@ defmodule SkateWeb.DetourRouteControllerTest do
assert %{
"data" => %{
"directions" => [
%{"instruction" => "1"},
%{"instruction" => "2"},
%{"instruction" => "3"}
%{"instruction" => "R - First Street"},
%{"instruction" => "L - Second Street"},
%{"instruction" => "L - Third Street"}
]
}
} =
Expand Down
15 changes: 9 additions & 6 deletions test/skate_web/controllers/detours_controller_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -786,19 +786,22 @@ defmodule SkateWeb.DetoursControllerTest do
"steps" => [
%{
"instruction" => "1",
"type" => 1
"type" => 1,
"name" => "A"
},
%{
"instruction" => "2",
"type" => 0
"type" => 0,
"name" => "B"
}
]
},
%{
"steps" => [
%{
"instruction" => "3",
"type" => 2
"type" => 2,
"name" => "C"
}
]
}
Expand Down Expand Up @@ -836,9 +839,9 @@ defmodule SkateWeb.DetoursControllerTest do
"data" => %{
"detour_shape" => %{
"directions" => [
%{"instruction" => "1"},
%{"instruction" => "2"},
%{"instruction" => "3"}
%{"instruction" => "R - A"},
%{"instruction" => "L - B"},
%{"instruction" => "L - C"}
]
}
}
Expand Down
Loading