Set Up

In this assignment you will be writing code to use Google's GeoCoding and Places APIs.

You will need to install the googlemaps Python package. Go to your Project Settings (Ctrl-Alt-S) and click the green plus sign on the right, search for and install the googlemaps package. see image.

You will need to go to https://console.developers.google.com/ (Links to an external site.)Links to an external site. to create a project, register to use those APIs, and get an API key

Requirements

Starter Files

Download the starter zip GeoCodeFunStarter.zip. It contains the following:

  • geocode_utils.py - this file contains a few helper classes and functions for you to use. You may NOT change any code in this file. Some notes on what is included:
    • oGeoLocation class which holds latitude and longitude and can compute it's distance to another GeoLocation object.
    • oGeoCoder class which contains class methods to use Google Maps API and Google Places API to get information about an address. See the __main__ section in geocode_utils for examples of how to use GeoCoder.find. Note: the GeoCoder.find_place method requires that the PlaceInformation class has been completed. The GeoCoder methods cache the results from find and find_place, reducing the likelihood that you will exceed your 1,000 geocode requests/day limit.
  • geocode.py - this file contains stubs with TODO notes for functionality that you must implement
  • small-places.txt - a sample places file containing 6 places. Later you will be given the crowdsourced places file.
  • hills-pine-docs.csv - a CSV file of all the doctors in Hillsborough and Pinellas counties who are certified to provide medical marijuana orders (as of April, 2017), part of a project I am working on with some colleagues who are journalists.

What to Implement

You must implement the following in geocode.py.

PlaceInformation methods

The first three get_ methods simply return the values that were provided when the object was constructed.

The __str__ method should return the name followed by the location details inside parentheses. It includes a doctest to ensure you have formatted it properly.

Although the constructor takes a latitude and longitude, you should store this information inside the PlaceInformation object using a GeoLocation object (see geocode_utils.py). The get_location method should return this GeoLocation object. Remember that in writing your class, you don't want to include code that appears elsewhere. For example, your GeoLocationobject knows how to compute a distance, so you should not be repeating the code for computing distances in your PlaceInformation class. You should instead be asking the GeoLocationobject to perform the computation.

Note that the other parameter of PlaceInformation's distance_from method can either be a PlaceInformation or GeoLocation object. Hint: isinstance is your friend.

This class is similar to the GeoLocation class, so you can use it as a model for how to write your own class. The GeoLocation class will also provide a useful example of how to comment your class. Each method should be commented and the class itself should have a general comment.

read_places_file

Given a filename of a places file (5 lines per entry), return a list of PlaceInformation objects in that file. Hint: the group_places function in geocode_utils can assist with this.

read_docs_file

Given a filename for the CSV file containing the list of medical marijuana doctors, return a list of PlaceInformation objects for each doctor. The name field should be the doctor's first and last name, and the tag should be 'medical marijuana doctor'. Remember CSV files are just plain text files where the fields/columns are separated by commas.

get_distances_to

Given a GeoLocation object and a list of PlaceInformation, return a sorted (from closest to farthest) list of tuples where the first element in the tuple is the distance from the GeoLocation object to the PlaceInformation object, and the seond element is the PlaceInformation object.

So for example, given a list named places that looks like the following:

[PlaceInformation((swah-rey), 2105 Central Ave, St. Petersburg, FL 33713, cafe, bar, dessert, GeoLocation(27.771237, -82.661880)),
PlaceInformation(Treasure Island, 10400 Gulf Blvd, Treasure Island, FL 33706, beach, GeoLocation(27.766331, -82.768642)),
PlaceInformation(Tampa Bay Brewing Company, 1600 E 9th Ave, Tampa, FL 33605, bar, restaurant, food, the pretzels are to die for, GeoLocation(27.961419, -82.441667))]

The call, get_distances_to(GeoLocation(28.058726, -82.415481), places) returns:

[(6.918112476360289,
PlaceInformation(Tampa Bay Brewing Company, 1600 E 9th Ave, Tampa, FL 33605, bar, restaurant, food, the pretzels are to die for, GeoLocation(27.961419, -82.441667))),
(24.945043802670956,
PlaceInformation((swah-rey), 2105 Central Ave, St. Petersburg, FL 33713, cafe, bar, dessert, GeoLocation(27.771237, -82.661880))),
(29.58076422739298,
PlaceInformation(Treasure Island, 10400 Gulf Blvd, Treasure Island, FL 33706, beach, GeoLocation(27.766331, -82.768642)))]

Also see the doctest for an example.

Hint: List comprehensions are your friend. Also see the sorted function (Links to an external site.)Links to an external site. and it's key parameter.

find_nearest

Given a GeoLocation object and a list of PlaceInformation, returns the PlaceInformation object that is nearest to the GeoLocation object.

There are a few ways of approaching this. One is to have a look at Python's builtin min function (Links to an external site.)Links to an external site. and its key parameter. However, if you are clever you may be able to enslave one of the other functions you are writing for this assignment.

find_matching_places

Given list of PlaceInformation object and a name and/or tag to search for find the matching places. If both name and tag parameters are None then return the original list. You are strongly encouraged to use re.search (Links to an external site.)Links to an external site. to do matching. See doctests for examples.

Note about doctests

The doctests that are provided are not exhaustive. They are there to provide guidance for how your function should behave. However, they do not test every case and, in fact, during grading the TA will use different test cases.

Also note, that if you simply hardcode your functions to only return the result listed in the doctests, you will receive a 0.

Academic Honesty!
It is not our intention to break the school's academic policy. Posted solutions are meant to be used as a reference and should not be submitted as is. We are not held liable for any misuse of the solutions. Please see the frequently asked questions page for further questions and inquiries.
Kindly complete the form. Please provide a valid email address and we will get back to you within 24 hours. Payment is through PayPal, Buy me a Coffee or Cryptocurrency. We are a nonprofit organization however we need funds to keep this organization operating and to be able to complete our research and development projects.