Skip to content

Instantly share code, notes, and snippets.

@hi5san
Created September 23, 2019 05:59
Show Gist options
  • Save hi5san/4b0276d2f336be15f04e112bc43b852e to your computer and use it in GitHub Desktop.
Save hi5san/4b0276d2f336be15f04e112bc43b852e to your computer and use it in GitHub Desktop.
Created on Cognitive Class Labs
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"<a href=\"https://cognitiveclass.ai\"><img src = \"https://ibm.box.com/shared/static/9gegpsmnsoo25ikkbl4qzlvlyjbgxs5x.png\" width = 400> </a>\n",
"\n",
"<h1 align=center><font size = 5>Learning FourSquare API with Python</font></h1>"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"## Introduction\n",
"\n",
"In this lab, you will learn in details how to make calls to the Foursquare API for different purposes. You will learn how to construct a URL to send a request to the API to search for a specific type of venues, to explore a particular venue, to explore a Foursquare user, to explore a geographical location, and to get trending venues around a location. Also, you will learn how to use the visualization library, Folium, to visualize the results."
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"## Table of Contents\n",
"\n",
"1. <a href=\"#item1\">Foursquare API Search Function</a>\n",
"2. <a href=\"#item2\">Explore a Given Venue</a> \n",
"3. <a href=\"#item3\">Explore a User</a> \n",
"4. <a href=\"#item4\">Foursquare API Explore Function</a> \n",
"5. <a href=\"#item5\">Get Trending Venues</a> "
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"### Import necessary Libraries"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Solving environment: done\n",
"\n",
"\n",
"==> WARNING: A newer version of conda exists. <==\n",
" current version: 4.5.11\n",
" latest version: 4.7.12\n",
"\n",
"Please update conda by running\n",
"\n",
" $ conda update -n base -c defaults conda\n",
"\n",
"\n",
"\n",
"## Package Plan ##\n",
"\n",
" environment location: /home/jupyterlab/conda/envs/python\n",
"\n",
" added / updated specs: \n",
" - geopy\n",
"\n",
"\n",
"The following packages will be downloaded:\n",
"\n",
" package | build\n",
" ---------------------------|-----------------\n",
" geopy-1.20.0 | py_0 57 KB conda-forge\n",
" certifi-2019.9.11 | py36_0 147 KB conda-forge\n",
" geographiclib-1.49 | py_0 32 KB conda-forge\n",
" ------------------------------------------------------------\n",
" Total: 237 KB\n",
"\n",
"The following NEW packages will be INSTALLED:\n",
"\n",
" geographiclib: 1.49-py_0 conda-forge\n",
" geopy: 1.20.0-py_0 conda-forge\n",
"\n",
"The following packages will be UPDATED:\n",
"\n",
" certifi: 2019.6.16-py36_1 conda-forge --> 2019.9.11-py36_0 conda-forge\n",
"\n",
"\n",
"Downloading and Extracting Packages\n",
"geopy-1.20.0 | 57 KB | ##################################### | 100% \n",
"certifi-2019.9.11 | 147 KB | ##################################### | 100% \n",
"geographiclib-1.49 | 32 KB | ##################################### | 100% \n",
"Preparing transaction: done\n",
"Verifying transaction: done\n",
"Executing transaction: done\n",
"Solving environment: done\n",
"\n",
"\n",
"==> WARNING: A newer version of conda exists. <==\n",
" current version: 4.5.11\n",
" latest version: 4.7.12\n",
"\n",
"Please update conda by running\n",
"\n",
" $ conda update -n base -c defaults conda\n",
"\n",
"\n",
"\n",
"# All requested packages already installed.\n",
"\n",
"Folium installed\n",
"Libraries imported.\n"
]
}
],
"source": [
"import requests # library to handle requests\n",
"import pandas as pd # library for data analsysis\n",
"import numpy as np # library to handle data in a vectorized manner\n",
"import random # library for random number generation\n",
"\n",
"!conda install -c conda-forge geopy --yes \n",
"from geopy.geocoders import Nominatim # module to convert an address into latitude and longitude values\n",
"\n",
"# libraries for displaying images\n",
"from IPython.display import Image \n",
"from IPython.core.display import HTML \n",
" \n",
"# tranforming json file into a pandas dataframe library\n",
"from pandas.io.json import json_normalize\n",
"\n",
"!conda install -c conda-forge folium=0.5.0 --yes\n",
"import folium # plotting library\n",
"\n",
"print('Folium installed')\n",
"print('Libraries imported.')"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"### Define Foursquare Credentials and Version"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"##### Make sure that you have created a Foursquare developer account and have your credentials handy"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Your credentails:\n",
"CLIENT_ID: SFOI1LSHZYPN20MQJFSHU3FVJRWXXC3ZOURGWSLLNO24OYWO\n",
"CLIENT_SECRET:GNL5N5NYVCDKI3OSZBZLCFCWB41GO2BSZWJSN2CDWRTSXSJJ\n"
]
}
],
"source": [
"CLIENT_ID = 'SFOI1LSHZYPN20MQJFSHU3FVJRWXXC3ZOURGWSLLNO24OYWO' # your Foursquare ID\n",
"CLIENT_SECRET = 'GNL5N5NYVCDKI3OSZBZLCFCWB41GO2BSZWJSN2CDWRTSXSJJ' # your Foursquare Secret\n",
"VERSION = '20180604'\n",
"LIMIT = 30\n",
"print('Your credentails:')\n",
"print('CLIENT_ID: ' + CLIENT_ID)\n",
"print('CLIENT_SECRET:' + CLIENT_SECRET)"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Let's again assume that you are staying at the Conrad hotel. So let's start by converting the Contrad Hotel's address to its latitude and longitude coordinates."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In order to define an instance of the geocoder, we need to define a user_agent. We will name our agent <em>foursquare_agent</em>, as shown below."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"40.7149555 -74.0153365\n"
]
}
],
"source": [
"address = '102 North End Ave, New York, NY'\n",
"\n",
"geolocator = Nominatim(user_agent=\"foursquare_agent\")\n",
"location = geolocator.geocode(address)\n",
"latitude = location.latitude\n",
"longitude = location.longitude\n",
"print(latitude, longitude)"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"<a id=\"item1\"></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"## 1. Search for a specific venue category\n",
"> `https://api.foursquare.com/v2/venues/`**search**`?client_id=`**CLIENT_ID**`&client_secret=`**CLIENT_SECRET**`&ll=`**LATITUDE**`,`**LONGITUDE**`&v=`**VERSION**`&query=`**QUERY**`&radius=`**RADIUS**`&limit=`**LIMIT**"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Now, let's assume that it is lunch time, and you are craving Italian food. So, let's define a query to search for Italian food that is within 500 metres from the Conrad Hotel. "
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
},
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Italian .... OK!\n"
]
}
],
"source": [
"search_query = 'Italian'\n",
"radius = 500\n",
"print(search_query + ' .... OK!')"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Define the corresponding URL"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/plain": [
"'https://api.foursquare.com/v2/venues/search?client_id=SFOI1LSHZYPN20MQJFSHU3FVJRWXXC3ZOURGWSLLNO24OYWO&client_secret=GNL5N5NYVCDKI3OSZBZLCFCWB41GO2BSZWJSN2CDWRTSXSJJ&ll=40.7149555,-74.0153365&v=20180604&query=Italian&radius=500&limit=30'"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"url = 'https://api.foursquare.com/v2/venues/search?client_id={}&client_secret={}&ll={},{}&v={}&query={}&radius={}&limit={}'.format(CLIENT_ID, CLIENT_SECRET, latitude, longitude, VERSION, search_query, radius, LIMIT)\n",
"url"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Send the GET Request and examine the results"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
},
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
"{'meta': {'code': 200, 'requestId': '5d880bb15315930031ca1832'},\n",
" 'response': {'venues': [{'id': '4fa862b3e4b0ebff2f749f06',\n",
" 'name': \"Harry's Italian Pizza Bar\",\n",
" 'location': {'address': '225 Murray St',\n",
" 'lat': 40.71521779064671,\n",
" 'lng': -74.01473940209351,\n",
" 'labeledLatLngs': [{'label': 'display',\n",
" 'lat': 40.71521779064671,\n",
" 'lng': -74.01473940209351}],\n",
" 'distance': 58,\n",
" 'postalCode': '10282',\n",
" 'cc': 'US',\n",
" 'city': 'New York',\n",
" 'state': 'NY',\n",
" 'country': 'United States',\n",
" 'formattedAddress': ['225 Murray St',\n",
" 'New York, NY 10282',\n",
" 'United States']},\n",
" 'categories': [{'id': '4bf58dd8d48988d1ca941735',\n",
" 'name': 'Pizza Place',\n",
" 'pluralName': 'Pizza Places',\n",
" 'shortName': 'Pizza',\n",
" 'icon': {'prefix': 'https://ss3.4sqi.net/img/categories_v2/food/pizza_',\n",
" 'suffix': '.png'},\n",
" 'primary': True}],\n",
" 'delivery': {'id': '294544',\n",
" 'url': 'https://www.seamless.com/menu/harrys-italian-pizza-bar-225-murray-st-new-york/294544?affiliate=1131&utm_source=foursquare-affiliate-network&utm_medium=affiliate&utm_campaign=1131&utm_content=294544',\n",
" 'provider': {'name': 'seamless',\n",
" 'icon': {'prefix': 'https://fastly.4sqi.net/img/general/cap/',\n",
" 'sizes': [40, 50],\n",
" 'name': '/delivery_provider_seamless_20180129.png'}}},\n",
" 'referralId': 'v-1569196977',\n",
" 'hasPerk': False},\n",
" {'id': '4f3232e219836c91c7bfde94',\n",
" 'name': 'Conca Cucina Italian Restaurant',\n",
" 'location': {'address': '63 W Broadway',\n",
" 'lat': 40.71446,\n",
" 'lng': -74.010086,\n",
" 'labeledLatLngs': [{'label': 'display',\n",
" 'lat': 40.71446,\n",
" 'lng': -74.010086}],\n",
" 'distance': 446,\n",
" 'postalCode': '10007',\n",
" 'cc': 'US',\n",
" 'city': 'New York',\n",
" 'state': 'NY',\n",
" 'country': 'United States',\n",
" 'formattedAddress': ['63 W Broadway',\n",
" 'New York, NY 10007',\n",
" 'United States']},\n",
" 'categories': [{'id': '4d4b7105d754a06374d81259',\n",
" 'name': 'Food',\n",
" 'pluralName': 'Food',\n",
" 'shortName': 'Food',\n",
" 'icon': {'prefix': 'https://ss3.4sqi.net/img/categories_v2/food/default_',\n",
" 'suffix': '.png'},\n",
" 'primary': True}],\n",
" 'referralId': 'v-1569196977',\n",
" 'hasPerk': False},\n",
" {'id': '3fd66200f964a520f4e41ee3',\n",
" 'name': 'Ecco',\n",
" 'location': {'address': '124 Chambers St',\n",
" 'crossStreet': 'btwn Church St & W Broadway',\n",
" 'lat': 40.71533713859952,\n",
" 'lng': -74.00884766217825,\n",
" 'labeledLatLngs': [{'label': 'display',\n",
" 'lat': 40.71533713859952,\n",
" 'lng': -74.00884766217825}],\n",
" 'distance': 549,\n",
" 'postalCode': '10007',\n",
" 'cc': 'US',\n",
" 'city': 'New York',\n",
" 'state': 'NY',\n",
" 'country': 'United States',\n",
" 'formattedAddress': ['124 Chambers St (btwn Church St & W Broadway)',\n",
" 'New York, NY 10007',\n",
" 'United States']},\n",
" 'categories': [{'id': '4bf58dd8d48988d110941735',\n",
" 'name': 'Italian Restaurant',\n",
" 'pluralName': 'Italian Restaurants',\n",
" 'shortName': 'Italian',\n",
" 'icon': {'prefix': 'https://ss3.4sqi.net/img/categories_v2/food/italian_',\n",
" 'suffix': '.png'},\n",
" 'primary': True}],\n",
" 'referralId': 'v-1569196977',\n",
" 'hasPerk': False}]}}"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"results = requests.get(url).json()\n",
"results"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Get relevant part of JSON and transform it into a *pandas* dataframe"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>id</th>\n",
" <th>name</th>\n",
" <th>categories</th>\n",
" <th>referralId</th>\n",
" <th>hasPerk</th>\n",
" <th>location.address</th>\n",
" <th>location.lat</th>\n",
" <th>location.lng</th>\n",
" <th>location.labeledLatLngs</th>\n",
" <th>location.distance</th>\n",
" <th>...</th>\n",
" <th>location.state</th>\n",
" <th>location.country</th>\n",
" <th>location.formattedAddress</th>\n",
" <th>delivery.id</th>\n",
" <th>delivery.url</th>\n",
" <th>delivery.provider.name</th>\n",
" <th>delivery.provider.icon.prefix</th>\n",
" <th>delivery.provider.icon.sizes</th>\n",
" <th>delivery.provider.icon.name</th>\n",
" <th>location.crossStreet</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <td>0</td>\n",
" <td>4fa862b3e4b0ebff2f749f06</td>\n",
" <td>Harry's Italian Pizza Bar</td>\n",
" <td>[{'id': '4bf58dd8d48988d1ca941735', 'name': 'P...</td>\n",
" <td>v-1569196977</td>\n",
" <td>False</td>\n",
" <td>225 Murray St</td>\n",
" <td>40.715218</td>\n",
" <td>-74.014739</td>\n",
" <td>[{'label': 'display', 'lat': 40.71521779064671...</td>\n",
" <td>58</td>\n",
" <td>...</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>[225 Murray St, New York, NY 10282, United Sta...</td>\n",
" <td>294544</td>\n",
" <td>https://www.seamless.com/menu/harrys-italian-p...</td>\n",
" <td>seamless</td>\n",
" <td>https://fastly.4sqi.net/img/general/cap/</td>\n",
" <td>[40, 50]</td>\n",
" <td>/delivery_provider_seamless_20180129.png</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <td>1</td>\n",
" <td>4f3232e219836c91c7bfde94</td>\n",
" <td>Conca Cucina Italian Restaurant</td>\n",
" <td>[{'id': '4d4b7105d754a06374d81259', 'name': 'F...</td>\n",
" <td>v-1569196977</td>\n",
" <td>False</td>\n",
" <td>63 W Broadway</td>\n",
" <td>40.714460</td>\n",
" <td>-74.010086</td>\n",
" <td>[{'label': 'display', 'lat': 40.71446, 'lng': ...</td>\n",
" <td>446</td>\n",
" <td>...</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>[63 W Broadway, New York, NY 10007, United Sta...</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <td>2</td>\n",
" <td>3fd66200f964a520f4e41ee3</td>\n",
" <td>Ecco</td>\n",
" <td>[{'id': '4bf58dd8d48988d110941735', 'name': 'I...</td>\n",
" <td>v-1569196977</td>\n",
" <td>False</td>\n",
" <td>124 Chambers St</td>\n",
" <td>40.715337</td>\n",
" <td>-74.008848</td>\n",
" <td>[{'label': 'display', 'lat': 40.71533713859952...</td>\n",
" <td>549</td>\n",
" <td>...</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>[124 Chambers St (btwn Church St &amp; W Broadway)...</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>btwn Church St &amp; W Broadway</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>3 rows × 23 columns</p>\n",
"</div>"
],
"text/plain": [
" id name \\\n",
"0 4fa862b3e4b0ebff2f749f06 Harry's Italian Pizza Bar \n",
"1 4f3232e219836c91c7bfde94 Conca Cucina Italian Restaurant \n",
"2 3fd66200f964a520f4e41ee3 Ecco \n",
"\n",
" categories referralId hasPerk \\\n",
"0 [{'id': '4bf58dd8d48988d1ca941735', 'name': 'P... v-1569196977 False \n",
"1 [{'id': '4d4b7105d754a06374d81259', 'name': 'F... v-1569196977 False \n",
"2 [{'id': '4bf58dd8d48988d110941735', 'name': 'I... v-1569196977 False \n",
"\n",
" location.address location.lat location.lng \\\n",
"0 225 Murray St 40.715218 -74.014739 \n",
"1 63 W Broadway 40.714460 -74.010086 \n",
"2 124 Chambers St 40.715337 -74.008848 \n",
"\n",
" location.labeledLatLngs location.distance ... \\\n",
"0 [{'label': 'display', 'lat': 40.71521779064671... 58 ... \n",
"1 [{'label': 'display', 'lat': 40.71446, 'lng': ... 446 ... \n",
"2 [{'label': 'display', 'lat': 40.71533713859952... 549 ... \n",
"\n",
" location.state location.country \\\n",
"0 NY United States \n",
"1 NY United States \n",
"2 NY United States \n",
"\n",
" location.formattedAddress delivery.id \\\n",
"0 [225 Murray St, New York, NY 10282, United Sta... 294544 \n",
"1 [63 W Broadway, New York, NY 10007, United Sta... NaN \n",
"2 [124 Chambers St (btwn Church St & W Broadway)... NaN \n",
"\n",
" delivery.url delivery.provider.name \\\n",
"0 https://www.seamless.com/menu/harrys-italian-p... seamless \n",
"1 NaN NaN \n",
"2 NaN NaN \n",
"\n",
" delivery.provider.icon.prefix delivery.provider.icon.sizes \\\n",
"0 https://fastly.4sqi.net/img/general/cap/ [40, 50] \n",
"1 NaN NaN \n",
"2 NaN NaN \n",
"\n",
" delivery.provider.icon.name location.crossStreet \n",
"0 /delivery_provider_seamless_20180129.png NaN \n",
"1 NaN NaN \n",
"2 NaN btwn Church St & W Broadway \n",
"\n",
"[3 rows x 23 columns]"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# assign relevant part of JSON to venues\n",
"venues = results['response']['venues']\n",
"\n",
"# tranform venues into a dataframe\n",
"dataframe = json_normalize(venues)\n",
"dataframe.head()"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Define information of interest and filter dataframe"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
},
"scrolled": true
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>name</th>\n",
" <th>categories</th>\n",
" <th>address</th>\n",
" <th>lat</th>\n",
" <th>lng</th>\n",
" <th>labeledLatLngs</th>\n",
" <th>distance</th>\n",
" <th>postalCode</th>\n",
" <th>cc</th>\n",
" <th>city</th>\n",
" <th>state</th>\n",
" <th>country</th>\n",
" <th>formattedAddress</th>\n",
" <th>crossStreet</th>\n",
" <th>id</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <td>0</td>\n",
" <td>Harry's Italian Pizza Bar</td>\n",
" <td>Pizza Place</td>\n",
" <td>225 Murray St</td>\n",
" <td>40.715218</td>\n",
" <td>-74.014739</td>\n",
" <td>[{'label': 'display', 'lat': 40.71521779064671...</td>\n",
" <td>58</td>\n",
" <td>10282</td>\n",
" <td>US</td>\n",
" <td>New York</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>[225 Murray St, New York, NY 10282, United Sta...</td>\n",
" <td>NaN</td>\n",
" <td>4fa862b3e4b0ebff2f749f06</td>\n",
" </tr>\n",
" <tr>\n",
" <td>1</td>\n",
" <td>Conca Cucina Italian Restaurant</td>\n",
" <td>Food</td>\n",
" <td>63 W Broadway</td>\n",
" <td>40.714460</td>\n",
" <td>-74.010086</td>\n",
" <td>[{'label': 'display', 'lat': 40.71446, 'lng': ...</td>\n",
" <td>446</td>\n",
" <td>10007</td>\n",
" <td>US</td>\n",
" <td>New York</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>[63 W Broadway, New York, NY 10007, United Sta...</td>\n",
" <td>NaN</td>\n",
" <td>4f3232e219836c91c7bfde94</td>\n",
" </tr>\n",
" <tr>\n",
" <td>2</td>\n",
" <td>Ecco</td>\n",
" <td>Italian Restaurant</td>\n",
" <td>124 Chambers St</td>\n",
" <td>40.715337</td>\n",
" <td>-74.008848</td>\n",
" <td>[{'label': 'display', 'lat': 40.71533713859952...</td>\n",
" <td>549</td>\n",
" <td>10007</td>\n",
" <td>US</td>\n",
" <td>New York</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>[124 Chambers St (btwn Church St &amp; W Broadway)...</td>\n",
" <td>btwn Church St &amp; W Broadway</td>\n",
" <td>3fd66200f964a520f4e41ee3</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" name categories address \\\n",
"0 Harry's Italian Pizza Bar Pizza Place 225 Murray St \n",
"1 Conca Cucina Italian Restaurant Food 63 W Broadway \n",
"2 Ecco Italian Restaurant 124 Chambers St \n",
"\n",
" lat lng labeledLatLngs \\\n",
"0 40.715218 -74.014739 [{'label': 'display', 'lat': 40.71521779064671... \n",
"1 40.714460 -74.010086 [{'label': 'display', 'lat': 40.71446, 'lng': ... \n",
"2 40.715337 -74.008848 [{'label': 'display', 'lat': 40.71533713859952... \n",
"\n",
" distance postalCode cc city state country \\\n",
"0 58 10282 US New York NY United States \n",
"1 446 10007 US New York NY United States \n",
"2 549 10007 US New York NY United States \n",
"\n",
" formattedAddress \\\n",
"0 [225 Murray St, New York, NY 10282, United Sta... \n",
"1 [63 W Broadway, New York, NY 10007, United Sta... \n",
"2 [124 Chambers St (btwn Church St & W Broadway)... \n",
"\n",
" crossStreet id \n",
"0 NaN 4fa862b3e4b0ebff2f749f06 \n",
"1 NaN 4f3232e219836c91c7bfde94 \n",
"2 btwn Church St & W Broadway 3fd66200f964a520f4e41ee3 "
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# keep only columns that include venue name, and anything that is associated with location\n",
"filtered_columns = ['name', 'categories'] + [col for col in dataframe.columns if col.startswith('location.')] + ['id']\n",
"dataframe_filtered = dataframe.loc[:, filtered_columns]\n",
"\n",
"# function that extracts the category of the venue\n",
"def get_category_type(row):\n",
" try:\n",
" categories_list = row['categories']\n",
" except:\n",
" categories_list = row['venue.categories']\n",
" \n",
" if len(categories_list) == 0:\n",
" return None\n",
" else:\n",
" return categories_list[0]['name']\n",
"\n",
"# filter the category for each row\n",
"dataframe_filtered['categories'] = dataframe_filtered.apply(get_category_type, axis=1)\n",
"\n",
"# clean column names by keeping only last term\n",
"dataframe_filtered.columns = [column.split('.')[-1] for column in dataframe_filtered.columns]\n",
"\n",
"dataframe_filtered"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Let's visualize the Italian restaurants that are nearby"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/plain": [
"0 Harry's Italian Pizza Bar\n",
"1 Conca Cucina Italian Restaurant\n",
"2 Ecco\n",
"Name: name, dtype: object"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataframe_filtered.name"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/html": [
"<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVMgPSBmYWxzZTsgTF9OT19UT1VDSCA9IGZhbHNlOyBMX0RJU0FCTEVfM0QgPSBmYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdnaXQuY29tL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9tYXN0ZXIvZm9saXVtL3RlbXBsYXRlcy9sZWFmbGV0LmF3ZXNvbWUucm90YXRlLmNzcyIvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfMTRlMzA2M2Y5YTk4NDBmZmFhZmMxNzdlYzNhNzljOTEgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogMTAwLjAlOwogICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgICAgICAgICAgdG9wOiAwLjAlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICA8L3N0eWxlPgogICAgICAgIAo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgICAgICAgICA8ZGl2IGNsYXNzPSJmb2xpdW0tbWFwIiBpZD0ibWFwXzE0ZTMwNjNmOWE5ODQwZmZhYWZjMTc3ZWMzYTc5YzkxIiA+PC9kaXY+CiAgICAgICAgCjwvYm9keT4KPHNjcmlwdD4gICAgCiAgICAKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGJvdW5kcyA9IG51bGw7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgdmFyIG1hcF8xNGUzMDYzZjlhOTg0MGZmYWFmYzE3N2VjM2E3OWM5MSA9IEwubWFwKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ21hcF8xNGUzMDYzZjlhOTg0MGZmYWFmYzE3N2VjM2E3OWM5MScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7Y2VudGVyOiBbNDAuNzE0OTU1NSwtNzQuMDE1MzM2NV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB6b29tOiAyMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heEJvdW5kczogYm91bmRzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF5ZXJzOiBbXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmxkQ29weUp1bXA6IGZhbHNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JzOiBMLkNSUy5FUFNHMzg1NwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHRpbGVfbGF5ZXJfYzhiMDNhZWIzZDhjNGQ3ZGFjNDUwYzYwNzc5N2QwNDMgPSBMLnRpbGVMYXllcigKICAgICAgICAgICAgICAgICdodHRwczovL3tzfS50aWxlLm9wZW5zdHJlZXRtYXAub3JnL3t6fS97eH0ve3l9LnBuZycsCiAgICAgICAgICAgICAgICB7CiAgImF0dHJpYnV0aW9uIjogbnVsbCwKICAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsCiAgIm1heFpvb20iOiAxOCwKICAibWluWm9vbSI6IDEsCiAgIm5vV3JhcCI6IGZhbHNlLAogICJzdWJkb21haW5zIjogImFiYyIKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTRlMzA2M2Y5YTk4NDBmZmFhZmMxNzdlYzNhNzljOTEpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzIzMmY0N2Q3MWE3MzQ4YWJhNTcxYWY2MjE3MGVjZDY4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE0OTU1NSwtNzQuMDE1MzM2NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJyZWQiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJyZWQiLAogICJmaWxsT3BhY2l0eSI6IDAuNiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDEwLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE0ZTMwNjNmOWE5ODQwZmZhYWZjMTc3ZWMzYTc5YzkxKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzY4NjVmMDkwYTJkNjRhOTY5MzkyMjRjZjdiNzljYTM2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2M0MjA3NzcwMDI3OTRkOWY5NDQ2MWQ1MDJkYzgyNzAwID0gJCgnPGRpdiBpZD0iaHRtbF9jNDIwNzc3MDAyNzk0ZDlmOTQ0NjFkNTAyZGM4MjcwMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q29ucmFkIEhvdGVsPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82ODY1ZjA5MGEyZDY0YTk2OTM5MjI0Y2Y3Yjc5Y2EzNi5zZXRDb250ZW50KGh0bWxfYzQyMDc3NzAwMjc5NGQ5Zjk0NDYxZDUwMmRjODI3MDApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjMyZjQ3ZDcxYTczNDhhYmE1NzFhZjYyMTcwZWNkNjguYmluZFBvcHVwKHBvcHVwXzY4NjVmMDkwYTJkNjRhOTY5MzkyMjRjZjdiNzljYTM2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I3MTIzZWM0NGRhMjQ1YzRiMTVmN2IxNGMxNmI0NmU0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE1MjE3NzkwNjQ2NzEsLTc0LjAxNDczOTQwMjA5MzUxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE0ZTMwNjNmOWE5ODQwZmZhYWZjMTc3ZWMzYTc5YzkxKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzJhNWZhNjk1ZDk1NzRjNWE4MDRkNzBlZGZlMDRjZTA0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzU0ZDY5ZmEzNTk3MTQ4ODc5MzM1MDY0MzNhYzIwMzNkID0gJCgnPGRpdiBpZD0iaHRtbF81NGQ2OWZhMzU5NzE0ODg3OTMzNTA2NDMzYWMyMDMzZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UGl6emEgUGxhY2U8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzJhNWZhNjk1ZDk1NzRjNWE4MDRkNzBlZGZlMDRjZTA0LnNldENvbnRlbnQoaHRtbF81NGQ2OWZhMzU5NzE0ODg3OTMzNTA2NDMzYWMyMDMzZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9iNzEyM2VjNDRkYTI0NWM0YjE1ZjdiMTRjMTZiNDZlNC5iaW5kUG9wdXAocG9wdXBfMmE1ZmE2OTVkOTU3NGM1YTgwNGQ3MGVkZmUwNGNlMDQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDVlNTUyODNjNDczNDk2NjlkNmU2YWRjZTA3MzgyZTUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTQ0NiwtNzQuMDEwMDg2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE0ZTMwNjNmOWE5ODQwZmZhYWZjMTc3ZWMzYTc5YzkxKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2IxMzI1OThmY2YwNzRhNjY5ZjNhMmYxOTY4OWUyY2NiID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2E3ODY3OTU2MzVhZDQwMDRiYWFlMTBlOTNiNjRkM2Q2ID0gJCgnPGRpdiBpZD0iaHRtbF9hNzg2Nzk1NjM1YWQ0MDA0YmFhZTEwZTkzYjY0ZDNkNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Rm9vZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjEzMjU5OGZjZjA3NGE2NjlmM2EyZjE5Njg5ZTJjY2Iuc2V0Q29udGVudChodG1sX2E3ODY3OTU2MzVhZDQwMDRiYWFlMTBlOTNiNjRkM2Q2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzQ1ZTU1MjgzYzQ3MzQ5NjY5ZDZlNmFkY2UwNzM4MmU1LmJpbmRQb3B1cChwb3B1cF9iMTMyNTk4ZmNmMDc0YTY2OWYzYTJmMTk2ODllMmNjYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl85NmNiODk4ZTRkNWM0MTliODUwZDllNDA0MDhhMWJmZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNTMzNzEzODU5OTUyLC03NC4wMDg4NDc2NjIxNzgyNV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNGUzMDYzZjlhOTg0MGZmYWFmYzE3N2VjM2E3OWM5MSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85ZTQwMjhhZDE0MmI0MDg0OWIwODFmYjk2MmM1MWIzNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xN2RiZDAyNjUwYjc0YjdkYmIyODU5OTgwZGU0M2I0OCA9ICQoJzxkaXYgaWQ9Imh0bWxfMTdkYmQwMjY1MGI3NGI3ZGJiMjg1OTk4MGRlNDNiNDgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkl0YWxpYW4gUmVzdGF1cmFudDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOWU0MDI4YWQxNDJiNDA4NDliMDgxZmI5NjJjNTFiMzcuc2V0Q29udGVudChodG1sXzE3ZGJkMDI2NTBiNzRiN2RiYjI4NTk5ODBkZTQzYjQ4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzk2Y2I4OThlNGQ1YzQxOWI4NTBkOWU0MDQwOGExYmZmLmJpbmRQb3B1cChwb3B1cF85ZTQwMjhhZDE0MmI0MDg0OWIwODFmYjk2MmM1MWIzNyk7CgogICAgICAgICAgICAKICAgICAgICAKPC9zY3JpcHQ+\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
],
"text/plain": [
"<folium.folium.Map at 0x7f60fcf5f358>"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"venues_map = folium.Map(location=[latitude, longitude], zoom_start=23) # generate map centred around the Conrad Hotel\n",
"\n",
"# add a red circle marker to represent the Conrad Hotel\n",
"folium.features.CircleMarker(\n",
" [latitude, longitude],\n",
" radius=10,\n",
" color='red',\n",
" popup='Conrad Hotel',\n",
" fill = True,\n",
" fill_color = 'red',\n",
" fill_opacity = 0.6\n",
").add_to(venues_map)\n",
"\n",
"# add the Italian restaurants as blue circle markers\n",
"for lat, lng, label in zip(dataframe_filtered.lat, dataframe_filtered.lng, dataframe_filtered.categories):\n",
" folium.features.CircleMarker(\n",
" [lat, lng],\n",
" radius=5,\n",
" color='blue',\n",
" popup=label,\n",
" fill = True,\n",
" fill_color='blue',\n",
" fill_opacity=0.6\n",
" ).add_to(venues_map)\n",
"\n",
"# display map\n",
"venues_map"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"<a id=\"item2\"></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"## 2. Explore a Given Venue\n",
"> `https://api.foursquare.com/v2/venues/`**VENUE_ID**`?client_id=`**CLIENT_ID**`&client_secret=`**CLIENT_SECRET**`&v=`**VERSION**"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"### A. Let's explore the closest Italian restaurant -- _Harry's Italian Pizza Bar_"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/plain": [
"'https://api.foursquare.com/v2/venues/4fa862b3e4b0ebff2f749f06?client_id=SFOI1LSHZYPN20MQJFSHU3FVJRWXXC3ZOURGWSLLNO24OYWO&client_secret=GNL5N5NYVCDKI3OSZBZLCFCWB41GO2BSZWJSN2CDWRTSXSJJ&v=20180604'"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"venue_id = '4fa862b3e4b0ebff2f749f06' # ID of Harry's Italian Pizza Bar\n",
"url = 'https://api.foursquare.com/v2/venues/{}?client_id={}&client_secret={}&v={}'.format(venue_id, CLIENT_ID, CLIENT_SECRET, VERSION)\n",
"url"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Send GET request for result"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"dict_keys(['id', 'name', 'contact', 'location', 'canonicalUrl', 'categories', 'verified', 'stats', 'url', 'price', 'hasMenu', 'likes', 'dislike', 'ok', 'rating', 'ratingColor', 'ratingSignals', 'delivery', 'menu', 'allowMenuUrlEdit', 'beenHere', 'specials', 'photos', 'reasons', 'hereNow', 'createdAt', 'tips', 'shortUrl', 'timeZone', 'listed', 'hours', 'popular', 'pageUpdates', 'inbox', 'attributes', 'bestPhoto', 'colors'])\n"
]
},
{
"data": {
"text/plain": [
"{'id': '4fa862b3e4b0ebff2f749f06',\n",
" 'name': \"Harry's Italian Pizza Bar\",\n",
" 'contact': {'phone': '2126081007', 'formattedPhone': '(212) 608-1007'},\n",
" 'location': {'address': '225 Murray St',\n",
" 'lat': 40.71521779064671,\n",
" 'lng': -74.01473940209351,\n",
" 'labeledLatLngs': [{'label': 'display',\n",
" 'lat': 40.71521779064671,\n",
" 'lng': -74.01473940209351}],\n",
" 'postalCode': '10282',\n",
" 'cc': 'US',\n",
" 'city': 'New York',\n",
" 'state': 'NY',\n",
" 'country': 'United States',\n",
" 'formattedAddress': ['225 Murray St',\n",
" 'New York, NY 10282',\n",
" 'United States']},\n",
" 'canonicalUrl': 'https://foursquare.com/v/harrys-italian-pizza-bar/4fa862b3e4b0ebff2f749f06',\n",
" 'categories': [{'id': '4bf58dd8d48988d1ca941735',\n",
" 'name': 'Pizza Place',\n",
" 'pluralName': 'Pizza Places',\n",
" 'shortName': 'Pizza',\n",
" 'icon': {'prefix': 'https://ss3.4sqi.net/img/categories_v2/food/pizza_',\n",
" 'suffix': '.png'},\n",
" 'primary': True},\n",
" {'id': '4bf58dd8d48988d110941735',\n",
" 'name': 'Italian Restaurant',\n",
" 'pluralName': 'Italian Restaurants',\n",
" 'shortName': 'Italian',\n",
" 'icon': {'prefix': 'https://ss3.4sqi.net/img/categories_v2/food/italian_',\n",
" 'suffix': '.png'}}],\n",
" 'verified': False,\n",
" 'stats': {'tipCount': 57},\n",
" 'url': 'http://harrysitalian.com',\n",
" 'price': {'tier': 2, 'message': 'Moderate', 'currency': '$'},\n",
" 'hasMenu': True,\n",
" 'likes': {'count': 120,\n",
" 'groups': [{'type': 'others', 'count': 120, 'items': []}],\n",
" 'summary': '120 Likes'},\n",
" 'dislike': False,\n",
" 'ok': False,\n",
" 'rating': 7.0,\n",
" 'ratingColor': 'C5DE35',\n",
" 'ratingSignals': 214,\n",
" 'delivery': {'id': '294544',\n",
" 'url': 'https://www.seamless.com/menu/harrys-italian-pizza-bar-225-murray-st-new-york/294544?affiliate=1131&utm_source=foursquare-affiliate-network&utm_medium=affiliate&utm_campaign=1131&utm_content=294544',\n",
" 'provider': {'name': 'seamless',\n",
" 'icon': {'prefix': 'https://fastly.4sqi.net/img/general/cap/',\n",
" 'sizes': [40, 50],\n",
" 'name': '/delivery_provider_seamless_20180129.png'}}},\n",
" 'menu': {'type': 'Menu',\n",
" 'label': 'Menu',\n",
" 'anchor': 'View Menu',\n",
" 'url': 'https://foursquare.com/v/harrys-italian-pizza-bar/4fa862b3e4b0ebff2f749f06/menu',\n",
" 'mobileUrl': 'https://foursquare.com/v/4fa862b3e4b0ebff2f749f06/device_menu'},\n",
" 'allowMenuUrlEdit': True,\n",
" 'beenHere': {'count': 0,\n",
" 'unconfirmedCount': 0,\n",
" 'marked': False,\n",
" 'lastCheckinExpiredAt': 0},\n",
" 'specials': {'count': 0, 'items': []},\n",
" 'photos': {'count': 149,\n",
" 'groups': [{'type': 'checkin',\n",
" 'name': \"Friends' check-in photos\",\n",
" 'count': 0,\n",
" 'items': []},\n",
" {'type': 'venue',\n",
" 'name': 'Venue photos',\n",
" 'count': 149,\n",
" 'items': [{'id': '4fad980de4b091b4626c3633',\n",
" 'createdAt': 1336776717,\n",
" 'source': {'name': 'Foursquare for Android',\n",
" 'url': 'https://foursquare.com/download/#/android'},\n",
" 'prefix': 'https://fastly.4sqi.net/img/general/',\n",
" 'suffix': '/ya1iQFI7pLjuIJp1PGDKlrZS3OJdHCF7tpILMmjv_2w.jpg',\n",
" 'width': 480,\n",
" 'height': 640,\n",
" 'user': {'id': '13676709',\n",
" 'firstName': 'Leony',\n",
" 'lastName': 'Naciri',\n",
" 'gender': 'none',\n",
" 'photo': {'prefix': 'https://fastly.4sqi.net/img/user/',\n",
" 'suffix': '/T0ANFNGNMCHUDEUE.jpg'}},\n",
" 'visibility': 'public'}]}],\n",
" 'summary': '0 photos'},\n",
" 'reasons': {'count': 1,\n",
" 'items': [{'summary': 'Lots of people like this place',\n",
" 'type': 'general',\n",
" 'reasonName': 'rawLikesReason'}]},\n",
" 'hereNow': {'count': 2,\n",
" 'summary': '2 people are here',\n",
" 'groups': [{'type': 'others',\n",
" 'name': 'Other people here',\n",
" 'count': 2,\n",
" 'items': []}]},\n",
" 'createdAt': 1336435379,\n",
" 'tips': {'count': 57,\n",
" 'groups': [{'type': 'others',\n",
" 'name': 'All tips',\n",
" 'count': 57,\n",
" 'items': [{'id': '53d27909498e0523841340b6',\n",
" 'createdAt': 1406302473,\n",
" 'text': \"Harry's Italian Pizza bar is known for it's amazing pizza, but did you know that the brunches here are amazing too? Try the Nutella French toast and we know you'll be sold.\",\n",
" 'type': 'user',\n",
" 'canonicalUrl': 'https://foursquare.com/item/53d27909498e0523841340b6',\n",
" 'lang': 'en',\n",
" 'likes': {'count': 4,\n",
" 'groups': [{'type': 'others',\n",
" 'count': 4,\n",
" 'items': [{'id': '369426',\n",
" 'firstName': 'P.',\n",
" 'lastName': 'M.',\n",
" 'gender': 'male',\n",
" 'photo': {'prefix': 'https://fastly.4sqi.net/img/user/',\n",
" 'suffix': '/JPQYUWJKUT0H2OO4.jpg'}},\n",
" {'id': '87587879',\n",
" 'firstName': 'Diane',\n",
" 'lastName': 'Danneels',\n",
" 'gender': 'female',\n",
" 'photo': {'prefix': 'https://fastly.4sqi.net/img/user/',\n",
" 'suffix': '/87587879-ESLRSZLQ2CBE2P4W.jpg'}},\n",
" {'id': '87591341',\n",
" 'firstName': 'Tim',\n",
" 'lastName': 'Sheehan',\n",
" 'gender': 'male',\n",
" 'photo': {'prefix': 'https://fastly.4sqi.net/img/user/',\n",
" 'suffix': '/-Z4YK4VKE0JSVXIY1.jpg'}},\n",
" {'id': '87473404',\n",
" 'firstName': 'TenantKing.com',\n",
" 'gender': 'none',\n",
" 'photo': {'prefix': 'https://fastly.4sqi.net/img/user/',\n",
" 'suffix': '/87473404-HI5DTBTK0HX401CA.png'},\n",
" 'type': 'page'}]}],\n",
" 'summary': '4 likes'},\n",
" 'logView': True,\n",
" 'agreeCount': 4,\n",
" 'disagreeCount': 0,\n",
" 'todo': {'count': 0},\n",
" 'user': {'id': '87473404',\n",
" 'firstName': 'TenantKing.com',\n",
" 'gender': 'none',\n",
" 'photo': {'prefix': 'https://fastly.4sqi.net/img/user/',\n",
" 'suffix': '/87473404-HI5DTBTK0HX401CA.png'},\n",
" 'type': 'page'}}]}]},\n",
" 'shortUrl': 'http://4sq.com/JNblHV',\n",
" 'timeZone': 'America/New_York',\n",
" 'listed': {'count': 54,\n",
" 'groups': [{'type': 'others',\n",
" 'name': 'Lists from other people',\n",
" 'count': 54,\n",
" 'items': [{'id': '4fa32fd0e4b04193744746b1',\n",
" 'name': 'Manhattan Haunts',\n",
" 'description': '',\n",
" 'type': 'others',\n",
" 'user': {'id': '24592223',\n",
" 'firstName': 'Becca',\n",
" 'lastName': 'McArthur',\n",
" 'gender': 'female',\n",
" 'photo': {'prefix': 'https://fastly.4sqi.net/img/user/',\n",
" 'suffix': '/24592223-RAW2UYM0GIB1U40K.jpg'}},\n",
" 'editable': False,\n",
" 'public': True,\n",
" 'collaborative': False,\n",
" 'url': '/becca_mcarthur/list/manhattan-haunts',\n",
" 'canonicalUrl': 'https://foursquare.com/becca_mcarthur/list/manhattan-haunts',\n",
" 'createdAt': 1336094672,\n",
" 'updatedAt': 1380845377,\n",
" 'photo': {'id': '4e8cc9461081e3b3544e12e5',\n",
" 'createdAt': 1317849414,\n",
" 'prefix': 'https://fastly.4sqi.net/img/general/',\n",
" 'suffix': '/0NLVU2HC1JF4DXIMKWUFW3QBUT31DC11EFNYYHMJG3NDWAPS.jpg',\n",
" 'width': 492,\n",
" 'height': 330,\n",
" 'user': {'id': '742542',\n",
" 'firstName': 'Time Out New York',\n",
" 'gender': 'none',\n",
" 'photo': {'prefix': 'https://fastly.4sqi.net/img/user/',\n",
" 'suffix': '/XXHKCBSQHBORZNSR.jpg'},\n",
" 'type': 'page'},\n",
" 'visibility': 'public'},\n",
" 'followers': {'count': 22},\n",
" 'listItems': {'count': 187,\n",
" 'items': [{'id': 'v4fa862b3e4b0ebff2f749f06',\n",
" 'createdAt': 1342934485}]}},\n",
" {'id': '4fae817be4b085f6b2a74d19',\n",
" 'name': 'USA NYC MAN FiDi',\n",
" 'description': 'Where to go for decent eats in the restaurant wasteland of Downtown NYC aka FiDi, along with Tribeca & Battery Park City.',\n",
" 'type': 'others',\n",
" 'user': {'id': '12113441',\n",
" 'firstName': 'Kino',\n",
" 'gender': 'male',\n",
" 'photo': {'prefix': 'https://fastly.4sqi.net/img/user/',\n",
" 'suffix': '/12113441-K5HTHFLU2MUCM0CM.jpg'}},\n",
" 'editable': False,\n",
" 'public': True,\n",
" 'collaborative': False,\n",
" 'url': '/kinosfault/list/usa-nyc-man-fidi',\n",
" 'canonicalUrl': 'https://foursquare.com/kinosfault/list/usa-nyc-man-fidi',\n",
" 'createdAt': 1336836475,\n",
" 'updatedAt': 1556754919,\n",
" 'photo': {'id': '55984992498e13ba75e353bb',\n",
" 'createdAt': 1436043666,\n",
" 'prefix': 'https://fastly.4sqi.net/img/general/',\n",
" 'suffix': '/12113441_iOa6Uh-Xi8bhj2-gpzkkw8MKiAIs7RmOcz_RM7m8ink.jpg',\n",
" 'width': 540,\n",
" 'height': 960,\n",
" 'user': {'id': '12113441',\n",
" 'firstName': 'Kino',\n",
" 'gender': 'male',\n",
" 'photo': {'prefix': 'https://fastly.4sqi.net/img/user/',\n",
" 'suffix': '/12113441-K5HTHFLU2MUCM0CM.jpg'}},\n",
" 'visibility': 'public'},\n",
" 'followers': {'count': 20},\n",
" 'listItems': {'count': 273,\n",
" 'items': [{'id': 'v4fa862b3e4b0ebff2f749f06',\n",
" 'createdAt': 1373909433}]}},\n",
" {'id': '4fddeff0e4b0e078037ac0d3',\n",
" 'name': 'NYC Resturants',\n",
" 'description': '',\n",
" 'type': 'others',\n",
" 'user': {'id': '21563126',\n",
" 'firstName': 'Richard',\n",
" 'lastName': 'Revilla',\n",
" 'gender': 'male',\n",
" 'photo': {'prefix': 'https://fastly.4sqi.net/img/user/',\n",
" 'suffix': '/21563126_v05J1KPw_SVj6Ehq9g8B9jeAGjFUMsU5QGl-NZ8inUQ7pKQm5bKplW37EmR7jS2A7GYPBBAtl.jpg'}},\n",
" 'editable': False,\n",
" 'public': True,\n",
" 'collaborative': True,\n",
" 'url': '/rickr7/list/nyc-resturants',\n",
" 'canonicalUrl': 'https://foursquare.com/rickr7/list/nyc-resturants',\n",
" 'createdAt': 1339944944,\n",
" 'updatedAt': 1565546947,\n",
" 'photo': {'id': '5072dd13e4b09145cdf782d1',\n",
" 'createdAt': 1349704979,\n",
" 'prefix': 'https://fastly.4sqi.net/img/general/',\n",
" 'suffix': '/208205_fGh2OuAZ9qJ4agbAA5wMVNOSIm9kNUlRtNwj1N-adqg.jpg',\n",
" 'width': 800,\n",
" 'height': 800,\n",
" 'user': {'id': '208205',\n",
" 'firstName': 'Thalia',\n",
" 'lastName': 'K',\n",
" 'gender': 'female',\n",
" 'photo': {'prefix': 'https://fastly.4sqi.net/img/user/',\n",
" 'suffix': '/SNOOLCAW2AG04ZKD.jpg'}},\n",
" 'visibility': 'public'},\n",
" 'followers': {'count': 12},\n",
" 'listItems': {'count': 198,\n",
" 'items': [{'id': 't54ed3b13498e857fd7dbb6fc',\n",
" 'createdAt': 1514680908}]}},\n",
" {'id': '5266c68a498e7c667807fe09',\n",
" 'name': 'Foodie Love in NY - 02',\n",
" 'description': '',\n",
" 'type': 'others',\n",
" 'user': {'id': '547977',\n",
" 'firstName': 'WiLL',\n",
" 'gender': 'male',\n",
" 'photo': {'prefix': 'https://fastly.4sqi.net/img/user/',\n",
" 'suffix': '/-Q5NYGDMFDMOITQRR.jpg'}},\n",
" 'editable': False,\n",
" 'public': True,\n",
" 'collaborative': False,\n",
" 'url': '/sweetiewill/list/foodie-love-in-ny--02',\n",
" 'canonicalUrl': 'https://foursquare.com/sweetiewill/list/foodie-love-in-ny--02',\n",
" 'createdAt': 1382467210,\n",
" 'updatedAt': 1391995585,\n",
" 'followers': {'count': 7},\n",
" 'listItems': {'count': 200,\n",
" 'items': [{'id': 'v4fa862b3e4b0ebff2f749f06',\n",
" 'createdAt': 1386809936}]}}]}]},\n",
" 'hours': {'status': 'Open until 11:00 PM',\n",
" 'richStatus': {'entities': [], 'text': 'Open until 11:00 PM'},\n",
" 'isOpen': True,\n",
" 'isLocalHoliday': False,\n",
" 'dayData': [],\n",
" 'timeframes': [{'days': 'Mon–Wed, Sun',\n",
" 'includesToday': True,\n",
" 'open': [{'renderedTime': '11:30 AM–11:00 PM'}],\n",
" 'segments': []},\n",
" {'days': 'Thu–Sat',\n",
" 'open': [{'renderedTime': '11:30 AM–Midnight'}],\n",
" 'segments': []}]},\n",
" 'popular': {'isOpen': False,\n",
" 'isLocalHoliday': False,\n",
" 'timeframes': [{'days': 'Today',\n",
" 'includesToday': True,\n",
" 'open': [{'renderedTime': 'Noon–3:00 PM'},\n",
" {'renderedTime': '5:00 PM–8:00 PM'}],\n",
" 'segments': []},\n",
" {'days': 'Mon',\n",
" 'open': [{'renderedTime': 'Noon–2:00 PM'},\n",
" {'renderedTime': '6:00 PM–8:00 PM'}],\n",
" 'segments': []},\n",
" {'days': 'Tue–Thu',\n",
" 'open': [{'renderedTime': 'Noon–2:00 PM'},\n",
" {'renderedTime': '5:00 PM–10:00 PM'}],\n",
" 'segments': []},\n",
" {'days': 'Fri',\n",
" 'open': [{'renderedTime': 'Noon–3:00 PM'},\n",
" {'renderedTime': '5:00 PM–11:00 PM'}],\n",
" 'segments': []},\n",
" {'days': 'Sat',\n",
" 'open': [{'renderedTime': 'Noon–4:00 PM'},\n",
" {'renderedTime': '6:00 PM–11:00 PM'}],\n",
" 'segments': []}]},\n",
" 'pageUpdates': {'count': 0, 'items': []},\n",
" 'inbox': {'count': 0, 'items': []},\n",
" 'attributes': {'groups': [{'type': 'price',\n",
" 'name': 'Price',\n",
" 'summary': '$$',\n",
" 'count': 1,\n",
" 'items': [{'displayName': 'Price', 'displayValue': '$$', 'priceTier': 2}]},\n",
" {'type': 'payments',\n",
" 'name': 'Credit Cards',\n",
" 'summary': 'Credit Cards',\n",
" 'count': 7,\n",
" 'items': [{'displayName': 'Credit Cards',\n",
" 'displayValue': 'Yes (incl. American Express)'}]},\n",
" {'type': 'outdoorSeating',\n",
" 'name': 'Outdoor Seating',\n",
" 'summary': 'Outdoor Seating',\n",
" 'count': 1,\n",
" 'items': [{'displayName': 'Outdoor Seating', 'displayValue': 'Yes'}]},\n",
" {'type': 'serves',\n",
" 'name': 'Menus',\n",
" 'summary': 'Happy Hour, Brunch & more',\n",
" 'count': 8,\n",
" 'items': [{'displayName': 'Brunch', 'displayValue': 'Brunch'},\n",
" {'displayName': 'Lunch', 'displayValue': 'Lunch'},\n",
" {'displayName': 'Dinner', 'displayValue': 'Dinner'},\n",
" {'displayName': 'Happy Hour', 'displayValue': 'Happy Hour'}]},\n",
" {'type': 'drinks',\n",
" 'name': 'Drinks',\n",
" 'summary': 'Beer, Wine & Cocktails',\n",
" 'count': 5,\n",
" 'items': [{'displayName': 'Beer', 'displayValue': 'Beer'},\n",
" {'displayName': 'Wine', 'displayValue': 'Wine'},\n",
" {'displayName': 'Cocktails', 'displayValue': 'Cocktails'}]},\n",
" {'type': 'diningOptions',\n",
" 'name': 'Dining Options',\n",
" 'summary': 'Delivery',\n",
" 'count': 5,\n",
" 'items': [{'displayName': 'Delivery', 'displayValue': 'Delivery'}]}]},\n",
" 'bestPhoto': {'id': '4fad980de4b091b4626c3633',\n",
" 'createdAt': 1336776717,\n",
" 'source': {'name': 'Foursquare for Android',\n",
" 'url': 'https://foursquare.com/download/#/android'},\n",
" 'prefix': 'https://fastly.4sqi.net/img/general/',\n",
" 'suffix': '/ya1iQFI7pLjuIJp1PGDKlrZS3OJdHCF7tpILMmjv_2w.jpg',\n",
" 'width': 480,\n",
" 'height': 640,\n",
" 'visibility': 'public'},\n",
" 'colors': {'highlightColor': {'photoId': '4fad980de4b091b4626c3633',\n",
" 'value': -13619152},\n",
" 'highlightTextColor': {'photoId': '4fad980de4b091b4626c3633', 'value': -1},\n",
" 'algoVersion': 3}}"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"result = requests.get(url).json()\n",
"print(result['response']['venue'].keys())\n",
"result['response']['venue']"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"### B. Get the venue's overall rating"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"7.0\n"
]
}
],
"source": [
"try:\n",
" print(result['response']['venue']['rating'])\n",
"except:\n",
" print('This venue has not been rated yet.')"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"That is not a very good rating. Let's check the rating of the second closest Italian restaurant."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"This venue has not been rated yet.\n"
]
}
],
"source": [
"venue_id = '4f3232e219836c91c7bfde94' # ID of Conca Cucina Italian Restaurant\n",
"url = 'https://api.foursquare.com/v2/venues/{}?client_id={}&client_secret={}&v={}'.format(venue_id, CLIENT_ID, CLIENT_SECRET, VERSION)\n",
"\n",
"result = requests.get(url).json()\n",
"try:\n",
" print(result['response']['venue']['rating'])\n",
"except:\n",
" print('This venue has not been rated yet.')"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"Since this restaurant has no ratings, let's check the third restaurant."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"7.9\n"
]
}
],
"source": [
"venue_id = '3fd66200f964a520f4e41ee3' # ID of Ecco\n",
"url = 'https://api.foursquare.com/v2/venues/{}?client_id={}&client_secret={}&v={}'.format(venue_id, CLIENT_ID, CLIENT_SECRET, VERSION)\n",
"\n",
"result = requests.get(url).json()\n",
"try:\n",
" print(result['response']['venue']['rating'])\n",
"except:\n",
" print('This venue has not been rated yet.')"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"Since this restaurant has a slightly better rating, let's explore it further."
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"### C. Get the number of tips"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/plain": [
"17"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"result['response']['venue']['tips']['count']"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"### D. Get the venue's tips\n",
"> `https://api.foursquare.com/v2/venues/`**VENUE_ID**`/tips?client_id=`**CLIENT_ID**`&client_secret=`**CLIENT_SECRET**`&v=`**VERSION**`&limit=`**LIMIT**"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Create URL and send GET request. Make sure to set limit to get all tips"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/plain": [
"{'meta': {'code': 200, 'requestId': '5d880bdce0c0c9002ce63b6e'},\n",
" 'response': {'tips': {'count': 17,\n",
" 'items': [{'id': '5ab1cb46c9a517174651d3fe',\n",
" 'createdAt': 1521601350,\n",
" 'text': 'A+ Italian food! Trust me on this: my mom’s side of the family is 100% Italian. I was born and bred to know good pasta when I see it, and Ecco is one of my all-time NYC favorites',\n",
" 'type': 'user',\n",
" 'canonicalUrl': 'https://foursquare.com/item/5ab1cb46c9a517174651d3fe',\n",
" 'lang': 'en',\n",
" 'likes': {'count': 0, 'groups': []},\n",
" 'logView': True,\n",
" 'agreeCount': 3,\n",
" 'disagreeCount': 0,\n",
" 'todo': {'count': 0},\n",
" 'user': {'id': '484542633',\n",
" 'firstName': 'Nick',\n",
" 'lastName': 'El-Tawil',\n",
" 'gender': 'male',\n",
" 'photo': {'prefix': 'https://fastly.4sqi.net/img/user/',\n",
" 'suffix': '/484542633_mK2Yum7T_7Tn9fWpndidJsmw2Hof_6T5vJBKCHPLMK5OL-U5ZiJGj51iwBstcpDLYa3Zvhvis.jpg'}},\n",
" 'authorInteractionType': 'liked'}]}}}"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"## Ecco Tips\n",
"limit = 15 # set limit to be greater than or equal to the total number of tips\n",
"url = 'https://api.foursquare.com/v2/venues/{}/tips?client_id={}&client_secret={}&v={}&limit={}'.format(venue_id, CLIENT_ID, CLIENT_SECRET, VERSION, limit)\n",
"\n",
"results = requests.get(url).json()\n",
"results"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Get tips and list of associated features"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/plain": [
"dict_keys(['id', 'createdAt', 'text', 'type', 'canonicalUrl', 'lang', 'likes', 'logView', 'agreeCount', 'disagreeCount', 'todo', 'user', 'authorInteractionType'])"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tips = results['response']['tips']['items']\n",
"\n",
"tip = results['response']['tips']['items'][0]\n",
"tip.keys()"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Format column width and display all tips"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>text</th>\n",
" <th>agreeCount</th>\n",
" <th>disagreeCount</th>\n",
" <th>id</th>\n",
" <th>user.firstName</th>\n",
" <th>user.lastName</th>\n",
" <th>user.gender</th>\n",
" <th>user.id</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <td>0</td>\n",
" <td>A+ Italian food! Trust me on this: my mom’s side of the family is 100% Italian. I was born and bred to know good pasta when I see it, and Ecco is one of my all-time NYC favorites</td>\n",
" <td>3</td>\n",
" <td>0</td>\n",
" <td>5ab1cb46c9a517174651d3fe</td>\n",
" <td>Nick</td>\n",
" <td>El-Tawil</td>\n",
" <td>male</td>\n",
" <td>484542633</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" text \\\n",
"0 A+ Italian food! Trust me on this: my mom’s side of the family is 100% Italian. I was born and bred to know good pasta when I see it, and Ecco is one of my all-time NYC favorites \n",
"\n",
" agreeCount disagreeCount id user.firstName \\\n",
"0 3 0 5ab1cb46c9a517174651d3fe Nick \n",
"\n",
" user.lastName user.gender user.id \n",
"0 El-Tawil male 484542633 "
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.set_option('display.max_colwidth', -1)\n",
"\n",
"tips_df = json_normalize(tips) # json normalize tips\n",
"\n",
"# columns to keep\n",
"filtered_columns = ['text', 'agreeCount', 'disagreeCount', 'id', 'user.firstName', 'user.lastName', 'user.gender', 'user.id']\n",
"tips_filtered = tips_df.loc[:, filtered_columns]\n",
"\n",
"# display tips\n",
"tips_filtered"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"Now remember that because we are using a personal developer account, then we can access only 2 of the restaurant's tips, instead of all 15 tips."
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"<a id=\"item3\"></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"## 3. Search a Foursquare User\n",
"> `https://api.foursquare.com/v2/users/`**USER_ID**`?client_id=`**CLIENT_ID**`&client_secret=`**CLIENT_SECRET**`&v=`**VERSION**"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"### Define URL, send GET request and display features associated with user"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/plain": [
"dict_keys(['id', 'firstName', 'lastName', 'gender', 'canonicalUrl', 'photo', 'friends', 'tips', 'homeCity', 'bio', 'contact', 'photos', 'type', 'mayorships', 'checkins', 'lists', 'lenses'])"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"user_id = '484542633' # user ID with most agree counts and complete profile\n",
"\n",
"url = 'https://api.foursquare.com/v2/users/{}?client_id={}&client_secret={}&v={}'.format(user_id, CLIENT_ID, CLIENT_SECRET, VERSION) # define URL\n",
"\n",
"# send GET request\n",
"results = requests.get(url).json()\n",
"user_data = results['response']['user']\n",
"\n",
"# display features associated with user\n",
"user_data.keys()"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"First Name: Nick\n",
"Last Name: El-Tawil\n",
"Home City: New York, NY\n"
]
}
],
"source": [
"print('First Name: ' + user_data['firstName'])\n",
"print('Last Name: ' + user_data['lastName'])\n",
"print('Home City: ' + user_data['homeCity'])"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### How many tips has this user submitted?"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/plain": [
"{'count': 238}"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"user_data['tips']"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"Wow! So it turns out that Nick is a very active Foursquare user, with more than 250 tips."
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"### Get User's tips"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>text</th>\n",
" <th>agreeCount</th>\n",
" <th>disagreeCount</th>\n",
" <th>id</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <td>0</td>\n",
" <td>The best! I’m especially fond of the salmon burger, but I’ve had half of the menu and never been disappointed. There’s a reason this place is well known even outside of the Village!</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>5aec594b1f7440002c138612</td>\n",
" </tr>\n",
" <tr>\n",
" <td>1</td>\n",
" <td>I used to down a pint of chocolate like it was nothing back when I was bulking. Highly recommended!</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>5accc9f66fa81f196724807b</td>\n",
" </tr>\n",
" <tr>\n",
" <td>2</td>\n",
" <td>They serve coffee!!!!!!</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>5accc98c0313204c9d7ec157</td>\n",
" </tr>\n",
" <tr>\n",
" <td>3</td>\n",
" <td>I’m a fan. In fact, I’m such a big fan, I want Taim to hire me to be their spokesman. Kind of like the Arabic Jared Fogle - but without the kid stuff.</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>5accbf033abcaf09a24612a0</td>\n",
" </tr>\n",
" <tr>\n",
" <td>4</td>\n",
" <td>The linguine with clams is on point 👌</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>5accbe3a911fc423730f3ed3</td>\n",
" </tr>\n",
" <tr>\n",
" <td>5</td>\n",
" <td>Great for a quick, cheap lunch! Shorter lines than Chipotle too👌</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>5acbecb86fa81f1967e019b0</td>\n",
" </tr>\n",
" <tr>\n",
" <td>6</td>\n",
" <td>Quick, cheap lunch that tastes good! Way shorter line than Chipotle, too.</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>5acbec70a0215b732e264fe8</td>\n",
" </tr>\n",
" <tr>\n",
" <td>7</td>\n",
" <td>You’re not a real New Yorker until you’ve shame-ordered Insomnia Cookies for delivery at 3am</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>5acbbd4eb1538e45373b07f5</td>\n",
" </tr>\n",
" <tr>\n",
" <td>8</td>\n",
" <td>Good for you yet still tasty! Clean green protein is my go-to after I hit the gym 💪</td>\n",
" <td>2</td>\n",
" <td>0</td>\n",
" <td>5acbbcda01235808d5d6dc75</td>\n",
" </tr>\n",
" <tr>\n",
" <td>9</td>\n",
" <td>Coffee game on point</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>5acbbb1501235808d5d6525e</td>\n",
" </tr>\n",
" <tr>\n",
" <td>10</td>\n",
" <td>This is the dive bar to end all other dive bars. Go here if you like cheap drinks! 🥃</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>5ab576abea1e444f2abb051e</td>\n",
" </tr>\n",
" <tr>\n",
" <td>11</td>\n",
" <td>Burger game strong 💪</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>5ab575fb6bdee65f759da8c1</td>\n",
" </tr>\n",
" <tr>\n",
" <td>12</td>\n",
" <td>Great burgers &amp; fries! Also, this place is exactly what it’s like when you go to a bar in the Southwest. Source: I’m from Arizona.</td>\n",
" <td>2</td>\n",
" <td>0</td>\n",
" <td>5ab5575d73fe2516ad8f363b</td>\n",
" </tr>\n",
" <tr>\n",
" <td>13</td>\n",
" <td>That guy looks familiar...</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>5ab5299635f98312029a53b7</td>\n",
" </tr>\n",
" <tr>\n",
" <td>14</td>\n",
" <td>Açaí bowl + peanut butter + whey protein = 💪💪💪</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>5ab42db53c858d64af2688a4</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" text \\\n",
"0 The best! I’m especially fond of the salmon burger, but I’ve had half of the menu and never been disappointed. There’s a reason this place is well known even outside of the Village! \n",
"1 I used to down a pint of chocolate like it was nothing back when I was bulking. Highly recommended! \n",
"2 They serve coffee!!!!!! \n",
"3 I’m a fan. In fact, I’m such a big fan, I want Taim to hire me to be their spokesman. Kind of like the Arabic Jared Fogle - but without the kid stuff. \n",
"4 The linguine with clams is on point 👌 \n",
"5 Great for a quick, cheap lunch! Shorter lines than Chipotle too👌 \n",
"6 Quick, cheap lunch that tastes good! Way shorter line than Chipotle, too. \n",
"7 You’re not a real New Yorker until you’ve shame-ordered Insomnia Cookies for delivery at 3am \n",
"8 Good for you yet still tasty! Clean green protein is my go-to after I hit the gym 💪 \n",
"9 Coffee game on point \n",
"10 This is the dive bar to end all other dive bars. Go here if you like cheap drinks! 🥃 \n",
"11 Burger game strong 💪 \n",
"12 Great burgers & fries! Also, this place is exactly what it’s like when you go to a bar in the Southwest. Source: I’m from Arizona. \n",
"13 That guy looks familiar... \n",
"14 Açaí bowl + peanut butter + whey protein = 💪💪💪 \n",
"\n",
" agreeCount disagreeCount id \n",
"0 1 0 5aec594b1f7440002c138612 \n",
"1 1 0 5accc9f66fa81f196724807b \n",
"2 1 0 5accc98c0313204c9d7ec157 \n",
"3 1 0 5accbf033abcaf09a24612a0 \n",
"4 1 0 5accbe3a911fc423730f3ed3 \n",
"5 1 0 5acbecb86fa81f1967e019b0 \n",
"6 1 0 5acbec70a0215b732e264fe8 \n",
"7 1 0 5acbbd4eb1538e45373b07f5 \n",
"8 2 0 5acbbcda01235808d5d6dc75 \n",
"9 1 0 5acbbb1501235808d5d6525e \n",
"10 1 0 5ab576abea1e444f2abb051e \n",
"11 1 0 5ab575fb6bdee65f759da8c1 \n",
"12 2 0 5ab5575d73fe2516ad8f363b \n",
"13 1 0 5ab5299635f98312029a53b7 \n",
"14 1 0 5ab42db53c858d64af2688a4 "
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# define tips URL\n",
"url = 'https://api.foursquare.com/v2/users/{}/tips?client_id={}&client_secret={}&v={}&limit={}'.format(user_id, CLIENT_ID, CLIENT_SECRET, VERSION, limit)\n",
"\n",
"# send GET request and get user's tips\n",
"results = requests.get(url).json()\n",
"tips = results['response']['tips']['items']\n",
"\n",
"# format column width\n",
"pd.set_option('display.max_colwidth', -1)\n",
"\n",
"tips_df = json_normalize(tips)\n",
"\n",
"# filter columns\n",
"filtered_columns = ['text', 'agreeCount', 'disagreeCount', 'id']\n",
"tips_filtered = tips_df.loc[:, filtered_columns]\n",
"\n",
"# display user's tips\n",
"tips_filtered"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Let's get the venue for the tip with the greatest number of agree counts"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Cowgirl\n",
"{'address': '519 Hudson St', 'crossStreet': 'at W 10th St', 'lat': 40.73373338282062, 'lng': -74.0062998849649, 'labeledLatLngs': [{'label': 'display', 'lat': 40.73373338282062, 'lng': -74.0062998849649}], 'postalCode': '10014', 'cc': 'US', 'city': 'New York', 'state': 'NY', 'country': 'United States', 'formattedAddress': ['519 Hudson St (at W 10th St)', 'New York, NY 10014', 'United States']}\n"
]
}
],
"source": [
"tip_id = '5ab5575d73fe2516ad8f363b' # tip id\n",
"\n",
"# define URL\n",
"url = 'http://api.foursquare.com/v2/tips/{}?client_id={}&client_secret={}&v={}'.format(tip_id, CLIENT_ID, CLIENT_SECRET, VERSION)\n",
"\n",
"# send GET Request and examine results\n",
"result = requests.get(url).json()\n",
"print(result['response']['tip']['venue']['name'])\n",
"print(result['response']['tip']['venue']['location'])"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"### Get User's friends"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
"Empty DataFrame\n",
"Columns: []\n",
"Index: []"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"user_friends = json_normalize(user_data['friends']['groups'][0]['items'])\n",
"user_friends"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"Interesting. Despite being very active, it turns out that Nick does not have any friends on Foursquare. This might definitely change in the future."
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"### Retrieve the User's Profile Image"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
},
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
"{'id': '484542633',\n",
" 'firstName': 'Nick',\n",
" 'lastName': 'El-Tawil',\n",
" 'gender': 'male',\n",
" 'canonicalUrl': 'https://foursquare.com/nickeltawil',\n",
" 'photo': {'prefix': 'https://fastly.4sqi.net/img/user/',\n",
" 'suffix': '/484542633_mK2Yum7T_7Tn9fWpndidJsmw2Hof_6T5vJBKCHPLMK5OL-U5ZiJGj51iwBstcpDLYa3Zvhvis.jpg'},\n",
" 'friends': {'count': 0,\n",
" 'groups': [{'type': 'others',\n",
" 'name': 'Other friends',\n",
" 'count': 0,\n",
" 'items': []}]},\n",
" 'tips': {'count': 238},\n",
" 'homeCity': 'New York, NY',\n",
" 'bio': 'https://www.tawil.team/nick-el-tawil/',\n",
" 'contact': {},\n",
" 'photos': {'count': 0, 'items': []},\n",
" 'type': 'user',\n",
" 'mayorships': {'count': 0, 'items': []},\n",
" 'checkins': {'count': 1, 'items': []},\n",
" 'lists': {'count': 2,\n",
" 'groups': [{'type': 'created', 'count': 0, 'items': []},\n",
" {'type': 'followed', 'count': 0, 'items': []},\n",
" {'type': 'yours',\n",
" 'count': 2,\n",
" 'items': [{'id': '484542633/todos',\n",
" 'name': \"Nick's Saved Places\",\n",
" 'description': '',\n",
" 'type': 'todos',\n",
" 'editable': False,\n",
" 'public': True,\n",
" 'collaborative': False,\n",
" 'url': '/nickeltawil/list/todos',\n",
" 'canonicalUrl': 'https://foursquare.com/nickeltawil/list/todos',\n",
" 'listItems': {'count': 0}},\n",
" {'id': '484542633/venuelikes',\n",
" 'name': 'Nick’s Liked Places',\n",
" 'description': '',\n",
" 'type': 'likes',\n",
" 'editable': False,\n",
" 'public': True,\n",
" 'collaborative': False,\n",
" 'url': '/nickeltawil/list/venuelikes',\n",
" 'canonicalUrl': 'https://foursquare.com/nickeltawil/list/venuelikes',\n",
" 'listItems': {'count': 0}}]}]},\n",
" 'lenses': []}"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"user_data"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/html": [
"<img src=\"https://igx.4sqi.net/img/user/300x300/484542633_mK2Yum7T_7Tn9fWpndidJsmw2Hof_6T5vJBKCHPLMK5OL-U5ZiJGj51iwBstcpDLYa3Zvhvis.jpg\"/>"
],
"text/plain": [
"<IPython.core.display.Image object>"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 1. grab prefix of photo\n",
"# 2. grab suffix of photo\n",
"# 3. concatenate them using the image size \n",
"Image(url='https://igx.4sqi.net/img/user/300x300/484542633_mK2Yum7T_7Tn9fWpndidJsmw2Hof_6T5vJBKCHPLMK5OL-U5ZiJGj51iwBstcpDLYa3Zvhvis.jpg')"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"<a id=\"item4\"></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"## 4. Explore a location\n",
"> `https://api.foursquare.com/v2/venues/`**explore**`?client_id=`**CLIENT_ID**`&client_secret=`**CLIENT_SECRET**`&ll=`**LATITUDE**`,`**LONGITUDE**`&v=`**VERSION**`&limit=`**LIMIT**"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### So, you just finished your gourmet dish at Ecco, and are just curious about the popular spots around the restaurant. In order to explore the area, let's start by getting the latitude and longitude values of Ecco Restaurant."
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [],
"source": [
"latitude = 40.715337\n",
"longitude = -74.008848"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Define URL"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/plain": [
"'https://api.foursquare.com/v2/venues/explore?client_id=SFOI1LSHZYPN20MQJFSHU3FVJRWXXC3ZOURGWSLLNO24OYWO&client_secret=GNL5N5NYVCDKI3OSZBZLCFCWB41GO2BSZWJSN2CDWRTSXSJJ&ll=40.715337,-74.008848&v=20180604&radius=500&limit=30'"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"url = 'https://api.foursquare.com/v2/venues/explore?client_id={}&client_secret={}&ll={},{}&v={}&radius={}&limit={}'.format(CLIENT_ID, CLIENT_SECRET, latitude, longitude, VERSION, radius, LIMIT)\n",
"url"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Send GET request and examine results"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [],
"source": [
"import requests"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/plain": [
"'There are 30 around Ecco restaurant.'"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"results = requests.get(url).json()\n",
"'There are {} around Ecco restaurant.'.format(len(results['response']['groups'][0]['items']))"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Get relevant part of JSON"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/plain": [
"{'reasons': {'count': 0,\n",
" 'items': [{'summary': 'This spot is popular',\n",
" 'type': 'general',\n",
" 'reasonName': 'globalInteractionReason'}]},\n",
" 'venue': {'id': '4af5d65ff964a52091fd21e3',\n",
" 'name': 'Korin',\n",
" 'location': {'address': '57 Warren St',\n",
" 'crossStreet': 'Church St',\n",
" 'lat': 40.71482437714839,\n",
" 'lng': -74.00940425461492,\n",
" 'labeledLatLngs': [{'label': 'display',\n",
" 'lat': 40.71482437714839,\n",
" 'lng': -74.00940425461492}],\n",
" 'distance': 73,\n",
" 'postalCode': '10007',\n",
" 'cc': 'US',\n",
" 'neighborhood': 'Tribeca',\n",
" 'city': 'New York',\n",
" 'state': 'NY',\n",
" 'country': 'United States',\n",
" 'formattedAddress': ['57 Warren St (Church St)',\n",
" 'New York, NY 10007',\n",
" 'United States']},\n",
" 'categories': [{'id': '4bf58dd8d48988d1f8941735',\n",
" 'name': 'Furniture / Home Store',\n",
" 'pluralName': 'Furniture / Home Stores',\n",
" 'shortName': 'Furniture / Home',\n",
" 'icon': {'prefix': 'https://ss3.4sqi.net/img/categories_v2/shops/furniture_',\n",
" 'suffix': '.png'},\n",
" 'primary': True}],\n",
" 'photos': {'count': 0, 'groups': []},\n",
" 'venuePage': {'id': '33104775'}},\n",
" 'referralId': 'e-0-4af5d65ff964a52091fd21e3-0'}"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"items = results['response']['groups'][0]['items']\n",
"items[0]"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Process JSON and convert it to a clean dataframe"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>name</th>\n",
" <th>categories</th>\n",
" <th>address</th>\n",
" <th>crossStreet</th>\n",
" <th>lat</th>\n",
" <th>lng</th>\n",
" <th>labeledLatLngs</th>\n",
" <th>distance</th>\n",
" <th>postalCode</th>\n",
" <th>cc</th>\n",
" <th>neighborhood</th>\n",
" <th>city</th>\n",
" <th>state</th>\n",
" <th>country</th>\n",
" <th>formattedAddress</th>\n",
" <th>id</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <td>0</td>\n",
" <td>Korin</td>\n",
" <td>Furniture / Home Store</td>\n",
" <td>57 Warren St</td>\n",
" <td>Church St</td>\n",
" <td>40.714824</td>\n",
" <td>-74.009404</td>\n",
" <td>[{'label': 'display', 'lat': 40.71482437714839, 'lng': -74.00940425461492}]</td>\n",
" <td>73</td>\n",
" <td>10007</td>\n",
" <td>US</td>\n",
" <td>Tribeca</td>\n",
" <td>New York</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>[57 Warren St (Church St), New York, NY 10007, United States]</td>\n",
" <td>4af5d65ff964a52091fd21e3</td>\n",
" </tr>\n",
" <tr>\n",
" <td>1</td>\n",
" <td>Juice Press</td>\n",
" <td>Vegetarian / Vegan Restaurant</td>\n",
" <td>83 Murray St</td>\n",
" <td>btwn Greenwich St &amp; W Broadway</td>\n",
" <td>40.714788</td>\n",
" <td>-74.011132</td>\n",
" <td>[{'label': 'display', 'lat': 40.71478769908051, 'lng': -74.0111317502157}]</td>\n",
" <td>202</td>\n",
" <td>10007</td>\n",
" <td>US</td>\n",
" <td>NaN</td>\n",
" <td>New York</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>[83 Murray St (btwn Greenwich St &amp; W Broadway), New York, NY 10007, United States]</td>\n",
" <td>54148bc6498ea7bb8c05b70a</td>\n",
" </tr>\n",
" <tr>\n",
" <td>2</td>\n",
" <td>Takahachi Bakery</td>\n",
" <td>Bakery</td>\n",
" <td>25 Murray St</td>\n",
" <td>at Church St</td>\n",
" <td>40.713653</td>\n",
" <td>-74.008804</td>\n",
" <td>[{'label': 'display', 'lat': 40.713652845301894, 'lng': -74.0088038953017}]</td>\n",
" <td>187</td>\n",
" <td>10007</td>\n",
" <td>US</td>\n",
" <td>NaN</td>\n",
" <td>New York</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>[25 Murray St (at Church St), New York, NY 10007, United States]</td>\n",
" <td>4c154c9a77cea593c401d260</td>\n",
" </tr>\n",
" <tr>\n",
" <td>3</td>\n",
" <td>Takahachi</td>\n",
" <td>Sushi Restaurant</td>\n",
" <td>145 Duane St</td>\n",
" <td>btwn W Broadway &amp; Church St</td>\n",
" <td>40.716526</td>\n",
" <td>-74.008101</td>\n",
" <td>[{'label': 'display', 'lat': 40.71652647412374, 'lng': -74.00810108466207}]</td>\n",
" <td>146</td>\n",
" <td>10013</td>\n",
" <td>US</td>\n",
" <td>NaN</td>\n",
" <td>New York</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>[145 Duane St (btwn W Broadway &amp; Church St), New York, NY 10013, United States]</td>\n",
" <td>4a8f2f39f964a520471420e3</td>\n",
" </tr>\n",
" <tr>\n",
" <td>4</td>\n",
" <td>Chambers Street Wines</td>\n",
" <td>Wine Shop</td>\n",
" <td>148 Chambers St</td>\n",
" <td>btwn West Broadway &amp; Hudson St</td>\n",
" <td>40.715773</td>\n",
" <td>-74.009718</td>\n",
" <td>[{'label': 'display', 'lat': 40.715773063928374, 'lng': -74.00971823312332}]</td>\n",
" <td>88</td>\n",
" <td>10007</td>\n",
" <td>US</td>\n",
" <td>NaN</td>\n",
" <td>New York</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>[148 Chambers St (btwn West Broadway &amp; Hudson St), New York, NY 10007, United States]</td>\n",
" <td>4adcf23cf964a520cc6221e3</td>\n",
" </tr>\n",
" <tr>\n",
" <td>5</td>\n",
" <td>Heyday</td>\n",
" <td>Spa</td>\n",
" <td>92 Reade St</td>\n",
" <td>NaN</td>\n",
" <td>40.715598</td>\n",
" <td>-74.007882</td>\n",
" <td>[{'label': 'display', 'lat': 40.715598486687675, 'lng': -74.00788227511288}]</td>\n",
" <td>86</td>\n",
" <td>10013</td>\n",
" <td>US</td>\n",
" <td>NaN</td>\n",
" <td>New York</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>[92 Reade St, New York, NY 10013, United States]</td>\n",
" <td>57ad129c498e05b086594d72</td>\n",
" </tr>\n",
" <tr>\n",
" <td>6</td>\n",
" <td>Equinox Tribeca</td>\n",
" <td>Gym</td>\n",
" <td>54 Murray Street</td>\n",
" <td>at W Broadway</td>\n",
" <td>40.714099</td>\n",
" <td>-74.009686</td>\n",
" <td>[{'label': 'display', 'lat': 40.71409860726041, 'lng': -74.0096857179283}]</td>\n",
" <td>154</td>\n",
" <td>10007</td>\n",
" <td>US</td>\n",
" <td>NaN</td>\n",
" <td>New York</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>[54 Murray Street (at W Broadway), New York, NY 10007, United States]</td>\n",
" <td>4a6e331af964a52031d41fe3</td>\n",
" </tr>\n",
" <tr>\n",
" <td>7</td>\n",
" <td>Philip Williams Posters</td>\n",
" <td>Antique Shop</td>\n",
" <td>122 Chambers St</td>\n",
" <td>NaN</td>\n",
" <td>40.715284</td>\n",
" <td>-74.008781</td>\n",
" <td>[{'label': 'display', 'lat': 40.71528423132827, 'lng': -74.00878093952018}]</td>\n",
" <td>8</td>\n",
" <td>10007</td>\n",
" <td>US</td>\n",
" <td>NaN</td>\n",
" <td>New York</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>[122 Chambers St, New York, NY 10007, United States]</td>\n",
" <td>4b747291f964a52042dd2de3</td>\n",
" </tr>\n",
" <tr>\n",
" <td>8</td>\n",
" <td>Nish Nūsh</td>\n",
" <td>Falafel Restaurant</td>\n",
" <td>88 Reade St</td>\n",
" <td>at Church St</td>\n",
" <td>40.715537</td>\n",
" <td>-74.007725</td>\n",
" <td>[{'label': 'display', 'lat': 40.71553710116416, 'lng': -74.00772452925565}]</td>\n",
" <td>97</td>\n",
" <td>10013</td>\n",
" <td>US</td>\n",
" <td>NaN</td>\n",
" <td>New York</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>[88 Reade St (at Church St), New York, NY 10013, United States]</td>\n",
" <td>50ba9119e4b071a4bae6dc10</td>\n",
" </tr>\n",
" <tr>\n",
" <td>9</td>\n",
" <td>Mulberry &amp; Vine</td>\n",
" <td>Café</td>\n",
" <td>73 Warren St</td>\n",
" <td>btwn W Broadway &amp; Greenwich St</td>\n",
" <td>40.715177</td>\n",
" <td>-74.010227</td>\n",
" <td>[{'label': 'display', 'lat': 40.71517693966315, 'lng': -74.01022747778285}]</td>\n",
" <td>117</td>\n",
" <td>10007</td>\n",
" <td>US</td>\n",
" <td>NaN</td>\n",
" <td>New York</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>[73 Warren St (btwn W Broadway &amp; Greenwich St), New York, NY 10007, United States]</td>\n",
" <td>5171b5cc011cef9833bbb787</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" name categories address \\\n",
"0 Korin Furniture / Home Store 57 Warren St \n",
"1 Juice Press Vegetarian / Vegan Restaurant 83 Murray St \n",
"2 Takahachi Bakery Bakery 25 Murray St \n",
"3 Takahachi Sushi Restaurant 145 Duane St \n",
"4 Chambers Street Wines Wine Shop 148 Chambers St \n",
"5 Heyday Spa 92 Reade St \n",
"6 Equinox Tribeca Gym 54 Murray Street \n",
"7 Philip Williams Posters Antique Shop 122 Chambers St \n",
"8 Nish Nūsh Falafel Restaurant 88 Reade St \n",
"9 Mulberry & Vine Café 73 Warren St \n",
"\n",
" crossStreet lat lng \\\n",
"0 Church St 40.714824 -74.009404 \n",
"1 btwn Greenwich St & W Broadway 40.714788 -74.011132 \n",
"2 at Church St 40.713653 -74.008804 \n",
"3 btwn W Broadway & Church St 40.716526 -74.008101 \n",
"4 btwn West Broadway & Hudson St 40.715773 -74.009718 \n",
"5 NaN 40.715598 -74.007882 \n",
"6 at W Broadway 40.714099 -74.009686 \n",
"7 NaN 40.715284 -74.008781 \n",
"8 at Church St 40.715537 -74.007725 \n",
"9 btwn W Broadway & Greenwich St 40.715177 -74.010227 \n",
"\n",
" labeledLatLngs \\\n",
"0 [{'label': 'display', 'lat': 40.71482437714839, 'lng': -74.00940425461492}] \n",
"1 [{'label': 'display', 'lat': 40.71478769908051, 'lng': -74.0111317502157}] \n",
"2 [{'label': 'display', 'lat': 40.713652845301894, 'lng': -74.0088038953017}] \n",
"3 [{'label': 'display', 'lat': 40.71652647412374, 'lng': -74.00810108466207}] \n",
"4 [{'label': 'display', 'lat': 40.715773063928374, 'lng': -74.00971823312332}] \n",
"5 [{'label': 'display', 'lat': 40.715598486687675, 'lng': -74.00788227511288}] \n",
"6 [{'label': 'display', 'lat': 40.71409860726041, 'lng': -74.0096857179283}] \n",
"7 [{'label': 'display', 'lat': 40.71528423132827, 'lng': -74.00878093952018}] \n",
"8 [{'label': 'display', 'lat': 40.71553710116416, 'lng': -74.00772452925565}] \n",
"9 [{'label': 'display', 'lat': 40.71517693966315, 'lng': -74.01022747778285}] \n",
"\n",
" distance postalCode cc neighborhood city state country \\\n",
"0 73 10007 US Tribeca New York NY United States \n",
"1 202 10007 US NaN New York NY United States \n",
"2 187 10007 US NaN New York NY United States \n",
"3 146 10013 US NaN New York NY United States \n",
"4 88 10007 US NaN New York NY United States \n",
"5 86 10013 US NaN New York NY United States \n",
"6 154 10007 US NaN New York NY United States \n",
"7 8 10007 US NaN New York NY United States \n",
"8 97 10013 US NaN New York NY United States \n",
"9 117 10007 US NaN New York NY United States \n",
"\n",
" formattedAddress \\\n",
"0 [57 Warren St (Church St), New York, NY 10007, United States] \n",
"1 [83 Murray St (btwn Greenwich St & W Broadway), New York, NY 10007, United States] \n",
"2 [25 Murray St (at Church St), New York, NY 10007, United States] \n",
"3 [145 Duane St (btwn W Broadway & Church St), New York, NY 10013, United States] \n",
"4 [148 Chambers St (btwn West Broadway & Hudson St), New York, NY 10007, United States] \n",
"5 [92 Reade St, New York, NY 10013, United States] \n",
"6 [54 Murray Street (at W Broadway), New York, NY 10007, United States] \n",
"7 [122 Chambers St, New York, NY 10007, United States] \n",
"8 [88 Reade St (at Church St), New York, NY 10013, United States] \n",
"9 [73 Warren St (btwn W Broadway & Greenwich St), New York, NY 10007, United States] \n",
"\n",
" id \n",
"0 4af5d65ff964a52091fd21e3 \n",
"1 54148bc6498ea7bb8c05b70a \n",
"2 4c154c9a77cea593c401d260 \n",
"3 4a8f2f39f964a520471420e3 \n",
"4 4adcf23cf964a520cc6221e3 \n",
"5 57ad129c498e05b086594d72 \n",
"6 4a6e331af964a52031d41fe3 \n",
"7 4b747291f964a52042dd2de3 \n",
"8 50ba9119e4b071a4bae6dc10 \n",
"9 5171b5cc011cef9833bbb787 "
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dataframe = json_normalize(items) # flatten JSON\n",
"\n",
"# filter columns\n",
"filtered_columns = ['venue.name', 'venue.categories'] + [col for col in dataframe.columns if col.startswith('venue.location.')] + ['venue.id']\n",
"dataframe_filtered = dataframe.loc[:, filtered_columns]\n",
"\n",
"# filter the category for each row\n",
"dataframe_filtered['venue.categories'] = dataframe_filtered.apply(get_category_type, axis=1)\n",
"\n",
"# clean columns\n",
"dataframe_filtered.columns = [col.split('.')[-1] for col in dataframe_filtered.columns]\n",
"\n",
"dataframe_filtered.head(10)"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Let's visualize these items on the map around our location"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/html": [
"<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVMgPSBmYWxzZTsgTF9OT19UT1VDSCA9IGZhbHNlOyBMX0RJU0FCTEVfM0QgPSBmYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdnaXQuY29tL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9tYXN0ZXIvZm9saXVtL3RlbXBsYXRlcy9sZWFmbGV0LmF3ZXNvbWUucm90YXRlLmNzcyIvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogMTAwLjAlOwogICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgICAgICAgICAgdG9wOiAwLjAlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICA8L3N0eWxlPgogICAgICAgIAo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgICAgICAgICA8ZGl2IGNsYXNzPSJmb2xpdW0tbWFwIiBpZD0ibWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzIiA+PC9kaXY+CiAgICAgICAgCjwvYm9keT4KPHNjcmlwdD4gICAgCiAgICAKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGJvdW5kcyA9IG51bGw7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgdmFyIG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyA9IEwubWFwKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ21hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7Y2VudGVyOiBbNDAuNzE1MzM3LC03NC4wMDg4NDhdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgem9vbTogMTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhCb3VuZHM6IGJvdW5kcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxheWVyczogW10sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JsZENvcHlKdW1wOiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyczogTC5DUlMuRVBTRzM4NTcKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciB0aWxlX2xheWVyXzFlZjA3MDgyZDA0MzQ1MmI4ZGU1OTY1YzU3NDExZWQyID0gTC50aWxlTGF5ZXIoCiAgICAgICAgICAgICAgICAnaHR0cHM6Ly97c30udGlsZS5vcGVuc3RyZWV0bWFwLm9yZy97en0ve3h9L3t5fS5wbmcnLAogICAgICAgICAgICAgICAgewogICJhdHRyaWJ1dGlvbiI6IG51bGwsCiAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICJtYXhab29tIjogMTgsCiAgIm1pblpvb20iOiAxLAogICJub1dyYXAiOiBmYWxzZSwKICAic3ViZG9tYWlucyI6ICJhYmMiCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84MDY2ZGY2NWIyNWM0OTg3OWZhNTg0MzFkYzY2YTNiOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNTMzNywtNzQuMDA4ODQ4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogInJlZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogInJlZCIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMTAsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzgxM2Y3MjZjYTM5NGMwOGEwN2JiNGRkMjEzN2U1NjggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNWM0OGE5NmQxMTJjNDFlNGEyYmQxNzljMGNjMDBmM2YgPSAkKCc8ZGl2IGlkPSJodG1sXzVjNDhhOTZkMTEyYzQxZTRhMmJkMTc5YzBjYzAwZjNmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FY2NvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zODEzZjcyNmNhMzk0YzA4YTA3YmI0ZGQyMTM3ZTU2OC5zZXRDb250ZW50KGh0bWxfNWM0OGE5NmQxMTJjNDFlNGEyYmQxNzljMGNjMDBmM2YpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODA2NmRmNjViMjVjNDk4NzlmYTU4NDMxZGM2NmEzYjkuYmluZFBvcHVwKHBvcHVwXzM4MTNmNzI2Y2EzOTRjMDhhMDdiYjRkZDIxMzdlNTY4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2JhYWIxZDViNGY1YTQ2ZDE5OTY4NjMzYzNmZGZkOGUxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE0ODI0Mzc3MTQ4MzksLTc0LjAwOTQwNDI1NDYxNDkyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzg3MGJiOTMwYzIzZjRlYWFiMTUxN2VmOWRiMmU0YWEzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzY5NTZmNzM3NGJkMTQ5NmU5ZjBhYjdiNGRiZGY4NTk3ID0gJCgnPGRpdiBpZD0iaHRtbF82OTU2ZjczNzRiZDE0OTZlOWYwYWI3YjRkYmRmODU5NyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RnVybml0dXJlIC8gSG9tZSBTdG9yZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfODcwYmI5MzBjMjNmNGVhYWIxNTE3ZWY5ZGIyZTRhYTMuc2V0Q29udGVudChodG1sXzY5NTZmNzM3NGJkMTQ5NmU5ZjBhYjdiNGRiZGY4NTk3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2JhYWIxZDViNGY1YTQ2ZDE5OTY4NjMzYzNmZGZkOGUxLmJpbmRQb3B1cChwb3B1cF84NzBiYjkzMGMyM2Y0ZWFhYjE1MTdlZjlkYjJlNGFhMyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mYTNlZDVkNDc4NGE0OTNmYWEyMWE1YmFlNmZlMGY4YyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNDc4NzY5OTA4MDUxLC03NC4wMTExMzE3NTAyMTU3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RlNjVkNDg4YTFmNzQ2OGM5N2YxNTg3MTljNGUwMDUxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2ExZjkzNTY0Y2Q0ZTQ5MTJiZDZkOTU3MWJmYTMwNTg1ID0gJCgnPGRpdiBpZD0iaHRtbF9hMWY5MzU2NGNkNGU0OTEyYmQ2ZDk1NzFiZmEzMDU4NSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VmVnZXRhcmlhbiAvIFZlZ2FuIFJlc3RhdXJhbnQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2RlNjVkNDg4YTFmNzQ2OGM5N2YxNTg3MTljNGUwMDUxLnNldENvbnRlbnQoaHRtbF9hMWY5MzU2NGNkNGU0OTEyYmQ2ZDk1NzFiZmEzMDU4NSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mYTNlZDVkNDc4NGE0OTNmYWEyMWE1YmFlNmZlMGY4Yy5iaW5kUG9wdXAocG9wdXBfZGU2NWQ0ODhhMWY3NDY4Yzk3ZjE1ODcxOWM0ZTAwNTEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOTM4MzVjMmUzNGNhNGQ2ODk5MGMyNWViMWQ1OWE1ODEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTM2NTI4NDUzMDE4OTQsLTc0LjAwODgwMzg5NTMwMTddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImJsdWUiLAogICJmaWxsT3BhY2l0eSI6IDAuNiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNDRiNmUxYTJiN2ZjNGIxOWI1NGI5NTFjMGVlMjQzYjIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMzI4MTlkZjZkYWE1NGFjZDgxMGM4YjYwYjdlMTUyMDcgPSAkKCc8ZGl2IGlkPSJodG1sXzMyODE5ZGY2ZGFhNTRhY2Q4MTBjOGI2MGI3ZTE1MjA3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CYWtlcnk8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzQ0YjZlMWEyYjdmYzRiMTliNTRiOTUxYzBlZTI0M2IyLnNldENvbnRlbnQoaHRtbF8zMjgxOWRmNmRhYTU0YWNkODEwYzhiNjBiN2UxNTIwNyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85MzgzNWMyZTM0Y2E0ZDY4OTkwYzI1ZWIxZDU5YTU4MS5iaW5kUG9wdXAocG9wdXBfNDRiNmUxYTJiN2ZjNGIxOWI1NGI5NTFjMGVlMjQzYjIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfM2U0MmI4ZjUzYjllNGIyNzgwYzRhYTQ4Njg2NTczZDYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTY1MjY0NzQxMjM3NCwtNzQuMDA4MTAxMDg0NjYyMDddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImJsdWUiLAogICJmaWxsT3BhY2l0eSI6IDAuNiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMDAyODU0NzQwNWZmNDE3Y2I1ZjFhZjU0ZDkxNDczODggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZmZhMWNjYzkxYTQ1NDNhMjk5YWZiNjhiNmNhN2VjOTQgPSAkKCc8ZGl2IGlkPSJodG1sX2ZmYTFjY2M5MWE0NTQzYTI5OWFmYjY4YjZjYTdlYzk0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TdXNoaSBSZXN0YXVyYW50PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wMDI4NTQ3NDA1ZmY0MTdjYjVmMWFmNTRkOTE0NzM4OC5zZXRDb250ZW50KGh0bWxfZmZhMWNjYzkxYTQ1NDNhMjk5YWZiNjhiNmNhN2VjOTQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfM2U0MmI4ZjUzYjllNGIyNzgwYzRhYTQ4Njg2NTczZDYuYmluZFBvcHVwKHBvcHVwXzAwMjg1NDc0MDVmZjQxN2NiNWYxYWY1NGQ5MTQ3Mzg4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2FiZmUxMDI2OTJmZDQ1NDliNWZmY2I3Yjk5YThkMWJmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE1NzczMDYzOTI4Mzc0LC03NC4wMDk3MTgyMzMxMjMzMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81NzViYTBkMDg4NGI0ODA3YWViNTNmZTUyNDRjMjFiOSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83ODFmODMxMTllNzk0MDhjOTBhNTIxZjc2NWIyMWZhOSA9ICQoJzxkaXYgaWQ9Imh0bWxfNzgxZjgzMTE5ZTc5NDA4YzkwYTUyMWY3NjViMjFmYTkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldpbmUgU2hvcDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNTc1YmEwZDA4ODRiNDgwN2FlYjUzZmU1MjQ0YzIxYjkuc2V0Q29udGVudChodG1sXzc4MWY4MzExOWU3OTQwOGM5MGE1MjFmNzY1YjIxZmE5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2FiZmUxMDI2OTJmZDQ1NDliNWZmY2I3Yjk5YThkMWJmLmJpbmRQb3B1cChwb3B1cF81NzViYTBkMDg4NGI0ODA3YWViNTNmZTUyNDRjMjFiOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jMjVjNzBmMDJhYTA0YjU0ODE1ZjQwYzg3NmI3MjI0NCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNTU5ODQ4NjY4NzY3NSwtNzQuMDA3ODgyMjc1MTEyODhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImJsdWUiLAogICJmaWxsT3BhY2l0eSI6IDAuNiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjQ1Mjc3ZTM0MzExNDNmZWFjYmU2NmIyNjA5NTRkODYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYTAzNDQ3MjA5MDIzNDg2NmI1ZDFhNmViZTAxY2M4MmYgPSAkKCc8ZGl2IGlkPSJodG1sX2EwMzQ0NzIwOTAyMzQ4NjZiNWQxYTZlYmUwMWNjODJmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TcGE8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Y0NTI3N2UzNDMxMTQzZmVhY2JlNjZiMjYwOTU0ZDg2LnNldENvbnRlbnQoaHRtbF9hMDM0NDcyMDkwMjM0ODY2YjVkMWE2ZWJlMDFjYzgyZik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jMjVjNzBmMDJhYTA0YjU0ODE1ZjQwYzg3NmI3MjI0NC5iaW5kUG9wdXAocG9wdXBfZjQ1Mjc3ZTM0MzExNDNmZWFjYmU2NmIyNjA5NTRkODYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZDI5NjcyZmQ0MDkzNDllMThlODA5NjBiMjdmZTczYWUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTQwOTg2MDcyNjA0MSwtNzQuMDA5Njg1NzE3OTI4M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81YmUzMzAxMjRlYjc0ZWEzYWNhNzAxNzIwMDQ1ZDlhNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iNjE0ZGU1ZTVjMjE0MTY1YTRiMzBmZjgzYmUxNjEyYSA9ICQoJzxkaXYgaWQ9Imh0bWxfYjYxNGRlNWU1YzIxNDE2NWE0YjMwZmY4M2JlMTYxMmEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkd5bTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNWJlMzMwMTI0ZWI3NGVhM2FjYTcwMTcyMDA0NWQ5YTcuc2V0Q29udGVudChodG1sX2I2MTRkZTVlNWMyMTQxNjVhNGIzMGZmODNiZTE2MTJhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2QyOTY3MmZkNDA5MzQ5ZTE4ZTgwOTYwYjI3ZmU3M2FlLmJpbmRQb3B1cChwb3B1cF81YmUzMzAxMjRlYjc0ZWEzYWNhNzAxNzIwMDQ1ZDlhNyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yOTg4ZDQwZjFhNWY0YTQxYTE4OGVjMDU4OTNkNjBmMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNTI4NDIzMTMyODI3LC03NC4wMDg3ODA5Mzk1MjAxOF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82OGJmZTIxNjQ5YTc0NmI4YTk4ZDJhMjIzYmMxMDEzNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81NThmY2Q0OGZkMWQ0YzI1YTNlNTUwYjBiZDAzNjE5OSA9ICQoJzxkaXYgaWQ9Imh0bWxfNTU4ZmNkNDhmZDFkNGMyNWEzZTU1MGIwYmQwMzYxOTkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkFudGlxdWUgU2hvcDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNjhiZmUyMTY0OWE3NDZiOGE5OGQyYTIyM2JjMTAxMzcuc2V0Q29udGVudChodG1sXzU1OGZjZDQ4ZmQxZDRjMjVhM2U1NTBiMGJkMDM2MTk5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzI5ODhkNDBmMWE1ZjRhNDFhMTg4ZWMwNTg5M2Q2MGYyLmJpbmRQb3B1cChwb3B1cF82OGJmZTIxNjQ5YTc0NmI4YTk4ZDJhMjIzYmMxMDEzNyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hMjY4NmE1OGNiYTk0MTIzYmU2NjJhZTNmZGNlYTViYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNTUzNzEwMTE2NDE2LC03NC4wMDc3MjQ1MjkyNTU2NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9hNDBkNjliNzdkYTM0ZDdjYjM5NmM2M2IwYTE4YWE0NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8yYjZiOGZiNWU4ZjQ0N2QwOGJlZWIwNGVhYTNiNTFmOSA9ICQoJzxkaXYgaWQ9Imh0bWxfMmI2YjhmYjVlOGY0NDdkMDhiZWViMDRlYWEzYjUxZjkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZhbGFmZWwgUmVzdGF1cmFudDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYTQwZDY5Yjc3ZGEzNGQ3Y2IzOTZjNjNiMGExOGFhNDQuc2V0Q29udGVudChodG1sXzJiNmI4ZmI1ZThmNDQ3ZDA4YmVlYjA0ZWFhM2I1MWY5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2EyNjg2YTU4Y2JhOTQxMjNiZTY2MmFlM2ZkY2VhNWJiLmJpbmRQb3B1cChwb3B1cF9hNDBkNjliNzdkYTM0ZDdjYjM5NmM2M2IwYTE4YWE0NCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mMzVlYWQ4OTg5MTE0ZTk4YWE0NTY5ZWVjOWI1ODhhOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNTE3NjkzOTY2MzE1LC03NC4wMTAyMjc0Nzc3ODI4NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82NzlmZjY5NWQwOTg0M2IwOGQ0NjQ1ZGIzOGJhNTU1NSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lYWI5ODM5ZmFhYTg0ZmEyYmNmZjE5OTU3MGY3ZTk1YSA9ICQoJzxkaXYgaWQ9Imh0bWxfZWFiOTgzOWZhYWE4NGZhMmJjZmYxOTk1NzBmN2U5NWEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNhZsOpPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82NzlmZjY5NWQwOTg0M2IwOGQ0NjQ1ZGIzOGJhNTU1NS5zZXRDb250ZW50KGh0bWxfZWFiOTgzOWZhYWE4NGZhMmJjZmYxOTk1NzBmN2U5NWEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjM1ZWFkODk4OTExNGU5OGFhNDU2OWVlYzliNTg4YTguYmluZFBvcHVwKHBvcHVwXzY3OWZmNjk1ZDA5ODQzYjA4ZDQ2NDVkYjM4YmE1NTU1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzdiMTIyNTVjZmQxMDRiMzliNjQyM2Y5NDZlODY2NGY0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE1NTc5MTU1NDIwNjA2LC03NC4wMTEzNjgyMzk1ODExOV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81NDJkNmVkNTc4MDM0ZDljYTY2N2QxZjgwNjEyNGVmMSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85NmI2MjJiZDEyYTk0N2UxOTk4NmQxNzQwNDM5MDk0ZCA9ICQoJzxkaXYgaWQ9Imh0bWxfOTZiNjIyYmQxMmE5NDdlMTk5ODZkMTc0MDQzOTA5NGQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkdyb2NlcnkgU3RvcmU8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzU0MmQ2ZWQ1NzgwMzRkOWNhNjY3ZDFmODA2MTI0ZWYxLnNldENvbnRlbnQoaHRtbF85NmI2MjJiZDEyYTk0N2UxOTk4NmQxNzQwNDM5MDk0ZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83YjEyMjU1Y2ZkMTA0YjM5YjY0MjNmOTQ2ZTg2NjRmNC5iaW5kUG9wdXAocG9wdXBfNTQyZDZlZDU3ODAzNGQ5Y2E2NjdkMWY4MDYxMjRlZjEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZmQ4MGJjYjQwZDI4NDg4Y2I1NWEyYjFlM2VjOWNlNDMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTU2Mjg2MjAwMjU2LC03NC4wMDc5OTIyNTgzODUzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2NkNWQ1NDg5ZDBlZDQzMTRhZmU1NzdiZGY4YTlhZjRkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzRiNjhjMGVkMjVkMTRhN2Y5OGJhNjI1Nzc0MjQwYjEzID0gJCgnPGRpdiBpZD0iaHRtbF80YjY4YzBlZDI1ZDE0YTdmOThiYTYyNTc3NDI0MGIxMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+R3ltIC8gRml0bmVzcyBDZW50ZXI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2NkNWQ1NDg5ZDBlZDQzMTRhZmU1NzdiZGY4YTlhZjRkLnNldENvbnRlbnQoaHRtbF80YjY4YzBlZDI1ZDE0YTdmOThiYTYyNTc3NDI0MGIxMyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mZDgwYmNiNDBkMjg0ODhjYjU1YTJiMWUzZWM5Y2U0My5iaW5kUG9wdXAocG9wdXBfY2Q1ZDU0ODlkMGVkNDMxNGFmZTU3N2JkZjhhOWFmNGQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZGNiYWE0YzY4ZWZiNDllZTlhNzEwZTZlMTUxNTYyZDAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTU0ODY1ODUyNDk3MzUsLTc0LjAwOTEzMzEzNTEwODM2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2QwZjhjNTMzZDY5ZDQxOTc5MTMwYzhjOTYyYzQ4YmE2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2E4YzYxYTNmMjM1MDRjOTRhODVjMmIxZTA4NWZkNzU3ID0gJCgnPGRpdiBpZD0iaHRtbF9hOGM2MWEzZjIzNTA0Yzk0YTg1YzJiMWUwODVmZDc1NyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QW1lcmljYW4gUmVzdGF1cmFudDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZDBmOGM1MzNkNjlkNDE5NzkxMzBjOGM5NjJjNDhiYTYuc2V0Q29udGVudChodG1sX2E4YzYxYTNmMjM1MDRjOTRhODVjMmIxZTA4NWZkNzU3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2RjYmFhNGM2OGVmYjQ5ZWU5YTcxMGU2ZTE1MTU2MmQwLmJpbmRQb3B1cChwb3B1cF9kMGY4YzUzM2Q2OWQ0MTk3OTEzMGM4Yzk2MmM0OGJhNik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81ODdmOTAwODE2YjM0MjY3YTY3MjM3OTc3ZTViNDIxNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNDM1LC03NC4wMDk4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2Y2NDBiZDE1YTQ1ZjRmODBhMTE5MTY0MmE5YjhlMGYxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc5MmE3YWNiMjY2MDQ3OWU5OWVhZjQ0NGYwZWE1OTQxID0gJCgnPGRpdiBpZD0iaHRtbF83OTJhN2FjYjI2NjA0NzllOTllYWY0NDRmMGVhNTk0MSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3RyaXAgQ2x1YjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZjY0MGJkMTVhNDVmNGY4MGExMTkxNjQyYTliOGUwZjEuc2V0Q29udGVudChodG1sXzc5MmE3YWNiMjY2MDQ3OWU5OWVhZjQ0NGYwZWE1OTQxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU4N2Y5MDA4MTZiMzQyNjdhNjcyMzc5NzdlNWI0MjE0LmJpbmRQb3B1cChwb3B1cF9mNjQwYmQxNWE0NWY0ZjgwYTExOTE2NDJhOWI4ZTBmMSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xZDM2ZDVhZDBjYzc0ZjAyOTE5MDg1MmIwZmM0YTNkZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNjM3OTg0MzE3MDcxLC03NC4wMDk2MjkzMzQ1MzQyOF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zNjRjYWE3ZWY1NjI0ZjZhYTU2ZDliZTczYTEzNTA0NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF84YmRmYzk0NzM0MjU0OGNmYTFhYmNkMzBiNTIxNjc1ZSA9ICQoJzxkaXYgaWQ9Imh0bWxfOGJkZmM5NDczNDI1NDhjZmExYWJjZDMwYjUyMTY3NWUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5ldyBBbWVyaWNhbiBSZXN0YXVyYW50PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zNjRjYWE3ZWY1NjI0ZjZhYTU2ZDliZTczYTEzNTA0NC5zZXRDb250ZW50KGh0bWxfOGJkZmM5NDczNDI1NDhjZmExYWJjZDMwYjUyMTY3NWUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMWQzNmQ1YWQwY2M3NGYwMjkxOTA4NTJiMGZjNGEzZGYuYmluZFBvcHVwKHBvcHVwXzM2NGNhYTdlZjU2MjRmNmFhNTZkOWJlNzNhMTM1MDQ0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzM4NjZkN2QxOTQwNTQ3NjM4ZmQzMmVkZTk1ZTE5NWI0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE0OTA5NTAxNTM5ODIsLTc0LjAwOTQ4MDI3MDExOTAzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzJiNWVmMmY3Mjg3NjQ1NGViOTQ2NDliOGZkZjcxOTg2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzVlZjE1NDliMzMxYjRmZmVhNjM3ZGNhMjlmNWZmN2UzID0gJCgnPGRpdiBpZD0iaHRtbF81ZWYxNTQ5YjMzMWI0ZmZlYTYzN2RjYTI5ZjVmZjdlMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Qm9va3N0b3JlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yYjVlZjJmNzI4NzY0NTRlYjk0NjQ5YjhmZGY3MTk4Ni5zZXRDb250ZW50KGh0bWxfNWVmMTU0OWIzMzFiNGZmZWE2MzdkY2EyOWY1ZmY3ZTMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMzg2NmQ3ZDE5NDA1NDc2MzhmZDMyZWRlOTVlMTk1YjQuYmluZFBvcHVwKHBvcHVwXzJiNWVmMmY3Mjg3NjQ1NGViOTQ2NDliOGZkZjcxOTg2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY3YTUzMmExZWIxZDRmMTc4M2EzMGNkMTVmZjk4NDU3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE2NzUyODE2ODc2NjM1LC03NC4wMDg1ODM3NjI5NTIyMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85ZjE3ZmU4YjE0NTA0ODQ4OGFkNDU2ZTM5Y2Q3ZjgzMSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mYTFhN2FlZDZmZjE0OGZjOWNhYzkwNTdmMjAwOGY5NSA9ICQoJzxkaXYgaWQ9Imh0bWxfZmExYTdhZWQ2ZmYxNDhmYzljYWM5MDU3ZjIwMDhmOTUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkFzaWFuIFJlc3RhdXJhbnQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzlmMTdmZThiMTQ1MDQ4NDg4YWQ0NTZlMzljZDdmODMxLnNldENvbnRlbnQoaHRtbF9mYTFhN2FlZDZmZjE0OGZjOWNhYzkwNTdmMjAwOGY5NSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82N2E1MzJhMWViMWQ0ZjE3ODNhMzBjZDE1ZmY5ODQ1Ny5iaW5kUG9wdXAocG9wdXBfOWYxN2ZlOGIxNDUwNDg0ODhhZDQ1NmUzOWNkN2Y4MzEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfY2JkNTBlYmM0OTU5NDAzNGEwMmIzMzliY2Y3YmY5YWQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTUzMDA2NDgwNTY5OSwtNzQuMDA5MzQ3MDMyNDcyMzldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImJsdWUiLAogICJmaWxsT3BhY2l0eSI6IDAuNiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNzMzN2I3ZDk5MzgwNDA5MjhmYmQxYTQ4NzU5MDA2ZjkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfY2NjZjQ3OGVkNTQ3NDE0Njg4MDc4YzNmOTg4MzVkYzEgPSAkKCc8ZGl2IGlkPSJodG1sX2NjY2Y0NzhlZDU0NzQxNDY4ODA3OGMzZjk4ODM1ZGMxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ib3RlbCBCYXI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzczMzdiN2Q5OTM4MDQwOTI4ZmJkMWE0ODc1OTAwNmY5LnNldENvbnRlbnQoaHRtbF9jY2NmNDc4ZWQ1NDc0MTQ2ODgwNzhjM2Y5ODgzNWRjMSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jYmQ1MGViYzQ5NTk0MDM0YTAyYjMzOWJjZjdiZjlhZC5iaW5kUG9wdXAocG9wdXBfNzMzN2I3ZDk5MzgwNDA5MjhmYmQxYTQ4NzU5MDA2ZjkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZTI1ZmU0MWI5MDkyNDRlMmI5ZDJjMzc5NWU3ZTQxYjEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTY3NDA4NDE2MzM2OSwtNzQuMDA4NjY2NDQzODg5M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wMjg1NTdmMjZkN2E0NzgyYjg5YTljZTQ3MGU1MDk4MSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF84MzQ4MThlYmQyMTk0MDgwOGI5ZGE3OGQ5ZjUzOGZlMiA9ICQoJzxkaXYgaWQ9Imh0bWxfODM0ODE4ZWJkMjE5NDA4MDhiOWRhNzhkOWY1MzhmZTIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNvY2t0YWlsIEJhcjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDI4NTU3ZjI2ZDdhNDc4MmI4OWE5Y2U0NzBlNTA5ODEuc2V0Q29udGVudChodG1sXzgzNDgxOGViZDIxOTQwODA4YjlkYTc4ZDlmNTM4ZmUyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2UyNWZlNDFiOTA5MjQ0ZTJiOWQyYzM3OTVlN2U0MWIxLmJpbmRQb3B1cChwb3B1cF8wMjg1NTdmMjZkN2E0NzgyYjg5YTljZTQ3MGU1MDk4MSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83MmU2YTA4N2JiNjg0ZDgzOTIzN2Y0YTQ0ZWZkYjdmNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNjc5MzA0ODU1ODA4LC03NC4wMDgyMTk5ODg3ODQ1N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84ZWM2ODU5M2JjNDQ0OTNhYWEwNWVkZWZmY2NhOTc0ZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iOGQ3ODJkYmMwOTM0MTQ1OWVkYmFiZjgxMzEwMjMxZSA9ICQoJzxkaXYgaWQ9Imh0bWxfYjhkNzgyZGJjMDkzNDE0NTllZGJhYmY4MTMxMDIzMWUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkFtZXJpY2FuIFJlc3RhdXJhbnQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzhlYzY4NTkzYmM0NDQ5M2FhYTA1ZWRlZmZjY2E5NzRmLnNldENvbnRlbnQoaHRtbF9iOGQ3ODJkYmMwOTM0MTQ1OWVkYmFiZjgxMzEwMjMxZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83MmU2YTA4N2JiNjg0ZDgzOTIzN2Y0YTQ0ZWZkYjdmNS5iaW5kUG9wdXAocG9wdXBfOGVjNjg1OTNiYzQ0NDkzYWFhMDVlZGVmZmNjYTk3NGYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYWJjMzE1M2E0Yzg0NGM2MzhjYTNjOTNiZTRiOGQ1NjUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTQxNywtNzQuMDA4NjZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImJsdWUiLAogICJmaWxsT3BhY2l0eSI6IDAuNiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOGY3NjNiYzJmOTkyNGZlZGEzOTcwM2QzN2M3N2NkMzYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYzM3MWQzNjlhY2UwNDBlYWJiNmEwNzI1YmFlNTk2NzggPSAkKCc8ZGl2IGlkPSJodG1sX2MzNzFkMzY5YWNlMDQwZWFiYjZhMDcyNWJhZTU5Njc4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UYWNvIFBsYWNlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84Zjc2M2JjMmY5OTI0ZmVkYTM5NzAzZDM3Yzc3Y2QzNi5zZXRDb250ZW50KGh0bWxfYzM3MWQzNjlhY2UwNDBlYWJiNmEwNzI1YmFlNTk2NzgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYWJjMzE1M2E0Yzg0NGM2MzhjYTNjOTNiZTRiOGQ1NjUuYmluZFBvcHVwKHBvcHVwXzhmNzYzYmMyZjk5MjRmZWRhMzk3MDNkMzdjNzdjZDM2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzI3MGI4NDdjMmViNzRjN2NhMjMzMjg4MjY5Mzk3N2VjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE0NzU0MTUxNDYxMjM2LC03NC4wMDc1ODA2MDAyMDM5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RlNWFkMmEyMTcyNDRmZjA5NmFlY2NkMzA5MjMxNDJlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2U4YzFhZWM2MDRlOTRlYzJiMjcxM2RkZTViYWQzOWRjID0gJCgnPGRpdiBpZD0iaHRtbF9lOGMxYWVjNjA0ZTk0ZWMyYjI3MTNkZGU1YmFkMzlkYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RnJlbmNoIFJlc3RhdXJhbnQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2RlNWFkMmEyMTcyNDRmZjA5NmFlY2NkMzA5MjMxNDJlLnNldENvbnRlbnQoaHRtbF9lOGMxYWVjNjA0ZTk0ZWMyYjI3MTNkZGU1YmFkMzlkYyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yNzBiODQ3YzJlYjc0YzdjYTIzMzI4ODI2OTM5NzdlYy5iaW5kUG9wdXAocG9wdXBfZGU1YWQyYTIxNzI0NGZmMDk2YWVjY2QzMDkyMzE0MmUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjkzZDM3ZmYyZjc2NDNmMzhlMTRjNDU4NDk3MWFkZDUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTcwMTAxMTQwOTkwNiwtNzQuMDA4MDQyNDQ1NjIyMjVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImJsdWUiLAogICJmaWxsT3BhY2l0eSI6IDAuNiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZmZlOGY1MjJlY2U3NDljZDkxY2Q2ZmZkZjQ2ZDQyYWMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZmVmNDJiOTNmYzg1NDVlMTljZGIzOTNjOGYyOWM2OTQgPSAkKCc8ZGl2IGlkPSJodG1sX2ZlZjQyYjkzZmM4NTQ1ZTE5Y2RiMzkzYzhmMjljNjk0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5GcmVuY2ggUmVzdGF1cmFudDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZmZlOGY1MjJlY2U3NDljZDkxY2Q2ZmZkZjQ2ZDQyYWMuc2V0Q29udGVudChodG1sX2ZlZjQyYjkzZmM4NTQ1ZTE5Y2RiMzkzYzhmMjljNjk0KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2I5M2QzN2ZmMmY3NjQzZjM4ZTE0YzQ1ODQ5NzFhZGQ1LmJpbmRQb3B1cChwb3B1cF9mZmU4ZjUyMmVjZTc0OWNkOTFjZDZmZmRmNDZkNDJhYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yYzJiMWZkM2ZiMjM0ZTlkYWIzMDYxYmU3NmIyNzFhMSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNTk0MTI1NTY2OTMxLC03NC4wMDg3MjA1MzU2NDQ5NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mODYwNjZjMDdjNGU0YzMxYjdjOWQ4MGY1N2ZkMTNlYiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iOTg1MWM3ZGFjYmM0YjdkYWIwZmIxOTRiNTgzMDU5MCA9ICQoJzxkaXYgaWQ9Imh0bWxfYjk4NTFjN2RhY2JjNGI3ZGFiMGZiMTk0YjU4MzA1OTAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5haWwgU2Fsb248L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Y4NjA2NmMwN2M0ZTRjMzFiN2M5ZDgwZjU3ZmQxM2ViLnNldENvbnRlbnQoaHRtbF9iOTg1MWM3ZGFjYmM0YjdkYWIwZmIxOTRiNTgzMDU5MCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yYzJiMWZkM2ZiMjM0ZTlkYWIzMDYxYmU3NmIyNzFhMS5iaW5kUG9wdXAocG9wdXBfZjg2MDY2YzA3YzRlNGMzMWI3YzlkODBmNTdmZDEzZWIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjZlNmFkNmI0ZGQ0NGZlNmE1YjlkYTgyN2UyMDRmNzUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTY2ODQzOTIyNzgyMiwtNzQuMDA4MzQzNDI4NjkyMzhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImJsdWUiLAogICJmaWxsT3BhY2l0eSI6IDAuNiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzM1YzE1ZmU5YzJkNDJjMjljZmVmNDI2ZTRiNDIwM2UgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMjdkODZiMzY0NWM4NDc4ZmE2M2IxOTI3ZGRiMTVhOWQgPSAkKCc8ZGl2IGlkPSJodG1sXzI3ZDg2YjM2NDVjODQ3OGZhNjNiMTkyN2RkYjE1YTlkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TdXNoaSBSZXN0YXVyYW50PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zMzVjMTVmZTljMmQ0MmMyOWNmZWY0MjZlNGI0MjAzZS5zZXRDb250ZW50KGh0bWxfMjdkODZiMzY0NWM4NDc4ZmE2M2IxOTI3ZGRiMTVhOWQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjZlNmFkNmI0ZGQ0NGZlNmE1YjlkYTgyN2UyMDRmNzUuYmluZFBvcHVwKHBvcHVwXzMzNWMxNWZlOWMyZDQyYzI5Y2ZlZjQyNmU0YjQyMDNlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzI0NDBmZGFmOTI2ODQxOGFhMWNiZjYyNDg0MjM3OTAxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE0MzQyMjkwMTU4MDg2LC03NC4wMDgwOTM1Njg0MDAwNF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81M2I5MzAxZDMyNDY0NTdiOGExM2YwYmYwN2Q5OTg1NiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zNjg5MGMxMzEzODE0OTcyOTJiOTU3MzE5ZGNiZjNiNiA9ICQoJzxkaXYgaWQ9Imh0bWxfMzY4OTBjMTMxMzgxNDk3MjkyYjk1NzMxOWRjYmYzYjYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPllvZ2EgU3R1ZGlvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81M2I5MzAxZDMyNDY0NTdiOGExM2YwYmYwN2Q5OTg1Ni5zZXRDb250ZW50KGh0bWxfMzY4OTBjMTMxMzgxNDk3MjkyYjk1NzMxOWRjYmYzYjYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjQ0MGZkYWY5MjY4NDE4YWExY2JmNjI0ODQyMzc5MDEuYmluZFBvcHVwKHBvcHVwXzUzYjkzMDFkMzI0NjQ1N2I4YTEzZjBiZjA3ZDk5ODU2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzRkYzA2YWE3NmYwNjQ3NzQ5MDI2NGUyNzg3OTBjYWYxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE1NTgsLTc0LjAwOTg1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzNmM2M1MjJkMmEyYzQ2OWJiZmZlODBiOTBhZDFiN2IxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2QzMGJmNjcxNDVmOTRhODE5MzdlZGYyYzk4ZmRhMTdhID0gJCgnPGRpdiBpZD0iaHRtbF9kMzBiZjY3MTQ1Zjk0YTgxOTM3ZWRmMmM5OGZkYTE3YSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmFnZWwgU2hvcDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfM2YzYzUyMmQyYTJjNDY5YmJmZmU4MGI5MGFkMWI3YjEuc2V0Q29udGVudChodG1sX2QzMGJmNjcxNDVmOTRhODE5MzdlZGYyYzk4ZmRhMTdhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzRkYzA2YWE3NmYwNjQ3NzQ5MDI2NGUyNzg3OTBjYWYxLmJpbmRQb3B1cChwb3B1cF8zZjNjNTIyZDJhMmM0NjliYmZmZTgwYjkwYWQxYjdiMSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yZGJmZGI3YzFlMTA0ZTM2OTlkZDEwMWM4ZWVlZjM5OSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNDc2LC03NC4wMDkyOF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jZjRjZDFlMWZmYjk0MmRhYmUyYzlhZjllMjA5ODY4NiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82ODA2Yzc2ZTJjODQ0NTRlOTg4NTMwODJjMzRhNjlmYSA9ICQoJzxkaXYgaWQ9Imh0bWxfNjgwNmM3NmUyYzg0NDU0ZTk4ODUzMDgyYzM0YTY5ZmEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJhYnkgU3RvcmU8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2NmNGNkMWUxZmZiOTQyZGFiZTJjOWFmOWUyMDk4Njg2LnNldENvbnRlbnQoaHRtbF82ODA2Yzc2ZTJjODQ0NTRlOTg4NTMwODJjMzRhNjlmYSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yZGJmZGI3YzFlMTA0ZTM2OTlkZDEwMWM4ZWVlZjM5OS5iaW5kUG9wdXAocG9wdXBfY2Y0Y2QxZTFmZmI5NDJkYWJlMmM5YWY5ZTIwOTg2ODYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYmNhMTY2OTU4ZmU3NDliMDg4ZjU4M2Q2ODM3MTA1NTAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTU4ODUxMjYwODYwMTUsLTc0LjAwODcxMzYxOTAyNDE4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2JmZTI5MGFjODIyYzRhOGM4MzI1ZDQwNDU4MjQwMDhhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzg0YjNjYzcxN2RmNjQ4NGY4ODUxZGMzNmRkNzAxMzg2ID0gJCgnPGRpdiBpZD0iaHRtbF84NGIzY2M3MTdkZjY0ODRmODg1MWRjMzZkZDcwMTM4NiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q29ja3RhaWwgQmFyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iZmUyOTBhYzgyMmM0YThjODMyNWQ0MDQ1ODI0MDA4YS5zZXRDb250ZW50KGh0bWxfODRiM2NjNzE3ZGY2NDg0Zjg4NTFkYzM2ZGQ3MDEzODYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYmNhMTY2OTU4ZmU3NDliMDg4ZjU4M2Q2ODM3MTA1NTAuYmluZFBvcHVwKHBvcHVwX2JmZTI5MGFjODIyYzRhOGM4MzI1ZDQwNDU4MjQwMDhhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I3N2E1NjdkMDMxZjQzOTBiNmU0Mzc1ZWYyMjUxYmEzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE3MTcyNzU4MDExNjgsLTc0LjAwOTMyODY5MTI1MTE3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzgzNDJiMGRjZTZiYjRiNDNiZmM5ODg2NWE0ZDhhMGZjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzY5MjdiZWYyZGFhODRjNGQ4NDU1YTU2YjA1NTNlODBlID0gJCgnPGRpdiBpZD0iaHRtbF82OTI3YmVmMmRhYTg0YzRkODQ1NWE1NmIwNTUzZTgwZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UGFyazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfODM0MmIwZGNlNmJiNGI0M2JmYzk4ODY1YTRkOGEwZmMuc2V0Q29udGVudChodG1sXzY5MjdiZWYyZGFhODRjNGQ4NDU1YTU2YjA1NTNlODBlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2I3N2E1NjdkMDMxZjQzOTBiNmU0Mzc1ZWYyMjUxYmEzLmJpbmRQb3B1cChwb3B1cF84MzQyYjBkY2U2YmI0YjQzYmZjOTg4NjVhNGQ4YTBmYyk7CgogICAgICAgICAgICAKICAgICAgICAKPC9zY3JpcHQ+\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
],
"text/plain": [
"<folium.folium.Map at 0x7f60fceac828>"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"venues_map = folium.Map(location=[latitude, longitude], zoom_start=15) # generate map centred around Ecco\n",
"\n",
"\n",
"# add Ecco as a red circle mark\n",
"folium.features.CircleMarker(\n",
" [latitude, longitude],\n",
" radius=10,\n",
" popup='Ecco',\n",
" fill=True,\n",
" color='red',\n",
" fill_color='red',\n",
" fill_opacity=0.6\n",
" ).add_to(venues_map)\n",
"\n",
"\n",
"# add popular spots to the map as blue circle markers\n",
"for lat, lng, label in zip(dataframe_filtered.lat, dataframe_filtered.lng, dataframe_filtered.categories):\n",
" folium.features.CircleMarker(\n",
" [lat, lng],\n",
" radius=5,\n",
" popup=label,\n",
" fill=True,\n",
" color='blue',\n",
" fill_color='blue',\n",
" fill_opacity=0.6\n",
" ).add_to(venues_map)\n",
"\n",
"# display map\n",
"venues_map"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"<a id=\"item5\"></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"## 5. Explore Trending Venues\n",
"> `https://api.foursquare.com/v2/venues/`**trending**`?client_id=`**CLIENT_ID**`&client_secret=`**CLIENT_SECRET**`&ll=`**LATITUDE**`,`**LONGITUDE**`&v=`**VERSION**"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"#### Now, instead of simply exploring the area around Ecco, you are interested in knowing the venues that are trending at the time you are done with your lunch, meaning the places with the highest foot traffic. So let's do that and get the trending venues around Ecco."
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/plain": [
"{'meta': {'code': 200, 'requestId': '5d88112a66fc65002cfcbb0a'},\n",
" 'response': {'venues': [{'id': '4e72a6ffaeb74f9f48eb61fe',\n",
" 'name': 'Feast of San Gennaro',\n",
" 'location': {'address': 'Mulberry St',\n",
" 'crossStreet': 'btwn Canal & Houston St',\n",
" 'lat': 40.72179480039333,\n",
" 'lng': -73.99631023406982,\n",
" 'labeledLatLngs': [{'label': 'display',\n",
" 'lat': 40.72179480039333,\n",
" 'lng': -73.99631023406982}],\n",
" 'distance': 1278,\n",
" 'postalCode': '10013',\n",
" 'cc': 'US',\n",
" 'city': 'New York',\n",
" 'state': 'NY',\n",
" 'country': 'United States',\n",
" 'formattedAddress': ['Mulberry St (btwn Canal & Houston St)',\n",
" 'New York, NY 10013',\n",
" 'United States']},\n",
" 'categories': [{'id': '5267e4d8e4b0ec79466e48c5',\n",
" 'name': 'Street Fair',\n",
" 'pluralName': 'Street Fairs',\n",
" 'shortName': 'Fair',\n",
" 'icon': {'prefix': 'https://ss3.4sqi.net/img/categories_v2/event/default_',\n",
" 'suffix': '.png'},\n",
" 'primary': True}]},\n",
" {'id': '40abf500f964a52035f31ee3',\n",
" 'name': 'Washington Square Park',\n",
" 'location': {'address': 'W 4th St',\n",
" 'crossStreet': 'btwn MacDougal St & University Pl',\n",
" 'lat': 40.73081579656163,\n",
" 'lng': -73.9974582195282,\n",
" 'labeledLatLngs': [{'label': 'display',\n",
" 'lat': 40.73081579656163,\n",
" 'lng': -73.9974582195282}],\n",
" 'distance': 1972,\n",
" 'postalCode': '10012',\n",
" 'cc': 'US',\n",
" 'city': 'New York',\n",
" 'state': 'NY',\n",
" 'country': 'United States',\n",
" 'formattedAddress': ['W 4th St (btwn MacDougal St & University Pl)',\n",
" 'New York, NY 10012',\n",
" 'United States']},\n",
" 'categories': [{'id': '4bf58dd8d48988d163941735',\n",
" 'name': 'Park',\n",
" 'pluralName': 'Parks',\n",
" 'shortName': 'Park',\n",
" 'icon': {'prefix': 'https://ss3.4sqi.net/img/categories_v2/parks_outdoors/park_',\n",
" 'suffix': '.png'},\n",
" 'primary': True}]},\n",
" {'id': '5cc4e9d0c876c8002c3010cb',\n",
" 'name': 'Wayla',\n",
" 'location': {'address': '100 Forsyth St',\n",
" 'crossStreet': 'btw Grand & Broome',\n",
" 'lat': 40.718193,\n",
" 'lng': -73.992846,\n",
" 'labeledLatLngs': [{'label': 'display',\n",
" 'lat': 40.718193,\n",
" 'lng': -73.992846}],\n",
" 'distance': 1387,\n",
" 'postalCode': '10002',\n",
" 'cc': 'US',\n",
" 'city': 'New York',\n",
" 'state': 'NY',\n",
" 'country': 'United States',\n",
" 'formattedAddress': ['100 Forsyth St (btw Grand & Broome)',\n",
" 'New York, NY 10002',\n",
" 'United States']},\n",
" 'categories': [{'id': '4bf58dd8d48988d149941735',\n",
" 'name': 'Thai Restaurant',\n",
" 'pluralName': 'Thai Restaurants',\n",
" 'shortName': 'Thai',\n",
" 'icon': {'prefix': 'https://ss3.4sqi.net/img/categories_v2/food/thai_',\n",
" 'suffix': '.png'},\n",
" 'primary': True}]}]}}"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# define URL\n",
"url = 'https://api.foursquare.com/v2/venues/trending?client_id={}&client_secret={}&ll={},{}&v={}'.format(CLIENT_ID, CLIENT_SECRET, latitude, longitude, VERSION)\n",
"\n",
"# send GET request and get trending venues\n",
"results = requests.get(url).json()\n",
"results"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"### Check if any venues are trending at this time"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [],
"source": [
"if len(results['response']['venues']) == 0:\n",
" trending_venues_df = 'No trending venues are available at the moment!'\n",
" \n",
"else:\n",
" trending_venues = results['response']['venues']\n",
" trending_venues_df = json_normalize(trending_venues)\n",
"\n",
" # filter columns\n",
" columns_filtered = ['name', 'categories'] + ['location.distance', 'location.city', 'location.postalCode', 'location.state', 'location.country', 'location.lat', 'location.lng']\n",
" trending_venues_df = trending_venues_df.loc[:, columns_filtered]\n",
"\n",
" # filter the category for each row\n",
" trending_venues_df['categories'] = trending_venues_df.apply(get_category_type, axis=1)"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>name</th>\n",
" <th>categories</th>\n",
" <th>location.distance</th>\n",
" <th>location.city</th>\n",
" <th>location.postalCode</th>\n",
" <th>location.state</th>\n",
" <th>location.country</th>\n",
" <th>location.lat</th>\n",
" <th>location.lng</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <td>0</td>\n",
" <td>The Rooftop @ Pier 17</td>\n",
" <td>Music Venue</td>\n",
" <td>1257</td>\n",
" <td>New York</td>\n",
" <td>10038</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>40.705463</td>\n",
" <td>-74.001598</td>\n",
" </tr>\n",
" <tr>\n",
" <td>1</td>\n",
" <td>Feast of San Gennaro</td>\n",
" <td>Street Fair</td>\n",
" <td>1278</td>\n",
" <td>New York</td>\n",
" <td>10013</td>\n",
" <td>NY</td>\n",
" <td>United States</td>\n",
" <td>40.721795</td>\n",
" <td>-73.996310</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" name categories location.distance location.city \\\n",
"0 The Rooftop @ Pier 17 Music Venue 1257 New York \n",
"1 Feast of San Gennaro Street Fair 1278 New York \n",
"\n",
" location.postalCode location.state location.country location.lat \\\n",
"0 10038 NY United States 40.705463 \n",
"1 10013 NY United States 40.721795 \n",
"\n",
" location.lng \n",
"0 -74.001598 \n",
"1 -73.996310 "
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# display trending venues\n",
"trending_venues_df"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"Now, depending on when you run the above code, you might get different venues since the venues with the highest foot traffic are fetched live. "
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"### Visualize trending venues"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [],
"source": [
"if len(results['response']['venues']) == 0:\n",
" venues_map = 'Cannot generate visual as no trending venues are available at the moment!'\n",
"\n",
"else:\n",
" venues_map = folium.Map(location=[latitude, longitude], zoom_start=15) # generate map centred around Ecco\n",
"\n",
"\n",
" # add Ecco as a red circle mark\n",
" folium.features.CircleMarker(\n",
" [latitude, longitude],\n",
" radius=10,\n",
" popup='Ecco',\n",
" fill=True,\n",
" color='red',\n",
" fill_color='red',\n",
" fill_opacity=0.6\n",
" ).add_to(venues_map)\n",
"\n",
"\n",
" # add the trending venues as blue circle markers\n",
" for lat, lng, label in zip(trending_venues_df['location.lat'], trending_venues_df['location.lng'], trending_venues_df['name']):\n",
" folium.features.CircleMarker(\n",
" [lat, lng],\n",
" radius=5,\n",
" poup=label,\n",
" fill=True,\n",
" color='blue',\n",
" fill_color='blue',\n",
" fill_opacity=0.6\n",
" ).add_to(venues_map)"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"button": false,
"collapsed": false,
"deletable": true,
"jupyter": {
"outputs_hidden": false
},
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"outputs": [
{
"data": {
"text/html": [
"<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVMgPSBmYWxzZTsgTF9OT19UT1VDSCA9IGZhbHNlOyBMX0RJU0FCTEVfM0QgPSBmYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdnaXQuY29tL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9tYXN0ZXIvZm9saXVtL3RlbXBsYXRlcy9sZWFmbGV0LmF3ZXNvbWUucm90YXRlLmNzcyIvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogMTAwLjAlOwogICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgICAgICAgICAgdG9wOiAwLjAlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICA8L3N0eWxlPgogICAgICAgIAo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgICAgICAgICA8ZGl2IGNsYXNzPSJmb2xpdW0tbWFwIiBpZD0ibWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzIiA+PC9kaXY+CiAgICAgICAgCjwvYm9keT4KPHNjcmlwdD4gICAgCiAgICAKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGJvdW5kcyA9IG51bGw7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgdmFyIG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyA9IEwubWFwKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ21hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7Y2VudGVyOiBbNDAuNzE1MzM3LC03NC4wMDg4NDhdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgem9vbTogMTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhCb3VuZHM6IGJvdW5kcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxheWVyczogW10sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JsZENvcHlKdW1wOiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyczogTC5DUlMuRVBTRzM4NTcKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciB0aWxlX2xheWVyXzFlZjA3MDgyZDA0MzQ1MmI4ZGU1OTY1YzU3NDExZWQyID0gTC50aWxlTGF5ZXIoCiAgICAgICAgICAgICAgICAnaHR0cHM6Ly97c30udGlsZS5vcGVuc3RyZWV0bWFwLm9yZy97en0ve3h9L3t5fS5wbmcnLAogICAgICAgICAgICAgICAgewogICJhdHRyaWJ1dGlvbiI6IG51bGwsCiAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICJtYXhab29tIjogMTgsCiAgIm1pblpvb20iOiAxLAogICJub1dyYXAiOiBmYWxzZSwKICAic3ViZG9tYWlucyI6ICJhYmMiCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84MDY2ZGY2NWIyNWM0OTg3OWZhNTg0MzFkYzY2YTNiOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNTMzNywtNzQuMDA4ODQ4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogInJlZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogInJlZCIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMTAsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzgxM2Y3MjZjYTM5NGMwOGEwN2JiNGRkMjEzN2U1NjggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNWM0OGE5NmQxMTJjNDFlNGEyYmQxNzljMGNjMDBmM2YgPSAkKCc8ZGl2IGlkPSJodG1sXzVjNDhhOTZkMTEyYzQxZTRhMmJkMTc5YzBjYzAwZjNmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FY2NvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zODEzZjcyNmNhMzk0YzA4YTA3YmI0ZGQyMTM3ZTU2OC5zZXRDb250ZW50KGh0bWxfNWM0OGE5NmQxMTJjNDFlNGEyYmQxNzljMGNjMDBmM2YpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODA2NmRmNjViMjVjNDk4NzlmYTU4NDMxZGM2NmEzYjkuYmluZFBvcHVwKHBvcHVwXzM4MTNmNzI2Y2EzOTRjMDhhMDdiYjRkZDIxMzdlNTY4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2JhYWIxZDViNGY1YTQ2ZDE5OTY4NjMzYzNmZGZkOGUxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE0ODI0Mzc3MTQ4MzksLTc0LjAwOTQwNDI1NDYxNDkyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzg3MGJiOTMwYzIzZjRlYWFiMTUxN2VmOWRiMmU0YWEzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzY5NTZmNzM3NGJkMTQ5NmU5ZjBhYjdiNGRiZGY4NTk3ID0gJCgnPGRpdiBpZD0iaHRtbF82OTU2ZjczNzRiZDE0OTZlOWYwYWI3YjRkYmRmODU5NyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RnVybml0dXJlIC8gSG9tZSBTdG9yZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfODcwYmI5MzBjMjNmNGVhYWIxNTE3ZWY5ZGIyZTRhYTMuc2V0Q29udGVudChodG1sXzY5NTZmNzM3NGJkMTQ5NmU5ZjBhYjdiNGRiZGY4NTk3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2JhYWIxZDViNGY1YTQ2ZDE5OTY4NjMzYzNmZGZkOGUxLmJpbmRQb3B1cChwb3B1cF84NzBiYjkzMGMyM2Y0ZWFhYjE1MTdlZjlkYjJlNGFhMyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mYTNlZDVkNDc4NGE0OTNmYWEyMWE1YmFlNmZlMGY4YyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNDc4NzY5OTA4MDUxLC03NC4wMTExMzE3NTAyMTU3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RlNjVkNDg4YTFmNzQ2OGM5N2YxNTg3MTljNGUwMDUxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2ExZjkzNTY0Y2Q0ZTQ5MTJiZDZkOTU3MWJmYTMwNTg1ID0gJCgnPGRpdiBpZD0iaHRtbF9hMWY5MzU2NGNkNGU0OTEyYmQ2ZDk1NzFiZmEzMDU4NSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VmVnZXRhcmlhbiAvIFZlZ2FuIFJlc3RhdXJhbnQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2RlNjVkNDg4YTFmNzQ2OGM5N2YxNTg3MTljNGUwMDUxLnNldENvbnRlbnQoaHRtbF9hMWY5MzU2NGNkNGU0OTEyYmQ2ZDk1NzFiZmEzMDU4NSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mYTNlZDVkNDc4NGE0OTNmYWEyMWE1YmFlNmZlMGY4Yy5iaW5kUG9wdXAocG9wdXBfZGU2NWQ0ODhhMWY3NDY4Yzk3ZjE1ODcxOWM0ZTAwNTEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOTM4MzVjMmUzNGNhNGQ2ODk5MGMyNWViMWQ1OWE1ODEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTM2NTI4NDUzMDE4OTQsLTc0LjAwODgwMzg5NTMwMTddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImJsdWUiLAogICJmaWxsT3BhY2l0eSI6IDAuNiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNDRiNmUxYTJiN2ZjNGIxOWI1NGI5NTFjMGVlMjQzYjIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMzI4MTlkZjZkYWE1NGFjZDgxMGM4YjYwYjdlMTUyMDcgPSAkKCc8ZGl2IGlkPSJodG1sXzMyODE5ZGY2ZGFhNTRhY2Q4MTBjOGI2MGI3ZTE1MjA3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CYWtlcnk8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzQ0YjZlMWEyYjdmYzRiMTliNTRiOTUxYzBlZTI0M2IyLnNldENvbnRlbnQoaHRtbF8zMjgxOWRmNmRhYTU0YWNkODEwYzhiNjBiN2UxNTIwNyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85MzgzNWMyZTM0Y2E0ZDY4OTkwYzI1ZWIxZDU5YTU4MS5iaW5kUG9wdXAocG9wdXBfNDRiNmUxYTJiN2ZjNGIxOWI1NGI5NTFjMGVlMjQzYjIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfM2U0MmI4ZjUzYjllNGIyNzgwYzRhYTQ4Njg2NTczZDYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTY1MjY0NzQxMjM3NCwtNzQuMDA4MTAxMDg0NjYyMDddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImJsdWUiLAogICJmaWxsT3BhY2l0eSI6IDAuNiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMDAyODU0NzQwNWZmNDE3Y2I1ZjFhZjU0ZDkxNDczODggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZmZhMWNjYzkxYTQ1NDNhMjk5YWZiNjhiNmNhN2VjOTQgPSAkKCc8ZGl2IGlkPSJodG1sX2ZmYTFjY2M5MWE0NTQzYTI5OWFmYjY4YjZjYTdlYzk0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TdXNoaSBSZXN0YXVyYW50PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wMDI4NTQ3NDA1ZmY0MTdjYjVmMWFmNTRkOTE0NzM4OC5zZXRDb250ZW50KGh0bWxfZmZhMWNjYzkxYTQ1NDNhMjk5YWZiNjhiNmNhN2VjOTQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfM2U0MmI4ZjUzYjllNGIyNzgwYzRhYTQ4Njg2NTczZDYuYmluZFBvcHVwKHBvcHVwXzAwMjg1NDc0MDVmZjQxN2NiNWYxYWY1NGQ5MTQ3Mzg4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2FiZmUxMDI2OTJmZDQ1NDliNWZmY2I3Yjk5YThkMWJmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE1NzczMDYzOTI4Mzc0LC03NC4wMDk3MTgyMzMxMjMzMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81NzViYTBkMDg4NGI0ODA3YWViNTNmZTUyNDRjMjFiOSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83ODFmODMxMTllNzk0MDhjOTBhNTIxZjc2NWIyMWZhOSA9ICQoJzxkaXYgaWQ9Imh0bWxfNzgxZjgzMTE5ZTc5NDA4YzkwYTUyMWY3NjViMjFmYTkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldpbmUgU2hvcDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNTc1YmEwZDA4ODRiNDgwN2FlYjUzZmU1MjQ0YzIxYjkuc2V0Q29udGVudChodG1sXzc4MWY4MzExOWU3OTQwOGM5MGE1MjFmNzY1YjIxZmE5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2FiZmUxMDI2OTJmZDQ1NDliNWZmY2I3Yjk5YThkMWJmLmJpbmRQb3B1cChwb3B1cF81NzViYTBkMDg4NGI0ODA3YWViNTNmZTUyNDRjMjFiOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jMjVjNzBmMDJhYTA0YjU0ODE1ZjQwYzg3NmI3MjI0NCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNTU5ODQ4NjY4NzY3NSwtNzQuMDA3ODgyMjc1MTEyODhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImJsdWUiLAogICJmaWxsT3BhY2l0eSI6IDAuNiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjQ1Mjc3ZTM0MzExNDNmZWFjYmU2NmIyNjA5NTRkODYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYTAzNDQ3MjA5MDIzNDg2NmI1ZDFhNmViZTAxY2M4MmYgPSAkKCc8ZGl2IGlkPSJodG1sX2EwMzQ0NzIwOTAyMzQ4NjZiNWQxYTZlYmUwMWNjODJmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TcGE8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Y0NTI3N2UzNDMxMTQzZmVhY2JlNjZiMjYwOTU0ZDg2LnNldENvbnRlbnQoaHRtbF9hMDM0NDcyMDkwMjM0ODY2YjVkMWE2ZWJlMDFjYzgyZik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jMjVjNzBmMDJhYTA0YjU0ODE1ZjQwYzg3NmI3MjI0NC5iaW5kUG9wdXAocG9wdXBfZjQ1Mjc3ZTM0MzExNDNmZWFjYmU2NmIyNjA5NTRkODYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZDI5NjcyZmQ0MDkzNDllMThlODA5NjBiMjdmZTczYWUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTQwOTg2MDcyNjA0MSwtNzQuMDA5Njg1NzE3OTI4M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81YmUzMzAxMjRlYjc0ZWEzYWNhNzAxNzIwMDQ1ZDlhNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iNjE0ZGU1ZTVjMjE0MTY1YTRiMzBmZjgzYmUxNjEyYSA9ICQoJzxkaXYgaWQ9Imh0bWxfYjYxNGRlNWU1YzIxNDE2NWE0YjMwZmY4M2JlMTYxMmEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkd5bTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNWJlMzMwMTI0ZWI3NGVhM2FjYTcwMTcyMDA0NWQ5YTcuc2V0Q29udGVudChodG1sX2I2MTRkZTVlNWMyMTQxNjVhNGIzMGZmODNiZTE2MTJhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2QyOTY3MmZkNDA5MzQ5ZTE4ZTgwOTYwYjI3ZmU3M2FlLmJpbmRQb3B1cChwb3B1cF81YmUzMzAxMjRlYjc0ZWEzYWNhNzAxNzIwMDQ1ZDlhNyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yOTg4ZDQwZjFhNWY0YTQxYTE4OGVjMDU4OTNkNjBmMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNTI4NDIzMTMyODI3LC03NC4wMDg3ODA5Mzk1MjAxOF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82OGJmZTIxNjQ5YTc0NmI4YTk4ZDJhMjIzYmMxMDEzNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81NThmY2Q0OGZkMWQ0YzI1YTNlNTUwYjBiZDAzNjE5OSA9ICQoJzxkaXYgaWQ9Imh0bWxfNTU4ZmNkNDhmZDFkNGMyNWEzZTU1MGIwYmQwMzYxOTkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkFudGlxdWUgU2hvcDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNjhiZmUyMTY0OWE3NDZiOGE5OGQyYTIyM2JjMTAxMzcuc2V0Q29udGVudChodG1sXzU1OGZjZDQ4ZmQxZDRjMjVhM2U1NTBiMGJkMDM2MTk5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzI5ODhkNDBmMWE1ZjRhNDFhMTg4ZWMwNTg5M2Q2MGYyLmJpbmRQb3B1cChwb3B1cF82OGJmZTIxNjQ5YTc0NmI4YTk4ZDJhMjIzYmMxMDEzNyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hMjY4NmE1OGNiYTk0MTIzYmU2NjJhZTNmZGNlYTViYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNTUzNzEwMTE2NDE2LC03NC4wMDc3MjQ1MjkyNTU2NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9hNDBkNjliNzdkYTM0ZDdjYjM5NmM2M2IwYTE4YWE0NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8yYjZiOGZiNWU4ZjQ0N2QwOGJlZWIwNGVhYTNiNTFmOSA9ICQoJzxkaXYgaWQ9Imh0bWxfMmI2YjhmYjVlOGY0NDdkMDhiZWViMDRlYWEzYjUxZjkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZhbGFmZWwgUmVzdGF1cmFudDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYTQwZDY5Yjc3ZGEzNGQ3Y2IzOTZjNjNiMGExOGFhNDQuc2V0Q29udGVudChodG1sXzJiNmI4ZmI1ZThmNDQ3ZDA4YmVlYjA0ZWFhM2I1MWY5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2EyNjg2YTU4Y2JhOTQxMjNiZTY2MmFlM2ZkY2VhNWJiLmJpbmRQb3B1cChwb3B1cF9hNDBkNjliNzdkYTM0ZDdjYjM5NmM2M2IwYTE4YWE0NCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mMzVlYWQ4OTg5MTE0ZTk4YWE0NTY5ZWVjOWI1ODhhOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNTE3NjkzOTY2MzE1LC03NC4wMTAyMjc0Nzc3ODI4NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82NzlmZjY5NWQwOTg0M2IwOGQ0NjQ1ZGIzOGJhNTU1NSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lYWI5ODM5ZmFhYTg0ZmEyYmNmZjE5OTU3MGY3ZTk1YSA9ICQoJzxkaXYgaWQ9Imh0bWxfZWFiOTgzOWZhYWE4NGZhMmJjZmYxOTk1NzBmN2U5NWEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNhZsOpPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82NzlmZjY5NWQwOTg0M2IwOGQ0NjQ1ZGIzOGJhNTU1NS5zZXRDb250ZW50KGh0bWxfZWFiOTgzOWZhYWE4NGZhMmJjZmYxOTk1NzBmN2U5NWEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjM1ZWFkODk4OTExNGU5OGFhNDU2OWVlYzliNTg4YTguYmluZFBvcHVwKHBvcHVwXzY3OWZmNjk1ZDA5ODQzYjA4ZDQ2NDVkYjM4YmE1NTU1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzdiMTIyNTVjZmQxMDRiMzliNjQyM2Y5NDZlODY2NGY0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE1NTc5MTU1NDIwNjA2LC03NC4wMTEzNjgyMzk1ODExOV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81NDJkNmVkNTc4MDM0ZDljYTY2N2QxZjgwNjEyNGVmMSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85NmI2MjJiZDEyYTk0N2UxOTk4NmQxNzQwNDM5MDk0ZCA9ICQoJzxkaXYgaWQ9Imh0bWxfOTZiNjIyYmQxMmE5NDdlMTk5ODZkMTc0MDQzOTA5NGQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkdyb2NlcnkgU3RvcmU8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzU0MmQ2ZWQ1NzgwMzRkOWNhNjY3ZDFmODA2MTI0ZWYxLnNldENvbnRlbnQoaHRtbF85NmI2MjJiZDEyYTk0N2UxOTk4NmQxNzQwNDM5MDk0ZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83YjEyMjU1Y2ZkMTA0YjM5YjY0MjNmOTQ2ZTg2NjRmNC5iaW5kUG9wdXAocG9wdXBfNTQyZDZlZDU3ODAzNGQ5Y2E2NjdkMWY4MDYxMjRlZjEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZmQ4MGJjYjQwZDI4NDg4Y2I1NWEyYjFlM2VjOWNlNDMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTU2Mjg2MjAwMjU2LC03NC4wMDc5OTIyNTgzODUzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2NkNWQ1NDg5ZDBlZDQzMTRhZmU1NzdiZGY4YTlhZjRkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzRiNjhjMGVkMjVkMTRhN2Y5OGJhNjI1Nzc0MjQwYjEzID0gJCgnPGRpdiBpZD0iaHRtbF80YjY4YzBlZDI1ZDE0YTdmOThiYTYyNTc3NDI0MGIxMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+R3ltIC8gRml0bmVzcyBDZW50ZXI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2NkNWQ1NDg5ZDBlZDQzMTRhZmU1NzdiZGY4YTlhZjRkLnNldENvbnRlbnQoaHRtbF80YjY4YzBlZDI1ZDE0YTdmOThiYTYyNTc3NDI0MGIxMyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mZDgwYmNiNDBkMjg0ODhjYjU1YTJiMWUzZWM5Y2U0My5iaW5kUG9wdXAocG9wdXBfY2Q1ZDU0ODlkMGVkNDMxNGFmZTU3N2JkZjhhOWFmNGQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZGNiYWE0YzY4ZWZiNDllZTlhNzEwZTZlMTUxNTYyZDAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTU0ODY1ODUyNDk3MzUsLTc0LjAwOTEzMzEzNTEwODM2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2QwZjhjNTMzZDY5ZDQxOTc5MTMwYzhjOTYyYzQ4YmE2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2E4YzYxYTNmMjM1MDRjOTRhODVjMmIxZTA4NWZkNzU3ID0gJCgnPGRpdiBpZD0iaHRtbF9hOGM2MWEzZjIzNTA0Yzk0YTg1YzJiMWUwODVmZDc1NyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QW1lcmljYW4gUmVzdGF1cmFudDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZDBmOGM1MzNkNjlkNDE5NzkxMzBjOGM5NjJjNDhiYTYuc2V0Q29udGVudChodG1sX2E4YzYxYTNmMjM1MDRjOTRhODVjMmIxZTA4NWZkNzU3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2RjYmFhNGM2OGVmYjQ5ZWU5YTcxMGU2ZTE1MTU2MmQwLmJpbmRQb3B1cChwb3B1cF9kMGY4YzUzM2Q2OWQ0MTk3OTEzMGM4Yzk2MmM0OGJhNik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81ODdmOTAwODE2YjM0MjY3YTY3MjM3OTc3ZTViNDIxNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNDM1LC03NC4wMDk4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2Y2NDBiZDE1YTQ1ZjRmODBhMTE5MTY0MmE5YjhlMGYxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc5MmE3YWNiMjY2MDQ3OWU5OWVhZjQ0NGYwZWE1OTQxID0gJCgnPGRpdiBpZD0iaHRtbF83OTJhN2FjYjI2NjA0NzllOTllYWY0NDRmMGVhNTk0MSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3RyaXAgQ2x1YjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZjY0MGJkMTVhNDVmNGY4MGExMTkxNjQyYTliOGUwZjEuc2V0Q29udGVudChodG1sXzc5MmE3YWNiMjY2MDQ3OWU5OWVhZjQ0NGYwZWE1OTQxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU4N2Y5MDA4MTZiMzQyNjdhNjcyMzc5NzdlNWI0MjE0LmJpbmRQb3B1cChwb3B1cF9mNjQwYmQxNWE0NWY0ZjgwYTExOTE2NDJhOWI4ZTBmMSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xZDM2ZDVhZDBjYzc0ZjAyOTE5MDg1MmIwZmM0YTNkZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNjM3OTg0MzE3MDcxLC03NC4wMDk2MjkzMzQ1MzQyOF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zNjRjYWE3ZWY1NjI0ZjZhYTU2ZDliZTczYTEzNTA0NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF84YmRmYzk0NzM0MjU0OGNmYTFhYmNkMzBiNTIxNjc1ZSA9ICQoJzxkaXYgaWQ9Imh0bWxfOGJkZmM5NDczNDI1NDhjZmExYWJjZDMwYjUyMTY3NWUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5ldyBBbWVyaWNhbiBSZXN0YXVyYW50PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zNjRjYWE3ZWY1NjI0ZjZhYTU2ZDliZTczYTEzNTA0NC5zZXRDb250ZW50KGh0bWxfOGJkZmM5NDczNDI1NDhjZmExYWJjZDMwYjUyMTY3NWUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMWQzNmQ1YWQwY2M3NGYwMjkxOTA4NTJiMGZjNGEzZGYuYmluZFBvcHVwKHBvcHVwXzM2NGNhYTdlZjU2MjRmNmFhNTZkOWJlNzNhMTM1MDQ0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzM4NjZkN2QxOTQwNTQ3NjM4ZmQzMmVkZTk1ZTE5NWI0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE0OTA5NTAxNTM5ODIsLTc0LjAwOTQ4MDI3MDExOTAzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzJiNWVmMmY3Mjg3NjQ1NGViOTQ2NDliOGZkZjcxOTg2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzVlZjE1NDliMzMxYjRmZmVhNjM3ZGNhMjlmNWZmN2UzID0gJCgnPGRpdiBpZD0iaHRtbF81ZWYxNTQ5YjMzMWI0ZmZlYTYzN2RjYTI5ZjVmZjdlMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Qm9va3N0b3JlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yYjVlZjJmNzI4NzY0NTRlYjk0NjQ5YjhmZGY3MTk4Ni5zZXRDb250ZW50KGh0bWxfNWVmMTU0OWIzMzFiNGZmZWE2MzdkY2EyOWY1ZmY3ZTMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMzg2NmQ3ZDE5NDA1NDc2MzhmZDMyZWRlOTVlMTk1YjQuYmluZFBvcHVwKHBvcHVwXzJiNWVmMmY3Mjg3NjQ1NGViOTQ2NDliOGZkZjcxOTg2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY3YTUzMmExZWIxZDRmMTc4M2EzMGNkMTVmZjk4NDU3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE2NzUyODE2ODc2NjM1LC03NC4wMDg1ODM3NjI5NTIyMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85ZjE3ZmU4YjE0NTA0ODQ4OGFkNDU2ZTM5Y2Q3ZjgzMSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mYTFhN2FlZDZmZjE0OGZjOWNhYzkwNTdmMjAwOGY5NSA9ICQoJzxkaXYgaWQ9Imh0bWxfZmExYTdhZWQ2ZmYxNDhmYzljYWM5MDU3ZjIwMDhmOTUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkFzaWFuIFJlc3RhdXJhbnQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzlmMTdmZThiMTQ1MDQ4NDg4YWQ0NTZlMzljZDdmODMxLnNldENvbnRlbnQoaHRtbF9mYTFhN2FlZDZmZjE0OGZjOWNhYzkwNTdmMjAwOGY5NSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82N2E1MzJhMWViMWQ0ZjE3ODNhMzBjZDE1ZmY5ODQ1Ny5iaW5kUG9wdXAocG9wdXBfOWYxN2ZlOGIxNDUwNDg0ODhhZDQ1NmUzOWNkN2Y4MzEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfY2JkNTBlYmM0OTU5NDAzNGEwMmIzMzliY2Y3YmY5YWQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTUzMDA2NDgwNTY5OSwtNzQuMDA5MzQ3MDMyNDcyMzldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImJsdWUiLAogICJmaWxsT3BhY2l0eSI6IDAuNiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNzMzN2I3ZDk5MzgwNDA5MjhmYmQxYTQ4NzU5MDA2ZjkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfY2NjZjQ3OGVkNTQ3NDE0Njg4MDc4YzNmOTg4MzVkYzEgPSAkKCc8ZGl2IGlkPSJodG1sX2NjY2Y0NzhlZDU0NzQxNDY4ODA3OGMzZjk4ODM1ZGMxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ib3RlbCBCYXI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzczMzdiN2Q5OTM4MDQwOTI4ZmJkMWE0ODc1OTAwNmY5LnNldENvbnRlbnQoaHRtbF9jY2NmNDc4ZWQ1NDc0MTQ2ODgwNzhjM2Y5ODgzNWRjMSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jYmQ1MGViYzQ5NTk0MDM0YTAyYjMzOWJjZjdiZjlhZC5iaW5kUG9wdXAocG9wdXBfNzMzN2I3ZDk5MzgwNDA5MjhmYmQxYTQ4NzU5MDA2ZjkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZTI1ZmU0MWI5MDkyNDRlMmI5ZDJjMzc5NWU3ZTQxYjEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTY3NDA4NDE2MzM2OSwtNzQuMDA4NjY2NDQzODg5M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wMjg1NTdmMjZkN2E0NzgyYjg5YTljZTQ3MGU1MDk4MSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF84MzQ4MThlYmQyMTk0MDgwOGI5ZGE3OGQ5ZjUzOGZlMiA9ICQoJzxkaXYgaWQ9Imh0bWxfODM0ODE4ZWJkMjE5NDA4MDhiOWRhNzhkOWY1MzhmZTIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNvY2t0YWlsIEJhcjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDI4NTU3ZjI2ZDdhNDc4MmI4OWE5Y2U0NzBlNTA5ODEuc2V0Q29udGVudChodG1sXzgzNDgxOGViZDIxOTQwODA4YjlkYTc4ZDlmNTM4ZmUyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2UyNWZlNDFiOTA5MjQ0ZTJiOWQyYzM3OTVlN2U0MWIxLmJpbmRQb3B1cChwb3B1cF8wMjg1NTdmMjZkN2E0NzgyYjg5YTljZTQ3MGU1MDk4MSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83MmU2YTA4N2JiNjg0ZDgzOTIzN2Y0YTQ0ZWZkYjdmNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNjc5MzA0ODU1ODA4LC03NC4wMDgyMTk5ODg3ODQ1N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84ZWM2ODU5M2JjNDQ0OTNhYWEwNWVkZWZmY2NhOTc0ZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iOGQ3ODJkYmMwOTM0MTQ1OWVkYmFiZjgxMzEwMjMxZSA9ICQoJzxkaXYgaWQ9Imh0bWxfYjhkNzgyZGJjMDkzNDE0NTllZGJhYmY4MTMxMDIzMWUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkFtZXJpY2FuIFJlc3RhdXJhbnQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzhlYzY4NTkzYmM0NDQ5M2FhYTA1ZWRlZmZjY2E5NzRmLnNldENvbnRlbnQoaHRtbF9iOGQ3ODJkYmMwOTM0MTQ1OWVkYmFiZjgxMzEwMjMxZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83MmU2YTA4N2JiNjg0ZDgzOTIzN2Y0YTQ0ZWZkYjdmNS5iaW5kUG9wdXAocG9wdXBfOGVjNjg1OTNiYzQ0NDkzYWFhMDVlZGVmZmNjYTk3NGYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYWJjMzE1M2E0Yzg0NGM2MzhjYTNjOTNiZTRiOGQ1NjUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTQxNywtNzQuMDA4NjZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImJsdWUiLAogICJmaWxsT3BhY2l0eSI6IDAuNiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOGY3NjNiYzJmOTkyNGZlZGEzOTcwM2QzN2M3N2NkMzYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYzM3MWQzNjlhY2UwNDBlYWJiNmEwNzI1YmFlNTk2NzggPSAkKCc8ZGl2IGlkPSJodG1sX2MzNzFkMzY5YWNlMDQwZWFiYjZhMDcyNWJhZTU5Njc4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UYWNvIFBsYWNlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84Zjc2M2JjMmY5OTI0ZmVkYTM5NzAzZDM3Yzc3Y2QzNi5zZXRDb250ZW50KGh0bWxfYzM3MWQzNjlhY2UwNDBlYWJiNmEwNzI1YmFlNTk2NzgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYWJjMzE1M2E0Yzg0NGM2MzhjYTNjOTNiZTRiOGQ1NjUuYmluZFBvcHVwKHBvcHVwXzhmNzYzYmMyZjk5MjRmZWRhMzk3MDNkMzdjNzdjZDM2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzI3MGI4NDdjMmViNzRjN2NhMjMzMjg4MjY5Mzk3N2VjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE0NzU0MTUxNDYxMjM2LC03NC4wMDc1ODA2MDAyMDM5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RlNWFkMmEyMTcyNDRmZjA5NmFlY2NkMzA5MjMxNDJlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2U4YzFhZWM2MDRlOTRlYzJiMjcxM2RkZTViYWQzOWRjID0gJCgnPGRpdiBpZD0iaHRtbF9lOGMxYWVjNjA0ZTk0ZWMyYjI3MTNkZGU1YmFkMzlkYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RnJlbmNoIFJlc3RhdXJhbnQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2RlNWFkMmEyMTcyNDRmZjA5NmFlY2NkMzA5MjMxNDJlLnNldENvbnRlbnQoaHRtbF9lOGMxYWVjNjA0ZTk0ZWMyYjI3MTNkZGU1YmFkMzlkYyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yNzBiODQ3YzJlYjc0YzdjYTIzMzI4ODI2OTM5NzdlYy5iaW5kUG9wdXAocG9wdXBfZGU1YWQyYTIxNzI0NGZmMDk2YWVjY2QzMDkyMzE0MmUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjkzZDM3ZmYyZjc2NDNmMzhlMTRjNDU4NDk3MWFkZDUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTcwMTAxMTQwOTkwNiwtNzQuMDA4MDQyNDQ1NjIyMjVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImJsdWUiLAogICJmaWxsT3BhY2l0eSI6IDAuNiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZmZlOGY1MjJlY2U3NDljZDkxY2Q2ZmZkZjQ2ZDQyYWMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZmVmNDJiOTNmYzg1NDVlMTljZGIzOTNjOGYyOWM2OTQgPSAkKCc8ZGl2IGlkPSJodG1sX2ZlZjQyYjkzZmM4NTQ1ZTE5Y2RiMzkzYzhmMjljNjk0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5GcmVuY2ggUmVzdGF1cmFudDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZmZlOGY1MjJlY2U3NDljZDkxY2Q2ZmZkZjQ2ZDQyYWMuc2V0Q29udGVudChodG1sX2ZlZjQyYjkzZmM4NTQ1ZTE5Y2RiMzkzYzhmMjljNjk0KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2I5M2QzN2ZmMmY3NjQzZjM4ZTE0YzQ1ODQ5NzFhZGQ1LmJpbmRQb3B1cChwb3B1cF9mZmU4ZjUyMmVjZTc0OWNkOTFjZDZmZmRmNDZkNDJhYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yYzJiMWZkM2ZiMjM0ZTlkYWIzMDYxYmU3NmIyNzFhMSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNTk0MTI1NTY2OTMxLC03NC4wMDg3MjA1MzU2NDQ5NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mODYwNjZjMDdjNGU0YzMxYjdjOWQ4MGY1N2ZkMTNlYiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iOTg1MWM3ZGFjYmM0YjdkYWIwZmIxOTRiNTgzMDU5MCA9ICQoJzxkaXYgaWQ9Imh0bWxfYjk4NTFjN2RhY2JjNGI3ZGFiMGZiMTk0YjU4MzA1OTAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5haWwgU2Fsb248L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Y4NjA2NmMwN2M0ZTRjMzFiN2M5ZDgwZjU3ZmQxM2ViLnNldENvbnRlbnQoaHRtbF9iOTg1MWM3ZGFjYmM0YjdkYWIwZmIxOTRiNTgzMDU5MCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yYzJiMWZkM2ZiMjM0ZTlkYWIzMDYxYmU3NmIyNzFhMS5iaW5kUG9wdXAocG9wdXBfZjg2MDY2YzA3YzRlNGMzMWI3YzlkODBmNTdmZDEzZWIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjZlNmFkNmI0ZGQ0NGZlNmE1YjlkYTgyN2UyMDRmNzUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTY2ODQzOTIyNzgyMiwtNzQuMDA4MzQzNDI4NjkyMzhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogImJsdWUiLAogICJmaWxsT3BhY2l0eSI6IDAuNiwKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZDc0ODFiYzc2NDMyNDUxNTk1MDI5MWQ5ZjgxMzRjZjMpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzM1YzE1ZmU5YzJkNDJjMjljZmVmNDI2ZTRiNDIwM2UgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMjdkODZiMzY0NWM4NDc4ZmE2M2IxOTI3ZGRiMTVhOWQgPSAkKCc8ZGl2IGlkPSJodG1sXzI3ZDg2YjM2NDVjODQ3OGZhNjNiMTkyN2RkYjE1YTlkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TdXNoaSBSZXN0YXVyYW50PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zMzVjMTVmZTljMmQ0MmMyOWNmZWY0MjZlNGI0MjAzZS5zZXRDb250ZW50KGh0bWxfMjdkODZiMzY0NWM4NDc4ZmE2M2IxOTI3ZGRiMTVhOWQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjZlNmFkNmI0ZGQ0NGZlNmE1YjlkYTgyN2UyMDRmNzUuYmluZFBvcHVwKHBvcHVwXzMzNWMxNWZlOWMyZDQyYzI5Y2ZlZjQyNmU0YjQyMDNlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzI0NDBmZGFmOTI2ODQxOGFhMWNiZjYyNDg0MjM3OTAxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE0MzQyMjkwMTU4MDg2LC03NC4wMDgwOTM1Njg0MDAwNF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81M2I5MzAxZDMyNDY0NTdiOGExM2YwYmYwN2Q5OTg1NiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zNjg5MGMxMzEzODE0OTcyOTJiOTU3MzE5ZGNiZjNiNiA9ICQoJzxkaXYgaWQ9Imh0bWxfMzY4OTBjMTMxMzgxNDk3MjkyYjk1NzMxOWRjYmYzYjYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPllvZ2EgU3R1ZGlvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81M2I5MzAxZDMyNDY0NTdiOGExM2YwYmYwN2Q5OTg1Ni5zZXRDb250ZW50KGh0bWxfMzY4OTBjMTMxMzgxNDk3MjkyYjk1NzMxOWRjYmYzYjYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjQ0MGZkYWY5MjY4NDE4YWExY2JmNjI0ODQyMzc5MDEuYmluZFBvcHVwKHBvcHVwXzUzYjkzMDFkMzI0NjQ1N2I4YTEzZjBiZjA3ZDk5ODU2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzRkYzA2YWE3NmYwNjQ3NzQ5MDI2NGUyNzg3OTBjYWYxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE1NTgsLTc0LjAwOTg1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzNmM2M1MjJkMmEyYzQ2OWJiZmZlODBiOTBhZDFiN2IxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2QzMGJmNjcxNDVmOTRhODE5MzdlZGYyYzk4ZmRhMTdhID0gJCgnPGRpdiBpZD0iaHRtbF9kMzBiZjY3MTQ1Zjk0YTgxOTM3ZWRmMmM5OGZkYTE3YSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmFnZWwgU2hvcDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfM2YzYzUyMmQyYTJjNDY5YmJmZmU4MGI5MGFkMWI3YjEuc2V0Q29udGVudChodG1sX2QzMGJmNjcxNDVmOTRhODE5MzdlZGYyYzk4ZmRhMTdhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzRkYzA2YWE3NmYwNjQ3NzQ5MDI2NGUyNzg3OTBjYWYxLmJpbmRQb3B1cChwb3B1cF8zZjNjNTIyZDJhMmM0NjliYmZmZTgwYjkwYWQxYjdiMSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yZGJmZGI3YzFlMTA0ZTM2OTlkZDEwMWM4ZWVlZjM5OSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxNDc2LC03NC4wMDkyOF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiYmx1ZSIsCiAgImZpbGxPcGFjaXR5IjogMC42LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9kNzQ4MWJjNzY0MzI0NTE1OTUwMjkxZDlmODEzNGNmMyk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jZjRjZDFlMWZmYjk0MmRhYmUyYzlhZjllMjA5ODY4NiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82ODA2Yzc2ZTJjODQ0NTRlOTg4NTMwODJjMzRhNjlmYSA9ICQoJzxkaXYgaWQ9Imh0bWxfNjgwNmM3NmUyYzg0NDU0ZTk4ODUzMDgyYzM0YTY5ZmEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJhYnkgU3RvcmU8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2NmNGNkMWUxZmZiOTQyZGFiZTJjOWFmOWUyMDk4Njg2LnNldENvbnRlbnQoaHRtbF82ODA2Yzc2ZTJjODQ0NTRlOTg4NTMwODJjMzRhNjlmYSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yZGJmZGI3YzFlMTA0ZTM2OTlkZDEwMWM4ZWVlZjM5OS5iaW5kUG9wdXAocG9wdXBfY2Y0Y2QxZTFmZmI5NDJkYWJlMmM5YWY5ZTIwOTg2ODYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYmNhMTY2OTU4ZmU3NDliMDg4ZjU4M2Q2ODM3MTA1NTAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTU4ODUxMjYwODYwMTUsLTc0LjAwODcxMzYxOTAyNDE4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2JmZTI5MGFjODIyYzRhOGM4MzI1ZDQwNDU4MjQwMDhhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzg0YjNjYzcxN2RmNjQ4NGY4ODUxZGMzNmRkNzAxMzg2ID0gJCgnPGRpdiBpZD0iaHRtbF84NGIzY2M3MTdkZjY0ODRmODg1MWRjMzZkZDcwMTM4NiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q29ja3RhaWwgQmFyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iZmUyOTBhYzgyMmM0YThjODMyNWQ0MDQ1ODI0MDA4YS5zZXRDb250ZW50KGh0bWxfODRiM2NjNzE3ZGY2NDg0Zjg4NTFkYzM2ZGQ3MDEzODYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYmNhMTY2OTU4ZmU3NDliMDg4ZjU4M2Q2ODM3MTA1NTAuYmluZFBvcHVwKHBvcHVwX2JmZTI5MGFjODIyYzRhOGM4MzI1ZDQwNDU4MjQwMDhhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I3N2E1NjdkMDMxZjQzOTBiNmU0Mzc1ZWYyMjUxYmEzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE3MTcyNzU4MDExNjgsLTc0LjAwOTMyODY5MTI1MTE3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJibHVlIiwKICAiZmlsbE9wYWNpdHkiOiAwLjYsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2Q3NDgxYmM3NjQzMjQ1MTU5NTAyOTFkOWY4MTM0Y2YzKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzgzNDJiMGRjZTZiYjRiNDNiZmM5ODg2NWE0ZDhhMGZjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzY5MjdiZWYyZGFhODRjNGQ4NDU1YTU2YjA1NTNlODBlID0gJCgnPGRpdiBpZD0iaHRtbF82OTI3YmVmMmRhYTg0YzRkODQ1NWE1NmIwNTUzZTgwZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UGFyazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfODM0MmIwZGNlNmJiNGI0M2JmYzk4ODY1YTRkOGEwZmMuc2V0Q29udGVudChodG1sXzY5MjdiZWYyZGFhODRjNGQ4NDU1YTU2YjA1NTNlODBlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2I3N2E1NjdkMDMxZjQzOTBiNmU0Mzc1ZWYyMjUxYmEzLmJpbmRQb3B1cChwb3B1cF84MzQyYjBkY2U2YmI0YjQzYmZjOTg4NjVhNGQ4YTBmYyk7CgogICAgICAgICAgICAKICAgICAgICAKPC9zY3JpcHQ+\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
],
"text/plain": [
"<folium.folium.Map at 0x7f60fceac828>"
]
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# display map\n",
"venues_map"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"<a id=\"item6\"></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"### Thank you for completing this lab!\n",
"\n",
"This notebook was created by [Alex Aklson](https://www.linkedin.com/in/aklson/). I hope you found this lab interesting and educational. Feel free to contact me if you have any questions!"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"This notebook is part of a course on **Coursera** called *Applied Data Science Capstone*. If you accessed this notebook outside the course, you can take this course online by clicking [here](http://cocl.us/DP0701EN_Coursera_Week2_LAB1)."
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"deletable": true,
"new_sheet": false,
"run_control": {
"read_only": false
}
},
"source": [
"<hr>\n",
"Copyright &copy; 2018 [Cognitive Class](https://cognitiveclass.ai/?utm_source=bducopyrightlink&utm_medium=dswb&utm_campaign=bdu). This notebook and its source code are released under the terms of the [MIT License](https://bigdatauniversity.com/mit-license/)."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python",
"language": "python",
"name": "conda-env-python-py"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.7"
},
"widgets": {
"state": {},
"version": "1.1.2"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment