-
Notifications
You must be signed in to change notification settings - Fork 5
/
lib_lat_lon.ex
105 lines (88 loc) · 2.87 KB
/
lib_lat_lon.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
defmodule LibLatLon do
@moduledoc """
This module is basically the only module consumers of this library
should be interested in.
There is a single function exported: [`LibLatLon.lookup/3`].
"""
@doc """
Pass anything to lookup using default provider and with default options.
Pass a provider as the second argument to use a specific provider.
Pass options map like `%{language: "es"}` as a last parameter to
tune the provider’s response. _NB:_ options are provider-specific.
## Examples
iex> LibLatLon.lookup(
...> {42, 3.14159265},
...> LibLatLon.Providers.Dummy,
...> %{extended: true}).details
%{
city: "Barcelona",
city_district: "Sant Martí",
country: "España",
country_code: "es",
county: "BCN",
postcode: "08020",
road: "Avinguda del Litoral",
state: "CAT",
suburb: "la Vila Olímpica del Poblenou"
}
"""
@spec lookup(any(), atom(), %{}) :: {:ok, LibLatLon.Info.t()} | {:error, any()}
def lookup(value, provider \\ default_provider(), opts \\ %{}) do
case guess_lookup(provider, value, opts) do
{:ok, result} -> result
anything -> anything
end
end
##############################################################################
@spec guess_lookup(atom(), any(), %{}) :: {:ok, LibLatLon.Info.t()} | {:error, any()}
defp guess_lookup(provider, any, opts) do
lookup_arg =
case LibLatLon.Coords.coordinate(any) do
{:ok, %LibLatLon.Coords{} = result} -> result
_ -> inspect(any)
end
provider.lookup(lookup_arg, opts)
end
##############################################################################
defmodule Utils do
@moduledoc false
@spec safe_float(binary() | number()) :: float()
def safe_float(v) when is_float(v), do: v
def safe_float(v) when is_integer(v), do: v * 1.0
def safe_float(v) when is_binary(v) do
case Float.parse(v) do
{float, ""} -> float
{float, _} -> float
:error -> 0.0
end
end
@spec strict_float(binary() | number()) :: float() | nil
def strict_float(v) when is_float(v), do: v
def strict_float(v) when is_integer(v), do: v * 1.0
def strict_float(v) when is_binary(v) do
case Float.parse(v) do
{float, ""} -> float
{_float, _non_empty} -> nil
:error -> nil
end
end
@spec keywordize(map() | nil) :: map()
def keywordize(nil), do: nil
def keywordize(%{} = map) do
map
|> Enum.map(fn
{k, v} when is_binary(k) -> {String.to_atom(k), v}
{k, v} when is_atom(k) -> {k, v}
{k, v} -> {k |> inspect() |> String.to_atom(), v}
end)
|> Enum.into(%{})
end
end
defp default_provider do
Application.get_env(
:lib_lat_lon,
:provider,
LibLatLon.Providers.OpenStreetMap
)
end
end