Question: Write in python DO NOT CHANGE ANY OF THE CODE IN THIS FILE import googlemaps class GeoLocation(object): Object that holds _latitude and
Write in python
""" DO NOT CHANGE ANY OF THE CODE IN THIS FILE """ import googlemaps class GeoLocation(object): """ Object that holds _latitude and _longitude values. Based off Stu Reges' code at http://nifty.stanford.edu/2015/reges-geolocator/GeoLocation.java, last access 10/15/2017 """ def __init__(self, latitude: float, longitude: float): self._latitude = latitude self._longitude = longitude def get_latitude(self) -> float: """ Returns the latitude :return: the latitude """ return self._latitude def get_longitude(self) -> float: """ Returns the longitude :return: the longitude """ return self._longitude def distance_from(self, other) -> float: """ Returns the distance between this GeoLocation object and other :param other: the other GeoLocation object to compute the distance to :return: the distance between this GeoLocation object and other """ import math radius = 3963.1676 # Earth's radius in miles lat1 = math.radians(self._latitude) long1 = math.radians(self._longitude) lat2 = math.radians(other._latitude) long2 = math.radians(other._longitude) # apply the spherical law of cosines with a triangle composed of the # two locations and the north pole the_cos = math.sin(lat1) * math.sin(lat2) \ + math.cos(lat1) * math.cos(lat2) \ * math.cos(long1 - long2) arc_length = math.acos(the_cos) return arc_length * radius def __str__(self): """ Returns a string representation of the object suitable for users :return: a string representation of the object suitable for users """ return 'latitude: {:f}, longitude: {:f}'.format(self._latitude, self._longitude) def __repr__(self): """ Returns a string representation of the object suitable for developers :return: a string representation of the object suitable for developers """ return 'GeoLocation({:f}, {:f})'.format(self._latitude, self._longitude) def get_key(): """ Returns the Google API Key from the api_key.ini file :return: the Google API Key from the api_key.ini file """ import configparser config = configparser.ConfigParser() config.read('api_key.ini') if config['DEFAULT']['GoogleAPIKey'] == 'YOUR API KEY HERE': raise ValueError('You must set your API key in api_key.ini!') return config['DEFAULT']['GoogleAPIKey'] class GeoCoder(object): """ Class to handle geocoding look ups via (memoized) class methods. """ # the name of the geocode cache file __geocode_cache_filename = 'find.cache' # the name of the place cache file __place_cache_filename = 'place.cache' # Used to cache geocoding queries __geocode_cache = {} # Used to cache results of place queries __place_cache = {} @classmethod def __write_cache(cls, filename, cache): """ Writes the cache to the specified file :param filename: the file to write to :param cache: the cache to be pickled """ import pickle with open(filename, 'wb+') as outfile: outfile.write(pickle.dumps(cls.__geocode_cache)) @classmethod def __read_cache(cls, filename): """ Reads the cache from the specified file and returns it :param filename: the file containing the (pickled) cache :return: the cache data read from the file """ import pickle with open(filename, 'rb') as infile: return pickle.loads(infile.read()) @classmethod def find(cls, query: str, raw=False): """ Returns geocoding info for the specified place :param query: an address or place (string) to get the coordinates for :param raw: optional parameter, if true returns the raw geocode result instead of a GeoLocation object :return: a GeoLocation object, if raw is False, and the raw geocoding result, if raw is True, for the specified place """ import os.path # if cache is empty, check to see if cache file exists if len(cls.__geocode_cache) == 0 and os.path.isfile('find.cache'): with open('find.cache', 'rb') as infile: cls.__geocode_cache = cls.__read_cache(cls.__geocode_cache_filename) geo_res = None # first check if result is in cache if query in cls.__geocode_cache: geo_res = cls.__geocode_cache[query] else: # it wasn't so do the query gmaps = googlemaps.Client(key=get_key()) results = gmaps.geocode(query) if len(results) < 1: return None geo_res = results[0] # store the results in the cache cls.__geocode_cache[query] = geo_res # save the results cls.__write_cache(cls.__geocode_cache_filename, cls.__geocode_cache) if not raw: return GeoLocation(geo_res['geometry']['location']['lat'], geo_res['geometry']['location']['lng']) else: return geo_res @classmethod def find_place(cls, query: str, raw=False): """ Returns PlaceInformation for the specified place :param query: a name/address of the place to lookup :param raw: optional parameter, if true returns the raw place result instead of a PlaceInformation object :return: a PlaceInformation object, if raw is False, and the raw place result, if raw is True, for the specified place """ import os.path from geocode import PlaceInformation # if cache is empty, check to see if cache file exists if len(cls.__place_cache) == 0 and os.path.isfile(cls.__place_cache_filename): cls.__place_cache = cls.__read_cache(cls.__place_cache_filename) place_res = None # first check if result is in cache if query in cls.__place_cache: place_res = cls.__place_cache[query] else: # it wasn't so do the query gmaps = googlemaps.Client(key=get_key()) # first get the place id geo_res = cls.find(query, True) # now access Google Places API for name place_res = gmaps.place(geo_res['place_id'])['result'] # store the results in the cache cls.__place_cache[query] = place_res # save the results cls.__write_cache(cls.__place_cache_filename, cls.__place_cache) if not raw: return PlaceInformation(place_res['name'], place_res['formatted_address'], ', '.join(place_res['types']), float(place_res['geometry']['location']['lat']), float(place_res['geometry']['location']['lng'])) else: return place_res def group_places(filename): """ Returns a list of tuples of the entries in a places file (5 lines per entry) :param filename: a places file (5 lines per entry) :return: a list of tuples of the entries in a places file (5 lines per entry) """ def grouper(n, iterable, padvalue=None): """ grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g','x','x') taken from https://docs.python.org/3/library/itertools.html#itertools-recipes, last access 10/30/2017 """ from itertools import zip_longest return zip_longest(*[iter(iterable)] * n, fillvalue=padvalue) with open(filename, 'r') as infile: lines = [line.strip() for line in infile.readlines() if len(line.strip()) > 1] if len(lines) % 5 != 0: raise Exception('Lines in file must be a multiple of 5') return list(grouper(5, lines)) if __name__ == "__main__": good_addr = 'Good, Trout Run, PA 17771, USA' good = GeoCoder.find(good_addr) # example of how to use GeoCoder.find print('good:', good) evil_addr = 'Evil Avenue, Belleville, IL 62221, USA' evil = GeoCoder.find(evil_addr) print('evil:', evil) print('Distance between good, {}, and evil, {}, is {} miles.'.format(good, evil, round(good.distance_from(evil), 3))) from typing import List, Tuple from geocode_utils import * class PlaceInformation(object): def __init__(self, name, address, tag, latitude, longitude): # TODO: Replace pass below with your implementation self._name = name self._address = address self._tag = tag self._location = GeoLocation(latitude, longitude) pass def get_name(self): # TODO: Replace pass below with your implementation return self._name pass def get_address(self): return self._address # TODO: Replace pass below with your implementation pass def get_tag(self): return self._tag # TODO: Replace pass below with your implementation pass def get_location(self) -> GeoLocation: return self._location # TODO: Replace pass below with your implementation pass
def distance_from(self, other): """ Returns the distance between self and other. :param other: either a GeoLocation object or a PlaceInformation object :return: the distance from other >>> good = PlaceInformation('Good', 'Good, Trout Run, PA 17771, USA', 'good, opposite of evil', 41.385746, -77.055198) >>> round(good.distance_from(GeoLocation(38.541242, -89.886266)), 2) 707.36 >>> good = PlaceInformation('Good', 'Good, Trout Run, PA 17771, USA', 'good, opposite of evil', 41.385746, -77.055198) >>> evil = PlaceInformation('Evil Avenue', 'Evil Ave, Belleville, IL 62221, USA', 'evil, opposite of good', 38.541242, -89.886266) >>> round(good.distance_from(evil),2) 707.36 """ return 707.36 # TODO: Replace pass below with your implementation pass
Step by Step Solution
There are 3 Steps involved in it
1 Expert Approved Answer
Step: 1 Unlock
Question Has Been Solved by an Expert!
Get step-by-step solutions from verified subject matter experts
Step: 2 Unlock
Step: 3 Unlock
