Skip to content

Instantly share code, notes, and snippets.

@pskifast
Created February 19, 2020 01:29
Show Gist options
  • Save pskifast/417aa2ee2d58189f74e1469401bb4ce7 to your computer and use it in GitHub Desktop.
Save pskifast/417aa2ee2d58189f74e1469401bb4ce7 to your computer and use it in GitHub Desktop.
Created on Cognitive Class Labs
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Segmenting and Clustering Neighborhoods in Toronto"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Solving environment: done\n",
"\n",
"\n",
"==> WARNING: A newer version of conda exists. <==\n",
" current version: 4.5.11\n",
" latest version: 4.8.2\n",
"\n",
"Please update conda by running\n",
"\n",
" $ conda update -n base -c defaults conda\n",
"\n",
"\n",
"\n",
"# All requested packages already installed.\n",
"\n",
"Requirement already satisfied: lxml in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (4.5.0)\n",
"All imported!\n"
]
}
],
"source": [
"# importing required libraries\n",
"\n",
"import pandas as pd\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"%matplotlib inline\n",
"\n",
"!conda install -c conda-forge geopy --yes\n",
"from geopy.geocoders import Nominatim\n",
"\n",
"import folium\n",
"\n",
"import requests\n",
"\n",
"from pandas.io.json import json_normalize\n",
"\n",
"import matplotlib.cm as cm\n",
"import matplotlib.colors as colors\n",
"\n",
"from sklearn.cluster import KMeans\n",
"\n",
"!pip install lxml\n",
"\n",
"print('All imported!')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Section 1: Web scraping Wikipedia HTML tables\n",
"\n",
"web site: https://en.wikipedia.org/wiki/List_of_postal_codes_of_Canada:_M"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>PostalCode</th>\n",
" <th>Borough</th>\n",
" <th>Neighborhood</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>M1A</td>\n",
" <td>Not assigned</td>\n",
" <td>Not assigned</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>M2A</td>\n",
" <td>Not assigned</td>\n",
" <td>Not assigned</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>M3A</td>\n",
" <td>North York</td>\n",
" <td>Parkwoods</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>M4A</td>\n",
" <td>North York</td>\n",
" <td>Victoria Village</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>M5A</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Harbourfront</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>282</th>\n",
" <td>M8Z</td>\n",
" <td>Etobicoke</td>\n",
" <td>Mimico NW</td>\n",
" </tr>\n",
" <tr>\n",
" <th>283</th>\n",
" <td>M8Z</td>\n",
" <td>Etobicoke</td>\n",
" <td>The Queensway West</td>\n",
" </tr>\n",
" <tr>\n",
" <th>284</th>\n",
" <td>M8Z</td>\n",
" <td>Etobicoke</td>\n",
" <td>Royal York South West</td>\n",
" </tr>\n",
" <tr>\n",
" <th>285</th>\n",
" <td>M8Z</td>\n",
" <td>Etobicoke</td>\n",
" <td>South of Bloor</td>\n",
" </tr>\n",
" <tr>\n",
" <th>286</th>\n",
" <td>M9Z</td>\n",
" <td>Not assigned</td>\n",
" <td>Not assigned</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>287 rows × 3 columns</p>\n",
"</div>"
],
"text/plain": [
" PostalCode Borough Neighborhood\n",
"0 M1A Not assigned Not assigned\n",
"1 M2A Not assigned Not assigned\n",
"2 M3A North York Parkwoods\n",
"3 M4A North York Victoria Village\n",
"4 M5A Downtown Toronto Harbourfront\n",
".. ... ... ...\n",
"282 M8Z Etobicoke Mimico NW\n",
"283 M8Z Etobicoke The Queensway West\n",
"284 M8Z Etobicoke Royal York South West\n",
"285 M8Z Etobicoke South of Bloor\n",
"286 M9Z Not assigned Not assigned\n",
"\n",
"[287 rows x 3 columns]"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Parsing the tables of the target webpage\n",
"data = pd.read_html('http://en.wikipedia.org/wiki/List_of_postal_codes_of_Canada:_M', header=0)\n",
"df = data[0]\n",
"\n",
"# Changing column names\n",
"df.columns = ['PostalCode', 'Borough', 'Neighborhood']\n",
"df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Section 2: Performing required operations"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>PostalCode</th>\n",
" <th>Borough</th>\n",
" <th>Neighborhood</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>M1B</td>\n",
" <td>Scarborough</td>\n",
" <td>Rouge, Malvern</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>M1C</td>\n",
" <td>Scarborough</td>\n",
" <td>Highland Creek, Rouge Hill, Port Union</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>M1E</td>\n",
" <td>Scarborough</td>\n",
" <td>Guildwood, Morningside, West Hill</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>M1G</td>\n",
" <td>Scarborough</td>\n",
" <td>Woburn</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>M1H</td>\n",
" <td>Scarborough</td>\n",
" <td>Cedarbrae</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>98</th>\n",
" <td>M9N</td>\n",
" <td>York</td>\n",
" <td>Weston</td>\n",
" </tr>\n",
" <tr>\n",
" <th>99</th>\n",
" <td>M9P</td>\n",
" <td>Etobicoke</td>\n",
" <td>Westmount</td>\n",
" </tr>\n",
" <tr>\n",
" <th>100</th>\n",
" <td>M9R</td>\n",
" <td>Etobicoke</td>\n",
" <td>Kingsview Village, Martin Grove Gardens, Richv...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>101</th>\n",
" <td>M9V</td>\n",
" <td>Etobicoke</td>\n",
" <td>Albion Gardens, Beaumond Heights, Humbergate, ...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>102</th>\n",
" <td>M9W</td>\n",
" <td>Etobicoke</td>\n",
" <td>Northwest</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>103 rows × 3 columns</p>\n",
"</div>"
],
"text/plain": [
" PostalCode Borough Neighborhood\n",
"0 M1B Scarborough Rouge, Malvern\n",
"1 M1C Scarborough Highland Creek, Rouge Hill, Port Union\n",
"2 M1E Scarborough Guildwood, Morningside, West Hill\n",
"3 M1G Scarborough Woburn\n",
"4 M1H Scarborough Cedarbrae\n",
".. ... ... ...\n",
"98 M9N York Weston\n",
"99 M9P Etobicoke Westmount\n",
"100 M9R Etobicoke Kingsview Village, Martin Grove Gardens, Richv...\n",
"101 M9V Etobicoke Albion Gardens, Beaumond Heights, Humbergate, ...\n",
"102 M9W Etobicoke Northwest\n",
"\n",
"[103 rows x 3 columns]"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Data cleaning per the instructions\n",
"df.drop(df[df.Borough == 'Not assigned'].index, inplace=True)\n",
"df.loc[df.Neighborhood == 'Not assigned', 'Neighborhood'] = df['Borough']\n",
"df.reset_index(drop=True, inplace=True)\n",
"df = df.groupby('PostalCode').agg({'Borough':'first','Neighborhood': ', '.join}).reset_index()\n",
"\n",
"df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Section 3: Verifying results"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Testing if grouping works, by comparing with table given in the instructions**"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>PostalCode</th>\n",
" <th>Borough</th>\n",
" <th>Neighborhood</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>101</th>\n",
" <td>M9V</td>\n",
" <td>Etobicoke</td>\n",
" <td>Albion Gardens, Beaumond Heights, Humbergate, ...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" PostalCode Borough Neighborhood\n",
"101 M9V Etobicoke Albion Gardens, Beaumond Heights, Humbergate, ..."
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.loc[df['PostalCode'] == 'M9V']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Printing number of rows of the resulting table**"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Final table has 103 rows.\n"
]
}
],
"source": [
"rows = df.shape\n",
"print('Final table has',df.shape[0], 'rows.')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Section 4: Adding coordinates"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Postal Code</th>\n",
" <th>Latitude</th>\n",
" <th>Longitude</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>M1B</td>\n",
" <td>43.806686</td>\n",
" <td>-79.194353</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>M1C</td>\n",
" <td>43.784535</td>\n",
" <td>-79.160497</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>M1E</td>\n",
" <td>43.763573</td>\n",
" <td>-79.188711</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>M1G</td>\n",
" <td>43.770992</td>\n",
" <td>-79.216917</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>M1H</td>\n",
" <td>43.773136</td>\n",
" <td>-79.239476</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Postal Code Latitude Longitude\n",
"0 M1B 43.806686 -79.194353\n",
"1 M1C 43.784535 -79.160497\n",
"2 M1E 43.763573 -79.188711\n",
"3 M1G 43.770992 -79.216917\n",
"4 M1H 43.773136 -79.239476"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# geocoder module is not working; using the csv file instead\n",
"# importing coordinates\n",
"coordinates = pd.DataFrame()\n",
"coordinates = pd.read_csv('Geospatial_Coordinates.csv',',')\n",
"\n",
"coordinates.head()"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>PostalCode</th>\n",
" <th>Borough</th>\n",
" <th>Neighborhood</th>\n",
" <th>Latitude</th>\n",
" <th>Longitude</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>M1B</td>\n",
" <td>Scarborough</td>\n",
" <td>Rouge, Malvern</td>\n",
" <td>43.806686</td>\n",
" <td>-79.194353</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>M1C</td>\n",
" <td>Scarborough</td>\n",
" <td>Highland Creek, Rouge Hill, Port Union</td>\n",
" <td>43.784535</td>\n",
" <td>-79.160497</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>M1E</td>\n",
" <td>Scarborough</td>\n",
" <td>Guildwood, Morningside, West Hill</td>\n",
" <td>43.763573</td>\n",
" <td>-79.188711</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>M1G</td>\n",
" <td>Scarborough</td>\n",
" <td>Woburn</td>\n",
" <td>43.770992</td>\n",
" <td>-79.216917</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>M1H</td>\n",
" <td>Scarborough</td>\n",
" <td>Cedarbrae</td>\n",
" <td>43.773136</td>\n",
" <td>-79.239476</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" PostalCode Borough Neighborhood Latitude \\\n",
"0 M1B Scarborough Rouge, Malvern 43.806686 \n",
"1 M1C Scarborough Highland Creek, Rouge Hill, Port Union 43.784535 \n",
"2 M1E Scarborough Guildwood, Morningside, West Hill 43.763573 \n",
"3 M1G Scarborough Woburn 43.770992 \n",
"4 M1H Scarborough Cedarbrae 43.773136 \n",
"\n",
" Longitude \n",
"0 -79.194353 \n",
"1 -79.160497 \n",
"2 -79.188711 \n",
"3 -79.216917 \n",
"4 -79.239476 "
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# populating original table with coordinates based on Postal Code\n",
"# renaiming columns in order to enable semaless merging\n",
"coordinates.columns = ['PostalCode','Latitude','Longitude']\n",
"# merging the two dataframes\n",
"df1 = pd.merge(df, coordinates, on=['PostalCode'])\n",
"df1.head()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(103, 5)"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df1.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Section 5: Visualising Toronto and its neighborhoods"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**First, I find the coordinates of Toronto and I define an instance of the geocoder**"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The geograpical coordinates of Toronto are 43.653963, -79.387207.\n"
]
}
],
"source": [
"address = 'Toronto, CA'\n",
"\n",
"geolocator = Nominatim(user_agent=\"toronto_explorer\")\n",
"location = geolocator.geocode(address)\n",
"latitude = location.latitude\n",
"longitude = location.longitude\n",
"print('The geograpical coordinates of Toronto are {}, {}.'.format(latitude, longitude))"
]
},
{
"cell_type": "code",
"execution_count": 10,
"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+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdnaXQuY29tL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9tYXN0ZXIvZm9saXVtL3RlbXBsYXRlcy9sZWFmbGV0LmF3ZXNvbWUucm90YXRlLmNzcyIvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogMTAwLjAlOwogICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgICAgICAgICAgdG9wOiAwLjAlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICA8L3N0eWxlPgogICAgICAgIAo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgICAgICAgICA8ZGl2IGNsYXNzPSJmb2xpdW0tbWFwIiBpZD0ibWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliIiA+PC9kaXY+CiAgICAgICAgCjwvYm9keT4KPHNjcmlwdD4gICAgCiAgICAKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGJvdW5kcyA9IG51bGw7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgdmFyIG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5YiA9IEwubWFwKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ21hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5YicsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7Y2VudGVyOiBbNDMuNjUzOTYzLC03OS4zODcyMDddLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgem9vbTogMTAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhCb3VuZHM6IGJvdW5kcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxheWVyczogW10sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JsZENvcHlKdW1wOiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyczogTC5DUlMuRVBTRzM4NTcKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciB0aWxlX2xheWVyXzQxYjc0OTRhOWE5MDQ0YTJiNzVmZDViNTg2NjUyYTc5ID0gTC50aWxlTGF5ZXIoCiAgICAgICAgICAgICAgICAnaHR0cHM6Ly97c30udGlsZS5vcGVuc3RyZWV0bWFwLm9yZy97en0ve3h9L3t5fS5wbmcnLAogICAgICAgICAgICAgICAgewogICJhdHRyaWJ1dGlvbiI6IG51bGwsCiAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICJtYXhab29tIjogMTgsCiAgIm1pblpvb20iOiAxLAogICJub1dyYXAiOiBmYWxzZSwKICAic3ViZG9tYWlucyI6ICJhYmMiCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81NmY2ZjdjODVjNjQ0NmJhOTQzYWM5YjczNjAyZjIzZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjgwNjY4NjI5OTk5OTk5NiwtNzkuMTk0MzUzNDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjc1YzIwZDJlNTBmNGQ2NmFiNzhmMzZkYjA4MmYxZDIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMTRmZWNlNGYyYzViNGQ0N2EwMGI5NjMyNmQ1Yjc4YjMgPSAkKCc8ZGl2IGlkPSJodG1sXzE0ZmVjZTRmMmM1YjRkNDdhMDBiOTYzMjZkNWI3OGIzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Sb3VnZSwgTWFsdmVybiwgU2NhcmJvcm91Z2g8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Y3NWMyMGQyZTUwZjRkNjZhYjc4ZjM2ZGIwODJmMWQyLnNldENvbnRlbnQoaHRtbF8xNGZlY2U0ZjJjNWI0ZDQ3YTAwYjk2MzI2ZDViNzhiMyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl81NmY2ZjdjODVjNjQ0NmJhOTQzYWM5YjczNjAyZjIzZC5iaW5kUG9wdXAocG9wdXBfZjc1YzIwZDJlNTBmNGQ2NmFiNzhmMzZkYjA4MmYxZDIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDBiNGRhY2M2ZDQzNDdmZmE5NTI0M2E5NDQyMWNmMmMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43ODQ1MzUxLC03OS4xNjA0OTcwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80ZjkwYTJmYzBhMjI0NDQ3OThkNDQyODNlNDEwZGQxZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zYWU2ODk4N2Y1OWE0NTAzYWMwZThmZmYzYzlkZjQ5YyA9ICQoJzxkaXYgaWQ9Imh0bWxfM2FlNjg5ODdmNTlhNDUwM2FjMGU4ZmZmM2M5ZGY0OWMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhpZ2hsYW5kIENyZWVrLCBSb3VnZSBIaWxsLCBQb3J0IFVuaW9uLCBTY2FyYm9yb3VnaDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNGY5MGEyZmMwYTIyNDQ0Nzk4ZDQ0MjgzZTQxMGRkMWYuc2V0Q29udGVudChodG1sXzNhZTY4OTg3ZjU5YTQ1MDNhYzBlOGZmZjNjOWRmNDljKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzQwYjRkYWNjNmQ0MzQ3ZmZhOTUyNDNhOTQ0MjFjZjJjLmJpbmRQb3B1cChwb3B1cF80ZjkwYTJmYzBhMjI0NDQ3OThkNDQyODNlNDEwZGQxZik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83OGJkZWJhNzliZjc0ZGUyYTEzNGE2ZDE0YjczZmNlOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc2MzU3MjYsLTc5LjE4ODcxMTVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjM2ZmJkZmIwYzdmNDY0MGE5ZDIxZjJmZDZjMTc2MTggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZTIyMGNkNTg2MzZiNDk3ZGJjNjE1ZTIzNGY0MjZkNjIgPSAkKCc8ZGl2IGlkPSJodG1sX2UyMjBjZDU4NjM2YjQ5N2RiYzYxNWUyMzRmNDI2ZDYyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5HdWlsZHdvb2QsIE1vcm5pbmdzaWRlLCBXZXN0IEhpbGwsIFNjYXJib3JvdWdoPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mMzZmYmRmYjBjN2Y0NjQwYTlkMjFmMmZkNmMxNzYxOC5zZXRDb250ZW50KGh0bWxfZTIyMGNkNTg2MzZiNDk3ZGJjNjE1ZTIzNGY0MjZkNjIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzhiZGViYTc5YmY3NGRlMmExMzRhNmQxNGI3M2ZjZTguYmluZFBvcHVwKHBvcHVwX2YzNmZiZGZiMGM3ZjQ2NDBhOWQyMWYyZmQ2YzE3NjE4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2IwNzU2NjY3YzcxYzRmYjNiZDU2ZDllNmVhZGQ1YWQzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzcwOTkyMSwtNzkuMjE2OTE3NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNTM5MjNhMGZiMzFlNGY2MjgyYzdiYWUwZTQ4Mjg2YTQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYzc4ZGU3NzNlNzAwNDY4ODg4ODdmZDQ1NDM3YjE0MzEgPSAkKCc8ZGl2IGlkPSJodG1sX2M3OGRlNzczZTcwMDQ2ODg4ODg3ZmQ0NTQzN2IxNDMxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Xb2J1cm4sIFNjYXJib3JvdWdoPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81MzkyM2EwZmIzMWU0ZjYyODJjN2JhZTBlNDgyODZhNC5zZXRDb250ZW50KGh0bWxfYzc4ZGU3NzNlNzAwNDY4ODg4ODdmZDQ1NDM3YjE0MzEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjA3NTY2NjdjNzFjNGZiM2JkNTZkOWU2ZWFkZDVhZDMuYmluZFBvcHVwKHBvcHVwXzUzOTIzYTBmYjMxZTRmNjI4MmM3YmFlMGU0ODI4NmE0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzA0YWFlMjE4Mzc0YjQ1ODViNGY0N2ZiNDNjYjVlODhkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzczMTM2LC03OS4yMzk0NzYwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84ZDRlNjZmZWE5MDA0NTk4Yjc3NjY0ZDg5MjA3YzYxNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hN2NmZDMxMzcyZGU0ODg3YjU3MjRiZTY4NGMwZTBhNSA9ICQoJzxkaXYgaWQ9Imh0bWxfYTdjZmQzMTM3MmRlNDg4N2I1NzI0YmU2ODRjMGUwYTUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNlZGFyYnJhZSwgU2NhcmJvcm91Z2g8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzhkNGU2NmZlYTkwMDQ1OThiNzc2NjRkODkyMDdjNjE0LnNldENvbnRlbnQoaHRtbF9hN2NmZDMxMzcyZGU0ODg3YjU3MjRiZTY4NGMwZTBhNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wNGFhZTIxODM3NGI0NTg1YjRmNDdmYjQzY2I1ZTg4ZC5iaW5kUG9wdXAocG9wdXBfOGQ0ZTY2ZmVhOTAwNDU5OGI3NzY2NGQ4OTIwN2M2MTQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOWQ5YWQwZjNkYzhiNGQwNjg0YjU5NTJjN2MyOWYyMmIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NDQ3MzQyLC03OS4yMzk0NzYwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85YjMzZGIyZjJiM2M0NWRjYjAzNzQwODFhZWQxMjIxZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hMGQ1ZDEzNzNkOWM0YWMwYjZlZWFmZTFmMTQwYzM2MCA9ICQoJzxkaXYgaWQ9Imh0bWxfYTBkNWQxMzczZDljNGFjMGI2ZWVhZmUxZjE0MGMzNjAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlNjYXJib3JvdWdoIFZpbGxhZ2UsIFNjYXJib3JvdWdoPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85YjMzZGIyZjJiM2M0NWRjYjAzNzQwODFhZWQxMjIxZi5zZXRDb250ZW50KGh0bWxfYTBkNWQxMzczZDljNGFjMGI2ZWVhZmUxZjE0MGMzNjApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOWQ5YWQwZjNkYzhiNGQwNjg0YjU5NTJjN2MyOWYyMmIuYmluZFBvcHVwKHBvcHVwXzliMzNkYjJmMmIzYzQ1ZGNiMDM3NDA4MWFlZDEyMjFmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzhiNTNmMWY0Y2Q1ZDQxYjdiM2U3ZDI4YjJiMDUzNzVhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzI3OTI5MiwtNzkuMjYyMDI5NDAwMDAwMDJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfM2RlY2Y2MGRhMTY2NDZmM2JiMTNjMTZkMDYxMmMxZGUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOTMwOTY5Y2FjNTU3NGU0YTgyNTk4NzI2YzJiY2Y1YTIgPSAkKCc8ZGl2IGlkPSJodG1sXzkzMDk2OWNhYzU1NzRlNGE4MjU5ODcyNmMyYmNmNWEyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FYXN0IEJpcmNobW91bnQgUGFyaywgSW9udmlldywgS2VubmVkeSBQYXJrLCBTY2FyYm9yb3VnaDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfM2RlY2Y2MGRhMTY2NDZmM2JiMTNjMTZkMDYxMmMxZGUuc2V0Q29udGVudChodG1sXzkzMDk2OWNhYzU1NzRlNGE4MjU5ODcyNmMyYmNmNWEyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzhiNTNmMWY0Y2Q1ZDQxYjdiM2U3ZDI4YjJiMDUzNzVhLmJpbmRQb3B1cChwb3B1cF8zZGVjZjYwZGExNjY0NmYzYmIxM2MxNmQwNjEyYzFkZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84NjkxMzcwMjE2M2E0NjcxOTljOTMwYTAyZWE3ZTM3NyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcxMTExMTcwMDAwMDAwNCwtNzkuMjg0NTc3Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lNDIxMjlhMDE2NDc0NjA0OTQ3NjYwYjBjYzQwMzQzNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iN2JhMGEwOTliNDU0ODkwODI3MGVmMzExOGZlOGZhOCA9ICQoJzxkaXYgaWQ9Imh0bWxfYjdiYTBhMDk5YjQ1NDg5MDgyNzBlZjMxMThmZThmYTgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNsYWlybGVhLCBHb2xkZW4gTWlsZSwgT2FrcmlkZ2UsIFNjYXJib3JvdWdoPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lNDIxMjlhMDE2NDc0NjA0OTQ3NjYwYjBjYzQwMzQzNC5zZXRDb250ZW50KGh0bWxfYjdiYTBhMDk5YjQ1NDg5MDgyNzBlZjMxMThmZThmYTgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODY5MTM3MDIxNjNhNDY3MTk5YzkzMGEwMmVhN2UzNzcuYmluZFBvcHVwKHBvcHVwX2U0MjEyOWEwMTY0NzQ2MDQ5NDc2NjBiMGNjNDAzNDM0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzVhNjYzMTg2OWUxZTRlZDRiYTM2ODdmMzk2NmRkYzNlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzE2MzE2LC03OS4yMzk0NzYwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80Yjg5ZWVjYWMzM2U0NTdkODQ3OTRiZGEzZjBhYjczMyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lMWRmNzA2MjE2MmE0ZjY4OGNlNjMwYzdmNzBiMTJlOCA9ICQoJzxkaXYgaWQ9Imh0bWxfZTFkZjcwNjIxNjJhNGY2ODhjZTYzMGM3ZjcwYjEyZTgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNsaWZmY3Jlc3QsIENsaWZmc2lkZSwgU2NhcmJvcm91Z2ggVmlsbGFnZSBXZXN0LCBTY2FyYm9yb3VnaDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNGI4OWVlY2FjMzNlNDU3ZDg0Nzk0YmRhM2YwYWI3MzMuc2V0Q29udGVudChodG1sX2UxZGY3MDYyMTYyYTRmNjg4Y2U2MzBjN2Y3MGIxMmU4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzVhNjYzMTg2OWUxZTRlZDRiYTM2ODdmMzk2NmRkYzNlLmJpbmRQb3B1cChwb3B1cF80Yjg5ZWVjYWMzM2U0NTdkODQ3OTRiZGEzZjBhYjczMyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wNTU1NDk4NTU0NDg0ZjgzYTFkNWQzYThhMWZhN2U2YyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY5MjY1NzAwMDAwMDAwNCwtNzkuMjY0ODQ4MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81YTE4M2ViODBiOTI0MjZkYmFlMGRlN2RjMDIxNTk5NyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80MWQyZmFkNzUwNzg0ZGNhOGVlNTU2NTA1MjBjZTAxNiA9ICQoJzxkaXYgaWQ9Imh0bWxfNDFkMmZhZDc1MDc4NGRjYThlZTU1NjUwNTIwY2UwMTYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJpcmNoIENsaWZmLCBDbGlmZnNpZGUgV2VzdCwgU2NhcmJvcm91Z2g8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzVhMTgzZWI4MGI5MjQyNmRiYWUwZGU3ZGMwMjE1OTk3LnNldENvbnRlbnQoaHRtbF80MWQyZmFkNzUwNzg0ZGNhOGVlNTU2NTA1MjBjZTAxNik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wNTU1NDk4NTU0NDg0ZjgzYTFkNWQzYThhMWZhN2U2Yy5iaW5kUG9wdXAocG9wdXBfNWExODNlYjgwYjkyNDI2ZGJhZTBkZTdkYzAyMTU5OTcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZWQ5ZTViZTg2OGQ5NDZjYWFjODI5ZWU1ODAwMGQ1MTQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NTc0MDk2LC03OS4yNzMzMDQwMDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lNWU3YTYyMmQ2ODI0MTdkODQ5MTM3NDdmYzRkZmUwOSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jYzFkY2I4OThkMTg0OTJiYTdiNThjODc4ZmQyN2QwZCA9ICQoJzxkaXYgaWQ9Imh0bWxfY2MxZGNiODk4ZDE4NDkyYmE3YjU4Yzg3OGZkMjdkMGQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvcnNldCBQYXJrLCBTY2FyYm9yb3VnaCBUb3duIENlbnRyZSwgV2V4Zm9yZCBIZWlnaHRzLCBTY2FyYm9yb3VnaDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZTVlN2E2MjJkNjgyNDE3ZDg0OTEzNzQ3ZmM0ZGZlMDkuc2V0Q29udGVudChodG1sX2NjMWRjYjg5OGQxODQ5MmJhN2I1OGM4NzhmZDI3ZDBkKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2VkOWU1YmU4NjhkOTQ2Y2FhYzgyOWVlNTgwMDBkNTE0LmJpbmRQb3B1cChwb3B1cF9lNWU3YTYyMmQ2ODI0MTdkODQ5MTM3NDdmYzRkZmUwOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kMDg4NTQwNDdlZjI0MThlYmJiYmU5YjRhNjlmY2Q5NSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc1MDA3MTUwMDAwMDAwNCwtNzkuMjk1ODQ5MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85NWRjNzQwYTFjNjI0OGU5OWM0OTI3M2ZlNTAzNGFhNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mNGZjMTVjZjJmYTc0ZWU1OTk5YmMwMmY4ZTFhNzZiYiA9ICQoJzxkaXYgaWQ9Imh0bWxfZjRmYzE1Y2YyZmE3NGVlNTk5OWJjMDJmOGUxYTc2YmIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1hcnl2YWxlLCBXZXhmb3JkLCBTY2FyYm9yb3VnaDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOTVkYzc0MGExYzYyNDhlOTljNDkyNzNmZTUwMzRhYTcuc2V0Q29udGVudChodG1sX2Y0ZmMxNWNmMmZhNzRlZTU5OTliYzAyZjhlMWE3NmJiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2QwODg1NDA0N2VmMjQxOGViYmJiZTliNGE2OWZjZDk1LmJpbmRQb3B1cChwb3B1cF85NWRjNzQwYTFjNjI0OGU5OWM0OTI3M2ZlNTAzNGFhNyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yODA1MWRiZDJiN2M0ZTAyYTNlNDZjZDY5NThmZTZjZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc5NDIwMDMsLTc5LjI2MjAyOTQwMDAwMDAyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzA0MTc4YTRmMGE1YjRkNjc4YTZlMDIzMDU0MzA4YWI4ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2I0M2JjODY3NWRkNDQ0N2RiMDI3NzVjYjExZDVhYjMyID0gJCgnPGRpdiBpZD0iaHRtbF9iNDNiYzg2NzVkZDQ0NDdkYjAyNzc1Y2IxMWQ1YWIzMiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QWdpbmNvdXJ0LCBTY2FyYm9yb3VnaDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDQxNzhhNGYwYTViNGQ2NzhhNmUwMjMwNTQzMDhhYjguc2V0Q29udGVudChodG1sX2I0M2JjODY3NWRkNDQ0N2RiMDI3NzVjYjExZDVhYjMyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzI4MDUxZGJkMmI3YzRlMDJhM2U0NmNkNjk1OGZlNmNkLmJpbmRQb3B1cChwb3B1cF8wNDE3OGE0ZjBhNWI0ZDY3OGE2ZTAyMzA1NDMwOGFiOCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wZjAzY2ZkM2MwNmI0N2I4YTAzMzQ4NTBhMjJjNTRmZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc4MTYzNzUsLTc5LjMwNDMwMjFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMjdhMTEwMTZmMzdkNGUxYmIyMWZkNTBiZWZiODVhMWMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOGYxMTU2ODA3MTI0NDFjZGI2MTM0NzUyYmNjMWFlZTIgPSAkKCc8ZGl2IGlkPSJodG1sXzhmMTE1NjgwNzEyNDQxY2RiNjEzNDc1MmJjYzFhZWUyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DbGFya3MgQ29ybmVycywgU3VsbGl2YW4sIFRhbSBPJiMzOTtTaGFudGVyLCBTY2FyYm9yb3VnaDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjdhMTEwMTZmMzdkNGUxYmIyMWZkNTBiZWZiODVhMWMuc2V0Q29udGVudChodG1sXzhmMTE1NjgwNzEyNDQxY2RiNjEzNDc1MmJjYzFhZWUyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzBmMDNjZmQzYzA2YjQ3YjhhMDMzNDg1MGEyMmM1NGZkLmJpbmRQb3B1cChwb3B1cF8yN2ExMTAxNmYzN2Q0ZTFiYjIxZmQ1MGJlZmI4NWExYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80ZTU5MmQzNWYzYTE0MGEzODliMDIxYTkxNDU5MmQxYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjgxNTI1MjIsLTc5LjI4NDU3NzJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZTg2Y2Y2MmY2YzY4NDljNjliNDYyMzdkNmRmZjAyMmUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzE5OWU0ZmEwZjcwNGZhNDg5MTg5YzVlMjJjOTBjN2IgPSAkKCc8ZGl2IGlkPSJodG1sXzcxOTllNGZhMGY3MDRmYTQ4OTE4OWM1ZTIyYzkwYzdiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5BZ2luY291cnQgTm9ydGgsIEwmIzM5O0Ftb3JlYXV4IEVhc3QsIE1pbGxpa2VuLCBTdGVlbGVzIEVhc3QsIFNjYXJib3JvdWdoPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lODZjZjYyZjZjNjg0OWM2OWI0NjIzN2Q2ZGZmMDIyZS5zZXRDb250ZW50KGh0bWxfNzE5OWU0ZmEwZjcwNGZhNDg5MTg5YzVlMjJjOTBjN2IpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNGU1OTJkMzVmM2ExNDBhMzg5YjAyMWE5MTQ1OTJkMWIuYmluZFBvcHVwKHBvcHVwX2U4NmNmNjJmNmM2ODQ5YzY5YjQ2MjM3ZDZkZmYwMjJlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2JlNDY2ZjUwYTQzYjQ3ZTE5NzYyYjNiYWNhMjZiYmIzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzk5NTI1MjAwMDAwMDA1LC03OS4zMTgzODg3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzRmZjAwMDg1OWU0YzQxZDhiMjA4ZmUzMjYxZTIwMTQ2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzM5ODJmZGRiNzQ5NTQ0ZmQ4YTgwMTQ5ZWVmZDVhNzM3ID0gJCgnPGRpdiBpZD0iaHRtbF8zOTgyZmRkYjc0OTU0NGZkOGE4MDE0OWVlZmQ1YTczNyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TCYjMzk7QW1vcmVhdXggV2VzdCwgU2NhcmJvcm91Z2g8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzRmZjAwMDg1OWU0YzQxZDhiMjA4ZmUzMjYxZTIwMTQ2LnNldENvbnRlbnQoaHRtbF8zOTgyZmRkYjc0OTU0NGZkOGE4MDE0OWVlZmQ1YTczNyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9iZTQ2NmY1MGE0M2I0N2UxOTc2MmIzYmFjYTI2YmJiMy5iaW5kUG9wdXAocG9wdXBfNGZmMDAwODU5ZTRjNDFkOGIyMDhmZTMyNjFlMjAxNDYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMGFmYjcxNGUwMDM2NGUxZmFhNjlkNjRlZjFkNjIwOWIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My44MzYxMjQ3MDAwMDAwMDYsLTc5LjIwNTYzNjA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2I4Mjc0YzBlMmYwZDRkOGM4NDE2MWU4YjI5ZWVhODEzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2IzYmQ0MWMyNmViZTQwYTk4YjQyMjczNzIzNTVmYjhhID0gJCgnPGRpdiBpZD0iaHRtbF9iM2JkNDFjMjZlYmU0MGE5OGI0MjI3MzcyMzU1ZmI4YSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VXBwZXIgUm91Z2UsIFNjYXJib3JvdWdoPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iODI3NGMwZTJmMGQ0ZDhjODQxNjFlOGIyOWVlYTgxMy5zZXRDb250ZW50KGh0bWxfYjNiZDQxYzI2ZWJlNDBhOThiNDIyNzM3MjM1NWZiOGEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMGFmYjcxNGUwMDM2NGUxZmFhNjlkNjRlZjFkNjIwOWIuYmluZFBvcHVwKHBvcHVwX2I4Mjc0YzBlMmYwZDRkOGM4NDE2MWU4YjI5ZWVhODEzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2FjOTI1NDdjMzAzMjQwMmZiZjEyOTY5YmMwYjNlODgyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuODAzNzYyMiwtNzkuMzYzNDUxN10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mNmYyMDRmNWVjNGY0NjA0YmIwOTAxNGY0MGJlMmYwZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80NWJkNThiYzdlZTA0YzdjYjQwZWNiMTQ4MWU0NzdhZCA9ICQoJzxkaXYgaWQ9Imh0bWxfNDViZDU4YmM3ZWUwNGM3Y2I0MGVjYjE0ODFlNDc3YWQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhpbGxjcmVzdCBWaWxsYWdlLCBOb3J0aCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mNmYyMDRmNWVjNGY0NjA0YmIwOTAxNGY0MGJlMmYwZS5zZXRDb250ZW50KGh0bWxfNDViZDU4YmM3ZWUwNGM3Y2I0MGVjYjE0ODFlNDc3YWQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYWM5MjU0N2MzMDMyNDAyZmJmMTI5NjliYzBiM2U4ODIuYmluZFBvcHVwKHBvcHVwX2Y2ZjIwNGY1ZWM0ZjQ2MDRiYjA5MDE0ZjQwYmUyZjBlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzI5ODg0N2E3N2NkODQ1MDM4MjNiZWQ2NDliNmY1NzVlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzc4NTE3NSwtNzkuMzQ2NTU1N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85MmI0MjE3ZTk0YTU0ZWRlYWFhNzU4ZjM4OWY5MzBmZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mNGI3MzI2YWJmMzM0MTI2ODc0ZDhjNDEzNzMyYjA2MSA9ICQoJzxkaXYgaWQ9Imh0bWxfZjRiNzMyNmFiZjMzNDEyNjg3NGQ4YzQxMzczMmIwNjEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZhaXJ2aWV3LCBIZW5yeSBGYXJtLCBPcmlvbGUsIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzkyYjQyMTdlOTRhNTRlZGVhYWE3NThmMzg5ZjkzMGZmLnNldENvbnRlbnQoaHRtbF9mNGI3MzI2YWJmMzM0MTI2ODc0ZDhjNDEzNzMyYjA2MSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yOTg4NDdhNzdjZDg0NTAzODIzYmVkNjQ5YjZmNTc1ZS5iaW5kUG9wdXAocG9wdXBfOTJiNDIxN2U5NGE1NGVkZWFhYTc1OGYzODlmOTMwZmYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZTk5NjliNDI1NTJhNGEzYmFiMjcyNzJlOGZjZTAyOGIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43ODY5NDczLC03OS4zODU5NzVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMjI0NTg5MDljMjIzNDFkYThkYjBkM2U1ZTk2MDQxZGYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOTVhOTE4MWZmYmVjNGZhYmE1YWM5MTRiMGU5ZjhlZWMgPSAkKCc8ZGl2IGlkPSJodG1sXzk1YTkxODFmZmJlYzRmYWJhNWFjOTE0YjBlOWY4ZWVjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CYXl2aWV3IFZpbGxhZ2UsIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzIyNDU4OTA5YzIyMzQxZGE4ZGIwZDNlNWU5NjA0MWRmLnNldENvbnRlbnQoaHRtbF85NWE5MTgxZmZiZWM0ZmFiYTVhYzkxNGIwZTlmOGVlYyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9lOTk2OWI0MjU1MmE0YTNiYWIyNzI3MmU4ZmNlMDI4Yi5iaW5kUG9wdXAocG9wdXBfMjI0NTg5MDljMjIzNDFkYThkYjBkM2U1ZTk2MDQxZGYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMTBkZjI3ZmJiYzBmNDJlODljZmQ4NThhY2VhNDZhYTkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NTc0OTAyLC03OS4zNzQ3MTQwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84ZTdiZjUwYTAwOTI0ZTlkYTYzMGU0OTRmNmUxYjE5ZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jNjAzZGM1OGQyZDQ0ZmI3YjdjZWE0YzcxODllZTc3MiA9ICQoJzxkaXYgaWQ9Imh0bWxfYzYwM2RjNThkMmQ0NGZiN2I3Y2VhNGM3MTg5ZWU3NzIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlNpbHZlciBIaWxscywgWW9yayBNaWxscywgTm9ydGggWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOGU3YmY1MGEwMDkyNGU5ZGE2MzBlNDk0ZjZlMWIxOWQuc2V0Q29udGVudChodG1sX2M2MDNkYzU4ZDJkNDRmYjdiN2NlYTRjNzE4OWVlNzcyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzEwZGYyN2ZiYmMwZjQyZTg5Y2ZkODU4YWNlYTQ2YWE5LmJpbmRQb3B1cChwb3B1cF84ZTdiZjUwYTAwOTI0ZTlkYTYzMGU0OTRmNmUxYjE5ZCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xYWE4ZjQ3OGI5MzM0MjViOTM0NTNjNmExMzFkZjE3ZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc4OTA1MywtNzkuNDA4NDkyNzk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMWZjYjA2NGY1ZjliNDdiMjkyYWNiZmVhMTI5ZDZmYWMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZTlhZWQzYzFhZTM1NGU0NjkwYTQzNDNmMWQ0Y2QwYjEgPSAkKCc8ZGl2IGlkPSJodG1sX2U5YWVkM2MxYWUzNTRlNDY5MGE0MzQzZjFkNGNkMGIxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5OZXd0b25icm9vaywgV2lsbG93ZGFsZSwgTm9ydGggWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMWZjYjA2NGY1ZjliNDdiMjkyYWNiZmVhMTI5ZDZmYWMuc2V0Q29udGVudChodG1sX2U5YWVkM2MxYWUzNTRlNDY5MGE0MzQzZjFkNGNkMGIxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzFhYThmNDc4YjkzMzQyNWI5MzQ1M2M2YTEzMWRmMTdmLmJpbmRQb3B1cChwb3B1cF8xZmNiMDY0ZjVmOWI0N2IyOTJhY2JmZWExMjlkNmZhYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81OTkzMDhiMjAwNmM0NTFmYjZiMTI3NDgwNTI5NGMzMyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc3MDExOTksLTc5LjQwODQ5Mjc5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RhYTZmNmRhMmI0NTQ3MDBiYjRiOGE5NjFmMWIyNDg0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzMyN2U0M2JiMGU3NTQ0MWE5MGZhOTM4MDNlNzkzNzMyID0gJCgnPGRpdiBpZD0iaHRtbF8zMjdlNDNiYjBlNzU0NDFhOTBmYTkzODAzZTc5MzczMiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2lsbG93ZGFsZSBTb3V0aCwgTm9ydGggWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZGFhNmY2ZGEyYjQ1NDcwMGJiNGI4YTk2MWYxYjI0ODQuc2V0Q29udGVudChodG1sXzMyN2U0M2JiMGU3NTQ0MWE5MGZhOTM4MDNlNzkzNzMyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU5OTMwOGIyMDA2YzQ1MWZiNmIxMjc0ODA1Mjk0YzMzLmJpbmRQb3B1cChwb3B1cF9kYWE2ZjZkYTJiNDU0NzAwYmI0YjhhOTYxZjFiMjQ4NCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lNGUzNjQ2ODNkOGU0Yjg3YWMxZjMxNWRlMTk1OWUyZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc1Mjc1ODI5OTk5OTk5NiwtNzkuNDAwMDQ5M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9hZGJkMDBhYjRmNjk0ZjY1YTM3OTAwNDRhYTgxMzNhMSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iNzZlMjc4ZDViM2M0MWJhOTc4MTJjZmM5NzY3YTg4OCA9ICQoJzxkaXYgaWQ9Imh0bWxfYjc2ZTI3OGQ1YjNjNDFiYTk3ODEyY2ZjOTc2N2E4ODgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPllvcmsgTWlsbHMgV2VzdCwgTm9ydGggWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYWRiZDAwYWI0ZjY5NGY2NWEzNzkwMDQ0YWE4MTMzYTEuc2V0Q29udGVudChodG1sX2I3NmUyNzhkNWIzYzQxYmE5NzgxMmNmYzk3NjdhODg4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2U0ZTM2NDY4M2Q4ZTRiODdhYzFmMzE1ZGUxOTU5ZTJmLmJpbmRQb3B1cChwb3B1cF9hZGJkMDBhYjRmNjk0ZjY1YTM3OTAwNDRhYTgxMzNhMSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hZmEwMmIwZDU1OGU0NjI0YTkwMDRjNTViMzA4OGMzNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc4MjczNjQsLTc5LjQ0MjI1OTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOTdkZTI1YTY4ZTgzNGJhNmE3M2E4ZjhkMGE5NTQzZGQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjlhNTQ1YmY5NWZkNGM0ZTlkYzUxNjhlNWRmMDQyMzYgPSAkKCc8ZGl2IGlkPSJodG1sX2Y5YTU0NWJmOTVmZDRjNGU5ZGM1MTY4ZTVkZjA0MjM2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XaWxsb3dkYWxlIFdlc3QsIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzk3ZGUyNWE2OGU4MzRiYTZhNzNhOGY4ZDBhOTU0M2RkLnNldENvbnRlbnQoaHRtbF9mOWE1NDViZjk1ZmQ0YzRlOWRjNTE2OGU1ZGYwNDIzNik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hZmEwMmIwZDU1OGU0NjI0YTkwMDRjNTViMzA4OGMzNS5iaW5kUG9wdXAocG9wdXBfOTdkZTI1YTY4ZTgzNGJhNmE3M2E4ZjhkMGE5NTQzZGQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOWQ0MDc5ZjYzZGU3NDUwYWEzZGQ4NTNhOTVmOTQ3OTYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NTMyNTg2LC03OS4zMjk2NTY1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzhkMDY5NjM5M2RjNDRhOWVhNGI1OTk5NGExZjVkZTBhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzViMTYzNjAzNDNjYzQ2NmNhOWJhZWNlNmI0YTkzZGQ2ID0gJCgnPGRpdiBpZD0iaHRtbF81YjE2MzYwMzQzY2M0NjZjYTliYWVjZTZiNGE5M2RkNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UGFya3dvb2RzLCBOb3J0aCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84ZDA2OTYzOTNkYzQ0YTllYTRiNTk5OTRhMWY1ZGUwYS5zZXRDb250ZW50KGh0bWxfNWIxNjM2MDM0M2NjNDY2Y2E5YmFlY2U2YjRhOTNkZDYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOWQ0MDc5ZjYzZGU3NDUwYWEzZGQ4NTNhOTVmOTQ3OTYuYmluZFBvcHVwKHBvcHVwXzhkMDY5NjM5M2RjNDRhOWVhNGI1OTk5NGExZjVkZTBhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzc3Mzg0YThjNzk4MjQ5NWFhZTQ2NTIyNjlkYTIwZGIwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzQ1OTA1Nzk5OTk5OTk2LC03OS4zNTIxODhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfODU0NmVjYzIyYjI0NGM1OWJmNDc4ZjhjMWRmZTU3OTAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYzg5YjdkMzk5NjdhNDM4NmIwZTFkNDU5MWMxZTgxNTQgPSAkKCc8ZGl2IGlkPSJodG1sX2M4OWI3ZDM5OTY3YTQzODZiMGUxZDQ1OTFjMWU4MTU0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Eb24gTWlsbHMgTm9ydGgsIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzg1NDZlY2MyMmIyNDRjNTliZjQ3OGY4YzFkZmU1NzkwLnNldENvbnRlbnQoaHRtbF9jODliN2QzOTk2N2E0Mzg2YjBlMWQ0NTkxYzFlODE1NCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83NzM4NGE4Yzc5ODI0OTVhYWU0NjUyMjY5ZGEyMGRiMC5iaW5kUG9wdXAocG9wdXBfODU0NmVjYzIyYjI0NGM1OWJmNDc4ZjhjMWRmZTU3OTApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZTI2ZGU4YTQ3ZDViNGRiOTlmYWNmNTVjYTg0Y2YzZmYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MjU4OTk3MDAwMDAwMSwtNzkuMzQwOTIzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2E1YzA5MzI2NjE1ZDQzMzU5MWZhZDZhMmRiMzM0ZTY3ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzg3YTEwZjIyZGY5ZDQ3NGViNWY4YmI4ODJmM2U0ZTNiID0gJCgnPGRpdiBpZD0iaHRtbF84N2ExMGYyMmRmOWQ0NzRlYjVmOGJiODgyZjNlNGUzYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RmxlbWluZ2RvbiBQYXJrLCBEb24gTWlsbHMgU291dGgsIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2E1YzA5MzI2NjE1ZDQzMzU5MWZhZDZhMmRiMzM0ZTY3LnNldENvbnRlbnQoaHRtbF84N2ExMGYyMmRmOWQ0NzRlYjVmOGJiODgyZjNlNGUzYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9lMjZkZThhNDdkNWI0ZGI5OWZhY2Y1NWNhODRjZjNmZi5iaW5kUG9wdXAocG9wdXBfYTVjMDkzMjY2MTVkNDMzNTkxZmFkNmEyZGIzMzRlNjcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMzM1ZDA1MDlkODQ5NDAzMmFkMTdkYjllMWFkZjI2MmUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NTQzMjgzLC03OS40NDIyNTkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RkN2U2MTA5ZDdhNDRlNjhiOGZlMGM4YTJmZjFjMTRkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2M3MTg3ZGI3NTliNjRkNWU5NzE3YzNiNTQ1NzZmMzk4ID0gJCgnPGRpdiBpZD0iaHRtbF9jNzE4N2RiNzU5YjY0ZDVlOTcxN2MzYjU0NTc2ZjM5OCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmF0aHVyc3QgTWFub3IsIERvd25zdmlldyBOb3J0aCwgV2lsc29uIEhlaWdodHMsIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2RkN2U2MTA5ZDdhNDRlNjhiOGZlMGM4YTJmZjFjMTRkLnNldENvbnRlbnQoaHRtbF9jNzE4N2RiNzU5YjY0ZDVlOTcxN2MzYjU0NTc2ZjM5OCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zMzVkMDUwOWQ4NDk0MDMyYWQxN2RiOWUxYWRmMjYyZS5iaW5kUG9wdXAocG9wdXBfZGQ3ZTYxMDlkN2E0NGU2OGI4ZmUwYzhhMmZmMWMxNGQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNjgzNDBjZmM0ZDE5NDUzOGIxZmZiODg5ZGFlYWIxMGQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43Njc5ODAzLC03OS40ODcyNjE5MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kNDY3NDE4ZWFhNTM0ZDU0YTg1MTU4YTI1MjRiNDRhOCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8yN2RkMTE4OTRjY2M0MDc1YTUzYzBiZTJhZDgxOTMxMCA9ICQoJzxkaXYgaWQ9Imh0bWxfMjdkZDExODk0Y2NjNDA3NWE1M2MwYmUyYWQ4MTkzMTAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5vcnRod29vZCBQYXJrLCBZb3JrIFVuaXZlcnNpdHksIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Q0Njc0MThlYWE1MzRkNTRhODUxNThhMjUyNGI0NGE4LnNldENvbnRlbnQoaHRtbF8yN2RkMTE4OTRjY2M0MDc1YTUzYzBiZTJhZDgxOTMxMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82ODM0MGNmYzRkMTk0NTM4YjFmZmI4ODlkYWVhYjEwZC5iaW5kUG9wdXAocG9wdXBfZDQ2NzQxOGVhYTUzNGQ1NGE4NTE1OGEyNTI0YjQ0YTgpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNGNjODFiYzIzYzQwNDg2YmI5YjA1YzRkMGZhZWIzZTEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43Mzc0NzMyMDAwMDAwMDQsLTc5LjQ2NDc2MzI5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2Q0NjVhNzkxZmU0MDRhNTk5MDE1YWUyMjI1ODA3MTFlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzQzNzlhYWRkNWI5ZjQ1Yzk5M2ExZjZlOTdhM2VhMzg5ID0gJCgnPGRpdiBpZD0iaHRtbF80Mzc5YWFkZDViOWY0NWM5OTNhMWY2ZTk3YTNlYTM4OSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q0ZCIFRvcm9udG8sIERvd25zdmlldyBFYXN0LCBOb3J0aCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9kNDY1YTc5MWZlNDA0YTU5OTAxNWFlMjIyNTgwNzExZS5zZXRDb250ZW50KGh0bWxfNDM3OWFhZGQ1YjlmNDVjOTkzYTFmNmU5N2EzZWEzODkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNGNjODFiYzIzYzQwNDg2YmI5YjA1YzRkMGZhZWIzZTEuYmluZFBvcHVwKHBvcHVwX2Q0NjVhNzkxZmU0MDRhNTk5MDE1YWUyMjI1ODA3MTFlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQ3Y2JiNGY2ZWQ2ZjQ4NmZhZjNmMjZhOTNiYTlmOWEwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzM5MDE0NiwtNzkuNTA2OTQzNl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82NDQ0OTc5NzQ1MDA0MzI3OWRmZTkzNzAxNDNlMGQ3YSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hMTY3MmQ1ZGY2YWU0MTZiYWE3MzIzMjg0ZTAwM2M0MyA9ICQoJzxkaXYgaWQ9Imh0bWxfYTE2NzJkNWRmNmFlNDE2YmFhNzMyMzI4NGUwMDNjNDMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvd25zdmlldyBXZXN0LCBOb3J0aCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82NDQ0OTc5NzQ1MDA0MzI3OWRmZTkzNzAxNDNlMGQ3YS5zZXRDb250ZW50KGh0bWxfYTE2NzJkNWRmNmFlNDE2YmFhNzMyMzI4NGUwMDNjNDMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDdjYmI0ZjZlZDZmNDg2ZmFmM2YyNmE5M2JhOWY5YTAuYmluZFBvcHVwKHBvcHVwXzY0NDQ5Nzk3NDUwMDQzMjc5ZGZlOTM3MDE0M2UwZDdhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2NlMTUwMTA1NmY1OTQ0ZDQ4ZGQ2OWEyMDQ5ZmU3NTQ0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzI4NDk2NCwtNzkuNDk1Njk3NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNDY2ZTZkNDcxMDE3NGI5MjgwMGUyNDQyM2Q5ZTkxY2UgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYmExOTAwNWY5MmEyNDgyMWJiYTZmYjJiODhjNjAxZjYgPSAkKCc8ZGl2IGlkPSJodG1sX2JhMTkwMDVmOTJhMjQ4MjFiYmE2ZmIyYjg4YzYwMWY2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Eb3duc3ZpZXcgQ2VudHJhbCwgTm9ydGggWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNDY2ZTZkNDcxMDE3NGI5MjgwMGUyNDQyM2Q5ZTkxY2Uuc2V0Q29udGVudChodG1sX2JhMTkwMDVmOTJhMjQ4MjFiYmE2ZmIyYjg4YzYwMWY2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2NlMTUwMTA1NmY1OTQ0ZDQ4ZGQ2OWEyMDQ5ZmU3NTQ0LmJpbmRQb3B1cChwb3B1cF80NjZlNmQ0NzEwMTc0YjkyODAwZTI0NDIzZDllOTFjZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83NjJiZDhiMzcxZTU0MWYyOTEwYTNmZjgyN2U3MjU1NCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc2MTYzMTMsLTc5LjUyMDk5OTQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzIyMjk4ZGU0NGE1NjQ4ZTVhNGI3OTYyNTllZjUxYjE2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzkxMTMyNzVmMGY0NTRlZjFhZDczMjBiYWVmMTU2MWI2ID0gJCgnPGRpdiBpZD0iaHRtbF85MTEzMjc1ZjBmNDU0ZWYxYWQ3MzIwYmFlZjE1NjFiNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RG93bnN2aWV3IE5vcnRod2VzdCwgTm9ydGggWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjIyOThkZTQ0YTU2NDhlNWE0Yjc5NjI1OWVmNTFiMTYuc2V0Q29udGVudChodG1sXzkxMTMyNzVmMGY0NTRlZjFhZDczMjBiYWVmMTU2MWI2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzc2MmJkOGIzNzFlNTQxZjI5MTBhM2ZmODI3ZTcyNTU0LmJpbmRQb3B1cChwb3B1cF8yMjI5OGRlNDRhNTY0OGU1YTRiNzk2MjU5ZWY1MWIxNik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mYWQ2N2QyOTU2ZTE0NjU5OGZhOGVhZjU3YjI0N2Q2MSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcyNTg4MjI5OTk5OTk5NSwtNzkuMzE1NTcxNTk5OTk5OThdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZTk0ZTBkMjk1YzRlNDIyNWFlMGFiZTM4MDllYWU5NjIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNGMyYzczNGUwMmYyNDhhOGFhODdmNWE4N2EwN2U2MzIgPSAkKCc8ZGl2IGlkPSJodG1sXzRjMmM3MzRlMDJmMjQ4YThhYTg3ZjVhODdhMDdlNjMyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5WaWN0b3JpYSBWaWxsYWdlLCBOb3J0aCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lOTRlMGQyOTVjNGU0MjI1YWUwYWJlMzgwOWVhZTk2Mi5zZXRDb250ZW50KGh0bWxfNGMyYzczNGUwMmYyNDhhOGFhODdmNWE4N2EwN2U2MzIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZmFkNjdkMjk1NmUxNDY1OThmYThlYWY1N2IyNDdkNjEuYmluZFBvcHVwKHBvcHVwX2U5NGUwZDI5NWM0ZTQyMjVhZTBhYmUzODA5ZWFlOTYyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzU5ODFhOWYyYjJhMzQ2ZGQ4MTI4MmU4YTMzYzBhYTRiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzA2Mzk3MiwtNzkuMzA5OTM3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2ExNzM4NDM5Y2ZjMjQyYmE4NDc3MWFhNzU2ZTBjN2EzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzRlNGFlOGVkMzM5MjRjMTc5N2MzZTI0YzVmYTdmZjQ0ID0gJCgnPGRpdiBpZD0iaHRtbF80ZTRhZThlZDMzOTI0YzE3OTdjM2UyNGM1ZmE3ZmY0NCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V29vZGJpbmUgR2FyZGVucywgUGFya3ZpZXcgSGlsbCwgRWFzdCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hMTczODQzOWNmYzI0MmJhODQ3NzFhYTc1NmUwYzdhMy5zZXRDb250ZW50KGh0bWxfNGU0YWU4ZWQzMzkyNGMxNzk3YzNlMjRjNWZhN2ZmNDQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNTk4MWE5ZjJiMmEzNDZkZDgxMjgyZThhMzNjMGFhNGIuYmluZFBvcHVwKHBvcHVwX2ExNzM4NDM5Y2ZjMjQyYmE4NDc3MWFhNzU2ZTBjN2EzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzM2NzljYmU1YjI4YzQ5MzY4NWZjNzQ3N2VjMTk3Y2QxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjk1MzQzOTAwMDAwMDA1LC03OS4zMTgzODg3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2JjMzRmYmU2NjE5NzRmNGFhMjk2NDhhM2QyM2QyOWQ1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzVlMGQ3MzZiNWYwNzQ0ZTU5MDg1NTA1Nzc4MjYyODNjID0gJCgnPGRpdiBpZD0iaHRtbF81ZTBkNzM2YjVmMDc0NGU1OTA4NTUwNTc3ODI2MjgzYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V29vZGJpbmUgSGVpZ2h0cywgRWFzdCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iYzM0ZmJlNjYxOTc0ZjRhYTI5NjQ4YTNkMjNkMjlkNS5zZXRDb250ZW50KGh0bWxfNWUwZDczNmI1ZjA3NDRlNTkwODU1MDU3NzgyNjI4M2MpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMzY3OWNiZTViMjhjNDkzNjg1ZmM3NDc3ZWMxOTdjZDEuYmluZFBvcHVwKHBvcHVwX2JjMzRmYmU2NjE5NzRmNGFhMjk2NDhhM2QyM2QyOWQ1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2E0NWY2YTJkNGUxNDRjM2I5ZTRkOGFmZDI1ZjZhZTM0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjc2MzU3Mzk5OTk5OTksLTc5LjI5MzAzMTJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjUzMzRlMmU5YzE0NDUyZThjNGFhMGU5ODdhNjI4YTMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYzU4MzlmYjI0ZTIwNDg1MGI5ZjQ1ZjVjNDg5NTY2NzUgPSAkKCc8ZGl2IGlkPSJodG1sX2M1ODM5ZmIyNGUyMDQ4NTBiOWY0NWY1YzQ4OTU2Njc1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UaGUgQmVhY2hlcywgRWFzdCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82NTMzNGUyZTljMTQ0NTJlOGM0YWEwZTk4N2E2MjhhMy5zZXRDb250ZW50KGh0bWxfYzU4MzlmYjI0ZTIwNDg1MGI5ZjQ1ZjVjNDg5NTY2NzUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYTQ1ZjZhMmQ0ZTE0NGMzYjllNGQ4YWZkMjVmNmFlMzQuYmluZFBvcHVwKHBvcHVwXzY1MzM0ZTJlOWMxNDQ1MmU4YzRhYTBlOTg3YTYyOGEzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2U0OWYyYzk2MmZjMjRmMGU5ZTRiMjI2OTNlMGRiNzc3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzA5MDYwNCwtNzkuMzYzNDUxN10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kMTg1MTA5NDYzYzg0MzgxYWFiYjAyNjIzZDZhMzZjMiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80NjA4MzAyZDNlOTk0NTFhYjM1YjE2MDc0OWExNTk3MSA9ICQoJzxkaXYgaWQ9Imh0bWxfNDYwODMwMmQzZTk5NDUxYWIzNWIxNjA3NDlhMTU5NzEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxlYXNpZGUsIEVhc3QgWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZDE4NTEwOTQ2M2M4NDM4MWFhYmIwMjYyM2Q2YTM2YzIuc2V0Q29udGVudChodG1sXzQ2MDgzMDJkM2U5OTQ1MWFiMzViMTYwNzQ5YTE1OTcxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2U0OWYyYzk2MmZjMjRmMGU5ZTRiMjI2OTNlMGRiNzc3LmJpbmRQb3B1cChwb3B1cF9kMTg1MTA5NDYzYzg0MzgxYWFiYjAyNjIzZDZhMzZjMik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iOGE5NjgyYTU5Y2Q0OTVhOTJiNDQyODQ5YThmOTZjMyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcwNTM2ODksLTc5LjM0OTM3MTkwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzI3ODU0YTkwNTZiYjQ4ZTk5MDEzMTQ1OThhODU5N2RkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2M2ZTQ1MmRhYWQ1ODQ1MmNhOTFiOTI5N2VhOTEzMmMzID0gJCgnPGRpdiBpZD0iaHRtbF9jNmU0NTJkYWFkNTg0NTJjYTkxYjkyOTdlYTkxMzJjMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VGhvcm5jbGlmZmUgUGFyaywgRWFzdCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yNzg1NGE5MDU2YmI0OGU5OTAxMzE0NTk4YTg1OTdkZC5zZXRDb250ZW50KGh0bWxfYzZlNDUyZGFhZDU4NDUyY2E5MWI5Mjk3ZWE5MTMyYzMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjhhOTY4MmE1OWNkNDk1YTkyYjQ0Mjg0OWE4Zjk2YzMuYmluZFBvcHVwKHBvcHVwXzI3ODU0YTkwNTZiYjQ4ZTk5MDEzMTQ1OThhODU5N2RkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2E4NjBlZDU0MTZmNjRiNWM5MDlkNjM5NzJkZDhhNTM3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjg1MzQ3LC03OS4zMzgxMDY1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2Y3NTIxMmRiY2JjZDRlYTk4YjgzYmFhMDdlNTU1ZDE5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzVmZjI0NWFlM2UxNjQ3MDQ4NzE3NTZjODhlYTA5OTdlID0gJCgnPGRpdiBpZD0iaHRtbF81ZmYyNDVhZTNlMTY0NzA0ODcxNzU2Yzg4ZWEwOTk3ZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RWFzdCBUb3JvbnRvLCBFYXN0IFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Y3NTIxMmRiY2JjZDRlYTk4YjgzYmFhMDdlNTU1ZDE5LnNldENvbnRlbnQoaHRtbF81ZmYyNDVhZTNlMTY0NzA0ODcxNzU2Yzg4ZWEwOTk3ZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hODYwZWQ1NDE2ZjY0YjVjOTA5ZDYzOTcyZGQ4YTUzNy5iaW5kUG9wdXAocG9wdXBfZjc1MjEyZGJjYmNkNGVhOThiODNiYWEwN2U1NTVkMTkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYzBjYjA4YjE2MzNmNDVhMzgwM2IzZmI0MDA2MTA3Y2MgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Nzk1NTcxLC03OS4zNTIxODhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNzE3ZTY1YWZkOGE1NGE2ODk3NDdlOGY1YWEwYmMzYWIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMDYwMGIwOWJlMzRjNDI0ZWIwOTMwMmNkYzYyN2FiMjYgPSAkKCc8ZGl2IGlkPSJodG1sXzA2MDBiMDliZTM0YzQyNGViMDkzMDJjZGM2MjdhYjI2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UaGUgRGFuZm9ydGggV2VzdCwgUml2ZXJkYWxlLCBFYXN0IFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzcxN2U2NWFmZDhhNTRhNjg5NzQ3ZThmNWFhMGJjM2FiLnNldENvbnRlbnQoaHRtbF8wNjAwYjA5YmUzNGM0MjRlYjA5MzAyY2RjNjI3YWIyNik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jMGNiMDhiMTYzM2Y0NWEzODAzYjNmYjQwMDYxMDdjYy5iaW5kUG9wdXAocG9wdXBfNzE3ZTY1YWZkOGE1NGE2ODk3NDdlOGY1YWEwYmMzYWIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMmQ1MTA5OGJiNzMxNDFiZGJhNDcwOWVlOTJjZjZmMWQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Njg5OTg1LC03OS4zMTU1NzE1OTk5OTk5OF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iOTVkODA1N2JkZGI0NDQwOGU4MTk2OTkyOGEyNjMwZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xOGU4NDM4M2M5Njg0ZmMxOTIzMTM5NTI1MTM4MjEyZSA9ICQoJzxkaXYgaWQ9Imh0bWxfMThlODQzODNjOTY4NGZjMTkyMzEzOTUyNTEzODIxMmUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlRoZSBCZWFjaGVzIFdlc3QsIEluZGlhIEJhemFhciwgRWFzdCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iOTVkODA1N2JkZGI0NDQwOGU4MTk2OTkyOGEyNjMwZS5zZXRDb250ZW50KGh0bWxfMThlODQzODNjOTY4NGZjMTkyMzEzOTUyNTEzODIxMmUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMmQ1MTA5OGJiNzMxNDFiZGJhNDcwOWVlOTJjZjZmMWQuYmluZFBvcHVwKHBvcHVwX2I5NWQ4MDU3YmRkYjQ0NDA4ZTgxOTY5OTI4YTI2MzBlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzM4NjcwZmM5MTdkMDQ5Y2E5OWU3NTcwYzliMjk2ZDdhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjU5NTI1NSwtNzkuMzQwOTIzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzM2YzUwNjE1MmI3OTRlZGY5NTQ3NWNiZDkyZWVmYTg2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzA1NjIzMjRjNjBlYjQ2MjY4ZjVkZWI5MWJlZmE5YzFiID0gJCgnPGRpdiBpZD0iaHRtbF8wNTYyMzI0YzYwZWI0NjI2OGY1ZGViOTFiZWZhOWMxYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3R1ZGlvIERpc3RyaWN0LCBFYXN0IFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzM2YzUwNjE1MmI3OTRlZGY5NTQ3NWNiZDkyZWVmYTg2LnNldENvbnRlbnQoaHRtbF8wNTYyMzI0YzYwZWI0NjI2OGY1ZGViOTFiZWZhOWMxYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zODY3MGZjOTE3ZDA0OWNhOTllNzU3MGM5YjI5NmQ3YS5iaW5kUG9wdXAocG9wdXBfMzZjNTA2MTUyYjc5NGVkZjk1NDc1Y2JkOTJlZWZhODYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZGIzOWM5MTg5MGFkNGRlMzg1ZTY4ZWFhOWEwYWZlZGIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MjgwMjA1LC03OS4zODg3OTAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzMxZThjNTMzNzFmMjQ5MjQ5MmYyMjNlYmQzZTYwZjA2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzcxMGI3MjA3YmYzNTQ5NTdhOTY5MmQ2MzI2NGE4OTUyID0gJCgnPGRpdiBpZD0iaHRtbF83MTBiNzIwN2JmMzU0OTU3YTk2OTJkNjMyNjRhODk1MiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TGF3cmVuY2UgUGFyaywgQ2VudHJhbCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zMWU4YzUzMzcxZjI0OTI0OTJmMjIzZWJkM2U2MGYwNi5zZXRDb250ZW50KGh0bWxfNzEwYjcyMDdiZjM1NDk1N2E5NjkyZDYzMjY0YTg5NTIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZGIzOWM5MTg5MGFkNGRlMzg1ZTY4ZWFhOWEwYWZlZGIuYmluZFBvcHVwKHBvcHVwXzMxZThjNTMzNzFmMjQ5MjQ5MmYyMjNlYmQzZTYwZjA2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzlhZmJmNTMzZmFiZDQxYTQ4MGRmODAzNWM2ZTkwNDBlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzEyNzUxMSwtNzkuMzkwMTk3NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85MjNkZGM5NDlhZTI0YWVkODA3NjI5ZTAwN2Y1YWRiYSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82NTNhMDczZjRlYzM0ZDk0YmFkYmFlZDFjNGQ4MGYwMiA9ICQoJzxkaXYgaWQ9Imh0bWxfNjUzYTA3M2Y0ZWMzNGQ5NGJhZGJhZWQxYzRkODBmMDIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRhdmlzdmlsbGUgTm9ydGgsIENlbnRyYWwgVG9yb250bzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOTIzZGRjOTQ5YWUyNGFlZDgwNzYyOWUwMDdmNWFkYmEuc2V0Q29udGVudChodG1sXzY1M2EwNzNmNGVjMzRkOTRiYWRiYWVkMWM0ZDgwZjAyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzlhZmJmNTMzZmFiZDQxYTQ4MGRmODAzNWM2ZTkwNDBlLmJpbmRQb3B1cChwb3B1cF85MjNkZGM5NDlhZTI0YWVkODA3NjI5ZTAwN2Y1YWRiYSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zMDIyZWI4ZDA1M2U0ODVhYjVmMmJiYzhhNTUyNDE5NSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcxNTM4MzQsLTc5LjQwNTY3ODQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2YwMGE2YmUwYTRiYzRhNDE5NmExNWI4ZjJjNmQ2ZmVlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2NjYmMzYjRhY2FhNjRlZDJiMDg3YWQzNDA4NGNjZjBhID0gJCgnPGRpdiBpZD0iaHRtbF9jY2JjM2I0YWNhYTY0ZWQyYjA4N2FkMzQwODRjY2YwYSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Tm9ydGggVG9yb250byBXZXN0LCBDZW50cmFsIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2YwMGE2YmUwYTRiYzRhNDE5NmExNWI4ZjJjNmQ2ZmVlLnNldENvbnRlbnQoaHRtbF9jY2JjM2I0YWNhYTY0ZWQyYjA4N2FkMzQwODRjY2YwYSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zMDIyZWI4ZDA1M2U0ODVhYjVmMmJiYzhhNTUyNDE5NS5iaW5kUG9wdXAocG9wdXBfZjAwYTZiZTBhNGJjNGE0MTk2YTE1YjhmMmM2ZDZmZWUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMmI2MjVlMTQzYTA1NDcyYjllZTQ3OGRhNGUyMGMyZGYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MDQzMjQ0LC03OS4zODg3OTAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2YxN2FjMzhiMWRkODRhZmRhYjgxNDA5MTBiYjg1M2U4ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2I0NzNiNjJiODAxYTQ4MzBhZjVhNzZhNjM1NThlZTkxID0gJCgnPGRpdiBpZD0iaHRtbF9iNDczYjYyYjgwMWE0ODMwYWY1YTc2YTYzNTU4ZWU5MSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RGF2aXN2aWxsZSwgQ2VudHJhbCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mMTdhYzM4YjFkZDg0YWZkYWI4MTQwOTEwYmI4NTNlOC5zZXRDb250ZW50KGh0bWxfYjQ3M2I2MmI4MDFhNDgzMGFmNWE3NmE2MzU1OGVlOTEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMmI2MjVlMTQzYTA1NDcyYjllZTQ3OGRhNGUyMGMyZGYuYmluZFBvcHVwKHBvcHVwX2YxN2FjMzhiMWRkODRhZmRhYjgxNDA5MTBiYjg1M2U4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzE1NDFiMmU0NzE1YTQ5YTE5YTFiYzAwNjU4YjU0YjkyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjg5NTc0MywtNzkuMzgzMTU5OTAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOTFhOThiYzNkODY3NDg0YTg0OGUxZmI0MGMxOTQ0ODkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOWIzNWM2NThhZjIwNGQwZDk5NmMyOGEzMmFjZTM1NTggPSAkKCc8ZGl2IGlkPSJodG1sXzliMzVjNjU4YWYyMDRkMGQ5OTZjMjhhMzJhY2UzNTU4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Nb29yZSBQYXJrLCBTdW1tZXJoaWxsIEVhc3QsIENlbnRyYWwgVG9yb250bzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOTFhOThiYzNkODY3NDg0YTg0OGUxZmI0MGMxOTQ0ODkuc2V0Q29udGVudChodG1sXzliMzVjNjU4YWYyMDRkMGQ5OTZjMjhhMzJhY2UzNTU4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzE1NDFiMmU0NzE1YTQ5YTE5YTFiYzAwNjU4YjU0YjkyLmJpbmRQb3B1cChwb3B1cF85MWE5OGJjM2Q4Njc0ODRhODQ4ZTFmYjQwYzE5NDQ4OSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wMmQzOWRmOTQyNjU0MzZjYmQyNzZkMTkxODA4NDdmMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY4NjQxMjI5OTk5OTk5LC03OS40MDAwNDkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzViNjc2MzQ2NWI1YjRiMWJiMzczYzk3OTNmZTJhYjA5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzlhM2MwMzY3YzQ5MTQ1M2I5N2UzNGUwOGFlZmVjZTA4ID0gJCgnPGRpdiBpZD0iaHRtbF85YTNjMDM2N2M0OTE0NTNiOTdlMzRlMDhhZWZlY2UwOCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RGVlciBQYXJrLCBGb3Jlc3QgSGlsbCBTRSwgUmF0aG5lbGx5LCBTb3V0aCBIaWxsLCBTdW1tZXJoaWxsIFdlc3QsIENlbnRyYWwgVG9yb250bzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNWI2NzYzNDY1YjViNGIxYmIzNzNjOTc5M2ZlMmFiMDkuc2V0Q29udGVudChodG1sXzlhM2MwMzY3YzQ5MTQ1M2I5N2UzNGUwOGFlZmVjZTA4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzAyZDM5ZGY5NDI2NTQzNmNiZDI3NmQxOTE4MDg0N2YyLmJpbmRQb3B1cChwb3B1cF81YjY3NjM0NjViNWI0YjFiYjM3M2M5NzkzZmUyYWIwOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl85YTNiMjY5MDYzYzM0NTRkYmQ5ZjlhNjA2OGJiNzBhMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY3OTU2MjYsLTc5LjM3NzUyOTQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2ZkYWUyZTZlMTk2NjQ3MjRhYzJjOTFiM2NmMWU3MWI0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzA5NjZmNWNiYTExYTRkZGFiMjc1MzY2OWVmZTJiMWRiID0gJCgnPGRpdiBpZD0iaHRtbF8wOTY2ZjVjYmExMWE0ZGRhYjI3NTM2NjllZmUyYjFkYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Um9zZWRhbGUsIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2ZkYWUyZTZlMTk2NjQ3MjRhYzJjOTFiM2NmMWU3MWI0LnNldENvbnRlbnQoaHRtbF8wOTY2ZjVjYmExMWE0ZGRhYjI3NTM2NjllZmUyYjFkYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85YTNiMjY5MDYzYzM0NTRkYmQ5ZjlhNjA2OGJiNzBhMi5iaW5kUG9wdXAocG9wdXBfZmRhZTJlNmUxOTY2NDcyNGFjMmM5MWIzY2YxZTcxYjQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZTkxZTg5N2I2MmM1NDhjODk2YmVlZmM3ODliNDNjYTcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Njc5NjcsLTc5LjM2NzY3NTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYTg4OWFjZjNiOWJiNDk3ZDliNDlhOGZhMGM3MzE5MjggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfODAzOTQ5MzYzYzg2NDc0ZTk1NTU4OTFjZDczOWRlZjQgPSAkKCc8ZGl2IGlkPSJodG1sXzgwMzk0OTM2M2M4NjQ3NGU5NTU1ODkxY2Q3MzlkZWY0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DYWJiYWdldG93biwgU3QuIEphbWVzIFRvd24sIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2E4ODlhY2YzYjliYjQ5N2Q5YjQ5YThmYTBjNzMxOTI4LnNldENvbnRlbnQoaHRtbF84MDM5NDkzNjNjODY0NzRlOTU1NTg5MWNkNzM5ZGVmNCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9lOTFlODk3YjYyYzU0OGM4OTZiZWVmYzc4OWI0M2NhNy5iaW5kUG9wdXAocG9wdXBfYTg4OWFjZjNiOWJiNDk3ZDliNDlhOGZhMGM3MzE5MjgpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOTUzNDRlZTQwYmFmNDMyMmFhZDVhNjdhMjFiNWRkMmYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NjU4NTk5LC03OS4zODMxNTk5MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82MmEzZmI1OTA3OGI0N2Q4YTgyYWU2Yjk4ZDc5NjY3ZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mOWI5MThhYzRmOGI0MjZmOGQwNjcxM2QxYTg5MjQwYSA9ICQoJzxkaXYgaWQ9Imh0bWxfZjliOTE4YWM0ZjhiNDI2ZjhkMDY3MTNkMWE4OTI0MGEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNodXJjaCBhbmQgV2VsbGVzbGV5LCBEb3dudG93biBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82MmEzZmI1OTA3OGI0N2Q4YTgyYWU2Yjk4ZDc5NjY3ZC5zZXRDb250ZW50KGh0bWxfZjliOTE4YWM0ZjhiNDI2ZjhkMDY3MTNkMWE4OTI0MGEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOTUzNDRlZTQwYmFmNDMyMmFhZDVhNjdhMjFiNWRkMmYuYmluZFBvcHVwKHBvcHVwXzYyYTNmYjU5MDc4YjQ3ZDhhODJhZTZiOThkNzk2NjdkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzhlM2IzNjg5OWEyMjRlNGE4YTAxMDEzM2U1MWMyNmJmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjU0MjU5OSwtNzkuMzYwNjM1OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jYThiZmVhNmM1MWI0NGU0YTkxMDJiNTNmMzhjNWM1MCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83NjJlOTFhY2RlZjE0ZDU0YjZhZTJiYWM2MWIwZTc5NSA9ICQoJzxkaXYgaWQ9Imh0bWxfNzYyZTkxYWNkZWYxNGQ1NGI2YWUyYmFjNjFiMGU3OTUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhhcmJvdXJmcm9udCwgRG93bnRvd24gVG9yb250bzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfY2E4YmZlYTZjNTFiNDRlNGE5MTAyYjUzZjM4YzVjNTAuc2V0Q29udGVudChodG1sXzc2MmU5MWFjZGVmMTRkNTRiNmFlMmJhYzYxYjBlNzk1KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzhlM2IzNjg5OWEyMjRlNGE4YTAxMDEzM2U1MWMyNmJmLmJpbmRQb3B1cChwb3B1cF9jYThiZmVhNmM1MWI0NGU0YTkxMDJiNTNmMzhjNWM1MCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wZTk5M2Q5ZDQyODI0Y2UyYjQxMTA4YzAxZWY3NTU1OCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1NzE2MTgsLTc5LjM3ODkzNzA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzgwNzEwODZkZDdhZDRkYTdhMjcwYjE5YTllY2JjNWNlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzUzYzlmZjliNDgzZjQ2ZjRhY2VjYjU4NjBjZjE3ODc2ID0gJCgnPGRpdiBpZD0iaHRtbF81M2M5ZmY5YjQ4M2Y0NmY0YWNlY2I1ODYwY2YxNzg3NiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UnllcnNvbiwgR2FyZGVuIERpc3RyaWN0LCBEb3dudG93biBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84MDcxMDg2ZGQ3YWQ0ZGE3YTI3MGIxOWE5ZWNiYzVjZS5zZXRDb250ZW50KGh0bWxfNTNjOWZmOWI0ODNmNDZmNGFjZWNiNTg2MGNmMTc4NzYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMGU5OTNkOWQ0MjgyNGNlMmI0MTEwOGMwMWVmNzU1NTguYmluZFBvcHVwKHBvcHVwXzgwNzEwODZkZDdhZDRkYTdhMjcwYjE5YTllY2JjNWNlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I2NWU0NzZmNDUwYjQ0NmFhMzU5MWE4OWM0NjRjM2M4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUxNDkzOSwtNzkuMzc1NDE3OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kZGZhNjUzMzNmZmM0YjljYjE4M2E4N2EyN2I2NzgyNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xNzEyMDhmYWM5MmM0ZWM0OTdiMjE3NWZlN2MwYzVlMiA9ICQoJzxkaXYgaWQ9Imh0bWxfMTcxMjA4ZmFjOTJjNGVjNDk3YjIxNzVmZTdjMGM1ZTIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlN0LiBKYW1lcyBUb3duLCBEb3dudG93biBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9kZGZhNjUzMzNmZmM0YjljYjE4M2E4N2EyN2I2NzgyNC5zZXRDb250ZW50KGh0bWxfMTcxMjA4ZmFjOTJjNGVjNDk3YjIxNzVmZTdjMGM1ZTIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjY1ZTQ3NmY0NTBiNDQ2YWEzNTkxYTg5YzQ2NGMzYzguYmluZFBvcHVwKHBvcHVwX2RkZmE2NTMzM2ZmYzRiOWNiMTgzYTg3YTI3YjY3ODI0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2VkYjA3OWU3ZWQ4ODRhNTFhMjhmMDNjMDIxNGYyY2MzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjQ0NzcwNzk5OTk5OTk2LC03OS4zNzMzMDY0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzZmZGRlM2ZjMWQ0MjQ3ODU5OWVjMGJjMGNlYTQxYWEyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2IxY2RiNmE0NDIxZjQ3ZTg4YzY1MjkzNzhiMGQ0ZjM1ID0gJCgnPGRpdiBpZD0iaHRtbF9iMWNkYjZhNDQyMWY0N2U4OGM2NTI5Mzc4YjBkNGYzNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmVyY3p5IFBhcmssIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzZmZGRlM2ZjMWQ0MjQ3ODU5OWVjMGJjMGNlYTQxYWEyLnNldENvbnRlbnQoaHRtbF9iMWNkYjZhNDQyMWY0N2U4OGM2NTI5Mzc4YjBkNGYzNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9lZGIwNzllN2VkODg0YTUxYTI4ZjAzYzAyMTRmMmNjMy5iaW5kUG9wdXAocG9wdXBfNmZkZGUzZmMxZDQyNDc4NTk5ZWMwYmMwY2VhNDFhYTIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMTgyMjM1MmMzMGE3NDlkZGI3MDIwOGIzMTMxNDAxNDggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NTc5NTI0LC03OS4zODczODI2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2E3ZmIzMzg1NTQxYjQ1NzRhMzQxODhlOTFlZGY1Y2UwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2Y4MjE5MTZlYmRjOTRlNGVhZWUwNWViYzU2NWI3MDEzID0gJCgnPGRpdiBpZD0iaHRtbF9mODIxOTE2ZWJkYzk0ZTRlYWVlMDVlYmM1NjViNzAxMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q2VudHJhbCBCYXkgU3RyZWV0LCBEb3dudG93biBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hN2ZiMzM4NTU0MWI0NTc0YTM0MTg4ZTkxZWRmNWNlMC5zZXRDb250ZW50KGh0bWxfZjgyMTkxNmViZGM5NGU0ZWFlZTA1ZWJjNTY1YjcwMTMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMTgyMjM1MmMzMGE3NDlkZGI3MDIwOGIzMTMxNDAxNDguYmluZFBvcHVwKHBvcHVwX2E3ZmIzMzg1NTQxYjQ1NzRhMzQxODhlOTFlZGY1Y2UwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzYzYzkwMDdhMzEyMTRiMDU5MDdlODI2ZGNlZmQzYWRkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUwNTcxMjAwMDAwMDEsLTc5LjM4NDU2NzVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZTc2MWUzZGQ0ZTMwNDI4NDg4NzEzYmE1MzNhZWQzM2YgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfODgxYzgyNWZkZGMzNDIyMmJmZGMxZTQ1ZWZhNzRhZGUgPSAkKCc8ZGl2IGlkPSJodG1sXzg4MWM4MjVmZGRjMzQyMjJiZmRjMWU0NWVmYTc0YWRlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5BZGVsYWlkZSwgS2luZywgUmljaG1vbmQsIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2U3NjFlM2RkNGUzMDQyODQ4ODcxM2JhNTMzYWVkMzNmLnNldENvbnRlbnQoaHRtbF84ODFjODI1ZmRkYzM0MjIyYmZkYzFlNDVlZmE3NGFkZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82M2M5MDA3YTMxMjE0YjA1OTA3ZTgyNmRjZWZkM2FkZC5iaW5kUG9wdXAocG9wdXBfZTc2MWUzZGQ0ZTMwNDI4NDg4NzEzYmE1MzNhZWQzM2YpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjJkZGY0NTFkYjZhNGEwMTg3MjYwMzZkZmE2ZjlhZWYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDA4MTU3LC03OS4zODE3NTIyOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zZGFmMzZjYWU0OWQ0ZTdkYTAwMWVkMzEwNjNmMTA3YSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iODIwZWJlOTljN2I0ZjIwYWQ5YjY3NmMwYjgwNDI5ZiA9ICQoJzxkaXYgaWQ9Imh0bWxfYjgyMGViZTk5YzdiNGYyMGFkOWI2NzZjMGI4MDQyOWYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhhcmJvdXJmcm9udCBFYXN0LCBUb3JvbnRvIElzbGFuZHMsIFVuaW9uIFN0YXRpb24sIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzNkYWYzNmNhZTQ5ZDRlN2RhMDAxZWQzMTA2M2YxMDdhLnNldENvbnRlbnQoaHRtbF9iODIwZWJlOTljN2I0ZjIwYWQ5YjY3NmMwYjgwNDI5Zik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mMmRkZjQ1MWRiNmE0YTAxODcyNjAzNmRmYTZmOWFlZi5iaW5kUG9wdXAocG9wdXBfM2RhZjM2Y2FlNDlkNGU3ZGEwMDFlZDMxMDYzZjEwN2EpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODM5YmY3N2IyMTA5NDA2M2EyODdiMjZkMTA3MTFhZTkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDcxNzY4LC03OS4zODE1NzY0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83ODgzYzgwMmIxNzg0ZjFhOGFkYTJiZWZkZTFhYWZkOSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83ZGNlOTg1MmM3OTg0NDYxYjViOGU2MDBiOWZkZmViNyA9ICQoJzxkaXYgaWQ9Imh0bWxfN2RjZTk4NTJjNzk4NDQ2MWI1YjhlNjAwYjlmZGZlYjciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRlc2lnbiBFeGNoYW5nZSwgVG9yb250byBEb21pbmlvbiBDZW50cmUsIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzc4ODNjODAyYjE3ODRmMWE4YWRhMmJlZmRlMWFhZmQ5LnNldENvbnRlbnQoaHRtbF83ZGNlOTg1MmM3OTg0NDYxYjViOGU2MDBiOWZkZmViNyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84MzliZjc3YjIxMDk0MDYzYTI4N2IyNmQxMDcxMWFlOS5iaW5kUG9wdXAocG9wdXBfNzg4M2M4MDJiMTc4NGYxYThhZGEyYmVmZGUxYWFmZDkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZDM0M2Y4ZjA3Nzc4NDNlM2E2NDMxMGNiYzQ4MzEzMzggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDgxOTg1LC03OS4zNzk4MTY5MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82MmZkNTZkMmE1NmU0NmE5OGJlMDg3YzMyZGNlZjNlMyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81OGM4YjZjODAxNTQ0ZDRhYTExNjQwNzU4NmY2MThhYSA9ICQoJzxkaXYgaWQ9Imh0bWxfNThjOGI2YzgwMTU0NGQ0YWExMTY0MDc1ODZmNjE4YWEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNvbW1lcmNlIENvdXJ0LCBWaWN0b3JpYSBIb3RlbCwgRG93bnRvd24gVG9yb250bzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNjJmZDU2ZDJhNTZlNDZhOThiZTA4N2MzMmRjZWYzZTMuc2V0Q29udGVudChodG1sXzU4YzhiNmM4MDE1NDRkNGFhMTE2NDA3NTg2ZjYxOGFhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2QzNDNmOGYwNzc3ODQzZTNhNjQzMTBjYmM0ODMxMzM4LmJpbmRQb3B1cChwb3B1cF82MmZkNTZkMmE1NmU0NmE5OGJlMDg3YzMyZGNlZjNlMyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82NjU0MDdiN2YwMjM0ZmI4YWM4Njc3ZGVmYjlhYWU3MSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjczMzI4MjUsLTc5LjQxOTc0OTddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYTE3ZWU3ZjcyN2YxNDgyNTg4YzZhMjEyYjcxZTFmYzcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDJiMjQ2OWRlMWEyNDFlMGEyNDUxNGQxZDdmMWE4MmYgPSAkKCc8ZGl2IGlkPSJodG1sX2QyYjI0NjlkZTFhMjQxZTBhMjQ1MTRkMWQ3ZjFhODJmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CZWRmb3JkIFBhcmssIExhd3JlbmNlIE1hbm9yIEVhc3QsIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2ExN2VlN2Y3MjdmMTQ4MjU4OGM2YTIxMmI3MWUxZmM3LnNldENvbnRlbnQoaHRtbF9kMmIyNDY5ZGUxYTI0MWUwYTI0NTE0ZDFkN2YxYTgyZik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82NjU0MDdiN2YwMjM0ZmI4YWM4Njc3ZGVmYjlhYWU3MS5iaW5kUG9wdXAocG9wdXBfYTE3ZWU3ZjcyN2YxNDgyNTg4YzZhMjEyYjcxZTFmYzcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOWMyOTJlOTM5NTQ1NDNjMzkxZTE3OGFlOGY2MWU1YjggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MTE2OTQ4LC03OS40MTY5MzU1OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84MGU1ZmYwZDI2MWE0YzNkYjJlN2VkNTg1OThjMjdmNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mZjVjYTRkN2UzOTk0N2RhYjVkMjk5YTBhYzNhZWFiYSA9ICQoJzxkaXYgaWQ9Imh0bWxfZmY1Y2E0ZDdlMzk5NDdkYWI1ZDI5OWEwYWMzYWVhYmEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJvc2VsYXduLCBDZW50cmFsIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzgwZTVmZjBkMjYxYTRjM2RiMmU3ZWQ1ODU5OGMyN2Y0LnNldENvbnRlbnQoaHRtbF9mZjVjYTRkN2UzOTk0N2RhYjVkMjk5YTBhYzNhZWFiYSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85YzI5MmU5Mzk1NDU0M2MzOTFlMTc4YWU4ZjYxZTViOC5iaW5kUG9wdXAocG9wdXBfODBlNWZmMGQyNjFhNGMzZGIyZTdlZDU4NTk4YzI3ZjQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODJjZTVkYjg3OWU4NGJlNGEzOWY4YmY4MmQ5NzRmODYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42OTY5NDc2LC03OS40MTEzMDcyMDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81NzQ1ODA4MTY1ZTU0OWYwYWY1ZjlhNjYxMTEyY2E0ZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iZWE2OGIwYjNlZDE0NDdmODk0NzFlYTViMDk0OWM2NCA9ICQoJzxkaXYgaWQ9Imh0bWxfYmVhNjhiMGIzZWQxNDQ3Zjg5NDcxZWE1YjA5NDljNjQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZvcmVzdCBIaWxsIE5vcnRoLCBGb3Jlc3QgSGlsbCBXZXN0LCBDZW50cmFsIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzU3NDU4MDgxNjVlNTQ5ZjBhZjVmOWE2NjExMTJjYTRmLnNldENvbnRlbnQoaHRtbF9iZWE2OGIwYjNlZDE0NDdmODk0NzFlYTViMDk0OWM2NCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84MmNlNWRiODc5ZTg0YmU0YTM5ZjhiZjgyZDk3NGY4Ni5iaW5kUG9wdXAocG9wdXBfNTc0NTgwODE2NWU1NDlmMGFmNWY5YTY2MTExMmNhNGYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfY2FkZjFmMDk1OWMzNDAyNWE0MmVhOWI5ZTc4NTVjYmMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NzI3MDk3LC03OS40MDU2Nzg0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9hZDgwMTdjNDk3Mjc0NTMyYTc4Mjk4NWZmZGVkN2RiMSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83NGUyZmUzNmU1ZWM0NzgzYjdiY2IyYWNhYzhjZGI1NSA9ICQoJzxkaXYgaWQ9Imh0bWxfNzRlMmZlMzZlNWVjNDc4M2I3YmNiMmFjYWM4Y2RiNTUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlRoZSBBbm5leCwgTm9ydGggTWlkdG93biwgWW9ya3ZpbGxlLCBDZW50cmFsIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2FkODAxN2M0OTcyNzQ1MzJhNzgyOTg1ZmZkZWQ3ZGIxLnNldENvbnRlbnQoaHRtbF83NGUyZmUzNmU1ZWM0NzgzYjdiY2IyYWNhYzhjZGI1NSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jYWRmMWYwOTU5YzM0MDI1YTQyZWE5YjllNzg1NWNiYy5iaW5kUG9wdXAocG9wdXBfYWQ4MDE3YzQ5NzI3NDUzMmE3ODI5ODVmZmRlZDdkYjEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNjJkMWYyNDBlMDA0NDBiN2JjNWRlOTJiNjU0MDZlMWUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NjI2OTU2LC03OS40MDAwNDkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2E5ZDRmZGRmMGZiZTQwOTZhMGY4Zjc4NjYyNjdmYzE0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2QzMDE2MWVkZDRjZjQ3YThiNDg4ZWU0YjVkYWRiZThkID0gJCgnPGRpdiBpZD0iaHRtbF9kMzAxNjFlZGQ0Y2Y0N2E4YjQ4OGVlNGI1ZGFkYmU4ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SGFyYm9yZCwgVW5pdmVyc2l0eSBvZiBUb3JvbnRvLCBEb3dudG93biBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hOWQ0ZmRkZjBmYmU0MDk2YTBmOGY3ODY2MjY3ZmMxNC5zZXRDb250ZW50KGh0bWxfZDMwMTYxZWRkNGNmNDdhOGI0ODhlZTRiNWRhZGJlOGQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNjJkMWYyNDBlMDA0NDBiN2JjNWRlOTJiNjU0MDZlMWUuYmluZFBvcHVwKHBvcHVwX2E5ZDRmZGRmMGZiZTQwOTZhMGY4Zjc4NjYyNjdmYzE0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2JmZjM2NzdiODNlZDRjMzNhOWI0MTc5MzVhYmM5MjhmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUzMjA1NywtNzkuNDAwMDQ5M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wMmU1ODYyNDIxYmQ0YmRjODkzZDA2MzI4Y2Y2ZDRlYyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jMjBhYjg5YmU1N2E0MDBjYWI4MWU1Zjc1ZWUwMjc2ZSA9ICQoJzxkaXYgaWQ9Imh0bWxfYzIwYWI4OWJlNTdhNDAwY2FiODFlNWY3NWVlMDI3NmUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNoaW5hdG93biwgR3JhbmdlIFBhcmssIEtlbnNpbmd0b24gTWFya2V0LCBEb3dudG93biBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wMmU1ODYyNDIxYmQ0YmRjODkzZDA2MzI4Y2Y2ZDRlYy5zZXRDb250ZW50KGh0bWxfYzIwYWI4OWJlNTdhNDAwY2FiODFlNWY3NWVlMDI3NmUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYmZmMzY3N2I4M2VkNGMzM2E5YjQxNzkzNWFiYzkyOGYuYmluZFBvcHVwKHBvcHVwXzAyZTU4NjI0MjFiZDRiZGM4OTNkMDYzMjhjZjZkNGVjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y1Yzg2MDVjNzVmMTRjZjhiM2E0OTE3YjYxNzk2YTBlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjI4OTQ2NywtNzkuMzk0NDE5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kODAyMzliZGQwMzI0OWQ5YmYwMTc4YTIwZmE0YjdhNSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lYzJlNjgxNTFhMGY0MzNhODQ0MDMwMjk5OTZkZWQzNyA9ICQoJzxkaXYgaWQ9Imh0bWxfZWMyZTY4MTUxYTBmNDMzYTg0NDAzMDI5OTk2ZGVkMzciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNOIFRvd2VyLCBCYXRodXJzdCBRdWF5LCBJc2xhbmQgYWlycG9ydCwgSGFyYm91cmZyb250IFdlc3QsIEtpbmcgYW5kIFNwYWRpbmEsIFJhaWx3YXkgTGFuZHMsIFNvdXRoIE5pYWdhcmEsIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Q4MDIzOWJkZDAzMjQ5ZDliZjAxNzhhMjBmYTRiN2E1LnNldENvbnRlbnQoaHRtbF9lYzJlNjgxNTFhMGY0MzNhODQ0MDMwMjk5OTZkZWQzNyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mNWM4NjA1Yzc1ZjE0Y2Y4YjNhNDkxN2I2MTc5NmEwZS5iaW5kUG9wdXAocG9wdXBfZDgwMjM5YmRkMDMyNDlkOWJmMDE3OGEyMGZhNGI3YTUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOTRhZTJkMjZiNTBjNDE5NzkxMDcyNzlmODBjODE3NDQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDY0MzUyLC03OS4zNzQ4NDU5OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9hZGQ3ZTQ1NjQ1N2I0NGI3OTE5Njk5YzE2YmQyNzcyZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hN2M0OWQ0Yjk4ODE0ODRiOWYxNzBmYjM4NjQ4MDk3MSA9ICQoJzxkaXYgaWQ9Imh0bWxfYTdjNDlkNGI5ODgxNDg0YjlmMTcwZmIzODY0ODA5NzEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlN0biBBIFBPIEJveGVzIDI1IFRoZSBFc3BsYW5hZGUsIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2FkZDdlNDU2NDU3YjQ0Yjc5MTk2OTljMTZiZDI3NzJmLnNldENvbnRlbnQoaHRtbF9hN2M0OWQ0Yjk4ODE0ODRiOWYxNzBmYjM4NjQ4MDk3MSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85NGFlMmQyNmI1MGM0MTk3OTEwNzI3OWY4MGM4MTc0NC5iaW5kUG9wdXAocG9wdXBfYWRkN2U0NTY0NTdiNDRiNzkxOTY5OWMxNmJkMjc3MmYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYThiM2U4MjdhNDY1NDZmYWIxOTRjM2Y5ODg3YjEzZmIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDg0MjkyLC03OS4zODIyODAyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzBmNDgwYzI5ZWM2MjQzZGFhMmZjNThlYzM5Y2I2ZDMyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2I0YWFmYzFhZmI1ZTQxZDI4ZTAxNzQ2NGQxNGM4OTNjID0gJCgnPGRpdiBpZD0iaHRtbF9iNGFhZmMxYWZiNWU0MWQyOGUwMTc0NjRkMTRjODkzYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Rmlyc3QgQ2FuYWRpYW4gUGxhY2UsIFVuZGVyZ3JvdW5kIGNpdHksIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzBmNDgwYzI5ZWM2MjQzZGFhMmZjNThlYzM5Y2I2ZDMyLnNldENvbnRlbnQoaHRtbF9iNGFhZmMxYWZiNWU0MWQyOGUwMTc0NjRkMTRjODkzYyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hOGIzZTgyN2E0NjU0NmZhYjE5NGMzZjk4ODdiMTNmYi5iaW5kUG9wdXAocG9wdXBfMGY0ODBjMjllYzYyNDNkYWEyZmM1OGVjMzljYjZkMzIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZGE4Y2NiYmRjYTkyNDljNWI1MjFkM2NmYWJiYWI3MTggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MTg1MTc5OTk5OTk5OTYsLTc5LjQ2NDc2MzI5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzlhYzQzZTBjZjc5ODQ1MTE5Yzc1MzI4Y2ZjOWJkZGIxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2RmZjk3NmYxNzIxMzQzMzE4MTVlNDNlMTk0YTQ4N2Y5ID0gJCgnPGRpdiBpZD0iaHRtbF9kZmY5NzZmMTcyMTM0MzMxODE1ZTQzZTE5NGE0ODdmOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TGF3cmVuY2UgSGVpZ2h0cywgTGF3cmVuY2UgTWFub3IsIE5vcnRoIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzlhYzQzZTBjZjc5ODQ1MTE5Yzc1MzI4Y2ZjOWJkZGIxLnNldENvbnRlbnQoaHRtbF9kZmY5NzZmMTcyMTM0MzMxODE1ZTQzZTE5NGE0ODdmOSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9kYThjY2JiZGNhOTI0OWM1YjUyMWQzY2ZhYmJhYjcxOC5iaW5kUG9wdXAocG9wdXBfOWFjNDNlMGNmNzk4NDUxMTljNzUzMjhjZmM5YmRkYjEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOTBiOWZjZjYwYzQ3NGRlN2E4NTUzOGFmYTM1ZGNmZWIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MDk1NzcsLTc5LjQ0NTA3MjU5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzY4NGMzZWE3ZTE2YjRiMzg4NWE3YTljNzllNjJmNDNlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzU0ODJiZmYzZTIzMjQyYzc4YzUxNDhkYmMzYjdhYjE5ID0gJCgnPGRpdiBpZD0iaHRtbF81NDgyYmZmM2UyMzI0MmM3OGM1MTQ4ZGJjM2I3YWIxOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+R2xlbmNhaXJuLCBOb3J0aCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82ODRjM2VhN2UxNmI0YjM4ODVhN2E5Yzc5ZTYyZjQzZS5zZXRDb250ZW50KGh0bWxfNTQ4MmJmZjNlMjMyNDJjNzhjNTE0OGRiYzNiN2FiMTkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOTBiOWZjZjYwYzQ3NGRlN2E4NTUzOGFmYTM1ZGNmZWIuYmluZFBvcHVwKHBvcHVwXzY4NGMzZWE3ZTE2YjRiMzg4NWE3YTljNzllNjJmNDNlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzBhOTBiOTVkOWQwOTQ2NmI5YmY3OTUwYWU2ZmY3ZjRmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjkzNzgxMywtNzkuNDI4MTkxNDAwMDAwMDJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMThkZTYxMWFmOGU5NDRhMzgxYzY5YjRhOTE1YjE4MGYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMWU2NmNlMzVlMTY5NDUwZGI2MzQyZTU1MDJkOTU3MzAgPSAkKCc8ZGl2IGlkPSJodG1sXzFlNjZjZTM1ZTE2OTQ1MGRiNjM0MmU1NTAyZDk1NzMwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IdW1ld29vZC1DZWRhcnZhbGUsIFlvcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzE4ZGU2MTFhZjhlOTQ0YTM4MWM2OWI0YTkxNWIxODBmLnNldENvbnRlbnQoaHRtbF8xZTY2Y2UzNWUxNjk0NTBkYjYzNDJlNTUwMmQ5NTczMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wYTkwYjk1ZDlkMDk0NjZiOWJmNzk1MGFlNmZmN2Y0Zi5iaW5kUG9wdXAocG9wdXBfMThkZTYxMWFmOGU5NDRhMzgxYzY5YjRhOTE1YjE4MGYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYzRiMWVhZWJjMDc5NGQzMmJmZmY4OTU5ZThiMDZhOGEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42ODkwMjU2LC03OS40NTM1MTJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYWJlNWM0OWFiZjgzNGRhZDlmYzlmNzU2NTk5YTdhMzcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjAxZTU0YmRlMmQ2NDJjNDgzZmZkMTZlNzA5NTY3MWUgPSAkKCc8ZGl2IGlkPSJodG1sX2YwMWU1NGJkZTJkNjQyYzQ4M2ZmZDE2ZTcwOTU2NzFlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DYWxlZG9uaWEtRmFpcmJhbmtzLCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hYmU1YzQ5YWJmODM0ZGFkOWZjOWY3NTY1OTlhN2EzNy5zZXRDb250ZW50KGh0bWxfZjAxZTU0YmRlMmQ2NDJjNDgzZmZkMTZlNzA5NTY3MWUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYzRiMWVhZWJjMDc5NGQzMmJmZmY4OTU5ZThiMDZhOGEuYmluZFBvcHVwKHBvcHVwX2FiZTVjNDlhYmY4MzRkYWQ5ZmM5Zjc1NjU5OWE3YTM3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I4MGM1ODU4NTFlZjRjOTQ5MTdlNTFiYmNmYTAyMzk1ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjY5NTQyLC03OS40MjI1NjM3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzYwNTdkM2FjYzgzMTQ4ZWFhZjdmOGVhNGY4NTdiNDIxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2NkZDg3ZGNjZjZmYjQ4MzE5MzVhMzk3NTM4NmIwYmZkID0gJCgnPGRpdiBpZD0iaHRtbF9jZGQ4N2RjY2Y2ZmI0ODMxOTM1YTM5NzUzODZiMGJmZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q2hyaXN0aWUsIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzYwNTdkM2FjYzgzMTQ4ZWFhZjdmOGVhNGY4NTdiNDIxLnNldENvbnRlbnQoaHRtbF9jZGQ4N2RjY2Y2ZmI0ODMxOTM1YTM5NzUzODZiMGJmZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9iODBjNTg1ODUxZWY0Yzk0OTE3ZTUxYmJjZmEwMjM5NS5iaW5kUG9wdXAocG9wdXBfNjA1N2QzYWNjODMxNDhlYWFmN2Y4ZWE0Zjg1N2I0MjEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTNiM2Q2NGQ2YzAyNDMwZDk0NjE3OTFlMWIxMjcyMGUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NjkwMDUxMDAwMDAwMSwtNzkuNDQyMjU5M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kMmZkMDRhNzlhNjE0YWJiOTE5ODg0ZDE0NzU5YmZiNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80YTY0ZTVlZTkxMzQ0NGE1YmZiZjViMzNlZDY2ZDcwOSA9ICQoJzxkaXYgaWQ9Imh0bWxfNGE2NGU1ZWU5MTM0NDRhNWJmYmY1YjMzZWQ2NmQ3MDkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvdmVyY291cnQgVmlsbGFnZSwgRHVmZmVyaW4sIFdlc3QgVG9yb250bzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZDJmZDA0YTc5YTYxNGFiYjkxOTg4NGQxNDc1OWJmYjcuc2V0Q29udGVudChodG1sXzRhNjRlNWVlOTEzNDQ0YTViZmJmNWIzM2VkNjZkNzA5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzUzYjNkNjRkNmMwMjQzMGQ5NDYxNzkxZTFiMTI3MjBlLmJpbmRQb3B1cChwb3B1cF9kMmZkMDRhNzlhNjE0YWJiOTE5ODg0ZDE0NzU5YmZiNyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zYjA4MzZkNDk0NTA0ZDU0ODBjNTUwNjA0NDRiM2NmYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY0NzkyNjcwMDAwMDAwNiwtNzkuNDE5NzQ5N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jOTRiYTEyY2MyZjc0ZDEwODFlYjQyMjY0NDFhYzRmYyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82MzNjOGFjMWE2ZDc0N2Q3YWE1OWYyMTYwZTQ2OGZkNiA9ICQoJzxkaXYgaWQ9Imh0bWxfNjMzYzhhYzFhNmQ3NDdkN2FhNTlmMjE2MGU0NjhmZDYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxpdHRsZSBQb3J0dWdhbCwgVHJpbml0eSwgV2VzdCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jOTRiYTEyY2MyZjc0ZDEwODFlYjQyMjY0NDFhYzRmYy5zZXRDb250ZW50KGh0bWxfNjMzYzhhYzFhNmQ3NDdkN2FhNTlmMjE2MGU0NjhmZDYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfM2IwODM2ZDQ5NDUwNGQ1NDgwYzU1MDYwNDQ0YjNjZmIuYmluZFBvcHVwKHBvcHVwX2M5NGJhMTJjYzJmNzRkMTA4MWViNDIyNjQ0MWFjNGZjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzIxZWM2NTcyNGEwZTQzY2JhOGY3N2Q5OWNjNWQ0ZTkyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjM2ODQ3MiwtNzkuNDI4MTkxNDAwMDAwMDJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZDE5MTQ0OWU2NjM0NDY4MThkYTc1Yjc3MmQ0NDEwZjcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfY2QxOWQyZDA1MTA1NGQ0NGEwOWI5Y2Y5MzFjYjI0MWEgPSAkKCc8ZGl2IGlkPSJodG1sX2NkMTlkMmQwNTEwNTRkNDRhMDliOWNmOTMxY2IyNDFhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ccm9ja3RvbiwgRXhoaWJpdGlvbiBQbGFjZSwgUGFya2RhbGUgVmlsbGFnZSwgV2VzdCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9kMTkxNDQ5ZTY2MzQ0NjgxOGRhNzViNzcyZDQ0MTBmNy5zZXRDb250ZW50KGh0bWxfY2QxOWQyZDA1MTA1NGQ0NGEwOWI5Y2Y5MzFjYjI0MWEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjFlYzY1NzI0YTBlNDNjYmE4Zjc3ZDk5Y2M1ZDRlOTIuYmluZFBvcHVwKHBvcHVwX2QxOTE0NDllNjYzNDQ2ODE4ZGE3NWI3NzJkNDQxMGY3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2VlNDhlZTJhZTQ1YjQwNTQ4ODcwODZiOWJmYmIyNjk0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzEzNzU2MjAwMDAwMDA2LC03OS40OTAwNzM4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2U2ZTdjNWI1YWU2NDRmZDVhMzRlZTUxZTk3YjI3YzBkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzgzM2I0ZmQ2ZmNhNDQ0ODNhYWFlZWY1OTdlZWU1MzA2ID0gJCgnPGRpdiBpZD0iaHRtbF84MzNiNGZkNmZjYTQ0NDgzYWFhZWVmNTk3ZWVlNTMwNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RG93bnN2aWV3LCBOb3J0aCBQYXJrLCBVcHdvb2QgUGFyaywgTm9ydGggWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZTZlN2M1YjVhZTY0NGZkNWEzNGVlNTFlOTdiMjdjMGQuc2V0Q29udGVudChodG1sXzgzM2I0ZmQ2ZmNhNDQ0ODNhYWFlZWY1OTdlZWU1MzA2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2VlNDhlZTJhZTQ1YjQwNTQ4ODcwODZiOWJmYmIyNjk0LmJpbmRQb3B1cChwb3B1cF9lNmU3YzViNWFlNjQ0ZmQ1YTM0ZWU1MWU5N2IyN2MwZCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xNGY3Y2ZkMDhhMTY0ZWQ2OGQ3Njg3MTAwOTgxM2I3ZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY5MTExNTgsLTc5LjQ3NjAxMzI5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzAzNjVjMzNmZTVhNzQ4NjNiMTEzMDBhN2RiODIzY2U5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzI0ZDM5OTI4MzIxYzRkMDZhYjIwMzg4MGM4YzMyMTdiID0gJCgnPGRpdiBpZD0iaHRtbF8yNGQzOTkyODMyMWM0ZDA2YWIyMDM4ODBjOGMzMjE3YiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RGVsIFJheSwgS2VlbGVzZGFsZSwgTW91bnQgRGVubmlzLCBTaWx2ZXJ0aG9ybiwgWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDM2NWMzM2ZlNWE3NDg2M2IxMTMwMGE3ZGI4MjNjZTkuc2V0Q29udGVudChodG1sXzI0ZDM5OTI4MzIxYzRkMDZhYjIwMzg4MGM4YzMyMTdiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzE0ZjdjZmQwOGExNjRlZDY4ZDc2ODcxMDA5ODEzYjdlLmJpbmRQb3B1cChwb3B1cF8wMzY1YzMzZmU1YTc0ODYzYjExMzAwYTdkYjgyM2NlOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hOTcxNjcxZmRjNjE0YmJjYTAzYjdhMGUzNmVkY2VjOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY3MzE4NTI5OTk5OTk5LC03OS40ODcyNjE5MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jYTU2MzM3Mjc5MzE0ZWU4YTE3ZDA1YTk5Y2RkM2FkNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wZGE4MTMwNmMxZGE0NTZkODQ0ODczMTk3ZDYxOGY3MCA9ICQoJzxkaXYgaWQ9Imh0bWxfMGRhODEzMDZjMWRhNDU2ZDg0NDg3MzE5N2Q2MThmNzAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlRoZSBKdW5jdGlvbiBOb3J0aCwgUnVubnltZWRlLCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jYTU2MzM3Mjc5MzE0ZWU4YTE3ZDA1YTk5Y2RkM2FkNC5zZXRDb250ZW50KGh0bWxfMGRhODEzMDZjMWRhNDU2ZDg0NDg3MzE5N2Q2MThmNzApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYTk3MTY3MWZkYzYxNGJiY2EwM2I3YTBlMzZlZGNlYzguYmluZFBvcHVwKHBvcHVwX2NhNTYzMzcyNzkzMTRlZThhMTdkMDVhOTljZGQzYWQ0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzFkODA4ZWU1MTU5ZTRkNWRiMmRmNTRkOGY3NzQ0NWU3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjYxNjA4MywtNzkuNDY0NzYzMjk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzhlNDgxMDY0MzYzNDhhYjk5ZGM0MmUzZjQ0ODJiOWEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYjRlZWUyMzQ3YzVlNGVlNTkxZjMzNmRjZTZlNDA1YjAgPSAkKCc8ZGl2IGlkPSJodG1sX2I0ZWVlMjM0N2M1ZTRlZTU5MWYzMzZkY2U2ZTQwNWIwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IaWdoIFBhcmssIFRoZSBKdW5jdGlvbiBTb3V0aCwgV2VzdCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jOGU0ODEwNjQzNjM0OGFiOTlkYzQyZTNmNDQ4MmI5YS5zZXRDb250ZW50KGh0bWxfYjRlZWUyMzQ3YzVlNGVlNTkxZjMzNmRjZTZlNDA1YjApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMWQ4MDhlZTUxNTllNGQ1ZGIyZGY1NGQ4Zjc3NDQ1ZTcuYmluZFBvcHVwKHBvcHVwX2M4ZTQ4MTA2NDM2MzQ4YWI5OWRjNDJlM2Y0NDgyYjlhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2MyMDM3MzU5YzViYTRiMmM5ODUzYTNhYjQ0OTUzMDc4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjQ4OTU5NywtNzkuNDU2MzI1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzVkNDY2YzY1ZTk1NjRiNzVhZThlMWY3YzAyMzIxOWJjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzFiZWM1MDhhYmFiYzQ0Mjg5ZTU2ZGQ2YWVhNDBjNThjID0gJCgnPGRpdiBpZD0iaHRtbF8xYmVjNTA4YWJhYmM0NDI4OWU1NmRkNmFlYTQwYzU4YyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UGFya2RhbGUsIFJvbmNlc3ZhbGxlcywgV2VzdCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81ZDQ2NmM2NWU5NTY0Yjc1YWU4ZTFmN2MwMjMyMTliYy5zZXRDb250ZW50KGh0bWxfMWJlYzUwOGFiYWJjNDQyODllNTZkZDZhZWE0MGM1OGMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYzIwMzczNTljNWJhNGIyYzk4NTNhM2FiNDQ5NTMwNzguYmluZFBvcHVwKHBvcHVwXzVkNDY2YzY1ZTk1NjRiNzVhZThlMWY3YzAyMzIxOWJjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2FjYzhiY2M1MDNmNTQ3MDg4NTc1NzdhODA0NDQ5NTFhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUxNTcwNiwtNzkuNDg0NDQ5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82OWQwZmI0NTgwNDQ0YTdjYWRmN2UxMTFjYzc4MmI2MiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xOWNlMDhkZDRhM2Y0OWRiOTMyMDk4ODA2NjA5ZDVkZCA9ICQoJzxkaXYgaWQ9Imh0bWxfMTljZTA4ZGQ0YTNmNDlkYjkzMjA5ODgwNjYwOWQ1ZGQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJ1bm55bWVkZSwgU3dhbnNlYSwgV2VzdCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82OWQwZmI0NTgwNDQ0YTdjYWRmN2UxMTFjYzc4MmI2Mi5zZXRDb250ZW50KGh0bWxfMTljZTA4ZGQ0YTNmNDlkYjkzMjA5ODgwNjYwOWQ1ZGQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYWNjOGJjYzUwM2Y1NDcwODg1NzU3N2E4MDQ0NDk1MWEuYmluZFBvcHVwKHBvcHVwXzY5ZDBmYjQ1ODA0NDRhN2NhZGY3ZTExMWNjNzgyYjYyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzFkODcwNDQ5MzliNDQ3MmQ5NjZkMzFjMjMyNTY3NDg0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjYyMzAxNSwtNzkuMzg5NDkzOF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81OTFlZTRiM2RkYjI0MDVhYTZjN2QyNmMxZWQ4ZDU1NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hZDM5YThmYjZjZGE0YjIyYmI0OGU3YzljZjcxMjNjYSA9ICQoJzxkaXYgaWQ9Imh0bWxfYWQzOWE4ZmI2Y2RhNGIyMmJiNDhlN2M5Y2Y3MTIzY2EiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlF1ZWVuJiMzOTtzIFBhcmssIERvd250b3duIFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzU5MWVlNGIzZGRiMjQwNWFhNmM3ZDI2YzFlZDhkNTU0LnNldENvbnRlbnQoaHRtbF9hZDM5YThmYjZjZGE0YjIyYmI0OGU3YzljZjcxMjNjYSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xZDg3MDQ0OTM5YjQ0NzJkOTY2ZDMxYzIzMjU2NzQ4NC5iaW5kUG9wdXAocG9wdXBfNTkxZWU0YjNkZGIyNDA1YWE2YzdkMjZjMWVkOGQ1NTQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDhjNDY5NTYyYTViNGZkY2I3NzgzMTA3MmNiZjEyYTEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42MzY5NjU2LC03OS42MTU4MTg5OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zOWNmZDkyNTIyODE0MGU1YTU3ZjM1ZDM4NzQyYWNhZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wNGI5YTY4ZmJlY2Y0MjNjOWMyNTJjOWQwZWRjYTIyYSA9ICQoJzxkaXYgaWQ9Imh0bWxfMDRiOWE2OGZiZWNmNDIzYzljMjUyYzlkMGVkY2EyMmEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNhbmFkYSBQb3N0IEdhdGV3YXkgUHJvY2Vzc2luZyBDZW50cmUsIE1pc3Npc3NhdWdhPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zOWNmZDkyNTIyODE0MGU1YTU3ZjM1ZDM4NzQyYWNhZC5zZXRDb250ZW50KGh0bWxfMDRiOWE2OGZiZWNmNDIzYzljMjUyYzlkMGVkY2EyMmEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDhjNDY5NTYyYTViNGZkY2I3NzgzMTA3MmNiZjEyYTEuYmluZFBvcHVwKHBvcHVwXzM5Y2ZkOTI1MjI4MTQwZTVhNTdmMzVkMzg3NDJhY2FkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzJiOTllMWQ5M2ZkZDRhZDliZjNhZThmMGM1N2E0YmQ5ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjYyNzQzOSwtNzkuMzIxNTU4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzQyOGY0ZjM4NjBkNzQyNGJiZDM1NWYzZmMxYzkyYzgzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzljZjJjZTQ1MTVkZTRkOTU4NzZjMzBmNDFlYmI4ZjU1ID0gJCgnPGRpdiBpZD0iaHRtbF85Y2YyY2U0NTE1ZGU0ZDk1ODc2YzMwZjQxZWJiOGY1NSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnVzaW5lc3MgUmVwbHkgTWFpbCBQcm9jZXNzaW5nIENlbnRyZSA5NjkgRWFzdGVybiwgRWFzdCBUb3JvbnRvPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80MjhmNGYzODYwZDc0MjRiYmQzNTVmM2ZjMWM5MmM4My5zZXRDb250ZW50KGh0bWxfOWNmMmNlNDUxNWRlNGQ5NTg3NmMzMGY0MWViYjhmNTUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMmI5OWUxZDkzZmRkNGFkOWJmM2FlOGYwYzU3YTRiZDkuYmluZFBvcHVwKHBvcHVwXzQyOGY0ZjM4NjBkNzQyNGJiZDM1NWYzZmMxYzkyYzgzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzRlMjJjZGFmYjA0MDQ5ZDVhYjE5ZWI2MmUzNzc5MzBlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjA1NjQ2NiwtNzkuNTAxMzIwNzAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZmI5YjZlNmY2N2E4NDllM2FmODBjODhjYWQ0OTQ4MmYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZWZhODJmNDk3NWZiNGNkYjg2NGE5YWQ5OTU3MGQwZDQgPSAkKCc8ZGl2IGlkPSJodG1sX2VmYTgyZjQ5NzVmYjRjZGI4NjRhOWFkOTk1NzBkMGQ0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IdW1iZXIgQmF5IFNob3JlcywgTWltaWNvIFNvdXRoLCBOZXcgVG9yb250bywgRXRvYmljb2tlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mYjliNmU2ZjY3YTg0OWUzYWY4MGM4OGNhZDQ5NDgyZi5zZXRDb250ZW50KGh0bWxfZWZhODJmNDk3NWZiNGNkYjg2NGE5YWQ5OTU3MGQwZDQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNGUyMmNkYWZiMDQwNDlkNWFiMTllYjYyZTM3NzkzMGUuYmluZFBvcHVwKHBvcHVwX2ZiOWI2ZTZmNjdhODQ5ZTNhZjgwYzg4Y2FkNDk0ODJmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2E0ZTY1MGFkMTRhNjQyYTM4Njc5ODgxZWYyNmYyZDllID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjAyNDEzNzAwMDAwMDEsLTc5LjU0MzQ4NDA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzMxZGE4NDRkOWNkZTRkMDk4ZDEzMjk3MTNjYjgwM2JmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2YyYzcyNGIzZTYzOTQyY2E5ZWUxMzZlMWZiYTk0MTYzID0gJCgnPGRpdiBpZD0iaHRtbF9mMmM3MjRiM2U2Mzk0MmNhOWVlMTM2ZTFmYmE5NDE2MyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QWxkZXJ3b29kLCBMb25nIEJyYW5jaCwgRXRvYmljb2tlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zMWRhODQ0ZDljZGU0ZDA5OGQxMzI5NzEzY2I4MDNiZi5zZXRDb250ZW50KGh0bWxfZjJjNzI0YjNlNjM5NDJjYTllZTEzNmUxZmJhOTQxNjMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYTRlNjUwYWQxNGE2NDJhMzg2Nzk4ODFlZjI2ZjJkOWUuYmluZFBvcHVwKHBvcHVwXzMxZGE4NDRkOWNkZTRkMDk4ZDEzMjk3MTNjYjgwM2JmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY5MDJjYWVlOTcxMTRlMjBiYzIxNTc0N2RkM2UzNWQ2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUzNjUzNjAwMDAwMDA1LC03OS41MDY5NDM2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzk4NTJmMTZhZjUyYzQ5ZTNhNDg3ODQ4ODg1NDU3MWMyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzEzODEzZGVjYjVjZTRkODA4ZmQ2N2FjMjQ3NmIwYWZmID0gJCgnPGRpdiBpZD0iaHRtbF8xMzgxM2RlY2I1Y2U0ZDgwOGZkNjdhYzI0NzZiMGFmZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VGhlIEtpbmdzd2F5LCBNb250Z29tZXJ5IFJvYWQsIE9sZCBNaWxsIE5vcnRoLCBFdG9iaWNva2U8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzk4NTJmMTZhZjUyYzQ5ZTNhNDg3ODQ4ODg1NDU3MWMyLnNldENvbnRlbnQoaHRtbF8xMzgxM2RlY2I1Y2U0ZDgwOGZkNjdhYzI0NzZiMGFmZik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82OTAyY2FlZTk3MTE0ZTIwYmMyMTU3NDdkZDNlMzVkNi5iaW5kUG9wdXAocG9wdXBfOTg1MmYxNmFmNTJjNDllM2E0ODc4NDg4ODU0NTcxYzIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYzgxOTNjZTc1YzNkNGIzNGE5NzQ1Y2U5NTRlNTBmMDkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42MzYyNTc5LC03OS40OTg1MDkwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lNDM2YjdiOTBhYWU0ZDk2ODJkZGNlYTIwOGFhYTYwNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xNjkwMzQzZmUzY2Q0N2EwYjQ4ZWEzNzYwMTYxN2VlZiA9ICQoJzxkaXYgaWQ9Imh0bWxfMTY5MDM0M2ZlM2NkNDdhMGI0OGVhMzc2MDE2MTdlZWYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkh1bWJlciBCYXksIEtpbmcmIzM5O3MgTWlsbCBQYXJrLCBLaW5nc3dheSBQYXJrIFNvdXRoIEVhc3QsIE1pbWljbyBORSwgT2xkIE1pbGwgU291dGgsIFRoZSBRdWVlbnN3YXkgRWFzdCwgUm95YWwgWW9yayBTb3V0aCBFYXN0LCBTdW5ueWxlYSwgRXRvYmljb2tlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lNDM2YjdiOTBhYWU0ZDk2ODJkZGNlYTIwOGFhYTYwNC5zZXRDb250ZW50KGh0bWxfMTY5MDM0M2ZlM2NkNDdhMGI0OGVhMzc2MDE2MTdlZWYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYzgxOTNjZTc1YzNkNGIzNGE5NzQ1Y2U5NTRlNTBmMDkuYmluZFBvcHVwKHBvcHVwX2U0MzZiN2I5MGFhZTRkOTY4MmRkY2VhMjA4YWFhNjA0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY1ZTRhYjkwNTI0MzRiYmQ5NmExZjY4MGQ3ZjUwYmZmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjI4ODQwOCwtNzkuNTIwOTk5NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNTU4MDAzN2QzNmQzNDNmM2IzMmVlYmEzYTViNjljYzkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYTQ4OWNlNTc4NzQ0NGYyNjkzMDhmMDBiMDNlMjA1YTUgPSAkKCc8ZGl2IGlkPSJodG1sX2E0ODljZTU3ODc0NDRmMjY5MzA4ZjAwYjAzZTIwNWE1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5LaW5nc3dheSBQYXJrIFNvdXRoIFdlc3QsIE1pbWljbyBOVywgVGhlIFF1ZWVuc3dheSBXZXN0LCBSb3lhbCBZb3JrIFNvdXRoIFdlc3QsIFNvdXRoIG9mIEJsb29yLCBFdG9iaWNva2U8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzU1ODAwMzdkMzZkMzQzZjNiMzJlZWJhM2E1YjY5Y2M5LnNldENvbnRlbnQoaHRtbF9hNDg5Y2U1Nzg3NDQ0ZjI2OTMwOGYwMGIwM2UyMDVhNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82NWU0YWI5MDUyNDM0YmJkOTZhMWY2ODBkN2Y1MGJmZi5iaW5kUG9wdXAocG9wdXBfNTU4MDAzN2QzNmQzNDNmM2IzMmVlYmEzYTViNjljYzkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMDliYTg5ODFkOGNjNDVhOGEzODYzYWI3MjllY2Q5NzMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Njc4NTU2LC03OS41MzIyNDI0MDAwMDAwMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iMmU4YjJjZTBkNjI0YTlhYWQ2ZDE3YTI4MGVjMWFlNiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81ZTIwMjYwYTYwNWI0ZjM1YjE4NDJjZDhkYTRmMDBkYiA9ICQoJzxkaXYgaWQ9Imh0bWxfNWUyMDI2MGE2MDViNGYzNWIxODQyY2Q4ZGE0ZjAwZGIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlF1ZWVuJiMzOTtzIFBhcmssIFF1ZWVuJiMzOTtzIFBhcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2IyZThiMmNlMGQ2MjRhOWFhZDZkMTdhMjgwZWMxYWU2LnNldENvbnRlbnQoaHRtbF81ZTIwMjYwYTYwNWI0ZjM1YjE4NDJjZDhkYTRmMDBkYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wOWJhODk4MWQ4Y2M0NWE4YTM4NjNhYjcyOWVjZDk3My5iaW5kUG9wdXAocG9wdXBfYjJlOGIyY2UwZDYyNGE5YWFkNmQxN2EyODBlYzFhZTYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYTc2ZTdhZmRjNTA4NGRiNzljZDMwZGQ0YTVhOTMwOTcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NTA5NDMyLC03OS41NTQ3MjQ0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wZDJmMGU5OWJiNTM0YjkzODQ3ZDFiZTU0MWE4NzRiZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mNDMzMTg2MjljOTE0OWQ4OTA3OTIzZDYwMmQwZGJjMSA9ICQoJzxkaXYgaWQ9Imh0bWxfZjQzMzE4NjI5YzkxNDlkODkwNzkyM2Q2MDJkMGRiYzEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNsb3ZlcmRhbGUsIElzbGluZ3RvbiwgTWFydGluIEdyb3ZlLCBQcmluY2VzcyBHYXJkZW5zLCBXZXN0IERlYW5lIFBhcmssIEV0b2JpY29rZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMGQyZjBlOTliYjUzNGI5Mzg0N2QxYmU1NDFhODc0YmUuc2V0Q29udGVudChodG1sX2Y0MzMxODYyOWM5MTQ5ZDg5MDc5MjNkNjAyZDBkYmMxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2E3NmU3YWZkYzUwODRkYjc5Y2QzMGRkNGE1YTkzMDk3LmJpbmRQb3B1cChwb3B1cF8wZDJmMGU5OWJiNTM0YjkzODQ3ZDFiZTU0MWE4NzRiZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80MTJiOWVlMTNlZWM0ODYwYTY2NTJiMGZkNzhhZTc4NCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY0MzUxNTIsLTc5LjU3NzIwMDc5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2ExMDcxMDI2YTI2NjRmMmNiODc5MWE2Mjk5MzIyODdmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc1NzNkY2QzYTkwMjRiZjZhYjcxNGM2ZTczYzliNDU2ID0gJCgnPGRpdiBpZD0iaHRtbF83NTczZGNkM2E5MDI0YmY2YWI3MTRjNmU3M2M5YjQ1NiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Qmxvb3JkYWxlIEdhcmRlbnMsIEVyaW5nYXRlLCBNYXJrbGFuZCBXb29kLCBPbGQgQnVybmhhbXRob3JwZSwgRXRvYmljb2tlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hMTA3MTAyNmEyNjY0ZjJjYjg3OTFhNjI5OTMyMjg3Zi5zZXRDb250ZW50KGh0bWxfNzU3M2RjZDNhOTAyNGJmNmFiNzE0YzZlNzNjOWI0NTYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDEyYjllZTEzZWVjNDg2MGE2NjUyYjBmZDc4YWU3ODQuYmluZFBvcHVwKHBvcHVwX2ExMDcxMDI2YTI2NjRmMmNiODc5MWE2Mjk5MzIyODdmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQ2MWVkM2ZiOTdmYzRlN2I4ODYxNGVhNjc3MTQxYjA1ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzU2MzAzMywtNzkuNTY1OTYzMjk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjQ1MjdlZTdkZTNkNDFkMThlNGQ0ZWQ0YTc0MjdkYWEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOTU4NWQ0MWU2ZTYwNGRlZTgxNTAyNzY3YWM2N2E4MTggPSAkKCc8ZGl2IGlkPSJodG1sXzk1ODVkNDFlNmU2MDRkZWU4MTUwMjc2N2FjNjdhODE4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IdW1iZXIgU3VtbWl0LCBOb3J0aCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mNDUyN2VlN2RlM2Q0MWQxOGU0ZDRlZDRhNzQyN2RhYS5zZXRDb250ZW50KGh0bWxfOTU4NWQ0MWU2ZTYwNGRlZTgxNTAyNzY3YWM2N2E4MTgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDYxZWQzZmI5N2ZjNGU3Yjg4NjE0ZWE2NzcxNDFiMDUuYmluZFBvcHVwKHBvcHVwX2Y0NTI3ZWU3ZGUzZDQxZDE4ZTRkNGVkNGE3NDI3ZGFhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I3MmJhYWM2ZTU5YTQxNThhMzQxNTMxYTcwMjkwYmFkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzI0NzY1OSwtNzkuNTMyMjQyNDAwMDAwMDJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjU3MTAzYTIyMzc1NGU5ZmJiNTUzNmI5MzhmMzZiMDIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNjFkZTQwZjlhMTNlNGJiNDg3ZTY4NzY4Mzc0ZDBlMGQgPSAkKCc8ZGl2IGlkPSJodG1sXzYxZGU0MGY5YTEzZTRiYjQ4N2U2ODc2ODM3NGQwZTBkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FbWVyeSwgSHVtYmVybGVhLCBOb3J0aCBZb3JrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82NTcxMDNhMjIzNzU0ZTlmYmI1NTM2YjkzOGYzNmIwMi5zZXRDb250ZW50KGh0bWxfNjFkZTQwZjlhMTNlNGJiNDg3ZTY4NzY4Mzc0ZDBlMGQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjcyYmFhYzZlNTlhNDE1OGEzNDE1MzFhNzAyOTBiYWQuYmluZFBvcHVwKHBvcHVwXzY1NzEwM2EyMjM3NTRlOWZiYjU1MzZiOTM4ZjM2YjAyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y0NzE5MzA0YzM5OTQyZjc4ZjU3YTYzOTY2ZjkyYmQxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzA2ODc2LC03OS41MTgxODg0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xY2EwODg0YmJhODA0NjYyYTI5ODJkNjcyN2RiYjE4YiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iZDhmZDRjNjBhMTg0ZDMzOTM1OGI4YTUzMmVmODVjNiA9ICQoJzxkaXYgaWQ9Imh0bWxfYmQ4ZmQ0YzYwYTE4NGQzMzkzNThiOGE1MzJlZjg1YzYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldlc3RvbiwgWW9yazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMWNhMDg4NGJiYTgwNDY2MmEyOTgyZDY3MjdkYmIxOGIuc2V0Q29udGVudChodG1sX2JkOGZkNGM2MGExODRkMzM5MzU4YjhhNTMyZWY4NWM2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2Y0NzE5MzA0YzM5OTQyZjc4ZjU3YTYzOTY2ZjkyYmQxLmJpbmRQb3B1cChwb3B1cF8xY2EwODg0YmJhODA0NjYyYTI5ODJkNjcyN2RiYjE4Yik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80ODYxOWFlYmRhODE0ODRkYjNiN2I1NWQ5NTMwNDU5MSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY5NjMxOSwtNzkuNTMyMjQyNDAwMDAwMDJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTdkZGQ3ZWZiMTVmNDg5ZmJlMmVhMDMyOTQ3NzMzOWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNTBjNmVkZWJhNGM5NDQzOGEwNzhmYzhjMjI5ZjE0MWIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNmZlZWQwODljMWY4NGE3OGExMWRlOTYzMWZhYjdmNGUgPSAkKCc8ZGl2IGlkPSJodG1sXzZmZWVkMDg5YzFmODRhNzhhMTFkZTk2MzFmYWI3ZjRlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XZXN0bW91bnQsIEV0b2JpY29rZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNTBjNmVkZWJhNGM5NDQzOGEwNzhmYzhjMjI5ZjE0MWIuc2V0Q29udGVudChodG1sXzZmZWVkMDg5YzFmODRhNzhhMTFkZTk2MzFmYWI3ZjRlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzQ4NjE5YWViZGE4MTQ4NGRiM2I3YjU1ZDk1MzA0NTkxLmJpbmRQb3B1cChwb3B1cF81MGM2ZWRlYmE0Yzk0NDM4YTA3OGZjOGMyMjlmMTQxYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81YWE2ZjZjZGY5Yjc0ZDVhYmZkMTM1MGFjNTZkYTViNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY4ODkwNTQsLTc5LjU1NDcyNDQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE3ZGRkN2VmYjE1ZjQ4OWZiZTJlYTAzMjk0NzczMzliKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2IwNThlM2NlYzE5OTRiZGFiNzY5OGEyYjNmNTA1ODY2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzFjOTI5ZTNiODg5ZTRmZjk4OWIyMDJkOTUwMWIwM2I1ID0gJCgnPGRpdiBpZD0iaHRtbF8xYzkyOWUzYjg4OWU0ZmY5ODliMjAyZDk1MDFiMDNiNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+S2luZ3N2aWV3IFZpbGxhZ2UsIE1hcnRpbiBHcm92ZSBHYXJkZW5zLCBSaWNodmlldyBHYXJkZW5zLCBTdC4gUGhpbGxpcHMsIEV0b2JpY29rZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjA1OGUzY2VjMTk5NGJkYWI3Njk4YTJiM2Y1MDU4NjYuc2V0Q29udGVudChodG1sXzFjOTI5ZTNiODg5ZTRmZjk4OWIyMDJkOTUwMWIwM2I1KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzVhYTZmNmNkZjliNzRkNWFiZmQxMzUwYWM1NmRhNWI0LmJpbmRQb3B1cChwb3B1cF9iMDU4ZTNjZWMxOTk0YmRhYjc2OThhMmIzZjUwNTg2Nik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84NDdkOWExMDJkNDY0OTQ0YTRiN2NmYzJjNTMyNTk1NCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjczOTQxNjM5OTk5OTk5NiwtNzkuNTg4NDM2OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84OTI0NDYzNjNkN2U0YjkwOWE1OTdkZjA3MWU4MmZhNSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wOWE2OWJjYTkxMzI0NzRhOWY4YjkwNTc3MWU4NDY1ZiA9ICQoJzxkaXYgaWQ9Imh0bWxfMDlhNjliY2E5MTMyNDc0YTlmOGI5MDU3NzFlODQ2NWYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkFsYmlvbiBHYXJkZW5zLCBCZWF1bW9uZCBIZWlnaHRzLCBIdW1iZXJnYXRlLCBKYW1lc3Rvd24sIE1vdW50IE9saXZlLCBTaWx2ZXJzdG9uZSwgU291dGggU3RlZWxlcywgVGhpc3RsZXRvd24sIEV0b2JpY29rZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfODkyNDQ2MzYzZDdlNGI5MDlhNTk3ZGYwNzFlODJmYTUuc2V0Q29udGVudChodG1sXzA5YTY5YmNhOTEzMjQ3NGE5ZjhiOTA1NzcxZTg0NjVmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzg0N2Q5YTEwMmQ0NjQ5NDRhNGI3Y2ZjMmM1MzI1OTU0LmJpbmRQb3B1cChwb3B1cF84OTI0NDYzNjNkN2U0YjkwOWE1OTdkZjA3MWU4MmZhNSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yNDNiMWEyMDJiMmM0N2Q0YTE5OWVjNmEwZGUxMzNkNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcwNjc0ODI5OTk5OTk5NCwtNzkuNTk0MDU0NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xN2RkZDdlZmIxNWY0ODlmYmUyZWEwMzI5NDc3MzM5Yik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84ZTAxZDNhNDlhZWQ0NjYwYWE0NTIyOGVhYjdiN2QxYiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zYzZlMTBhMGM5N2E0NTFiYTI5NWNhZTQ5ZWFmZTFkOSA9ICQoJzxkaXYgaWQ9Imh0bWxfM2M2ZTEwYTBjOTdhNDUxYmEyOTVjYWU0OWVhZmUxZDkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5vcnRod2VzdCwgRXRvYmljb2tlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84ZTAxZDNhNDlhZWQ0NjYwYWE0NTIyOGVhYjdiN2QxYi5zZXRDb250ZW50KGh0bWxfM2M2ZTEwYTBjOTdhNDUxYmEyOTVjYWU0OWVhZmUxZDkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjQzYjFhMjAyYjJjNDdkNGExOTllYzZhMGRlMTMzZDQuYmluZFBvcHVwKHBvcHVwXzhlMDFkM2E0OWFlZDQ2NjBhYTQ1MjI4ZWFiN2I3ZDFiKTsKCiAgICAgICAgICAgIAogICAgICAgIAo8L3NjcmlwdD4=\" 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 0x7f8f8fa82cc0>"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# create map of Toronto using latitude and longitude values\n",
"map_toronto = folium.Map(location=[latitude, longitude], zoom_start=10)\n",
"\n",
"# add markers to map\n",
"for lat, lng, borough, neighborhood in zip(df1['Latitude'], df1['Longitude'], df1['Borough'], df1['Neighborhood']):\n",
" label = '{}, {}'.format(neighborhood, borough)\n",
" label = folium.Popup(label, parse_html=True)\n",
" folium.CircleMarker(\n",
" [lat, lng],\n",
" radius=5,\n",
" popup=label,\n",
" color='blue',\n",
" fill=True,\n",
" fill_color='#3186cc',\n",
" fill_opacity=0.7,\n",
" parse_html=False).add_to(map_toronto) \n",
" \n",
"map_toronto"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Section 6: Collecting top venues for each neighborhood"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Connecting to Foursquare in order to retrieve data**"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"CLIENT_ID = 'Y1GHOWVY0PDCNUSIRMZDY41TVH5OF5MGXEMUHMNAFPPONZCN' # your Foursquare ID\n",
"CLIENT_SECRET = 'HBA5ORUDJOMI1AVMMAE1RPXFQWDUCZQGRY0RJHISCZXIUJ4N' # your Foursquare Secret\n",
"VERSION = '20140101' # Foursquare API version\n",
"limit = 100"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"def getNearbyVenues(names, latitudes, longitudes, radius=500):\n",
" venues_list=[]\n",
" hood = 0\n",
" for name, lat, lng in zip(names, latitudes, longitudes):\n",
" print(name)\n",
" # create the API request URL\n",
" url = 'https://api.foursquare.com/v2/venues/explore?&client_id={}&client_secret={}&v={}&ll={},{}&radius={}&limit={}'.format(\n",
" CLIENT_ID, \n",
" CLIENT_SECRET, \n",
" VERSION, \n",
" lat, \n",
" lng, \n",
" radius, \n",
" limit)\n",
" \n",
" # make the GET request\n",
" results = requests.get(url).json()[\"response\"]['groups'][0]['items']\n",
" \n",
" # return only relevant information for each nearby venue\n",
" venues_list.append([(\n",
" name, \n",
" lat, \n",
" lng, \n",
" v['venue']['name'], \n",
" v['venue']['location']['lat'], \n",
" v['venue']['location']['lng'], \n",
" v['venue']['categories'][0]['name']) for v in results])\n",
"\n",
" nearby_venues = pd.DataFrame([item for venue_list in venues_list for item in venue_list])\n",
" nearby_venues.columns = ['Neighborhood', \n",
" 'Neighborhood Latitude', \n",
" 'Neighborhood Longitude', \n",
" 'Venue', \n",
" 'Venue Latitude', \n",
" 'Venue Longitude', \n",
" 'Venue Category']\n",
"\n",
" return(nearby_venues)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Rouge, Malvern\n",
"Highland Creek, Rouge Hill, Port Union\n",
"Guildwood, Morningside, West Hill\n",
"Woburn\n",
"Cedarbrae\n",
"Scarborough Village\n",
"East Birchmount Park, Ionview, Kennedy Park\n",
"Clairlea, Golden Mile, Oakridge\n",
"Cliffcrest, Cliffside, Scarborough Village West\n",
"Birch Cliff, Cliffside West\n",
"Dorset Park, Scarborough Town Centre, Wexford Heights\n",
"Maryvale, Wexford\n",
"Agincourt\n",
"Clarks Corners, Sullivan, Tam O'Shanter\n",
"Agincourt North, L'Amoreaux East, Milliken, Steeles East\n",
"L'Amoreaux West\n",
"Upper Rouge\n",
"Hillcrest Village\n",
"Fairview, Henry Farm, Oriole\n",
"Bayview Village\n",
"Silver Hills, York Mills\n",
"Newtonbrook, Willowdale\n",
"Willowdale South\n",
"York Mills West\n",
"Willowdale West\n",
"Parkwoods\n",
"Don Mills North\n",
"Flemingdon Park, Don Mills South\n",
"Bathurst Manor, Downsview North, Wilson Heights\n",
"Northwood Park, York University\n",
"CFB Toronto, Downsview East\n",
"Downsview West\n",
"Downsview Central\n",
"Downsview Northwest\n",
"Victoria Village\n",
"Woodbine Gardens, Parkview Hill\n",
"Woodbine Heights\n",
"The Beaches\n",
"Leaside\n",
"Thorncliffe Park\n",
"East Toronto\n",
"The Danforth West, Riverdale\n",
"The Beaches West, India Bazaar\n",
"Studio District\n",
"Lawrence Park\n",
"Davisville North\n",
"North Toronto West\n",
"Davisville\n",
"Moore Park, Summerhill East\n",
"Deer Park, Forest Hill SE, Rathnelly, South Hill, Summerhill West\n",
"Rosedale\n",
"Cabbagetown, St. James Town\n",
"Church and Wellesley\n",
"Harbourfront\n",
"Ryerson, Garden District\n",
"St. James Town\n",
"Berczy Park\n",
"Central Bay Street\n",
"Adelaide, King, Richmond\n",
"Harbourfront East, Toronto Islands, Union Station\n",
"Design Exchange, Toronto Dominion Centre\n",
"Commerce Court, Victoria Hotel\n",
"Bedford Park, Lawrence Manor East\n",
"Roselawn\n",
"Forest Hill North, Forest Hill West\n",
"The Annex, North Midtown, Yorkville\n",
"Harbord, University of Toronto\n",
"Chinatown, Grange Park, Kensington Market\n",
"CN Tower, Bathurst Quay, Island airport, Harbourfront West, King and Spadina, Railway Lands, South Niagara\n",
"Stn A PO Boxes 25 The Esplanade\n",
"First Canadian Place, Underground city\n",
"Lawrence Heights, Lawrence Manor\n",
"Glencairn\n",
"Humewood-Cedarvale\n",
"Caledonia-Fairbanks\n",
"Christie\n",
"Dovercourt Village, Dufferin\n",
"Little Portugal, Trinity\n",
"Brockton, Exhibition Place, Parkdale Village\n",
"Downsview, North Park, Upwood Park\n",
"Del Ray, Keelesdale, Mount Dennis, Silverthorn\n",
"The Junction North, Runnymede\n",
"High Park, The Junction South\n",
"Parkdale, Roncesvalles\n",
"Runnymede, Swansea\n",
"Queen's Park\n",
"Canada Post Gateway Processing Centre\n",
"Business Reply Mail Processing Centre 969 Eastern\n",
"Humber Bay Shores, Mimico South, New Toronto\n",
"Alderwood, Long Branch\n",
"The Kingsway, Montgomery Road, Old Mill North\n",
"Humber Bay, King's Mill Park, Kingsway Park South East, Mimico NE, Old Mill South, The Queensway East, Royal York South East, Sunnylea\n",
"Kingsway Park South West, Mimico NW, The Queensway West, Royal York South West, South of Bloor\n",
"Queen's Park\n",
"Cloverdale, Islington, Martin Grove, Princess Gardens, West Deane Park\n",
"Bloordale Gardens, Eringate, Markland Wood, Old Burnhamthorpe\n",
"Humber Summit\n",
"Emery, Humberlea\n",
"Weston\n",
"Westmount\n",
"Kingsview Village, Martin Grove Gardens, Richview Gardens, St. Phillips\n",
"Albion Gardens, Beaumond Heights, Humbergate, Jamestown, Mount Olive, Silverstone, South Steeles, Thistletown\n",
"Northwest\n"
]
}
],
"source": [
"toronto_venues = getNearbyVenues(names=df1['Neighborhood'],\n",
" latitudes=df1['Latitude'],\n",
" longitudes=df1['Longitude']\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Neighborhood Latitude</th>\n",
" <th>Neighborhood Longitude</th>\n",
" <th>Venue</th>\n",
" <th>Venue Latitude</th>\n",
" <th>Venue Longitude</th>\n",
" <th>Venue Category</th>\n",
" </tr>\n",
" <tr>\n",
" <th>Neighborhood</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>Adelaide, King, Richmond</th>\n",
" <td>100</td>\n",
" <td>100</td>\n",
" <td>100</td>\n",
" <td>100</td>\n",
" <td>100</td>\n",
" <td>100</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Agincourt</th>\n",
" <td>5</td>\n",
" <td>5</td>\n",
" <td>5</td>\n",
" <td>5</td>\n",
" <td>5</td>\n",
" <td>5</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Agincourt North, L'Amoreaux East, Milliken, Steeles East</th>\n",
" <td>2</td>\n",
" <td>2</td>\n",
" <td>2</td>\n",
" <td>2</td>\n",
" <td>2</td>\n",
" <td>2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Albion Gardens, Beaumond Heights, Humbergate, Jamestown, Mount Olive, Silverstone, South Steeles, Thistletown</th>\n",
" <td>13</td>\n",
" <td>13</td>\n",
" <td>13</td>\n",
" <td>13</td>\n",
" <td>13</td>\n",
" <td>13</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Alderwood, Long Branch</th>\n",
" <td>10</td>\n",
" <td>10</td>\n",
" <td>10</td>\n",
" <td>10</td>\n",
" <td>10</td>\n",
" <td>10</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Willowdale West</th>\n",
" <td>7</td>\n",
" <td>7</td>\n",
" <td>7</td>\n",
" <td>7</td>\n",
" <td>7</td>\n",
" <td>7</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Woburn</th>\n",
" <td>4</td>\n",
" <td>4</td>\n",
" <td>4</td>\n",
" <td>4</td>\n",
" <td>4</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Woodbine Gardens, Parkview Hill</th>\n",
" <td>12</td>\n",
" <td>12</td>\n",
" <td>12</td>\n",
" <td>12</td>\n",
" <td>12</td>\n",
" <td>12</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Woodbine Heights</th>\n",
" <td>9</td>\n",
" <td>9</td>\n",
" <td>9</td>\n",
" <td>9</td>\n",
" <td>9</td>\n",
" <td>9</td>\n",
" </tr>\n",
" <tr>\n",
" <th>York Mills West</th>\n",
" <td>5</td>\n",
" <td>5</td>\n",
" <td>5</td>\n",
" <td>5</td>\n",
" <td>5</td>\n",
" <td>5</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>100 rows × 6 columns</p>\n",
"</div>"
],
"text/plain": [
" Neighborhood Latitude \\\n",
"Neighborhood \n",
"Adelaide, King, Richmond 100 \n",
"Agincourt 5 \n",
"Agincourt North, L'Amoreaux East, Milliken, Ste... 2 \n",
"Albion Gardens, Beaumond Heights, Humbergate, J... 13 \n",
"Alderwood, Long Branch 10 \n",
"... ... \n",
"Willowdale West 7 \n",
"Woburn 4 \n",
"Woodbine Gardens, Parkview Hill 12 \n",
"Woodbine Heights 9 \n",
"York Mills West 5 \n",
"\n",
" Neighborhood Longitude \\\n",
"Neighborhood \n",
"Adelaide, King, Richmond 100 \n",
"Agincourt 5 \n",
"Agincourt North, L'Amoreaux East, Milliken, Ste... 2 \n",
"Albion Gardens, Beaumond Heights, Humbergate, J... 13 \n",
"Alderwood, Long Branch 10 \n",
"... ... \n",
"Willowdale West 7 \n",
"Woburn 4 \n",
"Woodbine Gardens, Parkview Hill 12 \n",
"Woodbine Heights 9 \n",
"York Mills West 5 \n",
"\n",
" Venue Venue Latitude \\\n",
"Neighborhood \n",
"Adelaide, King, Richmond 100 100 \n",
"Agincourt 5 5 \n",
"Agincourt North, L'Amoreaux East, Milliken, Ste... 2 2 \n",
"Albion Gardens, Beaumond Heights, Humbergate, J... 13 13 \n",
"Alderwood, Long Branch 10 10 \n",
"... ... ... \n",
"Willowdale West 7 7 \n",
"Woburn 4 4 \n",
"Woodbine Gardens, Parkview Hill 12 12 \n",
"Woodbine Heights 9 9 \n",
"York Mills West 5 5 \n",
"\n",
" Venue Longitude \\\n",
"Neighborhood \n",
"Adelaide, King, Richmond 100 \n",
"Agincourt 5 \n",
"Agincourt North, L'Amoreaux East, Milliken, Ste... 2 \n",
"Albion Gardens, Beaumond Heights, Humbergate, J... 13 \n",
"Alderwood, Long Branch 10 \n",
"... ... \n",
"Willowdale West 7 \n",
"Woburn 4 \n",
"Woodbine Gardens, Parkview Hill 12 \n",
"Woodbine Heights 9 \n",
"York Mills West 5 \n",
"\n",
" Venue Category \n",
"Neighborhood \n",
"Adelaide, King, Richmond 100 \n",
"Agincourt 5 \n",
"Agincourt North, L'Amoreaux East, Milliken, Ste... 2 \n",
"Albion Gardens, Beaumond Heights, Humbergate, J... 13 \n",
"Alderwood, Long Branch 10 \n",
"... ... \n",
"Willowdale West 7 \n",
"Woburn 4 \n",
"Woodbine Gardens, Parkview Hill 12 \n",
"Woodbine Heights 9 \n",
"York Mills West 5 \n",
"\n",
"[100 rows x 6 columns]"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"toronto_venues.groupby('Neighborhood').count()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Section 7: Analysing neighborhood based on top venues"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Yoga Studio</th>\n",
" <th>Accessories Store</th>\n",
" <th>Afghan Restaurant</th>\n",
" <th>Airport</th>\n",
" <th>Airport Food Court</th>\n",
" <th>Airport Gate</th>\n",
" <th>Airport Lounge</th>\n",
" <th>Airport Service</th>\n",
" <th>Airport Terminal</th>\n",
" <th>American Restaurant</th>\n",
" <th>...</th>\n",
" <th>Trail</th>\n",
" <th>Train Station</th>\n",
" <th>Vegetarian / Vegan Restaurant</th>\n",
" <th>Video Game Store</th>\n",
" <th>Video Store</th>\n",
" <th>Vietnamese Restaurant</th>\n",
" <th>Warehouse Store</th>\n",
" <th>Wine Bar</th>\n",
" <th>Wings Joint</th>\n",
" <th>Women's Store</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5 rows × 267 columns</p>\n",
"</div>"
],
"text/plain": [
" Yoga Studio Accessories Store Afghan Restaurant Airport \\\n",
"0 0 0 0 0 \n",
"1 0 0 0 0 \n",
"2 0 0 0 0 \n",
"3 0 0 0 0 \n",
"4 0 0 0 0 \n",
"\n",
" Airport Food Court Airport Gate Airport Lounge Airport Service \\\n",
"0 0 0 0 0 \n",
"1 0 0 0 0 \n",
"2 0 0 0 0 \n",
"3 0 0 0 0 \n",
"4 0 0 0 0 \n",
"\n",
" Airport Terminal American Restaurant ... Trail Train Station \\\n",
"0 0 0 ... 0 0 \n",
"1 0 0 ... 0 0 \n",
"2 0 0 ... 0 0 \n",
"3 0 0 ... 0 0 \n",
"4 0 0 ... 0 0 \n",
"\n",
" Vegetarian / Vegan Restaurant Video Game Store Video Store \\\n",
"0 0 0 0 \n",
"1 0 0 0 \n",
"2 0 0 0 \n",
"3 0 0 0 \n",
"4 0 0 0 \n",
"\n",
" Vietnamese Restaurant Warehouse Store Wine Bar Wings Joint \\\n",
"0 0 0 0 0 \n",
"1 0 0 0 0 \n",
"2 0 0 0 0 \n",
"3 0 0 0 0 \n",
"4 0 0 0 0 \n",
"\n",
" Women's Store \n",
"0 0 \n",
"1 0 \n",
"2 0 \n",
"3 0 \n",
"4 0 \n",
"\n",
"[5 rows x 267 columns]"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"toronto_onehot = pd.get_dummies(toronto_venues[['Venue Category']], prefix=\"\", prefix_sep=\"\")\n",
"\n",
"# add neighborhood column back to dataframe\n",
"toronto_onehot['Neighborhood'] = toronto_venues['Neighborhood'] \n",
"\n",
"# move neighborhood column to the first column\n",
"fixed_columns = [toronto_onehot.columns[-1]] + list(toronto_onehot.columns[:-1])\n",
"toronto_onehot = toronto_onehot[fixed_columns]\n",
"\n",
"toronto_onehot.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Grouping rows by neighborhood and by taking the mean of the frequency of occurrence of each category**"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Neighborhood</th>\n",
" <th>Yoga Studio</th>\n",
" <th>Accessories Store</th>\n",
" <th>Afghan Restaurant</th>\n",
" <th>Airport</th>\n",
" <th>Airport Food Court</th>\n",
" <th>Airport Gate</th>\n",
" <th>Airport Lounge</th>\n",
" <th>Airport Service</th>\n",
" <th>Airport Terminal</th>\n",
" <th>...</th>\n",
" <th>Trail</th>\n",
" <th>Train Station</th>\n",
" <th>Vegetarian / Vegan Restaurant</th>\n",
" <th>Video Game Store</th>\n",
" <th>Video Store</th>\n",
" <th>Vietnamese Restaurant</th>\n",
" <th>Warehouse Store</th>\n",
" <th>Wine Bar</th>\n",
" <th>Wings Joint</th>\n",
" <th>Women's Store</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Adelaide, King, Richmond</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.02</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.01</td>\n",
" <td>0.0</td>\n",
" <td>0.01</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Agincourt</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Agincourt North, L'Amoreaux East, Milliken, St...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Albion Gardens, Beaumond Heights, Humbergate, ...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Alderwood, Long Branch</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>95</th>\n",
" <td>Willowdale West</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>96</th>\n",
" <td>Woburn</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>97</th>\n",
" <td>Woodbine Gardens, Parkview Hill</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>98</th>\n",
" <td>Woodbine Heights</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.111111</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>99</th>\n",
" <td>York Mills West</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" <td>0.0</td>\n",
" <td>0.00</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>100 rows × 267 columns</p>\n",
"</div>"
],
"text/plain": [
" Neighborhood Yoga Studio \\\n",
"0 Adelaide, King, Richmond 0.0 \n",
"1 Agincourt 0.0 \n",
"2 Agincourt North, L'Amoreaux East, Milliken, St... 0.0 \n",
"3 Albion Gardens, Beaumond Heights, Humbergate, ... 0.0 \n",
"4 Alderwood, Long Branch 0.0 \n",
".. ... ... \n",
"95 Willowdale West 0.0 \n",
"96 Woburn 0.0 \n",
"97 Woodbine Gardens, Parkview Hill 0.0 \n",
"98 Woodbine Heights 0.0 \n",
"99 York Mills West 0.0 \n",
"\n",
" Accessories Store Afghan Restaurant Airport Airport Food Court \\\n",
"0 0.0 0.0 0.0 0.0 \n",
"1 0.0 0.0 0.0 0.0 \n",
"2 0.0 0.0 0.0 0.0 \n",
"3 0.0 0.0 0.0 0.0 \n",
"4 0.0 0.0 0.0 0.0 \n",
".. ... ... ... ... \n",
"95 0.0 0.0 0.0 0.0 \n",
"96 0.0 0.0 0.0 0.0 \n",
"97 0.0 0.0 0.0 0.0 \n",
"98 0.0 0.0 0.0 0.0 \n",
"99 0.0 0.0 0.0 0.0 \n",
"\n",
" Airport Gate Airport Lounge Airport Service Airport Terminal ... \\\n",
"0 0.0 0.0 0.0 0.0 ... \n",
"1 0.0 0.0 0.0 0.0 ... \n",
"2 0.0 0.0 0.0 0.0 ... \n",
"3 0.0 0.0 0.0 0.0 ... \n",
"4 0.0 0.0 0.0 0.0 ... \n",
".. ... ... ... ... ... \n",
"95 0.0 0.0 0.0 0.0 ... \n",
"96 0.0 0.0 0.0 0.0 ... \n",
"97 0.0 0.0 0.0 0.0 ... \n",
"98 0.0 0.0 0.0 0.0 ... \n",
"99 0.0 0.0 0.0 0.0 ... \n",
"\n",
" Trail Train Station Vegetarian / Vegan Restaurant Video Game Store \\\n",
"0 0.0 0.0 0.02 0.0 \n",
"1 0.0 0.0 0.00 0.0 \n",
"2 0.0 0.0 0.00 0.0 \n",
"3 0.0 0.0 0.00 0.0 \n",
"4 0.0 0.0 0.00 0.0 \n",
".. ... ... ... ... \n",
"95 0.0 0.0 0.00 0.0 \n",
"96 0.0 0.0 0.00 0.0 \n",
"97 0.0 0.0 0.00 0.0 \n",
"98 0.0 0.0 0.00 0.0 \n",
"99 0.0 0.0 0.00 0.0 \n",
"\n",
" Video Store Vietnamese Restaurant Warehouse Store Wine Bar \\\n",
"0 0.000000 0.0 0.0 0.01 \n",
"1 0.000000 0.0 0.0 0.00 \n",
"2 0.000000 0.0 0.0 0.00 \n",
"3 0.000000 0.0 0.0 0.00 \n",
"4 0.000000 0.0 0.0 0.00 \n",
".. ... ... ... ... \n",
"95 0.000000 0.0 0.0 0.00 \n",
"96 0.000000 0.0 0.0 0.00 \n",
"97 0.000000 0.0 0.0 0.00 \n",
"98 0.111111 0.0 0.0 0.00 \n",
"99 0.000000 0.0 0.0 0.00 \n",
"\n",
" Wings Joint Women's Store \n",
"0 0.0 0.01 \n",
"1 0.0 0.00 \n",
"2 0.0 0.00 \n",
"3 0.0 0.00 \n",
"4 0.0 0.00 \n",
".. ... ... \n",
"95 0.0 0.00 \n",
"96 0.0 0.00 \n",
"97 0.0 0.00 \n",
"98 0.0 0.00 \n",
"99 0.0 0.00 \n",
"\n",
"[100 rows x 267 columns]"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"toronto_grouped = toronto_onehot.groupby('Neighborhood').mean().reset_index()\n",
"toronto_grouped"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Sorting the top 10 venues and putting them into a dataframe**"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"def return_most_common_venues(row, num_top_venues):\n",
" row_categories = row.iloc[1:]\n",
" row_categories_sorted = row_categories.sort_values(ascending=False)\n",
" \n",
" return row_categories_sorted.index.values[0:num_top_venues]"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Neighborhood</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Adelaide, King, Richmond</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Café</td>\n",
" <td>Bar</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Steakhouse</td>\n",
" <td>Sushi Restaurant</td>\n",
" <td>Bakery</td>\n",
" <td>Cosmetics Shop</td>\n",
" <td>Restaurant</td>\n",
" <td>Burger Joint</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Agincourt</td>\n",
" <td>Latin American Restaurant</td>\n",
" <td>Clothing Store</td>\n",
" <td>Lounge</td>\n",
" <td>Breakfast Spot</td>\n",
" <td>Skating Rink</td>\n",
" <td>Electronics Store</td>\n",
" <td>Eastern European Restaurant</td>\n",
" <td>Dumpling Restaurant</td>\n",
" <td>Department Store</td>\n",
" <td>Drugstore</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Agincourt North, L'Amoreaux East, Milliken, St...</td>\n",
" <td>Park</td>\n",
" <td>Playground</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Donut Shop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Albion Gardens, Beaumond Heights, Humbergate, ...</td>\n",
" <td>Pizza Place</td>\n",
" <td>Grocery Store</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Beer Store</td>\n",
" <td>Fast Food Restaurant</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Japanese Restaurant</td>\n",
" <td>Discount Store</td>\n",
" <td>Fried Chicken Joint</td>\n",
" <td>Liquor Store</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Alderwood, Long Branch</td>\n",
" <td>Pizza Place</td>\n",
" <td>Gym</td>\n",
" <td>Skating Rink</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Dance Studio</td>\n",
" <td>Pub</td>\n",
" <td>Pool</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Pharmacy</td>\n",
" <td>Comfort Food Restaurant</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Neighborhood \\\n",
"0 Adelaide, King, Richmond \n",
"1 Agincourt \n",
"2 Agincourt North, L'Amoreaux East, Milliken, St... \n",
"3 Albion Gardens, Beaumond Heights, Humbergate, ... \n",
"4 Alderwood, Long Branch \n",
"\n",
" 1st Most Common Venue 2nd Most Common Venue 3rd Most Common Venue \\\n",
"0 Coffee Shop Café Bar \n",
"1 Latin American Restaurant Clothing Store Lounge \n",
"2 Park Playground Doner Restaurant \n",
"3 Pizza Place Grocery Store Coffee Shop \n",
"4 Pizza Place Gym Skating Rink \n",
"\n",
" 4th Most Common Venue 5th Most Common Venue 6th Most Common Venue \\\n",
"0 Thai Restaurant Steakhouse Sushi Restaurant \n",
"1 Breakfast Spot Skating Rink Electronics Store \n",
"2 Department Store Dessert Shop Dim Sum Restaurant \n",
"3 Beer Store Fast Food Restaurant Sandwich Place \n",
"4 Sandwich Place Dance Studio Pub \n",
"\n",
" 7th Most Common Venue 8th Most Common Venue 9th Most Common Venue \\\n",
"0 Bakery Cosmetics Shop Restaurant \n",
"1 Eastern European Restaurant Dumpling Restaurant Department Store \n",
"2 Diner Discount Store Dog Run \n",
"3 Japanese Restaurant Discount Store Fried Chicken Joint \n",
"4 Pool Coffee Shop Pharmacy \n",
"\n",
" 10th Most Common Venue \n",
"0 Burger Joint \n",
"1 Drugstore \n",
"2 Donut Shop \n",
"3 Liquor Store \n",
"4 Comfort Food Restaurant "
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"num_top_venues = 10\n",
"\n",
"indicators = ['st', 'nd', 'rd']\n",
"\n",
"# create columns according to number of top venues\n",
"columns = ['Neighborhood']\n",
"for ind in np.arange(num_top_venues):\n",
" try:\n",
" columns.append('{}{} Most Common Venue'.format(ind+1, indicators[ind]))\n",
" except:\n",
" columns.append('{}th Most Common Venue'.format(ind+1))\n",
"\n",
"# create a new dataframe\n",
"neighborhoods_venues_sorted = pd.DataFrame(columns=columns)\n",
"neighborhoods_venues_sorted['Neighborhood'] = toronto_grouped['Neighborhood']\n",
"\n",
"for ind in np.arange(toronto_grouped.shape[0]):\n",
" neighborhoods_venues_sorted.iloc[ind, 1:] = return_most_common_venues(toronto_grouped.iloc[ind, :], num_top_venues)\n",
"\n",
"neighborhoods_venues_sorted.head()"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(100, 11)"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"neighborhoods_venues_sorted.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Section 8: Neighborhood Clustering"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"# set number of clusters\n",
"kclusters = 6\n",
"\n",
"toronto_grouped_clustering = toronto_grouped.drop('Neighborhood', 1)\n",
"\n",
"# run k-means clustering\n",
"kmeans = KMeans(init=\"k-means++\", n_clusters=kclusters, n_init=20).fit(toronto_grouped_clustering)\n",
"#kmeans = KMeans(n_clusters=kclusters, random_state=0).fit(toronto_grouped_clustering)"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>PostalCode</th>\n",
" <th>Borough</th>\n",
" <th>Neighborhood</th>\n",
" <th>Latitude</th>\n",
" <th>Longitude</th>\n",
" <th>Cluster Labels</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>M1B</td>\n",
" <td>Scarborough</td>\n",
" <td>Rouge, Malvern</td>\n",
" <td>43.806686</td>\n",
" <td>-79.194353</td>\n",
" <td>0</td>\n",
" <td>Fast Food Restaurant</td>\n",
" <td>Print Shop</td>\n",
" <td>Women's Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Doner Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>M1C</td>\n",
" <td>Scarborough</td>\n",
" <td>Highland Creek, Rouge Hill, Port Union</td>\n",
" <td>43.784535</td>\n",
" <td>-79.160497</td>\n",
" <td>2</td>\n",
" <td>History Museum</td>\n",
" <td>Bar</td>\n",
" <td>Women's Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Deli / Bodega</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>M1E</td>\n",
" <td>Scarborough</td>\n",
" <td>Guildwood, Morningside, West Hill</td>\n",
" <td>43.763573</td>\n",
" <td>-79.188711</td>\n",
" <td>0</td>\n",
" <td>Electronics Store</td>\n",
" <td>Intersection</td>\n",
" <td>Mexican Restaurant</td>\n",
" <td>Spa</td>\n",
" <td>Breakfast Spot</td>\n",
" <td>Pizza Place</td>\n",
" <td>Rental Car Location</td>\n",
" <td>Medical Center</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>M1G</td>\n",
" <td>Scarborough</td>\n",
" <td>Woburn</td>\n",
" <td>43.770992</td>\n",
" <td>-79.216917</td>\n",
" <td>0</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Pharmacy</td>\n",
" <td>Korean Restaurant</td>\n",
" <td>Women's Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>M1H</td>\n",
" <td>Scarborough</td>\n",
" <td>Cedarbrae</td>\n",
" <td>43.773136</td>\n",
" <td>-79.239476</td>\n",
" <td>0</td>\n",
" <td>Fried Chicken Joint</td>\n",
" <td>Caribbean Restaurant</td>\n",
" <td>Bank</td>\n",
" <td>Athletics &amp; Sports</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Gas Station</td>\n",
" <td>Hakka Restaurant</td>\n",
" <td>Lounge</td>\n",
" <td>Bakery</td>\n",
" <td>Dumpling Restaurant</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" PostalCode Borough Neighborhood Latitude \\\n",
"0 M1B Scarborough Rouge, Malvern 43.806686 \n",
"1 M1C Scarborough Highland Creek, Rouge Hill, Port Union 43.784535 \n",
"2 M1E Scarborough Guildwood, Morningside, West Hill 43.763573 \n",
"3 M1G Scarborough Woburn 43.770992 \n",
"4 M1H Scarborough Cedarbrae 43.773136 \n",
"\n",
" Longitude Cluster Labels 1st Most Common Venue 2nd Most Common Venue \\\n",
"0 -79.194353 0 Fast Food Restaurant Print Shop \n",
"1 -79.160497 2 History Museum Bar \n",
"2 -79.188711 0 Electronics Store Intersection \n",
"3 -79.216917 0 Coffee Shop Pharmacy \n",
"4 -79.239476 0 Fried Chicken Joint Caribbean Restaurant \n",
"\n",
" 3rd Most Common Venue 4th Most Common Venue 5th Most Common Venue \\\n",
"0 Women's Store Dog Run Department Store \n",
"1 Women's Store Dessert Shop Dim Sum Restaurant \n",
"2 Mexican Restaurant Spa Breakfast Spot \n",
"3 Korean Restaurant Women's Store Dog Run \n",
"4 Bank Athletics & Sports Thai Restaurant \n",
"\n",
" 6th Most Common Venue 7th Most Common Venue 8th Most Common Venue \\\n",
"0 Dessert Shop Dim Sum Restaurant Diner \n",
"1 Diner Discount Store Dog Run \n",
"2 Pizza Place Rental Car Location Medical Center \n",
"3 Department Store Dessert Shop Dim Sum Restaurant \n",
"4 Gas Station Hakka Restaurant Lounge \n",
"\n",
" 9th Most Common Venue 10th Most Common Venue \n",
"0 Discount Store Doner Restaurant \n",
"1 Doner Restaurant Deli / Bodega \n",
"2 Department Store Dessert Shop \n",
"3 Diner Discount Store \n",
"4 Bakery Dumpling Restaurant "
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# add clustering labels\n",
"neighborhoods_venues_sorted.insert(0, 'Cluster Labels', kmeans.labels_)\n",
"\n",
"# merge toronto_grouped with original table to add latitude/longitude for each neighborhood\n",
"toronto_merged = pd.merge(df1, neighborhoods_venues_sorted, on=['Neighborhood'], how='inner') #attention! merge and not join as aout of 103 Postal Codes only 100 return Foursquare data\n",
"\n",
"toronto_merged.head()"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(100, 12)"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"neighborhoods_venues_sorted.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Visualising the clusters**"
]
},
{
"cell_type": "code",
"execution_count": 23,
"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+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdnaXQuY29tL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9tYXN0ZXIvZm9saXVtL3RlbXBsYXRlcy9sZWFmbGV0LmF3ZXNvbWUucm90YXRlLmNzcyIvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogMTAwLjAlOwogICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgICAgICAgICAgdG9wOiAwLjAlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICA8L3N0eWxlPgogICAgICAgIAo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgICAgICAgICA8ZGl2IGNsYXNzPSJmb2xpdW0tbWFwIiBpZD0ibWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2IiA+PC9kaXY+CiAgICAgICAgCjwvYm9keT4KPHNjcmlwdD4gICAgCiAgICAKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGJvdW5kcyA9IG51bGw7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgdmFyIG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNiA9IEwubWFwKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ21hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNicsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7Y2VudGVyOiBbNDMuNjUzOTYzLC03OS4zODcyMDddLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgem9vbTogMTEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhCb3VuZHM6IGJvdW5kcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxheWVyczogW10sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JsZENvcHlKdW1wOiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyczogTC5DUlMuRVBTRzM4NTcKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciB0aWxlX2xheWVyXzEyZWVjMzQxYjA5NzRlNjc4ZTg4NjBhZmY1N2Y2NjI0ID0gTC50aWxlTGF5ZXIoCiAgICAgICAgICAgICAgICAnaHR0cHM6Ly97c30udGlsZS5vcGVuc3RyZWV0bWFwLm9yZy97en0ve3h9L3t5fS5wbmcnLAogICAgICAgICAgICAgICAgewogICJhdHRyaWJ1dGlvbiI6IG51bGwsCiAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICJtYXhab29tIjogMTgsCiAgIm1pblpvb20iOiAxLAogICJub1dyYXAiOiBmYWxzZSwKICAic3ViZG9tYWlucyI6ICJhYmMiCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wMzUxMmU5YzlhNzY0OGE1OThiZTgzN2M4M2Y3YWJlNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjgwNjY4NjI5OTk5OTk5NiwtNzkuMTk0MzUzNDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjMwMTBhM2YwZGZkNDdjNjk4MWY3NDVlM2IwZDI0YTggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNTljYTE2NTZkYjkxNDA4OGIwOTI5YjgyMGFjYWM2YjMgPSAkKCc8ZGl2IGlkPSJodG1sXzU5Y2ExNjU2ZGI5MTQwODhiMDkyOWI4MjBhY2FjNmIzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Sb3VnZSwgTWFsdmVybiBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2YzMDEwYTNmMGRmZDQ3YzY5ODFmNzQ1ZTNiMGQyNGE4LnNldENvbnRlbnQoaHRtbF81OWNhMTY1NmRiOTE0MDg4YjA5MjliODIwYWNhYzZiMyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wMzUxMmU5YzlhNzY0OGE1OThiZTgzN2M4M2Y3YWJlNC5iaW5kUG9wdXAocG9wdXBfZjMwMTBhM2YwZGZkNDdjNjk4MWY3NDVlM2IwZDI0YTgpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMGVmMTI3MjIxMmNmNDFjMzk5OWRiY2FiOGY5MDU5NTggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43ODQ1MzUxLC03OS4xNjA0OTcwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMTk5NmYzIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzE5OTZmMyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mNWE4MzFjYzhmOGY0ODdjOWNlMzA3MTU2MDc4NmYyZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80NzJlM2E4MWYyMjI0ZmI5OWZmMWUxZTQ4YTJlOTI0NSA9ICQoJzxkaXYgaWQ9Imh0bWxfNDcyZTNhODFmMjIyNGZiOTlmZjFlMWU0OGEyZTkyNDUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhpZ2hsYW5kIENyZWVrLCBSb3VnZSBIaWxsLCBQb3J0IFVuaW9uIENsdXN0ZXIgMjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZjVhODMxY2M4ZjhmNDg3YzljZTMwNzE1NjA3ODZmMmUuc2V0Q29udGVudChodG1sXzQ3MmUzYTgxZjIyMjRmYjk5ZmYxZTFlNDhhMmU5MjQ1KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzBlZjEyNzIyMTJjZjQxYzM5OTlkYmNhYjhmOTA1OTU4LmJpbmRQb3B1cChwb3B1cF9mNWE4MzFjYzhmOGY0ODdjOWNlMzA3MTU2MDc4NmYyZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yYzg3MjljMmY2Yzg0MDg2YWVlOGMyM2U5NWQxMTNkNiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc2MzU3MjYsLTc5LjE4ODcxMTVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzJlZTNmN2U1NTc1NGY3Yjg1ZTlmZjQxNTkxYzg0MDUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOWQ1MzQyNTc1NDBkNDhhNGJlMTQ2Y2JmZTQ4OTNlM2QgPSAkKCc8ZGl2IGlkPSJodG1sXzlkNTM0MjU3NTQwZDQ4YTRiZTE0NmNiZmU0ODkzZTNkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5HdWlsZHdvb2QsIE1vcm5pbmdzaWRlLCBXZXN0IEhpbGwgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jMmVlM2Y3ZTU1NzU0ZjdiODVlOWZmNDE1OTFjODQwNS5zZXRDb250ZW50KGh0bWxfOWQ1MzQyNTc1NDBkNDhhNGJlMTQ2Y2JmZTQ4OTNlM2QpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMmM4NzI5YzJmNmM4NDA4NmFlZThjMjNlOTVkMTEzZDYuYmluZFBvcHVwKHBvcHVwX2MyZWUzZjdlNTU3NTRmN2I4NWU5ZmY0MTU5MWM4NDA1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y1ZjIwODBiZmE3ZTQ4MWE4Zjk5Njg5MzI0YTUzYjM2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzcwOTkyMSwtNzkuMjE2OTE3NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfN2I5MmZhMzJiNTM2NDVmOWE0Yzk2NmNlNmFhZDY1NDQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMjU0NjI0MWRmMWIwNDY1ZGJmOTcxNGQzYmQ5MjY1ZWIgPSAkKCc8ZGl2IGlkPSJodG1sXzI1NDYyNDFkZjFiMDQ2NWRiZjk3MTRkM2JkOTI2NWViIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Xb2J1cm4gQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83YjkyZmEzMmI1MzY0NWY5YTRjOTY2Y2U2YWFkNjU0NC5zZXRDb250ZW50KGh0bWxfMjU0NjI0MWRmMWIwNDY1ZGJmOTcxNGQzYmQ5MjY1ZWIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjVmMjA4MGJmYTdlNDgxYThmOTk2ODkzMjRhNTNiMzYuYmluZFBvcHVwKHBvcHVwXzdiOTJmYTMyYjUzNjQ1ZjlhNGM5NjZjZTZhYWQ2NTQ0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzg5MWY3MDk4NGJhNTQ1NGE5OGU3ODU0OWZmNTk0YmJkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzczMTM2LC03OS4yMzk0NzYwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85MzIzOGM3NTAxYWQ0OTZiYjIyZDk3MjBhNTJiODgxZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iZGIxMmI5YjE5YWE0YjU3YWZmMmI3ZjJlZDNlOTc0ZSA9ICQoJzxkaXYgaWQ9Imh0bWxfYmRiMTJiOWIxOWFhNGI1N2FmZjJiN2YyZWQzZTk3NGUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNlZGFyYnJhZSBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzkzMjM4Yzc1MDFhZDQ5NmJiMjJkOTcyMGE1MmI4ODFmLnNldENvbnRlbnQoaHRtbF9iZGIxMmI5YjE5YWE0YjU3YWZmMmI3ZjJlZDNlOTc0ZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84OTFmNzA5ODRiYTU0NTRhOThlNzg1NDlmZjU5NGJiZC5iaW5kUG9wdXAocG9wdXBfOTMyMzhjNzUwMWFkNDk2YmIyMmQ5NzIwYTUyYjg4MWYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNjY3NzZmMjUzZTAwNGNiNGFiYzNmOTRkZTY2Y2E0NzUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NDQ3MzQyLC03OS4yMzk0NzYwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmY5NjRmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmOTY0ZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yY2UzYzgxNGVkZGE0NWFkOGI0ZGNiYTgxZTRkODFlMyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9kMWYzMDJhMTk5OGI0ZWVmYjZkNmMzZjg0YWUwNzAzNCA9ICQoJzxkaXYgaWQ9Imh0bWxfZDFmMzAyYTE5OThiNGVlZmI2ZDZjM2Y4NGFlMDcwMzQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlNjYXJib3JvdWdoIFZpbGxhZ2UgQ2x1c3RlciA1PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yY2UzYzgxNGVkZGE0NWFkOGI0ZGNiYTgxZTRkODFlMy5zZXRDb250ZW50KGh0bWxfZDFmMzAyYTE5OThiNGVlZmI2ZDZjM2Y4NGFlMDcwMzQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNjY3NzZmMjUzZTAwNGNiNGFiYzNmOTRkZTY2Y2E0NzUuYmluZFBvcHVwKHBvcHVwXzJjZTNjODE0ZWRkYTQ1YWQ4YjRkY2JhODFlNGQ4MWUzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzhiYjE1OGM4YTMwMzRkYjU5MzFkNDc4NTQ3YWQwNDU1ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzI3OTI5MiwtNzkuMjYyMDI5NDAwMDAwMDJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMWZiMjBmNTNmODY5NDdkNTlkYmY3MDA0YTcwNzgzNTggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzQ4MTQ3MGE1ZDczNDMxNjkxYzdhYjBhZmI2NzdhZDYgPSAkKCc8ZGl2IGlkPSJodG1sXzc0ODE0NzBhNWQ3MzQzMTY5MWM3YWIwYWZiNjc3YWQ2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FYXN0IEJpcmNobW91bnQgUGFyaywgSW9udmlldywgS2VubmVkeSBQYXJrIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMWZiMjBmNTNmODY5NDdkNTlkYmY3MDA0YTcwNzgzNTguc2V0Q29udGVudChodG1sXzc0ODE0NzBhNWQ3MzQzMTY5MWM3YWIwYWZiNjc3YWQ2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzhiYjE1OGM4YTMwMzRkYjU5MzFkNDc4NTQ3YWQwNDU1LmJpbmRQb3B1cChwb3B1cF8xZmIyMGY1M2Y4Njk0N2Q1OWRiZjcwMDRhNzA3ODM1OCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wYTVjNmZiZjQ2MWY0NDI3ODk5ZDM4YWE4N2FmNmVhMyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcxMTExMTcwMDAwMDAwNCwtNzkuMjg0NTc3Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9hY2YxODUzMzI3ZDI0ZTAxODc0ODA3NDYxNDFhYmRjZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8yNWI5NTJhYjZlNTU0ODg5YmJlY2VkOWM1MDdkYWRlMCA9ICQoJzxkaXYgaWQ9Imh0bWxfMjViOTUyYWI2ZTU1NDg4OWJiZWNlZDljNTA3ZGFkZTAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNsYWlybGVhLCBHb2xkZW4gTWlsZSwgT2FrcmlkZ2UgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hY2YxODUzMzI3ZDI0ZTAxODc0ODA3NDYxNDFhYmRjZi5zZXRDb250ZW50KGh0bWxfMjViOTUyYWI2ZTU1NDg4OWJiZWNlZDljNTA3ZGFkZTApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMGE1YzZmYmY0NjFmNDQyNzg5OWQzOGFhODdhZjZlYTMuYmluZFBvcHVwKHBvcHVwX2FjZjE4NTMzMjdkMjRlMDE4NzQ4MDc0NjE0MWFiZGNmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y2NmQzNDBmZDdiMDRmZDQ5MmRiMDJmMmRlOGMwMzk2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzE2MzE2LC03OS4yMzk0NzYwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80NTE1ODIzZWU1ZmU0NTgxYWI2NTU1Y2JmYmQ4ZjEyOSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iYWNmMWM1NWRhYzc0ZWQ5YjBkYzhkNjc2M2NmODc2ZSA9ICQoJzxkaXYgaWQ9Imh0bWxfYmFjZjFjNTVkYWM3NGVkOWIwZGM4ZDY3NjNjZjg3NmUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNsaWZmY3Jlc3QsIENsaWZmc2lkZSwgU2NhcmJvcm91Z2ggVmlsbGFnZSBXZXN0IENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNDUxNTgyM2VlNWZlNDU4MWFiNjU1NWNiZmJkOGYxMjkuc2V0Q29udGVudChodG1sX2JhY2YxYzU1ZGFjNzRlZDliMGRjOGQ2NzYzY2Y4NzZlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2Y2NmQzNDBmZDdiMDRmZDQ5MmRiMDJmMmRlOGMwMzk2LmJpbmRQb3B1cChwb3B1cF80NTE1ODIzZWU1ZmU0NTgxYWI2NTU1Y2JmYmQ4ZjEyOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl85NDFiZDdiNTNkNTg0YmQ5OTRhOWRmZDA1YTExYWIyNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY5MjY1NzAwMDAwMDAwNCwtNzkuMjY0ODQ4MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zNWUxZDQ1NmFlYTk0MzNkYjUwZDg1NzRhNzVjOGI5NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85ZjBiZDQ4ZTRlNTk0NjFjODY2MjEyNDQ2NmMyNWIzOCA9ICQoJzxkaXYgaWQ9Imh0bWxfOWYwYmQ0OGU0ZTU5NDYxYzg2NjIxMjQ0NjZjMjViMzgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJpcmNoIENsaWZmLCBDbGlmZnNpZGUgV2VzdCBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzM1ZTFkNDU2YWVhOTQzM2RiNTBkODU3NGE3NWM4Yjk0LnNldENvbnRlbnQoaHRtbF85ZjBiZDQ4ZTRlNTk0NjFjODY2MjEyNDQ2NmMyNWIzOCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85NDFiZDdiNTNkNTg0YmQ5OTRhOWRmZDA1YTExYWIyNS5iaW5kUG9wdXAocG9wdXBfMzVlMWQ0NTZhZWE5NDMzZGI1MGQ4NTc0YTc1YzhiOTQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMmZjNGU3ZWYwYzgxNGNlOWI1ODYzMjA0NTQ1MzMzMDEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NTc0MDk2LC03OS4yNzMzMDQwMDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xY2IwYTlmY2QxNWE0NDI4ODhkMDM0NjU2ZWNhYTg0MyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8yYTdkNWJmNjg5NTI0MmNlYmRjMzZiNzMzM2NlNDVjYyA9ICQoJzxkaXYgaWQ9Imh0bWxfMmE3ZDViZjY4OTUyNDJjZWJkYzM2YjczMzNjZTQ1Y2MiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvcnNldCBQYXJrLCBTY2FyYm9yb3VnaCBUb3duIENlbnRyZSwgV2V4Zm9yZCBIZWlnaHRzIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMWNiMGE5ZmNkMTVhNDQyODg4ZDAzNDY1NmVjYWE4NDMuc2V0Q29udGVudChodG1sXzJhN2Q1YmY2ODk1MjQyY2ViZGMzNmI3MzMzY2U0NWNjKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzJmYzRlN2VmMGM4MTRjZTliNTg2MzIwNDU0NTMzMzAxLmJpbmRQb3B1cChwb3B1cF8xY2IwYTlmY2QxNWE0NDI4ODhkMDM0NjU2ZWNhYTg0Myk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hYzI0ODM1OGRkNjI0NjFiYWI4ZDRjNzAzYzk1MDAxOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc1MDA3MTUwMDAwMDAwNCwtNzkuMjk1ODQ5MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jYTEwNWRhNDQ4NjQ0YWRmYjg2ZjYzNTRkZmU4ZDYyNSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81NTNmZDZiODJiZGI0MzQxYjM4NjZkZGU4YWYxMzQxMCA9ICQoJzxkaXYgaWQ9Imh0bWxfNTUzZmQ2YjgyYmRiNDM0MWIzODY2ZGRlOGFmMTM0MTAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1hcnl2YWxlLCBXZXhmb3JkIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfY2ExMDVkYTQ0ODY0NGFkZmI4NmY2MzU0ZGZlOGQ2MjUuc2V0Q29udGVudChodG1sXzU1M2ZkNmI4MmJkYjQzNDFiMzg2NmRkZThhZjEzNDEwKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2FjMjQ4MzU4ZGQ2MjQ2MWJhYjhkNGM3MDNjOTUwMDE5LmJpbmRQb3B1cChwb3B1cF9jYTEwNWRhNDQ4NjQ0YWRmYjg2ZjYzNTRkZmU4ZDYyNSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84MGFmZjZlYjAzNWI0ZmNkYWQyZjIwYmI4YjZiNjlkYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc5NDIwMDMsLTc5LjI2MjAyOTQwMDAwMDAyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzMxYTk0ZjExMmQ5MjQ2ZDNhY2I2NmI0ZWE3YzYxMjM1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzM5NmRlODJhOGI1ZDRiYWNiZmQ1NTc1N2RmYzI3NmMxID0gJCgnPGRpdiBpZD0iaHRtbF8zOTZkZTgyYThiNWQ0YmFjYmZkNTU3NTdkZmMyNzZjMSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QWdpbmNvdXJ0IENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzFhOTRmMTEyZDkyNDZkM2FjYjY2YjRlYTdjNjEyMzUuc2V0Q29udGVudChodG1sXzM5NmRlODJhOGI1ZDRiYWNiZmQ1NTc1N2RmYzI3NmMxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzgwYWZmNmViMDM1YjRmY2RhZDJmMjBiYjhiNmI2OWRiLmJpbmRQb3B1cChwb3B1cF8zMWE5NGYxMTJkOTI0NmQzYWNiNjZiNGVhN2M2MTIzNSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kMzU2MTdmOTc0MTY0MTc4OGQ3NmNiZDZlNDFmOWEyNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc4MTYzNzUsLTc5LjMwNDMwMjFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzA4Y2EzNjljMmE2NGQ5YzgzNjdkZmZjYzgyZWM3MzEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYWQ3YzJmMjRiZDUwNDZkZWI0YzhmNmNlYTc2MDM3MDIgPSAkKCc8ZGl2IGlkPSJodG1sX2FkN2MyZjI0YmQ1MDQ2ZGViNGM4ZjZjZWE3NjAzNzAyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DbGFya3MgQ29ybmVycywgU3VsbGl2YW4sIFRhbSBPJiMzOTtTaGFudGVyIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYzA4Y2EzNjljMmE2NGQ5YzgzNjdkZmZjYzgyZWM3MzEuc2V0Q29udGVudChodG1sX2FkN2MyZjI0YmQ1MDQ2ZGViNGM4ZjZjZWE3NjAzNzAyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2QzNTYxN2Y5NzQxNjQxNzg4ZDc2Y2JkNmU0MWY5YTI1LmJpbmRQb3B1cChwb3B1cF9jMDhjYTM2OWMyYTY0ZDljODM2N2RmZmNjODJlYzczMSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81ZjcxYjE0ZjM1OTY0OTUyYWE4M2JlYWRmYzVjN2U3ZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjgxNTI1MjIsLTc5LjI4NDU3NzJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmOTY0ZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjk2NGYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMWVkZjk4OGJlMDBhNGY0ZDk1ODI0OTcxNTlkODQxMDcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNTY3MTM2OWE4YTljNDcxZTljNDQwOWYxYzY4NGM4OTYgPSAkKCc8ZGl2IGlkPSJodG1sXzU2NzEzNjlhOGE5YzQ3MWU5YzQ0MDlmMWM2ODRjODk2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5BZ2luY291cnQgTm9ydGgsIEwmIzM5O0Ftb3JlYXV4IEVhc3QsIE1pbGxpa2VuLCBTdGVlbGVzIEVhc3QgQ2x1c3RlciA1PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xZWRmOTg4YmUwMGE0ZjRkOTU4MjQ5NzE1OWQ4NDEwNy5zZXRDb250ZW50KGh0bWxfNTY3MTM2OWE4YTljNDcxZTljNDQwOWYxYzY4NGM4OTYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNWY3MWIxNGYzNTk2NDk1MmFhODNiZWFkZmM1YzdlN2QuYmluZFBvcHVwKHBvcHVwXzFlZGY5ODhiZTAwYTRmNGQ5NTgyNDk3MTU5ZDg0MTA3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y0ZjRjNGMwZTk5MzQ1ZjE4YTE1MWNiMDFjNDliY2UzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzk5NTI1MjAwMDAwMDA1LC03OS4zMTgzODg3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzczOTVlNjVmMmNhZTQwMTViMzc2NmI4NmZkMDBkMjhhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzY0YWUwZjg0YmQ1ZDQyY2Q4OWM0NDBlYmEyYWE3Y2Y2ID0gJCgnPGRpdiBpZD0iaHRtbF82NGFlMGY4NGJkNWQ0MmNkODljNDQwZWJhMmFhN2NmNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TCYjMzk7QW1vcmVhdXggV2VzdCBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzczOTVlNjVmMmNhZTQwMTViMzc2NmI4NmZkMDBkMjhhLnNldENvbnRlbnQoaHRtbF82NGFlMGY4NGJkNWQ0MmNkODljNDQwZWJhMmFhN2NmNik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mNGY0YzRjMGU5OTM0NWYxOGExNTFjYjAxYzQ5YmNlMy5iaW5kUG9wdXAocG9wdXBfNzM5NWU2NWYyY2FlNDAxNWIzNzY2Yjg2ZmQwMGQyOGEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYzU3NzQ1ZTdkMGY2NDU5YWFjN2FjY2FmYzJjNjM1ZGEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My44MDM3NjIyLC03OS4zNjM0NTE3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RhMWMxNTBlMjU4ZjRjYzA5YTM4NmVkYWJiYTkxZmMxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2JiMGQ0NjQ0OWE4NzQ5ZmI4ZDAwYjI3OTQzZmNkNmU1ID0gJCgnPGRpdiBpZD0iaHRtbF9iYjBkNDY0NDlhODc0OWZiOGQwMGIyNzk0M2ZjZDZlNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SGlsbGNyZXN0IFZpbGxhZ2UgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9kYTFjMTUwZTI1OGY0Y2MwOWEzODZlZGFiYmE5MWZjMS5zZXRDb250ZW50KGh0bWxfYmIwZDQ2NDQ5YTg3NDlmYjhkMDBiMjc5NDNmY2Q2ZTUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYzU3NzQ1ZTdkMGY2NDU5YWFjN2FjY2FmYzJjNjM1ZGEuYmluZFBvcHVwKHBvcHVwX2RhMWMxNTBlMjU4ZjRjYzA5YTM4NmVkYWJiYTkxZmMxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzc3NWExZmVjODE1MTQwMjU4OWJlNGQ1MTU1OTNiMWY4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzc4NTE3NSwtNzkuMzQ2NTU1N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81OWU3ZmQ4NTc1OWI0ZGI5OWI2OWViMTkwZTcxYjIzYSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jM2FlYTkzZDJjZmY0MjhiOGY0MzIwNjY2MzM4MmQ4YyA9ICQoJzxkaXYgaWQ9Imh0bWxfYzNhZWE5M2QyY2ZmNDI4YjhmNDMyMDY2NjMzODJkOGMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZhaXJ2aWV3LCBIZW5yeSBGYXJtLCBPcmlvbGUgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81OWU3ZmQ4NTc1OWI0ZGI5OWI2OWViMTkwZTcxYjIzYS5zZXRDb250ZW50KGh0bWxfYzNhZWE5M2QyY2ZmNDI4YjhmNDMyMDY2NjMzODJkOGMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzc1YTFmZWM4MTUxNDAyNTg5YmU0ZDUxNTU5M2IxZjguYmluZFBvcHVwKHBvcHVwXzU5ZTdmZDg1NzU5YjRkYjk5YjY5ZWIxOTBlNzFiMjNhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzI0ZWMzOWM0MGIzZjRmNWY5ZDVjMTNmYTQzMmYwMDdkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzg2OTQ3MywtNzkuMzg1OTc1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2U2M2E4MTY3MmFlYzQzN2FiYWZiYzliZDhjMjA3YWJmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2MwNmMxM2VjNWU2NDRjY2Y5NWJiNzJlMTM3NjVlNjNjID0gJCgnPGRpdiBpZD0iaHRtbF9jMDZjMTNlYzVlNjQ0Y2NmOTViYjcyZTEzNzY1ZTYzYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmF5dmlldyBWaWxsYWdlIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZTYzYTgxNjcyYWVjNDM3YWJhZmJjOWJkOGMyMDdhYmYuc2V0Q29udGVudChodG1sX2MwNmMxM2VjNWU2NDRjY2Y5NWJiNzJlMTM3NjVlNjNjKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzI0ZWMzOWM0MGIzZjRmNWY5ZDVjMTNmYTQzMmYwMDdkLmJpbmRQb3B1cChwb3B1cF9lNjNhODE2NzJhZWM0MzdhYmFmYmM5YmQ4YzIwN2FiZik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83NmI3ODE0MzA0YzA0NmE5YWY2ZjYxMjQ0ZDZiNDEyYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc1NzQ5MDIsLTc5LjM3NDcxNDA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNiMmYzOTYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjYjJmMzk2IiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzJlOWEzMzBjZThkMDQyNTdiYmI5OGNhM2MxZGRlNjhhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzdhYzQ3ZDdhM2ZjZjQyMjY4Mjk4YTdjZGMzYTdjNzdiID0gJCgnPGRpdiBpZD0iaHRtbF83YWM0N2Q3YTNmY2Y0MjI2ODI5OGE3Y2RjM2E3Yzc3YiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U2lsdmVyIEhpbGxzLCBZb3JrIE1pbGxzIENsdXN0ZXIgNDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMmU5YTMzMGNlOGQwNDI1N2JiYjk4Y2EzYzFkZGU2OGEuc2V0Q29udGVudChodG1sXzdhYzQ3ZDdhM2ZjZjQyMjY4Mjk4YTdjZGMzYTdjNzdiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzc2Yjc4MTQzMDRjMDQ2YTlhZjZmNjEyNDRkNmI0MTJiLmJpbmRQb3B1cChwb3B1cF8yZTlhMzMwY2U4ZDA0MjU3YmJiOThjYTNjMWRkZTY4YSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wYWFlZTg2NGQwYjc0ZjNhYmVlZTA3NTIzMTFiZDM1YiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc4OTA1MywtNzkuNDA4NDkyNzk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjliZjYwNzU3M2FmNGJkZmI5ZDc5OTFhMDZiNTBiZjggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzAzMmU5ZDFjMWViNDlkYmE1MjJiOTM2MWUyNGFjNjYgPSAkKCc8ZGl2IGlkPSJodG1sXzcwMzJlOWQxYzFlYjQ5ZGJhNTIyYjkzNjFlMjRhYzY2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5OZXd0b25icm9vaywgV2lsbG93ZGFsZSBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Y5YmY2MDc1NzNhZjRiZGZiOWQ3OTkxYTA2YjUwYmY4LnNldENvbnRlbnQoaHRtbF83MDMyZTlkMWMxZWI0OWRiYTUyMmI5MzYxZTI0YWM2Nik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wYWFlZTg2NGQwYjc0ZjNhYmVlZTA3NTIzMTFiZDM1Yi5iaW5kUG9wdXAocG9wdXBfZjliZjYwNzU3M2FmNGJkZmI5ZDc5OTFhMDZiNTBiZjgpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMDAyMTQzMmJmMThiNDVhYjhjMWYyMWY5MDFkYTI5NjcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NzAxMTk5LC03OS40MDg0OTI3OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84YmI5YjU0ZGQ3N2Q0NzQ4YWI4YjBmZDU1NWQ0NDNhYyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iM2I4NmJmNTljMzM0NjFmODAwZTIwNzUyMjFiMjc3NiA9ICQoJzxkaXYgaWQ9Imh0bWxfYjNiODZiZjU5YzMzNDYxZjgwMGUyMDc1MjIxYjI3NzYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldpbGxvd2RhbGUgU291dGggQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84YmI5YjU0ZGQ3N2Q0NzQ4YWI4YjBmZDU1NWQ0NDNhYy5zZXRDb250ZW50KGh0bWxfYjNiODZiZjU5YzMzNDYxZjgwMGUyMDc1MjIxYjI3NzYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMDAyMTQzMmJmMThiNDVhYjhjMWYyMWY5MDFkYTI5NjcuYmluZFBvcHVwKHBvcHVwXzhiYjliNTRkZDc3ZDQ3NDhhYjhiMGZkNTU1ZDQ0M2FjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzk0ZGI1NDY4YjY1YzRlMjBhNGIyZGNmYTZjOTU2YWJhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzUyNzU4Mjk5OTk5OTk2LC03OS40MDAwNDkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjk2NGYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmY5NjRmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzJmYmU1ODQ4YzAxODRhYWViYWFkNjBhMmI1YTQwNTVjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzEyNDFmZDc3OTMwYTRlZGY4NTQxMWVmYWZjZGY2MTdmID0gJCgnPGRpdiBpZD0iaHRtbF8xMjQxZmQ3NzkzMGE0ZWRmODU0MTFlZmFmY2RmNjE3ZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+WW9yayBNaWxscyBXZXN0IENsdXN0ZXIgNTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMmZiZTU4NDhjMDE4NGFhZWJhYWQ2MGEyYjVhNDA1NWMuc2V0Q29udGVudChodG1sXzEyNDFmZDc3OTMwYTRlZGY4NTQxMWVmYWZjZGY2MTdmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzk0ZGI1NDY4YjY1YzRlMjBhNGIyZGNmYTZjOTU2YWJhLmJpbmRQb3B1cChwb3B1cF8yZmJlNTg0OGMwMTg0YWFlYmFhZDYwYTJiNWE0MDU1Yyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lODQ3MGI2MDYwNzA0NGY0OWFjNDdmNTk0NjZiMzgwNiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc4MjczNjQsLTc5LjQ0MjI1OTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjZmNWY2ZTQwYjI0NDc5MjllODcyM2I0YmMyMDU5NjkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOGMzMjhmZTA0MWUyNGI2NzkwNjRjOWU5ODEyZjkzZDkgPSAkKCc8ZGl2IGlkPSJodG1sXzhjMzI4ZmUwNDFlMjRiNjc5MDY0YzllOTgxMmY5M2Q5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XaWxsb3dkYWxlIFdlc3QgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82NmY1ZjZlNDBiMjQ0NzkyOWU4NzIzYjRiYzIwNTk2OS5zZXRDb250ZW50KGh0bWxfOGMzMjhmZTA0MWUyNGI2NzkwNjRjOWU5ODEyZjkzZDkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZTg0NzBiNjA2MDcwNDRmNDlhYzQ3ZjU5NDY2YjM4MDYuYmluZFBvcHVwKHBvcHVwXzY2ZjVmNmU0MGIyNDQ3OTI5ZTg3MjNiNGJjMjA1OTY5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2MwOTYzMzEwMmZlNjRlYzc4ODZiNGVhZDdkYjI3ZDc2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzUzMjU4NiwtNzkuMzI5NjU2NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmY5NjRmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmOTY0ZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jYTMxOWYyOWNhMDA0MDc5ODgzNmZjNzZmNzllZWM5YSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wMDM0MzI5ZWE5MmM0ZTQ2YTk5MDM2ODIyNjk3YzFmZCA9ICQoJzxkaXYgaWQ9Imh0bWxfMDAzNDMyOWVhOTJjNGU0NmE5OTAzNjgyMjY5N2MxZmQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlBhcmt3b29kcyBDbHVzdGVyIDU8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2NhMzE5ZjI5Y2EwMDQwNzk4ODM2ZmM3NmY3OWVlYzlhLnNldENvbnRlbnQoaHRtbF8wMDM0MzI5ZWE5MmM0ZTQ2YTk5MDM2ODIyNjk3YzFmZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jMDk2MzMxMDJmZTY0ZWM3ODg2YjRlYWQ3ZGIyN2Q3Ni5iaW5kUG9wdXAocG9wdXBfY2EzMTlmMjljYTAwNDA3OTg4MzZmYzc2Zjc5ZWVjOWEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMGIyNDgwYTdlNTAxNDRkZGJjYWI3MDYyNjhhYTE4YjEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NDU5MDU3OTk5OTk5OTYsLTc5LjM1MjE4OF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mNWJjZjgxYjgzNmI0YWIzOTNjZDE5YzJkODZlNDk2YiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iYjlhZmU4ZmI3NGY0NjU2YTJjODRmNjA5MDhlNTZiOSA9ICQoJzxkaXYgaWQ9Imh0bWxfYmI5YWZlOGZiNzRmNDY1NmEyYzg0ZjYwOTA4ZTU2YjkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvbiBNaWxscyBOb3J0aCBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Y1YmNmODFiODM2YjRhYjM5M2NkMTljMmQ4NmU0OTZiLnNldENvbnRlbnQoaHRtbF9iYjlhZmU4ZmI3NGY0NjU2YTJjODRmNjA5MDhlNTZiOSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wYjI0ODBhN2U1MDE0NGRkYmNhYjcwNjI2OGFhMThiMS5iaW5kUG9wdXAocG9wdXBfZjViY2Y4MWI4MzZiNGFiMzkzY2QxOWMyZDg2ZTQ5NmIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfN2QwNjZhMzdmZmYxNGI5ZDgwYzI5OTRjOTk2ZTM2MjEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MjU4OTk3MDAwMDAwMSwtNzkuMzQwOTIzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzE3ODYxNTUzNWJlYTQ5MjJiMjc0NGFkZTY1YzAyMzAyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzk1NjcyNWFhYmI0MDQ3NDY4YTE4YTNhMmU5ZTZiMTkzID0gJCgnPGRpdiBpZD0iaHRtbF85NTY3MjVhYWJiNDA0NzQ2OGExOGEzYTJlOWU2YjE5MyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RmxlbWluZ2RvbiBQYXJrLCBEb24gTWlsbHMgU291dGggQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xNzg2MTU1MzViZWE0OTIyYjI3NDRhZGU2NWMwMjMwMi5zZXRDb250ZW50KGh0bWxfOTU2NzI1YWFiYjQwNDc0NjhhMThhM2EyZTllNmIxOTMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfN2QwNjZhMzdmZmYxNGI5ZDgwYzI5OTRjOTk2ZTM2MjEuYmluZFBvcHVwKHBvcHVwXzE3ODYxNTUzNWJlYTQ5MjJiMjc0NGFkZTY1YzAyMzAyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2U3OGJiZjU4NDA2NTQ2NTZiZTMzOTNlY2YzYTcxZmQwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzU0MzI4MywtNzkuNDQyMjU5M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83ZmVlOWU5NGNmYTI0OThlODI2OWNmMzk1N2U3YzYzZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jYTViMmM2ZjUzZTA0ODdkYWY0ZTU4ZDI5NDJmZmZkYiA9ICQoJzxkaXYgaWQ9Imh0bWxfY2E1YjJjNmY1M2UwNDg3ZGFmNGU1OGQyOTQyZmZmZGIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJhdGh1cnN0IE1hbm9yLCBEb3duc3ZpZXcgTm9ydGgsIFdpbHNvbiBIZWlnaHRzIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfN2ZlZTllOTRjZmEyNDk4ZTgyNjljZjM5NTdlN2M2M2Uuc2V0Q29udGVudChodG1sX2NhNWIyYzZmNTNlMDQ4N2RhZjRlNThkMjk0MmZmZmRiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2U3OGJiZjU4NDA2NTQ2NTZiZTMzOTNlY2YzYTcxZmQwLmJpbmRQb3B1cChwb3B1cF83ZmVlOWU5NGNmYTI0OThlODI2OWNmMzk1N2U3YzYzZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kNGU5OWQyYTI2ODg0ZjkzYThiMjc5NmMwNDJmZjljOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc2Nzk4MDMsLTc5LjQ4NzI2MTkwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2E4M2NiNDk0NzYwYTRkMWM4ZmY3NTI2ZGY2NDkyZjNmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2YwNzA0ZTIzOWUzYzQzYzZhOTQwODI1NWU3MmMzM2Y5ID0gJCgnPGRpdiBpZD0iaHRtbF9mMDcwNGUyMzllM2M0M2M2YTk0MDgyNTVlNzJjMzNmOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Tm9ydGh3b29kIFBhcmssIFlvcmsgVW5pdmVyc2l0eSBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2E4M2NiNDk0NzYwYTRkMWM4ZmY3NTI2ZGY2NDkyZjNmLnNldENvbnRlbnQoaHRtbF9mMDcwNGUyMzllM2M0M2M2YTk0MDgyNTVlNzJjMzNmOSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9kNGU5OWQyYTI2ODg0ZjkzYThiMjc5NmMwNDJmZjljOC5iaW5kUG9wdXAocG9wdXBfYTgzY2I0OTQ3NjBhNGQxYzhmZjc1MjZkZjY0OTJmM2YpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjk4MGVhZTgxZDkwNGMyZTgwMGVjMWUwYTFkMmJmNDAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43Mzc0NzMyMDAwMDAwMDQsLTc5LjQ2NDc2MzI5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzllYTlkZGM3NTc2YjQxN2FiYjVmM2U5MmUzMDYyN2IzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzJkMmE1MGU2MTkxYTRkZjZiYmQ4ZDE3MmVmMDk4NjRlID0gJCgnPGRpdiBpZD0iaHRtbF8yZDJhNTBlNjE5MWE0ZGY2YmJkOGQxNzJlZjA5ODY0ZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q0ZCIFRvcm9udG8sIERvd25zdmlldyBFYXN0IENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOWVhOWRkYzc1NzZiNDE3YWJiNWYzZTkyZTMwNjI3YjMuc2V0Q29udGVudChodG1sXzJkMmE1MGU2MTkxYTRkZjZiYmQ4ZDE3MmVmMDk4NjRlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2Y5ODBlYWU4MWQ5MDRjMmU4MDBlYzFlMGExZDJiZjQwLmJpbmRQb3B1cChwb3B1cF85ZWE5ZGRjNzU3NmI0MTdhYmI1ZjNlOTJlMzA2MjdiMyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82NjVhYTIxNzJhODc0NTFhOGFiMWNlNzc1NjMwNjY5MyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjczOTAxNDYsLTc5LjUwNjk0MzZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjYzMjI4NjdiYWZhNGJhYThmNzcxMTE5ZTU2YTFiZTYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNGEwMzg1YzZjYzk1NDc5OGExNDQ3NTNkYjY5ZTQ1MTEgPSAkKCc8ZGl2IGlkPSJodG1sXzRhMDM4NWM2Y2M5NTQ3OThhMTQ0NzUzZGI2OWU0NTExIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Eb3duc3ZpZXcgV2VzdCBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzY2MzIyODY3YmFmYTRiYWE4Zjc3MTExOWU1NmExYmU2LnNldENvbnRlbnQoaHRtbF80YTAzODVjNmNjOTU0Nzk4YTE0NDc1M2RiNjllNDUxMSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82NjVhYTIxNzJhODc0NTFhOGFiMWNlNzc1NjMwNjY5My5iaW5kUG9wdXAocG9wdXBfNjYzMjI4NjdiYWZhNGJhYThmNzcxMTE5ZTU2YTFiZTYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZmRkOTNkOGQ4NzJmNDQ2YmE0MmUyZWZhYWRmM2YzNjUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43Mjg0OTY0LC03OS40OTU2OTc0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jZjA0MzZkYTZlMjc0MDJmODE3NmRiMmVlOGZlYWVjYiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lYmJlMmM3NTdhNTQ0NTJjOThlNjI0MWM3MDNhMTE3MSA9ICQoJzxkaXYgaWQ9Imh0bWxfZWJiZTJjNzU3YTU0NDUyYzk4ZTYyNDFjNzAzYTExNzEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvd25zdmlldyBDZW50cmFsIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfY2YwNDM2ZGE2ZTI3NDAyZjgxNzZkYjJlZThmZWFlY2Iuc2V0Q29udGVudChodG1sX2ViYmUyYzc1N2E1NDQ1MmM5OGU2MjQxYzcwM2ExMTcxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2ZkZDkzZDhkODcyZjQ0NmJhNDJlMmVmYWFkZjNmMzY1LmJpbmRQb3B1cChwb3B1cF9jZjA0MzZkYTZlMjc0MDJmODE3NmRiMmVlOGZlYWVjYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zNDAzYjQ1ZDA0Y2M0NTE2YmJlMGM3NzU2Mjc2ZTkwMyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc2MTYzMTMsLTc5LjUyMDk5OTQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2ZmNGRlZTI3ZGRhZTQ3YWM5MTBmOGUxZDRhOTQ2NWIwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2U3OGJjMjczYzQwNjRjMjliYTMxYWViM2U3ZTliZDlhID0gJCgnPGRpdiBpZD0iaHRtbF9lNzhiYzI3M2M0MDY0YzI5YmEzMWFlYjNlN2U5YmQ5YSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RG93bnN2aWV3IE5vcnRod2VzdCBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2ZmNGRlZTI3ZGRhZTQ3YWM5MTBmOGUxZDRhOTQ2NWIwLnNldENvbnRlbnQoaHRtbF9lNzhiYzI3M2M0MDY0YzI5YmEzMWFlYjNlN2U5YmQ5YSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zNDAzYjQ1ZDA0Y2M0NTE2YmJlMGM3NzU2Mjc2ZTkwMy5iaW5kUG9wdXAocG9wdXBfZmY0ZGVlMjdkZGFlNDdhYzkxMGY4ZTFkNGE5NDY1YjApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMWJlODI1OTAxYmVhNDc5OThiNmY0NzQ4ZTg5ZWNiZGEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MjU4ODIyOTk5OTk5OTUsLTc5LjMxNTU3MTU5OTk5OTk4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2FhZDA1NzU2MTI5ZDQ1YzJiYzhhZDI2NWRiNDZjNWVmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzMwYzcyZTZlMTAwYzQ2NDJhNDQwNmE1YzBkMDJlYTUzID0gJCgnPGRpdiBpZD0iaHRtbF8zMGM3MmU2ZTEwMGM0NjQyYTQ0MDZhNWMwZDAyZWE1MyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VmljdG9yaWEgVmlsbGFnZSBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2FhZDA1NzU2MTI5ZDQ1YzJiYzhhZDI2NWRiNDZjNWVmLnNldENvbnRlbnQoaHRtbF8zMGM3MmU2ZTEwMGM0NjQyYTQ0MDZhNWMwZDAyZWE1Myk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xYmU4MjU5MDFiZWE0Nzk5OGI2ZjQ3NDhlODllY2JkYS5iaW5kUG9wdXAocG9wdXBfYWFkMDU3NTYxMjlkNDVjMmJjOGFkMjY1ZGI0NmM1ZWYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYWIwYTJkYWQ4ZTM4NDhmYWJkNzI4ZWM3MzA2ZmUzZjggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MDYzOTcyLC03OS4zMDk5MzddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNmE2MjYzNzQzYWE0NDBkNGE1ZmZkNzI1N2UwYjBkYWIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfODM1NzZlNTliMTdmNDY2NmI3OWE3N2YzMTY3NzcwMmMgPSAkKCc8ZGl2IGlkPSJodG1sXzgzNTc2ZTU5YjE3ZjQ2NjZiNzlhNzdmMzE2Nzc3MDJjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Xb29kYmluZSBHYXJkZW5zLCBQYXJrdmlldyBIaWxsIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNmE2MjYzNzQzYWE0NDBkNGE1ZmZkNzI1N2UwYjBkYWIuc2V0Q29udGVudChodG1sXzgzNTc2ZTU5YjE3ZjQ2NjZiNzlhNzdmMzE2Nzc3MDJjKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2FiMGEyZGFkOGUzODQ4ZmFiZDcyOGVjNzMwNmZlM2Y4LmJpbmRQb3B1cChwb3B1cF82YTYyNjM3NDNhYTQ0MGQ0YTVmZmQ3MjU3ZTBiMGRhYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zZjY5NWU4ZDQ3MjM0OGY1YmI0ODRlYzQ1MzJkZDgzZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY5NTM0MzkwMDAwMDAwNSwtNzkuMzE4Mzg4N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85NzdiYzMzZTIyMDA0YjY3ODVjZjFjZWQ3N2NmMjZhOSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hYzZiNTI5NDVkNTc0ZDgxYjgwYmRhOWY3NDZkN2VjNCA9ICQoJzxkaXYgaWQ9Imh0bWxfYWM2YjUyOTQ1ZDU3NGQ4MWI4MGJkYTlmNzQ2ZDdlYzQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldvb2RiaW5lIEhlaWdodHMgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85NzdiYzMzZTIyMDA0YjY3ODVjZjFjZWQ3N2NmMjZhOS5zZXRDb250ZW50KGh0bWxfYWM2YjUyOTQ1ZDU3NGQ4MWI4MGJkYTlmNzQ2ZDdlYzQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfM2Y2OTVlOGQ0NzIzNDhmNWJiNDg0ZWM0NTMyZGQ4M2UuYmluZFBvcHVwKHBvcHVwXzk3N2JjMzNlMjIwMDRiNjc4NWNmMWNlZDc3Y2YyNmE5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzg3OGJmYjg3Nzg2ODQ3MzY4M2ExZWFkZTIwMmMzNTg1ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjc2MzU3Mzk5OTk5OTksLTc5LjI5MzAzMTJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzRiYTQ1MDk4MmM1NDNlMmEzMWRjMGNlMjUxMTY4ZTIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYjQ3MjFlOTY0MDE2NDVlMWJiNTBlZTQ4NjhkY2ZkNjggPSAkKCc8ZGl2IGlkPSJodG1sX2I0NzIxZTk2NDAxNjQ1ZTFiYjUwZWU0ODY4ZGNmZDY4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UaGUgQmVhY2hlcyBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzM0YmE0NTA5ODJjNTQzZTJhMzFkYzBjZTI1MTE2OGUyLnNldENvbnRlbnQoaHRtbF9iNDcyMWU5NjQwMTY0NWUxYmI1MGVlNDg2OGRjZmQ2OCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84NzhiZmI4Nzc4Njg0NzM2ODNhMWVhZGUyMDJjMzU4NS5iaW5kUG9wdXAocG9wdXBfMzRiYTQ1MDk4MmM1NDNlMmEzMWRjMGNlMjUxMTY4ZTIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMjIzMjIzOTc2NmNjNGUxNDgxYmFiM2VmMGYxMDczMzYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MDkwNjA0LC03OS4zNjM0NTE3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzcxMThhNDEwNThjNTRiOTliYzIzOGE2NTRiNTQyOGJjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2NiMmEzNjU0OTJmMjRiYzk4ZGNjY2Y0ZWVjNGRmMTRjID0gJCgnPGRpdiBpZD0iaHRtbF9jYjJhMzY1NDkyZjI0YmM5OGRjY2NmNGVlYzRkZjE0YyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TGVhc2lkZSBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzcxMThhNDEwNThjNTRiOTliYzIzOGE2NTRiNTQyOGJjLnNldENvbnRlbnQoaHRtbF9jYjJhMzY1NDkyZjI0YmM5OGRjY2NmNGVlYzRkZjE0Yyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yMjMyMjM5NzY2Y2M0ZTE0ODFiYWIzZWYwZjEwNzMzNi5iaW5kUG9wdXAocG9wdXBfNzExOGE0MTA1OGM1NGI5OWJjMjM4YTY1NGI1NDI4YmMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTg1MTgyMWU2ZTdiNGQ0YTlhZDNlZTA5YzVlODM3YjEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MDUzNjg5LC03OS4zNDkzNzE5MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yYTgzYmUwN2VlNTU0NzkxODcxOTg4NTBlMGY2ZGY5NiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82NDFiNmJlY2IzOTQ0YWQ3YWM1ODRlNGZhM2I1NTdiNyA9ICQoJzxkaXYgaWQ9Imh0bWxfNjQxYjZiZWNiMzk0NGFkN2FjNTg0ZTRmYTNiNTU3YjciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlRob3JuY2xpZmZlIFBhcmsgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yYTgzYmUwN2VlNTU0NzkxODcxOTg4NTBlMGY2ZGY5Ni5zZXRDb250ZW50KGh0bWxfNjQxYjZiZWNiMzk0NGFkN2FjNTg0ZTRmYTNiNTU3YjcpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNTg1MTgyMWU2ZTdiNGQ0YTlhZDNlZTA5YzVlODM3YjEuYmluZFBvcHVwKHBvcHVwXzJhODNiZTA3ZWU1NTQ3OTE4NzE5ODg1MGUwZjZkZjk2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzFjMjg5NTBhNzMyMTQyNjU4YTAyOWE5OGQ1Y2UyYWMyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjg1MzQ3LC03OS4zMzgxMDY1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjk2NGYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmY5NjRmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzM3NDJkMzU3NGM4ZDQ4MzhiMmMyMzlhOTg4ZTMyZDllID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2I5N2YwNDk5MWE3NDQzNzM4MWNhNjA3Mjc3MjdkMjVlID0gJCgnPGRpdiBpZD0iaHRtbF9iOTdmMDQ5OTFhNzQ0MzczODFjYTYwNzI3NzI3ZDI1ZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RWFzdCBUb3JvbnRvIENsdXN0ZXIgNTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzc0MmQzNTc0YzhkNDgzOGIyYzIzOWE5ODhlMzJkOWUuc2V0Q29udGVudChodG1sX2I5N2YwNDk5MWE3NDQzNzM4MWNhNjA3Mjc3MjdkMjVlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzFjMjg5NTBhNzMyMTQyNjU4YTAyOWE5OGQ1Y2UyYWMyLmJpbmRQb3B1cChwb3B1cF8zNzQyZDM1NzRjOGQ0ODM4YjJjMjM5YTk4OGUzMmQ5ZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mYWVmZTJiNjNkYzg0MTgwODFmNjljNWFkNGQyYTYwMCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY3OTU1NzEsLTc5LjM1MjE4OF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xMzY5M2ZlNWMzNWE0Zjk2OTU4MjM3YTM4YTgzOTE5NSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hMzU3ZmYyNmQ0MDA0MDY4YjBlNDNjNzJjNjQzZWZlNyA9ICQoJzxkaXYgaWQ9Imh0bWxfYTM1N2ZmMjZkNDAwNDA2OGIwZTQzYzcyYzY0M2VmZTciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlRoZSBEYW5mb3J0aCBXZXN0LCBSaXZlcmRhbGUgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xMzY5M2ZlNWMzNWE0Zjk2OTU4MjM3YTM4YTgzOTE5NS5zZXRDb250ZW50KGh0bWxfYTM1N2ZmMjZkNDAwNDA2OGIwZTQzYzcyYzY0M2VmZTcpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZmFlZmUyYjYzZGM4NDE4MDgxZjY5YzVhZDRkMmE2MDAuYmluZFBvcHVwKHBvcHVwXzEzNjkzZmU1YzM1YTRmOTY5NTgyMzdhMzhhODM5MTk1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2ZkZGQ1NTFmNDFiYjQzZmFhY2NlYzcwNDAyODcxYzY1ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjY4OTk4NSwtNzkuMzE1NTcxNTk5OTk5OThdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOWVlNTVmOGExYWQzNGQ0ZThjMzNjMzRkMDY2NWM1MzkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZTcwNDNhODJiMmQxNGRiMmFlOGU4NmE0N2Q3OTU4NmQgPSAkKCc8ZGl2IGlkPSJodG1sX2U3MDQzYTgyYjJkMTRkYjJhZThlODZhNDdkNzk1ODZkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UaGUgQmVhY2hlcyBXZXN0LCBJbmRpYSBCYXphYXIgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85ZWU1NWY4YTFhZDM0ZDRlOGMzM2MzNGQwNjY1YzUzOS5zZXRDb250ZW50KGh0bWxfZTcwNDNhODJiMmQxNGRiMmFlOGU4NmE0N2Q3OTU4NmQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZmRkZDU1MWY0MWJiNDNmYWFjY2VjNzA0MDI4NzFjNjUuYmluZFBvcHVwKHBvcHVwXzllZTU1ZjhhMWFkMzRkNGU4YzMzYzM0ZDA2NjVjNTM5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzEzMmQ4Y2I3NWMxZTQ5NDNhMTA2ZGRmYmM1MTA5ZTlkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjU5NTI1NSwtNzkuMzQwOTIzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzIyZDVmY2RmMzRiYTQwYmI4OTYzYmQ3NjU4N2UxMmNmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzYwNWE4ZDgxNWIxODRkNjVhNTFkNTczZDIyZGE5N2FlID0gJCgnPGRpdiBpZD0iaHRtbF82MDVhOGQ4MTViMTg0ZDY1YTUxZDU3M2QyMmRhOTdhZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3R1ZGlvIERpc3RyaWN0IENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjJkNWZjZGYzNGJhNDBiYjg5NjNiZDc2NTg3ZTEyY2Yuc2V0Q29udGVudChodG1sXzYwNWE4ZDgxNWIxODRkNjVhNTFkNTczZDIyZGE5N2FlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzEzMmQ4Y2I3NWMxZTQ5NDNhMTA2ZGRmYmM1MTA5ZTlkLmJpbmRQb3B1cChwb3B1cF8yMmQ1ZmNkZjM0YmE0MGJiODk2M2JkNzY1ODdlMTJjZik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jMWU3ZmVjMGIwNjA0NTk4ODRmYzVmMzE4NjI2NWIxYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcyODAyMDUsLTc5LjM4ODc5MDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmOTY0ZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjk2NGYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZTk0ZTIxM2IyZmU4NGE5OThlYTk0OWRlMmUyYTE3ZWYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNjdkMWI4NGZkZTcwNGE1NWIwM2YwOWNiODUzODJlZDUgPSAkKCc8ZGl2IGlkPSJodG1sXzY3ZDFiODRmZGU3MDRhNTViMDNmMDljYjg1MzgyZWQ1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5MYXdyZW5jZSBQYXJrIENsdXN0ZXIgNTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZTk0ZTIxM2IyZmU4NGE5OThlYTk0OWRlMmUyYTE3ZWYuc2V0Q29udGVudChodG1sXzY3ZDFiODRmZGU3MDRhNTViMDNmMDljYjg1MzgyZWQ1KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2MxZTdmZWMwYjA2MDQ1OTg4NGZjNWYzMTg2MjY1YjFiLmJpbmRQb3B1cChwb3B1cF9lOTRlMjEzYjJmZTg0YTk5OGVhOTQ5ZGUyZTJhMTdlZik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yOTg5NWE4NWViMTE0N2Q0YjcyYTE2NjdmMGYyNTczYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcxMjc1MTEsLTc5LjM5MDE5NzVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMDQ2MWE0ODA5NzQ3NGE0ZGIwMDg5NGNjN2I2Zjc1NTMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzMxYjIyYzE1NmE0NDE1Mzg1OTk0ZjRlMmJlOTE3M2QgPSAkKCc8ZGl2IGlkPSJodG1sXzczMWIyMmMxNTZhNDQxNTM4NTk5NGY0ZTJiZTkxNzNkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5EYXZpc3ZpbGxlIE5vcnRoIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDQ2MWE0ODA5NzQ3NGE0ZGIwMDg5NGNjN2I2Zjc1NTMuc2V0Q29udGVudChodG1sXzczMWIyMmMxNTZhNDQxNTM4NTk5NGY0ZTJiZTkxNzNkKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzI5ODk1YTg1ZWIxMTQ3ZDRiNzJhMTY2N2YwZjI1NzNiLmJpbmRQb3B1cChwb3B1cF8wNDYxYTQ4MDk3NDc0YTRkYjAwODk0Y2M3YjZmNzU1Myk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iNjkyNThkY2Q3MGI0ZGU0ODNiZjlkMWU2MDc4YzZjYyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcxNTM4MzQsLTc5LjQwNTY3ODQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzVlN2QwNWZkZDI5ODRiMGRiY2VhMWY0NjIyNjdiZTJhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2E3M2Y4NzQ0YzM0NTRmNDg4YjFhZTk1MjVlZjE2MWY5ID0gJCgnPGRpdiBpZD0iaHRtbF9hNzNmODc0NGMzNDU0ZjQ4OGIxYWU5NTI1ZWYxNjFmOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Tm9ydGggVG9yb250byBXZXN0IENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNWU3ZDA1ZmRkMjk4NGIwZGJjZWExZjQ2MjI2N2JlMmEuc2V0Q29udGVudChodG1sX2E3M2Y4NzQ0YzM0NTRmNDg4YjFhZTk1MjVlZjE2MWY5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2I2OTI1OGRjZDcwYjRkZTQ4M2JmOWQxZTYwNzhjNmNjLmJpbmRQb3B1cChwb3B1cF81ZTdkMDVmZGQyOTg0YjBkYmNlYTFmNDYyMjY3YmUyYSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wM2NmZDhhN2FhZDk0OTVlYmJhYjllZmQ5OGI5Y2ZmMSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcwNDMyNDQsLTc5LjM4ODc5MDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYTQxNmFkMjdiZTIzNDVkOTgzMmM2MDQ3ZTA4MGU0YzYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMTQwYTJjZGNjZGVmNGIyMjk4MGYwYzEyNzUwYTg0ZjkgPSAkKCc8ZGl2IGlkPSJodG1sXzE0MGEyY2RjY2RlZjRiMjI5ODBmMGMxMjc1MGE4NGY5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5EYXZpc3ZpbGxlIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYTQxNmFkMjdiZTIzNDVkOTgzMmM2MDQ3ZTA4MGU0YzYuc2V0Q29udGVudChodG1sXzE0MGEyY2RjY2RlZjRiMjI5ODBmMGMxMjc1MGE4NGY5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzAzY2ZkOGE3YWFkOTQ5NWViYmFiOWVmZDk4YjljZmYxLmJpbmRQb3B1cChwb3B1cF9hNDE2YWQyN2JlMjM0NWQ5ODMyYzYwNDdlMDgwZTRjNik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80MjgzYjVjM2RhNDA0MWIxYTg0OGRhMDFlZDc0OWMwMCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY4OTU3NDMsLTc5LjM4MzE1OTkwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjk2NGYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmY5NjRmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2VlZDZmYTIyZWRlYjQxYWI5YWMzOTlkZGQ3MzdjNjZmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzlhNTE5NjZlNjBkMjRhMzZiNzgyMzE3ZTZiM2UwN2ZkID0gJCgnPGRpdiBpZD0iaHRtbF85YTUxOTY2ZTYwZDI0YTM2Yjc4MjMxN2U2YjNlMDdmZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TW9vcmUgUGFyaywgU3VtbWVyaGlsbCBFYXN0IENsdXN0ZXIgNTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZWVkNmZhMjJlZGViNDFhYjlhYzM5OWRkZDczN2M2NmYuc2V0Q29udGVudChodG1sXzlhNTE5NjZlNjBkMjRhMzZiNzgyMzE3ZTZiM2UwN2ZkKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzQyODNiNWMzZGE0MDQxYjFhODQ4ZGEwMWVkNzQ5YzAwLmJpbmRQb3B1cChwb3B1cF9lZWQ2ZmEyMmVkZWI0MWFiOWFjMzk5ZGRkNzM3YzY2Zik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84NzI0NTY2NTExMTE0OTQzYTZhNTJhNWE0NjRjZTU3MSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY4NjQxMjI5OTk5OTk5LC03OS40MDAwNDkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzRlODA3MmVjZTUxYjRjZjg5OWQ0ZWExNzUzY2Y4M2JiID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2I5MDMwOTQwYTlmMjQ1NWRiMzJlMDJmMDg5NWY4MTc2ID0gJCgnPGRpdiBpZD0iaHRtbF9iOTAzMDk0MGE5ZjI0NTVkYjMyZTAyZjA4OTVmODE3NiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RGVlciBQYXJrLCBGb3Jlc3QgSGlsbCBTRSwgUmF0aG5lbGx5LCBTb3V0aCBIaWxsLCBTdW1tZXJoaWxsIFdlc3QgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80ZTgwNzJlY2U1MWI0Y2Y4OTlkNGVhMTc1M2NmODNiYi5zZXRDb250ZW50KGh0bWxfYjkwMzA5NDBhOWYyNDU1ZGIzMmUwMmYwODk1ZjgxNzYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODcyNDU2NjUxMTExNDk0M2E2YTUyYTVhNDY0Y2U1NzEuYmluZFBvcHVwKHBvcHVwXzRlODA3MmVjZTUxYjRjZjg5OWQ0ZWExNzUzY2Y4M2JiKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzk0YmIwMzBmNWZlOTQwYTE4MGJmNDk5OGZhZTc3NzFjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjc5NTYyNiwtNzkuMzc3NTI5NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmOTY0ZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjk2NGYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjJiOWQ5NTZmYWEyNGI5Njg2NjE5MzIyYTJiYWYxN2IgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjQ5Y2RjNWMwNmM1NDJlODljNjQ3N2U4MWI2NWQ4ZmMgPSAkKCc8ZGl2IGlkPSJodG1sX2Y0OWNkYzVjMDZjNTQyZTg5YzY0NzdlODFiNjVkOGZjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Sb3NlZGFsZSBDbHVzdGVyIDU8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2YyYjlkOTU2ZmFhMjRiOTY4NjYxOTMyMmEyYmFmMTdiLnNldENvbnRlbnQoaHRtbF9mNDljZGM1YzA2YzU0MmU4OWM2NDc3ZTgxYjY1ZDhmYyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85NGJiMDMwZjVmZTk0MGExODBiZjQ5OThmYWU3NzcxYy5iaW5kUG9wdXAocG9wdXBfZjJiOWQ5NTZmYWEyNGI5Njg2NjE5MzIyYTJiYWYxN2IpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTYzZTkyYjEwY2VhNDNkYzkxMGFhYmMzNTc4MjQ3NWMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Njc5NjcsLTc5LjM2NzY3NTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZTk5ZTUzZWI0MWNhNDExZmFkMTNkNTg1OWVhMTM0YTAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZWM0ODcxZmJhNjE1NDg5MzgwZjFlODRiZTE2NDBkNTIgPSAkKCc8ZGl2IGlkPSJodG1sX2VjNDg3MWZiYTYxNTQ4OTM4MGYxZTg0YmUxNjQwZDUyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DYWJiYWdldG93biwgU3QuIEphbWVzIFRvd24gQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lOTllNTNlYjQxY2E0MTFmYWQxM2Q1ODU5ZWExMzRhMC5zZXRDb250ZW50KGh0bWxfZWM0ODcxZmJhNjE1NDg5MzgwZjFlODRiZTE2NDBkNTIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNTYzZTkyYjEwY2VhNDNkYzkxMGFhYmMzNTc4MjQ3NWMuYmluZFBvcHVwKHBvcHVwX2U5OWU1M2ViNDFjYTQxMWZhZDEzZDU4NTllYTEzNGEwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2JlMzIxM2Y2ZmQxZDRkMDI4NjQ4ZmU4NWE3ZDhhN2E4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjY1ODU5OSwtNzkuMzgzMTU5OTAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNDcyYmM3ZWJhODVkNGE5ZDg2MzQ4MGNmMzE5NDNmODUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfM2FlOTdiZWU0MzNlNGQwMWJlMDU1NDY0YmExZDY1OWUgPSAkKCc8ZGl2IGlkPSJodG1sXzNhZTk3YmVlNDMzZTRkMDFiZTA1NTQ2NGJhMWQ2NTllIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DaHVyY2ggYW5kIFdlbGxlc2xleSBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzQ3MmJjN2ViYTg1ZDRhOWQ4NjM0ODBjZjMxOTQzZjg1LnNldENvbnRlbnQoaHRtbF8zYWU5N2JlZTQzM2U0ZDAxYmUwNTU0NjRiYTFkNjU5ZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9iZTMyMTNmNmZkMWQ0ZDAyODY0OGZlODVhN2Q4YTdhOC5iaW5kUG9wdXAocG9wdXBfNDcyYmM3ZWJhODVkNGE5ZDg2MzQ4MGNmMzE5NDNmODUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNzhmNGNjNDY2M2VlNDMwOGI0MjE0NTMzMDEyMTg4ZTEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NTQyNTk5LC03OS4zNjA2MzU5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzc3YThiOTY0NzVjODQ0ZmY4YWM1OTkwMzY4NDFiN2E2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzVmYThiOWIzNDYxNTRiYWFhMjRiNDhkMTdkMjY2YjdjID0gJCgnPGRpdiBpZD0iaHRtbF81ZmE4YjliMzQ2MTU0YmFhYTI0YjQ4ZDE3ZDI2NmI3YyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SGFyYm91cmZyb250IENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNzdhOGI5NjQ3NWM4NDRmZjhhYzU5OTAzNjg0MWI3YTYuc2V0Q29udGVudChodG1sXzVmYThiOWIzNDYxNTRiYWFhMjRiNDhkMTdkMjY2YjdjKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzc4ZjRjYzQ2NjNlZTQzMDhiNDIxNDUzMzAxMjE4OGUxLmJpbmRQb3B1cChwb3B1cF83N2E4Yjk2NDc1Yzg0NGZmOGFjNTk5MDM2ODQxYjdhNik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yYWZlODkxMGJlYzc0ZjNjYTBmZTRmODY3NzA0NzE0ZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1NzE2MTgsLTc5LjM3ODkzNzA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzhmM2MzZTA4ZWUxYzRmYmI5N2ExZGI2NDQ4YTNlYTkyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzEwZTQxMTU1MTk1OTQ2OTdiM2NjNDIzZmZlY2I2ODM5ID0gJCgnPGRpdiBpZD0iaHRtbF8xMGU0MTE1NTE5NTk0Njk3YjNjYzQyM2ZmZWNiNjgzOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UnllcnNvbiwgR2FyZGVuIERpc3RyaWN0IENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOGYzYzNlMDhlZTFjNGZiYjk3YTFkYjY0NDhhM2VhOTIuc2V0Q29udGVudChodG1sXzEwZTQxMTU1MTk1OTQ2OTdiM2NjNDIzZmZlY2I2ODM5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzJhZmU4OTEwYmVjNzRmM2NhMGZlNGY4Njc3MDQ3MTRkLmJpbmRQb3B1cChwb3B1cF84ZjNjM2UwOGVlMWM0ZmJiOTdhMWRiNjQ0OGEzZWE5Mik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80NDQ1Y2YwNjVkMTY0MzY5OGMxNjZmZGE0YzYyZTBmNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1MTQ5MzksLTc5LjM3NTQxNzldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZDFmYTU5ZGQ5ZTI2NGI4MTk5MzMxYzEwMTA2MDdjOTAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMmMyMTY2MDNkYTcxNDVkMDkyNjIwMWY0MGUyZWNlNzQgPSAkKCc8ZGl2IGlkPSJodG1sXzJjMjE2NjAzZGE3MTQ1ZDA5MjYyMDFmNDBlMmVjZTc0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TdC4gSmFtZXMgVG93biBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2QxZmE1OWRkOWUyNjRiODE5OTMzMWMxMDEwNjA3YzkwLnNldENvbnRlbnQoaHRtbF8yYzIxNjYwM2RhNzE0NWQwOTI2MjAxZjQwZTJlY2U3NCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80NDQ1Y2YwNjVkMTY0MzY5OGMxNjZmZGE0YzYyZTBmNC5iaW5kUG9wdXAocG9wdXBfZDFmYTU5ZGQ5ZTI2NGI4MTk5MzMxYzEwMTA2MDdjOTApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMjE1NjliOWZiMzc5NDdhMzgwMzAzMDdmMjVmNmZmYjkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDQ3NzA3OTk5OTk5OTYsLTc5LjM3MzMwNjRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYmE4YmFjN2M2ZTY1NGYzOTk2YzUxZjgxY2QzYzVjOWIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZWE1MGE5NmFiMzJlNDUwZGI3Mjg5ZGMxZjNiMjI1MDEgPSAkKCc8ZGl2IGlkPSJodG1sX2VhNTBhOTZhYjMyZTQ1MGRiNzI4OWRjMWYzYjIyNTAxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CZXJjenkgUGFyayBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2JhOGJhYzdjNmU2NTRmMzk5NmM1MWY4MWNkM2M1YzliLnNldENvbnRlbnQoaHRtbF9lYTUwYTk2YWIzMmU0NTBkYjcyODlkYzFmM2IyMjUwMSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yMTU2OWI5ZmIzNzk0N2EzODAzMDMwN2YyNWY2ZmZiOS5iaW5kUG9wdXAocG9wdXBfYmE4YmFjN2M2ZTY1NGYzOTk2YzUxZjgxY2QzYzVjOWIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMjhlNTkzYWEzOTlhNDQ2Y2JkMDdiMDE5ZWQ4ZWZlOTggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NTc5NTI0LC03OS4zODczODI2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzM0ZWFiMTJkNzcyMDQ0NmQ5ZTM1YTEyY2ZlYTM0ZWI5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzNlNTk4MzA1MDRjZjRhZmJhYWQyMTUyYTgwNTczYzk5ID0gJCgnPGRpdiBpZD0iaHRtbF8zZTU5ODMwNTA0Y2Y0YWZiYWFkMjE1MmE4MDU3M2M5OSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q2VudHJhbCBCYXkgU3RyZWV0IENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzRlYWIxMmQ3NzIwNDQ2ZDllMzVhMTJjZmVhMzRlYjkuc2V0Q29udGVudChodG1sXzNlNTk4MzA1MDRjZjRhZmJhYWQyMTUyYTgwNTczYzk5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzI4ZTU5M2FhMzk5YTQ0NmNiZDA3YjAxOWVkOGVmZTk4LmJpbmRQb3B1cChwb3B1cF8zNGVhYjEyZDc3MjA0NDZkOWUzNWExMmNmZWEzNGViOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iOGNiYzhiZjUxZjk0NjgzYjI2ZWY4ZmMwZmE0N2MyYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1MDU3MTIwMDAwMDAxLC03OS4zODQ1Njc1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2M3MDdjMzJlYzBjYjQ0MGZhMjIxNjNhZjVhMGRmOTI1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2E4YmI2NzQzMzNlZTQxM2Y5Njg0ZDdjYTQ5MzJlZTA2ID0gJCgnPGRpdiBpZD0iaHRtbF9hOGJiNjc0MzMzZWU0MTNmOTY4NGQ3Y2E0OTMyZWUwNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QWRlbGFpZGUsIEtpbmcsIFJpY2htb25kIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYzcwN2MzMmVjMGNiNDQwZmEyMjE2M2FmNWEwZGY5MjUuc2V0Q29udGVudChodG1sX2E4YmI2NzQzMzNlZTQxM2Y5Njg0ZDdjYTQ5MzJlZTA2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2I4Y2JjOGJmNTFmOTQ2ODNiMjZlZjhmYzBmYTQ3YzJiLmJpbmRQb3B1cChwb3B1cF9jNzA3YzMyZWMwY2I0NDBmYTIyMTYzYWY1YTBkZjkyNSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80ODU0NzEwOTgyOTc0ZDczYTU1NDFlZTRhYTFlYjk0OSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY0MDgxNTcsLTc5LjM4MTc1MjI5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzI3ZTJhMTRlNThmMjQ4YTVhOTg1NWUzYWNiN2YxMmI1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzMxYzEwNTFmMDE5OTQwMzlhM2I5YTQ1ZDMzNGEwMTU2ID0gJCgnPGRpdiBpZD0iaHRtbF8zMWMxMDUxZjAxOTk0MDM5YTNiOWE0NWQzMzRhMDE1NiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SGFyYm91cmZyb250IEVhc3QsIFRvcm9udG8gSXNsYW5kcywgVW5pb24gU3RhdGlvbiBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzI3ZTJhMTRlNThmMjQ4YTVhOTg1NWUzYWNiN2YxMmI1LnNldENvbnRlbnQoaHRtbF8zMWMxMDUxZjAxOTk0MDM5YTNiOWE0NWQzMzRhMDE1Nik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80ODU0NzEwOTgyOTc0ZDczYTU1NDFlZTRhYTFlYjk0OS5iaW5kUG9wdXAocG9wdXBfMjdlMmExNGU1OGYyNDhhNWE5ODU1ZTNhY2I3ZjEyYjUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYWRlYmUxMzgyZTY4NDQ4MDgwOTk3Yjc5NTU3ODA5NDkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDcxNzY4LC03OS4zODE1NzY0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85NGU0ZDE4OGQzMTI0ODRlYjY4MzE2ZDk0ZDc2MDY3OCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83YzdlYzc4ZjVhMWY0YzRkODFiNjg5OTM0ZDM3NDFhYiA9ICQoJzxkaXYgaWQ9Imh0bWxfN2M3ZWM3OGY1YTFmNGM0ZDgxYjY4OTkzNGQzNzQxYWIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRlc2lnbiBFeGNoYW5nZSwgVG9yb250byBEb21pbmlvbiBDZW50cmUgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85NGU0ZDE4OGQzMTI0ODRlYjY4MzE2ZDk0ZDc2MDY3OC5zZXRDb250ZW50KGh0bWxfN2M3ZWM3OGY1YTFmNGM0ZDgxYjY4OTkzNGQzNzQxYWIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYWRlYmUxMzgyZTY4NDQ4MDgwOTk3Yjc5NTU3ODA5NDkuYmluZFBvcHVwKHBvcHVwXzk0ZTRkMTg4ZDMxMjQ4NGViNjgzMTZkOTRkNzYwNjc4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2M2MTc1ZGMyMWViMzRlMWFhOWI1MjcxMzA5MzA0NWEyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjQ4MTk4NSwtNzkuMzc5ODE2OTAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfY2ZmYTVjMDVkOGIxNGJiYWEzMGY2NWVlZTcxMDUyYmQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMmUxNjk4MDc2MzVkNDc3Mzk1MzkxMTVlMmE5ZDM3ZGYgPSAkKCc8ZGl2IGlkPSJodG1sXzJlMTY5ODA3NjM1ZDQ3NzM5NTM5MTE1ZTJhOWQzN2RmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Db21tZXJjZSBDb3VydCwgVmljdG9yaWEgSG90ZWwgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jZmZhNWMwNWQ4YjE0YmJhYTMwZjY1ZWVlNzEwNTJiZC5zZXRDb250ZW50KGh0bWxfMmUxNjk4MDc2MzVkNDc3Mzk1MzkxMTVlMmE5ZDM3ZGYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYzYxNzVkYzIxZWIzNGUxYWE5YjUyNzEzMDkzMDQ1YTIuYmluZFBvcHVwKHBvcHVwX2NmZmE1YzA1ZDhiMTRiYmFhMzBmNjVlZWU3MTA1MmJkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2RiOWVmNTYxNTVhZDQ2NDNhNTdjYWVhOWVkNTVhYjQ5ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzMzMjgyNSwtNzkuNDE5NzQ5N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80NDZhYzA2YjE5NmU0NTE0ODA0YTU2Y2ZkZjI5ODEzZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lMWExNDAxNDU1NTM0MDRhYWI5N2E2NzFjMTc0YTNlNCA9ICQoJzxkaXYgaWQ9Imh0bWxfZTFhMTQwMTQ1NTUzNDA0YWFiOTdhNjcxYzE3NGEzZTQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJlZGZvcmQgUGFyaywgTGF3cmVuY2UgTWFub3IgRWFzdCBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzQ0NmFjMDZiMTk2ZTQ1MTQ4MDRhNTZjZmRmMjk4MTNmLnNldENvbnRlbnQoaHRtbF9lMWExNDAxNDU1NTM0MDRhYWI5N2E2NzFjMTc0YTNlNCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9kYjllZjU2MTU1YWQ0NjQzYTU3Y2FlYTllZDU1YWI0OS5iaW5kUG9wdXAocG9wdXBfNDQ2YWMwNmIxOTZlNDUxNDgwNGE1NmNmZGYyOTgxM2YpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfY2FkZGNmMjg5Yjk4NGRlYjk1Yzk0NmE3ZTdkY2NkOWEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MTE2OTQ4LC03OS40MTY5MzU1OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjNGRmM2NlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzRkZjNjZSIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kMmFjODUzODYyNDc0YjE5ODMxYWRkZmFiNmI5MjA1OSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iNjY0ZTVlODE3OTQ0Y2UyODJhNDVjNDcxZDJjM2I5OCA9ICQoJzxkaXYgaWQ9Imh0bWxfYjY2NGU1ZTgxNzk0NGNlMjgyYTQ1YzQ3MWQyYzNiOTgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJvc2VsYXduIENsdXN0ZXIgMzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZDJhYzg1Mzg2MjQ3NGIxOTgzMWFkZGZhYjZiOTIwNTkuc2V0Q29udGVudChodG1sX2I2NjRlNWU4MTc5NDRjZTI4MmE0NWM0NzFkMmMzYjk4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2NhZGRjZjI4OWI5ODRkZWI5NWM5NDZhN2U3ZGNjZDlhLmJpbmRQb3B1cChwb3B1cF9kMmFjODUzODYyNDc0YjE5ODMxYWRkZmFiNmI5MjA1OSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zNjc5NzcyZDU3YzE0YTlhOGExZTk1MzE1NGQzZjhhYSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY5Njk0NzYsLTc5LjQxMTMwNzIwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjk2NGYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmY5NjRmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2M4MTE0ODBkNjkwMjQ4NmViNjQyZGJkNDQyMjcyNTQ0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc2YjhhZTNlNDQyOTQzZjJhZDE5YTZhZTY4ZmQ2YjlkID0gJCgnPGRpdiBpZD0iaHRtbF83NmI4YWUzZTQ0Mjk0M2YyYWQxOWE2YWU2OGZkNmI5ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Rm9yZXN0IEhpbGwgTm9ydGgsIEZvcmVzdCBIaWxsIFdlc3QgQ2x1c3RlciA1PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jODExNDgwZDY5MDI0ODZlYjY0MmRiZDQ0MjI3MjU0NC5zZXRDb250ZW50KGh0bWxfNzZiOGFlM2U0NDI5NDNmMmFkMTlhNmFlNjhmZDZiOWQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMzY3OTc3MmQ1N2MxNGE5YThhMWU5NTMxNTRkM2Y4YWEuYmluZFBvcHVwKHBvcHVwX2M4MTE0ODBkNjkwMjQ4NmViNjQyZGJkNDQyMjcyNTQ0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I1NDNmMjAzYjE2MTRmNWZhNTc2YjQyYzcxM2Q3MTViID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjcyNzA5NywtNzkuNDA1Njc4NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOWYwOGZiNTY4ODI5NDJhN2JhMWE5OTEwYzA4ZWUyMmEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfY2ZhZGM0ODc0ZDAyNDA3M2I4MDU0NWY3MzdmMGQ5NjIgPSAkKCc8ZGl2IGlkPSJodG1sX2NmYWRjNDg3NGQwMjQwNzNiODA1NDVmNzM3ZjBkOTYyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UaGUgQW5uZXgsIE5vcnRoIE1pZHRvd24sIFlvcmt2aWxsZSBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzlmMDhmYjU2ODgyOTQyYTdiYTFhOTkxMGMwOGVlMjJhLnNldENvbnRlbnQoaHRtbF9jZmFkYzQ4NzRkMDI0MDczYjgwNTQ1ZjczN2YwZDk2Mik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9iNTQzZjIwM2IxNjE0ZjVmYTU3NmI0MmM3MTNkNzE1Yi5iaW5kUG9wdXAocG9wdXBfOWYwOGZiNTY4ODI5NDJhN2JhMWE5OTEwYzA4ZWUyMmEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjI3N2I1NGUwNzRjNDRkNzk3NTdlOTZkMzQwNjQ3YzUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NjI2OTU2LC03OS40MDAwNDkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzAzOTg4ZmM4ZWY0ZjQyOGI4MmQzYjBiZDgxNjhkZWFjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2UzNDlhMDc0NzUxMjQ2MWFiMzYwMDkyYTliYzU0ZTQxID0gJCgnPGRpdiBpZD0iaHRtbF9lMzQ5YTA3NDc1MTI0NjFhYjM2MDA5MmE5YmM1NGU0MSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SGFyYm9yZCwgVW5pdmVyc2l0eSBvZiBUb3JvbnRvIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDM5ODhmYzhlZjRmNDI4YjgyZDNiMGJkODE2OGRlYWMuc2V0Q29udGVudChodG1sX2UzNDlhMDc0NzUxMjQ2MWFiMzYwMDkyYTliYzU0ZTQxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2IyNzdiNTRlMDc0YzQ0ZDc5NzU3ZTk2ZDM0MDY0N2M1LmJpbmRQb3B1cChwb3B1cF8wMzk4OGZjOGVmNGY0MjhiODJkM2IwYmQ4MTY4ZGVhYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wNGVhNDJkMTUyYzA0NDE3OGI5NjI2MTEzYWVmNDVjNiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1MzIwNTcsLTc5LjQwMDA0OTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNGRmOWExZTllNjRmNGRjYWI2MmI5OGM3NjVmZGMxMTMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNWRiMmE0OWE1YWZhNDFhNGI0YzExZTFhZmQ3YmIzZWIgPSAkKCc8ZGl2IGlkPSJodG1sXzVkYjJhNDlhNWFmYTQxYTRiNGMxMWUxYWZkN2JiM2ViIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DaGluYXRvd24sIEdyYW5nZSBQYXJrLCBLZW5zaW5ndG9uIE1hcmtldCBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzRkZjlhMWU5ZTY0ZjRkY2FiNjJiOThjNzY1ZmRjMTEzLnNldENvbnRlbnQoaHRtbF81ZGIyYTQ5YTVhZmE0MWE0YjRjMTFlMWFmZDdiYjNlYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wNGVhNDJkMTUyYzA0NDE3OGI5NjI2MTEzYWVmNDVjNi5iaW5kUG9wdXAocG9wdXBfNGRmOWExZTllNjRmNGRjYWI2MmI5OGM3NjVmZGMxMTMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZmEzYjUyNGI1YTI5NGUxZjk0NTRhNzgzNjA4MmI0NTEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Mjg5NDY3LC03OS4zOTQ0MTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzNjNzIwOTU1MjA1NDQ2ODk5MGUwNWI2ODExZjM5NjdiID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzMzZWZjNjU2NWJkZDRhYjdhYzlmN2I0NGQ1NWFhMDhmID0gJCgnPGRpdiBpZD0iaHRtbF8zM2VmYzY1NjViZGQ0YWI3YWM5ZjdiNDRkNTVhYTA4ZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q04gVG93ZXIsIEJhdGh1cnN0IFF1YXksIElzbGFuZCBhaXJwb3J0LCBIYXJib3VyZnJvbnQgV2VzdCwgS2luZyBhbmQgU3BhZGluYSwgUmFpbHdheSBMYW5kcywgU291dGggTmlhZ2FyYSBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzNjNzIwOTU1MjA1NDQ2ODk5MGUwNWI2ODExZjM5NjdiLnNldENvbnRlbnQoaHRtbF8zM2VmYzY1NjViZGQ0YWI3YWM5ZjdiNDRkNTVhYTA4Zik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mYTNiNTI0YjVhMjk0ZTFmOTQ1NGE3ODM2MDgyYjQ1MS5iaW5kUG9wdXAocG9wdXBfM2M3MjA5NTUyMDU0NDY4OTkwZTA1YjY4MTFmMzk2N2IpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZmNjZmZhNzViOTU4NDdmNjhiOGVkMjEwOWU1MTYxODMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDY0MzUyLC03OS4zNzQ4NDU5OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82YWNiYmFlMDE0YTA0NTY0OTgzNzBmNGZhM2YzMDgzMSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mYzYxNDkzY2ViMzY0ZWQ3ODg5NTQyMTA2MTFhYTU2YSA9ICQoJzxkaXYgaWQ9Imh0bWxfZmM2MTQ5M2NlYjM2NGVkNzg4OTU0MjEwNjExYWE1NmEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlN0biBBIFBPIEJveGVzIDI1IFRoZSBFc3BsYW5hZGUgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82YWNiYmFlMDE0YTA0NTY0OTgzNzBmNGZhM2YzMDgzMS5zZXRDb250ZW50KGh0bWxfZmM2MTQ5M2NlYjM2NGVkNzg4OTU0MjEwNjExYWE1NmEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZmNjZmZhNzViOTU4NDdmNjhiOGVkMjEwOWU1MTYxODMuYmluZFBvcHVwKHBvcHVwXzZhY2JiYWUwMTRhMDQ1NjQ5ODM3MGY0ZmEzZjMwODMxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzkyMmVjMjhmM2RmZjQwMzE4ZGE5MmU0NGQ2MWUwMDQ5ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjQ4NDI5MiwtNzkuMzgyMjgwMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84ZWMzMTkxYTg3YjQ0YTY1YTU1OTY4NzEwZDE4MzE3MCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82MzYzNGRkYjUwNDA0ZjcyYTE3NzRhNGMyMjgyOTAzZSA9ICQoJzxkaXYgaWQ9Imh0bWxfNjM2MzRkZGI1MDQwNGY3MmExNzc0YTRjMjI4MjkwM2UiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZpcnN0IENhbmFkaWFuIFBsYWNlLCBVbmRlcmdyb3VuZCBjaXR5IENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOGVjMzE5MWE4N2I0NGE2NWE1NTk2ODcxMGQxODMxNzAuc2V0Q29udGVudChodG1sXzYzNjM0ZGRiNTA0MDRmNzJhMTc3NGE0YzIyODI5MDNlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzkyMmVjMjhmM2RmZjQwMzE4ZGE5MmU0NGQ2MWUwMDQ5LmJpbmRQb3B1cChwb3B1cF84ZWMzMTkxYTg3YjQ0YTY1YTU1OTY4NzEwZDE4MzE3MCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zNDU0MjBhZGI2NmU0NDMzYjhmZTUxNzhlNzUzZmFhOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcxODUxNzk5OTk5OTk5NiwtNzkuNDY0NzYzMjk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfY2YyMmRhYmMyNGI2NGQwZWJhYWJmMGE3NTBkYTA0YTkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMGNhNTM1M2M5ODdiNDFjZDhlNjNiMWE2NjcxZDMxZWIgPSAkKCc8ZGl2IGlkPSJodG1sXzBjYTUzNTNjOTg3YjQxY2Q4ZTYzYjFhNjY3MWQzMWViIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5MYXdyZW5jZSBIZWlnaHRzLCBMYXdyZW5jZSBNYW5vciBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2NmMjJkYWJjMjRiNjRkMGViYWFiZjBhNzUwZGEwNGE5LnNldENvbnRlbnQoaHRtbF8wY2E1MzUzYzk4N2I0MWNkOGU2M2IxYTY2NzFkMzFlYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zNDU0MjBhZGI2NmU0NDMzYjhmZTUxNzhlNzUzZmFhOC5iaW5kUG9wdXAocG9wdXBfY2YyMmRhYmMyNGI2NGQwZWJhYWJmMGE3NTBkYTA0YTkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMTY0ODkyNWRhZDMxNGJiY2EzNTBjODQ2NTdhNzYzMDUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MDk1NzcsLTc5LjQ0NTA3MjU5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzczZDM2ZjE1MDljOTQ1ZmJiZjViMjEyOTEyMjBkZDY5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2IxMWIzMTIxMmE5NTQ2YjM4YjQ0ZWM3MjlkYjEwMGZhID0gJCgnPGRpdiBpZD0iaHRtbF9iMTFiMzEyMTJhOTU0NmIzOGI0NGVjNzI5ZGIxMDBmYSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+R2xlbmNhaXJuIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNzNkMzZmMTUwOWM5NDVmYmJmNWIyMTI5MTIyMGRkNjkuc2V0Q29udGVudChodG1sX2IxMWIzMTIxMmE5NTQ2YjM4YjQ0ZWM3MjlkYjEwMGZhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzE2NDg5MjVkYWQzMTRiYmNhMzUwYzg0NjU3YTc2MzA1LmJpbmRQb3B1cChwb3B1cF83M2QzNmYxNTA5Yzk0NWZiYmY1YjIxMjkxMjIwZGQ2OSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80NTY0NmM5MmNhMmU0YWMzYTQwOThhOGVjZTE5NWVmYyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY5Mzc4MTMsLTc5LjQyODE5MTQwMDAwMDAyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2IzNmM0NDMzYWI4OTQ0MjNhYTdkZDc4Mjg2Y2NiMWFlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzMyZjg5ZTU4NTk0YzRlNjViNGFlY2MyYmQ2NWFhM2NjID0gJCgnPGRpdiBpZD0iaHRtbF8zMmY4OWU1ODU5NGM0ZTY1YjRhZWNjMmJkNjVhYTNjYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SHVtZXdvb2QtQ2VkYXJ2YWxlIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjM2YzQ0MzNhYjg5NDQyM2FhN2RkNzgyODZjY2IxYWUuc2V0Q29udGVudChodG1sXzMyZjg5ZTU4NTk0YzRlNjViNGFlY2MyYmQ2NWFhM2NjKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzQ1NjQ2YzkyY2EyZTRhYzNhNDA5OGE4ZWNlMTk1ZWZjLmJpbmRQb3B1cChwb3B1cF9iMzZjNDQzM2FiODk0NDIzYWE3ZGQ3ODI4NmNjYjFhZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82YTFiNDBjYWVlZjg0ZjkxYTk1NjE1NTQyYmQ2NmJlMCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY4OTAyNTYsLTc5LjQ1MzUxMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmY5NjRmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmOTY0ZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zOWZlMDViMTg5ZjE0NzJhYjAyNDcwYmMzNTExNWMxNSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82NmIwZDljNmY2YTg0YjhjYmZkYjVkNTdiNjBlZWY0YyA9ICQoJzxkaXYgaWQ9Imh0bWxfNjZiMGQ5YzZmNmE4NGI4Y2JmZGI1ZDU3YjYwZWVmNGMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNhbGVkb25pYS1GYWlyYmFua3MgQ2x1c3RlciA1PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zOWZlMDViMTg5ZjE0NzJhYjAyNDcwYmMzNTExNWMxNS5zZXRDb250ZW50KGh0bWxfNjZiMGQ5YzZmNmE4NGI4Y2JmZGI1ZDU3YjYwZWVmNGMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNmExYjQwY2FlZWY4NGY5MWE5NTYxNTU0MmJkNjZiZTAuYmluZFBvcHVwKHBvcHVwXzM5ZmUwNWIxODlmMTQ3MmFiMDI0NzBiYzM1MTE1YzE1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzA1ZTg4NjlmODBjNzQyZjdhZWFhMTJlNzRmZGIzNGM5ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjY5NTQyLC03OS40MjI1NjM3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2M0ZGRiMjdlYWYwYjQ5ZjM4OGRkMDFjODQyMTdlY2U4ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzgxMjg4ZWIyNzQxYjQ2NTU5ZGQxZjdlODA0MmE3OWIyID0gJCgnPGRpdiBpZD0iaHRtbF84MTI4OGViMjc0MWI0NjU1OWRkMWY3ZTgwNDJhNzliMiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q2hyaXN0aWUgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jNGRkYjI3ZWFmMGI0OWYzODhkZDAxYzg0MjE3ZWNlOC5zZXRDb250ZW50KGh0bWxfODEyODhlYjI3NDFiNDY1NTlkZDFmN2U4MDQyYTc5YjIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMDVlODg2OWY4MGM3NDJmN2FlYWExMmU3NGZkYjM0YzkuYmluZFBvcHVwKHBvcHVwX2M0ZGRiMjdlYWYwYjQ5ZjM4OGRkMDFjODQyMTdlY2U4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzBhZDM1MThlNTM5MDQ4ODhhMDA1MjM5YzM3MWMxMDNiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjY5MDA1MTAwMDAwMDEsLTc5LjQ0MjI1OTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYWJlZGFiZmIxYzY3NDZkMWJiY2E0YzYxYjkwNDc5MzUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYmQ1OTU0MDdmZGVmNGFhMWE5MmRlNmM2ODlmMTA3YmUgPSAkKCc8ZGl2IGlkPSJodG1sX2JkNTk1NDA3ZmRlZjRhYTFhOTJkZTZjNjg5ZjEwN2JlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Eb3ZlcmNvdXJ0IFZpbGxhZ2UsIER1ZmZlcmluIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYWJlZGFiZmIxYzY3NDZkMWJiY2E0YzYxYjkwNDc5MzUuc2V0Q29udGVudChodG1sX2JkNTk1NDA3ZmRlZjRhYTFhOTJkZTZjNjg5ZjEwN2JlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzBhZDM1MThlNTM5MDQ4ODhhMDA1MjM5YzM3MWMxMDNiLmJpbmRQb3B1cChwb3B1cF9hYmVkYWJmYjFjNjc0NmQxYmJjYTRjNjFiOTA0NzkzNSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl85NzgxYTE0MDlhMDU0MzIyYjcwYzNhODVkZTdmZGIzNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY0NzkyNjcwMDAwMDAwNiwtNzkuNDE5NzQ5N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lYmQzZjU2ZjAxMDM0ZWE2OGUxYzY2OTdjNmQ4OTcyZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83YjNkZTE0NGQ2YWE0MmE4OTk5MGY5MjVlYWY4MGZiNCA9ICQoJzxkaXYgaWQ9Imh0bWxfN2IzZGUxNDRkNmFhNDJhODk5OTBmOTI1ZWFmODBmYjQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxpdHRsZSBQb3J0dWdhbCwgVHJpbml0eSBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2ViZDNmNTZmMDEwMzRlYTY4ZTFjNjY5N2M2ZDg5NzJkLnNldENvbnRlbnQoaHRtbF83YjNkZTE0NGQ2YWE0MmE4OTk5MGY5MjVlYWY4MGZiNCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85NzgxYTE0MDlhMDU0MzIyYjcwYzNhODVkZTdmZGIzNy5iaW5kUG9wdXAocG9wdXBfZWJkM2Y1NmYwMTAzNGVhNjhlMWM2Njk3YzZkODk3MmQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNmQ4Mzk1NDdhYzg0NDUzMGExOGZlNTg1YWM0MTRjOWYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42MzY4NDcyLC03OS40MjgxOTE0MDAwMDAwMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zMzk4YzVhMGFiZjY0NDRmODc3NTBkNGE4MTNmMzY0NyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xOTA4ZTcxYzMwZDI0MTJmYThmMzZhYjhhZjFkOWJmNiA9ICQoJzxkaXYgaWQ9Imh0bWxfMTkwOGU3MWMzMGQyNDEyZmE4ZjM2YWI4YWYxZDliZjYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJyb2NrdG9uLCBFeGhpYml0aW9uIFBsYWNlLCBQYXJrZGFsZSBWaWxsYWdlIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzM5OGM1YTBhYmY2NDQ0Zjg3NzUwZDRhODEzZjM2NDcuc2V0Q29udGVudChodG1sXzE5MDhlNzFjMzBkMjQxMmZhOGYzNmFiOGFmMWQ5YmY2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzZkODM5NTQ3YWM4NDQ1MzBhMThmZTU4NWFjNDE0YzlmLmJpbmRQb3B1cChwb3B1cF8zMzk4YzVhMGFiZjY0NDRmODc3NTBkNGE4MTNmMzY0Nyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lZDEwMjJiNTU5OTk0MjE5YWI0YzRhYzhhNzYyYzg0YiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcxMzc1NjIwMDAwMDAwNiwtNzkuNDkwMDczOF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xMDJkOGRlYzNiMDU0MTdkYjE2ZjUyZjRiNTkwODE0ZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82OTE1ZjM3OTU2NWU0YjI5OTE3YTk5YWFhNmFkM2I0YSA9ICQoJzxkaXYgaWQ9Imh0bWxfNjkxNWYzNzk1NjVlNGIyOTkxN2E5OWFhYTZhZDNiNGEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvd25zdmlldywgTm9ydGggUGFyaywgVXB3b29kIFBhcmsgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xMDJkOGRlYzNiMDU0MTdkYjE2ZjUyZjRiNTkwODE0ZS5zZXRDb250ZW50KGh0bWxfNjkxNWYzNzk1NjVlNGIyOTkxN2E5OWFhYTZhZDNiNGEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZWQxMDIyYjU1OTk5NDIxOWFiNGM0YWM4YTc2MmM4NGIuYmluZFBvcHVwKHBvcHVwXzEwMmQ4ZGVjM2IwNTQxN2RiMTZmNTJmNGI1OTA4MTRlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzRjMGE3NTY1Y2M0NjRiOTFiMGMwM2FlOThlYjNkZDcxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjkxMTE1OCwtNzkuNDc2MDEzMjk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMjFlNWQ4ZjJmZGE1NGFhNDk5OTM2N2U0ZjdmYWU3MWIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNGVkNWZkMWUzY2QyNDM3ZDlhNmE2ZDc5MzNmYzJiMmUgPSAkKCc8ZGl2IGlkPSJodG1sXzRlZDVmZDFlM2NkMjQzN2Q5YTZhNmQ3OTMzZmMyYjJlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5EZWwgUmF5LCBLZWVsZXNkYWxlLCBNb3VudCBEZW5uaXMsIFNpbHZlcnRob3JuIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjFlNWQ4ZjJmZGE1NGFhNDk5OTM2N2U0ZjdmYWU3MWIuc2V0Q29udGVudChodG1sXzRlZDVmZDFlM2NkMjQzN2Q5YTZhNmQ3OTMzZmMyYjJlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzRjMGE3NTY1Y2M0NjRiOTFiMGMwM2FlOThlYjNkZDcxLmJpbmRQb3B1cChwb3B1cF8yMWU1ZDhmMmZkYTU0YWE0OTk5MzY3ZTRmN2ZhZTcxYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82YmExMmQ0OWEwMjU0OTEwOGRiNDFhYzFmYWU4ZjM3YSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY3MzE4NTI5OTk5OTk5LC03OS40ODcyNjE5MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yYjM2MmRkNmE1Y2Y0MjI4ODY3ZTg5ODhiMGNhN2RkOSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hODc4ZWZmYmE5Mjg0ZDcyYTRiMWEzMTU5NGZlMDZlYiA9ICQoJzxkaXYgaWQ9Imh0bWxfYTg3OGVmZmJhOTI4NGQ3MmE0YjFhMzE1OTRmZTA2ZWIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlRoZSBKdW5jdGlvbiBOb3J0aCwgUnVubnltZWRlIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMmIzNjJkZDZhNWNmNDIyODg2N2U4OTg4YjBjYTdkZDkuc2V0Q29udGVudChodG1sX2E4NzhlZmZiYTkyODRkNzJhNGIxYTMxNTk0ZmUwNmViKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzZiYTEyZDQ5YTAyNTQ5MTA4ZGI0MWFjMWZhZThmMzdhLmJpbmRQb3B1cChwb3B1cF8yYjM2MmRkNmE1Y2Y0MjI4ODY3ZTg5ODhiMGNhN2RkOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kNjNhNjBkMDAwZmI0OWI1YjAzYjI2MWQxMTUzNzkyMSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY2MTYwODMsLTc5LjQ2NDc2MzI5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzJkM2RhNjE0YmE4ODQ5Y2E5NDQ3ZTI1ZjYzZDE5OGViID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2M3M2NiZTBmYWQwOTQ2NmM4NzRhMmU4NjRjMWJiZmQwID0gJCgnPGRpdiBpZD0iaHRtbF9jNzNjYmUwZmFkMDk0NjZjODc0YTJlODY0YzFiYmZkMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SGlnaCBQYXJrLCBUaGUgSnVuY3Rpb24gU291dGggQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yZDNkYTYxNGJhODg0OWNhOTQ0N2UyNWY2M2QxOThlYi5zZXRDb250ZW50KGh0bWxfYzczY2JlMGZhZDA5NDY2Yzg3NGEyZTg2NGMxYmJmZDApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZDYzYTYwZDAwMGZiNDliNWIwM2IyNjFkMTE1Mzc5MjEuYmluZFBvcHVwKHBvcHVwXzJkM2RhNjE0YmE4ODQ5Y2E5NDQ3ZTI1ZjYzZDE5OGViKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzkyM2U5YmM4ZDBiODQ4YmQ5YTE4OTAyNzRmMDViZWU3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjQ4OTU5NywtNzkuNDU2MzI1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzA4YmU0OWI2NTM3MTQzNTlhYzg3NzY4OWRlYzNlYzJkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2ZlMDE5ZDQ5ZTZkMzRiYmQ5ZDVhZWZmMzRjMTFiYWM2ID0gJCgnPGRpdiBpZD0iaHRtbF9mZTAxOWQ0OWU2ZDM0YmJkOWQ1YWVmZjM0YzExYmFjNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UGFya2RhbGUsIFJvbmNlc3ZhbGxlcyBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzA4YmU0OWI2NTM3MTQzNTlhYzg3NzY4OWRlYzNlYzJkLnNldENvbnRlbnQoaHRtbF9mZTAxOWQ0OWU2ZDM0YmJkOWQ1YWVmZjM0YzExYmFjNik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85MjNlOWJjOGQwYjg0OGJkOWExODkwMjc0ZjA1YmVlNy5iaW5kUG9wdXAocG9wdXBfMDhiZTQ5YjY1MzcxNDM1OWFjODc3Njg5ZGVjM2VjMmQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMDc2NTRjNzhhMmRhNGNkY2IxZTRkMmE1ODk0MDUyYzMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NTE1NzA2LC03OS40ODQ0NDk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RjMDQ0YzhhMDY0NzRhY2Q5MGM0ZDUxODU3Yjg3M2U3ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzg4MWNmYjg0YjUwZTQyZWZhNzlhYWEwZjZhYzU1ZDhjID0gJCgnPGRpdiBpZD0iaHRtbF84ODFjZmI4NGI1MGU0MmVmYTc5YWFhMGY2YWM1NWQ4YyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UnVubnltZWRlLCBTd2Fuc2VhIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZGMwNDRjOGEwNjQ3NGFjZDkwYzRkNTE4NTdiODczZTcuc2V0Q29udGVudChodG1sXzg4MWNmYjg0YjUwZTQyZWZhNzlhYWEwZjZhYzU1ZDhjKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzA3NjU0Yzc4YTJkYTRjZGNiMWU0ZDJhNTg5NDA1MmMzLmJpbmRQb3B1cChwb3B1cF9kYzA0NGM4YTA2NDc0YWNkOTBjNGQ1MTg1N2I4NzNlNyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lMzU5MDNhMTIyYmE0MDNkODU2ZjUyODNjYWU4YTA5NiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY2MjMwMTUsLTc5LjM4OTQ5MzhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzJjZGYyMDk5MGE1NDVkOGE5YzhiZDQ1ODM3N2U1MjAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfY2ViZWFiNzM0ZTVlNDIyNDkxNGE4NjFhMTJiZmVhMTkgPSAkKCc8ZGl2IGlkPSJodG1sX2NlYmVhYjczNGU1ZTQyMjQ5MTRhODYxYTEyYmZlYTE5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5RdWVlbiYjMzk7cyBQYXJrIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYzJjZGYyMDk5MGE1NDVkOGE5YzhiZDQ1ODM3N2U1MjAuc2V0Q29udGVudChodG1sX2NlYmVhYjczNGU1ZTQyMjQ5MTRhODYxYTEyYmZlYTE5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2UzNTkwM2ExMjJiYTQwM2Q4NTZmNTI4M2NhZThhMDk2LmJpbmRQb3B1cChwb3B1cF9jMmNkZjIwOTkwYTU0NWQ4YTljOGJkNDU4Mzc3ZTUyMCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wOTMyN2U1YmRkNTY0MDE5YmI1MmVlNjRiOTZmODdiYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY2Nzg1NTYsLTc5LjUzMjI0MjQwMDAwMDAyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2FkM2VjN2UxOTczNjRkY2Y4OTFkOWQ2ZjE5MDA3ODRjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzBkZTYxN2U5NmViYzQwNzQ4MTgxM2I5ZjM2NzgyYTE3ID0gJCgnPGRpdiBpZD0iaHRtbF8wZGU2MTdlOTZlYmM0MDc0ODE4MTNiOWYzNjc4MmExNyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UXVlZW4mIzM5O3MgUGFyayBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2FkM2VjN2UxOTczNjRkY2Y4OTFkOWQ2ZjE5MDA3ODRjLnNldENvbnRlbnQoaHRtbF8wZGU2MTdlOTZlYmM0MDc0ODE4MTNiOWYzNjc4MmExNyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wOTMyN2U1YmRkNTY0MDE5YmI1MmVlNjRiOTZmODdiYi5iaW5kUG9wdXAocG9wdXBfYWQzZWM3ZTE5NzM2NGRjZjg5MWQ5ZDZmMTkwMDc4NGMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTVkYzkyMWExZDQwNGI3NmIwMWRjMzYxZmIzMThkM2EgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42MzY5NjU2LC03OS42MTU4MTg5OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iMmJlYjk1MGU0N2Q0MDdmYjRhNjlkNzdkMDhhNmZkYyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81NDAxM2E5ZmQ3ZWQ0NTlkYmNkZDYzMWEyMDc0NDk3YyA9ICQoJzxkaXYgaWQ9Imh0bWxfNTQwMTNhOWZkN2VkNDU5ZGJjZGQ2MzFhMjA3NDQ5N2MiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNhbmFkYSBQb3N0IEdhdGV3YXkgUHJvY2Vzc2luZyBDZW50cmUgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iMmJlYjk1MGU0N2Q0MDdmYjRhNjlkNzdkMDhhNmZkYy5zZXRDb250ZW50KGh0bWxfNTQwMTNhOWZkN2VkNDU5ZGJjZGQ2MzFhMjA3NDQ5N2MpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNTVkYzkyMWExZDQwNGI3NmIwMWRjMzYxZmIzMThkM2EuYmluZFBvcHVwKHBvcHVwX2IyYmViOTUwZTQ3ZDQwN2ZiNGE2OWQ3N2QwOGE2ZmRjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzU4YTQ0YzU0ZmZmZDQ0ODE4MTBhOWNiMTUzM2RlNDQ3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjYyNzQzOSwtNzkuMzIxNTU4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzhhZjA1ZmMzZWVmNDQ0MGNhYjMzZDE2ZTU4ZTFiMTA3ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzMwZGM1NDQ5YTY5NzRjYTJiOTIwZGYxZTU3ZWI3MjEwID0gJCgnPGRpdiBpZD0iaHRtbF8zMGRjNTQ0OWE2OTc0Y2EyYjkyMGRmMWU1N2ViNzIxMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnVzaW5lc3MgUmVwbHkgTWFpbCBQcm9jZXNzaW5nIENlbnRyZSA5NjkgRWFzdGVybiBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzhhZjA1ZmMzZWVmNDQ0MGNhYjMzZDE2ZTU4ZTFiMTA3LnNldENvbnRlbnQoaHRtbF8zMGRjNTQ0OWE2OTc0Y2EyYjkyMGRmMWU1N2ViNzIxMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl81OGE0NGM1NGZmZmQ0NDgxODEwYTljYjE1MzNkZTQ0Ny5iaW5kUG9wdXAocG9wdXBfOGFmMDVmYzNlZWY0NDQwY2FiMzNkMTZlNThlMWIxMDcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfN2VkNGEyMmM3ZGE3NDJmZGFmNzZhMDEyMTc4MWViOGUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42MDU2NDY2LC03OS41MDEzMjA3MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iMGYwYjkyODU2YzA0NzE1YjljMmRlNjBmNjExYzRjYiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lMDUxN2RjZTBiNjM0ODdkYjgyYmUwNzlkNjdlZWNiZiA9ICQoJzxkaXYgaWQ9Imh0bWxfZTA1MTdkY2UwYjYzNDg3ZGI4MmJlMDc5ZDY3ZWVjYmYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkh1bWJlciBCYXkgU2hvcmVzLCBNaW1pY28gU291dGgsIE5ldyBUb3JvbnRvIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjBmMGI5Mjg1NmMwNDcxNWI5YzJkZTYwZjYxMWM0Y2Iuc2V0Q29udGVudChodG1sX2UwNTE3ZGNlMGI2MzQ4N2RiODJiZTA3OWQ2N2VlY2JmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzdlZDRhMjJjN2RhNzQyZmRhZjc2YTAxMjE3ODFlYjhlLmJpbmRQb3B1cChwb3B1cF9iMGYwYjkyODU2YzA0NzE1YjljMmRlNjBmNjExYzRjYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wMzE2NWI5Y2M4Mjk0MDIxODFhZmIzNjA2OGRmN2FmYSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjYwMjQxMzcwMDAwMDAxLC03OS41NDM0ODQwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80ODIyMTg3YzkzODM0ZWE5YThiYTVlMjZhNjRlMjhkMyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8yNTVhMjY4MDE3Mjk0OTcyYTFhZjAyZTBiMmVhMzQzNCA9ICQoJzxkaXYgaWQ9Imh0bWxfMjU1YTI2ODAxNzI5NDk3MmExYWYwMmUwYjJlYTM0MzQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkFsZGVyd29vZCwgTG9uZyBCcmFuY2ggQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80ODIyMTg3YzkzODM0ZWE5YThiYTVlMjZhNjRlMjhkMy5zZXRDb250ZW50KGh0bWxfMjU1YTI2ODAxNzI5NDk3MmExYWYwMmUwYjJlYTM0MzQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMDMxNjViOWNjODI5NDAyMTgxYWZiMzYwNjhkZjdhZmEuYmluZFBvcHVwKHBvcHVwXzQ4MjIxODdjOTM4MzRlYTlhOGJhNWUyNmE2NGUyOGQzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQwYzVmOWE3NDgzMzQ1OGFhZGZjOTg2YTY2MGQzYTQzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUzNjUzNjAwMDAwMDA1LC03OS41MDY5NDM2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjk2NGYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmY5NjRmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzNjNzU5Y2YzYzllNjRhMDZhYjIxMDEwYTlkYTM5MmNiID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2JlZGE5MjdiOTU5MjQ4NmZiN2E0OThlZWEyZDNhMzE3ID0gJCgnPGRpdiBpZD0iaHRtbF9iZWRhOTI3Yjk1OTI0ODZmYjdhNDk4ZWVhMmQzYTMxNyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VGhlIEtpbmdzd2F5LCBNb250Z29tZXJ5IFJvYWQsIE9sZCBNaWxsIE5vcnRoIENsdXN0ZXIgNTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfM2M3NTljZjNjOWU2NGEwNmFiMjEwMTBhOWRhMzkyY2Iuc2V0Q29udGVudChodG1sX2JlZGE5MjdiOTU5MjQ4NmZiN2E0OThlZWEyZDNhMzE3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzQwYzVmOWE3NDgzMzQ1OGFhZGZjOTg2YTY2MGQzYTQzLmJpbmRQb3B1cChwb3B1cF8zYzc1OWNmM2M5ZTY0YTA2YWIyMTAxMGE5ZGEzOTJjYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jZTdlYzZkYjNhNGE0YjQ4ODkwNWJmMjM2MWNhZWQwNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjYzNjI1NzksLTc5LjQ5ODUwOTA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiM4MDAwZmYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjODAwMGZmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2Q5YTc0YzI3ZmJjNjQ0Njg5Y2NjYTdjMzgzMGU2NzhjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzI4YWQ2N2M2NDkwZDRmNjA4ODllZmM0YjMyZWNiZGEwID0gJCgnPGRpdiBpZD0iaHRtbF8yOGFkNjdjNjQ5MGQ0ZjYwODg5ZWZjNGIzMmVjYmRhMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SHVtYmVyIEJheSwgS2luZyYjMzk7cyBNaWxsIFBhcmssIEtpbmdzd2F5IFBhcmsgU291dGggRWFzdCwgTWltaWNvIE5FLCBPbGQgTWlsbCBTb3V0aCwgVGhlIFF1ZWVuc3dheSBFYXN0LCBSb3lhbCBZb3JrIFNvdXRoIEVhc3QsIFN1bm55bGVhIENsdXN0ZXIgMTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZDlhNzRjMjdmYmM2NDQ2ODljY2NhN2MzODMwZTY3OGMuc2V0Q29udGVudChodG1sXzI4YWQ2N2M2NDkwZDRmNjA4ODllZmM0YjMyZWNiZGEwKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2NlN2VjNmRiM2E0YTRiNDg4OTA1YmYyMzYxY2FlZDA3LmJpbmRQb3B1cChwb3B1cF9kOWE3NGMyN2ZiYzY0NDY4OWNjY2E3YzM4MzBlNjc4Yyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yNjU1MjgxYTBmZmY0NjM4YmQwZWU5ZWVjYjg1ODM5ZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjYyODg0MDgsLTc5LjUyMDk5OTQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjAwMDAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzhjMzE4MWZkM2QxYzRmNDg4ODBiMjhmMjE0MWJkN2M3ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzkyYzkwNDY0YTVmMDQ0Y2JiNjNlMmE5NmZkM2U0ODUwID0gJCgnPGRpdiBpZD0iaHRtbF85MmM5MDQ2NGE1ZjA0NGNiYjYzZTJhOTZmZDNlNDg1MCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+S2luZ3N3YXkgUGFyayBTb3V0aCBXZXN0LCBNaW1pY28gTlcsIFRoZSBRdWVlbnN3YXkgV2VzdCwgUm95YWwgWW9yayBTb3V0aCBXZXN0LCBTb3V0aCBvZiBCbG9vciBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzhjMzE4MWZkM2QxYzRmNDg4ODBiMjhmMjE0MWJkN2M3LnNldENvbnRlbnQoaHRtbF85MmM5MDQ2NGE1ZjA0NGNiYjYzZTJhOTZmZDNlNDg1MCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yNjU1MjgxYTBmZmY0NjM4YmQwZWU5ZWVjYjg1ODM5ZC5iaW5kUG9wdXAocG9wdXBfOGMzMTgxZmQzZDFjNGY0ODg4MGIyOGYyMTQxYmQ3YzcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNmZiODdlMWIwMWE0NGY2Mzg5ZDY3NzAzMmY1OTFiOGUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDM1MTUyLC03OS41NzcyMDA3OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83Y2VjNzE4NDZmYmI0ODQyYmMyOGVkZDM5YTU1ZDk5NyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hMDkzMzU0ZTYxNTk0MzQ1OTM1NzNiNzhhMDM5YjE4MSA9ICQoJzxkaXYgaWQ9Imh0bWxfYTA5MzM1NGU2MTU5NDM0NTkzNTczYjc4YTAzOWIxODEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJsb29yZGFsZSBHYXJkZW5zLCBFcmluZ2F0ZSwgTWFya2xhbmQgV29vZCwgT2xkIEJ1cm5oYW10aG9ycGUgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83Y2VjNzE4NDZmYmI0ODQyYmMyOGVkZDM5YTU1ZDk5Ny5zZXRDb250ZW50KGh0bWxfYTA5MzM1NGU2MTU5NDM0NTkzNTczYjc4YTAzOWIxODEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNmZiODdlMWIwMWE0NGY2Mzg5ZDY3NzAzMmY1OTFiOGUuYmluZFBvcHVwKHBvcHVwXzdjZWM3MTg0NmZiYjQ4NDJiYzI4ZWRkMzlhNTVkOTk3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzBkMzE0NTAxNTczMDRmM2NiOTVkMDJmZGEzNWE2N2U4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzU2MzAzMywtNzkuNTY1OTYzMjk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZmYxNjlhZDJkZDE2NGJjMWJjOTZiZjYyYzkxYzY1YjYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDVhZmJhMWMwZjY0NDc4MjlmZDBmZmJlZWMyNzMwYWIgPSAkKCc8ZGl2IGlkPSJodG1sX2Q1YWZiYTFjMGY2NDQ3ODI5ZmQwZmZiZWVjMjczMGFiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IdW1iZXIgU3VtbWl0IENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZmYxNjlhZDJkZDE2NGJjMWJjOTZiZjYyYzkxYzY1YjYuc2V0Q29udGVudChodG1sX2Q1YWZiYTFjMGY2NDQ3ODI5ZmQwZmZiZWVjMjczMGFiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzBkMzE0NTAxNTczMDRmM2NiOTVkMDJmZGEzNWE2N2U4LmJpbmRQb3B1cChwb3B1cF9mZjE2OWFkMmRkMTY0YmMxYmM5NmJmNjJjOTFjNjViNik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84MmI3MGI0MTI0OWU0YzZlYmRhMTEwMTlmZmU4ODhhNiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcyNDc2NTksLTc5LjUzMjI0MjQwMDAwMDAyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiM4MDAwZmYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjODAwMGZmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2Y0ZWRiNDE0ZTJlMDQ2MGI4ODZjZjNjOTUyNzlkMGEyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzNjZTVhZmU3NmUyNjRhMzc4OGI1MDY2ZjZhZTVhMGE1ID0gJCgnPGRpdiBpZD0iaHRtbF8zY2U1YWZlNzZlMjY0YTM3ODhiNTA2NmY2YWU1YTBhNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RW1lcnksIEh1bWJlcmxlYSBDbHVzdGVyIDE8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Y0ZWRiNDE0ZTJlMDQ2MGI4ODZjZjNjOTUyNzlkMGEyLnNldENvbnRlbnQoaHRtbF8zY2U1YWZlNzZlMjY0YTM3ODhiNTA2NmY2YWU1YTBhNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84MmI3MGI0MTI0OWU0YzZlYmRhMTEwMTlmZmU4ODhhNi5iaW5kUG9wdXAocG9wdXBfZjRlZGI0MTRlMmUwNDYwYjg4NmNmM2M5NTI3OWQwYTIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNzhkNWYzMTE2NTVkNGNkZWFhNGUxZWY5ZTRhNDJjMzQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MDY4NzYsLTc5LjUxODE4ODQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjk2NGYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmY5NjRmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzJhYWRlMDI1MzU0YjQ5ZTY5M2U2YjM1YzJkNTk3Y2I2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2ZjYjU4NzBmZDU2NDRjNDM4YTM3YmI5ZjBkYTdmOGVkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzczMTk4OTg1YmFjYjRmNzQ4NDk0YzgyZTMxNmU5NzYwID0gJCgnPGRpdiBpZD0iaHRtbF83MzE5ODk4NWJhY2I0Zjc0ODQ5NGM4MmUzMTZlOTc2MCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2VzdG9uIENsdXN0ZXIgNTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZmNiNTg3MGZkNTY0NGM0MzhhMzdiYjlmMGRhN2Y4ZWQuc2V0Q29udGVudChodG1sXzczMTk4OTg1YmFjYjRmNzQ4NDk0YzgyZTMxNmU5NzYwKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzc4ZDVmMzExNjU1ZDRjZGVhYTRlMWVmOWU0YTQyYzM0LmJpbmRQb3B1cChwb3B1cF9mY2I1ODcwZmQ1NjQ0YzQzOGEzN2JiOWYwZGE3ZjhlZCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yZDM5YzU4OWRiNTM0YmU4YTEwNTc5MDQxYTM0MmMxZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY5NjMxOSwtNzkuNTMyMjQyNDAwMDAwMDJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNTk0M2I4NTg5MzZmNDVhOWI1NWJkYTRkNzEzMjhjMWMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOWQ1YzYzNmFhNWNlNDIyMzk5MTIzMDAzOTA2ZDljNDQgPSAkKCc8ZGl2IGlkPSJodG1sXzlkNWM2MzZhYTVjZTQyMjM5OTEyMzAwMzkwNmQ5YzQ0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XZXN0bW91bnQgQ2x1c3RlciAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81OTQzYjg1ODkzNmY0NWE5YjU1YmRhNGQ3MTMyOGMxYy5zZXRDb250ZW50KGh0bWxfOWQ1YzYzNmFhNWNlNDIyMzk5MTIzMDAzOTA2ZDljNDQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMmQzOWM1ODlkYjUzNGJlOGExMDU3OTA0MWEzNDJjMWQuYmluZFBvcHVwKHBvcHVwXzU5NDNiODU4OTM2ZjQ1YTliNTViZGE0ZDcxMzI4YzFjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzBiNDQ0MDA4MmVmYTQwYWQ4M2RiNzU3ZmU0M2M1NDY4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjg4OTA1NCwtNzkuNTU0NzI0NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZWZiYzkzMTUzNzIzNGEzMzhmZTMxMjEyZTQxNTJkODMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjZhZGVlYzNhZjBkNGNkY2I1MGI3ZDFhMTZhNmU5YzMgPSAkKCc8ZGl2IGlkPSJodG1sX2Y2YWRlZWMzYWYwZDRjZGNiNTBiN2QxYTE2YTZlOWMzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5LaW5nc3ZpZXcgVmlsbGFnZSwgTWFydGluIEdyb3ZlIEdhcmRlbnMsIFJpY2h2aWV3IEdhcmRlbnMsIFN0LiBQaGlsbGlwcyBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2VmYmM5MzE1MzcyMzRhMzM4ZmUzMTIxMmU0MTUyZDgzLnNldENvbnRlbnQoaHRtbF9mNmFkZWVjM2FmMGQ0Y2RjYjUwYjdkMWExNmE2ZTljMyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wYjQ0NDAwODJlZmE0MGFkODNkYjc1N2ZlNDNjNTQ2OC5iaW5kUG9wdXAocG9wdXBfZWZiYzkzMTUzNzIzNGEzMzhmZTMxMjEyZTQxNTJkODMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZDJmZGY2OTFjN2YzNGViNmE4OTFhMDY5ZjUxNTlkYjggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43Mzk0MTYzOTk5OTk5OTYsLTc5LjU4ODQzNjldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmMDAwMCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjAwMDAiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMmFhZGUwMjUzNTRiNDllNjkzZTZiMzVjMmQ1OTdjYjYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNmI4NDQyMzQ3ZTA0NGFiZTlmMGRkMjQ2MWViMWY3NGYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZGY3NzI2ODJkYjIyNDcwZjlmMTRjNzZiZTk0OGVjMzEgPSAkKCc8ZGl2IGlkPSJodG1sX2RmNzcyNjgyZGIyMjQ3MGY5ZjE0Yzc2YmU5NDhlYzMxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5BbGJpb24gR2FyZGVucywgQmVhdW1vbmQgSGVpZ2h0cywgSHVtYmVyZ2F0ZSwgSmFtZXN0b3duLCBNb3VudCBPbGl2ZSwgU2lsdmVyc3RvbmUsIFNvdXRoIFN0ZWVsZXMsIFRoaXN0bGV0b3duIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNmI4NDQyMzQ3ZTA0NGFiZTlmMGRkMjQ2MWViMWY3NGYuc2V0Q29udGVudChodG1sX2RmNzcyNjgyZGIyMjQ3MGY5ZjE0Yzc2YmU5NDhlYzMxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2QyZmRmNjkxYzdmMzRlYjZhODkxYTA2OWY1MTU5ZGI4LmJpbmRQb3B1cChwb3B1cF82Yjg0NDIzNDdlMDQ0YWJlOWYwZGQyNDYxZWIxZjc0Zik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wNjMxOTZlMDVjMTU0MjY2ODUyNTUwMTdhODlhZTViOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcwNjc0ODI5OTk5OTk5NCwtNzkuNTk0MDU0NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yYWFkZTAyNTM1NGI0OWU2OTNlNmIzNWMyZDU5N2NiNik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81MjM0OTBiNzk0MGY0NTUwOWZlOTA1ZjBlNmY1NzcwMCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80YmEyZTQ0MjI1Mjg0YWYzYjVkNDI0MjMyYzI3OGIzMCA9ICQoJzxkaXYgaWQ9Imh0bWxfNGJhMmU0NDIyNTI4NGFmM2I1ZDQyNDIzMmMyNzhiMzAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5vcnRod2VzdCBDbHVzdGVyIDA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzUyMzQ5MGI3OTQwZjQ1NTA5ZmU5MDVmMGU2ZjU3NzAwLnNldENvbnRlbnQoaHRtbF80YmEyZTQ0MjI1Mjg0YWYzYjVkNDI0MjMyYzI3OGIzMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wNjMxOTZlMDVjMTU0MjY2ODUyNTUwMTdhODlhZTViOS5iaW5kUG9wdXAocG9wdXBfNTIzNDkwYjc5NDBmNDU1MDlmZTkwNWYwZTZmNTc3MDApOwoKICAgICAgICAgICAgCiAgICAgICAgCjwvc2NyaXB0Pg==\" 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 0x7f8f8f7bcd68>"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# create map\n",
"map_clusters = folium.Map(location=[latitude, longitude], zoom_start=11)\n",
"\n",
"# set color scheme for the clusters\n",
"x = np.arange(kclusters)\n",
"ys = [i + x + (i*x)**2 for i in range(kclusters)]\n",
"colors_array = cm.rainbow(np.linspace(0, 1, len(ys)))\n",
"rainbow = [colors.rgb2hex(i) for i in colors_array]\n",
"\n",
"# add markers to the map\n",
"markers_colors = []\n",
"for lat, lon, poi, cluster in zip(toronto_merged['Latitude'], toronto_merged['Longitude'], toronto_merged['Neighborhood'], toronto_merged['Cluster Labels']):\n",
" label = folium.Popup(str(poi) + ' Cluster ' + str(cluster), parse_html=True)\n",
" folium.CircleMarker(\n",
" [lat, lon],\n",
" radius=5,\n",
" popup=label,\n",
" color=rainbow[cluster-1],\n",
" fill=True,\n",
" fill_color=rainbow[cluster-1],\n",
" fill_opacity=0.7).add_to(map_clusters)\n",
" \n",
"map_clusters"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>PostalCode</th>\n",
" <th>Borough</th>\n",
" <th>Neighborhood</th>\n",
" <th>Latitude</th>\n",
" <th>Longitude</th>\n",
" <th>Cluster Labels</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>M1B</td>\n",
" <td>Scarborough</td>\n",
" <td>Rouge, Malvern</td>\n",
" <td>43.806686</td>\n",
" <td>-79.194353</td>\n",
" <td>0</td>\n",
" <td>Fast Food Restaurant</td>\n",
" <td>Print Shop</td>\n",
" <td>Women's Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Doner Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>M1C</td>\n",
" <td>Scarborough</td>\n",
" <td>Highland Creek, Rouge Hill, Port Union</td>\n",
" <td>43.784535</td>\n",
" <td>-79.160497</td>\n",
" <td>2</td>\n",
" <td>History Museum</td>\n",
" <td>Bar</td>\n",
" <td>Women's Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Deli / Bodega</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>M1E</td>\n",
" <td>Scarborough</td>\n",
" <td>Guildwood, Morningside, West Hill</td>\n",
" <td>43.763573</td>\n",
" <td>-79.188711</td>\n",
" <td>0</td>\n",
" <td>Electronics Store</td>\n",
" <td>Intersection</td>\n",
" <td>Mexican Restaurant</td>\n",
" <td>Spa</td>\n",
" <td>Breakfast Spot</td>\n",
" <td>Pizza Place</td>\n",
" <td>Rental Car Location</td>\n",
" <td>Medical Center</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>M1G</td>\n",
" <td>Scarborough</td>\n",
" <td>Woburn</td>\n",
" <td>43.770992</td>\n",
" <td>-79.216917</td>\n",
" <td>0</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Pharmacy</td>\n",
" <td>Korean Restaurant</td>\n",
" <td>Women's Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>M1H</td>\n",
" <td>Scarborough</td>\n",
" <td>Cedarbrae</td>\n",
" <td>43.773136</td>\n",
" <td>-79.239476</td>\n",
" <td>0</td>\n",
" <td>Fried Chicken Joint</td>\n",
" <td>Caribbean Restaurant</td>\n",
" <td>Bank</td>\n",
" <td>Athletics &amp; Sports</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Gas Station</td>\n",
" <td>Hakka Restaurant</td>\n",
" <td>Lounge</td>\n",
" <td>Bakery</td>\n",
" <td>Dumpling Restaurant</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" PostalCode Borough Neighborhood Latitude \\\n",
"0 M1B Scarborough Rouge, Malvern 43.806686 \n",
"1 M1C Scarborough Highland Creek, Rouge Hill, Port Union 43.784535 \n",
"2 M1E Scarborough Guildwood, Morningside, West Hill 43.763573 \n",
"3 M1G Scarborough Woburn 43.770992 \n",
"4 M1H Scarborough Cedarbrae 43.773136 \n",
"\n",
" Longitude Cluster Labels 1st Most Common Venue 2nd Most Common Venue \\\n",
"0 -79.194353 0 Fast Food Restaurant Print Shop \n",
"1 -79.160497 2 History Museum Bar \n",
"2 -79.188711 0 Electronics Store Intersection \n",
"3 -79.216917 0 Coffee Shop Pharmacy \n",
"4 -79.239476 0 Fried Chicken Joint Caribbean Restaurant \n",
"\n",
" 3rd Most Common Venue 4th Most Common Venue 5th Most Common Venue \\\n",
"0 Women's Store Dog Run Department Store \n",
"1 Women's Store Dessert Shop Dim Sum Restaurant \n",
"2 Mexican Restaurant Spa Breakfast Spot \n",
"3 Korean Restaurant Women's Store Dog Run \n",
"4 Bank Athletics & Sports Thai Restaurant \n",
"\n",
" 6th Most Common Venue 7th Most Common Venue 8th Most Common Venue \\\n",
"0 Dessert Shop Dim Sum Restaurant Diner \n",
"1 Diner Discount Store Dog Run \n",
"2 Pizza Place Rental Car Location Medical Center \n",
"3 Department Store Dessert Shop Dim Sum Restaurant \n",
"4 Gas Station Hakka Restaurant Lounge \n",
"\n",
" 9th Most Common Venue 10th Most Common Venue \n",
"0 Discount Store Doner Restaurant \n",
"1 Doner Restaurant Deli / Bodega \n",
"2 Department Store Dessert Shop \n",
"3 Diner Discount Store \n",
"4 Bakery Dumpling Restaurant "
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"toronto_merged.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Section 9: Exploring the clusters"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Cluster 1**"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Neighborhood</th>\n",
" <th>Cluster Labels</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Rouge, Malvern</td>\n",
" <td>0</td>\n",
" <td>Fast Food Restaurant</td>\n",
" <td>Print Shop</td>\n",
" <td>Women's Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Doner Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Guildwood, Morningside, West Hill</td>\n",
" <td>0</td>\n",
" <td>Electronics Store</td>\n",
" <td>Intersection</td>\n",
" <td>Mexican Restaurant</td>\n",
" <td>Spa</td>\n",
" <td>Breakfast Spot</td>\n",
" <td>Pizza Place</td>\n",
" <td>Rental Car Location</td>\n",
" <td>Medical Center</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Woburn</td>\n",
" <td>0</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Pharmacy</td>\n",
" <td>Korean Restaurant</td>\n",
" <td>Women's Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Cedarbrae</td>\n",
" <td>0</td>\n",
" <td>Fried Chicken Joint</td>\n",
" <td>Caribbean Restaurant</td>\n",
" <td>Bank</td>\n",
" <td>Athletics &amp; Sports</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Gas Station</td>\n",
" <td>Hakka Restaurant</td>\n",
" <td>Lounge</td>\n",
" <td>Bakery</td>\n",
" <td>Dumpling Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>East Birchmount Park, Ionview, Kennedy Park</td>\n",
" <td>0</td>\n",
" <td>Department Store</td>\n",
" <td>Convenience Store</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Discount Store</td>\n",
" <td>Chinese Restaurant</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Dog Run</td>\n",
" <td>Doner Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>94</th>\n",
" <td>Humber Summit</td>\n",
" <td>0</td>\n",
" <td>Empanada Restaurant</td>\n",
" <td>Pizza Place</td>\n",
" <td>Dog Run</td>\n",
" <td>Deli / Bodega</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Doner Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>97</th>\n",
" <td>Westmount</td>\n",
" <td>0</td>\n",
" <td>Pizza Place</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Intersection</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Discount Store</td>\n",
" <td>Chinese Restaurant</td>\n",
" <td>Middle Eastern Restaurant</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Donut Shop</td>\n",
" <td>Dog Run</td>\n",
" </tr>\n",
" <tr>\n",
" <th>98</th>\n",
" <td>Kingsview Village, Martin Grove Gardens, Richv...</td>\n",
" <td>0</td>\n",
" <td>Mobile Phone Shop</td>\n",
" <td>Bus Line</td>\n",
" <td>Pizza Place</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Discount Store</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Dog Run</td>\n",
" </tr>\n",
" <tr>\n",
" <th>99</th>\n",
" <td>Albion Gardens, Beaumond Heights, Humbergate, ...</td>\n",
" <td>0</td>\n",
" <td>Pizza Place</td>\n",
" <td>Grocery Store</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Beer Store</td>\n",
" <td>Fast Food Restaurant</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Japanese Restaurant</td>\n",
" <td>Discount Store</td>\n",
" <td>Fried Chicken Joint</td>\n",
" <td>Liquor Store</td>\n",
" </tr>\n",
" <tr>\n",
" <th>100</th>\n",
" <td>Northwest</td>\n",
" <td>0</td>\n",
" <td>Rental Car Location</td>\n",
" <td>Drugstore</td>\n",
" <td>Bar</td>\n",
" <td>Dog Run</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Women's Store</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>84 rows × 12 columns</p>\n",
"</div>"
],
"text/plain": [
" Neighborhood Cluster Labels \\\n",
"0 Rouge, Malvern 0 \n",
"2 Guildwood, Morningside, West Hill 0 \n",
"3 Woburn 0 \n",
"4 Cedarbrae 0 \n",
"6 East Birchmount Park, Ionview, Kennedy Park 0 \n",
".. ... ... \n",
"94 Humber Summit 0 \n",
"97 Westmount 0 \n",
"98 Kingsview Village, Martin Grove Gardens, Richv... 0 \n",
"99 Albion Gardens, Beaumond Heights, Humbergate, ... 0 \n",
"100 Northwest 0 \n",
"\n",
" 1st Most Common Venue 2nd Most Common Venue 3rd Most Common Venue \\\n",
"0 Fast Food Restaurant Print Shop Women's Store \n",
"2 Electronics Store Intersection Mexican Restaurant \n",
"3 Coffee Shop Pharmacy Korean Restaurant \n",
"4 Fried Chicken Joint Caribbean Restaurant Bank \n",
"6 Department Store Convenience Store Coffee Shop \n",
".. ... ... ... \n",
"94 Empanada Restaurant Pizza Place Dog Run \n",
"97 Pizza Place Coffee Shop Intersection \n",
"98 Mobile Phone Shop Bus Line Pizza Place \n",
"99 Pizza Place Grocery Store Coffee Shop \n",
"100 Rental Car Location Drugstore Bar \n",
"\n",
" 4th Most Common Venue 5th Most Common Venue 6th Most Common Venue \\\n",
"0 Dog Run Department Store Dessert Shop \n",
"2 Spa Breakfast Spot Pizza Place \n",
"3 Women's Store Dog Run Department Store \n",
"4 Athletics & Sports Thai Restaurant Gas Station \n",
"6 Discount Store Chinese Restaurant Dessert Shop \n",
".. ... ... ... \n",
"94 Deli / Bodega Department Store Dessert Shop \n",
"97 Sandwich Place Discount Store Chinese Restaurant \n",
"98 Sandwich Place Discount Store Department Store \n",
"99 Beer Store Fast Food Restaurant Sandwich Place \n",
"100 Dog Run Department Store Dessert Shop \n",
"\n",
" 7th Most Common Venue 8th Most Common Venue 9th Most Common Venue \\\n",
"0 Dim Sum Restaurant Diner Discount Store \n",
"2 Rental Car Location Medical Center Department Store \n",
"3 Dessert Shop Dim Sum Restaurant Diner \n",
"4 Hakka Restaurant Lounge Bakery \n",
"6 Dim Sum Restaurant Diner Dog Run \n",
".. ... ... ... \n",
"94 Dim Sum Restaurant Diner Discount Store \n",
"97 Middle Eastern Restaurant Doner Restaurant Donut Shop \n",
"98 Dessert Shop Dim Sum Restaurant Diner \n",
"99 Japanese Restaurant Discount Store Fried Chicken Joint \n",
"100 Dim Sum Restaurant Diner Discount Store \n",
"\n",
" 10th Most Common Venue \n",
"0 Doner Restaurant \n",
"2 Dessert Shop \n",
"3 Discount Store \n",
"4 Dumpling Restaurant \n",
"6 Doner Restaurant \n",
".. ... \n",
"94 Doner Restaurant \n",
"97 Dog Run \n",
"98 Dog Run \n",
"99 Liquor Store \n",
"100 Women's Store \n",
"\n",
"[84 rows x 12 columns]"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"toronto_merged.loc[toronto_merged['Cluster Labels'] == 0, toronto_merged.columns[[2] + list(range(5, toronto_merged.shape[1]))]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Cluster 2**"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Neighborhood</th>\n",
" <th>Cluster Labels</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>91</th>\n",
" <td>Humber Bay, King's Mill Park, Kingsway Park So...</td>\n",
" <td>1</td>\n",
" <td>Baseball Field</td>\n",
" <td>Women's Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Donut Shop</td>\n",
" <td>Falafel Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>95</th>\n",
" <td>Emery, Humberlea</td>\n",
" <td>1</td>\n",
" <td>Baseball Field</td>\n",
" <td>Women's Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Donut Shop</td>\n",
" <td>Falafel Restaurant</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Neighborhood Cluster Labels \\\n",
"91 Humber Bay, King's Mill Park, Kingsway Park So... 1 \n",
"95 Emery, Humberlea 1 \n",
"\n",
" 1st Most Common Venue 2nd Most Common Venue 3rd Most Common Venue \\\n",
"91 Baseball Field Women's Store Dessert Shop \n",
"95 Baseball Field Women's Store Dessert Shop \n",
"\n",
" 4th Most Common Venue 5th Most Common Venue 6th Most Common Venue \\\n",
"91 Dim Sum Restaurant Diner Discount Store \n",
"95 Dim Sum Restaurant Diner Discount Store \n",
"\n",
" 7th Most Common Venue 8th Most Common Venue 9th Most Common Venue \\\n",
"91 Dog Run Doner Restaurant Donut Shop \n",
"95 Dog Run Doner Restaurant Donut Shop \n",
"\n",
" 10th Most Common Venue \n",
"91 Falafel Restaurant \n",
"95 Falafel Restaurant "
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"toronto_merged.loc[toronto_merged['Cluster Labels'] == 1, toronto_merged.columns[[2] + list(range(5, toronto_merged.shape[1]))]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Cluster 3**"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Neighborhood</th>\n",
" <th>Cluster Labels</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Highland Creek, Rouge Hill, Port Union</td>\n",
" <td>2</td>\n",
" <td>History Museum</td>\n",
" <td>Bar</td>\n",
" <td>Women's Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Deli / Bodega</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Neighborhood Cluster Labels \\\n",
"1 Highland Creek, Rouge Hill, Port Union 2 \n",
"\n",
" 1st Most Common Venue 2nd Most Common Venue 3rd Most Common Venue \\\n",
"1 History Museum Bar Women's Store \n",
"\n",
" 4th Most Common Venue 5th Most Common Venue 6th Most Common Venue \\\n",
"1 Dessert Shop Dim Sum Restaurant Diner \n",
"\n",
" 7th Most Common Venue 8th Most Common Venue 9th Most Common Venue \\\n",
"1 Discount Store Dog Run Doner Restaurant \n",
"\n",
" 10th Most Common Venue \n",
"1 Deli / Bodega "
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"toronto_merged.loc[toronto_merged['Cluster Labels'] == 2, toronto_merged.columns[[2] + list(range(5, toronto_merged.shape[1]))]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Cluster 4**"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Neighborhood</th>\n",
" <th>Cluster Labels</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>62</th>\n",
" <td>Roselawn</td>\n",
" <td>3</td>\n",
" <td>Garden</td>\n",
" <td>Women's Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Dance Studio</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Neighborhood Cluster Labels 1st Most Common Venue 2nd Most Common Venue \\\n",
"62 Roselawn 3 Garden Women's Store \n",
"\n",
" 3rd Most Common Venue 4th Most Common Venue 5th Most Common Venue \\\n",
"62 Dog Run Department Store Dessert Shop \n",
"\n",
" 6th Most Common Venue 7th Most Common Venue 8th Most Common Venue \\\n",
"62 Dim Sum Restaurant Diner Discount Store \n",
"\n",
" 9th Most Common Venue 10th Most Common Venue \n",
"62 Doner Restaurant Dance Studio "
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"toronto_merged.loc[toronto_merged['Cluster Labels'] == 3, toronto_merged.columns[[2] + list(range(5, toronto_merged.shape[1]))]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Cluster 5**"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Neighborhood</th>\n",
" <th>Cluster Labels</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>19</th>\n",
" <td>Silver Hills, York Mills</td>\n",
" <td>4</td>\n",
" <td>Cafeteria</td>\n",
" <td>Women's Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Dance Studio</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Neighborhood Cluster Labels 1st Most Common Venue \\\n",
"19 Silver Hills, York Mills 4 Cafeteria \n",
"\n",
" 2nd Most Common Venue 3rd Most Common Venue 4th Most Common Venue \\\n",
"19 Women's Store Dog Run Department Store \n",
"\n",
" 5th Most Common Venue 6th Most Common Venue 7th Most Common Venue \\\n",
"19 Dessert Shop Dim Sum Restaurant Diner \n",
"\n",
" 8th Most Common Venue 9th Most Common Venue 10th Most Common Venue \n",
"19 Discount Store Doner Restaurant Dance Studio "
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"toronto_merged.loc[toronto_merged['Cluster Labels'] == 4, toronto_merged.columns[[2] + list(range(5, toronto_merged.shape[1]))]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Cluster 6**"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Neighborhood</th>\n",
" <th>Cluster Labels</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>Scarborough Village</td>\n",
" <td>5</td>\n",
" <td>Playground</td>\n",
" <td>Jewelry Store</td>\n",
" <td>Women's Store</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Drugstore</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14</th>\n",
" <td>Agincourt North, L'Amoreaux East, Milliken, St...</td>\n",
" <td>5</td>\n",
" <td>Park</td>\n",
" <td>Playground</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Donut Shop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>22</th>\n",
" <td>York Mills West</td>\n",
" <td>5</td>\n",
" <td>Park</td>\n",
" <td>Convenience Store</td>\n",
" <td>Bank</td>\n",
" <td>Bar</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Women's Store</td>\n",
" </tr>\n",
" <tr>\n",
" <th>24</th>\n",
" <td>Parkwoods</td>\n",
" <td>5</td>\n",
" <td>Park</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Bus Stop</td>\n",
" <td>Eastern European Restaurant</td>\n",
" <td>Dumpling Restaurant</td>\n",
" <td>Drugstore</td>\n",
" <td>Donut Shop</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Ethiopian Restaurant</td>\n",
" <td>Discount Store</td>\n",
" </tr>\n",
" <tr>\n",
" <th>39</th>\n",
" <td>East Toronto</td>\n",
" <td>5</td>\n",
" <td>Park</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Convenience Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Doner Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>43</th>\n",
" <td>Lawrence Park</td>\n",
" <td>5</td>\n",
" <td>Park</td>\n",
" <td>Swim School</td>\n",
" <td>Bus Line</td>\n",
" <td>Dog Run</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Deli / Bodega</td>\n",
" </tr>\n",
" <tr>\n",
" <th>47</th>\n",
" <td>Moore Park, Summerhill East</td>\n",
" <td>5</td>\n",
" <td>Park</td>\n",
" <td>Playground</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Donut Shop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>49</th>\n",
" <td>Rosedale</td>\n",
" <td>5</td>\n",
" <td>Park</td>\n",
" <td>Playground</td>\n",
" <td>Trail</td>\n",
" <td>Eastern European Restaurant</td>\n",
" <td>Dumpling Restaurant</td>\n",
" <td>Drugstore</td>\n",
" <td>Donut Shop</td>\n",
" <td>Electronics Store</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Curling Ice</td>\n",
" </tr>\n",
" <tr>\n",
" <th>63</th>\n",
" <td>Forest Hill North, Forest Hill West</td>\n",
" <td>5</td>\n",
" <td>Park</td>\n",
" <td>Jewelry Store</td>\n",
" <td>Sushi Restaurant</td>\n",
" <td>Trail</td>\n",
" <td>Dumpling Restaurant</td>\n",
" <td>Eastern European Restaurant</td>\n",
" <td>Drugstore</td>\n",
" <td>Donut Shop</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Dance Studio</td>\n",
" </tr>\n",
" <tr>\n",
" <th>73</th>\n",
" <td>Caledonia-Fairbanks</td>\n",
" <td>5</td>\n",
" <td>Park</td>\n",
" <td>Pool</td>\n",
" <td>Women's Store</td>\n",
" <td>College Rec Center</td>\n",
" <td>Deli / Bodega</td>\n",
" <td>Empanada Restaurant</td>\n",
" <td>Electronics Store</td>\n",
" <td>Eastern European Restaurant</td>\n",
" <td>Dumpling Restaurant</td>\n",
" <td>Drugstore</td>\n",
" </tr>\n",
" <tr>\n",
" <th>90</th>\n",
" <td>The Kingsway, Montgomery Road, Old Mill North</td>\n",
" <td>5</td>\n",
" <td>Park</td>\n",
" <td>River</td>\n",
" <td>Empanada Restaurant</td>\n",
" <td>Electronics Store</td>\n",
" <td>Eastern European Restaurant</td>\n",
" <td>Dumpling Restaurant</td>\n",
" <td>Drugstore</td>\n",
" <td>Donut Shop</td>\n",
" <td>Ethiopian Restaurant</td>\n",
" <td>Dog Run</td>\n",
" </tr>\n",
" <tr>\n",
" <th>96</th>\n",
" <td>Weston</td>\n",
" <td>5</td>\n",
" <td>Park</td>\n",
" <td>Convenience Store</td>\n",
" <td>Dog Run</td>\n",
" <td>Department Store</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dim Sum Restaurant</td>\n",
" <td>Diner</td>\n",
" <td>Discount Store</td>\n",
" <td>Doner Restaurant</td>\n",
" <td>Dance Studio</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Neighborhood Cluster Labels \\\n",
"5 Scarborough Village 5 \n",
"14 Agincourt North, L'Amoreaux East, Milliken, St... 5 \n",
"22 York Mills West 5 \n",
"24 Parkwoods 5 \n",
"39 East Toronto 5 \n",
"43 Lawrence Park 5 \n",
"47 Moore Park, Summerhill East 5 \n",
"49 Rosedale 5 \n",
"63 Forest Hill North, Forest Hill West 5 \n",
"73 Caledonia-Fairbanks 5 \n",
"90 The Kingsway, Montgomery Road, Old Mill North 5 \n",
"96 Weston 5 \n",
"\n",
" 1st Most Common Venue 2nd Most Common Venue 3rd Most Common Venue \\\n",
"5 Playground Jewelry Store Women's Store \n",
"14 Park Playground Doner Restaurant \n",
"22 Park Convenience Store Bank \n",
"24 Park Food & Drink Shop Bus Stop \n",
"39 Park Coffee Shop Convenience Store \n",
"43 Park Swim School Bus Line \n",
"47 Park Playground Doner Restaurant \n",
"49 Park Playground Trail \n",
"63 Park Jewelry Store Sushi Restaurant \n",
"73 Park Pool Women's Store \n",
"90 Park River Empanada Restaurant \n",
"96 Park Convenience Store Dog Run \n",
"\n",
" 4th Most Common Venue 5th Most Common Venue \\\n",
"5 Doner Restaurant Dessert Shop \n",
"14 Department Store Dessert Shop \n",
"22 Bar Doner Restaurant \n",
"24 Eastern European Restaurant Dumpling Restaurant \n",
"39 Dog Run Department Store \n",
"43 Dog Run Dessert Shop \n",
"47 Department Store Dessert Shop \n",
"49 Eastern European Restaurant Dumpling Restaurant \n",
"63 Trail Dumpling Restaurant \n",
"73 College Rec Center Deli / Bodega \n",
"90 Electronics Store Eastern European Restaurant \n",
"96 Department Store Dessert Shop \n",
"\n",
" 6th Most Common Venue 7th Most Common Venue \\\n",
"5 Dim Sum Restaurant Diner \n",
"14 Dim Sum Restaurant Diner \n",
"22 Dim Sum Restaurant Diner \n",
"24 Drugstore Donut Shop \n",
"39 Dessert Shop Dim Sum Restaurant \n",
"43 Dim Sum Restaurant Diner \n",
"47 Dim Sum Restaurant Diner \n",
"49 Drugstore Donut Shop \n",
"63 Eastern European Restaurant Drugstore \n",
"73 Empanada Restaurant Electronics Store \n",
"90 Dumpling Restaurant Drugstore \n",
"96 Dim Sum Restaurant Diner \n",
"\n",
" 8th Most Common Venue 9th Most Common Venue 10th Most Common Venue \n",
"5 Discount Store Dog Run Drugstore \n",
"14 Discount Store Dog Run Donut Shop \n",
"22 Discount Store Dog Run Women's Store \n",
"24 Doner Restaurant Ethiopian Restaurant Discount Store \n",
"39 Diner Discount Store Doner Restaurant \n",
"43 Discount Store Doner Restaurant Deli / Bodega \n",
"47 Discount Store Dog Run Donut Shop \n",
"49 Electronics Store Doner Restaurant Curling Ice \n",
"63 Donut Shop Doner Restaurant Dance Studio \n",
"73 Eastern European Restaurant Dumpling Restaurant Drugstore \n",
"90 Donut Shop Ethiopian Restaurant Dog Run \n",
"96 Discount Store Doner Restaurant Dance Studio "
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"toronto_merged.loc[toronto_merged['Cluster Labels'] == 5, toronto_merged.columns[[2] + list(range(5, toronto_merged.shape[1]))]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Section 10: Conclusions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Started with 10 clusters and observed the qualitative characteristics of the clustering results.\n",
"\n",
"It seemed that clustering was not very successful:\n",
"* no clear similarity patter on many of the clusters \n",
"* some over-fitting was evident; neighborhood (Postal Code) with park was not assigned to the cluster of parks and similar \"green\" areas\n",
" \n",
"Started reducing clusters and monitored the results.\n",
"\n",
"Ended up in the following:\n",
"* manual setup of the main KMeans parameters\n",
"* 6 clusters:\n",
" 1. Places close to a restaurant and various other venues of general interest\n",
" 2. Places close to baseball field and women's store\n",
" 3. PLace closest to a history museum\n",
" 4. Place closest to a garden\n",
" 5. Place closest to a cafeteria\n",
" 6. PLaces closest to a park"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python",
"language": "python",
"name": "conda-env-python-py"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.7"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment