Packages

use google locations to create geocoords for driving directions between multiple locations and send them to your api.

Current section

Files

Jump to
google_directions_generator lib google_directions_generator.ex
Raw

lib/google_directions_generator.ex

defmodule GoogleDirectionsGenerator do
@moduledoc """
Generate Geocoordinates for random locations located nearby
"""
import Maybe
alias GoogleDirectionsGenerator.Http
@types [
"accounting",
"airport",
"amusement_park",
"aquarium",
"art_gallery",
"atm",
"bakery",
"bank",
"bar",
"beauty_salon",
"bicycle_store",
"book_store",
"bowling_alley",
"bus_station",
"cafe",
"campground",
"car_dealer",
"car_rental",
"car_repair",
"car_wash",
"casino",
"cemetery",
"church",
"city_hall",
"clothing_store",
"convenience_store",
"courthouse",
"dentist",
"department_store",
"doctor",
"electrician",
"electronics_store",
"embassy",
"fire_station",
"florist",
"funeral_home",
"furniture_store",
"gas_station",
"gym",
"hair_care",
"hardware_store",
"hindu_temple",
"home_goods_store",
"hospital",
"insurance_agency",
"jewelry_store",
"laundry",
"lawyer",
"library",
"liquor_store",
"local_government_office",
"locksmith",
"lodging",
"meal_delivery",
"meal_takeaway",
"mosque",
"movie_rental",
"movie_theater",
"moving_company",
"museum",
"night_club",
"painter",
"park",
"parking",
"pet_store",
"pharmacy",
"physiotherapist",
"plumber",
"police",
"post_office",
"real_estate_agency",
"restaurant",
"roofing_contractor",
"rv_park",
"school",
"shoe_store",
"shopping_mall",
"spa",
"stadium",
"storage",
"store",
"subway_station",
"synagogue",
"taxi_stand",
"train_station",
"transit_station",
"travel_agency",
"university",
"veterinary_care",
"zoo"
]
@doc """
## Run The Module and return a list of driving coords based on a nearby random location
"""
def run do
random()
end
@doc """
## Send to the endpoint
"""
def push(url, %{count: count, delay: delay}) do
{_, reply} = Http.fetch_lat_lng()
my_coords = decode_lat_long(reply)
params = ["lat=#{my_coords.lat}", "lng=#{my_coords.lng}"]
Http.push(url, Enum.join(params, "&"))
for _ <- 1..count do
{_, trip_coords} = random()
Enum.each(trip_coords, fn x ->
params = ["lat=#{x.start_location.lat}", "lng=#{x.start_location.lng}"]
Http.push(url, Enum.join(params, "&"))
:timer.sleep(:timer.seconds(:rand.uniform(delay)))
params = ["lat=#{x.end_location.lat}", "lng=#{x.end_location.lng}"]
Http.push(url, Enum.join(params, "&"))
:timer.sleep(:timer.seconds(:rand.uniform(delay)))
end)
end
end
def push(url, %{count: count, delay: delay}, custom_params) do
{_, reply} = Http.fetch_lat_lng()
my_coords = decode_lat_long(reply)
params = ["lat=#{my_coords.lat}", "lng=#{my_coords.lng}"]
custom_params_list =
Enum.map(custom_params, fn x ->
{key, val} = x
key <> "=" <> val
end)
params = Enum.concat(custom_params_list, params)
Http.push(url, Enum.join(params, "&"))
for _ <- 1..count do
{_, trip_coords} = random()
Enum.each(trip_coords, fn x ->
params = ["lat=#{x.start_location.lat}", "lng=#{x.start_location.lng}"]
params = Enum.concat(custom_params_list, params)
Http.push(url, Enum.join(params, "&"))
:timer.sleep(:timer.seconds(:rand.uniform(delay)))
Http.push(url, Enum.join(params, "&"))
:timer.sleep(:timer.seconds(:rand.uniform(delay)))
end)
end
end
def push(url, %{count: count, delay: delay}, custom_params, origin) do
params = ["lat=#{origin.lat}", "lng=#{origin.lng}"]
custom_params_list =
Enum.map(custom_params, fn x ->
{key, val} = x
key <> "=" <> val
end)
params = Enum.concat(custom_params_list, params)
Http.push(url, Enum.join(params, "&"))
result =
for _ <- 1..count do
{status, trip_coords} = random()
case status do
:ok ->
Enum.each(trip_coords, fn x ->
params = ["lat=#{x.start_location.lat}", "lng=#{x.start_location.lng}"]
params = Enum.concat(custom_params_list, params)
Http.push(url, Enum.join(params, "&"))
:timer.sleep(:timer.seconds(:rand.uniform(delay)))
params = ["lat=#{x.end_location.lat}", "lng=#{x.end_location.lng}"]
params = Enum.concat(custom_params_list, params)
Http.push(url, Enum.join(params, "&"))
:timer.sleep(:timer.seconds(:rand.uniform(delay)))
end)
:error ->
{:error, trip_coords}
end
end
result
|> Enum.filter(fn x -> x == :ok end)
case Enum.count(result) do
0 -> :ok
result -> List.first(result)
end
end
@doc """
## Get a random place geocoords based on starting location
"""
def random(radius \\ 5000) do
{status, result} = Http.geo_locate()
{status, decoded} = Jason.decode(result.body)
case status do
:ok ->
coords = decoded.location
lat = to_string(coords.lat)
lng = to_string(coords.lng)
type = Enum.random(@types)
params = %{lat: lat, lng: lng, radius: radius, type: type}
result = Http.nearby_search(params)
decoded_json = Jason.decode!(result.body)
reply =
case decoded_json do
%{"html_attributions" => [], "results" => [], "status" => "ZERO_RESULTS"} ->
{status, reply} = random()
case status do
:ok -> reply
:error -> []
end
_ ->
decoded_json.results
end
locations =
Enum.map(reply, fn x ->
get_coords(x)
end)
create_route(locations)
:error ->
if maybe(decoded.message) do
{:error, decoded.message}
else
{:error, "Error Fetching Results"}
end
end
end
@doc """
## Get coordinates from a location result
"""
def get_coords(data) do
case data do
%{lat: _lat, lng: _lng, name: _name} ->
data
_ ->
geometry = data.geometry
coords = geometry.location
name = data.name
vicinity = data.vicinity
%{name: name, lat: coords.lat, lng: coords.lng, vicinity: vicinity}
end
end
@doc """
## Create a driving route from location coords
"""
def create_route(locations \\ []) do
case(Enum.count(locations) > 1) do
true ->
[origin | destination] = Enum.chunk_every(locations, 2)
result = Http.waypoints(%{origin: origin, destination: destination})
waypoints_json = Jason.decode!(result.body)
[routes] = waypoints_json.routes
legs = routes.legs
steps =
Enum.map(legs, fn x ->
x.steps
end)
# Map.get(x, "start_location")
waypoints =
List.flatten(steps)
|> Enum.map(fn x ->
start_loc = x.start_location
start_map = %{lat: start_loc.lat, lng: start_loc.lng}
end_loc = x.end_location
end_map = %{lat: end_loc.lat, lng: end_loc.lng}
%{start_location: start_map, end_location: end_map}
end)
{:ok, waypoints}
false ->
{:error, "Locations must be greater then 2"}
end
end
@doc """
## get the coords of the current server
"""
def decode_lat_long(data) do
decoded = Jason.decode(data)
is_json =
case decoded do
{:error, _msg} -> false
_ -> true
end
case is_json do
false ->
%{lat: 0, lng: 0}
true ->
lat = to_string(decoded.latitude)
lng = to_string(decoded.longitude)
%{lat: lat, lng: lng}
end
end
end