Maidenhead grid module converts grid squares to lat/lon coordinates. Submission form validates grids, bands, modes, and email, computes positions and distance, then triggers the weather/HRRR/terrain processing pipeline via Oban.
41 lines
982 B
Elixir
41 lines
982 B
Elixir
defmodule Microwaveprop.Radio.Maidenhead do
|
|
@moduledoc false
|
|
|
|
@spec valid?(any()) :: boolean()
|
|
def valid?(nil), do: false
|
|
|
|
def valid?(grid) when is_binary(grid) do
|
|
String.match?(grid, ~r/^[A-Ra-r]{2}[0-9]{2}$/) or
|
|
String.match?(grid, ~r/^[A-Ra-r]{2}[0-9]{2}[A-Xa-x]{2}$/)
|
|
end
|
|
|
|
def valid?(_), do: false
|
|
|
|
@spec to_latlon(any()) :: {:ok, {float(), float()}} | :error
|
|
def to_latlon(nil), do: :error
|
|
|
|
def to_latlon(grid) when is_binary(grid) do
|
|
grid = String.upcase(grid)
|
|
|
|
if valid?(grid) do
|
|
<<f1, f2, s1, s2>> <> rest = grid
|
|
|
|
lon = (f1 - ?A) * 20 + (s1 - ?0) * 2 - 180
|
|
lat = (f2 - ?A) * 10 + (s2 - ?0) * 1 - 90
|
|
|
|
case rest do
|
|
<<ss1, ss2>> ->
|
|
lon = lon + (ss1 - ?A) * (5 / 60) + 5 / 120
|
|
lat = lat + (ss2 - ?A) * (2.5 / 60) + 2.5 / 120
|
|
{:ok, {lat, lon}}
|
|
|
|
"" ->
|
|
{:ok, {lat + 0.5, lon + 1.0}}
|
|
end
|
|
else
|
|
:error
|
|
end
|
|
end
|
|
|
|
def to_latlon(_), do: :error
|
|
end
|