72 lines
1.9 KiB
Elixir
72 lines
1.9 KiB
Elixir
defmodule Parser.UtilityHelpers do
|
|
@moduledoc """
|
|
Utility and ambiguity helpers for APRS.
|
|
"""
|
|
|
|
def count_spaces(str) do
|
|
str |> String.graphemes() |> Enum.count(fn c -> c == " " end)
|
|
end
|
|
|
|
def count_leading_braces(packet), do: count_leading_braces(packet, 0)
|
|
|
|
def count_leading_braces(<<"}", rest::binary>>, count), do: count_leading_braces(rest, count + 1)
|
|
|
|
def count_leading_braces(_packet, count), do: count
|
|
|
|
def calculate_position_ambiguity(latitude, longitude) do
|
|
lat_spaces = count_spaces(latitude)
|
|
lon_spaces = count_spaces(longitude)
|
|
|
|
Map.get(
|
|
%{{0, 0} => 0, {1, 1} => 1, {2, 2} => 2, {3, 3} => 3, {4, 4} => 4},
|
|
{lat_spaces, lon_spaces},
|
|
0
|
|
)
|
|
end
|
|
|
|
def find_matches(regex, text) do
|
|
case Regex.names(regex) do
|
|
[] ->
|
|
matches = Regex.run(regex, text)
|
|
|
|
Enum.reduce(Enum.with_index(matches), %{}, fn {match, index}, acc ->
|
|
Map.put(acc, index, match)
|
|
end)
|
|
|
|
_ ->
|
|
Regex.named_captures(regex, text)
|
|
end
|
|
end
|
|
|
|
def validate_position_data(latitude, longitude) do
|
|
import Decimal, only: [new: 1, add: 2, negate: 1]
|
|
|
|
lat =
|
|
case Regex.run(~r/^(\d{2})(\d{2}\.\d+)([NS])$/, latitude) do
|
|
[_, degrees, minutes, direction] ->
|
|
lat_val = add(new(degrees), Decimal.div(new(minutes), new("60")))
|
|
if direction == "S", do: negate(lat_val), else: lat_val
|
|
|
|
_ ->
|
|
nil
|
|
end
|
|
|
|
lon =
|
|
case Regex.run(~r/^(\d{3})(\d{2}\.\d+)([EW])$/, longitude) do
|
|
[_, degrees, minutes, direction] ->
|
|
lon_val = add(new(degrees), Decimal.div(new(minutes), new("60")))
|
|
if direction == "W", do: negate(lon_val), else: lon_val
|
|
|
|
_ ->
|
|
nil
|
|
end
|
|
|
|
if is_struct(lat, Decimal) and is_struct(lon, Decimal) do
|
|
{:ok, {lat, lon}}
|
|
else
|
|
{:error, :invalid_position}
|
|
end
|
|
end
|
|
|
|
def validate_timestamp(_time), do: nil
|
|
end
|