Shipping with APIs
Please Log In for full access to the web site.
Note that this link will take you to an external site (https://shimmer.mit.edu) to authenticate, and then you will be redirected back to this page.
1) Overview
With the recent heat waves, the Northern Ice Cream Exports (NICE) company has received a spike in complaints from customers about their ice cream orders arriving melted. As an intern at NICE, you have been tasked with finding the minimum number of ice packs that packages shipped out of the company warehouse in Cambridge, MA need to stay cool.
This zip file HERE contains a skeleton lab.py
file that you should work in and a file of tests in test.py
. To run the test cases, make sure the file where you are writing code is named lab.py
and then you can run the test.py
file as you would any other Python file. The test file has the same test cases as the code checker so it will be useful in debugging.
You are tasked with writing a function get_ice_packs
, which takes in an order dictionary of the form:
{"ID":"52", "Address":"100 Valley Drive", "City":"Helena", "State":"MT", "Zip Code":"59602", "Item":"tomatoes", "Amount":"17"}
And returns an integer number of ice packs required for this shipment. NICE has an extremely sophisticated formula for the number of ice packs:
where
- N is the number of ice packs
- T is the maximum temperature between the shipping location (Cambridge MA, 02142) and the delivery location on the current day.
- D is the distance between shipping and delivery locations.
Note: since the number of ice packs should always be an integer, we should round any decimal amounts up so we still have enough cooling capacity. So if we calculate N = 4.0, we should return 4 ice packs, but if N = 4.01, we should return 5 ice packs.
We also provide you with some useful tools:
- A csv file
ZIP_codes.csv
for determining the latitude/longitude of various zipcodes - An API endpoint that we can call with a latitude and longitude to get a url for finding weather data
- An API endpoint for determining distances between two zip codes
Before you start coding though, please go through the next section introducing API usage.
2) Intro to APIs
For this exercise we're going to be learning about APIs. An API, or Application Program Interface, is a way to communicate with other applications - usually sending and receiving data.
The most common form of API is a web API that is performed by sending an HTTP request, or essentially visiting a URL of a website. But instead of returning a pretty web page it'll return data packaged in a string that looks very similar to a python dictionary. In fact we can use some tools to convert it directly into a python dictionary. We'll be using web APIs for this exercise.
2.1) Weather API
For example if in another tab you visit this URL, you'll see the weekly forecast for Alliance, Nebraska - home of the famous Carhenge. This is an example of the weather API you can read about at api.weather.gov.
There's a lot of information here, tucked inside nested dictionary format, but what we'll mostly be concerned with are the "periods"
which show daily temperatures, such as:
"periods": [
{
"number": 7,
"name": "Monday",
"startTime": "2021-07-12T12:00:00-06:00",
"endTime": "2021-07-12T18:00:00-06:00",
"isDaytime": true,
"temperature": 90,
"temperatureUnit": "F",
},
]
From which we'll be able to know that Monday, July 12, 2021, has a high of 90 degrees. That's all very helpful, but how do we determine what the URL we need is? Fortunately, the weather API has another endpoint that takes in a latitude and longitude and will help us figure out the forecast URL. For example, try visiting:
https://api.weather.gov/points/42.1423,-102.8580
You'll see that down below the key "properties"
maps to a dictionary, and in that dictionary there's a key for "forecast"
. The value of forecast
is the URL for the forecast API.
To test your understanding, try finding the high temperature for Cambridge, (42.393246,-71.133833) for tomorrow during the day and enter the result rounded to an integer below. Hint, you'll need to edit the above URL to use the coordinates for Cambridge. Then you can visit that page and find the URL for the forecast API for Cambridge.
For this API, we format the url as such, filling in the respective areas for latitude and longitude:
https://api.weather.gov/points/<latitude>,<longitude>
2.2) Calling APIs in Python
Now you're able to visit an API manually, but let's see how to do the same process in code. We'll be using the requests
library in order to retreive the data you saw on your browser, and then convert it into a python dictionary. For example, the following code will retreive the same data as visiting the url. We then convert the response to a python dictionary using the .json()
method.
import requests
url = "https://api.weather.gov/points/42.1423,-102.8580"
response = requests.get(url)
data = response.json()
print(data)
Check yourself by writing a function get_temp(latitude, longitude)
that given a latitude and longitude point, visits the url at that point, and extracts the forecast url from the returned dictionary. Then use the extracted url to make another API request and get the forecast data from the response. For this assignment, we will only use the temperature from the period with number
equal to 1, extract and print that temperature.
Submit your get_temp
code in a file named lab.py
below. Note that the tests run are the same as the two test_temp test cases in the test.py
file you downloaded.
2.3) API Keys
Some APIs require you to have an account in order to use the service. We'll only be using free APIs right now, but one of them (the zipcode distance API) requires making a free account. You should do so here by clicking on the green Free Key button. You'll receive an email and be able to access an API key which is a string of characters. You can use "Shipping API" as the application name and we recommend signing up with an email that you don't care about much to avoid spam. Once you've signed up, you will be able to get an API key here. We'll include the API key as part of the url for the API request.
For this specific API, we format the url as such:
https://www.zipcodeapi.com/rest/<api-key>/distance.<format>/<zip1>/<zip2>/<unit>
For example, when we call the API, we use the staff key of 65wLFxIkjMfl9c3VfbqPdRQST9ZmnYEz9DDZ9xy1NySkOsJFsW73V8isUYDdaBnb
. We'll use json
for the format so we can easily convert the response to a Python dictionary. An example url is as follows:
https://www.zipcodeapi.com/rest/65wLFxIkjMfl9c3VfbqPdRQST9ZmnYEz9DDZ9xy1NySkOsJFsW73V8isUYDdaBnb/distance.json/02115/59602/mile
To check yourself, use either python or a web browser to find the distance between Cambridge (02142) and Brooklyn (11222).
3) Implementation
Now that we've gone over how to use these API tools, let's revisit what we need to accomplish in this assignment and the high level functionality of get_ice_packs(order)
.
As an example if we input this order
{"ID":"52", "Address":"100 Valley Drive", "City":"Helena", "State":"MT", "Zip Code":"59602", "Item":"tomatoes", "Amount":"17"}
Then we'll use the csv file ZIP_codes.csv
to determine the latitude and longitude for the start and destination zipcodes. Next we use those to call the weather API, and we'll say we got 80
degrees for zipcode 59602 and 75
degrees for zipcode 02142 for their respective period 1 entries. According to the zipcode API, the distance is 2009.656
. Then according to the formula, we would need (80-70)*2009.656/1000 = 20.09, or 21 whole ice packs. Our function should then return the integer 21.
Submit your finished code below and note that the tests run are the same as those in the test.py
file you downloaded.
Next Exercise: Electric Bill