Skip to content

Instantly share code, notes, and snippets.

@maptastik
Last active November 26, 2018 14:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maptastik/594254a6125e09c2621f66382107d55e to your computer and use it in GitHub Desktop.
Save maptastik/594254a6125e09c2621f66382107d55e to your computer and use it in GitHub Desktop.
A notebook to demonstrate how to use pandas and geopy to geocode a CSV of summer camp locations
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Geocoding 2018 Summer Camp Locations\n",
"\n",
"This notebook will walk through the process for geocoding summer camp locations using pandas and geopy/Google V3 Geocoding API."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Load data"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Load data from Excel list of location"
]
},
{
"cell_type": "code",
"execution_count": 96,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style>\n",
" .dataframe thead tr:only-child th {\n",
" text-align: right;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: left;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>MAP_NUM</th>\n",
" <th>LOCATION</th>\n",
" <th>LOCATION_TYPE</th>\n",
" <th>PHYSICAL ADDRESS</th>\n",
" <th>ADDRESS_1</th>\n",
" <th>ADDRESS_2</th>\n",
" <th>ZIP</th>\n",
" <th>PHONE</th>\n",
" <th>NOTES</th>\n",
" <th>Unnamed: 9</th>\n",
" <th>Unnamed: 10</th>\n",
" <th>Unnamed: 11</th>\n",
" <th>Unnamed: 12</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1</td>\n",
" <td>Abbotts Creek</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>9950 Durant Road 27614</td>\n",
" <td>9950 Durant Road</td>\n",
" <td>NaN</td>\n",
" <td>27614</td>\n",
" <td>919-996-2270</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",
" <th>1</th>\n",
" <td>2</td>\n",
" <td>Barwell Road Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>5857 Barwell Park Drive 27610</td>\n",
" <td>5857 Barwell Park Drive</td>\n",
" <td>NaN</td>\n",
" <td>27610</td>\n",
" <td>919-996-5994</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",
" <th>2</th>\n",
" <td>3</td>\n",
" <td>Biltmore Hills Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>2615 Fitzgerald Drive 27610</td>\n",
" <td>2615 Fitzgerald Drive</td>\n",
" <td>NaN</td>\n",
" <td>27610</td>\n",
" <td>919-831-6895</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",
" <th>3</th>\n",
" <td>4</td>\n",
" <td>Brentwood Neighborhood Park and Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>3315 Vinson Court 27604</td>\n",
" <td>3315 Vinson Court</td>\n",
" <td>NaN</td>\n",
" <td>27604</td>\n",
" <td>919-996-4895</td>\n",
" <td>Art For Fun</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>5</td>\n",
" <td>Brier Creek Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>10810 Globe Road 27617</td>\n",
" <td>10810 Globe Road</td>\n",
" <td>NaN</td>\n",
" <td>27617</td>\n",
" <td>919-420-2340</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" MAP_NUM LOCATION LOCATION_TYPE \\\n",
"0 1 Abbotts Creek City of Raleigh Facility \n",
"1 2 Barwell Road Community Center City of Raleigh Facility \n",
"2 3 Biltmore Hills Community Center City of Raleigh Facility \n",
"3 4 Brentwood Neighborhood Park and Center City of Raleigh Facility \n",
"4 5 Brier Creek Community Center City of Raleigh Facility \n",
"\n",
" PHYSICAL ADDRESS ADDRESS_1 ADDRESS_2 ZIP \\\n",
"0 9950 Durant Road 27614 9950 Durant Road NaN 27614 \n",
"1 5857 Barwell Park Drive 27610 5857 Barwell Park Drive NaN 27610 \n",
"2 2615 Fitzgerald Drive 27610 2615 Fitzgerald Drive NaN 27610 \n",
"3 3315 Vinson Court 27604 3315 Vinson Court NaN 27604 \n",
"4 10810 Globe Road 27617 10810 Globe Road NaN 27617 \n",
"\n",
" PHONE NOTES Unnamed: 9 Unnamed: 10 Unnamed: 11 Unnamed: 12 \n",
"0 919-996-2270 NaN NaN NaN NaN NaN \n",
"1 919-996-5994 NaN NaN NaN NaN NaN \n",
"2 919-831-6895 NaN NaN NaN NaN NaN \n",
"3 919-996-4895 Art For Fun NaN NaN NaN NaN \n",
"4 919-420-2340 NaN NaN NaN NaN NaN "
]
},
"execution_count": 96,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = pd.read_excel('./data/2018_Camp_Locations_RC.xlsx', sheet_name='Sheet1')\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Clean up data for geocoding. In this case, we can just get rid of columns that have `NaN` values. We don't need them for geocoding."
]
},
{
"cell_type": "code",
"execution_count": 97,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style>\n",
" .dataframe thead tr:only-child th {\n",
" text-align: right;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: left;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>MAP_NUM</th>\n",
" <th>LOCATION</th>\n",
" <th>LOCATION_TYPE</th>\n",
" <th>PHYSICAL ADDRESS</th>\n",
" <th>ADDRESS_1</th>\n",
" <th>ZIP</th>\n",
" <th>PHONE</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1</td>\n",
" <td>Abbotts Creek</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>9950 Durant Road 27614</td>\n",
" <td>9950 Durant Road</td>\n",
" <td>27614</td>\n",
" <td>919-996-2270</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2</td>\n",
" <td>Barwell Road Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>5857 Barwell Park Drive 27610</td>\n",
" <td>5857 Barwell Park Drive</td>\n",
" <td>27610</td>\n",
" <td>919-996-5994</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3</td>\n",
" <td>Biltmore Hills Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>2615 Fitzgerald Drive 27610</td>\n",
" <td>2615 Fitzgerald Drive</td>\n",
" <td>27610</td>\n",
" <td>919-831-6895</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>4</td>\n",
" <td>Brentwood Neighborhood Park and Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>3315 Vinson Court 27604</td>\n",
" <td>3315 Vinson Court</td>\n",
" <td>27604</td>\n",
" <td>919-996-4895</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>5</td>\n",
" <td>Brier Creek Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>10810 Globe Road 27617</td>\n",
" <td>10810 Globe Road</td>\n",
" <td>27617</td>\n",
" <td>919-420-2340</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" MAP_NUM LOCATION LOCATION_TYPE \\\n",
"0 1 Abbotts Creek City of Raleigh Facility \n",
"1 2 Barwell Road Community Center City of Raleigh Facility \n",
"2 3 Biltmore Hills Community Center City of Raleigh Facility \n",
"3 4 Brentwood Neighborhood Park and Center City of Raleigh Facility \n",
"4 5 Brier Creek Community Center City of Raleigh Facility \n",
"\n",
" PHYSICAL ADDRESS ADDRESS_1 ZIP PHONE \n",
"0 9950 Durant Road 27614 9950 Durant Road 27614 919-996-2270 \n",
"1 5857 Barwell Park Drive 27610 5857 Barwell Park Drive 27610 919-996-5994 \n",
"2 2615 Fitzgerald Drive 27610 2615 Fitzgerald Drive 27610 919-831-6895 \n",
"3 3315 Vinson Court 27604 3315 Vinson Court 27604 919-996-4895 \n",
"4 10810 Globe Road 27617 10810 Globe Road 27617 919-420-2340 "
]
},
"execution_count": 97,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = df.dropna(axis=1)\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Geocode dataframe"
]
},
{
"cell_type": "code",
"execution_count": 100,
"metadata": {},
"outputs": [],
"source": [
"from geopy.geocoders import GoogleV3\n",
"geocoder = GoogleV3(api_key='AIzaSyCC5IavvH5NV-K7GKqtST00eA75_2KvtCo', timeout=10)"
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [],
"source": [
"def get_coordinates(address):\n",
" location = geocoder.geocode(address)\n",
" return [location.latitude, location.longitude]"
]
},
{
"cell_type": "code",
"execution_count": 98,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style>\n",
" .dataframe thead tr:only-child th {\n",
" text-align: right;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: left;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>MAP_NUM</th>\n",
" <th>LOCATION</th>\n",
" <th>LOCATION_TYPE</th>\n",
" <th>PHYSICAL ADDRESS</th>\n",
" <th>ADDRESS_1</th>\n",
" <th>ZIP</th>\n",
" <th>PHONE</th>\n",
" <th>LAT</th>\n",
" <th>LNG</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1</td>\n",
" <td>Abbotts Creek</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>9950 Durant Road 27614</td>\n",
" <td>9950 Durant Road</td>\n",
" <td>27614</td>\n",
" <td>919-996-2270</td>\n",
" <td>35.903344</td>\n",
" <td>-78.579608</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2</td>\n",
" <td>Barwell Road Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>5857 Barwell Park Drive 27610</td>\n",
" <td>5857 Barwell Park Drive</td>\n",
" <td>27610</td>\n",
" <td>919-996-5994</td>\n",
" <td>35.731058</td>\n",
" <td>-78.551656</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3</td>\n",
" <td>Biltmore Hills Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>2615 Fitzgerald Drive 27610</td>\n",
" <td>2615 Fitzgerald Drive</td>\n",
" <td>27610</td>\n",
" <td>919-831-6895</td>\n",
" <td>35.746200</td>\n",
" <td>-78.628158</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>4</td>\n",
" <td>Brentwood Neighborhood Park and Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>3315 Vinson Court 27604</td>\n",
" <td>3315 Vinson Court</td>\n",
" <td>27604</td>\n",
" <td>919-996-4895</td>\n",
" <td>35.828641</td>\n",
" <td>-78.600941</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>5</td>\n",
" <td>Brier Creek Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>10810 Globe Road 27617</td>\n",
" <td>10810 Globe Road</td>\n",
" <td>27617</td>\n",
" <td>919-420-2340</td>\n",
" <td>35.900626</td>\n",
" <td>-78.804267</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>6</td>\n",
" <td>Carolina Pines Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>2305 Lake Wheeler Road 27603</td>\n",
" <td>2305 Lake Wheeler Road</td>\n",
" <td>27603</td>\n",
" <td>919-831-6435</td>\n",
" <td>35.749209</td>\n",
" <td>-78.668611</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>7</td>\n",
" <td>Chavis Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>505 Martin Luther King Jr. Boulevard 27601</td>\n",
" <td>505 Martin Luther King Jr. Boulevard</td>\n",
" <td>27601</td>\n",
" <td>919-831-6989</td>\n",
" <td>35.769329</td>\n",
" <td>-78.629177</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>7</td>\n",
" <td>John Chavis Park</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>505 Martin Luther King Jr. Boulevard 27601</td>\n",
" <td>505 Martin Luther King Jr. Boulevard</td>\n",
" <td>27601</td>\n",
" <td>919-831-6989</td>\n",
" <td>35.769329</td>\n",
" <td>-78.629177</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>8N</td>\n",
" <td>Durant Nature Preserve</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>8305 Camp Durant Road 27615</td>\n",
" <td>8305 Camp Durant Road</td>\n",
" <td>27615</td>\n",
" <td>919-996-2147</td>\n",
" <td>35.894781</td>\n",
" <td>-78.579020</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>8N</td>\n",
" <td>Durant Nature Preserve</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>8305 Camp Durant Road 27615</td>\n",
" <td>8305 Camp Durant Road</td>\n",
" <td>27615</td>\n",
" <td>919-996-6855</td>\n",
" <td>35.894781</td>\n",
" <td>-78.579020</td>\n",
" </tr>\n",
" <tr>\n",
" <th>10</th>\n",
" <td>8S</td>\n",
" <td>Durant Nature Preserve</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>3237 Spottswood Street 27615</td>\n",
" <td>3237 Spottswood Street</td>\n",
" <td>27615</td>\n",
" <td>919-996-6855</td>\n",
" <td>35.890998</td>\n",
" <td>-78.577307</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11</th>\n",
" <td>9</td>\n",
" <td>Eastgate Park</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>4200 Quail Hollow Drive 27609</td>\n",
" <td>4200 Quail Hollow Drive</td>\n",
" <td>27609</td>\n",
" <td>919-996-2139</td>\n",
" <td>35.839481</td>\n",
" <td>-78.623998</td>\n",
" </tr>\n",
" <tr>\n",
" <th>12</th>\n",
" <td>10</td>\n",
" <td>Glen Eden Park c/o Jaycee Park</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>1500 Glen Eden Drive 27612</td>\n",
" <td>1500 Glen Eden Drive</td>\n",
" <td>27612</td>\n",
" <td>919-996-6833</td>\n",
" <td>35.827326</td>\n",
" <td>-78.684525</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13</th>\n",
" <td>11</td>\n",
" <td>Green Road Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>4201 Green Road 27604</td>\n",
" <td>4201 Green Road</td>\n",
" <td>27604</td>\n",
" <td>919-872-4140</td>\n",
" <td>35.841127</td>\n",
" <td>-78.591128</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14</th>\n",
" <td>12</td>\n",
" <td>Greystone Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>7713-55 Leadmine Road 27615</td>\n",
" <td>7713-55 Leadmine Road</td>\n",
" <td>27615</td>\n",
" <td>919-996-4848</td>\n",
" <td>35.886144</td>\n",
" <td>-78.660126</td>\n",
" </tr>\n",
" <tr>\n",
" <th>15</th>\n",
" <td>13</td>\n",
" <td>Halifax Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>1023 Halifx Street 27604</td>\n",
" <td>1023 Halifx Street</td>\n",
" <td>27604</td>\n",
" <td>919-996-6378</td>\n",
" <td>35.793097</td>\n",
" <td>-78.638867</td>\n",
" </tr>\n",
" <tr>\n",
" <th>16</th>\n",
" <td>14</td>\n",
" <td>Hill Street Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>2307 Hill Street 27604</td>\n",
" <td>2307 Hill Street</td>\n",
" <td>27604</td>\n",
" <td>919-996-5300</td>\n",
" <td>35.812405</td>\n",
" <td>-78.588315</td>\n",
" </tr>\n",
" <tr>\n",
" <th>17</th>\n",
" <td>15</td>\n",
" <td>Jaycee Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>2405 Wade Avenue 27607</td>\n",
" <td>2405 Wade Avenue</td>\n",
" <td>27607</td>\n",
" <td>919-996-6833</td>\n",
" <td>35.799836</td>\n",
" <td>-78.663665</td>\n",
" </tr>\n",
" <tr>\n",
" <th>18</th>\n",
" <td>16</td>\n",
" <td>Kiwanis Park c/o Optimist Park</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>2525 Noble Road 27608</td>\n",
" <td>2525 Noble Road</td>\n",
" <td>27608</td>\n",
" <td>919-870-2880</td>\n",
" <td>35.815066</td>\n",
" <td>-78.631315</td>\n",
" </tr>\n",
" <tr>\n",
" <th>19</th>\n",
" <td>17</td>\n",
" <td>Lake Lynn Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>7921 Ray Road 27613</td>\n",
" <td>7921 Ray Road</td>\n",
" <td>27613</td>\n",
" <td>919-870-2911</td>\n",
" <td>35.887496</td>\n",
" <td>-78.699167</td>\n",
" </tr>\n",
" <tr>\n",
" <th>20</th>\n",
" <td>18</td>\n",
" <td>Laurel Hills Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>3808 Edwards Mill Road 27612</td>\n",
" <td>3808 Edwards Mill Road</td>\n",
" <td>27612</td>\n",
" <td>919-420-2383</td>\n",
" <td>35.829849</td>\n",
" <td>-78.697331</td>\n",
" </tr>\n",
" <tr>\n",
" <th>21</th>\n",
" <td>19</td>\n",
" <td>Lions Park</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>516 Dennis Avenue 27604</td>\n",
" <td>516 Dennis Avenue</td>\n",
" <td>27604</td>\n",
" <td>919-996-4726</td>\n",
" <td>35.797284</td>\n",
" <td>-78.614022</td>\n",
" </tr>\n",
" <tr>\n",
" <th>22</th>\n",
" <td>20</td>\n",
" <td>Marsh Creek Park</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>3050 New Hope Road 27604</td>\n",
" <td>3050 New Hope Road</td>\n",
" <td>27604</td>\n",
" <td>919-996-4920</td>\n",
" <td>35.822528</td>\n",
" <td>-78.569007</td>\n",
" </tr>\n",
" <tr>\n",
" <th>23</th>\n",
" <td>21</td>\n",
" <td>Method Road Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>514 Method Road 27607</td>\n",
" <td>514 Method Road</td>\n",
" <td>27607</td>\n",
" <td>919-996-6066</td>\n",
" <td>35.792777</td>\n",
" <td>-78.694459</td>\n",
" </tr>\n",
" <tr>\n",
" <th>24</th>\n",
" <td>22</td>\n",
" <td>Millbrook Exchange Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>1905 Spring Forest Road 27615</td>\n",
" <td>1905 Spring Forest Road</td>\n",
" <td>27615</td>\n",
" <td>919-996-4156</td>\n",
" <td>35.869213</td>\n",
" <td>-78.607374</td>\n",
" </tr>\n",
" <tr>\n",
" <th>25</th>\n",
" <td>23</td>\n",
" <td>Mordecai Historic Park</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>1 Mimosa Street 27604</td>\n",
" <td>1 Mimosa Street</td>\n",
" <td>27604</td>\n",
" <td>919-996-4364</td>\n",
" <td>35.792693</td>\n",
" <td>-78.633293</td>\n",
" </tr>\n",
" <tr>\n",
" <th>26</th>\n",
" <td>24</td>\n",
" <td>Optimist Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>5900 Whittier Drive 27609</td>\n",
" <td>5900 Whittier Drive</td>\n",
" <td>27609</td>\n",
" <td>919-870-2880</td>\n",
" <td>35.862368</td>\n",
" <td>-78.644087</td>\n",
" </tr>\n",
" <tr>\n",
" <th>27</th>\n",
" <td>25</td>\n",
" <td>Peach Road</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>911 Ileagnes Road 27603</td>\n",
" <td>911 Ileagnes Road</td>\n",
" <td>27603</td>\n",
" <td>919-807-8545</td>\n",
" <td>35.742595</td>\n",
" <td>-78.654882</td>\n",
" </tr>\n",
" <tr>\n",
" <th>28</th>\n",
" <td>26</td>\n",
" <td>Powell Drive Park</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>740 Powell Drive 27606</td>\n",
" <td>740 Powell Drive</td>\n",
" <td>27606</td>\n",
" <td>919-996-6066</td>\n",
" <td>35.778995</td>\n",
" <td>-78.714358</td>\n",
" </tr>\n",
" <tr>\n",
" <th>29</th>\n",
" <td>27</td>\n",
" <td>Powell Drive Park</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>740 Powell Drive 27606</td>\n",
" <td>740 Powell Drive</td>\n",
" <td>27606</td>\n",
" <td>919-996-2117</td>\n",
" <td>35.778995</td>\n",
" <td>-78.714358</td>\n",
" </tr>\n",
" <tr>\n",
" <th>30</th>\n",
" <td>28</td>\n",
" <td>Pullen Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>408 Ashe Avenue 27607</td>\n",
" <td>408 Ashe Avenue</td>\n",
" <td>27607</td>\n",
" <td>919-831-6052</td>\n",
" <td>35.780651</td>\n",
" <td>-78.660985</td>\n",
" </tr>\n",
" <tr>\n",
" <th>31</th>\n",
" <td>29</td>\n",
" <td>Raleigh City Museum</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>220 Fayetteville Street 27601</td>\n",
" <td>220 Fayetteville Street</td>\n",
" <td>27601</td>\n",
" <td>919-996-2220</td>\n",
" <td>35.777665</td>\n",
" <td>-78.639752</td>\n",
" </tr>\n",
" <tr>\n",
" <th>32</th>\n",
" <td>30</td>\n",
" <td>Ralph Campbell Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>756 Lunar Drive 27610</td>\n",
" <td>756 Lunar Drive</td>\n",
" <td>27610</td>\n",
" <td>919-250-2757</td>\n",
" <td>35.764880</td>\n",
" <td>-78.608950</td>\n",
" </tr>\n",
" <tr>\n",
" <th>33</th>\n",
" <td>31</td>\n",
" <td>Roberts Park Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>1300 E. Martin Street 27610</td>\n",
" <td>1300 E. Martin Street</td>\n",
" <td>27610</td>\n",
" <td>919-831-6830</td>\n",
" <td>35.775519</td>\n",
" <td>-78.618301</td>\n",
" </tr>\n",
" <tr>\n",
" <th>34</th>\n",
" <td>32</td>\n",
" <td>St. Monica Teen Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>15 N. Tarboro Street 27601</td>\n",
" <td>15 N. Tarboro Street</td>\n",
" <td>27601</td>\n",
" <td>919-996-4770</td>\n",
" <td>35.780801</td>\n",
" <td>-78.622524</td>\n",
" </tr>\n",
" <tr>\n",
" <th>35</th>\n",
" <td>33</td>\n",
" <td>Sanderford Road Park</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>2623 Sanderford Road 27610</td>\n",
" <td>2623 Sanderford Road</td>\n",
" <td>27610</td>\n",
" <td>919-831-1898</td>\n",
" <td>35.742872</td>\n",
" <td>-78.613637</td>\n",
" </tr>\n",
" <tr>\n",
" <th>36</th>\n",
" <td>34</td>\n",
" <td>Sgt. Courtney T. Johnson Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>1801 Proctor Road 27610</td>\n",
" <td>1801 Proctor Road</td>\n",
" <td>27610</td>\n",
" <td>919-831-6719</td>\n",
" <td>35.753030</td>\n",
" <td>-78.608991</td>\n",
" </tr>\n",
" <tr>\n",
" <th>37</th>\n",
" <td>34</td>\n",
" <td>Southgate</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>1801 Proctor Road 27610</td>\n",
" <td>1801 Proctor Road</td>\n",
" <td>27610</td>\n",
" <td>919-831-6719</td>\n",
" <td>35.753030</td>\n",
" <td>-78.608991</td>\n",
" </tr>\n",
" <tr>\n",
" <th>38</th>\n",
" <td>36</td>\n",
" <td>Tarboro Road Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>121 N. Tarboro Street 27610</td>\n",
" <td>121 N. Tarboro Street</td>\n",
" <td>27610</td>\n",
" <td>919-831-6505</td>\n",
" <td>35.781433</td>\n",
" <td>-78.622732</td>\n",
" </tr>\n",
" <tr>\n",
" <th>39</th>\n",
" <td>37</td>\n",
" <td>Walnut Creek Wetland Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>950 Peterson Street 27610</td>\n",
" <td>950 Peterson Street</td>\n",
" <td>27610</td>\n",
" <td>919-996-4895</td>\n",
" <td>35.760369</td>\n",
" <td>-78.624900</td>\n",
" </tr>\n",
" <tr>\n",
" <th>40</th>\n",
" <td>37</td>\n",
" <td>Walnut Creek Wetland Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>950 Peterson Street 27610</td>\n",
" <td>950 Peterson Street</td>\n",
" <td>27610</td>\n",
" <td>919-996-6856</td>\n",
" <td>35.760369</td>\n",
" <td>-78.624900</td>\n",
" </tr>\n",
" <tr>\n",
" <th>41</th>\n",
" <td>37</td>\n",
" <td>Walnut Creek Wetland Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>950 Peterson Street 27610</td>\n",
" <td>950 Peterson Street</td>\n",
" <td>27610</td>\n",
" <td>919-996-6855</td>\n",
" <td>35.760369</td>\n",
" <td>-78.624900</td>\n",
" </tr>\n",
" <tr>\n",
" <th>42</th>\n",
" <td>38</td>\n",
" <td>Worthdale Community Center</td>\n",
" <td>City of Raleigh Facility</td>\n",
" <td>1001 Cooper Road 27610</td>\n",
" <td>1001 Cooper Road</td>\n",
" <td>27610</td>\n",
" <td>919-996-2730</td>\n",
" <td>35.763377</td>\n",
" <td>-78.587070</td>\n",
" </tr>\n",
" <tr>\n",
" <th>43</th>\n",
" <td>39</td>\n",
" <td>Hilburn Academy</td>\n",
" <td>Non-City of Raleigh Facility</td>\n",
" <td>7100 Hilburn Drive 27613</td>\n",
" <td>7100 Hilburn Drive</td>\n",
" <td>27613</td>\n",
" <td>919-996-6165</td>\n",
" <td>35.874950</td>\n",
" <td>-78.713914</td>\n",
" </tr>\n",
" <tr>\n",
" <th>44</th>\n",
" <td>40</td>\n",
" <td>Pleasant Grove Elementary School</td>\n",
" <td>Non-City of Raleigh Facility</td>\n",
" <td>3605 Pleasant Grove Church Road 27560</td>\n",
" <td>3605 Pleasant Grove Church Road</td>\n",
" <td>27560</td>\n",
" <td>919-996-6165</td>\n",
" <td>35.888117</td>\n",
" <td>-78.818829</td>\n",
" </tr>\n",
" <tr>\n",
" <th>45</th>\n",
" <td>41</td>\n",
" <td>Ravenscroft School</td>\n",
" <td>Non-City of Raleigh Facility</td>\n",
" <td>7409 Falls of Neuse Road 27615</td>\n",
" <td>7409 Falls of Neuse Road</td>\n",
" <td>27615</td>\n",
" <td>919-996-6165</td>\n",
" <td>35.885346</td>\n",
" <td>-78.631096</td>\n",
" </tr>\n",
" <tr>\n",
" <th>46</th>\n",
" <td>42</td>\n",
" <td>Underwood Elementary</td>\n",
" <td>Non-City of Raleigh Facility</td>\n",
" <td>1614 Glenwood Avenue 27608</td>\n",
" <td>1614 Glenwood Avenue</td>\n",
" <td>27608</td>\n",
" <td>919-996-6165</td>\n",
" <td>35.802266</td>\n",
" <td>-78.645150</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" MAP_NUM LOCATION \\\n",
"0 1 Abbotts Creek \n",
"1 2 Barwell Road Community Center \n",
"2 3 Biltmore Hills Community Center \n",
"3 4 Brentwood Neighborhood Park and Center \n",
"4 5 Brier Creek Community Center \n",
"5 6 Carolina Pines Community Center \n",
"6 7 Chavis Community Center \n",
"7 7 John Chavis Park \n",
"8 8N Durant Nature Preserve \n",
"9 8N Durant Nature Preserve \n",
"10 8S Durant Nature Preserve \n",
"11 9 Eastgate Park \n",
"12 10 Glen Eden Park c/o Jaycee Park \n",
"13 11 Green Road Community Center \n",
"14 12 Greystone Community Center \n",
"15 13 Halifax Community Center \n",
"16 14 Hill Street Center \n",
"17 15 Jaycee Community Center \n",
"18 16 Kiwanis Park c/o Optimist Park \n",
"19 17 Lake Lynn Community Center \n",
"20 18 Laurel Hills Community Center \n",
"21 19 Lions Park \n",
"22 20 Marsh Creek Park \n",
"23 21 Method Road Community Center \n",
"24 22 Millbrook Exchange Community Center \n",
"25 23 Mordecai Historic Park \n",
"26 24 Optimist Community Center \n",
"27 25 Peach Road \n",
"28 26 Powell Drive Park \n",
"29 27 Powell Drive Park \n",
"30 28 Pullen Community Center \n",
"31 29 Raleigh City Museum \n",
"32 30 Ralph Campbell Community Center \n",
"33 31 Roberts Park Community Center \n",
"34 32 St. Monica Teen Center \n",
"35 33 Sanderford Road Park \n",
"36 34 Sgt. Courtney T. Johnson Center \n",
"37 34 Southgate \n",
"38 36 Tarboro Road Community Center \n",
"39 37 Walnut Creek Wetland Center \n",
"40 37 Walnut Creek Wetland Center \n",
"41 37 Walnut Creek Wetland Center \n",
"42 38 Worthdale Community Center \n",
"43 39 Hilburn Academy \n",
"44 40 Pleasant Grove Elementary School \n",
"45 41 Ravenscroft School \n",
"46 42 Underwood Elementary \n",
"\n",
" LOCATION_TYPE PHYSICAL ADDRESS \\\n",
"0 City of Raleigh Facility 9950 Durant Road 27614 \n",
"1 City of Raleigh Facility 5857 Barwell Park Drive 27610 \n",
"2 City of Raleigh Facility 2615 Fitzgerald Drive 27610 \n",
"3 City of Raleigh Facility 3315 Vinson Court 27604 \n",
"4 City of Raleigh Facility 10810 Globe Road 27617 \n",
"5 City of Raleigh Facility 2305 Lake Wheeler Road 27603 \n",
"6 City of Raleigh Facility 505 Martin Luther King Jr. Boulevard 27601 \n",
"7 City of Raleigh Facility 505 Martin Luther King Jr. Boulevard 27601 \n",
"8 City of Raleigh Facility 8305 Camp Durant Road 27615 \n",
"9 City of Raleigh Facility 8305 Camp Durant Road 27615 \n",
"10 City of Raleigh Facility 3237 Spottswood Street 27615 \n",
"11 City of Raleigh Facility 4200 Quail Hollow Drive 27609 \n",
"12 City of Raleigh Facility 1500 Glen Eden Drive 27612 \n",
"13 City of Raleigh Facility 4201 Green Road 27604 \n",
"14 City of Raleigh Facility 7713-55 Leadmine Road 27615 \n",
"15 City of Raleigh Facility 1023 Halifx Street 27604 \n",
"16 City of Raleigh Facility 2307 Hill Street 27604 \n",
"17 City of Raleigh Facility 2405 Wade Avenue 27607 \n",
"18 City of Raleigh Facility 2525 Noble Road 27608 \n",
"19 City of Raleigh Facility 7921 Ray Road 27613 \n",
"20 City of Raleigh Facility 3808 Edwards Mill Road 27612 \n",
"21 City of Raleigh Facility 516 Dennis Avenue 27604 \n",
"22 City of Raleigh Facility 3050 New Hope Road 27604 \n",
"23 City of Raleigh Facility 514 Method Road 27607 \n",
"24 City of Raleigh Facility 1905 Spring Forest Road 27615 \n",
"25 City of Raleigh Facility 1 Mimosa Street 27604 \n",
"26 City of Raleigh Facility 5900 Whittier Drive 27609 \n",
"27 City of Raleigh Facility 911 Ileagnes Road 27603 \n",
"28 City of Raleigh Facility 740 Powell Drive 27606 \n",
"29 City of Raleigh Facility 740 Powell Drive 27606 \n",
"30 City of Raleigh Facility 408 Ashe Avenue 27607 \n",
"31 City of Raleigh Facility 220 Fayetteville Street 27601 \n",
"32 City of Raleigh Facility 756 Lunar Drive 27610 \n",
"33 City of Raleigh Facility 1300 E. Martin Street 27610 \n",
"34 City of Raleigh Facility 15 N. Tarboro Street 27601 \n",
"35 City of Raleigh Facility 2623 Sanderford Road 27610 \n",
"36 City of Raleigh Facility 1801 Proctor Road 27610 \n",
"37 City of Raleigh Facility 1801 Proctor Road 27610 \n",
"38 City of Raleigh Facility 121 N. Tarboro Street 27610 \n",
"39 City of Raleigh Facility 950 Peterson Street 27610 \n",
"40 City of Raleigh Facility 950 Peterson Street 27610 \n",
"41 City of Raleigh Facility 950 Peterson Street 27610 \n",
"42 City of Raleigh Facility 1001 Cooper Road 27610 \n",
"43 Non-City of Raleigh Facility 7100 Hilburn Drive 27613 \n",
"44 Non-City of Raleigh Facility 3605 Pleasant Grove Church Road 27560 \n",
"45 Non-City of Raleigh Facility 7409 Falls of Neuse Road 27615 \n",
"46 Non-City of Raleigh Facility 1614 Glenwood Avenue 27608 \n",
"\n",
" ADDRESS_1 ZIP PHONE LAT \\\n",
"0 9950 Durant Road 27614 919-996-2270 35.903344 \n",
"1 5857 Barwell Park Drive 27610 919-996-5994 35.731058 \n",
"2 2615 Fitzgerald Drive 27610 919-831-6895 35.746200 \n",
"3 3315 Vinson Court 27604 919-996-4895 35.828641 \n",
"4 10810 Globe Road 27617 919-420-2340 35.900626 \n",
"5 2305 Lake Wheeler Road 27603 919-831-6435 35.749209 \n",
"6 505 Martin Luther King Jr. Boulevard 27601 919-831-6989 35.769329 \n",
"7 505 Martin Luther King Jr. Boulevard 27601 919-831-6989 35.769329 \n",
"8 8305 Camp Durant Road 27615 919-996-2147 35.894781 \n",
"9 8305 Camp Durant Road 27615 919-996-6855 35.894781 \n",
"10 3237 Spottswood Street 27615 919-996-6855 35.890998 \n",
"11 4200 Quail Hollow Drive 27609 919-996-2139 35.839481 \n",
"12 1500 Glen Eden Drive 27612 919-996-6833 35.827326 \n",
"13 4201 Green Road 27604 919-872-4140 35.841127 \n",
"14 7713-55 Leadmine Road 27615 919-996-4848 35.886144 \n",
"15 1023 Halifx Street 27604 919-996-6378 35.793097 \n",
"16 2307 Hill Street 27604 919-996-5300 35.812405 \n",
"17 2405 Wade Avenue 27607 919-996-6833 35.799836 \n",
"18 2525 Noble Road 27608 919-870-2880 35.815066 \n",
"19 7921 Ray Road 27613 919-870-2911 35.887496 \n",
"20 3808 Edwards Mill Road 27612 919-420-2383 35.829849 \n",
"21 516 Dennis Avenue 27604 919-996-4726 35.797284 \n",
"22 3050 New Hope Road 27604 919-996-4920 35.822528 \n",
"23 514 Method Road 27607 919-996-6066 35.792777 \n",
"24 1905 Spring Forest Road 27615 919-996-4156 35.869213 \n",
"25 1 Mimosa Street 27604 919-996-4364 35.792693 \n",
"26 5900 Whittier Drive 27609 919-870-2880 35.862368 \n",
"27 911 Ileagnes Road 27603 919-807-8545 35.742595 \n",
"28 740 Powell Drive 27606 919-996-6066 35.778995 \n",
"29 740 Powell Drive 27606 919-996-2117 35.778995 \n",
"30 408 Ashe Avenue 27607 919-831-6052 35.780651 \n",
"31 220 Fayetteville Street 27601 919-996-2220 35.777665 \n",
"32 756 Lunar Drive 27610 919-250-2757 35.764880 \n",
"33 1300 E. Martin Street 27610 919-831-6830 35.775519 \n",
"34 15 N. Tarboro Street 27601 919-996-4770 35.780801 \n",
"35 2623 Sanderford Road 27610 919-831-1898 35.742872 \n",
"36 1801 Proctor Road 27610 919-831-6719 35.753030 \n",
"37 1801 Proctor Road 27610 919-831-6719 35.753030 \n",
"38 121 N. Tarboro Street 27610 919-831-6505 35.781433 \n",
"39 950 Peterson Street 27610 919-996-4895 35.760369 \n",
"40 950 Peterson Street 27610 919-996-6856 35.760369 \n",
"41 950 Peterson Street 27610 919-996-6855 35.760369 \n",
"42 1001 Cooper Road 27610 919-996-2730 35.763377 \n",
"43 7100 Hilburn Drive 27613 919-996-6165 35.874950 \n",
"44 3605 Pleasant Grove Church Road 27560 919-996-6165 35.888117 \n",
"45 7409 Falls of Neuse Road 27615 919-996-6165 35.885346 \n",
"46 1614 Glenwood Avenue 27608 919-996-6165 35.802266 \n",
"\n",
" LNG \n",
"0 -78.579608 \n",
"1 -78.551656 \n",
"2 -78.628158 \n",
"3 -78.600941 \n",
"4 -78.804267 \n",
"5 -78.668611 \n",
"6 -78.629177 \n",
"7 -78.629177 \n",
"8 -78.579020 \n",
"9 -78.579020 \n",
"10 -78.577307 \n",
"11 -78.623998 \n",
"12 -78.684525 \n",
"13 -78.591128 \n",
"14 -78.660126 \n",
"15 -78.638867 \n",
"16 -78.588315 \n",
"17 -78.663665 \n",
"18 -78.631315 \n",
"19 -78.699167 \n",
"20 -78.697331 \n",
"21 -78.614022 \n",
"22 -78.569007 \n",
"23 -78.694459 \n",
"24 -78.607374 \n",
"25 -78.633293 \n",
"26 -78.644087 \n",
"27 -78.654882 \n",
"28 -78.714358 \n",
"29 -78.714358 \n",
"30 -78.660985 \n",
"31 -78.639752 \n",
"32 -78.608950 \n",
"33 -78.618301 \n",
"34 -78.622524 \n",
"35 -78.613637 \n",
"36 -78.608991 \n",
"37 -78.608991 \n",
"38 -78.622732 \n",
"39 -78.624900 \n",
"40 -78.624900 \n",
"41 -78.624900 \n",
"42 -78.587070 \n",
"43 -78.713914 \n",
"44 -78.818829 \n",
"45 -78.631096 \n",
"46 -78.645150 "
]
},
"execution_count": 98,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df[\"LAT\"], df[\"LNG\"] = zip(*df.apply(lambda row: get_coordinates(row[\"PHYSICAL ADDRESS\"]), axis = 1))\n",
"df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Inspect results"
]
},
{
"cell_type": "code",
"execution_count": 76,
"metadata": {},
"outputs": [],
"source": [
"import folium"
]
},
{
"cell_type": "code",
"execution_count": 99,
"metadata": {},
"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+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIgLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC5taW4uY3NzIiAvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLXRoZW1lLm1pbi5jc3MiIC8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIgLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuY3NzIiAvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL3Jhd2dpdC5jb20vcHl0aG9uLXZpc3VhbGl6YXRpb24vZm9saXVtL21hc3Rlci9mb2xpdW0vdGVtcGxhdGVzL2xlYWZsZXQuYXdlc29tZS5yb3RhdGUuY3NzIiAvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogMTAwLjAlOwogICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgICAgICAgICAgdG9wOiAwLjAlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICA8L3N0eWxlPgogICAgICAgIAo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgICAgICAgICA8ZGl2IGNsYXNzPSJmb2xpdW0tbWFwIiBpZD0ibWFwXzgwMjkxNzI3OTFkMjQxZTVhNjA5NTUyNjk1OWFiY2JiIiA+PC9kaXY+CiAgICAgICAgCjwvYm9keT4KPHNjcmlwdD4gICAgCiAgICAKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGJvdW5kcyA9IG51bGw7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgdmFyIG1hcF84MDI5MTcyNzkxZDI0MWU1YTYwOTU1MjY5NTlhYmNiYiA9IEwubWFwKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ21hcF84MDI5MTcyNzkxZDI0MWU1YTYwOTU1MjY5NTlhYmNiYicsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7Y2VudGVyOiBbMzUuNzc5NTksLTc4LjYzODE3OV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB6b29tOiAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heEJvdW5kczogYm91bmRzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF5ZXJzOiBbXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmxkQ29weUp1bXA6IGZhbHNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JzOiBMLkNSUy5FUFNHMzg1NwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHRpbGVfbGF5ZXJfYWQ0YjY0YjE1ZDcyNDljZWIzMTU4YTUxMjVkZDdkYzkgPSBMLnRpbGVMYXllcigKICAgICAgICAgICAgICAgICdodHRwczovL3tzfS50aWxlLm9wZW5zdHJlZXRtYXAub3JnL3t6fS97eH0ve3l9LnBuZycsCiAgICAgICAgICAgICAgICB7CiAgImF0dHJpYnV0aW9uIjogbnVsbCwKICAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsCiAgIm1heFpvb20iOiAxOCwKICAibWluWm9vbSI6IDEsCiAgIm5vV3JhcCI6IGZhbHNlLAogICJzdWJkb21haW5zIjogImFiYyIKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzA3NTdiN2RmYzdhNjQ5YThhNTkzODRkN2FmYjQ5ZmVjID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzUuOTAzMzQ0LC03OC41Nzk2MDc5XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZmNlOWZjMDVjZDM1NGRhMDg1YWFiMGE2ZDVmYWFjMTYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYTgzNDYyN2Y2MzM5NDNmZWI0ZWQ5NzY4ZjlmYmY0ZjYgPSAkKCc8ZGl2IGlkPSJodG1sX2E4MzQ2MjdmNjMzOTQzZmViNGVkOTc2OGY5ZmJmNGY2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij4xIC0gQWJib3R0cyBDcmVlazxicj45OTUwIER1cmFudCBSb2FkIDI3NjE0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mY2U5ZmMwNWNkMzU0ZGEwODVhYWIwYTZkNWZhYWMxNi5zZXRDb250ZW50KGh0bWxfYTgzNDYyN2Y2MzM5NDNmZWI0ZWQ5NzY4ZjlmYmY0ZjYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl8wNzU3YjdkZmM3YTY0OWE4YTU5Mzg0ZDdhZmI0OWZlYy5iaW5kUG9wdXAocG9wdXBfZmNlOWZjMDVjZDM1NGRhMDg1YWFiMGE2ZDVmYWFjMTYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfNzlmOGE3Y2VmZTU2NGQyNjlmN2VmMjdiYzk5MTBkODkgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNS43MzEwNTc2LC03OC41NTE2NTYxXSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfN2NhY2EwZDc4NWE4NDM0Y2I1ZGQyOGU3OGVhZWY2Y2MgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMWU1MzRlZTIzZTRlNDUzZWFiMmE0NTRiMjJkZGI0ZjggPSAkKCc8ZGl2IGlkPSJodG1sXzFlNTM0ZWUyM2U0ZTQ1M2VhYjJhNDU0YjIyZGRiNGY4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij4yIC0gQmFyd2VsbCBSb2FkIENvbW11bml0eSBDZW50ZXI8YnI+NTg1NyBCYXJ3ZWxsIFBhcmsgRHJpdmUgMjc2MTA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzdjYWNhMGQ3ODVhODQzNGNiNWRkMjhlNzhlYWVmNmNjLnNldENvbnRlbnQoaHRtbF8xZTUzNGVlMjNlNGU0NTNlYWIyYTQ1NGIyMmRkYjRmOCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyXzc5ZjhhN2NlZmU1NjRkMjY5ZjdlZjI3YmM5OTEwZDg5LmJpbmRQb3B1cChwb3B1cF83Y2FjYTBkNzg1YTg0MzRjYjVkZDI4ZTc4ZWFlZjZjYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl8xNDRkYTQwZWE4NzU0ZTQ4YTYyNTllNjYzNGU4MGU1ZCA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1Ljc0NjE5OTUsLTc4LjYyODE1OF0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzgwMjkxNzI3OTFkMjQxZTVhNjA5NTUyNjk1OWFiY2JiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2M4NTYzODgzZDgwNjQ2ZWJhNDRmNzlhNzA2MGQzMThhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc5ODQyMDc5NGI4MjQ3OWQ5ZjE3YjNiZWU2MjkwYmJhID0gJCgnPGRpdiBpZD0iaHRtbF83OTg0MjA3OTRiODI0NzlkOWYxN2IzYmVlNjI5MGJiYSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+MyAtIEJpbHRtb3JlIEhpbGxzIENvbW11bml0eSBDZW50ZXI8YnI+MjYxNSBGaXR6Z2VyYWxkIERyaXZlIDI3NjEwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jODU2Mzg4M2Q4MDY0NmViYTQ0Zjc5YTcwNjBkMzE4YS5zZXRDb250ZW50KGh0bWxfNzk4NDIwNzk0YjgyNDc5ZDlmMTdiM2JlZTYyOTBiYmEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl8xNDRkYTQwZWE4NzU0ZTQ4YTYyNTllNjYzNGU4MGU1ZC5iaW5kUG9wdXAocG9wdXBfYzg1NjM4ODNkODA2NDZlYmE0NGY3OWE3MDYwZDMxOGEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfZDVjYjFhNzhkZTExNGU3NDlmYzNiZjEwYmZhNTQyODkgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNS44Mjg2NDEyLC03OC42MDA5NDExXSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNzRiZTgzN2FhYmYyNDlmZDhhZTk4YzMwNDc0ZGYxMzMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYzU1MmYzOTIyNDk5NDFhY2JhYWUxMGUxNDZjMzI0NGEgPSAkKCc8ZGl2IGlkPSJodG1sX2M1NTJmMzkyMjQ5OTQxYWNiYWFlMTBlMTQ2YzMyNDRhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij40IC0gQnJlbnR3b29kIE5laWdoYm9yaG9vZCBQYXJrIGFuZCBDZW50ZXI8YnI+MzMxNSBWaW5zb24gQ291cnQgMjc2MDQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzc0YmU4MzdhYWJmMjQ5ZmQ4YWU5OGMzMDQ3NGRmMTMzLnNldENvbnRlbnQoaHRtbF9jNTUyZjM5MjI0OTk0MWFjYmFhZTEwZTE0NmMzMjQ0YSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyX2Q1Y2IxYTc4ZGUxMTRlNzQ5ZmMzYmYxMGJmYTU0Mjg5LmJpbmRQb3B1cChwb3B1cF83NGJlODM3YWFiZjI0OWZkOGFlOThjMzA0NzRkZjEzMyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl81MjA2ZDhkNzc4YWQ0ZGI4ODc2MjZlMTBiZTdjMDNhZSA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1LjkwMDYyNjIsLTc4LjgwNDI2NjhdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84MDI5MTcyNzkxZDI0MWU1YTYwOTU1MjY5NTlhYmNiYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wZTg2ODZhODRmYmE0NmVkYjcyODg0MTQyNjk4YjVlNiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82YjNhMmNkMTc3Yzc0YTA1OTUwNGYwZTE2ZjI1ZThiNyA9ICQoJzxkaXYgaWQ9Imh0bWxfNmIzYTJjZDE3N2M3NGEwNTk1MDRmMGUxNmYyNWU4YjciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPjUgLSBCcmllciBDcmVlayBDb21tdW5pdHkgQ2VudGVyPGJyPjEwODEwIEdsb2JlIFJvYWQgMjc2MTc8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzBlODY4NmE4NGZiYTQ2ZWRiNzI4ODQxNDI2OThiNWU2LnNldENvbnRlbnQoaHRtbF82YjNhMmNkMTc3Yzc0YTA1OTUwNGYwZTE2ZjI1ZThiNyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyXzUyMDZkOGQ3NzhhZDRkYjg4NzYyNmUxMGJlN2MwM2FlLmJpbmRQb3B1cChwb3B1cF8wZTg2ODZhODRmYmE0NmVkYjcyODg0MTQyNjk4YjVlNik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl8zNDc5ZDcxMzkyNDg0NTU1YWQyZGI1Njg1OWRjNGViZSA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1Ljc0OTIwODYsLTc4LjY2ODYxMDldLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84MDI5MTcyNzkxZDI0MWU1YTYwOTU1MjY5NTlhYmNiYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lNTY5MTAxMjI0NGY0NTNmYmFiYTFjMTM0ODM3MDUyNSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lMmZiZmI0OWM2YWI0MzQ4ODMyMGM1YzY3MDgwZDVkOSA9ICQoJzxkaXYgaWQ9Imh0bWxfZTJmYmZiNDljNmFiNDM0ODgzMjBjNWM2NzA4MGQ1ZDkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPjYgLSBDYXJvbGluYSBQaW5lcyBDb21tdW5pdHkgQ2VudGVyPGJyPjIzMDUgTGFrZSBXaGVlbGVyIFJvYWQgMjc2MDM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2U1NjkxMDEyMjQ0ZjQ1M2ZiYWJhMWMxMzQ4MzcwNTI1LnNldENvbnRlbnQoaHRtbF9lMmZiZmI0OWM2YWI0MzQ4ODMyMGM1YzY3MDgwZDVkOSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyXzM0NzlkNzEzOTI0ODQ1NTVhZDJkYjU2ODU5ZGM0ZWJlLmJpbmRQb3B1cChwb3B1cF9lNTY5MTAxMjI0NGY0NTNmYmFiYTFjMTM0ODM3MDUyNSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl9lYzY4NWMxODcyZTk0OTQ1OTVjYmQ0MDNkMzQyYjQxNiA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1Ljc2OTMyODYsLTc4LjYyOTE3NzNdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84MDI5MTcyNzkxZDI0MWU1YTYwOTU1MjY5NTlhYmNiYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81YmQ3MWFlMmNlMmY0MjA3OWE3OTI0NGVjY2M5MDFmOCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9kZjQ2MjY1MDZjZDY0YTcwOTQ5ZTY1YmNjMDliNjgwYSA9ICQoJzxkaXYgaWQ9Imh0bWxfZGY0NjI2NTA2Y2Q2NGE3MDk0OWU2NWJjYzA5YjY4MGEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPjcgLSBDaGF2aXMgQ29tbXVuaXR5IENlbnRlcjxicj41MDUgTWFydGluIEx1dGhlciBLaW5nIEpyLiBCb3VsZXZhcmQgMjc2MDE8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzViZDcxYWUyY2UyZjQyMDc5YTc5MjQ0ZWNjYzkwMWY4LnNldENvbnRlbnQoaHRtbF9kZjQ2MjY1MDZjZDY0YTcwOTQ5ZTY1YmNjMDliNjgwYSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyX2VjNjg1YzE4NzJlOTQ5NDU5NWNiZDQwM2QzNDJiNDE2LmJpbmRQb3B1cChwb3B1cF81YmQ3MWFlMmNlMmY0MjA3OWE3OTI0NGVjY2M5MDFmOCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl8wY2Y2MGZmNzFhNGE0ODJhYTFjOTI4ZDVlNWZiYjhmNCA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1Ljc2OTMyODYsLTc4LjYyOTE3NzNdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84MDI5MTcyNzkxZDI0MWU1YTYwOTU1MjY5NTlhYmNiYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81YmRkY2U3MzI2MjU0OTQzODhjMDVmZjcwNDM0NzU4MyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80NGU3MjhjODE1MzE0ZDY4YTI1YmEwZmRjZDNiNGE3MyA9ICQoJzxkaXYgaWQ9Imh0bWxfNDRlNzI4YzgxNTMxNGQ2OGEyNWJhMGZkY2QzYjRhNzMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPjcgLSBKb2huIENoYXZpcyBQYXJrPGJyPjUwNSBNYXJ0aW4gTHV0aGVyIEtpbmcgSnIuIEJvdWxldmFyZCAyNzYwMTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNWJkZGNlNzMyNjI1NDk0Mzg4YzA1ZmY3MDQzNDc1ODMuc2V0Q29udGVudChodG1sXzQ0ZTcyOGM4MTUzMTRkNjhhMjViYTBmZGNkM2I0YTczKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfMGNmNjBmZjcxYTRhNDgyYWExYzkyOGQ1ZTVmYmI4ZjQuYmluZFBvcHVwKHBvcHVwXzViZGRjZTczMjYyNTQ5NDM4OGMwNWZmNzA0MzQ3NTgzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzZkODFlYTVmYjNjZDQzNzE5YmNiZDFjYTAyODI0ZTA5ID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzUuODk0NzgxMDAwMDAwMDEsLTc4LjU3OTAyMDFdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84MDI5MTcyNzkxZDI0MWU1YTYwOTU1MjY5NTlhYmNiYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84NjZkZjIxNWNmNjQ0YzcwYWZjYzllNTExYmQxZWQzZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83ZmQyMTU4YWNiNWQ0ZjY1OGVhYjg0NzcwZWEwNjdmYSA9ICQoJzxkaXYgaWQ9Imh0bWxfN2ZkMjE1OGFjYjVkNGY2NThlYWI4NDc3MGVhMDY3ZmEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPjhOIC0gRHVyYW50IE5hdHVyZSBQcmVzZXJ2ZTxicj44MzA1IENhbXAgRHVyYW50IFJvYWQgMjc2MTU8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzg2NmRmMjE1Y2Y2NDRjNzBhZmNjOWU1MTFiZDFlZDNlLnNldENvbnRlbnQoaHRtbF83ZmQyMTU4YWNiNWQ0ZjY1OGVhYjg0NzcwZWEwNjdmYSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyXzZkODFlYTVmYjNjZDQzNzE5YmNiZDFjYTAyODI0ZTA5LmJpbmRQb3B1cChwb3B1cF84NjZkZjIxNWNmNjQ0YzcwYWZjYzllNTExYmQxZWQzZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl84MTljZDNkZjdlNGI0OWMzYmU0MDI3YTU2NWNlZmM0OCA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1Ljg5NDc4MTAwMDAwMDAxLC03OC41NzkwMjAxXSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjdjYTllNmFiNzZhNGU4Mzg1ZWVmYjYxMDJkMGJiNDYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMzFjZDZjOWQzZjQxNDkxZDllYzFjNTVmNDMwZjU1MzUgPSAkKCc8ZGl2IGlkPSJodG1sXzMxY2Q2YzlkM2Y0MTQ5MWQ5ZWMxYzU1ZjQzMGY1NTM1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij44TiAtIER1cmFudCBOYXR1cmUgUHJlc2VydmU8YnI+ODMwNSBDYW1wIER1cmFudCBSb2FkIDI3NjE1PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82N2NhOWU2YWI3NmE0ZTgzODVlZWZiNjEwMmQwYmI0Ni5zZXRDb250ZW50KGh0bWxfMzFjZDZjOWQzZjQxNDkxZDllYzFjNTVmNDMwZjU1MzUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl84MTljZDNkZjdlNGI0OWMzYmU0MDI3YTU2NWNlZmM0OC5iaW5kUG9wdXAocG9wdXBfNjdjYTllNmFiNzZhNGU4Mzg1ZWVmYjYxMDJkMGJiNDYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfNDIxMGFmMmYyZTJkNGY0MWIxODlhMzk1ZDIyNzhjNTUgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNS44OTA5OTgsLTc4LjU3NzMwN10sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzgwMjkxNzI3OTFkMjQxZTVhNjA5NTUyNjk1OWFiY2JiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzdmN2M3MzZlNjg4ZjQxODg5Njc4NWIwYTdlYzIzNmFhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzU1YjcyOWFhZjIwNDQ1MDRhZWU3MzQ0ODE0OTFlNDViID0gJCgnPGRpdiBpZD0iaHRtbF81NWI3MjlhYWYyMDQ0NTA0YWVlNzM0NDgxNDkxZTQ1YiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+OFMgLSBEdXJhbnQgTmF0dXJlIFByZXNlcnZlPGJyPjMyMzcgU3BvdHRzd29vZCBTdHJlZXQgMjc2MTU8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzdmN2M3MzZlNjg4ZjQxODg5Njc4NWIwYTdlYzIzNmFhLnNldENvbnRlbnQoaHRtbF81NWI3MjlhYWYyMDQ0NTA0YWVlNzM0NDgxNDkxZTQ1Yik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyXzQyMTBhZjJmMmUyZDRmNDFiMTg5YTM5NWQyMjc4YzU1LmJpbmRQb3B1cChwb3B1cF83ZjdjNzM2ZTY4OGY0MTg4OTY3ODViMGE3ZWMyMzZhYSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl8wNWQyYTk4MzNmY2Y0NTJiYWU1YWE4ZDhkOGRlYjc3NyA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1LjgzOTQ4MDUsLTc4LjYyMzk5NzY5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNDFhYzM2Y2YxM2ZmNDJiYTk3Y2I5OThjMGUyM2U5ZjggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNjM0ZTlhZjRhZTkyNGUzNzk2ZTBhMjhlNWJmNzc2NTEgPSAkKCc8ZGl2IGlkPSJodG1sXzYzNGU5YWY0YWU5MjRlMzc5NmUwYTI4ZTViZjc3NjUxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij45IC0gRWFzdGdhdGUgUGFyazxicj40MjAwIFF1YWlsIEhvbGxvdyBEcml2ZSAyNzYwOTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNDFhYzM2Y2YxM2ZmNDJiYTk3Y2I5OThjMGUyM2U5Zjguc2V0Q29udGVudChodG1sXzYzNGU5YWY0YWU5MjRlMzc5NmUwYTI4ZTViZjc3NjUxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfMDVkMmE5ODMzZmNmNDUyYmFlNWFhOGQ4ZDhkZWI3NzcuYmluZFBvcHVwKHBvcHVwXzQxYWMzNmNmMTNmZjQyYmE5N2NiOTk4YzBlMjNlOWY4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzBkNWU2ZDBlN2U2MzRkMmU4MzUyNDY4ZjE1MGFkMmI2ID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzUuODI3MzI2MjAwMDAwMDEsLTc4LjY4NDUyNV0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzgwMjkxNzI3OTFkMjQxZTVhNjA5NTUyNjk1OWFiY2JiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RkMDJkNzUwMDUyOTRlMTJiZmY1ZjRlYmUxNmM0YmY0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzY5MDgyZTE1OWZjYTRkY2VhM2JmY2I1ZGQyNmU0NWFhID0gJCgnPGRpdiBpZD0iaHRtbF82OTA4MmUxNTlmY2E0ZGNlYTNiZmNiNWRkMjZlNDVhYSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+MTAgLSBHbGVuIEVkZW4gUGFyayBjL28gSmF5Y2VlIFBhcms8YnI+MTUwMCBHbGVuIEVkZW4gRHJpdmUgMjc2MTI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2RkMDJkNzUwMDUyOTRlMTJiZmY1ZjRlYmUxNmM0YmY0LnNldENvbnRlbnQoaHRtbF82OTA4MmUxNTlmY2E0ZGNlYTNiZmNiNWRkMjZlNDVhYSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyXzBkNWU2ZDBlN2U2MzRkMmU4MzUyNDY4ZjE1MGFkMmI2LmJpbmRQb3B1cChwb3B1cF9kZDAyZDc1MDA1Mjk0ZTEyYmZmNWY0ZWJlMTZjNGJmNCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl85ZmUyMmFkMGM3MWE0NmQzODYwYzZjZmJhYjY0NTg2MiA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1Ljg0MTEyNzUsLTc4LjU5MTEyODVdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84MDI5MTcyNzkxZDI0MWU1YTYwOTU1MjY5NTlhYmNiYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yMGY1YTc5MWQ4YjU0NDczODYzZWUzZGRiNjhiOGNlYSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lMzVmOWUyZmJiYWQ0ZDMyYTU2NTY0Zjg0ZWU4YjI5MyA9ICQoJzxkaXYgaWQ9Imh0bWxfZTM1ZjllMmZiYmFkNGQzMmE1NjU2NGY4NGVlOGIyOTMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPjExIC0gR3JlZW4gUm9hZCBDb21tdW5pdHkgQ2VudGVyPGJyPjQyMDEgR3JlZW4gUm9hZCAyNzYwNDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjBmNWE3OTFkOGI1NDQ3Mzg2M2VlM2RkYjY4YjhjZWEuc2V0Q29udGVudChodG1sX2UzNWY5ZTJmYmJhZDRkMzJhNTY1NjRmODRlZThiMjkzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfOWZlMjJhZDBjNzFhNDZkMzg2MGM2Y2ZiYWI2NDU4NjIuYmluZFBvcHVwKHBvcHVwXzIwZjVhNzkxZDhiNTQ0NzM4NjNlZTNkZGI2OGI4Y2VhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzM4NjgwYTNjMzY1ODQ1NmFhYjgwODM2MmU4NDI0MzVkID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzUuODg2MTQ0NCwtNzguNjYwMTI2NDk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84MDI5MTcyNzkxZDI0MWU1YTYwOTU1MjY5NTlhYmNiYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iODhkMGFhMzU2Njc0YTdkOWM4OTQwMTY4OGE2NjA2ZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zNDZiNWNkYzlhMGQ0NTQ2YWFjYmUyOWY1OWFhMGQ3MSA9ICQoJzxkaXYgaWQ9Imh0bWxfMzQ2YjVjZGM5YTBkNDU0NmFhY2JlMjlmNTlhYTBkNzEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPjEyIC0gR3JleXN0b25lIENvbW11bml0eSBDZW50ZXIgPGJyPjc3MTMtNTUgTGVhZG1pbmUgUm9hZCAyNzYxNTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjg4ZDBhYTM1NjY3NGE3ZDljODk0MDE2ODhhNjYwNmUuc2V0Q29udGVudChodG1sXzM0NmI1Y2RjOWEwZDQ1NDZhYWNiZTI5ZjU5YWEwZDcxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfMzg2ODBhM2MzNjU4NDU2YWFiODA4MzYyZTg0MjQzNWQuYmluZFBvcHVwKHBvcHVwX2I4OGQwYWEzNTY2NzRhN2Q5Yzg5NDAxNjg4YTY2MDZlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyX2Q5ZmJjZDRhMmM0YjQzY2I5NjRmNjJjNjM2NzRmMjRmID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzUuNzkzMDk3LC03OC42Mzg4NjY5OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzgwMjkxNzI3OTFkMjQxZTVhNjA5NTUyNjk1OWFiY2JiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2FiZWZjZGU1ZGU2YjRhYWU4Yjc4NDUwN2IyOGIzNGE1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzM5NmY0ODk4Njg1ZjQ0MzQ5YjE4NzRjMDU3Zjk5ZDhmID0gJCgnPGRpdiBpZD0iaHRtbF8zOTZmNDg5ODY4NWY0NDM0OWIxODc0YzA1N2Y5OWQ4ZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+MTMgLSBIYWxpZmF4IENvbW11bml0eSBDZW50ZXI8YnI+MTAyMyBIYWxpZnggU3RyZWV0IDI3NjA0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hYmVmY2RlNWRlNmI0YWFlOGI3ODQ1MDdiMjhiMzRhNS5zZXRDb250ZW50KGh0bWxfMzk2ZjQ4OTg2ODVmNDQzNDliMTg3NGMwNTdmOTlkOGYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl9kOWZiY2Q0YTJjNGI0M2NiOTY0ZjYyYzYzNjc0ZjI0Zi5iaW5kUG9wdXAocG9wdXBfYWJlZmNkZTVkZTZiNGFhZThiNzg0NTA3YjI4YjM0YTUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfODNjZGI4OGYyM2IyNGE4MWE1MmQ4NzBlNDRmMWQxYTQgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNS44MTI0MDU1LC03OC41ODgzMTU0XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZGY5ZWU4NDAxZDRkNGI0YzljODUwNzM0OGE1YzJiNWYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYjEwMmMzMWZlZjcyNGU3ZmE1OGZmYTEzYzgwZGZlNWIgPSAkKCc8ZGl2IGlkPSJodG1sX2IxMDJjMzFmZWY3MjRlN2ZhNThmZmExM2M4MGRmZTViIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij4xNCAtIEhpbGwgU3RyZWV0IENlbnRlcjxicj4yMzA3IEhpbGwgU3RyZWV0IDI3NjA0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9kZjllZTg0MDFkNGQ0YjRjOWM4NTA3MzQ4YTVjMmI1Zi5zZXRDb250ZW50KGh0bWxfYjEwMmMzMWZlZjcyNGU3ZmE1OGZmYTEzYzgwZGZlNWIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl84M2NkYjg4ZjIzYjI0YTgxYTUyZDg3MGU0NGYxZDFhNC5iaW5kUG9wdXAocG9wdXBfZGY5ZWU4NDAxZDRkNGI0YzljODUwNzM0OGE1YzJiNWYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfZWI2NzFkYjIxY2MxNDhjMjllYmE2YjFjYTFmZmY5MDIgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNS43OTk4MzU3LC03OC42NjM2NjUyXSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYjQ2OGMwY2Y1YTcwNGI0NTkxZmY1ODIwYTRiYjJlZDUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfN2VmOTk5ZTEyMGJjNGM4Yjk4MTc4NzM3ZDRmMWIzOTUgPSAkKCc8ZGl2IGlkPSJodG1sXzdlZjk5OWUxMjBiYzRjOGI5ODE3ODczN2Q0ZjFiMzk1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij4xNSAtIEpheWNlZSBDb21tdW5pdHkgQ2VudGVyPGJyPjI0MDUgV2FkZSBBdmVudWUgMjc2MDc8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2I0NjhjMGNmNWE3MDRiNDU5MWZmNTgyMGE0YmIyZWQ1LnNldENvbnRlbnQoaHRtbF83ZWY5OTllMTIwYmM0YzhiOTgxNzg3MzdkNGYxYjM5NSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyX2ViNjcxZGIyMWNjMTQ4YzI5ZWJhNmIxY2ExZmZmOTAyLmJpbmRQb3B1cChwb3B1cF9iNDY4YzBjZjVhNzA0YjQ1OTFmZjU4MjBhNGJiMmVkNSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl9jN2QzNWUxZTAzYjM0M2VkYjQ4MjIzZGE0MjVmZWI5MCA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1LjgxNTA2NTcsLTc4LjYzMTMxNDVdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84MDI5MTcyNzkxZDI0MWU1YTYwOTU1MjY5NTlhYmNiYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wMTA5ZjExNTA2ODY0YTIyOWU4ZmM4MGViOGY1ZTdiNiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hMzM0NThmNTA5MjY0NmFiOTA0Njk3ZjQwODJjY2UxMCA9ICQoJzxkaXYgaWQ9Imh0bWxfYTMzNDU4ZjUwOTI2NDZhYjkwNDY5N2Y0MDgyY2NlMTAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPjE2IC0gS2l3YW5pcyBQYXJrIGMvbyBPcHRpbWlzdCBQYXJrPGJyPjI1MjUgTm9ibGUgUm9hZCAgMjc2MDg8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzAxMDlmMTE1MDY4NjRhMjI5ZThmYzgwZWI4ZjVlN2I2LnNldENvbnRlbnQoaHRtbF9hMzM0NThmNTA5MjY0NmFiOTA0Njk3ZjQwODJjY2UxMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyX2M3ZDM1ZTFlMDNiMzQzZWRiNDgyMjNkYTQyNWZlYjkwLmJpbmRQb3B1cChwb3B1cF8wMTA5ZjExNTA2ODY0YTIyOWU4ZmM4MGViOGY1ZTdiNik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl82YjNhMTc1Y2FlM2M0ZjJjYTdkMmJhMDhmMDUxMzg1YSA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1Ljg4NzQ5NjMsLTc4LjY5OTE2NjhdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84MDI5MTcyNzkxZDI0MWU1YTYwOTU1MjY5NTlhYmNiYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iYmNhZWEzOWQ3NDA0MjliOGQ0NTI3ZmIzNmU2YmEzZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF84MzE2MDAyNTY1YWM0NjBkYWE1Yzg4OTNkNjlhODljMyA9ICQoJzxkaXYgaWQ9Imh0bWxfODMxNjAwMjU2NWFjNDYwZGFhNWM4ODkzZDY5YTg5YzMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPjE3IC0gTGFrZSBMeW5uIENvbW11bml0eSBDZW50ZXI8YnI+NzkyMSBSYXkgUm9hZCAyNzYxMzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYmJjYWVhMzlkNzQwNDI5YjhkNDUyN2ZiMzZlNmJhM2Quc2V0Q29udGVudChodG1sXzgzMTYwMDI1NjVhYzQ2MGRhYTVjODg5M2Q2OWE4OWMzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfNmIzYTE3NWNhZTNjNGYyY2E3ZDJiYTA4ZjA1MTM4NWEuYmluZFBvcHVwKHBvcHVwX2JiY2FlYTM5ZDc0MDQyOWI4ZDQ1MjdmYjM2ZTZiYTNkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzBjZGNjMTg1NTA1YTQyNGM4YmMwYjIyNDAxY2VlMWZmID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzUuODI5ODQ5LC03OC42OTczMzA5OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzgwMjkxNzI3OTFkMjQxZTVhNjA5NTUyNjk1OWFiY2JiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzhjZjY0ZGMwMDMwNzQyOTM4ZWQ0ZDRiZTlmMTNjNWFjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzE2YmU2NzRiODQwYjRlYWY4YzMzMzE3M2FkNmE0YmRmID0gJCgnPGRpdiBpZD0iaHRtbF8xNmJlNjc0Yjg0MGI0ZWFmOGMzMzMxNzNhZDZhNGJkZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+MTggLSBMYXVyZWwgSGlsbHMgQ29tbXVuaXR5IENlbnRlcjxicj4zODA4IEVkd2FyZHMgTWlsbCBSb2FkICAyNzYxMjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOGNmNjRkYzAwMzA3NDI5MzhlZDRkNGJlOWYxM2M1YWMuc2V0Q29udGVudChodG1sXzE2YmU2NzRiODQwYjRlYWY4YzMzMzE3M2FkNmE0YmRmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfMGNkY2MxODU1MDVhNDI0YzhiYzBiMjI0MDFjZWUxZmYuYmluZFBvcHVwKHBvcHVwXzhjZjY0ZGMwMDMwNzQyOTM4ZWQ0ZDRiZTlmMTNjNWFjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzdhZDhlZGU2NjVmMzQ1MGNiYzZmZTYzNDI0MmNhNGFlID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzUuNzk3MjgzNiwtNzguNjE0MDIxNl0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzgwMjkxNzI3OTFkMjQxZTVhNjA5NTUyNjk1OWFiY2JiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2I3Y2RhODk5NjM3ZDQyZTNiMDU0ZTMwZGVlZDViNWYxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2JjMWI2NDBlYjllYTQwZTc4YmJjMTRiM2I4NmI0NzlkID0gJCgnPGRpdiBpZD0iaHRtbF9iYzFiNjQwZWI5ZWE0MGU3OGJiYzE0YjNiODZiNDc5ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+MTkgLSBMaW9ucyBQYXJrIDxicj41MTYgRGVubmlzIEF2ZW51ZSAyNzYwNDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjdjZGE4OTk2MzdkNDJlM2IwNTRlMzBkZWVkNWI1ZjEuc2V0Q29udGVudChodG1sX2JjMWI2NDBlYjllYTQwZTc4YmJjMTRiM2I4NmI0NzlkKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfN2FkOGVkZTY2NWYzNDUwY2JjNmZlNjM0MjQyY2E0YWUuYmluZFBvcHVwKHBvcHVwX2I3Y2RhODk5NjM3ZDQyZTNiMDU0ZTMwZGVlZDViNWYxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzM2MjdiMzExMDVhOTQ2ZjdhOWRiYzI3NzkyMGVlODhhID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzUuODIyNTI4LC03OC41NjkwMDY4OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzgwMjkxNzI3OTFkMjQxZTVhNjA5NTUyNjk1OWFiY2JiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2QwNTI5NWZlZGQ4YTRjMTdhYTA0YjBiZjU4MTA1Y2UxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzA4NGRlYmY3YTg0YzQxZWJhYmFlOTUzMzA0NTYzYjIxID0gJCgnPGRpdiBpZD0iaHRtbF8wODRkZWJmN2E4NGM0MWViYWJhZTk1MzMwNDU2M2IyMSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+MjAgLSBNYXJzaCBDcmVlayBQYXJrPGJyPjMwNTAgTmV3IEhvcGUgUm9hZCAyNzYwNDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZDA1Mjk1ZmVkZDhhNGMxN2FhMDRiMGJmNTgxMDVjZTEuc2V0Q29udGVudChodG1sXzA4NGRlYmY3YTg0YzQxZWJhYmFlOTUzMzA0NTYzYjIxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfMzYyN2IzMTEwNWE5NDZmN2E5ZGJjMjc3OTIwZWU4OGEuYmluZFBvcHVwKHBvcHVwX2QwNTI5NWZlZGQ4YTRjMTdhYTA0YjBiZjU4MTA1Y2UxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyX2YxYTM0Nzg5Njg3MjQ4NmY5OTU2MzRiOTZlNjFlYTc3ID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzUuNzkyNzc3NSwtNzguNjk0NDU5NF0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzgwMjkxNzI3OTFkMjQxZTVhNjA5NTUyNjk1OWFiY2JiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2IxMmVhZGZiODgwOTQ3NjhiMjk1Y2NmZGJhZDg4N2QxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzIxMThmY2FkMTVlYTRiMTQ5MjM4MmQxMzhhMDMwZWQ5ID0gJCgnPGRpdiBpZD0iaHRtbF8yMTE4ZmNhZDE1ZWE0YjE0OTIzODJkMTM4YTAzMGVkOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+MjEgLSBNZXRob2QgUm9hZCBDb21tdW5pdHkgQ2VudGVyPGJyPjUxNCBNZXRob2QgUm9hZCAyNzYwNzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjEyZWFkZmI4ODA5NDc2OGIyOTVjY2ZkYmFkODg3ZDEuc2V0Q29udGVudChodG1sXzIxMThmY2FkMTVlYTRiMTQ5MjM4MmQxMzhhMDMwZWQ5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfZjFhMzQ3ODk2ODcyNDg2Zjk5NTYzNGI5NmU2MWVhNzcuYmluZFBvcHVwKHBvcHVwX2IxMmVhZGZiODgwOTQ3NjhiMjk1Y2NmZGJhZDg4N2QxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyX2FlNjg0NjgzN2MzMTQwZGQ4YWNhM2E0MmI5ZDE3NWFlID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzUuODY5MjEzMiwtNzguNjA3Mzc0MV0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzgwMjkxNzI3OTFkMjQxZTVhNjA5NTUyNjk1OWFiY2JiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzNkMmM2MzI3NGNmNTRjZGM4ZGUxNGE3NGNlZWMyMTI1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2JhOTEzODA1YzExZTQyYTFhNDk0ZGUwZTI0ZjdlNWVjID0gJCgnPGRpdiBpZD0iaHRtbF9iYTkxMzgwNWMxMWU0MmExYTQ5NGRlMGUyNGY3ZTVlYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+MjIgLSBNaWxsYnJvb2sgRXhjaGFuZ2UgQ29tbXVuaXR5IENlbnRlcjxicj4xOTA1IFNwcmluZyBGb3Jlc3QgUm9hZCAyNzYxNTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfM2QyYzYzMjc0Y2Y1NGNkYzhkZTE0YTc0Y2VlYzIxMjUuc2V0Q29udGVudChodG1sX2JhOTEzODA1YzExZTQyYTFhNDk0ZGUwZTI0ZjdlNWVjKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfYWU2ODQ2ODM3YzMxNDBkZDhhY2EzYTQyYjlkMTc1YWUuYmluZFBvcHVwKHBvcHVwXzNkMmM2MzI3NGNmNTRjZGM4ZGUxNGE3NGNlZWMyMTI1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzVmZGYxYWMwMGZjNjQxZDhhMWU2ZjBiZGNhOWM3YmQ4ID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzUuNzkyNjkzNCwtNzguNjMzMjkzMTAwMDAwMDJdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84MDI5MTcyNzkxZDI0MWU1YTYwOTU1MjY5NTlhYmNiYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yMjNiYmJiOGUzNzY0YzcxOGU2MWU2ZTEzYzAxN2U5MCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83NzdhNzcwNGMxNmU0MThkYjg1ODBkYjU3ZDQxNWJhMSA9ICQoJzxkaXYgaWQ9Imh0bWxfNzc3YTc3MDRjMTZlNDE4ZGI4NTgwZGI1N2Q0MTViYTEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPjIzIC0gTW9yZGVjYWkgSGlzdG9yaWMgUGFyayA8YnI+MSBNaW1vc2EgU3RyZWV0IDI3NjA0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yMjNiYmJiOGUzNzY0YzcxOGU2MWU2ZTEzYzAxN2U5MC5zZXRDb250ZW50KGh0bWxfNzc3YTc3MDRjMTZlNDE4ZGI4NTgwZGI1N2Q0MTViYTEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl81ZmRmMWFjMDBmYzY0MWQ4YTFlNmYwYmRjYTljN2JkOC5iaW5kUG9wdXAocG9wdXBfMjIzYmJiYjhlMzc2NGM3MThlNjFlNmUxM2MwMTdlOTApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfMzZlM2ZjN2M3OTU5NDEyZWFkNTdkYWJkNDVkZmEyNmYgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNS44NjIzNjc3LC03OC42NDQwODc1XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMjU4N2VlOGE3MmJhNGM1MGI0NDE2NGFhYzYxZWVhMzUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfY2ViOGVlMGM2NTFjNDFmMmE0YTgzNzQ2NWE0NGZhMjQgPSAkKCc8ZGl2IGlkPSJodG1sX2NlYjhlZTBjNjUxYzQxZjJhNGE4Mzc0NjVhNDRmYTI0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij4yNCAtIE9wdGltaXN0IENvbW11bml0eSBDZW50ZXI8YnI+NTkwMCBXaGl0dGllciBEcml2ZSAyNzYwOTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjU4N2VlOGE3MmJhNGM1MGI0NDE2NGFhYzYxZWVhMzUuc2V0Q29udGVudChodG1sX2NlYjhlZTBjNjUxYzQxZjJhNGE4Mzc0NjVhNDRmYTI0KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfMzZlM2ZjN2M3OTU5NDEyZWFkNTdkYWJkNDVkZmEyNmYuYmluZFBvcHVwKHBvcHVwXzI1ODdlZThhNzJiYTRjNTBiNDQxNjRhYWM2MWVlYTM1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzM1YjMwNTllNDJkZjQ5ZDNhZWIyYWE2NzMxNGUyNmM3ID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzUuNzQyNTk1MSwtNzguNjU0ODgyMV0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzgwMjkxNzI3OTFkMjQxZTVhNjA5NTUyNjk1OWFiY2JiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzMzYWM2MGU0NTEzZjQzNDViM2ViYWNkM2U5ZTMyOWQ5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2I1MjJkN2Q3NjRkYzQ3MGI5MWMzMzU2NjEzYzVkMmQ0ID0gJCgnPGRpdiBpZD0iaHRtbF9iNTIyZDdkNzY0ZGM0NzBiOTFjMzM1NjYxM2M1ZDJkNCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+MjUgLSBQZWFjaCBSb2FkPGJyPjkxMSBJbGVhZ25lcyBSb2FkIDI3NjAzPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zM2FjNjBlNDUxM2Y0MzQ1YjNlYmFjZDNlOWUzMjlkOS5zZXRDb250ZW50KGh0bWxfYjUyMmQ3ZDc2NGRjNDcwYjkxYzMzNTY2MTNjNWQyZDQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl8zNWIzMDU5ZTQyZGY0OWQzYWViMmFhNjczMTRlMjZjNy5iaW5kUG9wdXAocG9wdXBfMzNhYzYwZTQ1MTNmNDM0NWIzZWJhY2QzZTllMzI5ZDkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfNjc4YzM4MDE5ZGJmNDVlMGFlMmE0NTNkMzVhM2ZkMDMgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNS43Nzg5OTUsLTc4LjcxNDM1Nzk5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfODFhZTA0YmVhMWVjNGFiNGEyMDU2YTU3MGFkNTFkNzkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMmU1YTY2ZTI0Yjk5NDg3OWFkYzJmYjEzMDhmNWYxYWMgPSAkKCc8ZGl2IGlkPSJodG1sXzJlNWE2NmUyNGI5OTQ4NzlhZGMyZmIxMzA4ZjVmMWFjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij4yNiAtIFBvd2VsbCBEcml2ZSBQYXJrPGJyPjc0MCBQb3dlbGwgRHJpdmUgMjc2MDY8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzgxYWUwNGJlYTFlYzRhYjRhMjA1NmE1NzBhZDUxZDc5LnNldENvbnRlbnQoaHRtbF8yZTVhNjZlMjRiOTk0ODc5YWRjMmZiMTMwOGY1ZjFhYyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyXzY3OGMzODAxOWRiZjQ1ZTBhZTJhNDUzZDM1YTNmZDAzLmJpbmRQb3B1cChwb3B1cF84MWFlMDRiZWExZWM0YWI0YTIwNTZhNTcwYWQ1MWQ3OSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl9mZTRlY2NjNDg0OTU0NWI1YThiYmE2ZjM3MjMwMDI5OCA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1Ljc3ODk5NSwtNzguNzE0MzU3OTk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84MDI5MTcyNzkxZDI0MWU1YTYwOTU1MjY5NTlhYmNiYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jYTUyMWZjNjljZDQ0M2I5OTY1Zjg4NzUzYTJkYjFhYyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9kMWViNzZlOGE2ZGI0MTkwYjc0ZjlhNWE0NTA1MzYxNyA9ICQoJzxkaXYgaWQ9Imh0bWxfZDFlYjc2ZThhNmRiNDE5MGI3NGY5YTVhNDUwNTM2MTciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPjI3IC0gUG93ZWxsIERyaXZlIFBhcms8YnI+NzQwIFBvd2VsbCBEcml2ZSAyNzYwNjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfY2E1MjFmYzY5Y2Q0NDNiOTk2NWY4ODc1M2EyZGIxYWMuc2V0Q29udGVudChodG1sX2QxZWI3NmU4YTZkYjQxOTBiNzRmOWE1YTQ1MDUzNjE3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfZmU0ZWNjYzQ4NDk1NDViNWE4YmJhNmYzNzIzMDAyOTguYmluZFBvcHVwKHBvcHVwX2NhNTIxZmM2OWNkNDQzYjk5NjVmODg3NTNhMmRiMWFjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyX2JhNGRmNWM3MWYwYTQ3MjdhMzNiZTBmOTVjNDhkYThiID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzUuNzgwNjUxLC03OC42NjA5ODU0XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMDUwMWNmODVhZDMzNGZlYjg0MGMwMjI2MDdjM2FlYzMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYTlkODk0YmI1Y2QzNGI1YTk4MDgxOWZhMDc4NzcyNzIgPSAkKCc8ZGl2IGlkPSJodG1sX2E5ZDg5NGJiNWNkMzRiNWE5ODA4MTlmYTA3ODc3MjcyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij4yOCAtIFB1bGxlbiBDb21tdW5pdHkgQ2VudGVyIDxicj40MDggQXNoZSBBdmVudWUgMjc2MDc8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzA1MDFjZjg1YWQzMzRmZWI4NDBjMDIyNjA3YzNhZWMzLnNldENvbnRlbnQoaHRtbF9hOWQ4OTRiYjVjZDM0YjVhOTgwODE5ZmEwNzg3NzI3Mik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyX2JhNGRmNWM3MWYwYTQ3MjdhMzNiZTBmOTVjNDhkYThiLmJpbmRQb3B1cChwb3B1cF8wNTAxY2Y4NWFkMzM0ZmViODQwYzAyMjYwN2MzYWVjMyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl9kZjdlOTk2OTlhYzQ0NGNjYTg2ZGJhYmIyNGI4M2ZkZSA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1Ljc3NzY2NTMsLTc4LjYzOTc1MTY5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfM2FmOTZiN2VlMTBhNDhlNDlkZTdmYTVkZmJkY2ExYjQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOWExN2YxMzNlNTliNDkyODk1Mjc4MjFjN2IxYWE2ZGMgPSAkKCc8ZGl2IGlkPSJodG1sXzlhMTdmMTMzZTU5YjQ5Mjg5NTI3ODIxYzdiMWFhNmRjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij4yOSAtIFJhbGVpZ2ggQ2l0eSBNdXNldW08YnI+MjIwIEZheWV0dGV2aWxsZSBTdHJlZXQgMjc2MDE8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzNhZjk2YjdlZTEwYTQ4ZTQ5ZGU3ZmE1ZGZiZGNhMWI0LnNldENvbnRlbnQoaHRtbF85YTE3ZjEzM2U1OWI0OTI4OTUyNzgyMWM3YjFhYTZkYyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyX2RmN2U5OTY5OWFjNDQ0Y2NhODZkYmFiYjI0YjgzZmRlLmJpbmRQb3B1cChwb3B1cF8zYWY5NmI3ZWUxMGE0OGU0OWRlN2ZhNWRmYmRjYTFiNCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl9jNTMyYWZlMDQ2ZDM0NjlmODMzZTA5N2Y2ZTJlMjY1OCA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1Ljc2NDg4MDMsLTc4LjYwODk1MDI5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjE5Yzk1N2M2ZGYxNDQ3Mzg4YzQ5YTRkZWVmYzcyMTIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZTI3YzBlNDUzMzZiNDBiNzk2ZDNkNDhjYWIzMDQ0OTkgPSAkKCc8ZGl2IGlkPSJodG1sX2UyN2MwZTQ1MzM2YjQwYjc5NmQzZDQ4Y2FiMzA0NDk5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij4zMCAtIFJhbHBoIENhbXBiZWxsIENvbW11bml0eSBDZW50ZXI8YnI+NzU2IEx1bmFyIERyaXZlIDI3NjEwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82MTljOTU3YzZkZjE0NDczODhjNDlhNGRlZWZjNzIxMi5zZXRDb250ZW50KGh0bWxfZTI3YzBlNDUzMzZiNDBiNzk2ZDNkNDhjYWIzMDQ0OTkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl9jNTMyYWZlMDQ2ZDM0NjlmODMzZTA5N2Y2ZTJlMjY1OC5iaW5kUG9wdXAocG9wdXBfNjE5Yzk1N2M2ZGYxNDQ3Mzg4YzQ5YTRkZWVmYzcyMTIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfYjAwN2E3MjgyNDk5NDA0OGIxYTUwOTAyODVhNDc5MWIgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNS43NzU1MTksLTc4LjYxODMwMV0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzgwMjkxNzI3OTFkMjQxZTVhNjA5NTUyNjk1OWFiY2JiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzg0ZmE2ZjA3NjBhYjQ0NzI5YTA1MzhkYWFiYzExMjJkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzQ2NGU0NzdhMjFmODQwYmNhNDU2MGFlYzc0Njg5MzU2ID0gJCgnPGRpdiBpZD0iaHRtbF80NjRlNDc3YTIxZjg0MGJjYTQ1NjBhZWM3NDY4OTM1NiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+MzEgLSBSb2JlcnRzIFBhcmsgQ29tbXVuaXR5IENlbnRlcjxicj4xMzAwIEUuIE1hcnRpbiBTdHJlZXQgMjc2MTA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzg0ZmE2ZjA3NjBhYjQ0NzI5YTA1MzhkYWFiYzExMjJkLnNldENvbnRlbnQoaHRtbF80NjRlNDc3YTIxZjg0MGJjYTQ1NjBhZWM3NDY4OTM1Nik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyX2IwMDdhNzI4MjQ5OTQwNDhiMWE1MDkwMjg1YTQ3OTFiLmJpbmRQb3B1cChwb3B1cF84NGZhNmYwNzYwYWI0NDcyOWEwNTM4ZGFhYmMxMTIyZCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl9kNGNkYTU0NjlkOTI0MWVhODFjMTY2ZWRiN2QyMjFkYyA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1Ljc4MDgwMTQsLTc4LjYyMjUyNDNdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84MDI5MTcyNzkxZDI0MWU1YTYwOTU1MjY5NTlhYmNiYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81MTIzZTU0OGQwOTc0NmM5YmU3YjUwZGMzMjhjOGYxYiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wNTQzOTk3NWZhNGM0YmE0YWM3NGJhMjVjYTI0ZDllMSA9ICQoJzxkaXYgaWQ9Imh0bWxfMDU0Mzk5NzVmYTRjNGJhNGFjNzRiYTI1Y2EyNGQ5ZTEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPjMyIC0gU3QuIE1vbmljYSBUZWVuIENlbnRlciA8YnI+MTUgTi4gVGFyYm9ybyBTdHJlZXQgMjc2MDE8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzUxMjNlNTQ4ZDA5NzQ2YzliZTdiNTBkYzMyOGM4ZjFiLnNldENvbnRlbnQoaHRtbF8wNTQzOTk3NWZhNGM0YmE0YWM3NGJhMjVjYTI0ZDllMSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyX2Q0Y2RhNTQ2OWQ5MjQxZWE4MWMxNjZlZGI3ZDIyMWRjLmJpbmRQb3B1cChwb3B1cF81MTIzZTU0OGQwOTc0NmM5YmU3YjUwZGMzMjhjOGYxYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl8yOTA1N2VkNjFkZWM0NGI1YTJjY2ZlN2E2OGNmNzY0NyA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1Ljc0Mjg3MjEsLTc4LjYxMzYzNjU5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNzQzZWJiNDM5YTU4NGQ2YTk2ZDBkODBiOGUzZTkxNDMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOWU1YTkwMWU3MDgxNDlhZGI1YmUzYTk4MTM1N2NiZjMgPSAkKCc8ZGl2IGlkPSJodG1sXzllNWE5MDFlNzA4MTQ5YWRiNWJlM2E5ODEzNTdjYmYzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij4zMyAtIFNhbmRlcmZvcmQgUm9hZCBQYXJrPGJyPjI2MjMgU2FuZGVyZm9yZCBSb2FkIDI3NjEwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83NDNlYmI0MzlhNTg0ZDZhOTZkMGQ4MGI4ZTNlOTE0My5zZXRDb250ZW50KGh0bWxfOWU1YTkwMWU3MDgxNDlhZGI1YmUzYTk4MTM1N2NiZjMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl8yOTA1N2VkNjFkZWM0NGI1YTJjY2ZlN2E2OGNmNzY0Ny5iaW5kUG9wdXAocG9wdXBfNzQzZWJiNDM5YTU4NGQ2YTk2ZDBkODBiOGUzZTkxNDMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfMDQxODM3ZTJhMDZmNDdmM2I3NTYyMzU0MjE4YTg3NDEgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNS43NTMwMywtNzguNjA4OTkwOF0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzgwMjkxNzI3OTFkMjQxZTVhNjA5NTUyNjk1OWFiY2JiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzgwMTE2MmFlNzZjMDQyOWFiMmIwN2YwZDlmNWZiZTk5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2IwNGVjNDUxMjQ3YzQzNjc4Y2Q0N2QwMzkxN2QyOThiID0gJCgnPGRpdiBpZD0iaHRtbF9iMDRlYzQ1MTI0N2M0MzY3OGNkNDdkMDM5MTdkMjk4YiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+MzQgLSBTZ3QuIENvdXJ0bmV5IFQuIEpvaG5zb24gQ2VudGVyPGJyPjE4MDEgUHJvY3RvciBSb2FkIDI3NjEwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84MDExNjJhZTc2YzA0MjlhYjJiMDdmMGQ5ZjVmYmU5OS5zZXRDb250ZW50KGh0bWxfYjA0ZWM0NTEyNDdjNDM2NzhjZDQ3ZDAzOTE3ZDI5OGIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl8wNDE4MzdlMmEwNmY0N2YzYjc1NjIzNTQyMThhODc0MS5iaW5kUG9wdXAocG9wdXBfODAxMTYyYWU3NmMwNDI5YWIyYjA3ZjBkOWY1ZmJlOTkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfYTg0N2YyZWM3NzlmNDE5Yjg3MjM3MzMyM2U1OWFiYWIgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNS43NTMwMywtNzguNjA4OTkwOF0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzgwMjkxNzI3OTFkMjQxZTVhNjA5NTUyNjk1OWFiY2JiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzEzZjM0NDM4ZGYxZTQ2ZjhiYjI5NDEyYmNkY2ZjYWMyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2I5OWExZDg3ZjNiMDRmODRiZmY1ODIwMDNlYWFjNDUxID0gJCgnPGRpdiBpZD0iaHRtbF9iOTlhMWQ4N2YzYjA0Zjg0YmZmNTgyMDAzZWFhYzQ1MSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+MzQgLSBTb3V0aGdhdGU8YnI+MTgwMSBQcm9jdG9yIFJvYWQgMjc2MTA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzEzZjM0NDM4ZGYxZTQ2ZjhiYjI5NDEyYmNkY2ZjYWMyLnNldENvbnRlbnQoaHRtbF9iOTlhMWQ4N2YzYjA0Zjg0YmZmNTgyMDAzZWFhYzQ1MSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyX2E4NDdmMmVjNzc5ZjQxOWI4NzIzNzMzMjNlNTlhYmFiLmJpbmRQb3B1cChwb3B1cF8xM2YzNDQzOGRmMWU0NmY4YmIyOTQxMmJjZGNmY2FjMik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl8xMTE2M2YyYjU0N2E0Y2QyODg4ZmFlMWZkZTY4MjBiNCA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1Ljc4MTQzMzQsLTc4LjYyMjczMjVdLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84MDI5MTcyNzkxZDI0MWU1YTYwOTU1MjY5NTlhYmNiYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wYzVkZDQ1OTUyMWI0MTViYjBkZGMzNTgwODk3NjVkMCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wNjFiN2I0OGJjMDc0MGJjOTQ5YWE2ZDZlYjBjYThiOSA9ICQoJzxkaXYgaWQ9Imh0bWxfMDYxYjdiNDhiYzA3NDBiYzk0OWFhNmQ2ZWIwY2E4YjkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPjM2IC0gVGFyYm9ybyBSb2FkIENvbW11bml0eSBDZW50ZXI8YnI+MTIxIE4uIFRhcmJvcm8gU3RyZWV0IDI3NjEwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wYzVkZDQ1OTUyMWI0MTViYjBkZGMzNTgwODk3NjVkMC5zZXRDb250ZW50KGh0bWxfMDYxYjdiNDhiYzA3NDBiYzk0OWFhNmQ2ZWIwY2E4YjkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl8xMTE2M2YyYjU0N2E0Y2QyODg4ZmFlMWZkZTY4MjBiNC5iaW5kUG9wdXAocG9wdXBfMGM1ZGQ0NTk1MjFiNDE1YmIwZGRjMzU4MDg5NzY1ZDApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfNGU5OTQ3MjZjN2QxNDE3N2E1MGU1YTE5NGJhZTk4Y2EgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNS43NjAzNjg2LC03OC42MjQ4OTk5XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjY3M2I5NTE3M2YyNDMxZmFjY2RmMWRkMWM0NzMzYjcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMzk4ODMyMDFmZWM1NDk1YTlkNDEyYzRmODA4ODQ4MWQgPSAkKCc8ZGl2IGlkPSJodG1sXzM5ODgzMjAxZmVjNTQ5NWE5ZDQxMmM0ZjgwODg0ODFkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij4zNyAtIFdhbG51dCBDcmVlayBXZXRsYW5kIENlbnRlciA8YnI+OTUwIFBldGVyc29uIFN0cmVldCAyNzYxMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZjY3M2I5NTE3M2YyNDMxZmFjY2RmMWRkMWM0NzMzYjcuc2V0Q29udGVudChodG1sXzM5ODgzMjAxZmVjNTQ5NWE5ZDQxMmM0ZjgwODg0ODFkKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBtYXJrZXJfNGU5OTQ3MjZjN2QxNDE3N2E1MGU1YTE5NGJhZTk4Y2EuYmluZFBvcHVwKHBvcHVwX2Y2NzNiOTUxNzNmMjQzMWZhY2NkZjFkZDFjNDczM2I3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCgogICAgICAgICAgICB2YXIgbWFya2VyXzVhOThmZWJkMDc3ZjQ1ODE5YjEwZmYwY2EzYTdlNzYwID0gTC5tYXJrZXIoCiAgICAgICAgICAgICAgICBbMzUuNzYwMzY4NiwtNzguNjI0ODk5OV0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzgwMjkxNzI3OTFkMjQxZTVhNjA5NTUyNjk1OWFiY2JiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzU2NzJkNjZhYTAwOTQyZWRiODMwYjkzZTc1ZmRjNzZlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzA2NTBhY2Q0YmY5ZDRjNjA4NTA5YmNjZDMzMTIyOWU4ID0gJCgnPGRpdiBpZD0iaHRtbF8wNjUwYWNkNGJmOWQ0YzYwODUwOWJjY2QzMzEyMjllOCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+MzcgLSBXYWxudXQgQ3JlZWsgV2V0bGFuZCBDZW50ZXIgPGJyPjk1MCBQZXRlcnNvbiBTdHJlZXQgMjc2MTA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzU2NzJkNjZhYTAwOTQyZWRiODMwYjkzZTc1ZmRjNzZlLnNldENvbnRlbnQoaHRtbF8wNjUwYWNkNGJmOWQ0YzYwODUwOWJjY2QzMzEyMjllOCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyXzVhOThmZWJkMDc3ZjQ1ODE5YjEwZmYwY2EzYTdlNzYwLmJpbmRQb3B1cChwb3B1cF81NjcyZDY2YWEwMDk0MmVkYjgzMGI5M2U3NWZkYzc2ZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl9kYTA5MDExZTgxMGE0ZDJkODNmNTg1Njk3YTMxMjAyYyA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1Ljc2MDM2ODYsLTc4LjYyNDg5OTldLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGljb246IG5ldyBMLkljb24uRGVmYXVsdCgpCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgLmFkZFRvKG1hcF84MDI5MTcyNzkxZDI0MWU1YTYwOTU1MjY5NTlhYmNiYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80MmZjYWM2OTMzOWM0ZjJlOGYwNzdkNzdhZmFjNWI0YiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xNGVhYjUxYjE1Mzc0MjM0YjQyNTJjOWU5MGU0OWE2NiA9ICQoJzxkaXYgaWQ9Imh0bWxfMTRlYWI1MWIxNTM3NDIzNGI0MjUyYzllOTBlNDlhNjYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPjM3IC0gV2FsbnV0IENyZWVrIFdldGxhbmQgQ2VudGVyIDxicj45NTAgUGV0ZXJzb24gU3RyZWV0IDI3NjEwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80MmZjYWM2OTMzOWM0ZjJlOGYwNzdkNzdhZmFjNWI0Yi5zZXRDb250ZW50KGh0bWxfMTRlYWI1MWIxNTM3NDIzNGI0MjUyYzllOTBlNDlhNjYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl9kYTA5MDExZTgxMGE0ZDJkODNmNTg1Njk3YTMxMjAyYy5iaW5kUG9wdXAocG9wdXBfNDJmY2FjNjkzMzljNGYyZThmMDc3ZDc3YWZhYzViNGIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfNDMxZGIyNmNkNmYxNDc4NTg5YjE3MzQ2ZjQ5YWFiNWMgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNS43NjMzNzc0LC03OC41ODcwNjk3MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzgwMjkxNzI3OTFkMjQxZTVhNjA5NTUyNjk1OWFiY2JiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzMxODQzMTU0NTBlMjQ4OThiYTM1ZDljMjgzZjhjOWJlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzNjZjgwMjY4YmJkZTQ5OGY5Mjg3ZTE2MDhkNjY4NjU1ID0gJCgnPGRpdiBpZD0iaHRtbF8zY2Y4MDI2OGJiZGU0OThmOTI4N2UxNjA4ZDY2ODY1NSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+MzggLSBXb3J0aGRhbGUgQ29tbXVuaXR5IENlbnRlcjxicj4xMDAxIENvb3BlciBSb2FkIDI3NjEwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zMTg0MzE1NDUwZTI0ODk4YmEzNWQ5YzI4M2Y4YzliZS5zZXRDb250ZW50KGh0bWxfM2NmODAyNjhiYmRlNDk4ZjkyODdlMTYwOGQ2Njg2NTUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl80MzFkYjI2Y2Q2ZjE0Nzg1ODliMTczNDZmNDlhYWI1Yy5iaW5kUG9wdXAocG9wdXBfMzE4NDMxNTQ1MGUyNDg5OGJhMzVkOWMyODNmOGM5YmUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfNGJiNzJhNTc5NmRmNDI3MmFkNDNlZDQ5Zjg0MGM5ZDcgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNS44NzQ5NSwtNzguNzEzOTEzNl0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWNvbjogbmV3IEwuSWNvbi5EZWZhdWx0KCkKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAuYWRkVG8obWFwXzgwMjkxNzI3OTFkMjQxZTVhNjA5NTUyNjk1OWFiY2JiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2E3N2MwNTI3ZjAyYTRhZWVhMWZlOWQ5YThlYjgwMzMwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzVjZTVjODJmOGQ4NzQyNmU5ZWFhOTAyYjgzNDRkNTVjID0gJCgnPGRpdiBpZD0iaHRtbF81Y2U1YzgyZjhkODc0MjZlOWVhYTkwMmI4MzQ0ZDU1YyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+MzkgLSBIaWxidXJuIEFjYWRlbXk8YnI+NzEwMCBIaWxidXJuIERyaXZlIDI3NjEzPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hNzdjMDUyN2YwMmE0YWVlYTFmZTlkOWE4ZWI4MDMzMC5zZXRDb250ZW50KGh0bWxfNWNlNWM4MmY4ZDg3NDI2ZTllYWE5MDJiODM0NGQ1NWMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl80YmI3MmE1Nzk2ZGY0MjcyYWQ0M2VkNDlmODQwYzlkNy5iaW5kUG9wdXAocG9wdXBfYTc3YzA1MjdmMDJhNGFlZWExZmU5ZDlhOGViODAzMzApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfZmY4MWIyM2I2ZjlhNDZiZmEyMjRmNTg5MmZkMGYyZTcgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNS44ODgxMTczLC03OC44MTg4Mjg5XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMjViMzQyMjU3NTFiNDdjMzk1NWNhYzdkOTcwYzZjNjAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOTkyMTlmOWE1MTMwNDM4YWIxNzI3YjYxZjI1OTQ1OTQgPSAkKCc8ZGl2IGlkPSJodG1sXzk5MjE5ZjlhNTEzMDQzOGFiMTcyN2I2MWYyNTk0NTk0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij40MCAtIFBsZWFzYW50IEdyb3ZlIEVsZW1lbnRhcnkgU2Nob29sPGJyPjM2MDUgUGxlYXNhbnQgR3JvdmUgQ2h1cmNoIFJvYWQgMjc1NjA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzI1YjM0MjI1NzUxYjQ3YzM5NTVjYWM3ZDk3MGM2YzYwLnNldENvbnRlbnQoaHRtbF85OTIxOWY5YTUxMzA0MzhhYjE3MjdiNjFmMjU5NDU5NCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgbWFya2VyX2ZmODFiMjNiNmY5YTQ2YmZhMjI0ZjU4OTJmZDBmMmU3LmJpbmRQb3B1cChwb3B1cF8yNWIzNDIyNTc1MWI0N2MzOTU1Y2FjN2Q5NzBjNmM2MCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAoKICAgICAgICAgICAgdmFyIG1hcmtlcl81YjZhODUzYzZjYmI0NDUxYjQxMTY4ZWZlOGQwZmYxYSA9IEwubWFya2VyKAogICAgICAgICAgICAgICAgWzM1Ljg4NTM0NjQsLTc4LjYzMTA5NjM5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMTk1ZGViNTRmZGY1NGRhZGJmNDcyOTFmOTc4MDNlZTIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYWI4YjAxMTRlYjQzNGFjNThkYzkyNjg2NWZhYTI0MzcgPSAkKCc8ZGl2IGlkPSJodG1sX2FiOGIwMTE0ZWI0MzRhYzU4ZGM5MjY4NjVmYWEyNDM3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij40MSAtIFJhdmVuc2Nyb2Z0IFNjaG9vbCA8YnI+NzQwOSBGYWxscyBvZiBOZXVzZSBSb2FkIDI3NjE1PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xOTVkZWI1NGZkZjU0ZGFkYmY0NzI5MWY5NzgwM2VlMi5zZXRDb250ZW50KGh0bWxfYWI4YjAxMTRlYjQzNGFjNThkYzkyNjg2NWZhYTI0MzcpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl81YjZhODUzYzZjYmI0NDUxYjQxMTY4ZWZlOGQwZmYxYS5iaW5kUG9wdXAocG9wdXBfMTk1ZGViNTRmZGY1NGRhZGJmNDcyOTFmOTc4MDNlZTIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKCiAgICAgICAgICAgIHZhciBtYXJrZXJfODI2NDMwYTI5MTdmNDNlMTkxNThiM2UwZmVkMjkxYzYgPSBMLm1hcmtlcigKICAgICAgICAgICAgICAgIFszNS44MDIyNjU3LC03OC42NDUxNTAxXSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpY29uOiBuZXcgTC5JY29uLkRlZmF1bHQoKQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIC5hZGRUbyhtYXBfODAyOTE3Mjc5MWQyNDFlNWE2MDk1NTI2OTU5YWJjYmIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzVjNDhlMzg2YWY3NDgyNzk2YmQzZTVlZDc1Mjg3ODQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNTU4NjE2MzEyMGM0NGFjN2E1NGQ2YWUxNjQ5Yzg2MzMgPSAkKCc8ZGl2IGlkPSJodG1sXzU1ODYxNjMxMjBjNDRhYzdhNTRkNmFlMTY0OWM4NjMzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij40MiAtIFVuZGVyd29vZCBFbGVtZW50YXJ5PGJyPjE2MTQgR2xlbndvb2QgQXZlbnVlIDI3NjA4PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jNWM0OGUzODZhZjc0ODI3OTZiZDNlNWVkNzUyODc4NC5zZXRDb250ZW50KGh0bWxfNTU4NjE2MzEyMGM0NGFjN2E1NGQ2YWUxNjQ5Yzg2MzMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIG1hcmtlcl84MjY0MzBhMjkxN2Y0M2UxOTE1OGIzZTBmZWQyOTFjNi5iaW5kUG9wdXAocG9wdXBfYzVjNDhlMzg2YWY3NDgyNzk2YmQzZTVlZDc1Mjg3ODQpOwoKICAgICAgICAgICAgCiAgICAgICAgCjwvc2NyaXB0Pg==\" 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 0x22b40166748>"
]
},
"execution_count": 99,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"map = folium.Map(location=[35.779590, -78.638179])\n",
"df.apply(lambda row: folium.Marker(location=[row[\"LAT\"], row[\"LNG\"]],\n",
" popup=str(row[\"MAP_NUM\"]) + \" - \" + row[\"LOCATION\"] + \"<br>\" + row[\"PHYSICAL ADDRESS\"]).add_to(map), axis = 1)\n",
"map"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. Export to CSV"
]
},
{
"cell_type": "code",
"execution_count": 102,
"metadata": {},
"outputs": [],
"source": [
"df.to_csv('./data/camp_locations.csv')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"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.2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment