Skip to content

Instantly share code, notes, and snippets.

@gustamo
Created June 22, 2020 19:53
Show Gist options
  • Save gustamo/ba680bb57a009764e1c8802328b4acdc to your computer and use it in GitHub Desktop.
Save gustamo/ba680bb57a009764e1c8802328b4acdc to your computer and use it in GitHub Desktop.
Created on Skills Network Labs
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a href=\"https://en.wikipedia.org/wiki/The_Accidental_Tourist_(film)\">\n",
"<img src = \"https://images-na.ssl-images-amazon.com/images/I/91hXwldu4lL._RI_.jpg\" width = 400> </a>\n",
"\n",
"<h1 align=center><font size = 5>The Accidental Tourist Reccomendation System</font></h1>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<h1 align=center><font size = 3>This notebook was made for the travelers that live in NY and want to visit Toronto. Even far from their neighborhoods, they want to have the same conveniences they have in the neighborhood they live. They don't want to be badly surprised with having no venues around that they are not used to. So the user will pick the neighborhood he lives in NY from a list, and then the algorithm will find the similar neighborhoods in Toronto. </font></h1>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First, we import all the libraries we need:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Collecting package metadata (current_repodata.json): done\n",
"Solving environment: done\n",
"\n",
"## Package Plan ##\n",
"\n",
" environment location: /home/jupyterlab/conda/envs/python\n",
"\n",
" added / updated specs:\n",
" - geopy\n",
"\n",
"\n",
"The following packages will be downloaded:\n",
"\n",
" package | build\n",
" ---------------------------|-----------------\n",
" ca-certificates-2020.4.5.2 | hecda079_0 147 KB conda-forge\n",
" certifi-2020.4.5.2 | py36h9f0ad1d_0 152 KB conda-forge\n",
" geographiclib-1.50 | py_0 34 KB conda-forge\n",
" geopy-1.22.0 | pyh9f0ad1d_0 63 KB conda-forge\n",
" ------------------------------------------------------------\n",
" Total: 395 KB\n",
"\n",
"The following NEW packages will be INSTALLED:\n",
"\n",
" geographiclib conda-forge/noarch::geographiclib-1.50-py_0\n",
" geopy conda-forge/noarch::geopy-1.22.0-pyh9f0ad1d_0\n",
"\n",
"The following packages will be UPDATED:\n",
"\n",
" ca-certificates 2020.4.5.1-hecc5488_0 --> 2020.4.5.2-hecda079_0\n",
" certifi 2020.4.5.1-py36h9f0ad1d_0 --> 2020.4.5.2-py36h9f0ad1d_0\n",
"\n",
"\n",
"\n",
"Downloading and Extracting Packages\n",
"geopy-1.22.0 | 63 KB | ##################################### | 100% \n",
"certifi-2020.4.5.2 | 152 KB | ##################################### | 100% \n",
"ca-certificates-2020 | 147 KB | ##################################### | 100% \n",
"geographiclib-1.50 | 34 KB | ##################################### | 100% \n",
"Preparing transaction: done\n",
"Verifying transaction: done\n",
"Executing transaction: done\n",
"Collecting package metadata (current_repodata.json): done\n",
"Solving environment: failed with initial frozen solve. Retrying with flexible solve.\n",
"Collecting package metadata (repodata.json): done\n",
"Solving environment: done\n",
"\n",
"## Package Plan ##\n",
"\n",
" environment location: /home/jupyterlab/conda/envs/python\n",
"\n",
" added / updated specs:\n",
" - folium=0.5.0\n",
"\n",
"\n",
"The following packages will be downloaded:\n",
"\n",
" package | build\n",
" ---------------------------|-----------------\n",
" altair-4.1.0 | py_1 614 KB conda-forge\n",
" branca-0.4.1 | py_0 26 KB conda-forge\n",
" brotlipy-0.7.0 |py36h8c4c3a4_1000 346 KB conda-forge\n",
" chardet-3.0.4 |py36h9f0ad1d_1006 188 KB conda-forge\n",
" cryptography-2.9.2 | py36h45558ae_0 613 KB conda-forge\n",
" folium-0.5.0 | py_0 45 KB conda-forge\n",
" pandas-1.0.4 | py36h830a2c2_0 10.1 MB conda-forge\n",
" pysocks-1.7.1 | py36h9f0ad1d_1 27 KB conda-forge\n",
" toolz-0.10.0 | py_0 46 KB conda-forge\n",
" vincent-0.4.4 | py_1 28 KB conda-forge\n",
" ------------------------------------------------------------\n",
" Total: 12.0 MB\n",
"\n",
"The following NEW packages will be INSTALLED:\n",
"\n",
" altair conda-forge/noarch::altair-4.1.0-py_1\n",
" attrs conda-forge/noarch::attrs-19.3.0-py_0\n",
" branca conda-forge/noarch::branca-0.4.1-py_0\n",
" brotlipy conda-forge/linux-64::brotlipy-0.7.0-py36h8c4c3a4_1000\n",
" chardet conda-forge/linux-64::chardet-3.0.4-py36h9f0ad1d_1006\n",
" cryptography conda-forge/linux-64::cryptography-2.9.2-py36h45558ae_0\n",
" entrypoints conda-forge/linux-64::entrypoints-0.3-py36h9f0ad1d_1001\n",
" folium conda-forge/noarch::folium-0.5.0-py_0\n",
" idna conda-forge/noarch::idna-2.9-py_1\n",
" importlib_metadata conda-forge/noarch::importlib_metadata-1.6.0-0\n",
" jinja2 conda-forge/noarch::jinja2-2.11.2-pyh9f0ad1d_0\n",
" jsonschema conda-forge/linux-64::jsonschema-3.2.0-py36h9f0ad1d_1\n",
" markupsafe conda-forge/linux-64::markupsafe-1.1.1-py36h8c4c3a4_1\n",
" pandas conda-forge/linux-64::pandas-1.0.4-py36h830a2c2_0\n",
" pyopenssl conda-forge/noarch::pyopenssl-19.1.0-py_1\n",
" pyrsistent conda-forge/linux-64::pyrsistent-0.16.0-py36h8c4c3a4_0\n",
" pysocks conda-forge/linux-64::pysocks-1.7.1-py36h9f0ad1d_1\n",
" pytz conda-forge/noarch::pytz-2020.1-pyh9f0ad1d_0\n",
" requests conda-forge/noarch::requests-2.23.0-pyh8c360ce_2\n",
" toolz conda-forge/noarch::toolz-0.10.0-py_0\n",
" urllib3 conda-forge/noarch::urllib3-1.25.9-py_0\n",
" vincent conda-forge/noarch::vincent-0.4.4-py_1\n",
"\n",
"\n",
"\n",
"Downloading and Extracting Packages\n",
"pysocks-1.7.1 | 27 KB | ##################################### | 100% \n",
"toolz-0.10.0 | 46 KB | ##################################### | 100% \n",
"chardet-3.0.4 | 188 KB | ##################################### | 100% \n",
"pandas-1.0.4 | 10.1 MB | ##################################### | 100% \n",
"folium-0.5.0 | 45 KB | ##################################### | 100% \n",
"branca-0.4.1 | 26 KB | ##################################### | 100% \n",
"cryptography-2.9.2 | 613 KB | ##################################### | 100% \n",
"brotlipy-0.7.0 | 346 KB | ##################################### | 100% \n",
"altair-4.1.0 | 614 KB | ##################################### | 100% \n",
"vincent-0.4.4 | 28 KB | ##################################### | 100% \n",
"Preparing transaction: done\n",
"Verifying transaction: done\n",
"Executing transaction: done\n"
]
}
],
"source": [
"import numpy as np # library to handle data in a vectorized manner\n",
"\n",
"import pandas as pd # library for data analsysis\n",
"pd.set_option('display.max_columns', None)\n",
"pd.set_option('display.max_rows', None)\n",
"\n",
"import json # library to handle JSON files\n",
"\n",
"!conda install -c conda-forge geopy --yes # uncomment this line if you haven't completed the Foursquare API lab\n",
"from geopy.geocoders import Nominatim # convert an address into latitude and longitude values\n",
"\n",
"import requests # library to handle requests\n",
"from pandas.io.json import json_normalize # tranform JSON file into a pandas dataframe\n",
"\n",
"# Matplotlib and associated plotting modules\n",
"import matplotlib.cm as cm\n",
"import matplotlib.colors as colors\n",
"\n",
"# import k-means from clustering stage\n",
"from sklearn.cluster import KMeans\n",
"\n",
"!conda install -c conda-forge folium=0.5.0 --yes # uncomment this line if you haven't completed the Foursquare API lab\n",
"import folium # map rendering library\n",
"\n",
"#!conda install -c conda-forge ipywidgets\n",
"#import ipywidgets as widgets\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: ipywidgets in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (7.4.2)\n",
"Requirement already satisfied: ipython>=4.0.0; python_version >= \"3.3\" in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from ipywidgets) (7.14.0)\n",
"Requirement already satisfied: ipykernel>=4.5.1 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from ipywidgets) (5.2.1)\n",
"Requirement already satisfied: traitlets>=4.3.1 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from ipywidgets) (4.3.3)\n",
"Requirement already satisfied: nbformat>=4.2.0 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from ipywidgets) (5.0.6)\n",
"Requirement already satisfied: widgetsnbextension~=3.4.0 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from ipywidgets) (3.4.2)\n",
"Requirement already satisfied: decorator in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from ipython>=4.0.0; python_version >= \"3.3\"->ipywidgets) (4.4.2)\n",
"Requirement already satisfied: backcall in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from ipython>=4.0.0; python_version >= \"3.3\"->ipywidgets) (0.1.0)\n",
"Requirement already satisfied: prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from ipython>=4.0.0; python_version >= \"3.3\"->ipywidgets) (3.0.5)\n",
"Requirement already satisfied: pygments in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from ipython>=4.0.0; python_version >= \"3.3\"->ipywidgets) (2.6.1)\n",
"Requirement already satisfied: pexpect; sys_platform != \"win32\" in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from ipython>=4.0.0; python_version >= \"3.3\"->ipywidgets) (4.8.0)\n",
"Requirement already satisfied: jedi>=0.10 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from ipython>=4.0.0; python_version >= \"3.3\"->ipywidgets) (0.17.0)\n",
"Requirement already satisfied: pickleshare in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from ipython>=4.0.0; python_version >= \"3.3\"->ipywidgets) (0.7.5)\n",
"Requirement already satisfied: setuptools>=18.5 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from ipython>=4.0.0; python_version >= \"3.3\"->ipywidgets) (46.3.0.post20200513)\n",
"Requirement already satisfied: tornado>=4.2 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from ipykernel>=4.5.1->ipywidgets) (6.0.4)\n",
"Requirement already satisfied: jupyter-client in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from ipykernel>=4.5.1->ipywidgets) (6.1.3)\n",
"Requirement already satisfied: six in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from traitlets>=4.3.1->ipywidgets) (1.14.0)\n",
"Requirement already satisfied: ipython-genutils in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from traitlets>=4.3.1->ipywidgets) (0.2.0)\n",
"Requirement already satisfied: jsonschema!=2.5.0,>=2.4 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from nbformat>=4.2.0->ipywidgets) (3.2.0)\n",
"Requirement already satisfied: jupyter-core in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from nbformat>=4.2.0->ipywidgets) (4.6.3)\n",
"Requirement already satisfied: notebook>=4.4.1 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from widgetsnbextension~=3.4.0->ipywidgets) (6.0.3)\n",
"Requirement already satisfied: wcwidth in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0->ipython>=4.0.0; python_version >= \"3.3\"->ipywidgets) (0.1.9)\n",
"Requirement already satisfied: ptyprocess>=0.5 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from pexpect; sys_platform != \"win32\"->ipython>=4.0.0; python_version >= \"3.3\"->ipywidgets) (0.6.0)\n",
"Requirement already satisfied: parso>=0.7.0 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from jedi>=0.10->ipython>=4.0.0; python_version >= \"3.3\"->ipywidgets) (0.7.0)\n",
"Requirement already satisfied: pyzmq>=13 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from jupyter-client->ipykernel>=4.5.1->ipywidgets) (19.0.1)\n",
"Requirement already satisfied: python-dateutil>=2.1 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from jupyter-client->ipykernel>=4.5.1->ipywidgets) (2.8.1)\n",
"Requirement already satisfied: attrs>=17.4.0 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from jsonschema!=2.5.0,>=2.4->nbformat>=4.2.0->ipywidgets) (19.3.0)\n",
"Requirement already satisfied: importlib-metadata; python_version < \"3.8\" in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from jsonschema!=2.5.0,>=2.4->nbformat>=4.2.0->ipywidgets) (1.6.0)\n",
"Requirement already satisfied: pyrsistent>=0.14.0 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from jsonschema!=2.5.0,>=2.4->nbformat>=4.2.0->ipywidgets) (0.16.0)\n",
"Requirement already satisfied: nbconvert in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from notebook>=4.4.1->widgetsnbextension~=3.4.0->ipywidgets) (5.6.1)\n",
"Requirement already satisfied: terminado>=0.8.1 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from notebook>=4.4.1->widgetsnbextension~=3.4.0->ipywidgets) (0.8.3)\n",
"Requirement already satisfied: Send2Trash in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from notebook>=4.4.1->widgetsnbextension~=3.4.0->ipywidgets) (1.5.0)\n",
"Requirement already satisfied: jinja2 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from notebook>=4.4.1->widgetsnbextension~=3.4.0->ipywidgets) (2.11.2)\n",
"Requirement already satisfied: prometheus-client in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from notebook>=4.4.1->widgetsnbextension~=3.4.0->ipywidgets) (0.7.1)\n",
"Requirement already satisfied: zipp>=0.5 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from importlib-metadata; python_version < \"3.8\"->jsonschema!=2.5.0,>=2.4->nbformat>=4.2.0->ipywidgets) (3.1.0)\n",
"Requirement already satisfied: entrypoints>=0.2.2 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from nbconvert->notebook>=4.4.1->widgetsnbextension~=3.4.0->ipywidgets) (0.3)\n",
"Requirement already satisfied: bleach in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from nbconvert->notebook>=4.4.1->widgetsnbextension~=3.4.0->ipywidgets) (1.5.0)\n",
"Requirement already satisfied: testpath in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from nbconvert->notebook>=4.4.1->widgetsnbextension~=3.4.0->ipywidgets) (0.4.4)\n",
"Requirement already satisfied: pandocfilters>=1.4.1 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from nbconvert->notebook>=4.4.1->widgetsnbextension~=3.4.0->ipywidgets) (1.4.2)\n",
"Requirement already satisfied: mistune<2,>=0.8.1 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from nbconvert->notebook>=4.4.1->widgetsnbextension~=3.4.0->ipywidgets) (0.8.4)\n",
"Requirement already satisfied: defusedxml in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from nbconvert->notebook>=4.4.1->widgetsnbextension~=3.4.0->ipywidgets) (0.6.0)\n",
"Requirement already satisfied: MarkupSafe>=0.23 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from jinja2->notebook>=4.4.1->widgetsnbextension~=3.4.0->ipywidgets) (1.1.1)\n",
"Requirement already satisfied: html5lib!=0.9999,!=0.99999,<0.99999999,>=0.999 in /home/jupyterlab/conda/envs/python/lib/python3.6/site-packages (from bleach->nbconvert->notebook>=4.4.1->widgetsnbextension~=3.4.0->ipywidgets) (0.9999999)\n",
"Enabling notebook extension jupyter-js-widgets/extension...\n",
" - Validating: \u001b[32mOK\u001b[0m\n"
]
}
],
"source": [
"!pip install ipywidgets\n",
"!jupyter nbextension enable --py widgetsnbextension\n",
"import ipywidgets as widgets"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then we start importing the data from Toronto:"
]
},
{
"cell_type": "code",
"execution_count": 292,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Shape of Dataframe: (183, 3)\n"
]
},
{
"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>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>M2A</td>\n",
" <td>Not assigned</td>\n",
" <td>NaN</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>Regent Park / Harbourfront</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Postalcode Borough Neighborhood\n",
"0 M1A Not assigned NaN\n",
"1 M2A Not assigned NaN\n",
"2 M3A North York Parkwoods\n",
"3 M4A North York Victoria Village\n",
"4 M5A Downtown Toronto Regent Park / Harbourfront"
]
},
"execution_count": 292,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"## I've copied the table of neighborhoods from Wikipedia, and saved it to a CSV file.\n",
"## Let's put it to a Pandas dataframe:\n",
"wiki_toronto_neighborhoods_raw = pd.read_csv('Wiki_Toronto_Neighborhoods.csv')\n",
"print('Shape of Dataframe: ',wiki_toronto_neighborhoods_raw.shape)\n",
"\n",
"## Rename column so it gets exactly like instructed by Alex:\n",
"wiki_toronto_neighborhoods_raw.rename(columns={\"Postal code\": \"Postalcode\"}, inplace=True)\n",
"wiki_toronto_neighborhoods_raw.head()"
]
},
{
"cell_type": "code",
"execution_count": 293,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Shape of Dataframe after removing \"Not assigned\" Boroughs: (106, 3)\n",
"Shape of Dataframe after removing NaN values: (103, 3)\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/jupyterlab/conda/envs/python/lib/python3.6/site-packages/ipykernel_launcher.py:7: SettingWithCopyWarning: \n",
"A value is trying to be set on a copy of a slice from a DataFrame\n",
"\n",
"See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
" import sys\n"
]
},
{
"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>M3A</td>\n",
" <td>North York</td>\n",
" <td>Parkwoods</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>M4A</td>\n",
" <td>North York</td>\n",
" <td>Victoria Village</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>M5A</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Regent Park / Harbourfront</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>M6A</td>\n",
" <td>North York</td>\n",
" <td>Lawrence Manor / Lawrence Heights</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>M7A</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Queen's Park / Ontario Provincial Government</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Postalcode Borough Neighborhood\n",
"0 M3A North York Parkwoods\n",
"1 M4A North York Victoria Village\n",
"2 M5A Downtown Toronto Regent Park / Harbourfront\n",
"3 M6A North York Lawrence Manor / Lawrence Heights\n",
"4 M7A Downtown Toronto Queen's Park / Ontario Provincial Government"
]
},
"execution_count": 293,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"## Remove the 'Not assigned' Boroughs\n",
"condition = wiki_toronto_neighborhoods_raw['Borough'] != 'Not assigned'\n",
"Toronto_Neighb = wiki_toronto_neighborhoods_raw[condition]\n",
"print('Shape of Dataframe after removing \"Not assigned\" Boroughs: ',Toronto_Neighb.shape)\n",
"\n",
"## Also, remove the records with Nan in any columns, to clean the table (there were only 3)\n",
"Toronto_Neighb.dropna(how='any', inplace = True)\n",
"Toronto_Neighb.reset_index(drop=True, inplace=True)\n",
"print('Shape of Dataframe after removing NaN values: ',Toronto_Neighb.shape)\n",
"Toronto_Neighb.head()\n",
"\n",
"## There is no need to aggregate records (as asked by Alex) since the Wikipedia page is updated\n",
"## So this line keeps commentend:\n",
"## Toronto_Neighb = Toronto_Neighb.groupby(level=['Postalcode'], sort=False).agg( ','.join)"
]
},
{
"cell_type": "code",
"execution_count": 294,
"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>78</th>\n",
" <td>M1S</td>\n",
" <td>Scarborough</td>\n",
" <td>Agincourt</td>\n",
" </tr>\n",
" <tr>\n",
" <th>93</th>\n",
" <td>M8W</td>\n",
" <td>Etobicoke</td>\n",
" <td>Alderwood / Long Branch</td>\n",
" </tr>\n",
" <tr>\n",
" <th>28</th>\n",
" <td>M3H</td>\n",
" <td>North York</td>\n",
" <td>Bathurst Manor / Wilson Heights / Downsview North</td>\n",
" </tr>\n",
" <tr>\n",
" <th>39</th>\n",
" <td>M2K</td>\n",
" <td>North York</td>\n",
" <td>Bayview Village</td>\n",
" </tr>\n",
" <tr>\n",
" <th>55</th>\n",
" <td>M5M</td>\n",
" <td>North York</td>\n",
" <td>Bedford Park / Lawrence Manor East</td>\n",
" </tr>\n",
" <tr>\n",
" <th>20</th>\n",
" <td>M5E</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Berczy Park</td>\n",
" </tr>\n",
" <tr>\n",
" <th>58</th>\n",
" <td>M1N</td>\n",
" <td>Scarborough</td>\n",
" <td>Birch Cliff / Cliffside West</td>\n",
" </tr>\n",
" <tr>\n",
" <th>43</th>\n",
" <td>M6K</td>\n",
" <td>West Toronto</td>\n",
" <td>Brockton / Parkdale Village / Exhibition Place</td>\n",
" </tr>\n",
" <tr>\n",
" <th>100</th>\n",
" <td>M7Y</td>\n",
" <td>East Toronto</td>\n",
" <td>Business reply mail Processing CentrE</td>\n",
" </tr>\n",
" <tr>\n",
" <th>87</th>\n",
" <td>M5V</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>CN Tower / King and Spadina / Railway Lands / ...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>21</th>\n",
" <td>M6E</td>\n",
" <td>York</td>\n",
" <td>Caledonia-Fairbanks</td>\n",
" </tr>\n",
" <tr>\n",
" <th>76</th>\n",
" <td>M7R</td>\n",
" <td>Mississauga</td>\n",
" <td>Canada Post Gateway Processing Centre</td>\n",
" </tr>\n",
" <tr>\n",
" <th>26</th>\n",
" <td>M1H</td>\n",
" <td>Scarborough</td>\n",
" <td>Cedarbrae</td>\n",
" </tr>\n",
" <tr>\n",
" <th>24</th>\n",
" <td>M5G</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Central Bay Street</td>\n",
" </tr>\n",
" <tr>\n",
" <th>25</th>\n",
" <td>M6G</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Christie</td>\n",
" </tr>\n",
" <tr>\n",
" <th>99</th>\n",
" <td>M4Y</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Church and Wellesley</td>\n",
" </tr>\n",
" <tr>\n",
" <th>82</th>\n",
" <td>M1T</td>\n",
" <td>Scarborough</td>\n",
" <td>Clarks Corners / Tam O'Shanter / Sullivan</td>\n",
" </tr>\n",
" <tr>\n",
" <th>51</th>\n",
" <td>M1M</td>\n",
" <td>Scarborough</td>\n",
" <td>Cliffside / Cliffcrest / Scarborough Village West</td>\n",
" </tr>\n",
" <tr>\n",
" <th>48</th>\n",
" <td>M5L</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Commerce Court / Victoria Hotel</td>\n",
" </tr>\n",
" <tr>\n",
" <th>79</th>\n",
" <td>M4S</td>\n",
" <td>Central Toronto</td>\n",
" <td>Davisville</td>\n",
" </tr>\n",
" <tr>\n",
" <th>67</th>\n",
" <td>M4P</td>\n",
" <td>Central Toronto</td>\n",
" <td>Davisville North</td>\n",
" </tr>\n",
" <tr>\n",
" <th>56</th>\n",
" <td>M6M</td>\n",
" <td>York</td>\n",
" <td>Del Ray / Mount Dennis / Keelsdale and Silvert...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>M3B</td>\n",
" <td>North York</td>\n",
" <td>Don Mills</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13</th>\n",
" <td>M3C</td>\n",
" <td>North York</td>\n",
" <td>Don Mills</td>\n",
" </tr>\n",
" <tr>\n",
" <th>65</th>\n",
" <td>M1P</td>\n",
" <td>Scarborough</td>\n",
" <td>Dorset Park / Wexford Heights / Scarborough To...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>40</th>\n",
" <td>M3K</td>\n",
" <td>North York</td>\n",
" <td>Downsview</td>\n",
" </tr>\n",
" <tr>\n",
" <th>46</th>\n",
" <td>M3L</td>\n",
" <td>North York</td>\n",
" <td>Downsview</td>\n",
" </tr>\n",
" <tr>\n",
" <th>60</th>\n",
" <td>M3N</td>\n",
" <td>North York</td>\n",
" <td>Downsview</td>\n",
" </tr>\n",
" <tr>\n",
" <th>53</th>\n",
" <td>M3M</td>\n",
" <td>North York</td>\n",
" <td>Downsview</td>\n",
" </tr>\n",
" <tr>\n",
" <th>31</th>\n",
" <td>M6H</td>\n",
" <td>West Toronto</td>\n",
" <td>Dufferin / Dovercourt Village</td>\n",
" </tr>\n",
" <tr>\n",
" <th>35</th>\n",
" <td>M4J</td>\n",
" <td>East York</td>\n",
" <td>East Toronto</td>\n",
" </tr>\n",
" <tr>\n",
" <th>17</th>\n",
" <td>M9C</td>\n",
" <td>Etobicoke</td>\n",
" <td>Eringate / Bloordale Gardens / Old Burnhamthor...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>33</th>\n",
" <td>M2J</td>\n",
" <td>North York</td>\n",
" <td>Fairview / Henry Farm / Oriole</td>\n",
" </tr>\n",
" <tr>\n",
" <th>97</th>\n",
" <td>M5X</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>First Canadian Place / Underground city</td>\n",
" </tr>\n",
" <tr>\n",
" <th>68</th>\n",
" <td>M5P</td>\n",
" <td>Central Toronto</td>\n",
" <td>Forest Hill North &amp; West</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>M5B</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Garden District-Ryerson</td>\n",
" </tr>\n",
" <tr>\n",
" <th>10</th>\n",
" <td>M6B</td>\n",
" <td>North York</td>\n",
" <td>Glencairn</td>\n",
" </tr>\n",
" <tr>\n",
" <th>44</th>\n",
" <td>M1L</td>\n",
" <td>Scarborough</td>\n",
" <td>Golden Mile / Clairlea / Oakridge</td>\n",
" </tr>\n",
" <tr>\n",
" <th>18</th>\n",
" <td>M1E</td>\n",
" <td>Scarborough</td>\n",
" <td>Guildwood / Morningside / West Hill</td>\n",
" </tr>\n",
" <tr>\n",
" <th>36</th>\n",
" <td>M5J</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Harbourfront East / Union Station / Toronto Is...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>69</th>\n",
" <td>M6P</td>\n",
" <td>West Toronto</td>\n",
" <td>High Park / The Junction South</td>\n",
" </tr>\n",
" <tr>\n",
" <th>27</th>\n",
" <td>M2H</td>\n",
" <td>North York</td>\n",
" <td>Hillcrest Village</td>\n",
" </tr>\n",
" <tr>\n",
" <th>50</th>\n",
" <td>M9L</td>\n",
" <td>North York</td>\n",
" <td>Humber Summit</td>\n",
" </tr>\n",
" <tr>\n",
" <th>57</th>\n",
" <td>M9M</td>\n",
" <td>North York</td>\n",
" <td>Humberlea / Emery</td>\n",
" </tr>\n",
" <tr>\n",
" <th>16</th>\n",
" <td>M6C</td>\n",
" <td>York</td>\n",
" <td>Humewood-Cedarvale</td>\n",
" </tr>\n",
" <tr>\n",
" <th>47</th>\n",
" <td>M4L</td>\n",
" <td>East Toronto</td>\n",
" <td>India Bazaar / The Beaches West</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>M9A</td>\n",
" <td>Etobicoke</td>\n",
" <td>Islington Avenue</td>\n",
" </tr>\n",
" <tr>\n",
" <th>38</th>\n",
" <td>M1K</td>\n",
" <td>Scarborough</td>\n",
" <td>Kennedy Park / Ionview / East Birchmount Park</td>\n",
" </tr>\n",
" <tr>\n",
" <th>84</th>\n",
" <td>M5T</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Kensington Market / Chinatown / Grange Park</td>\n",
" </tr>\n",
" <tr>\n",
" <th>77</th>\n",
" <td>M9R</td>\n",
" <td>Etobicoke</td>\n",
" <td>Kingsview Village / St. Phillips / Martin Grov...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>M6A</td>\n",
" <td>North York</td>\n",
" <td>Lawrence Manor / Lawrence Heights</td>\n",
" </tr>\n",
" <tr>\n",
" <th>61</th>\n",
" <td>M4N</td>\n",
" <td>Central Toronto</td>\n",
" <td>Lawrence Park</td>\n",
" </tr>\n",
" <tr>\n",
" <th>23</th>\n",
" <td>M4G</td>\n",
" <td>East York</td>\n",
" <td>Leaside</td>\n",
" </tr>\n",
" <tr>\n",
" <th>37</th>\n",
" <td>M6J</td>\n",
" <td>West Toronto</td>\n",
" <td>Little Portugal / Trinity</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>M1B</td>\n",
" <td>Scarborough</td>\n",
" <td>Malvern / Rouge</td>\n",
" </tr>\n",
" <tr>\n",
" <th>85</th>\n",
" <td>M1V</td>\n",
" <td>Scarborough</td>\n",
" <td>Milliken / Agincourt North / Steeles East / L'...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>102</th>\n",
" <td>M8Z</td>\n",
" <td>Etobicoke</td>\n",
" <td>Mimico NW / The Queensway West / South of Bloo...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>83</th>\n",
" <td>M4T</td>\n",
" <td>Central Toronto</td>\n",
" <td>Moore Park / Summerhill East</td>\n",
" </tr>\n",
" <tr>\n",
" <th>88</th>\n",
" <td>M8V</td>\n",
" <td>Etobicoke</td>\n",
" <td>New Toronto / Mimico South / Humber Bay Shores</td>\n",
" </tr>\n",
" <tr>\n",
" <th>49</th>\n",
" <td>M6L</td>\n",
" <td>North York</td>\n",
" <td>North Park / Maple Leaf Park / Upwood Park</td>\n",
" </tr>\n",
" <tr>\n",
" <th>73</th>\n",
" <td>M4R</td>\n",
" <td>Central Toronto</td>\n",
" <td>North Toronto West</td>\n",
" </tr>\n",
" <tr>\n",
" <th>94</th>\n",
" <td>M9W</td>\n",
" <td>Etobicoke</td>\n",
" <td>Northwest</td>\n",
" </tr>\n",
" <tr>\n",
" <th>34</th>\n",
" <td>M3J</td>\n",
" <td>North York</td>\n",
" <td>Northwood Park / York University</td>\n",
" </tr>\n",
" <tr>\n",
" <th>101</th>\n",
" <td>M8Y</td>\n",
" <td>Etobicoke</td>\n",
" <td>Old Mill South / King's Mill Park / Sunnylea /...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>75</th>\n",
" <td>M6R</td>\n",
" <td>West Toronto</td>\n",
" <td>Parkdale / Roncesvalles</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>M4B</td>\n",
" <td>East York</td>\n",
" <td>Parkview Hill / Woodbine Gardens</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>M3A</td>\n",
" <td>North York</td>\n",
" <td>Parkwoods</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>M7A</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Queen's Park / Ontario Provincial Government</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>M5A</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Regent Park / Harbourfront</td>\n",
" </tr>\n",
" <tr>\n",
" <th>30</th>\n",
" <td>M5H</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Richmond / Adelaide / King</td>\n",
" </tr>\n",
" <tr>\n",
" <th>91</th>\n",
" <td>M4W</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Rosedale</td>\n",
" </tr>\n",
" <tr>\n",
" <th>62</th>\n",
" <td>M5N</td>\n",
" <td>Central Toronto</td>\n",
" <td>Roselawn</td>\n",
" </tr>\n",
" <tr>\n",
" <th>12</th>\n",
" <td>M1C</td>\n",
" <td>Scarborough</td>\n",
" <td>Rouge Hill / Port Union / Highland Creek</td>\n",
" </tr>\n",
" <tr>\n",
" <th>81</th>\n",
" <td>M6S</td>\n",
" <td>West Toronto</td>\n",
" <td>Runnymede / Swansea</td>\n",
" </tr>\n",
" <tr>\n",
" <th>63</th>\n",
" <td>M6N</td>\n",
" <td>York</td>\n",
" <td>Runnymede / The Junction North</td>\n",
" </tr>\n",
" <tr>\n",
" <th>32</th>\n",
" <td>M1J</td>\n",
" <td>Scarborough</td>\n",
" <td>Scarborough Village</td>\n",
" </tr>\n",
" <tr>\n",
" <th>89</th>\n",
" <td>M9V</td>\n",
" <td>Etobicoke</td>\n",
" <td>South Steeles / Silverstone / Humbergate / Jam...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>15</th>\n",
" <td>M5C</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>St. James Town</td>\n",
" </tr>\n",
" <tr>\n",
" <th>96</th>\n",
" <td>M4X</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>St. James Town / Cabbagetown</td>\n",
" </tr>\n",
" <tr>\n",
" <th>90</th>\n",
" <td>M1W</td>\n",
" <td>Scarborough</td>\n",
" <td>Steeles West / L'Amoreaux West</td>\n",
" </tr>\n",
" <tr>\n",
" <th>92</th>\n",
" <td>M5W</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Stn A PO Boxes</td>\n",
" </tr>\n",
" <tr>\n",
" <th>54</th>\n",
" <td>M4M</td>\n",
" <td>East Toronto</td>\n",
" <td>Studio District</td>\n",
" </tr>\n",
" <tr>\n",
" <th>86</th>\n",
" <td>M4V</td>\n",
" <td>Central Toronto</td>\n",
" <td>Summerhill West / Rathnelly / South Hill / For...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>74</th>\n",
" <td>M5R</td>\n",
" <td>Central Toronto</td>\n",
" <td>The Annex / North Midtown / Yorkville</td>\n",
" </tr>\n",
" <tr>\n",
" <th>19</th>\n",
" <td>M4E</td>\n",
" <td>East Toronto</td>\n",
" <td>The Beaches</td>\n",
" </tr>\n",
" <tr>\n",
" <th>41</th>\n",
" <td>M4K</td>\n",
" <td>East Toronto</td>\n",
" <td>The Danforth West / Riverdale</td>\n",
" </tr>\n",
" <tr>\n",
" <th>98</th>\n",
" <td>M8X</td>\n",
" <td>Etobicoke</td>\n",
" <td>The Kingsway / Montgomery Road / Old Mill North</td>\n",
" </tr>\n",
" <tr>\n",
" <th>29</th>\n",
" <td>M4H</td>\n",
" <td>East York</td>\n",
" <td>Thorncliffe Park</td>\n",
" </tr>\n",
" <tr>\n",
" <th>42</th>\n",
" <td>M5K</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Toronto Dominion Centre / Design Exchange</td>\n",
" </tr>\n",
" <tr>\n",
" <th>80</th>\n",
" <td>M5S</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>University of Toronto / Harbord</td>\n",
" </tr>\n",
" <tr>\n",
" <th>95</th>\n",
" <td>M1X</td>\n",
" <td>Scarborough</td>\n",
" <td>Upper Rouge</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>M4A</td>\n",
" <td>North York</td>\n",
" <td>Victoria Village</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11</th>\n",
" <td>M9B</td>\n",
" <td>Etobicoke</td>\n",
" <td>West Deane Park / Princess Gardens / Martin Gr...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>70</th>\n",
" <td>M9P</td>\n",
" <td>Etobicoke</td>\n",
" <td>Westmount</td>\n",
" </tr>\n",
" <tr>\n",
" <th>64</th>\n",
" <td>M9N</td>\n",
" <td>York</td>\n",
" <td>Weston</td>\n",
" </tr>\n",
" <tr>\n",
" <th>71</th>\n",
" <td>M1R</td>\n",
" <td>Scarborough</td>\n",
" <td>Wexford / Maryvale</td>\n",
" </tr>\n",
" <tr>\n",
" <th>72</th>\n",
" <td>M2R</td>\n",
" <td>North York</td>\n",
" <td>Willowdale</td>\n",
" </tr>\n",
" <tr>\n",
" <th>59</th>\n",
" <td>M2N</td>\n",
" <td>North York</td>\n",
" <td>Willowdale</td>\n",
" </tr>\n",
" <tr>\n",
" <th>52</th>\n",
" <td>M2M</td>\n",
" <td>North York</td>\n",
" <td>Willowdale / Newtonbrook</td>\n",
" </tr>\n",
" <tr>\n",
" <th>22</th>\n",
" <td>M1G</td>\n",
" <td>Scarborough</td>\n",
" <td>Woburn</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14</th>\n",
" <td>M4C</td>\n",
" <td>East York</td>\n",
" <td>Woodbine Heights</td>\n",
" </tr>\n",
" <tr>\n",
" <th>45</th>\n",
" <td>M2L</td>\n",
" <td>North York</td>\n",
" <td>York Mills / Silver Hills</td>\n",
" </tr>\n",
" <tr>\n",
" <th>66</th>\n",
" <td>M2P</td>\n",
" <td>North York</td>\n",
" <td>York Mills West</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Postalcode Borough \\\n",
"78 M1S Scarborough \n",
"93 M8W Etobicoke \n",
"28 M3H North York \n",
"39 M2K North York \n",
"55 M5M North York \n",
"20 M5E Downtown Toronto \n",
"58 M1N Scarborough \n",
"43 M6K West Toronto \n",
"100 M7Y East Toronto \n",
"87 M5V Downtown Toronto \n",
"21 M6E York \n",
"76 M7R Mississauga \n",
"26 M1H Scarborough \n",
"24 M5G Downtown Toronto \n",
"25 M6G Downtown Toronto \n",
"99 M4Y Downtown Toronto \n",
"82 M1T Scarborough \n",
"51 M1M Scarborough \n",
"48 M5L Downtown Toronto \n",
"79 M4S Central Toronto \n",
"67 M4P Central Toronto \n",
"56 M6M York \n",
"7 M3B North York \n",
"13 M3C North York \n",
"65 M1P Scarborough \n",
"40 M3K North York \n",
"46 M3L North York \n",
"60 M3N North York \n",
"53 M3M North York \n",
"31 M6H West Toronto \n",
"35 M4J East York \n",
"17 M9C Etobicoke \n",
"33 M2J North York \n",
"97 M5X Downtown Toronto \n",
"68 M5P Central Toronto \n",
"9 M5B Downtown Toronto \n",
"10 M6B North York \n",
"44 M1L Scarborough \n",
"18 M1E Scarborough \n",
"36 M5J Downtown Toronto \n",
"69 M6P West Toronto \n",
"27 M2H North York \n",
"50 M9L North York \n",
"57 M9M North York \n",
"16 M6C York \n",
"47 M4L East Toronto \n",
"5 M9A Etobicoke \n",
"38 M1K Scarborough \n",
"84 M5T Downtown Toronto \n",
"77 M9R Etobicoke \n",
"3 M6A North York \n",
"61 M4N Central Toronto \n",
"23 M4G East York \n",
"37 M6J West Toronto \n",
"6 M1B Scarborough \n",
"85 M1V Scarborough \n",
"102 M8Z Etobicoke \n",
"83 M4T Central Toronto \n",
"88 M8V Etobicoke \n",
"49 M6L North York \n",
"73 M4R Central Toronto \n",
"94 M9W Etobicoke \n",
"34 M3J North York \n",
"101 M8Y Etobicoke \n",
"75 M6R West Toronto \n",
"8 M4B East York \n",
"0 M3A North York \n",
"4 M7A Downtown Toronto \n",
"2 M5A Downtown Toronto \n",
"30 M5H Downtown Toronto \n",
"91 M4W Downtown Toronto \n",
"62 M5N Central Toronto \n",
"12 M1C Scarborough \n",
"81 M6S West Toronto \n",
"63 M6N York \n",
"32 M1J Scarborough \n",
"89 M9V Etobicoke \n",
"15 M5C Downtown Toronto \n",
"96 M4X Downtown Toronto \n",
"90 M1W Scarborough \n",
"92 M5W Downtown Toronto \n",
"54 M4M East Toronto \n",
"86 M4V Central Toronto \n",
"74 M5R Central Toronto \n",
"19 M4E East Toronto \n",
"41 M4K East Toronto \n",
"98 M8X Etobicoke \n",
"29 M4H East York \n",
"42 M5K Downtown Toronto \n",
"80 M5S Downtown Toronto \n",
"95 M1X Scarborough \n",
"1 M4A North York \n",
"11 M9B Etobicoke \n",
"70 M9P Etobicoke \n",
"64 M9N York \n",
"71 M1R Scarborough \n",
"72 M2R North York \n",
"59 M2N North York \n",
"52 M2M North York \n",
"22 M1G Scarborough \n",
"14 M4C East York \n",
"45 M2L North York \n",
"66 M2P North York \n",
"\n",
" Neighborhood \n",
"78 Agincourt \n",
"93 Alderwood / Long Branch \n",
"28 Bathurst Manor / Wilson Heights / Downsview North \n",
"39 Bayview Village \n",
"55 Bedford Park / Lawrence Manor East \n",
"20 Berczy Park \n",
"58 Birch Cliff / Cliffside West \n",
"43 Brockton / Parkdale Village / Exhibition Place \n",
"100 Business reply mail Processing CentrE \n",
"87 CN Tower / King and Spadina / Railway Lands / ... \n",
"21 Caledonia-Fairbanks \n",
"76 Canada Post Gateway Processing Centre \n",
"26 Cedarbrae \n",
"24 Central Bay Street \n",
"25 Christie \n",
"99 Church and Wellesley \n",
"82 Clarks Corners / Tam O'Shanter / Sullivan \n",
"51 Cliffside / Cliffcrest / Scarborough Village West \n",
"48 Commerce Court / Victoria Hotel \n",
"79 Davisville \n",
"67 Davisville North \n",
"56 Del Ray / Mount Dennis / Keelsdale and Silvert... \n",
"7 Don Mills \n",
"13 Don Mills \n",
"65 Dorset Park / Wexford Heights / Scarborough To... \n",
"40 Downsview \n",
"46 Downsview \n",
"60 Downsview \n",
"53 Downsview \n",
"31 Dufferin / Dovercourt Village \n",
"35 East Toronto \n",
"17 Eringate / Bloordale Gardens / Old Burnhamthor... \n",
"33 Fairview / Henry Farm / Oriole \n",
"97 First Canadian Place / Underground city \n",
"68 Forest Hill North & West \n",
"9 Garden District-Ryerson \n",
"10 Glencairn \n",
"44 Golden Mile / Clairlea / Oakridge \n",
"18 Guildwood / Morningside / West Hill \n",
"36 Harbourfront East / Union Station / Toronto Is... \n",
"69 High Park / The Junction South \n",
"27 Hillcrest Village \n",
"50 Humber Summit \n",
"57 Humberlea / Emery \n",
"16 Humewood-Cedarvale \n",
"47 India Bazaar / The Beaches West \n",
"5 Islington Avenue \n",
"38 Kennedy Park / Ionview / East Birchmount Park \n",
"84 Kensington Market / Chinatown / Grange Park \n",
"77 Kingsview Village / St. Phillips / Martin Grov... \n",
"3 Lawrence Manor / Lawrence Heights \n",
"61 Lawrence Park \n",
"23 Leaside \n",
"37 Little Portugal / Trinity \n",
"6 Malvern / Rouge \n",
"85 Milliken / Agincourt North / Steeles East / L'... \n",
"102 Mimico NW / The Queensway West / South of Bloo... \n",
"83 Moore Park / Summerhill East \n",
"88 New Toronto / Mimico South / Humber Bay Shores \n",
"49 North Park / Maple Leaf Park / Upwood Park \n",
"73 North Toronto West \n",
"94 Northwest \n",
"34 Northwood Park / York University \n",
"101 Old Mill South / King's Mill Park / Sunnylea /... \n",
"75 Parkdale / Roncesvalles \n",
"8 Parkview Hill / Woodbine Gardens \n",
"0 Parkwoods \n",
"4 Queen's Park / Ontario Provincial Government \n",
"2 Regent Park / Harbourfront \n",
"30 Richmond / Adelaide / King \n",
"91 Rosedale \n",
"62 Roselawn \n",
"12 Rouge Hill / Port Union / Highland Creek \n",
"81 Runnymede / Swansea \n",
"63 Runnymede / The Junction North \n",
"32 Scarborough Village \n",
"89 South Steeles / Silverstone / Humbergate / Jam... \n",
"15 St. James Town \n",
"96 St. James Town / Cabbagetown \n",
"90 Steeles West / L'Amoreaux West \n",
"92 Stn A PO Boxes \n",
"54 Studio District \n",
"86 Summerhill West / Rathnelly / South Hill / For... \n",
"74 The Annex / North Midtown / Yorkville \n",
"19 The Beaches \n",
"41 The Danforth West / Riverdale \n",
"98 The Kingsway / Montgomery Road / Old Mill North \n",
"29 Thorncliffe Park \n",
"42 Toronto Dominion Centre / Design Exchange \n",
"80 University of Toronto / Harbord \n",
"95 Upper Rouge \n",
"1 Victoria Village \n",
"11 West Deane Park / Princess Gardens / Martin Gr... \n",
"70 Westmount \n",
"64 Weston \n",
"71 Wexford / Maryvale \n",
"72 Willowdale \n",
"59 Willowdale \n",
"52 Willowdale / Newtonbrook \n",
"22 Woburn \n",
"14 Woodbine Heights \n",
"45 York Mills / Silver Hills \n",
"66 York Mills West "
]
},
"execution_count": 294,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Toronto_Neighb.sort_values('Neighborhood')"
]
},
{
"cell_type": "code",
"execution_count": 295,
"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>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": [
" Postalcode 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": 295,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"## Now let's get the coordinates from other table. I've decided to get directly from the CSV file\n",
"## So let's put it in this dataframe:\n",
"\n",
"coord = pd.read_csv('Geospatial_Coordinates.csv')\n",
"coord.rename(columns={\"Postal Code\": \"Postalcode\"}, inplace=True)\n",
"coord.head()"
]
},
{
"cell_type": "code",
"execution_count": 296,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/jupyterlab/conda/envs/python/lib/python3.6/site-packages/ipykernel_launcher.py:2: SettingWithCopyWarning: \n",
"A value is trying to be set on a copy of a slice from a DataFrame.\n",
"Try using .loc[row_indexer,col_indexer] = value instead\n",
"\n",
"See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
" \n",
"/home/jupyterlab/conda/envs/python/lib/python3.6/site-packages/ipykernel_launcher.py:3: SettingWithCopyWarning: \n",
"A value is trying to be set on a copy of a slice from a DataFrame.\n",
"Try using .loc[row_indexer,col_indexer] = value instead\n",
"\n",
"See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
" This is separate from the ipykernel package so we can avoid doing imports until\n"
]
},
{
"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>M3A</td>\n",
" <td>North York</td>\n",
" <td>Parkwoods</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>M4A</td>\n",
" <td>North York</td>\n",
" <td>Victoria Village</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>M5A</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Regent Park / Harbourfront</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>M6A</td>\n",
" <td>North York</td>\n",
" <td>Lawrence Manor / Lawrence Heights</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>M7A</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Queen's Park / Ontario Provincial Government</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Postalcode Borough Neighborhood \\\n",
"0 M3A North York Parkwoods \n",
"1 M4A North York Victoria Village \n",
"2 M5A Downtown Toronto Regent Park / Harbourfront \n",
"3 M6A North York Lawrence Manor / Lawrence Heights \n",
"4 M7A Downtown Toronto Queen's Park / Ontario Provincial Government \n",
"\n",
" Latitude Longitude \n",
"0 NaN NaN \n",
"1 NaN NaN \n",
"2 NaN NaN \n",
"3 NaN NaN \n",
"4 NaN NaN "
]
},
"execution_count": 296,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"## Now let's create two new columns to accomodate the geolocation data:\n",
"Toronto_Neighb['Latitude'] = np.nan\n",
"Toronto_Neighb['Longitude'] = np.nan\n",
"Toronto_Neighb.head()"
]
},
{
"cell_type": "code",
"execution_count": 297,
"metadata": {},
"outputs": [],
"source": [
"## We want to update the values of \"coord\" into \"Toronto_Neighb\"\n",
"## I will use the update method, so first I need to equalize the indexes of both dataframes\n",
"Toronto_Neighb.set_index('Postalcode', inplace=True)\n",
"coord.set_index('Postalcode', inplace=True)"
]
},
{
"cell_type": "code",
"execution_count": 298,
"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>Borough</th>\n",
" <th>Neighborhood</th>\n",
" <th>Latitude</th>\n",
" <th>Longitude</th>\n",
" </tr>\n",
" <tr>\n",
" <th>Postalcode</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>M3A</th>\n",
" <td>North York</td>\n",
" <td>Parkwoods</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>M4A</th>\n",
" <td>North York</td>\n",
" <td>Victoria Village</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>M5A</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Regent Park / Harbourfront</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>M6A</th>\n",
" <td>North York</td>\n",
" <td>Lawrence Manor / Lawrence Heights</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>M7A</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Queen's Park / Ontario Provincial Government</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Borough Neighborhood \\\n",
"Postalcode \n",
"M3A North York Parkwoods \n",
"M4A North York Victoria Village \n",
"M5A Downtown Toronto Regent Park / Harbourfront \n",
"M6A North York Lawrence Manor / Lawrence Heights \n",
"M7A Downtown Toronto Queen's Park / Ontario Provincial Government \n",
"\n",
" Latitude Longitude \n",
"Postalcode \n",
"M3A NaN NaN \n",
"M4A NaN NaN \n",
"M5A NaN NaN \n",
"M6A NaN NaN \n",
"M7A NaN NaN "
]
},
"execution_count": 298,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"## As you can see, now the Postalcode is the index:\n",
"Toronto_Neighb.head()"
]
},
{
"cell_type": "code",
"execution_count": 299,
"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>Latitude</th>\n",
" <th>Longitude</th>\n",
" </tr>\n",
" <tr>\n",
" <th>Postalcode</th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>M1B</th>\n",
" <td>43.806686</td>\n",
" <td>-79.194353</td>\n",
" </tr>\n",
" <tr>\n",
" <th>M1C</th>\n",
" <td>43.784535</td>\n",
" <td>-79.160497</td>\n",
" </tr>\n",
" <tr>\n",
" <th>M1E</th>\n",
" <td>43.763573</td>\n",
" <td>-79.188711</td>\n",
" </tr>\n",
" <tr>\n",
" <th>M1G</th>\n",
" <td>43.770992</td>\n",
" <td>-79.216917</td>\n",
" </tr>\n",
" <tr>\n",
" <th>M1H</th>\n",
" <td>43.773136</td>\n",
" <td>-79.239476</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Latitude Longitude\n",
"Postalcode \n",
"M1B 43.806686 -79.194353\n",
"M1C 43.784535 -79.160497\n",
"M1E 43.763573 -79.188711\n",
"M1G 43.770992 -79.216917\n",
"M1H 43.773136 -79.239476"
]
},
"execution_count": 299,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"## ...as well as in the coord dataframe:\n",
"coord.head()"
]
},
{
"cell_type": "code",
"execution_count": 300,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/jupyterlab/conda/envs/python/lib/python3.6/site-packages/pandas/core/frame.py:5732: SettingWithCopyWarning: \n",
"A value is trying to be set on a copy of a slice from a DataFrame.\n",
"Try using .loc[row_indexer,col_indexer] = value instead\n",
"\n",
"See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
" self[col] = expressions.where(mask, this, that)\n"
]
}
],
"source": [
"## Now we can use the update method, which update the columns of same name, based on the index:\n",
"Toronto_Neighb.update(coord)"
]
},
{
"cell_type": "code",
"execution_count": 301,
"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>Borough</th>\n",
" <th>Neighborhood</th>\n",
" <th>Latitude</th>\n",
" <th>Longitude</th>\n",
" </tr>\n",
" <tr>\n",
" <th>Postalcode</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>M3A</th>\n",
" <td>North York</td>\n",
" <td>Parkwoods</td>\n",
" <td>43.753259</td>\n",
" <td>-79.329656</td>\n",
" </tr>\n",
" <tr>\n",
" <th>M4A</th>\n",
" <td>North York</td>\n",
" <td>Victoria Village</td>\n",
" <td>43.725882</td>\n",
" <td>-79.315572</td>\n",
" </tr>\n",
" <tr>\n",
" <th>M5A</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Regent Park / Harbourfront</td>\n",
" <td>43.654260</td>\n",
" <td>-79.360636</td>\n",
" </tr>\n",
" <tr>\n",
" <th>M6A</th>\n",
" <td>North York</td>\n",
" <td>Lawrence Manor / Lawrence Heights</td>\n",
" <td>43.718518</td>\n",
" <td>-79.464763</td>\n",
" </tr>\n",
" <tr>\n",
" <th>M7A</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Queen's Park / Ontario Provincial Government</td>\n",
" <td>43.662301</td>\n",
" <td>-79.389494</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Borough Neighborhood \\\n",
"Postalcode \n",
"M3A North York Parkwoods \n",
"M4A North York Victoria Village \n",
"M5A Downtown Toronto Regent Park / Harbourfront \n",
"M6A North York Lawrence Manor / Lawrence Heights \n",
"M7A Downtown Toronto Queen's Park / Ontario Provincial Government \n",
"\n",
" Latitude Longitude \n",
"Postalcode \n",
"M3A 43.753259 -79.329656 \n",
"M4A 43.725882 -79.315572 \n",
"M5A 43.654260 -79.360636 \n",
"M6A 43.718518 -79.464763 \n",
"M7A 43.662301 -79.389494 "
]
},
"execution_count": 301,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"## Now let's check if Latitude and Longitude are completed:\n",
"Toronto_Neighb.head()"
]
},
{
"cell_type": "code",
"execution_count": 302,
"metadata": {},
"outputs": [],
"source": [
"## Let's reset the index so our main dataframe gets back to what it was:\n",
"Toronto_Neighb.reset_index(inplace=True)"
]
},
{
"cell_type": "code",
"execution_count": 303,
"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>M3A</td>\n",
" <td>North York</td>\n",
" <td>Parkwoods</td>\n",
" <td>43.753259</td>\n",
" <td>-79.329656</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>M4A</td>\n",
" <td>North York</td>\n",
" <td>Victoria Village</td>\n",
" <td>43.725882</td>\n",
" <td>-79.315572</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>M5A</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Regent Park / Harbourfront</td>\n",
" <td>43.654260</td>\n",
" <td>-79.360636</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>M6A</td>\n",
" <td>North York</td>\n",
" <td>Lawrence Manor / Lawrence Heights</td>\n",
" <td>43.718518</td>\n",
" <td>-79.464763</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>M7A</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Queen's Park / Ontario Provincial Government</td>\n",
" <td>43.662301</td>\n",
" <td>-79.389494</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Postalcode Borough Neighborhood \\\n",
"0 M3A North York Parkwoods \n",
"1 M4A North York Victoria Village \n",
"2 M5A Downtown Toronto Regent Park / Harbourfront \n",
"3 M6A North York Lawrence Manor / Lawrence Heights \n",
"4 M7A Downtown Toronto Queen's Park / Ontario Provincial Government \n",
"\n",
" Latitude Longitude \n",
"0 43.753259 -79.329656 \n",
"1 43.725882 -79.315572 \n",
"2 43.654260 -79.360636 \n",
"3 43.718518 -79.464763 \n",
"4 43.662301 -79.389494 "
]
},
"execution_count": 303,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Toronto_Neighb.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"All set for Toronto! Now let's work on NY data."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Neighborhood has a total of 5 boroughs and 306 neighborhoods. In order to segement the neighborhoods and explore them, we will essentially need a dataset that contains the 5 boroughs and the neighborhoods that exist in each borough as well as the the latitude and logitude coordinates of each neighborhood. \n",
"\n",
"Luckily, this dataset exists for free on the web. Feel free to try to find this dataset on your own, but here is the link to the dataset: https://geo.nyu.edu/catalog/nyu_2451_34572"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For your convenience, I downloaded the files and placed it on the server, so you can simply run a `wget` command and access the data. So let's go ahead and do that."
]
},
{
"cell_type": "code",
"execution_count": 304,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
},
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Data downloaded!\n"
]
}
],
"source": [
"!wget -q -O 'newyork_data.json' https://cocl.us/new_york_dataset\n",
"print('Data downloaded!')"
]
},
{
"cell_type": "code",
"execution_count": 305,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"#Next, let's load the data.\n",
"with open('newyork_data.json') as json_data:\n",
" newyork_data = json.load(json_data)"
]
},
{
"cell_type": "code",
"execution_count": 306,
"metadata": {},
"outputs": [],
"source": [
"#Notice how all the relevant data is in the *features* key,\n",
"#which is basically a list of the neighborhoods.\n",
"#So, let's define a new variable that includes this data.\n",
"neighborhoods_data = newyork_data['features']"
]
},
{
"cell_type": "code",
"execution_count": 307,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"data": {
"text/plain": [
"{'type': 'Feature',\n",
" 'id': 'nyu_2451_34572.1',\n",
" 'geometry': {'type': 'Point',\n",
" 'coordinates': [-73.84720052054902, 40.89470517661]},\n",
" 'geometry_name': 'geom',\n",
" 'properties': {'name': 'Wakefield',\n",
" 'stacked': 1,\n",
" 'annoline1': 'Wakefield',\n",
" 'annoline2': None,\n",
" 'annoline3': None,\n",
" 'annoangle': 0.0,\n",
" 'borough': 'Bronx',\n",
" 'bbox': [-73.84720052054902,\n",
" 40.89470517661,\n",
" -73.84720052054902,\n",
" 40.89470517661]}}"
]
},
"execution_count": 307,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#Let's take a look at the first item in this list.\n",
"neighborhoods_data[0]"
]
},
{
"cell_type": "code",
"execution_count": 308,
"metadata": {},
"outputs": [],
"source": [
"# The next task is essentially transforming this data of nested\n",
"# Python dictionaries into a *pandas* dataframe.\n",
"# So let's start by creating an empty dataframe."
]
},
{
"cell_type": "code",
"execution_count": 309,
"metadata": {},
"outputs": [],
"source": [
"# define the dataframe columns\n",
"column_names = ['Borough', 'Neighborhood', 'Latitude', 'Longitude'] \n",
"\n",
"# instantiate the dataframe\n",
"neighborhoods_NY = pd.DataFrame(columns=column_names)"
]
},
{
"cell_type": "code",
"execution_count": 311,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Borough</th>\n",
" <th>Neighborhood</th>\n",
" <th>Latitude</th>\n",
" <th>Longitude</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
"Empty DataFrame\n",
"Columns: [Borough, Neighborhood, Latitude, Longitude]\n",
"Index: []"
]
},
"execution_count": 311,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#Take a look at the empty dataframe to confirm that the columns are as intended.\n",
"neighborhoods_NY"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then let's loop through the data and fill the dataframe one row at a time."
]
},
{
"cell_type": "code",
"execution_count": 312,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"for data in neighborhoods_data:\n",
" borough = neighborhood_name = data['properties']['borough'] \n",
" neighborhood_name = data['properties']['name']\n",
" \n",
" neighborhood_latlon = data['geometry']['coordinates']\n",
" neighborhood_lat = neighborhood_latlon[1]\n",
" neighborhood_lon = neighborhood_latlon[0]\n",
" \n",
" neighborhoods_NY = neighborhoods_NY.append({'Borough': borough,\n",
" 'Neighborhood': neighborhood_name,\n",
" 'Latitude': neighborhood_lat,\n",
" 'Longitude': neighborhood_lon}, ignore_index=True)"
]
},
{
"cell_type": "code",
"execution_count": 314,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
},
"scrolled": true
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>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>Bronx</td>\n",
" <td>Wakefield</td>\n",
" <td>40.894705</td>\n",
" <td>-73.847201</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Bronx</td>\n",
" <td>Co-op City</td>\n",
" <td>40.874294</td>\n",
" <td>-73.829939</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Bronx</td>\n",
" <td>Eastchester</td>\n",
" <td>40.887556</td>\n",
" <td>-73.827806</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Bronx</td>\n",
" <td>Fieldston</td>\n",
" <td>40.895437</td>\n",
" <td>-73.905643</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Bronx</td>\n",
" <td>Riverdale</td>\n",
" <td>40.890834</td>\n",
" <td>-73.912585</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Borough Neighborhood Latitude Longitude\n",
"0 Bronx Wakefield 40.894705 -73.847201\n",
"1 Bronx Co-op City 40.874294 -73.829939\n",
"2 Bronx Eastchester 40.887556 -73.827806\n",
"3 Bronx Fieldston 40.895437 -73.905643\n",
"4 Bronx Riverdale 40.890834 -73.912585"
]
},
"execution_count": 314,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#Quickly examine the resulting dataframe.\n",
"neighborhoods_NY.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And make sure that the dataset has all 5 boroughs and 306 neighborhoods."
]
},
{
"cell_type": "code",
"execution_count": 315,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The dataframe has 5 boroughs and 306 neighborhoods.\n"
]
}
],
"source": [
"print('The dataframe has {} boroughs and {} neighborhoods.'.format(\n",
" len(neighborhoods_NY['Borough'].unique()),\n",
" neighborhoods_NY.shape[0]\n",
" )\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Use geopy library to get the latitude and longitude values of New York City.\n",
"# In order to define an instance of the geocoder, we need to define a user_agent.\n",
"# We will name our agent ny_explorer, as shown below."
]
},
{
"cell_type": "code",
"execution_count": 316,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
},
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The geograpical coordinate of New York City are 40.7127281, -74.0060152.\n"
]
}
],
"source": [
"address = 'New York City, NY'\n",
"\n",
"geolocator = Nominatim(user_agent=\"ny_explorer\")\n",
"location = geolocator.geocode(address)\n",
"latitude = location.latitude\n",
"longitude = location.longitude\n",
"print('The geograpical coordinate of New York City are {}, {}.'.format(latitude, longitude))"
]
},
{
"cell_type": "code",
"execution_count": 317,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"data": {
"text/html": [
"<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><span style=\"color:#565656\">Make this Notebook Trusted to load map: File -> Trust Notebook</span><iframe src=\"about:blank\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" data-html=PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVMgPSBmYWxzZTsgTF9OT19UT1VDSCA9IGZhbHNlOyBMX0RJU0FCTEVfM0QgPSBmYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdnaXQuY29tL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9tYXN0ZXIvZm9saXVtL3RlbXBsYXRlcy9sZWFmbGV0LmF3ZXNvbWUucm90YXRlLmNzcyIvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogMTAwLjAlOwogICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgICAgICAgICAgdG9wOiAwLjAlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICA8L3N0eWxlPgogICAgICAgIAo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgICAgICAgICA8ZGl2IGNsYXNzPSJmb2xpdW0tbWFwIiBpZD0ibWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhIiA+PC9kaXY+CiAgICAgICAgCjwvYm9keT4KPHNjcmlwdD4gICAgCiAgICAKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGJvdW5kcyA9IG51bGw7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgdmFyIG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSA9IEwubWFwKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ21hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7Y2VudGVyOiBbNDAuNzEyNzI4MSwtNzQuMDA2MDE1Ml0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB6b29tOiAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heEJvdW5kczogYm91bmRzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF5ZXJzOiBbXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmxkQ29weUp1bXA6IGZhbHNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JzOiBMLkNSUy5FUFNHMzg1NwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHRpbGVfbGF5ZXJfYTdhMzIzNTYyMmRlNDQ0OTljZDExNTQwNDYwNGZhYjIgPSBMLnRpbGVMYXllcigKICAgICAgICAgICAgICAgICdodHRwczovL3tzfS50aWxlLm9wZW5zdHJlZXRtYXAub3JnL3t6fS97eH0ve3l9LnBuZycsCiAgICAgICAgICAgICAgICB7CiAgImF0dHJpYnV0aW9uIjogbnVsbCwKICAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsCiAgIm1heFpvb20iOiAxOCwKICAibWluWm9vbSI6IDEsCiAgIm5vV3JhcCI6IGZhbHNlLAogICJzdWJkb21haW5zIjogImFiYyIKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY0MjllMDgzZTkyNTQyMjJiOGNmMzZmYWNkYWQxNGNiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODk0NzA1MTc2NjEsLTczLjg0NzIwMDUyMDU0OTAyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzg3ZDNhZDhlM2JmMjQyNmVhMWE2NTIxMDBlMzIzMTJiID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzgyYWU2MGYxYjhkNzQyYmFhZjU0YjBjODFlNWEwMzFiID0gJCgnPGRpdiBpZD0iaHRtbF84MmFlNjBmMWI4ZDc0MmJhYWY1NGIwYzgxZTVhMDMxYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2FrZWZpZWxkLCBCcm9ueDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfODdkM2FkOGUzYmYyNDI2ZWExYTY1MjEwMGUzMjMxMmIuc2V0Q29udGVudChodG1sXzgyYWU2MGYxYjhkNzQyYmFhZjU0YjBjODFlNWEwMzFiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzY0MjllMDgzZTkyNTQyMjJiOGNmMzZmYWNkYWQxNGNiLmJpbmRQb3B1cChwb3B1cF84N2QzYWQ4ZTNiZjI0MjZlYTFhNjUyMTAwZTMyMzEyYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82YjNmOWM4Y2MyNzc0ZDkxYTE1NDQ4ODIzNWY2YzAzNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjg3NDI5NDE5MzAzMDEyLC03My44Mjk5MzkxMDgxMjM5OF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84NDhkODM5MWUyODI0ZmYzOTFmMzY1NGUxN2ZmNTNlMyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81NGM3ZDE5M2QwYzU0ZTFjOWU1OTVhNDY0ZjMyYzc4MiA9ICQoJzxkaXYgaWQ9Imh0bWxfNTRjN2QxOTNkMGM1NGUxYzllNTk1YTQ2NGYzMmM3ODIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNvLW9wIENpdHksIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84NDhkODM5MWUyODI0ZmYzOTFmMzY1NGUxN2ZmNTNlMy5zZXRDb250ZW50KGh0bWxfNTRjN2QxOTNkMGM1NGUxYzllNTk1YTQ2NGYzMmM3ODIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNmIzZjljOGNjMjc3NGQ5MWExNTQ0ODgyMzVmNmMwMzcuYmluZFBvcHVwKHBvcHVwXzg0OGQ4MzkxZTI4MjRmZjM5MWYzNjU0ZTE3ZmY1M2UzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzUxYzUyNmViMWFlODRjOWE5NjFkNDZkMTU5YWRiNDQ4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODg3NTU1Njc3MzUwNzc1LC03My44Mjc4MDY0NDcxNjQxMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wZWFkNzQ1MWMzOGQ0ZWVlOWUzN2Q4ZmJhMjEyMWRhYiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81ZjhiNWZhYzBjOGY0YjU0YjAxZTMyZjgxY2YyOTlhNSA9ICQoJzxkaXYgaWQ9Imh0bWxfNWY4YjVmYWMwYzhmNGI1NGIwMWUzMmY4MWNmMjk5YTUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkVhc3RjaGVzdGVyLCBCcm9ueDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMGVhZDc0NTFjMzhkNGVlZTllMzdkOGZiYTIxMjFkYWIuc2V0Q29udGVudChodG1sXzVmOGI1ZmFjMGM4ZjRiNTRiMDFlMzJmODFjZjI5OWE1KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzUxYzUyNmViMWFlODRjOWE5NjFkNDZkMTU5YWRiNDQ4LmJpbmRQb3B1cChwb3B1cF8wZWFkNzQ1MWMzOGQ0ZWVlOWUzN2Q4ZmJhMjEyMWRhYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xYjQ3MGVmNmVlMjM0YmQxODc4NTFhNTYwNzBmNDU4YyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjg5NTQzNzQyNjkwMzgzLC03My45MDU2NDI1OTU5MTY4Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iMzgxZTM4MGE0NmY0OWJjOWMyMmJlMjMyZTJmNTZmZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8yOGZmNDM5NTk0NGM0YmM4YWVlZDU1OTFiNDU0ZjkzNCA9ICQoJzxkaXYgaWQ9Imh0bWxfMjhmZjQzOTU5NDRjNGJjOGFlZWQ1NTkxYjQ1NGY5MzQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZpZWxkc3RvbiwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2IzODFlMzgwYTQ2ZjQ5YmM5YzIyYmUyMzJlMmY1NmZmLnNldENvbnRlbnQoaHRtbF8yOGZmNDM5NTk0NGM0YmM4YWVlZDU1OTFiNDU0ZjkzNCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xYjQ3MGVmNmVlMjM0YmQxODc4NTFhNTYwNzBmNDU4Yy5iaW5kUG9wdXAocG9wdXBfYjM4MWUzODBhNDZmNDliYzljMjJiZTIzMmUyZjU2ZmYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNjViMDkzYTQwYmI1NDU0YjhjMjFlNWE1MmJlOTFkYTAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44OTA4MzQ0OTM4OTEzMDUsLTczLjkxMjU4NTQ2MTA4NTddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjdlMDAzY2Q4ZjA2NDM5MWJhMjEzNzBjMDllMjZiZGUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZmFhNDRkMmY3ZWU5NDg1YmJkZDYxNjY1NTIwNGU5NzMgPSAkKCc8ZGl2IGlkPSJodG1sX2ZhYTQ0ZDJmN2VlOTQ4NWJiZGQ2MTY2NTUyMDRlOTczIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5SaXZlcmRhbGUsIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82N2UwMDNjZDhmMDY0MzkxYmEyMTM3MGMwOWUyNmJkZS5zZXRDb250ZW50KGh0bWxfZmFhNDRkMmY3ZWU5NDg1YmJkZDYxNjY1NTIwNGU5NzMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNjViMDkzYTQwYmI1NDU0YjhjMjFlNWE1MmJlOTFkYTAuYmluZFBvcHVwKHBvcHVwXzY3ZTAwM2NkOGYwNjQzOTFiYTIxMzcwYzA5ZTI2YmRlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2ZmNTcyYjU2ZmVjOTQ1ZDBiZmI5YjI3YTkwMDA3MWFjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODgxNjg3MzcxMjA1MjEsLTczLjkwMjgxNzk4NzI0NjA0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzU2ZjZjMjMyYmE4ZTRhMzQ4M2Q4MDM1NDQ3ZGM1ZmZhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzViYTkyOGNhYjI0MjQ2Yjk4ZGZiNjVhZmE0ZDQxMjBhID0gJCgnPGRpdiBpZD0iaHRtbF81YmE5MjhjYWIyNDI0NmI5OGRmYjY1YWZhNGQ0MTIwYSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+S2luZ3NicmlkZ2UsIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81NmY2YzIzMmJhOGU0YTM0ODNkODAzNTQ0N2RjNWZmYS5zZXRDb250ZW50KGh0bWxfNWJhOTI4Y2FiMjQyNDZiOThkZmI2NWFmYTRkNDEyMGEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZmY1NzJiNTZmZWM5NDVkMGJmYjliMjdhOTAwMDcxYWMuYmluZFBvcHVwKHBvcHVwXzU2ZjZjMjMyYmE4ZTRhMzQ4M2Q4MDM1NDQ3ZGM1ZmZhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2UyZTJlMmY2NzUwMzQ4YmE5NWU5YTMxNWNhYzMzMzQ3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODc2NTUwNzc4Nzk5NjQsLTczLjkxMDY1OTY1ODYyOTgxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzVhNGJhNjI2YTk3YTQ2YWM5ODcwMGYzMjQ4OGIwN2NhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2IzYjFmOGNhMTZjNDRhZGE4ZWU1YzU2MmQzY2JlYjIxID0gJCgnPGRpdiBpZD0iaHRtbF9iM2IxZjhjYTE2YzQ0YWRhOGVlNWM1NjJkM2NiZWIyMSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TWFyYmxlIEhpbGwsIE1hbmhhdHRhbjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNWE0YmE2MjZhOTdhNDZhYzk4NzAwZjMyNDg4YjA3Y2Euc2V0Q29udGVudChodG1sX2IzYjFmOGNhMTZjNDRhZGE4ZWU1YzU2MmQzY2JlYjIxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2UyZTJlMmY2NzUwMzQ4YmE5NWU5YTMxNWNhYzMzMzQ3LmJpbmRQb3B1cChwb3B1cF81YTRiYTYyNmE5N2E0NmFjOTg3MDBmMzI0ODhiMDdjYSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mYmVjMjMzNGFkNzA0ZjM1Yjc3MWIwMTJkZTgwYWJjYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjg5ODI3MjYxMjEzODA1LC03My44NjczMTQ5NjgxNDE3Nl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yMjc4MWVhOTAxMDY0MzY5OTIxMTM4MjhhNjJiOWZmOCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xZTQ4NjE0MzRmNGM0NzQ5OTVhMzk1YjgwMDM5YzFhOCA9ICQoJzxkaXYgaWQ9Imh0bWxfMWU0ODYxNDM0ZjRjNDc0OTk1YTM5NWI4MDAzOWMxYTgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldvb2RsYXduLCBCcm9ueDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjI3ODFlYTkwMTA2NDM2OTkyMTEzODI4YTYyYjlmZjguc2V0Q29udGVudChodG1sXzFlNDg2MTQzNGY0YzQ3NDk5NWEzOTViODAwMzljMWE4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2ZiZWMyMzM0YWQ3MDRmMzViNzcxYjAxMmRlODBhYmNiLmJpbmRQb3B1cChwb3B1cF8yMjc4MWVhOTAxMDY0MzY5OTIxMTM4MjhhNjJiOWZmOCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81MWFiNGRjMDhmNTA0NDU4OWE2ZWY2YzQ2Y2U5MmJiNiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjg3NzIyNDE1NTk5NDQ2LC03My44NzkzOTA3Mzk1NjgxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2E0MzZmODc2MWQxMzQzNzJiNGM1NDVkNzQxOThjNjMxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2FlMTg4YTk2NWVkMDQ2ZDdiNDIzZjIzYTM3MTc2OWY1ID0gJCgnPGRpdiBpZD0iaHRtbF9hZTE4OGE5NjVlZDA0NmQ3YjQyM2YyM2EzNzE3NjlmNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Tm9yd29vZCwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2E0MzZmODc2MWQxMzQzNzJiNGM1NDVkNzQxOThjNjMxLnNldENvbnRlbnQoaHRtbF9hZTE4OGE5NjVlZDA0NmQ3YjQyM2YyM2EzNzE3NjlmNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl81MWFiNGRjMDhmNTA0NDU4OWE2ZWY2YzQ2Y2U5MmJiNi5iaW5kUG9wdXAocG9wdXBfYTQzNmY4NzYxZDEzNDM3MmI0YzU0NWQ3NDE5OGM2MzEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOGI4NzBhYTg0ODdjNDE0NDgwMDFiMjEwYTA2YzYyYTggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44ODEwMzg4NzgxOTIxMSwtNzMuODU3NDQ2NDI5NzQyMDddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZTdiOTY1NmNmNzdlNDViZmJhMzQwYWYxMmI1ZDA2MGIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYmNiNGMzYjNkZDM1NGI2NGI1NTkzZmU5MGQ4NTNkNTUgPSAkKCc8ZGl2IGlkPSJodG1sX2JjYjRjM2IzZGQzNTRiNjRiNTU5M2ZlOTBkODUzZDU1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XaWxsaWFtc2JyaWRnZSwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2U3Yjk2NTZjZjc3ZTQ1YmZiYTM0MGFmMTJiNWQwNjBiLnNldENvbnRlbnQoaHRtbF9iY2I0YzNiM2RkMzU0YjY0YjU1OTNmZTkwZDg1M2Q1NSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84Yjg3MGFhODQ4N2M0MTQ0ODAwMWIyMTBhMDZjNjJhOC5iaW5kUG9wdXAocG9wdXBfZTdiOTY1NmNmNzdlNDViZmJhMzQwYWYxMmI1ZDA2MGIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYmU2N2JkNmZmMDFiNDk2MWJkNzUyYzJiMGNmZTVmMjQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44NjY4NTgxMDcyNTI2OTYsLTczLjgzNTc5NzU5ODA4MTE3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2E1ZTI0ZTIwMzY1MTQzNjk5OWEwZTljMzNhOTdmMjdlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc4YWEwOGY5M2MyZDQwZjZiYmIwZTIzNWVlOWUzYjE0ID0gJCgnPGRpdiBpZD0iaHRtbF83OGFhMDhmOTNjMmQ0MGY2YmJiMGUyMzVlZTllM2IxNCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmF5Y2hlc3RlciwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2E1ZTI0ZTIwMzY1MTQzNjk5OWEwZTljMzNhOTdmMjdlLnNldENvbnRlbnQoaHRtbF83OGFhMDhmOTNjMmQ0MGY2YmJiMGUyMzVlZTllM2IxNCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9iZTY3YmQ2ZmYwMWI0OTYxYmQ3NTJjMmIwY2ZlNWYyNC5iaW5kUG9wdXAocG9wdXBfYTVlMjRlMjAzNjUxNDM2OTk5YTBlOWMzM2E5N2YyN2UpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTJmZTU1MDU3NDlkNDM3YmIwNjZjYTc1MzQ2ZWVhYTcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44NTc0MTM0OTgwODg2NSwtNzMuODU0NzU1NjQwMTc5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzBkZGZkNzVlYmFjNGUxZmJlZjc0NWMxMDdiMjBlMGEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMTk2MzRkMDMwNDEwNDNiYWE0ZDExMzMwOWY2YTczMTQgPSAkKCc8ZGl2IGlkPSJodG1sXzE5NjM0ZDAzMDQxMDQzYmFhNGQxMTMzMDlmNmE3MzE0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5QZWxoYW0gUGFya3dheSwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2MwZGRmZDc1ZWJhYzRlMWZiZWY3NDVjMTA3YjIwZTBhLnNldENvbnRlbnQoaHRtbF8xOTYzNGQwMzA0MTA0M2JhYTRkMTEzMzA5ZjZhNzMxNCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl81MmZlNTUwNTc0OWQ0MzdiYjA2NmNhNzUzNDZlZWFhNy5iaW5kUG9wdXAocG9wdXBfYzBkZGZkNzVlYmFjNGUxZmJlZjc0NWMxMDdiMjBlMGEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfN2VhYTRkYjE5NjYyNDM0YmFjNTY0ZWRiYTMyM2FjM2YgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44NDcyNDY3MDQ5MTgxMywtNzMuNzg2NDg4NDUyNjc0MTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOWE1YWU3ZTk2NmYwNGQxOWIxNDJlYTYzY2MxNjExODQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNWM1Nzc3N2U3MWZhNDVhODhjMjBjMDA5YTMxZWIxYTAgPSAkKCc8ZGl2IGlkPSJodG1sXzVjNTc3NzdlNzFmYTQ1YTg4YzIwYzAwOWEzMWViMWEwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DaXR5IElzbGFuZCwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzlhNWFlN2U5NjZmMDRkMTliMTQyZWE2M2NjMTYxMTg0LnNldENvbnRlbnQoaHRtbF81YzU3Nzc3ZTcxZmE0NWE4OGMyMGMwMDlhMzFlYjFhMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83ZWFhNGRiMTk2NjI0MzRiYWM1NjRlZGJhMzIzYWMzZi5iaW5kUG9wdXAocG9wdXBfOWE1YWU3ZTk2NmYwNGQxOWIxNDJlYTYzY2MxNjExODQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZWQ1ZDgwZTk1NWMxNGExNGEzOGY5NDE4NWUxNzg2YzUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44NzAxODUxNjQ5NzUzMjUsLTczLjg4NTUxMjE4NDE5MTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMDIzNDA3NDU2YWY5NDEzYTg1MTRjMTUyYWYyMWIxNTIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjUwZjAxMGNmNmQ4NDI4ODkyMmM3MTFkNDkxZGU0MzEgPSAkKCc8ZGl2IGlkPSJodG1sX2Y1MGYwMTBjZjZkODQyODg5MjJjNzExZDQ5MWRlNDMxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CZWRmb3JkIFBhcmssIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wMjM0MDc0NTZhZjk0MTNhODUxNGMxNTJhZjIxYjE1Mi5zZXRDb250ZW50KGh0bWxfZjUwZjAxMGNmNmQ4NDI4ODkyMmM3MTFkNDkxZGU0MzEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZWQ1ZDgwZTk1NWMxNGExNGEzOGY5NDE4NWUxNzg2YzUuYmluZFBvcHVwKHBvcHVwXzAyMzQwNzQ1NmFmOTQxM2E4NTE0YzE1MmFmMjFiMTUyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzkyMDlhZWIyYmI0ZTQ1ZjM5OTIxNGZlNjc4YzBlNjQxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODU1NzI3MDc3MTk2NjQsLTczLjkxMDQxNTk2MTkxMzFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMWY4YmMyYTAwOTVhNDEwNGIyN2Y0YzJhMjlmOTBjYTQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfN2I1MTc1ZjQ3NTdiNDM2YTg2NzdjZThiNDc5OGI3MmIgPSAkKCc8ZGl2IGlkPSJodG1sXzdiNTE3NWY0NzU3YjQzNmE4Njc3Y2U4YjQ3OThiNzJiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Vbml2ZXJzaXR5IEhlaWdodHMsIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xZjhiYzJhMDA5NWE0MTA0YjI3ZjRjMmEyOWY5MGNhNC5zZXRDb250ZW50KGh0bWxfN2I1MTc1ZjQ3NTdiNDM2YTg2NzdjZThiNDc5OGI3MmIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOTIwOWFlYjJiYjRlNDVmMzk5MjE0ZmU2NzhjMGU2NDEuYmluZFBvcHVwKHBvcHVwXzFmOGJjMmEwMDk1YTQxMDRiMjdmNGMyYTI5ZjkwY2E0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzMwODNlNTBhMjYwOTRjMmRhYTc0NjJiYWUxN2MxM2JjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODQ3ODk3OTI2MDYyNzEsLTczLjkxOTY3MTU5MTE5NTY1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzk1ZTM4YmQ2NmNkMDQ4M2JhYTQ5MmFmODBkODA5YmEwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2ZiM2RjZmVkMmVhNzRhM2U4MDY3YjQ4N2I1ZWM4ZTVkID0gJCgnPGRpdiBpZD0iaHRtbF9mYjNkY2ZlZDJlYTc0YTNlODA2N2I0ODdiNWVjOGU1ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TW9ycmlzIEhlaWdodHMsIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85NWUzOGJkNjZjZDA0ODNiYWE0OTJhZjgwZDgwOWJhMC5zZXRDb250ZW50KGh0bWxfZmIzZGNmZWQyZWE3NGEzZTgwNjdiNDg3YjVlYzhlNWQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMzA4M2U1MGEyNjA5NGMyZGFhNzQ2MmJhZTE3YzEzYmMuYmluZFBvcHVwKHBvcHVwXzk1ZTM4YmQ2NmNkMDQ4M2JhYTQ5MmFmODBkODA5YmEwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzVkYjNjNzdjNjY5ZjQzODc4MzYwNjM3MThkYTg1MWNlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODYwOTk2Nzk2Mzg2NTQsLTczLjg5NjQyNjU1OTgxNjIzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzYyYTM2YzJkODgzYjRkNDZiYWI1NGU1OTUwYzU4MDYxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzQ2YTQ0MjNhOTllMzRhMmRhYzc0NGUyNzkzZDA3ZTdiID0gJCgnPGRpdiBpZD0iaHRtbF80NmE0NDIzYTk5ZTM0YTJkYWM3NDRlMjc5M2QwN2U3YiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Rm9yZGhhbSwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzYyYTM2YzJkODgzYjRkNDZiYWI1NGU1OTUwYzU4MDYxLnNldENvbnRlbnQoaHRtbF80NmE0NDIzYTk5ZTM0YTJkYWM3NDRlMjc5M2QwN2U3Yik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl81ZGIzYzc3YzY2OWY0Mzg3ODM2MDYzNzE4ZGE4NTFjZS5iaW5kUG9wdXAocG9wdXBfNjJhMzZjMmQ4ODNiNGQ0NmJhYjU0ZTU5NTBjNTgwNjEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZWRmNDBlN2ExZmFhNDNjNGFiOTE1NWY2MTQ5YjQ0MmQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44NDI2OTYxNTc4NjA1MywtNzMuODg3MzU2MTc1MzIzMzhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzczMWU1Nzc0MTc1NDliNmE2MDg0YThmNWIyNWE0NWEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMzY0Y2E1MjQxMzgzNDE1M2IxMDg0ZGI3YzZiOTZhYzkgPSAkKCc8ZGl2IGlkPSJodG1sXzM2NGNhNTI0MTM4MzQxNTNiMTA4NGRiN2M2Yjk2YWM5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FYXN0IFRyZW1vbnQsIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jNzMxZTU3NzQxNzU0OWI2YTYwODRhOGY1YjI1YTQ1YS5zZXRDb250ZW50KGh0bWxfMzY0Y2E1MjQxMzgzNDE1M2IxMDg0ZGI3YzZiOTZhYzkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZWRmNDBlN2ExZmFhNDNjNGFiOTE1NWY2MTQ5YjQ0MmQuYmluZFBvcHVwKHBvcHVwX2M3MzFlNTc3NDE3NTQ5YjZhNjA4NGE4ZjViMjVhNDVhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2NlZmQ2OTAyMDVlNjRmM2RhZTliODQyYjg0OTEzNTE3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODM5NDc1MDU2NzI2NTMsLTczLjg3Nzc0NDc0OTEwNTQ1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzZlMWI5NDc5ZDUyNjQ3NzA5ZTE1OTA5MzUyMTE2M2I1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2E4ZGUyZTc4MDM1OTQ0ZjE5NTIwYzk0OWUyMTA2Mzg4ID0gJCgnPGRpdiBpZD0iaHRtbF9hOGRlMmU3ODAzNTk0NGYxOTUyMGM5NDllMjEwNjM4OCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2VzdCBGYXJtcywgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzZlMWI5NDc5ZDUyNjQ3NzA5ZTE1OTA5MzUyMTE2M2I1LnNldENvbnRlbnQoaHRtbF9hOGRlMmU3ODAzNTk0NGYxOTUyMGM5NDllMjEwNjM4OCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jZWZkNjkwMjA1ZTY0ZjNkYWU5Yjg0MmI4NDkxMzUxNy5iaW5kUG9wdXAocG9wdXBfNmUxYjk0NzlkNTI2NDc3MDllMTU5MDkzNTIxMTYzYjUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODdkODM0NWE4YjQ4NDNmZWExM2FhOTg2MzU5ZDc0NzEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44MzY2MjMwMTA3MDYwNTYsLTczLjkyNjEwMjA5MzU4MTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZGVhYmE3NDJkM2MyNGM2Zjk1N2FhNjI5NWI5MWI2ZDIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMDlmMzU5YTc5ZTNlNGZkNGI3YmM0ZTJiY2NjMWQ1NDAgPSAkKCc8ZGl2IGlkPSJodG1sXzA5ZjM1OWE3OWUzZTRmZDRiN2JjNGUyYmNjYzFkNTQwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IaWdoICBCcmlkZ2UsIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9kZWFiYTc0MmQzYzI0YzZmOTU3YWE2Mjk1YjkxYjZkMi5zZXRDb250ZW50KGh0bWxfMDlmMzU5YTc5ZTNlNGZkNGI3YmM0ZTJiY2NjMWQ1NDApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODdkODM0NWE4YjQ4NDNmZWExM2FhOTg2MzU5ZDc0NzEuYmluZFBvcHVwKHBvcHVwX2RlYWJhNzQyZDNjMjRjNmY5NTdhYTYyOTViOTFiNmQyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2U2NTRmN2IyYTMwZjRhMzdiYWE4ODkwOTk1MjJjYWM4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODE5NzU0MzcwNTk0OTM2LC03My45MDk0MjE2MDc1NzQzNl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lODE5YWFmZTAxYzU0Y2M1YTM0OTkzOGUxNTE0ZTFjYiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jYmMwMmY0N2JiZjQ0NTVhYjRiZjYzYTMxMTllNTQ5YSA9ICQoJzxkaXYgaWQ9Imh0bWxfY2JjMDJmNDdiYmY0NDU1YWI0YmY2M2EzMTE5ZTU0OWEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1lbHJvc2UsIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lODE5YWFmZTAxYzU0Y2M1YTM0OTkzOGUxNTE0ZTFjYi5zZXRDb250ZW50KGh0bWxfY2JjMDJmNDdiYmY0NDU1YWI0YmY2M2EzMTE5ZTU0OWEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZTY1NGY3YjJhMzBmNGEzN2JhYTg4OTA5OTUyMmNhYzguYmluZFBvcHVwKHBvcHVwX2U4MTlhYWZlMDFjNTRjYzVhMzQ5OTM4ZTE1MTRlMWNiKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzAwZDM5Nzg5ZjE0ZDQ3YjU4Mjg1ZjNhNzMyOWE5NDQ2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODA2MjM4NzQ5MzUxNzcsLTczLjkxNjA5OTg3NDg3NTc1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2ZkY2I5ZTJmNTdlODRhMDQ5MTgwNTA5YjU0ZTJiOTUwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzZjZTE2OTBiOWYwMzQxYjU5MWMzMDE4ZDdhNGRjNmU3ID0gJCgnPGRpdiBpZD0iaHRtbF82Y2UxNjkwYjlmMDM0MWI1OTFjMzAxOGQ3YTRkYzZlNyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TW90dCBIYXZlbiwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2ZkY2I5ZTJmNTdlODRhMDQ5MTgwNTA5YjU0ZTJiOTUwLnNldENvbnRlbnQoaHRtbF82Y2UxNjkwYjlmMDM0MWI1OTFjMzAxOGQ3YTRkYzZlNyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wMGQzOTc4OWYxNGQ0N2I1ODI4NWYzYTczMjlhOTQ0Ni5iaW5kUG9wdXAocG9wdXBfZmRjYjllMmY1N2U4NGEwNDkxODA1MDliNTRlMmI5NTApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjhlZWM0Yjk5YWMyNDNhMmIwNjA4ZTA1YTEyNjNiOTEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44MDE2NjM2Mjc3NTYyMDYsLTczLjkxMzIyMTM5Mzg2MTM1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzZlMDVkMGE1OGE4ZDQzYjk5ODFjNDY1MjAxYTNhMDMxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzk3NjZkNTg3OTBlNjQyZGFhYjZhNGRjYjk1ZjhjYzE0ID0gJCgnPGRpdiBpZD0iaHRtbF85NzY2ZDU4NzkwZTY0MmRhYWI2YTRkY2I5NWY4Y2MxNCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UG9ydCBNb3JyaXMsIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82ZTA1ZDBhNThhOGQ0M2I5OTgxYzQ2NTIwMWEzYTAzMS5zZXRDb250ZW50KGh0bWxfOTc2NmQ1ODc5MGU2NDJkYWFiNmE0ZGNiOTVmOGNjMTQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjhlZWM0Yjk5YWMyNDNhMmIwNjA4ZTA1YTEyNjNiOTEuYmluZFBvcHVwKHBvcHVwXzZlMDVkMGE1OGE4ZDQzYjk5ODFjNDY1MjAxYTNhMDMxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzc2Zjk1ODA0Y2RjMzRmZGM4MDUzODc1MmJlOGEwNjI1ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODE1MDk5MDQ1NDU4MjIsLTczLjg5NTc4ODIwMDk0NDZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMDMzMjkxNjc0NTY4NDY1Mjk5NDk1YWY1NTFjOTY5NGQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOTVmODg5ZWE0Nzg0NDQwY2E5ZGRhNjZiNDZhMWM5NmMgPSAkKCc8ZGl2IGlkPSJodG1sXzk1Zjg4OWVhNDc4NDQ0MGNhOWRkYTY2YjQ2YTFjOTZjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Mb25nd29vZCwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzAzMzI5MTY3NDU2ODQ2NTI5OTQ5NWFmNTUxYzk2OTRkLnNldENvbnRlbnQoaHRtbF85NWY4ODllYTQ3ODQ0NDBjYTlkZGE2NmI0NmExYzk2Yyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83NmY5NTgwNGNkYzM0ZmRjODA1Mzg3NTJiZThhMDYyNS5iaW5kUG9wdXAocG9wdXBfMDMzMjkxNjc0NTY4NDY1Mjk5NDk1YWY1NTFjOTY5NGQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMmExNTAwMDA1NjgyNDc2MDhjOGMxNTczZTYxMzBjOGIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44MDk3Mjk4NzkzODcwOSwtNzMuODgzMzE1MDU5NTUyOTFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzYwZDZlNjIzYWNjNGRiNTgwNDFhMDdmZjlkNDhlNDAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMjFmODRiNGY2NDdjNGE2NmI4Yzg4ZWY0Y2Q5NDQ0MzUgPSAkKCc8ZGl2IGlkPSJodG1sXzIxZjg0YjRmNjQ3YzRhNjZiOGM4OGVmNGNkOTQ0NDM1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IdW50cyBQb2ludCwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2M2MGQ2ZTYyM2FjYzRkYjU4MDQxYTA3ZmY5ZDQ4ZTQwLnNldENvbnRlbnQoaHRtbF8yMWY4NGI0ZjY0N2M0YTY2YjhjODhlZjRjZDk0NDQzNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yYTE1MDAwMDU2ODI0NzYwOGM4YzE1NzNlNjEzMGM4Yi5iaW5kUG9wdXAocG9wdXBfYzYwZDZlNjIzYWNjNGRiNTgwNDFhMDdmZjlkNDhlNDApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYmExM2VmNjliYzFlNGI0NGFjYmNmZjM3ZjJmMGEzNDggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44MjM1OTE5ODU4NTUzNCwtNzMuOTAxNTA2NDg5NDMwNTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzYxNjIwMjNhNzYwNDIxOWIyZWMxNDc4YWZhM2FhMmQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZGFmODdiZWEyMTA3NDZhZGFkNWFlMzA1ZDA0MGNhYmUgPSAkKCc8ZGl2IGlkPSJodG1sX2RhZjg3YmVhMjEwNzQ2YWRhZDVhZTMwNWQwNDBjYWJlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Nb3JyaXNhbmlhLCBCcm9ueDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzYxNjIwMjNhNzYwNDIxOWIyZWMxNDc4YWZhM2FhMmQuc2V0Q29udGVudChodG1sX2RhZjg3YmVhMjEwNzQ2YWRhZDVhZTMwNWQwNDBjYWJlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2JhMTNlZjY5YmMxZTRiNDRhY2JjZmYzN2YyZjBhMzQ4LmJpbmRQb3B1cChwb3B1cF8zNjE2MjAyM2E3NjA0MjE5YjJlYzE0NzhhZmEzYWEyZCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zYjU1ZDRmNDZlNzM0OGZiYWYwMDhkYTI4NWUzZTEwZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjgyMTAxMjE5NzkxNDAxNSwtNzMuODY1NzQ2MDk1NTQ5MjRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjZlMDlhYzQ1ZjZhNDlkYzk5M2U1MDhlYWY4YWIxMjkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfODQ5YzU1MzQ5YjBkNDhmNzgzNDRlMjYwYjM3MzMzMzIgPSAkKCc8ZGl2IGlkPSJodG1sXzg0OWM1NTM0OWIwZDQ4Zjc4MzQ0ZTI2MGIzNzMzMzMyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Tb3VuZHZpZXcsIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mNmUwOWFjNDVmNmE0OWRjOTkzZTUwOGVhZjhhYjEyOS5zZXRDb250ZW50KGh0bWxfODQ5YzU1MzQ5YjBkNDhmNzgzNDRlMjYwYjM3MzMzMzIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfM2I1NWQ0ZjQ2ZTczNDhmYmFmMDA4ZGEyODVlM2UxMGQuYmluZFBvcHVwKHBvcHVwX2Y2ZTA5YWM0NWY2YTQ5ZGM5OTNlNTA4ZWFmOGFiMTI5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Q1ZDc1NzdmNTFmYzQ5MzRhMDIyYjZiODU4NmQwY2ZmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODA2NTUxMTIwMDM1ODksLTczLjg1NDE0NDE2MTg5MjY2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2U5NjBhMzNjNmFlYjQ5MDFhYTc5ZTBkOTI3OThkMGE2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzcyZDMxNmVlMTY3OTQxNGJhMTZhNjY2ZDY3YTM1NzNhID0gJCgnPGRpdiBpZD0iaHRtbF83MmQzMTZlZTE2Nzk0MTRiYTE2YTY2NmQ2N2EzNTczYSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q2xhc29uIFBvaW50LCBCcm9ueDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZTk2MGEzM2M2YWViNDkwMWFhNzllMGQ5Mjc5OGQwYTYuc2V0Q29udGVudChodG1sXzcyZDMxNmVlMTY3OTQxNGJhMTZhNjY2ZDY3YTM1NzNhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2Q1ZDc1NzdmNTFmYzQ5MzRhMDIyYjZiODU4NmQwY2ZmLmJpbmRQb3B1cChwb3B1cF9lOTYwYTMzYzZhZWI0OTAxYWE3OWUwZDkyNzk4ZDBhNik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xOTQ5YjlhNGViMDA0YWFlYTNhYTk2MWUyNTNjMDM5NCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjgxNTEwOTI1ODA0MDA1LC03My44MTYzNTAwMjE1ODQ0MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yYjQyNTAyZmQ5N2Y0YjliYWZlYTAzMTFhMGI5Njc1NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iYjEwYzUyZDFiZjY0YWEwYWMxMWI1ODlmYmRlYzliYyA9ICQoJzxkaXYgaWQ9Imh0bWxfYmIxMGM1MmQxYmY2NGFhMGFjMTFiNTg5ZmJkZWM5YmMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlRocm9ncyBOZWNrLCBCcm9ueDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMmI0MjUwMmZkOTdmNGI5YmFmZWEwMzExYTBiOTY3NTQuc2V0Q29udGVudChodG1sX2JiMTBjNTJkMWJmNjRhYTBhYzExYjU4OWZiZGVjOWJjKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzE5NDliOWE0ZWIwMDRhYWVhM2FhOTYxZTI1M2MwMzk0LmJpbmRQb3B1cChwb3B1cF8yYjQyNTAyZmQ5N2Y0YjliYWZlYTAzMTFhMGI5Njc1NCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82NjdiMTIyYTVkYmY0ZDk5OTQzM2UzYzNmOWU0NTIwNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjg0NDI0NTkzNjk0NzM3NCwtNzMuODI0MDk5MjY3NTM4NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yOGI5NzY3ZWY0ZjE0ZGJjOTE2YzBkNWY1NWI5ZjlkOCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9kNjcwNDY2YjFmN2Q0ODM2OGU3NWQ1NTcyMGQzZWE3OCA9ICQoJzxkaXYgaWQ9Imh0bWxfZDY3MDQ2NmIxZjdkNDgzNjhlNzVkNTU3MjBkM2VhNzgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNvdW50cnkgQ2x1YiwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzI4Yjk3NjdlZjRmMTRkYmM5MTZjMGQ1ZjU1YjlmOWQ4LnNldENvbnRlbnQoaHRtbF9kNjcwNDY2YjFmN2Q0ODM2OGU3NWQ1NTcyMGQzZWE3OCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82NjdiMTIyYTVkYmY0ZDk5OTQzM2UzYzNmOWU0NTIwNS5iaW5kUG9wdXAocG9wdXBfMjhiOTc2N2VmNGYxNGRiYzkxNmMwZDVmNTViOWY5ZDgpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZTgxMTcyODBlZTIyNDkyYWI4OWJlZGQwYmZhZGYyMmIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44Mzc5Mzc4MjIyNjcyODYsLTczLjg1NjAwMzEwNTM1NzgzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzI1OTVmZWY1YjIwYjRhYmNhYmVkNGZkMmE1OGRjYjQwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2ZhMGZhMzY0ZmIxYzQxMTA4OTMxOWEwZGEzNTlmZTA2ID0gJCgnPGRpdiBpZD0iaHRtbF9mYTBmYTM2NGZiMWM0MTEwODkzMTlhMGRhMzU5ZmUwNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UGFya2NoZXN0ZXIsIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yNTk1ZmVmNWIyMGI0YWJjYWJlZDRmZDJhNThkY2I0MC5zZXRDb250ZW50KGh0bWxfZmEwZmEzNjRmYjFjNDExMDg5MzE5YTBkYTM1OWZlMDYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZTgxMTcyODBlZTIyNDkyYWI4OWJlZGQwYmZhZGYyMmIuYmluZFBvcHVwKHBvcHVwXzI1OTVmZWY1YjIwYjRhYmNhYmVkNGZkMmE1OGRjYjQwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY3MTgwM2EyZWUzYjQwMzc4YWM2NjRlZmU5OTgyZTQwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODQwNjE5NDk2NDMyNywtNzMuODQyMTk0MDc2MDQ0NDRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMmMzOTNiYWUzZTg5NDU3ODhmYmE4MThhN2JlYTdlZGYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNTBmZDA2Y2MxYjUxNDY0NWJmMGE5Yjc4MDVkMDQxNjkgPSAkKCc8ZGl2IGlkPSJodG1sXzUwZmQwNmNjMWI1MTQ2NDViZjBhOWI3ODA1ZDA0MTY5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XZXN0Y2hlc3RlciBTcXVhcmUsIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yYzM5M2JhZTNlODk0NTc4OGZiYTgxOGE3YmVhN2VkZi5zZXRDb250ZW50KGh0bWxfNTBmZDA2Y2MxYjUxNDY0NWJmMGE5Yjc4MDVkMDQxNjkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNjcxODAzYTJlZTNiNDAzNzhhYzY2NGVmZTk5ODJlNDAuYmluZFBvcHVwKHBvcHVwXzJjMzkzYmFlM2U4OTQ1Nzg4ZmJhODE4YTdiZWE3ZWRmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY4MTU2ZjFlOTJlNzQ2MjQ4ZjgxY2Q3MmEyMjUzMjY1ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODQzNjA4NDcxMjQ3MTgsLTczLjg2NjI5OTE4MDc1NjFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOGYyNzNkOGMwZjlmNDgyZDgwNTI3YTQ0MjhkNTgxYzEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfY2JiZDM4NGMzNTFhNDhmN2E1NGVlMjk0YWVjNmMzOTcgPSAkKCc8ZGl2IGlkPSJodG1sX2NiYmQzODRjMzUxYTQ4ZjdhNTRlZTI5NGFlYzZjMzk3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5WYW4gTmVzdCwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzhmMjczZDhjMGY5ZjQ4MmQ4MDUyN2E0NDI4ZDU4MWMxLnNldENvbnRlbnQoaHRtbF9jYmJkMzg0YzM1MWE0OGY3YTU0ZWUyOTRhZWM2YzM5Nyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82ODE1NmYxZTkyZTc0NjI0OGY4MWNkNzJhMjI1MzI2NS5iaW5kUG9wdXAocG9wdXBfOGYyNzNkOGMwZjlmNDgyZDgwNTI3YTQ0MjhkNTgxYzEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjFkMDgxZWJkOTJlNDI0NTgyY2FhNGIwMmE5YzEzZjQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44NDc1NDkwNjM1MzYzMzQsLTczLjg1MDQwMTc4MDMwNDIxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2M3NzZkMmVmZTViZjQxMTk4YzgyYmY5MTk3ZWE5MWI1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzcwMDM1NTkzNWVmOTQ2NDJiZDc2Mjc4MmVlMTFiYTMzID0gJCgnPGRpdiBpZD0iaHRtbF83MDAzNTU5MzVlZjk0NjQyYmQ3NjI3ODJlZTExYmEzMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TW9ycmlzIFBhcmssIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jNzc2ZDJlZmU1YmY0MTE5OGM4MmJmOTE5N2VhOTFiNS5zZXRDb250ZW50KGh0bWxfNzAwMzU1OTM1ZWY5NDY0MmJkNzYyNzgyZWUxMWJhMzMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjFkMDgxZWJkOTJlNDI0NTgyY2FhNGIwMmE5YzEzZjQuYmluZFBvcHVwKHBvcHVwX2M3NzZkMmVmZTViZjQxMTk4YzgyYmY5MTk3ZWE5MWI1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQ5NTc2ZmE2NjVjOTQwNjY4OTQxMDE3YjMzODA0YWE0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODU3Mjc3MTAwNzM4OTUsLTczLjg4ODQ1MTk2MTM0ODA0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzQ4ZDlmYTBkNmRmMDQxYmViMWUyNWYzNjU4MzA0MTY2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2RlMzU4MTA5MzYyMjQ3OTZhZDU2OGM0NzFmNWUzOGM0ID0gJCgnPGRpdiBpZD0iaHRtbF9kZTM1ODEwOTM2MjI0Nzk2YWQ1NjhjNDcxZjVlMzhjNCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmVsbW9udCwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzQ4ZDlmYTBkNmRmMDQxYmViMWUyNWYzNjU4MzA0MTY2LnNldENvbnRlbnQoaHRtbF9kZTM1ODEwOTM2MjI0Nzk2YWQ1NjhjNDcxZjVlMzhjNCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80OTU3NmZhNjY1Yzk0MDY2ODk0MTAxN2IzMzgwNGFhNC5iaW5kUG9wdXAocG9wdXBfNDhkOWZhMGQ2ZGYwNDFiZWIxZTI1ZjM2NTgzMDQxNjYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYWZhZTFmNDY1MDZmNDE0NzgzNDczNGQyZWM5NjgxZTkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44ODEzOTQ5NzcyNzA4NiwtNzMuOTE3MTkwNDgyMTAzOTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfODhmNTkxMGNhMTk5NDdlOTlkZWEzNWUzNmQ2ZmUxN2YgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNGY1MmMzNTdmMmQ5NGE4MGFlMzk3MjM4MTU4MWU0YWMgPSAkKCc8ZGl2IGlkPSJodG1sXzRmNTJjMzU3ZjJkOTRhODBhZTM5NzIzODE1ODFlNGFjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TcHV5dGVuIER1eXZpbCwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzg4ZjU5MTBjYTE5OTQ3ZTk5ZGVhMzVlMzZkNmZlMTdmLnNldENvbnRlbnQoaHRtbF80ZjUyYzM1N2YyZDk0YTgwYWUzOTcyMzgxNTgxZTRhYyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hZmFlMWY0NjUwNmY0MTQ3ODM0NzM0ZDJlYzk2ODFlOS5iaW5kUG9wdXAocG9wdXBfODhmNTkxMGNhMTk5NDdlOTlkZWEzNWUzNmQ2ZmUxN2YpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZWZlOGFjYmM0NjQyNDkwNGEzYWI0YzEzMTg4NjU3OTggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC45MDg1NDI4Mjk1MDY2NiwtNzMuOTA0NTMwNTQ5MDg5MjddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYWZiNzE5MGE0MzA0NDFiOWI4YTMyOTk5ZjQxNTkwZTYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMjFhOTYyYmJjOGFkNGUyYTlkYzYyODdlNDJlNDNmOTYgPSAkKCc8ZGl2IGlkPSJodG1sXzIxYTk2MmJiYzhhZDRlMmE5ZGM2Mjg3ZTQyZTQzZjk2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ob3J0aCBSaXZlcmRhbGUsIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hZmI3MTkwYTQzMDQ0MWI5YjhhMzI5OTlmNDE1OTBlNi5zZXRDb250ZW50KGh0bWxfMjFhOTYyYmJjOGFkNGUyYTlkYzYyODdlNDJlNDNmOTYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZWZlOGFjYmM0NjQyNDkwNGEzYWI0YzEzMTg4NjU3OTguYmluZFBvcHVwKHBvcHVwX2FmYjcxOTBhNDMwNDQxYjliOGEzMjk5OWY0MTU5MGU2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzUwZWY1MjUwZGI1ZDQ0NDI4MGQyN2U5ZTY4YWM5MzRlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODUwNjQxNDA5NDAzMzUsLTczLjgzMjA3Mzc4MjQwNDddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMDQ2ZjRmMGYxNjQ5NGQ2NGFmOGRkZDE1MTY5NjE4NzkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfM2ZjYWM4ODBmNzM1NGY4YjhmYThhNTY2ZWVmNTRjYjEgPSAkKCc8ZGl2IGlkPSJodG1sXzNmY2FjODgwZjczNTRmOGI4ZmE4YTU2NmVlZjU0Y2IxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5QZWxoYW0gQmF5LCBCcm9ueDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDQ2ZjRmMGYxNjQ5NGQ2NGFmOGRkZDE1MTY5NjE4Nzkuc2V0Q29udGVudChodG1sXzNmY2FjODgwZjczNTRmOGI4ZmE4YTU2NmVlZjU0Y2IxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzUwZWY1MjUwZGI1ZDQ0NDI4MGQyN2U5ZTY4YWM5MzRlLmJpbmRQb3B1cChwb3B1cF8wNDZmNGYwZjE2NDk0ZDY0YWY4ZGRkMTUxNjk2MTg3OSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yYzA0ZDEyYzljOTM0NzU2ODZlOGYyOWQ2NmJmZTBjNiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjgyNjU3OTUxNjg2OTIyLC03My44MjYyMDI3NTk5NDA3M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zMDlmOTU5MGM4M2U0M2Y1YTRjNDMwODY0MjM4YTY4NSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85Njc2ZmFjNzM5ODQ0YzZmYTRiMDUwOGZlNzVkNzgyYSA9ICQoJzxkaXYgaWQ9Imh0bWxfOTY3NmZhYzczOTg0NGM2ZmE0YjA1MDhmZTc1ZDc4MmEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlNjaHV5bGVydmlsbGUsIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zMDlmOTU5MGM4M2U0M2Y1YTRjNDMwODY0MjM4YTY4NS5zZXRDb250ZW50KGh0bWxfOTY3NmZhYzczOTg0NGM2ZmE0YjA1MDhmZTc1ZDc4MmEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMmMwNGQxMmM5YzkzNDc1Njg2ZThmMjlkNjZiZmUwYzYuYmluZFBvcHVwKHBvcHVwXzMwOWY5NTkwYzgzZTQzZjVhNGM0MzA4NjQyMzhhNjg1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzlkNTQ5OTRmZjVhZjQ3OGNiYjAzNDkzZmNkNGQ0MDE2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODIxOTg2MTE4MTYzNDk0LC03My44MTM4ODUxNDQyODYxOV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80N2VjYjYzZDdmMjU0NDNlOGI0YTM5NWZkMDViYTZkMiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jMjU3NDBjYTRhYjI0MjA0ODcxYzI3NTQxMGY5ODBkMiA9ICQoJzxkaXYgaWQ9Imh0bWxfYzI1NzQwY2E0YWIyNDIwNDg3MWMyNzU0MTBmOTgwZDIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkVkZ2V3YXRlciBQYXJrLCBCcm9ueDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNDdlY2I2M2Q3ZjI1NDQzZThiNGEzOTVmZDA1YmE2ZDIuc2V0Q29udGVudChodG1sX2MyNTc0MGNhNGFiMjQyMDQ4NzFjMjc1NDEwZjk4MGQyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzlkNTQ5OTRmZjVhZjQ3OGNiYjAzNDkzZmNkNGQ0MDE2LmJpbmRQb3B1cChwb3B1cF80N2VjYjYzZDdmMjU0NDNlOGI0YTM5NWZkMDViYTZkMik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iODFjYTc3NmE5NTE0NzY2YmMxMGQyMTVlZDY2MzMzZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjgxOTAxNDM3Njk4ODMxNCwtNzMuODQ4MDI3Mjk1ODI3MzVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMTlkNmUzNjI0NzA3NDM4MDk1Y2NhYTRiNzgyZjVlYWQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMWU4ZjRlY2I0MDRiNGFmMTljZGU3ZWVjNmFjZjM3ODAgPSAkKCc8ZGl2IGlkPSJodG1sXzFlOGY0ZWNiNDA0YjRhZjE5Y2RlN2VlYzZhY2YzNzgwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DYXN0bGUgSGlsbCwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzE5ZDZlMzYyNDcwNzQzODA5NWNjYWE0Yjc4MmY1ZWFkLnNldENvbnRlbnQoaHRtbF8xZThmNGVjYjQwNGI0YWYxOWNkZTdlZWM2YWNmMzc4MCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9iODFjYTc3NmE5NTE0NzY2YmMxMGQyMTVlZDY2MzMzZC5iaW5kUG9wdXAocG9wdXBfMTlkNmUzNjI0NzA3NDM4MDk1Y2NhYTRiNzgyZjVlYWQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTI1YTE4MGQzOWUxNDk4NDkxZjE0OTcxYjYyYjM1MTUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44NzEzNzA3ODE5MjM3MSwtNzMuODYzMzIzNjE2NTI3NzddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNTBmOTBmZTA4NmM0NDJlYmI3OTEyYmEzNTgzNjkzZDggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNDQzMjhlNjQ1MGQ2NDcwYjlkZTJkMDY5M2M4YTI2YWIgPSAkKCc8ZGl2IGlkPSJodG1sXzQ0MzI4ZTY0NTBkNjQ3MGI5ZGUyZDA2OTNjOGEyNmFiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5PbGludmlsbGUsIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81MGY5MGZlMDg2YzQ0MmViYjc5MTJiYTM1ODM2OTNkOC5zZXRDb250ZW50KGh0bWxfNDQzMjhlNjQ1MGQ2NDcwYjlkZTJkMDY5M2M4YTI2YWIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNTI1YTE4MGQzOWUxNDk4NDkxZjE0OTcxYjYyYjM1MTUuYmluZFBvcHVwKHBvcHVwXzUwZjkwZmUwODZjNDQyZWJiNzkxMmJhMzU4MzY5M2Q4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzZkYjYzNGNhMTc0ZTQ4YjQ5MzBlMjBlNTBmOGE0MWJlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODYyOTY1NjI0Nzc5OTgsLTczLjg0MTYxMTk0ODMxMjIzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzg5OTY3MDJhZmMyYjQ3MzQ4NTAzNWE1NDNlMjQ5NDRlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2I4MzczYzUxMDYzNDQzZWU4OGRkNjUwNGE0NDEyZmVlID0gJCgnPGRpdiBpZD0iaHRtbF9iODM3M2M1MTA2MzQ0M2VlODhkZDY1MDRhNDQxMmZlZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UGVsaGFtIEdhcmRlbnMsIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84OTk2NzAyYWZjMmI0NzM0ODUwMzVhNTQzZTI0OTQ0ZS5zZXRDb250ZW50KGh0bWxfYjgzNzNjNTEwNjM0NDNlZTg4ZGQ2NTA0YTQ0MTJmZWUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNmRiNjM0Y2ExNzRlNDhiNDkzMGUyMGU1MGY4YTQxYmUuYmluZFBvcHVwKHBvcHVwXzg5OTY3MDJhZmMyYjQ3MzQ4NTAzNWE1NDNlMjQ5NDRlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzI3YzliZDRlNDBiZjQ0NWY4ZDI3N2E1ZTEyNzVjNTAxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODM0MjgzODA3MzM4NTEsLTczLjkxNTU4OTQxNzczNDQ0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzllZGI4ZmZkZTUyNjQ1Y2I4M2QzOWY2ZmM5OWVkYWM2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzQ5NWM0ZTYxZmY2OTRhNmRhYjcxNWU3YzdiYmY5MzM3ID0gJCgnPGRpdiBpZD0iaHRtbF80OTVjNGU2MWZmNjk0YTZkYWI3MTVlN2M3YmJmOTMzNyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q29uY291cnNlLCBCcm9ueDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOWVkYjhmZmRlNTI2NDVjYjgzZDM5ZjZmYzk5ZWRhYzYuc2V0Q29udGVudChodG1sXzQ5NWM0ZTYxZmY2OTRhNmRhYjcxNWU3YzdiYmY5MzM3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzI3YzliZDRlNDBiZjQ0NWY4ZDI3N2E1ZTEyNzVjNTAxLmJpbmRQb3B1cChwb3B1cF85ZWRiOGZmZGU1MjY0NWNiODNkMzlmNmZjOTllZGFjNik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jZjZhYmY4OWQ2ZmM0MzRiOTc4NzJhZGE3Y2I1ZDRmMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjgyOTc3NDI5Nzg3MTYxLC03My44NTA1MzUyNDQ1MTkzNV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80NmZmNjY2NTFkZGU0ODAzYmI0OGZkOGRhNDE5N2M4OSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8yZmM1MDQxZGNlOGY0YjVkOWJjMTFiN2Y4Y2YxYjdjMiA9ICQoJzxkaXYgaWQ9Imh0bWxfMmZjNTA0MWRjZThmNGI1ZDliYzExYjdmOGNmMWI3YzIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlVuaW9ucG9ydCwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzQ2ZmY2NjY1MWRkZTQ4MDNiYjQ4ZmQ4ZGE0MTk3Yzg5LnNldENvbnRlbnQoaHRtbF8yZmM1MDQxZGNlOGY0YjVkOWJjMTFiN2Y4Y2YxYjdjMik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jZjZhYmY4OWQ2ZmM0MzRiOTc4NzJhZGE3Y2I1ZDRmMi5iaW5kUG9wdXAocG9wdXBfNDZmZjY2NjUxZGRlNDgwM2JiNDhmZDhkYTQxOTdjODkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjVkZGY2NTRiZmE3NDk5MGE5NDVkMjExYWJhNTM1NWUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44ODQ1NjEzMDMwMzczMiwtNzMuODQ4MDgyNzE4NzcxNjhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfY2Q5Y2Q1NTVjYWIzNDJjNDk0Njc0NjA0NmYwMzBjYjMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMjJmNDcxZWRiMDJjNGEzYjkzNDZlYTA3Y2Y3ZjlkNDcgPSAkKCc8ZGl2IGlkPSJodG1sXzIyZjQ3MWVkYjAyYzRhM2I5MzQ2ZWEwN2NmN2Y5ZDQ3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FZGVud2FsZCwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2NkOWNkNTU1Y2FiMzQyYzQ5NDY3NDYwNDZmMDMwY2IzLnNldENvbnRlbnQoaHRtbF8yMmY0NzFlZGIwMmM0YTNiOTM0NmVhMDdjZjdmOWQ0Nyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9iNWRkZjY1NGJmYTc0OTkwYTk0NWQyMTFhYmE1MzU1ZS5iaW5kUG9wdXAocG9wdXBfY2Q5Y2Q1NTVjYWIzNDJjNDk0Njc0NjA0NmYwMzBjYjMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNjQ1MGY1NTA5ZWVjNDM0YmE5MGI3OWU4Mjg5Y2VkMTkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42MjU4MDEwNjUwMTA2NTYsLTc0LjAzMDYyMDY5MzUzODEzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzZkZDA4NDQ5OWNmZjQ2YTdiZGRjZWVjZjcxNTczY2U5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzhlOGEyNGYyZTM2NDQzMWY4YmRkYjBlNjc1MjU2MzIwID0gJCgnPGRpdiBpZD0iaHRtbF84ZThhMjRmMmUzNjQ0MzFmOGJkZGIwZTY3NTI1NjMyMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmF5IFJpZGdlLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNmRkMDg0NDk5Y2ZmNDZhN2JkZGNlZWNmNzE1NzNjZTkuc2V0Q29udGVudChodG1sXzhlOGEyNGYyZTM2NDQzMWY4YmRkYjBlNjc1MjU2MzIwKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzY0NTBmNTUwOWVlYzQzNGJhOTBiNzllODI4OWNlZDE5LmJpbmRQb3B1cChwb3B1cF82ZGQwODQ0OTljZmY0NmE3YmRkY2VlY2Y3MTU3M2NlOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jZjFiMTgwNGZlZDI0MTljOWNjMzA5YzM4NjkxMDYwMCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjYxMTAwODkwMjAyMDQ0LC03My45OTUxNzk5ODM4MDcyOV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9hZDEwNWE0OWMyYjM0N2Y5OWFiYTVjNGZhMzgzNTNkMSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jZjA0ZWM4ZTAxNTE0ZTUwYjFkOGVlMjAyNjgwYWRmZCA9ICQoJzxkaXYgaWQ9Imh0bWxfY2YwNGVjOGUwMTUxNGU1MGIxZDhlZTIwMjY4MGFkZmQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJlbnNvbmh1cnN0LCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYWQxMDVhNDljMmIzNDdmOTlhYmE1YzRmYTM4MzUzZDEuc2V0Q29udGVudChodG1sX2NmMDRlYzhlMDE1MTRlNTBiMWQ4ZWUyMDI2ODBhZGZkKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2NmMWIxODA0ZmVkMjQxOWM5Y2MzMDljMzg2OTEwNjAwLmJpbmRQb3B1cChwb3B1cF9hZDEwNWE0OWMyYjM0N2Y5OWFiYTVjNGZhMzgzNTNkMSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl85NTljZWFhZGNhN2Q0OWI2YjRhMDQ1YjVmZDRiYzNkYyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY0NTEwMjk0OTI1NDI5LC03NC4wMTAzMTYxODUyNzc4NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lMmU2OTVlOTQ3ODc0NWQ1YTUwZWJkOTRhNThkYzNmZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lODA2NWMwOTJjNWE0OTczOWJkNjFmZDAyMzVhMTA3MCA9ICQoJzxkaXYgaWQ9Imh0bWxfZTgwNjVjMDkyYzVhNDk3MzliZDYxZmQwMjM1YTEwNzAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlN1bnNldCBQYXJrLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZTJlNjk1ZTk0Nzg3NDVkNWE1MGViZDk0YTU4ZGMzZmUuc2V0Q29udGVudChodG1sX2U4MDY1YzA5MmM1YTQ5NzM5YmQ2MWZkMDIzNWExMDcwKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzk1OWNlYWFkY2E3ZDQ5YjZiNGEwNDViNWZkNGJjM2RjLmJpbmRQb3B1cChwb3B1cF9lMmU2OTVlOTQ3ODc0NWQ1YTUwZWJkOTRhNThkYzNmZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mMGRhN2FjY2FmNWY0ZjY0OWZlMzFkZTljMDczZGI5NCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjczMDIwMDk4NDg2NDcsLTczLjk1NDI0MDkzMTI3MzkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzdhOGZlNTFlNGUyODQ0NDY4MDA4Y2ViZjhiZWFlM2Q2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzk0ZDY3OTc2ODNhYzQ4M2ZiNGRhMzM2ZjVjMWMxNWRlID0gJCgnPGRpdiBpZD0iaHRtbF85NGQ2Nzk3NjgzYWM0ODNmYjRkYTMzNmY1YzFjMTVkZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+R3JlZW5wb2ludCwgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzdhOGZlNTFlNGUyODQ0NDY4MDA4Y2ViZjhiZWFlM2Q2LnNldENvbnRlbnQoaHRtbF85NGQ2Nzk3NjgzYWM0ODNmYjRkYTMzNmY1YzFjMTVkZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mMGRhN2FjY2FmNWY0ZjY0OWZlMzFkZTljMDczZGI5NC5iaW5kUG9wdXAocG9wdXBfN2E4ZmU1MWU0ZTI4NDQ0NjgwMDhjZWJmOGJlYWUzZDYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfY2YyZDY5MDJiY2IzNDU4NWIxYzhkNjYwMGYyNWQxZGYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC41OTUyNjAwMTMwNjU5MywtNzMuOTczNDcwODc3MDg0NDVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOTYzZWNmY2Q2MmYzNDNjNDk3ZjA0MjczYjA5ZjI0NDYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYWExZDFjOTViMWI2NDg0N2E1NTE0NTlkNTcwMTNlMGMgPSAkKCc8ZGl2IGlkPSJodG1sX2FhMWQxYzk1YjFiNjQ4NDdhNTUxNDU5ZDU3MDEzZTBjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5HcmF2ZXNlbmQsIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85NjNlY2ZjZDYyZjM0M2M0OTdmMDQyNzNiMDlmMjQ0Ni5zZXRDb250ZW50KGh0bWxfYWExZDFjOTViMWI2NDg0N2E1NTE0NTlkNTcwMTNlMGMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfY2YyZDY5MDJiY2IzNDU4NWIxYzhkNjYwMGYyNWQxZGYuYmluZFBvcHVwKHBvcHVwXzk2M2VjZmNkNjJmMzQzYzQ5N2YwNDI3M2IwOWYyNDQ2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2RjMDY4ZmMyMjdlMTQ0NGE4YWNhM2VlY2Q5YmI3ZDhlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTc2ODI1MDY1NjY2MDQsLTczLjk2NTA5NDQ4Nzg1MzM2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzhlZDY4NzgxYmU4MzQzOTY4ZWE2ZjNmNWVmZmZhN2I1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2Y2NjFhOTc2MzYwZDRhZWViN2E3NDJlYzFmYjNjNmI5ID0gJCgnPGRpdiBpZD0iaHRtbF9mNjYxYTk3NjM2MGQ0YWVlYjdhNzQyZWMxZmIzYzZiOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnJpZ2h0b24gQmVhY2gsIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84ZWQ2ODc4MWJlODM0Mzk2OGVhNmYzZjVlZmZmYTdiNS5zZXRDb250ZW50KGh0bWxfZjY2MWE5NzYzNjBkNGFlZWI3YTc0MmVjMWZiM2M2YjkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZGMwNjhmYzIyN2UxNDQ0YThhY2EzZWVjZDliYjdkOGUuYmluZFBvcHVwKHBvcHVwXzhlZDY4NzgxYmU4MzQzOTY4ZWE2ZjNmNWVmZmZhN2I1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2QyNzkxNzRlZGEzMTQyMWVhNTEwZjhjNTg2ZWQ3NzViID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTg2ODkwMTI2NzgzODQsLTczLjk0MzE4NjQwNDgyOTc5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2E4ZGM2NmEwZWY2YTQyOTVhMjg0YTYwZDJjYjUwOGI5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzkzZDliYzRkMTFkODQyMzliNDZlYmRlYTJhMTgwMzE5ID0gJCgnPGRpdiBpZD0iaHRtbF85M2Q5YmM0ZDExZDg0MjM5YjQ2ZWJkZWEyYTE4MDMxOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U2hlZXBzaGVhZCBCYXksIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hOGRjNjZhMGVmNmE0Mjk1YTI4NGE2MGQyY2I1MDhiOS5zZXRDb250ZW50KGh0bWxfOTNkOWJjNGQxMWQ4NDIzOWI0NmViZGVhMmExODAzMTkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZDI3OTE3NGVkYTMxNDIxZWE1MTBmOGM1ODZlZDc3NWIuYmluZFBvcHVwKHBvcHVwX2E4ZGM2NmEwZWY2YTQyOTVhMjg0YTYwZDJjYjUwOGI5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzdiNzNmZDg0YWEwMjRmNzJiMDRiMWVkOWI0MjdjYzUzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjE0NDMyNTEzMzUwOTgsLTczLjk1NzQzODQwNTU5OTM5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzdlYTc5YmE1NWU2YTRlNWZhMTU1MTA3NTQ3NmUwYjg3ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzYzNDdjMGIyOGVjNTQ3NThhOGEyYzQ0MjRjYmE0N2I5ID0gJCgnPGRpdiBpZD0iaHRtbF82MzQ3YzBiMjhlYzU0NzU4YThhMmM0NDI0Y2JhNDdiOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TWFuaGF0dGFuIFRlcnJhY2UsIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83ZWE3OWJhNTVlNmE0ZTVmYTE1NTEwNzU0NzZlMGI4Ny5zZXRDb250ZW50KGh0bWxfNjM0N2MwYjI4ZWM1NDc1OGE4YTJjNDQyNGNiYTQ3YjkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfN2I3M2ZkODRhYTAyNGY3MmIwNGIxZWQ5YjQyN2NjNTMuYmluZFBvcHVwKHBvcHVwXzdlYTc5YmE1NWU2YTRlNWZhMTU1MTA3NTQ3NmUwYjg3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzA2ZTI4MGEzZDQ0NjQwZTg5ZjUxMTNjOWMxZjBmNGViID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjM2MzI1ODkwMjY2NzcsLTczLjk1ODQwMTA2NTMzOTAzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzhjMDlhZDliNzkzZTQyYzk4YWZlNWI5Mzk1YzM1Y2IyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2M4MmEwM2JkYWEzMjQ3ZWViY2E3Y2MyOWVjY2M5N2MzID0gJCgnPGRpdiBpZD0iaHRtbF9jODJhMDNiZGFhMzI0N2VlYmNhN2NjMjllY2NjOTdjMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RmxhdGJ1c2gsIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84YzA5YWQ5Yjc5M2U0MmM5OGFmZTViOTM5NWMzNWNiMi5zZXRDb250ZW50KGh0bWxfYzgyYTAzYmRhYTMyNDdlZWJjYTdjYzI5ZWNjYzk3YzMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMDZlMjgwYTNkNDQ2NDBlODlmNTExM2M5YzFmMGY0ZWIuYmluZFBvcHVwKHBvcHVwXzhjMDlhZDliNzkzZTQyYzk4YWZlNWI5Mzk1YzM1Y2IyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2RiNmU0OWZkZjc5NjRmZTk4MzA4ZDYxY2U4ODM2MGYyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjcwODI5MTc2OTUyOTQsLTczLjk0MzI5MTE5MDczNTgyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzFlOWM0ZTZmYmZjNTRhYmNiZTBkMmUzYmRkZjY1ZTg3ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2ViZjE1ODk3MjU4ZTRkYzJhNWZlY2Q5ODU2MmQxN2JmID0gJCgnPGRpdiBpZD0iaHRtbF9lYmYxNTg5NzI1OGU0ZGMyYTVmZWNkOTg1NjJkMTdiZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q3Jvd24gSGVpZ2h0cywgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzFlOWM0ZTZmYmZjNTRhYmNiZTBkMmUzYmRkZjY1ZTg3LnNldENvbnRlbnQoaHRtbF9lYmYxNTg5NzI1OGU0ZGMyYTVmZWNkOTg1NjJkMTdiZik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9kYjZlNDlmZGY3OTY0ZmU5ODMwOGQ2MWNlODgzNjBmMi5iaW5kUG9wdXAocG9wdXBfMWU5YzRlNmZiZmM1NGFiY2JlMGQyZTNiZGRmNjVlODcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMjkzMTY5YTBlZjk4NGRkYmFkNDVkYTBmZWM4NTY0NzUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42NDE3MTc3NjY2ODk2MSwtNzMuOTM2MTAyNTYxODU4MzZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNmJjY2FkMTdkN2Y2NGMxM2JjMWIyM2NkOTQ3ZDQ2Y2MgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNGE4MThiYTlkNDhkNDhlNTljNTYxMTk1ZTczN2M2MWEgPSAkKCc8ZGl2IGlkPSJodG1sXzRhODE4YmE5ZDQ4ZDQ4ZTU5YzU2MTE5NWU3MzdjNjFhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FYXN0IEZsYXRidXNoLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNmJjY2FkMTdkN2Y2NGMxM2JjMWIyM2NkOTQ3ZDQ2Y2Muc2V0Q29udGVudChodG1sXzRhODE4YmE5ZDQ4ZDQ4ZTU5YzU2MTE5NWU3MzdjNjFhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzI5MzE2OWEwZWY5ODRkZGJhZDQ1ZGEwZmVjODU2NDc1LmJpbmRQb3B1cChwb3B1cF82YmNjYWQxN2Q3ZjY0YzEzYmMxYjIzY2Q5NDdkNDZjYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84NjNhNTkzZTRkYTM0ODBhOTA1ZDk4ZGEyNjRlNzVkZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY0MjM4MTk1ODAwMzUyNiwtNzMuOTgwNDIxMTA1NTk0NzRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMGU0ZmJmOTg2Y2I3NDRlZThkZmM1ODE5YTgxMTU2YzMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMjY3YTEzYzcyOTQzNGNhNmE5YWYzNTM3MWJiYjAwNWIgPSAkKCc8ZGl2IGlkPSJodG1sXzI2N2ExM2M3Mjk0MzRjYTZhOWFmMzUzNzFiYmIwMDViIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5LZW5zaW5ndG9uLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMGU0ZmJmOTg2Y2I3NDRlZThkZmM1ODE5YTgxMTU2YzMuc2V0Q29udGVudChodG1sXzI2N2ExM2M3Mjk0MzRjYTZhOWFmMzUzNzFiYmIwMDViKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzg2M2E1OTNlNGRhMzQ4MGE5MDVkOThkYTI2NGU3NWRkLmJpbmRQb3B1cChwb3B1cF8wZTRmYmY5ODZjYjc0NGVlOGRmYzU4MTlhODExNTZjMyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yMGRjMDZjZjFlNjQ0OWE5OTI1ZWNmYTY0MDFhYmRhOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY1Njk0NTgzNTc1MTA0LC03My45ODAwNzM0MDQzMDE3Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82YjgwNTQwMmM5ODY0OWVmOTVlODljZWEzYjJjMGY2ZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF84YWM1YjRmNTZiMTg0NzY2OGQ0YTFjYzk4MjY5YzRmYSA9ICQoJzxkaXYgaWQ9Imh0bWxfOGFjNWI0ZjU2YjE4NDc2NjhkNGExY2M5ODI2OWM0ZmEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldpbmRzb3IgVGVycmFjZSwgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzZiODA1NDAyYzk4NjQ5ZWY5NWU4OWNlYTNiMmMwZjZkLnNldENvbnRlbnQoaHRtbF84YWM1YjRmNTZiMTg0NzY2OGQ0YTFjYzk4MjY5YzRmYSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yMGRjMDZjZjFlNjQ0OWE5OTI1ZWNmYTY0MDFhYmRhOS5iaW5kUG9wdXAocG9wdXBfNmI4MDU0MDJjOTg2NDllZjk1ZTg5Y2VhM2IyYzBmNmQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNzIyNjdjNzIxYThiNDRmN2EyMjc1YWFkMmI5N2M5NzIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42NzY4MjIyNjIyNTQ3MjQsLTczLjk2NDg1OTI0MjYyNjldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfM2RiNWEyY2QxMGE4NDBjZDg2YTk1YWM1MzA4OTBmNWQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNDc5YTkwZmE4ZjM3NDQ0YTk0MTc1YTUwYzY4YjgzY2UgPSAkKCc8ZGl2IGlkPSJodG1sXzQ3OWE5MGZhOGYzNzQ0NGE5NDE3NWE1MGM2OGI4M2NlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Qcm9zcGVjdCBIZWlnaHRzLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfM2RiNWEyY2QxMGE4NDBjZDg2YTk1YWM1MzA4OTBmNWQuc2V0Q29udGVudChodG1sXzQ3OWE5MGZhOGYzNzQ0NGE5NDE3NWE1MGM2OGI4M2NlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzcyMjY3YzcyMWE4YjQ0ZjdhMjI3NWFhZDJiOTdjOTcyLmJpbmRQb3B1cChwb3B1cF8zZGI1YTJjZDEwYTg0MGNkODZhOTVhYzUzMDg5MGY1ZCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lOTBjZDhhNzk5MDM0NDI1YjJmOWMxZTU4YzdjMzQwZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY2Mzk0OTk0MzM5NzU1LC03My45MTAyMzUzNjE3NjYwN10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83YjA4ZDEwZGFlYmI0NzJlYjNlYmY3NDZkYTYwNmI2OSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82NWU5ZDYyMzcxODg0NWE5OWQ0Y2I2MThlMzg4YzFhNSA9ICQoJzxkaXYgaWQ9Imh0bWxfNjVlOWQ2MjM3MTg4NDVhOTlkNGNiNjE4ZTM4OGMxYTUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJyb3duc3ZpbGxlLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfN2IwOGQxMGRhZWJiNDcyZWIzZWJmNzQ2ZGE2MDZiNjkuc2V0Q29udGVudChodG1sXzY1ZTlkNjIzNzE4ODQ1YTk5ZDRjYjYxOGUzODhjMWE1KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2U5MGNkOGE3OTkwMzQ0MjViMmY5YzFlNThjN2MzNDBkLmJpbmRQb3B1cChwb3B1cF83YjA4ZDEwZGFlYmI0NzJlYjNlYmY3NDZkYTYwNmI2OSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80NWNhMDg4YzA1Zjk0MWE4YTNhNDYzZTQ0YzA5NTIyYyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcwNzE0NDM5MzQ0MjUxLC03My45NTgxMTUyOTIyMDkyN10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83ZDI4NDA3ZGJhMjE0YTU3YWUyODkxYzg4ZTM4NGVkMSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wOTExYzExZTc1YzQ0YjY1YWQwN2Q2ZTRkMDQxZWUxMyA9ICQoJzxkaXYgaWQ9Imh0bWxfMDkxMWMxMWU3NWM0NGI2NWFkMDdkNmU0ZDA0MWVlMTMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldpbGxpYW1zYnVyZywgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzdkMjg0MDdkYmEyMTRhNTdhZTI4OTFjODhlMzg0ZWQxLnNldENvbnRlbnQoaHRtbF8wOTExYzExZTc1YzQ0YjY1YWQwN2Q2ZTRkMDQxZWUxMyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80NWNhMDg4YzA1Zjk0MWE4YTNhNDYzZTQ0YzA5NTIyYy5iaW5kUG9wdXAocG9wdXBfN2QyODQwN2RiYTIxNGE1N2FlMjg5MWM4OGUzODRlZDEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYWU2NjExNzZmZmFiNDdjZWE3ZTQzMjI4OTRkYzEzMGEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42OTgxMTYxMTAxNzkwMSwtNzMuOTI1MjU3OTc0ODcwNDVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzBlNzlkZjc0NWU0NGZjNmI2MTI2NGIxMzRiNDgzYWIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDcwYzk0ODlkOWQ2NGZjZGIyYzc4NGYyZTA0ZThjY2UgPSAkKCc8ZGl2IGlkPSJodG1sX2Q3MGM5NDg5ZDlkNjRmY2RiMmM3ODRmMmUwNGU4Y2NlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CdXNod2ljaywgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzMwZTc5ZGY3NDVlNDRmYzZiNjEyNjRiMTM0YjQ4M2FiLnNldENvbnRlbnQoaHRtbF9kNzBjOTQ4OWQ5ZDY0ZmNkYjJjNzg0ZjJlMDRlOGNjZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hZTY2MTE3NmZmYWI0N2NlYTdlNDMyMjg5NGRjMTMwYS5iaW5kUG9wdXAocG9wdXBfMzBlNzlkZjc0NWU0NGZjNmI2MTI2NGIxMzRiNDgzYWIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMDI3MmU2MTdmNDUyNGE2NWI0YTQzZjg0N2Q0NGJlODEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42ODcyMzE2MDc3MjA0NTYsLTczLjk0MTc4NDg4NjkwMjk3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzVjYjg4ZTEyNzgxMjRlMzZhNzc3MzZmNmVkZjE1MjYwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2IyYmQ1ZTc5Yjk5NjQwMjViYzdkNjFmZDRhZGFhZGEyID0gJCgnPGRpdiBpZD0iaHRtbF9iMmJkNWU3OWI5OTY0MDI1YmM3ZDYxZmQ0YWRhYWRhMiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmVkZm9yZCBTdHV5dmVzYW50LCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNWNiODhlMTI3ODEyNGUzNmE3NzczNmY2ZWRmMTUyNjAuc2V0Q29udGVudChodG1sX2IyYmQ1ZTc5Yjk5NjQwMjViYzdkNjFmZDRhZGFhZGEyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzAyNzJlNjE3ZjQ1MjRhNjViNGE0M2Y4NDdkNDRiZTgxLmJpbmRQb3B1cChwb3B1cF81Y2I4OGUxMjc4MTI0ZTM2YTc3NzM2ZjZlZGYxNTI2MCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iMzMyMmI2OTQ4NzU0YTM0YjM3ODE2NmY1YTNmYmUzNiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY5NTg2MzcyMjcyNDA4NCwtNzMuOTkzNzgyMjU0OTY0MjRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOGU2ZGIxNjcwZGU0NGI1M2I0NGM5N2EzMGFiNDEyNDYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYjFlYTFkOGM5ZDRmNDM4Zjk5NTJjYWUyN2VlNGFlNjcgPSAkKCc8ZGl2IGlkPSJodG1sX2IxZWExZDhjOWQ0ZjQzOGY5OTUyY2FlMjdlZTRhZTY3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ccm9va2x5biBIZWlnaHRzLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOGU2ZGIxNjcwZGU0NGI1M2I0NGM5N2EzMGFiNDEyNDYuc2V0Q29udGVudChodG1sX2IxZWExZDhjOWQ0ZjQzOGY5OTUyY2FlMjdlZTRhZTY3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2IzMzIyYjY5NDg3NTRhMzRiMzc4MTY2ZjVhM2ZiZTM2LmJpbmRQb3B1cChwb3B1cF84ZTZkYjE2NzBkZTQ0YjUzYjQ0Yzk3YTMwYWI0MTI0Nik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hNDI0MzRkMjlkYzA0ZTAxYTU4MzZkNTNmMzRmNWQ3ZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY4NzkxOTcyMjQ4NTU3NCwtNzMuOTk4NTYxMzkyMTg0NjNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYjE2MzhiMThlMDM3NDY2Mjk5NmIzYmZkODE1ODE0ZDAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfODg3NzVlYzBkNmUwNGU3MjljYmQyYmNiODMxNGM1NTkgPSAkKCc8ZGl2IGlkPSJodG1sXzg4Nzc1ZWMwZDZlMDRlNzI5Y2JkMmJjYjgzMTRjNTU5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Db2JibGUgSGlsbCwgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2IxNjM4YjE4ZTAzNzQ2NjI5OTZiM2JmZDgxNTgxNGQwLnNldENvbnRlbnQoaHRtbF84ODc3NWVjMGQ2ZTA0ZTcyOWNiZDJiY2I4MzE0YzU1OSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hNDI0MzRkMjlkYzA0ZTAxYTU4MzZkNTNmMzRmNWQ3ZC5iaW5kUG9wdXAocG9wdXBfYjE2MzhiMThlMDM3NDY2Mjk5NmIzYmZkODE1ODE0ZDApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNzQ0NjdiN2ZjNmQ2NGU2NDkyZmVhNjRiZTYzN2E2YjQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42ODA1NDAyMzEwNzY0ODUsLTczLjk5NDY1MzcyODI4MDA2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzMwZjY2NjRmZDRmZTRiMGFiZWZlNzg1NTMxYjk1NzkyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzVjYzJiNTQ1OGRhMjRmYWRiODU4YjRmMWJmZTdiZDM0ID0gJCgnPGRpdiBpZD0iaHRtbF81Y2MyYjU0NThkYTI0ZmFkYjg1OGI0ZjFiZmU3YmQzNCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q2Fycm9sbCBHYXJkZW5zLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzBmNjY2NGZkNGZlNGIwYWJlZmU3ODU1MzFiOTU3OTIuc2V0Q29udGVudChodG1sXzVjYzJiNTQ1OGRhMjRmYWRiODU4YjRmMWJmZTdiZDM0KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzc0NDY3YjdmYzZkNjRlNjQ5MmZlYTY0YmU2MzdhNmI0LmJpbmRQb3B1cChwb3B1cF8zMGY2NjY0ZmQ0ZmU0YjBhYmVmZTc4NTUzMWI5NTc5Mik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iMTYyZmI1MTgzODk0OGRlOTIyMmU3YjdiNDRlODA0ZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY3NjI1MzIzMDI1MDg4NiwtNzQuMDEyNzU4OTc0NzM1Nl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lNGUxOWEwYTE1ZTM0NGZkOTQ4MWQ0ZWU5YjM0ZGJiYyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xMmM3OWMwYjg4ZTM0OTc5OTFiMWM2ODc1YmE3ODNhNiA9ICQoJzxkaXYgaWQ9Imh0bWxfMTJjNzljMGI4OGUzNDk3OTkxYjFjNjg3NWJhNzgzYTYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJlZCBIb29rLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZTRlMTlhMGExNWUzNDRmZDk0ODFkNGVlOWIzNGRiYmMuc2V0Q29udGVudChodG1sXzEyYzc5YzBiODhlMzQ5Nzk5MWIxYzY4NzViYTc4M2E2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2IxNjJmYjUxODM4OTQ4ZGU5MjIyZTdiN2I0NGU4MDRlLmJpbmRQb3B1cChwb3B1cF9lNGUxOWEwYTE1ZTM0NGZkOTQ4MWQ0ZWU5YjM0ZGJiYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kZDcxZDU1NWJjZjI0ZDdhYjkxYmJkZTQwNmZiYjNlOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY3MzkzMTE0MzE4NzE1NCwtNzMuOTk0NDQwODcxNDUzMzldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfODAxNDIyNDQ3MjIwNGZiNTlhNzYzNDVlMTY0NTJjNzYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNDE5MmZhNDM1YzZkNDQwMGI0YmI1OThlODcxZmNiNjYgPSAkKCc8ZGl2IGlkPSJodG1sXzQxOTJmYTQzNWM2ZDQ0MDBiNGJiNTk4ZTg3MWZjYjY2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Hb3dhbnVzLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfODAxNDIyNDQ3MjIwNGZiNTlhNzYzNDVlMTY0NTJjNzYuc2V0Q29udGVudChodG1sXzQxOTJmYTQzNWM2ZDQ0MDBiNGJiNTk4ZTg3MWZjYjY2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2RkNzFkNTU1YmNmMjRkN2FiOTFiYmRlNDA2ZmJiM2U5LmJpbmRQb3B1cChwb3B1cF84MDE0MjI0NDcyMjA0ZmI1OWE3NjM0NWUxNjQ1MmM3Nik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kMzQwMGQyMmY5N2E0NTg1OWNmNTFiNjllZGQ5Y2Q1MSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY4ODUyNzI2MDE4OTc3LC03My45NzI5MDU3NDM2OTA5Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kNDJlNmYzNjJjMWE0NWI1ODFmZGQ5NDYwMzUzMGZhNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iMTA5YjJlMDI4Mzc0YTk3OTNlYzk2ZGU0MTQ4N2FlMCA9ICQoJzxkaXYgaWQ9Imh0bWxfYjEwOWIyZTAyODM3NGE5NzkzZWM5NmRlNDE0ODdhZTAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZvcnQgR3JlZW5lLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZDQyZTZmMzYyYzFhNDViNTgxZmRkOTQ2MDM1MzBmYTcuc2V0Q29udGVudChodG1sX2IxMDliMmUwMjgzNzRhOTc5M2VjOTZkZTQxNDg3YWUwKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2QzNDAwZDIyZjk3YTQ1ODU5Y2Y1MWI2OWVkZDljZDUxLmJpbmRQb3B1cChwb3B1cF9kNDJlNmYzNjJjMWE0NWI1ODFmZGQ5NDYwMzUzMGZhNyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84OTdkMzg4YjQxOWE0MjMwYTkzOGY5MjU5MTBiYjUyNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY3MjMyMDUyMjY4MTk3LC03My45NzcwNTAzMDE4MzkyNF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wYmI4MzhiOTIzZjc0NGUwOGY3YTRmYzBkZWU5NTFhZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iMjkyN2UzNDFkODE0MDU4YWUwNDdiMTY2ODk0MTg4NSA9ICQoJzxkaXYgaWQ9Imh0bWxfYjI5MjdlMzQxZDgxNDA1OGFlMDQ3YjE2Njg5NDE4ODUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlBhcmsgU2xvcGUsIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wYmI4MzhiOTIzZjc0NGUwOGY3YTRmYzBkZWU5NTFhZS5zZXRDb250ZW50KGh0bWxfYjI5MjdlMzQxZDgxNDA1OGFlMDQ3YjE2Njg5NDE4ODUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODk3ZDM4OGI0MTlhNDIzMGE5MzhmOTI1OTEwYmI1MjcuYmluZFBvcHVwKHBvcHVwXzBiYjgzOGI5MjNmNzQ0ZTA4ZjdhNGZjMGRlZTk1MWFlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2FhZTJiOWZmMDE2YTRhN2ViNDBlMTYzZTcwZDczYTNhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjgyMzkxMDExNDQyMTEsLTczLjg3NjYxNTk2NDU3Mjk2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzhjZmIzN2I2NTU4ZjQxMWJhNWUxMDdkYTZlZjM0YzEwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2MxOWUxNTA3NTA0MzRlMTZhZDEzZmZkYjQ3MGM5NjRkID0gJCgnPGRpdiBpZD0iaHRtbF9jMTllMTUwNzUwNDM0ZTE2YWQxM2ZmZGI0NzBjOTY0ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q3lwcmVzcyBIaWxscywgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzhjZmIzN2I2NTU4ZjQxMWJhNWUxMDdkYTZlZjM0YzEwLnNldENvbnRlbnQoaHRtbF9jMTllMTUwNzUwNDM0ZTE2YWQxM2ZmZGI0NzBjOTY0ZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hYWUyYjlmZjAxNmE0YTdlYjQwZTE2M2U3MGQ3M2EzYS5iaW5kUG9wdXAocG9wdXBfOGNmYjM3YjY1NThmNDExYmE1ZTEwN2RhNmVmMzRjMTApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjM1NGRkYTNkZjRlNDljOTlmNDFhMzRkNWIzOGU0ZjggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42Njk5MjU3MDA4NDcwNDUsLTczLjg4MDY5ODYzOTE3MzY2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2E3NWUxODE5NTcxOTRlMjA5MzM1MjVmY2FmN2Q5NzI2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2VmNjEzMjIzZjYxODRmYzA5YTRlMjE5ZTMxYTViMjVmID0gJCgnPGRpdiBpZD0iaHRtbF9lZjYxMzIyM2Y2MTg0ZmMwOWE0ZTIxOWUzMWE1YjI1ZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RWFzdCBOZXcgWW9yaywgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2E3NWUxODE5NTcxOTRlMjA5MzM1MjVmY2FmN2Q5NzI2LnNldENvbnRlbnQoaHRtbF9lZjYxMzIyM2Y2MTg0ZmMwOWE0ZTIxOWUzMWE1YjI1Zik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mMzU0ZGRhM2RmNGU0OWM5OWY0MWEzNGQ1YjM4ZTRmOC5iaW5kUG9wdXAocG9wdXBfYTc1ZTE4MTk1NzE5NGUyMDkzMzUyNWZjYWY3ZDk3MjYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOTI0MDA1ZWFiNjA0NDcxMDkyMDg5OGY1OWEwMmYzOTggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42NDc1ODkwNTIzMDg3NCwtNzMuODc5MzY5NzAwNDU4NzVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMjY4Y2E0ZDdiM2IwNDJmNWIxYzc4ODVkNjI3Zjg4ZWUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZGU2OGI3N2NhNGE3NGY3NzkxOTA5NDEwOTA2MzllZGYgPSAkKCc8ZGl2IGlkPSJodG1sX2RlNjhiNzdjYTRhNzRmNzc5MTkwOTQxMDkwNjM5ZWRmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TdGFycmV0dCBDaXR5LCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjY4Y2E0ZDdiM2IwNDJmNWIxYzc4ODVkNjI3Zjg4ZWUuc2V0Q29udGVudChodG1sX2RlNjhiNzdjYTRhNzRmNzc5MTkwOTQxMDkwNjM5ZWRmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzkyNDAwNWVhYjYwNDQ3MTA5MjA4OThmNTlhMDJmMzk4LmJpbmRQb3B1cChwb3B1cF8yNjhjYTRkN2IzYjA0MmY1YjFjNzg4NWQ2MjdmODhlZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82ZWI5YTM1ZjU0MTI0MWQzOWI3ZTU0OGM2N2IwODM5NyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjYzNTU2NDMyNzk3NDI4LC03My45MDIwOTI2OTc3ODk2Nl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iNGQ5NzZlMTQ4YTE0ODAzYTdjMjIxMGEwYTJmNzM5NyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80MmQ1NjlhMGY2OGI0NzM4YmUxZGJmNjRiZWU3NjFlYiA9ICQoJzxkaXYgaWQ9Imh0bWxfNDJkNTY5YTBmNjhiNDczOGJlMWRiZjY0YmVlNzYxZWIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNhbmFyc2llLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjRkOTc2ZTE0OGExNDgwM2E3YzIyMTBhMGEyZjczOTcuc2V0Q29udGVudChodG1sXzQyZDU2OWEwZjY4YjQ3MzhiZTFkYmY2NGJlZTc2MWViKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzZlYjlhMzVmNTQxMjQxZDM5YjdlNTQ4YzY3YjA4Mzk3LmJpbmRQb3B1cChwb3B1cF9iNGQ5NzZlMTQ4YTE0ODAzYTdjMjIxMGEwYTJmNzM5Nyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mNDI3MmMwMTY3NTc0ZWQ5OWFlZGI1MzRmZDM0MTA5YiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjYzMDQ0NjA0Mzc1NzQ2NiwtNzMuOTI5MTEzMDI2NDQ2NzRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMjMwZDU4MzUzZmNhNDc0Y2FjNWIxYTgxMGE5OWZlZGUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfODgwYThiNGEzODIxNDBjNzk4MzZmZGY4OWU1Njg0YWMgPSAkKCc8ZGl2IGlkPSJodG1sXzg4MGE4YjRhMzgyMTQwYzc5ODM2ZmRmODllNTY4NGFjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5GbGF0bGFuZHMsIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yMzBkNTgzNTNmY2E0NzRjYWM1YjFhODEwYTk5ZmVkZS5zZXRDb250ZW50KGh0bWxfODgwYThiNGEzODIxNDBjNzk4MzZmZGY4OWU1Njg0YWMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjQyNzJjMDE2NzU3NGVkOTlhZWRiNTM0ZmQzNDEwOWIuYmluZFBvcHVwKHBvcHVwXzIzMGQ1ODM1M2ZjYTQ3NGNhYzViMWE4MTBhOTlmZWRlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzA1NzhkN2VmOTkwZDRmNTE4Y2FjNWRjOGE3ZGQ0NjEyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjA2MzM2NDIxNjg1NjI2LC03My45MDgxODU3MTc3NzQyM10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kM2VjMGY4NmU1YjA0ZmYxOTMyZjU2ODQ1OWRjZjkwNSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80NWU3ZDUwNDY1NzQ0MDJkODU4NzU0NGMzYTJhNWIxZiA9ICQoJzxkaXYgaWQ9Imh0bWxfNDVlN2Q1MDQ2NTc0NDAyZDg1ODc1NDRjM2EyYTViMWYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1pbGwgSXNsYW5kLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZDNlYzBmODZlNWIwNGZmMTkzMmY1Njg0NTlkY2Y5MDUuc2V0Q29udGVudChodG1sXzQ1ZTdkNTA0NjU3NDQwMmQ4NTg3NTQ0YzNhMmE1YjFmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzA1NzhkN2VmOTkwZDRmNTE4Y2FjNWRjOGE3ZGQ0NjEyLmJpbmRQb3B1cChwb3B1cF9kM2VjMGY4NmU1YjA0ZmYxOTMyZjU2ODQ1OWRjZjkwNSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kY2JiYzRkZWNlZTQ0MmJmOGQyODg3MzFjN2IyNjAyNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjU3NzkxMzUwMzA4NjU3LC03My45NDM1MzcyMjg5MTg4Nl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iYWQyOWEyYWMyNGE0ZTEwOWNjN2QwYjA2N2QzNGJhNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85NzFkMDlmNDNjYjY0YWZiODdjZTY5ZjAxY2M3OTI4MyA9ICQoJzxkaXYgaWQ9Imh0bWxfOTcxZDA5ZjQzY2I2NGFmYjg3Y2U2OWYwMWNjNzkyODMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1hbmhhdHRhbiBCZWFjaCwgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2JhZDI5YTJhYzI0YTRlMTA5Y2M3ZDBiMDY3ZDM0YmE3LnNldENvbnRlbnQoaHRtbF85NzFkMDlmNDNjYjY0YWZiODdjZTY5ZjAxY2M3OTI4Myk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9kY2JiYzRkZWNlZTQ0MmJmOGQyODg3MzFjN2IyNjAyNC5iaW5kUG9wdXAocG9wdXBfYmFkMjlhMmFjMjRhNGUxMDljYzdkMGIwNjdkMzRiYTcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNGU3NGIxNmQwYjQ3NDliMzhiMjZhMjNiMzlhNTdlZTQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC41NzQyOTI1NjQ3MTYwMSwtNzMuOTg4NjgyOTU4MjE2MzddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZWNmYWE1Y2U5ZWE0NGU0Mzg0MDUxYzQ0NjZhNTdkNDEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMTU0NDI0NmIzYmViNDc2MTlhMjc0OTdkN2E1Zjk5NzQgPSAkKCc8ZGl2IGlkPSJodG1sXzE1NDQyNDZiM2JlYjQ3NjE5YTI3NDk3ZDdhNWY5OTc0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Db25leSBJc2xhbmQsIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lY2ZhYTVjZTllYTQ0ZTQzODQwNTFjNDQ2NmE1N2Q0MS5zZXRDb250ZW50KGh0bWxfMTU0NDI0NmIzYmViNDc2MTlhMjc0OTdkN2E1Zjk5NzQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNGU3NGIxNmQwYjQ3NDliMzhiMjZhMjNiMzlhNTdlZTQuYmluZFBvcHVwKHBvcHVwX2VjZmFhNWNlOWVhNDRlNDM4NDA1MWM0NDY2YTU3ZDQxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQ1ZDg0NzJkMGM0YjRkMDg5MzMyYzc3NGU1MmYxODJiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTk5NTE4NzAyODIyMzgsLTczLjk5ODc1MjIxNDQzNTE5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzIzNmRlMmI1ZDk1ODRiYmY4ZDQwNmZiODlmZTk3NDg5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzIwMjM2ZGY5YWQ4ZDRiZDE5ODBiZjg0NjAzOTdlOTk5ID0gJCgnPGRpdiBpZD0iaHRtbF8yMDIzNmRmOWFkOGQ0YmQxOTgwYmY4NDYwMzk3ZTk5OSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmF0aCBCZWFjaCwgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzIzNmRlMmI1ZDk1ODRiYmY4ZDQwNmZiODlmZTk3NDg5LnNldENvbnRlbnQoaHRtbF8yMDIzNmRmOWFkOGQ0YmQxOTgwYmY4NDYwMzk3ZTk5OSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80NWQ4NDcyZDBjNGI0ZDA4OTMzMmM3NzRlNTJmMTgyYi5iaW5kUG9wdXAocG9wdXBfMjM2ZGUyYjVkOTU4NGJiZjhkNDA2ZmI4OWZlOTc0ODkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMTI0YTQwMDcyY2U5NGI1YWFlMjU4NmE0MjEwNWQ0NzIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42MzMxMzA1MTI3NTgwMTUsLTczLjk5MDQ5ODIzMDQ0ODExXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzg0MWQxYzU1MzBjNjQ5MzY4ZjMzMmU4MDRkNGJlMjQyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2I3YjI4MWU1MWEwMTRkNzNiZDgwZTY0MGMzYzY3ZjMyID0gJCgnPGRpdiBpZD0iaHRtbF9iN2IyODFlNTFhMDE0ZDczYmQ4MGU2NDBjM2M2N2YzMiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Qm9yb3VnaCBQYXJrLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfODQxZDFjNTUzMGM2NDkzNjhmMzMyZTgwNGQ0YmUyNDIuc2V0Q29udGVudChodG1sX2I3YjI4MWU1MWEwMTRkNzNiZDgwZTY0MGMzYzY3ZjMyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzEyNGE0MDA3MmNlOTRiNWFhZTI1ODZhNDIxMDVkNDcyLmJpbmRQb3B1cChwb3B1cF84NDFkMWM1NTMwYzY0OTM2OGYzMzJlODA0ZDRiZTI0Mik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xZGU3ZDIwN2UxOTQ0ZmUyODEwZGYyOWIxMTBkZjI4ZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjYxOTIxOTQ1NzcyMjYzNiwtNzQuMDE5MzEzNzU2MzYwMjJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNDIwYWIyZjgzY2Q5NGE4OTljNjE3NmVmYmQyOGRkOWEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjZjN2Y4ZmUyODg1NDI4ZGFiNzlmYjk3M2Q3M2FhYjggPSAkKCc8ZGl2IGlkPSJodG1sX2Y2YzdmOGZlMjg4NTQyOGRhYjc5ZmI5NzNkNzNhYWI4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5EeWtlciBIZWlnaHRzLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNDIwYWIyZjgzY2Q5NGE4OTljNjE3NmVmYmQyOGRkOWEuc2V0Q29udGVudChodG1sX2Y2YzdmOGZlMjg4NTQyOGRhYjc5ZmI5NzNkNzNhYWI4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzFkZTdkMjA3ZTE5NDRmZTI4MTBkZjI5YjExMGRmMjhmLmJpbmRQb3B1cChwb3B1cF80MjBhYjJmODNjZDk0YTg5OWM2MTc2ZWZiZDI4ZGQ5YSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zZTI4NjlkYTdmOGI0NTFhODgzZTY3NDFiMzRlYTE5YyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjU5MDg0ODQzMzkwMjA0NiwtNzMuOTMwMTAxNzA2OTExOTZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfM2EzZmUzZWY3NjcxNDIwZWIxNTAwMGFkM2UzYmYxMWUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMTE0MmE0NjEyZGMzNDFkMGJkY2NjMzYyYjYyNGYzZGEgPSAkKCc8ZGl2IGlkPSJodG1sXzExNDJhNDYxMmRjMzQxZDBiZGNjYzM2MmI2MjRmM2RhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5HZXJyaXRzZW4gQmVhY2gsIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zYTNmZTNlZjc2NzE0MjBlYjE1MDAwYWQzZTNiZjExZS5zZXRDb250ZW50KGh0bWxfMTE0MmE0NjEyZGMzNDFkMGJkY2NjMzYyYjYyNGYzZGEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfM2UyODY5ZGE3ZjhiNDUxYTg4M2U2NzQxYjM0ZWExOWMuYmluZFBvcHVwKHBvcHVwXzNhM2ZlM2VmNzY3MTQyMGViMTUwMDBhZDNlM2JmMTFlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I4MzZlMmJhMmQ2ZDQ2MzZhNDk3OTM3MzQzOWFjYTVmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjA5NzQ3Nzc5ODk0NjA0LC03My45MzEzNDQwNDEwODQ5N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yNTI0NTQ3MDdkNGM0MmJjOTE4NWM0MGJjYzVlYTliOSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zNjkxOGIxM2NlMDU0ZGM2OTI1MTRiMjRiMGQ1NmIwMiA9ICQoJzxkaXYgaWQ9Imh0bWxfMzY5MThiMTNjZTA1NGRjNjkyNTE0YjI0YjBkNTZiMDIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1hcmluZSBQYXJrLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjUyNDU0NzA3ZDRjNDJiYzkxODVjNDBiY2M1ZWE5Yjkuc2V0Q29udGVudChodG1sXzM2OTE4YjEzY2UwNTRkYzY5MjUxNGIyNGIwZDU2YjAyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2I4MzZlMmJhMmQ2ZDQ2MzZhNDk3OTM3MzQzOWFjYTVmLmJpbmRQb3B1cChwb3B1cF8yNTI0NTQ3MDdkNGM0MmJjOTE4NWM0MGJjYzVlYTliOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hMzY1ZDc2ZWJiYTE0MmI0YjYyZjAyOTlmZDRjZjlhMCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY5MzIyOTQyMTg4MTUwNCwtNzMuOTY3ODQzMDYyMTYzNjddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfM2Q4MWJjMGRkYTU4NDJiYjkxMGFhMTY3NWUzNTEzY2QgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzQ0ZmJkNjIxZmQ1NGRhYWE5N2MzZGM1YWY2NTllNDIgPSAkKCc8ZGl2IGlkPSJodG1sXzc0NGZiZDYyMWZkNTRkYWFhOTdjM2RjNWFmNjU5ZTQyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DbGludG9uIEhpbGwsIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zZDgxYmMwZGRhNTg0MmJiOTEwYWExNjc1ZTM1MTNjZC5zZXRDb250ZW50KGh0bWxfNzQ0ZmJkNjIxZmQ1NGRhYWE5N2MzZGM1YWY2NTllNDIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYTM2NWQ3NmViYmExNDJiNGI2MmYwMjk5ZmQ0Y2Y5YTAuYmluZFBvcHVwKHBvcHVwXzNkODFiYzBkZGE1ODQyYmI5MTBhYTE2NzVlMzUxM2NkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzkzZThjMTY2OTBiMjRmZTE4ODQ1ODQxOGFlZWNjZDlmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTc2Mzc1Mzc4OTAyMjQsLTc0LjAwNzg3MzExMjAwMjRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYjMwZTU3ZjhmNzY0NGZhMmI0ZGI1ZjY3NzBlMzYyZmQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjMwZmU2NjZiZTE4NDUzMTllNTA3ZDI4N2Q2Y2Y1MjIgPSAkKCc8ZGl2IGlkPSJodG1sX2YzMGZlNjY2YmUxODQ1MzE5ZTUwN2QyODdkNmNmNTIyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TZWEgR2F0ZSwgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2IzMGU1N2Y4Zjc2NDRmYTJiNGRiNWY2NzcwZTM2MmZkLnNldENvbnRlbnQoaHRtbF9mMzBmZTY2NmJlMTg0NTMxOWU1MDdkMjg3ZDZjZjUyMik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85M2U4YzE2NjkwYjI0ZmUxODg0NTg0MThhZWVjY2Q5Zi5iaW5kUG9wdXAocG9wdXBfYjMwZTU3ZjhmNzY0NGZhMmI0ZGI1ZjY3NzBlMzYyZmQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYTA2NjY3ZGIyMjQ3NDI1ZDljNWUyZTk4OTVlY2NiMTkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42OTA4NDQwMjEwOTgwMiwtNzMuOTgzNDYzMzc0MzEwOTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOTgzZWU5Y2YyMDA3NDRhNDk1MDNmYjlhOTg2ZTcwMzIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNGM3NjFlOTdiZGUyNDdjZWIxMjc2Mzg0ZDJhYzkyNzkgPSAkKCc8ZGl2IGlkPSJodG1sXzRjNzYxZTk3YmRlMjQ3Y2ViMTI3NjM4NGQyYWM5Mjc5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Eb3dudG93biwgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzk4M2VlOWNmMjAwNzQ0YTQ5NTAzZmI5YTk4NmU3MDMyLnNldENvbnRlbnQoaHRtbF80Yzc2MWU5N2JkZTI0N2NlYjEyNzYzODRkMmFjOTI3OSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hMDY2NjdkYjIyNDc0MjVkOWM1ZTJlOTg5NWVjY2IxOS5iaW5kUG9wdXAocG9wdXBfOTgzZWU5Y2YyMDA3NDRhNDk1MDNmYjlhOTg2ZTcwMzIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNjg4MjIwMmI3YTQ0NDZhOWFiMzE5ODNhYjM5ZTdlZTcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42ODU2ODI5MTIwOTE0NDQsLTczLjk4Mzc0ODI0MTE1Nzk4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzgzOTA3MGJlOTRlZjQ5ZmE4ZGIyMTQxNWI5OGE5NTY2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzMzMjFkM2Y1ZjcxZTQ2ZGM4MjllYTBhZDIyNTc1YmFjID0gJCgnPGRpdiBpZD0iaHRtbF8zMzIxZDNmNWY3MWU0NmRjODI5ZWEwYWQyMjU3NWJhYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Qm9lcnVtIEhpbGwsIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84MzkwNzBiZTk0ZWY0OWZhOGRiMjE0MTViOThhOTU2Ni5zZXRDb250ZW50KGh0bWxfMzMyMWQzZjVmNzFlNDZkYzgyOWVhMGFkMjI1NzViYWMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNjg4MjIwMmI3YTQ0NDZhOWFiMzE5ODNhYjM5ZTdlZTcuYmluZFBvcHVwKHBvcHVwXzgzOTA3MGJlOTRlZjQ5ZmE4ZGIyMTQxNWI5OGE5NTY2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzc1YWI2MmZiMDk1YzQxNDg5NGZjMWY5MDE5ZjRhMGY5ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjU4NDIwMDE3NDY5ODE1LC03My45NTQ4OTg2NzA3NzcxM10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iNTIzMWExNjhlMGU0NWMzYTM5MTBiMzVkZjY0NTQxMiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80MGYwMGE4M2MyMjE0NGIyYjE5OGE3NDc1ZTNiYmJkMyA9ICQoJzxkaXYgaWQ9Imh0bWxfNDBmMDBhODNjMjIxNDRiMmIxOThhNzQ3NWUzYmJiZDMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlByb3NwZWN0IExlZmZlcnRzIEdhcmRlbnMsIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iNTIzMWExNjhlMGU0NWMzYTM5MTBiMzVkZjY0NTQxMi5zZXRDb250ZW50KGh0bWxfNDBmMDBhODNjMjIxNDRiMmIxOThhNzQ3NWUzYmJiZDMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzVhYjYyZmIwOTVjNDE0ODk0ZmMxZjkwMTlmNGEwZjkuYmluZFBvcHVwKHBvcHVwX2I1MjMxYTE2OGUwZTQ1YzNhMzkxMGIzNWRmNjQ1NDEyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzIzYjllNTZlNWUzNTQ4MGY4MmM0ZThjZmZjNmM4OTBlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjc4NDAyNTU0Nzk1MzU1LC03My45MTMwNjgzMTc4NzM5NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yZTMyZDZhNTUwMmM0NGFjOGFhZmRkNzhiOTJhOWMyNiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9kMjUxODBhMjczMTg0MTk4YmY3ZGRhNDBiMGQwMTNlYSA9ICQoJzxkaXYgaWQ9Imh0bWxfZDI1MTgwYTI3MzE4NDE5OGJmN2RkYTQwYjBkMDEzZWEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk9jZWFuIEhpbGwsIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yZTMyZDZhNTUwMmM0NGFjOGFhZmRkNzhiOTJhOWMyNi5zZXRDb250ZW50KGh0bWxfZDI1MTgwYTI3MzE4NDE5OGJmN2RkYTQwYjBkMDEzZWEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjNiOWU1NmU1ZTM1NDgwZjgyYzRlOGNmZmM2Yzg5MGUuYmluZFBvcHVwKHBvcHVwXzJlMzJkNmE1NTAyYzQ0YWM4YWFmZGQ3OGI5MmE5YzI2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzVlZjg3MTljNDg4NTRkOWFiYzNmZmFjYjc0MzdmYjA3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjc4NTY5OTU3Mjc0NzksLTczLjg2Nzk3NTk4MDgxMzM0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RhZTdjZjU1MzZhZjQ5M2FiMzMyY2EzMmIwZDE5MmY5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzdlZDhjNzYzNmVlNzQ5ZDk4MWQ5OTRlZDI2YWEyM2I2ID0gJCgnPGRpdiBpZD0iaHRtbF83ZWQ4Yzc2MzZlZTc0OWQ5ODFkOTk0ZWQyNmFhMjNiNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q2l0eSBMaW5lLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZGFlN2NmNTUzNmFmNDkzYWIzMzJjYTMyYjBkMTkyZjkuc2V0Q29udGVudChodG1sXzdlZDhjNzYzNmVlNzQ5ZDk4MWQ5OTRlZDI2YWEyM2I2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzVlZjg3MTljNDg4NTRkOWFiYzNmZmFjYjc0MzdmYjA3LmJpbmRQb3B1cChwb3B1cF9kYWU3Y2Y1NTM2YWY0OTNhYjMzMmNhMzJiMGQxOTJmOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83NDkyODQyZDcwNmM0ZGJhOGVhODhhZTBmMjQyMGNhYSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjYxNTE0OTU1MDQ1MzA4LC03My44OTg1NTYzMzYzMDMxN10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80MDE0ZTdiMTNhNWM0N2U0ODMwMjFlYzNmMTIyYmZmNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jOWI3NTU4M2ExOTM0ZWYyODY0M2VmNjdiZmNhMzZhOSA9ICQoJzxkaXYgaWQ9Imh0bWxfYzliNzU1ODNhMTkzNGVmMjg2NDNlZjY3YmZjYTM2YTkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJlcmdlbiBCZWFjaCwgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzQwMTRlN2IxM2E1YzQ3ZTQ4MzAyMWVjM2YxMjJiZmY3LnNldENvbnRlbnQoaHRtbF9jOWI3NTU4M2ExOTM0ZWYyODY0M2VmNjdiZmNhMzZhOSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83NDkyODQyZDcwNmM0ZGJhOGVhODhhZTBmMjQyMGNhYS5iaW5kUG9wdXAocG9wdXBfNDAxNGU3YjEzYTVjNDdlNDgzMDIxZWMzZjEyMmJmZjcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMDQzN2ZjYzkxNmRjNDg0NDhlYTY3YTY2M2UwYjkyMWYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42MjU1OTU4OTg2OTg0MywtNzMuOTU3NTk1MjM0ODk4MzhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMmVkNGNhMzI5MGE1NDdmM2I2YWViNDE1ZjQxZDRmZTkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNTliZWM5ZGFlOTc0NDJkZGE1NGNhZWI0ZTI0ZWUzOTIgPSAkKCc8ZGl2IGlkPSJodG1sXzU5YmVjOWRhZTk3NDQyZGRhNTRjYWViNGUyNGVlMzkyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5NaWR3b29kLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMmVkNGNhMzI5MGE1NDdmM2I2YWViNDE1ZjQxZDRmZTkuc2V0Q29udGVudChodG1sXzU5YmVjOWRhZTk3NDQyZGRhNTRjYWViNGUyNGVlMzkyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzA0MzdmY2M5MTZkYzQ4NDQ4ZWE2N2E2NjNlMGI5MjFmLmJpbmRQb3B1cChwb3B1cF8yZWQ0Y2EzMjkwYTU0N2YzYjZhZWI0MTVmNDFkNGZlOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl85NjU1ZjM0OTZjYzE0OGYyYjQ5ZDQ5NDQ3N2ZhMzc1ZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY0NzAwODYwMzE4NTE4NSwtNzMuOTYyNjEzMTY3MTYwNDhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjUxNmExYzkyYmIwNDY4MWJjNzJiMzJmYTdlOWFhNGYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNDBiMDk4OTI3OTRkNDkzM2E5MWFkYzMzOTBlMzM1YTAgPSAkKCc8ZGl2IGlkPSJodG1sXzQwYjA5ODkyNzk0ZDQ5MzNhOTFhZGMzMzkwZTMzNWEwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Qcm9zcGVjdCBQYXJrIFNvdXRoLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNjUxNmExYzkyYmIwNDY4MWJjNzJiMzJmYTdlOWFhNGYuc2V0Q29udGVudChodG1sXzQwYjA5ODkyNzk0ZDQ5MzNhOTFhZGMzMzkwZTMzNWEwKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzk2NTVmMzQ5NmNjMTQ4ZjJiNDlkNDk0NDc3ZmEzNzVlLmJpbmRQb3B1cChwb3B1cF82NTE2YTFjOTJiYjA0NjgxYmM3MmIzMmZhN2U5YWE0Zik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80NGY4MzQ0ZjA5NmQ0ODEyOTg4NjkxNjZmZGI4ZjQ1MyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjYyMzg0NTI0NDc4NDE5LC03My45MTYwNzQ4Mzk1MTMyNF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iYzQ2OTgxZmUwNzc0YTIzOTA3ZjE1ZDVhNjI1ZDc5YiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80OTQwODNmOTdhNjU0MjAwYjMzNjc0YTYzY2M5ODMwNCA9ICQoJzxkaXYgaWQ9Imh0bWxfNDk0MDgzZjk3YTY1NDIwMGIzMzY3NGE2M2NjOTgzMDQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkdlb3JnZXRvd24sIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iYzQ2OTgxZmUwNzc0YTIzOTA3ZjE1ZDVhNjI1ZDc5Yi5zZXRDb250ZW50KGh0bWxfNDk0MDgzZjk3YTY1NDIwMGIzMzY3NGE2M2NjOTgzMDQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDRmODM0NGYwOTZkNDgxMjk4ODY5MTY2ZmRiOGY0NTMuYmluZFBvcHVwKHBvcHVwX2JjNDY5ODFmZTA3NzRhMjM5MDdmMTVkNWE2MjVkNzliKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2IxOGQ3OWM3MTM1NDQ4ZGU4ZjRhNzQ2ZTMyZTdjN2IxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzA4NDkyNDEwNDE1NDgsLTczLjkzODg1ODE1MjY5MTk1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RjMTUzNzBmNjQ5OTQ0YWZiNDA0MDBiNWRjNDYwNmEyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2UxODA0M2E2OTIxZDRmOGNhNjE0ODEzMGIxYzg0NmFlID0gJCgnPGRpdiBpZD0iaHRtbF9lMTgwNDNhNjkyMWQ0ZjhjYTYxNDgxMzBiMWM4NDZhZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RWFzdCBXaWxsaWFtc2J1cmcsIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9kYzE1MzcwZjY0OTk0NGFmYjQwNDAwYjVkYzQ2MDZhMi5zZXRDb250ZW50KGh0bWxfZTE4MDQzYTY5MjFkNGY4Y2E2MTQ4MTMwYjFjODQ2YWUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjE4ZDc5YzcxMzU0NDhkZThmNGE3NDZlMzJlN2M3YjEuYmluZFBvcHVwKHBvcHVwX2RjMTUzNzBmNjQ5OTQ0YWZiNDA0MDBiNWRjNDYwNmEyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzU5OTJmNjQzZDg2YzRmYzg5NDg4ZGNjYzgwNDk0NGUwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE0ODIyOTA2NTMyMDE0LC03My45NTg4MDg1NzU4NzU4Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80NzI1ZGY2OTcxMjE0M2E3Yjg2YjFjOThhYjU0NTU2MyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hZDMyMzEyYTliYmI0OTUwYTBlZGYwZjkxMDNlNmM0OSA9ICQoJzxkaXYgaWQ9Imh0bWxfYWQzMjMxMmE5YmJiNDk1MGEwZWRmMGY5MTAzZTZjNDkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5vcnRoIFNpZGUsIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80NzI1ZGY2OTcxMjE0M2E3Yjg2YjFjOThhYjU0NTU2My5zZXRDb250ZW50KGh0bWxfYWQzMjMxMmE5YmJiNDk1MGEwZWRmMGY5MTAzZTZjNDkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNTk5MmY2NDNkODZjNGZjODk0ODhkY2NjODA0OTQ0ZTAuYmluZFBvcHVwKHBvcHVwXzQ3MjVkZjY5NzEyMTQzYTdiODZiMWM5OGFiNTQ1NTYzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2JjMTk0ZDJhOTUxNTQ3MjZiNjVjYTA1NzZmNDIxYTMxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzEwODYxNDcyNjUwNjQsLTczLjk1ODAwMDk1MTUzMzMxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzUzNWQ3MDA2YzdjYTRjNmZhMWIwYmYwMjZjMDMxMDJmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzM3MzFkNjMxMTE2OTRjNjNhMzQxYTdlNzY5OTVkZWI4ID0gJCgnPGRpdiBpZD0iaHRtbF8zNzMxZDYzMTExNjk0YzYzYTM0MWE3ZTc2OTk1ZGViOCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U291dGggU2lkZSwgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzUzNWQ3MDA2YzdjYTRjNmZhMWIwYmYwMjZjMDMxMDJmLnNldENvbnRlbnQoaHRtbF8zNzMxZDYzMTExNjk0YzYzYTM0MWE3ZTc2OTk1ZGViOCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9iYzE5NGQyYTk1MTU0NzI2YjY1Y2EwNTc2ZjQyMWEzMS5iaW5kUG9wdXAocG9wdXBfNTM1ZDcwMDZjN2NhNGM2ZmExYjBiZjAyNmMwMzEwMmYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYTA3YjZhOTY2MDY0NDdhZDlkNmVhNmRmNzQzYTFkMTggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42MTMwNTk3NjY2Nzk0MiwtNzMuOTY4MzY2NzgwMzU1NDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYjhkZWNlYTc2MTc4NGY2ZWJmMzIwNTljYjkxNjZlZjkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYzRkNDg4YzU1YjViNDk5MTliMDQzNGFmZjFjMjMyNDAgPSAkKCc8ZGl2IGlkPSJodG1sX2M0ZDQ4OGM1NWI1YjQ5OTE5YjA0MzRhZmYxYzIzMjQwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5PY2VhbiBQYXJrd2F5LCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjhkZWNlYTc2MTc4NGY2ZWJmMzIwNTljYjkxNjZlZjkuc2V0Q29udGVudChodG1sX2M0ZDQ4OGM1NWI1YjQ5OTE5YjA0MzRhZmYxYzIzMjQwKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2EwN2I2YTk2NjA2NDQ3YWQ5ZDZlYTZkZjc0M2ExZDE4LmJpbmRQb3B1cChwb3B1cF9iOGRlY2VhNzYxNzg0ZjZlYmYzMjA1OWNiOTE2NmVmOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84NjllNjY4MTA1MTk0ODMxYjgzYTY3ZjU2NzZlZWFjOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjYxNDc2ODEyNjk0MjI2LC03NC4wMzE5NzkxNDUzNzk4NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yYjE1ZTAwZTQ5YjE0YjI4OWY2MzI3MDRiMzA5OWMwYSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82MGEyNzQyYTBhMTA0ODhiYjdjZjllNjI5ODkzODQxMyA9ICQoJzxkaXYgaWQ9Imh0bWxfNjBhMjc0MmEwYTEwNDg4YmI3Y2Y5ZTYyOTg5Mzg0MTMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZvcnQgSGFtaWx0b24sIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yYjE1ZTAwZTQ5YjE0YjI4OWY2MzI3MDRiMzA5OWMwYS5zZXRDb250ZW50KGh0bWxfNjBhMjc0MmEwYTEwNDg4YmI3Y2Y5ZTYyOTg5Mzg0MTMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODY5ZTY2ODEwNTE5NDgzMWI4M2E2N2Y1Njc2ZWVhYzkuYmluZFBvcHVwKHBvcHVwXzJiMTVlMDBlNDliMTRiMjg5ZjYzMjcwNGIzMDk5YzBhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y5ZDA1NGEwNTUxMTRmODBhYzBhYTIyMzhkMDVkYzAxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE1NjE4NDIyMzE0MzIsLTczLjk5NDI3OTM2MjU1OTc4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzZlZWM5NjQyZGFjMjQ0ODNiMDQ1MzBhYWJmNTYwOTExID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzJkMDkxNjU0MDU2ZjQzOTc4OGNkMTJhMTE0YjBkNWJkID0gJCgnPGRpdiBpZD0iaHRtbF8yZDA5MTY1NDA1NmY0Mzk3ODhjZDEyYTExNGIwZDViZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q2hpbmF0b3duLCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzZlZWM5NjQyZGFjMjQ0ODNiMDQ1MzBhYWJmNTYwOTExLnNldENvbnRlbnQoaHRtbF8yZDA5MTY1NDA1NmY0Mzk3ODhjZDEyYTExNGIwZDViZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mOWQwNTRhMDU1MTE0ZjgwYWMwYWEyMjM4ZDA1ZGMwMS5iaW5kUG9wdXAocG9wdXBfNmVlYzk2NDJkYWMyNDQ4M2IwNDUzMGFhYmY1NjA5MTEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjhiMzMzNTMxN2UzNDNiZjg3NjExOTJlOTJmYmZkYmEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44NTE5MDI1MjU1NTMwNSwtNzMuOTM2OTAwMjc5ODUyMzRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNWZiMzk4YjFjZjUzNGJkMTg1ZjJlYmU3NzE5YWY0MTQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOTI1ZjI3NDUxMjExNGEyZTk5Yzg5YmE5Mjg0NTc4MzYgPSAkKCc8ZGl2IGlkPSJodG1sXzkyNWYyNzQ1MTIxMTRhMmU5OWM4OWJhOTI4NDU3ODM2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XYXNoaW5ndG9uIEhlaWdodHMsIE1hbmhhdHRhbjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNWZiMzk4YjFjZjUzNGJkMTg1ZjJlYmU3NzE5YWY0MTQuc2V0Q29udGVudChodG1sXzkyNWYyNzQ1MTIxMTRhMmU5OWM4OWJhOTI4NDU3ODM2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2Y4YjMzMzUzMTdlMzQzYmY4NzYxMTkyZTkyZmJmZGJhLmJpbmRQb3B1cChwb3B1cF81ZmIzOThiMWNmNTM0YmQxODVmMmViZTc3MTlhZjQxNCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80NmVmYTI2NjcxMGQ0ZTE2YjMxNjY2NzlmMDVmYzBkOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjg2NzY4Mzk2NDQ5OTE1LC03My45MjEyMTA0MjIwMzg5N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84ODYwZDgzNGEzNzI0MDdlYmRkYTkyZDY1NGRiMTE1ZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jNTk5NjBkNTA0ZmM0MDljYWY4YmM5ODIzZDAwNjYzOCA9ICQoJzxkaXYgaWQ9Imh0bWxfYzU5OTYwZDUwNGZjNDA5Y2FmOGJjOTgyM2QwMDY2MzgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPklud29vZCwgTWFuaGF0dGFuPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84ODYwZDgzNGEzNzI0MDdlYmRkYTkyZDY1NGRiMTE1ZC5zZXRDb250ZW50KGh0bWxfYzU5OTYwZDUwNGZjNDA5Y2FmOGJjOTgyM2QwMDY2MzgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDZlZmEyNjY3MTBkNGUxNmIzMTY2Njc5ZjA1ZmMwZDkuYmluZFBvcHVwKHBvcHVwXzg4NjBkODM0YTM3MjQwN2ViZGRhOTJkNjU0ZGIxMTVkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzJjYjVmN2U5NTk4NjQwMGU4ZjViNDY1ODMwMzM3YmU5ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODIzNjA0Mjg0ODExOTM1LC03My45NDk2ODc5MTg4MzM2Nl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85ZDg3YTY4NGE4MTA0OWM4YTU0NjE3ZjlhYjE1NmQ1OSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80MGRkM2UwNjU5MTI0YWYzYjI1NGRiZTgzMjEzN2VjOCA9ICQoJzxkaXYgaWQ9Imh0bWxfNDBkZDNlMDY1OTEyNGFmM2IyNTRkYmU4MzIxMzdlYzgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhhbWlsdG9uIEhlaWdodHMsIE1hbmhhdHRhbjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOWQ4N2E2ODRhODEwNDljOGE1NDYxN2Y5YWIxNTZkNTkuc2V0Q29udGVudChodG1sXzQwZGQzZTA2NTkxMjRhZjNiMjU0ZGJlODMyMTM3ZWM4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzJjYjVmN2U5NTk4NjQwMGU4ZjViNDY1ODMwMzM3YmU5LmJpbmRQb3B1cChwb3B1cF85ZDg3YTY4NGE4MTA0OWM4YTU0NjE3ZjlhYjE1NmQ1OSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hZTZlOTExMTJhNTI0YWMzYjA5NmY3ODc0MmQ4NWUxNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjgxNjkzNDQyOTQ5NzgsLTczLjk1NzM4NTM5MzUxODhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNGZlM2Q4NDFkNzc4NDIwMzk4NWYzNjRjOGRmMTFmM2IgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDYxZGEyYjcyNDAyNGYzMGI2MWNhNDY5ZWVhZTliM2QgPSAkKCc8ZGl2IGlkPSJodG1sX2Q2MWRhMmI3MjQwMjRmMzBiNjFjYTQ2OWVlYWU5YjNkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5NYW5oYXR0YW52aWxsZSwgTWFuaGF0dGFuPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80ZmUzZDg0MWQ3Nzg0MjAzOTg1ZjM2NGM4ZGYxMWYzYi5zZXRDb250ZW50KGh0bWxfZDYxZGEyYjcyNDAyNGYzMGI2MWNhNDY5ZWVhZTliM2QpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYWU2ZTkxMTEyYTUyNGFjM2IwOTZmNzg3NDJkODVlMTQuYmluZFBvcHVwKHBvcHVwXzRmZTNkODQxZDc3ODQyMDM5ODVmMzY0YzhkZjExZjNiKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2E4NmM2MmIyMzM4YTQ4ZDc5NmY2MTliYTA0M2Y0OGNmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODE1OTc2MDY3NDI0MTQsLTczLjk0MzIxMTEyNjAzOTA1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2NmNzE1NDI2ZWNlYjRlY2I4OTUyNTQ3OTk4ZmEzOWE5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzkzNDJmNjA3MjU4NTQ0NDY4OWNlMWUwMmEzZjMwNWUyID0gJCgnPGRpdiBpZD0iaHRtbF85MzQyZjYwNzI1ODU0NDQ2ODljZTFlMDJhM2YzMDVlMiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q2VudHJhbCBIYXJsZW0sIE1hbmhhdHRhbjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfY2Y3MTU0MjZlY2ViNGVjYjg5NTI1NDc5OThmYTM5YTkuc2V0Q29udGVudChodG1sXzkzNDJmNjA3MjU4NTQ0NDY4OWNlMWUwMmEzZjMwNWUyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2E4NmM2MmIyMzM4YTQ4ZDc5NmY2MTliYTA0M2Y0OGNmLmJpbmRQb3B1cChwb3B1cF9jZjcxNTQyNmVjZWI0ZWNiODk1MjU0Nzk5OGZhMzlhOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82MWVmZjZkMWZmZmM0YTFmOGY4ZmFmODI0ZmYwNjNhZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc5MjI0OTQ2NjYzMDMzLC03My45NDQxODIyMzE0ODUyNF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yNjNjOGEyZjEyODU0ZWE0OGM2ZGY5MDJlNTEyMmI5ZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zYWQ2M2VlNzRmNjE0MjZiODU5OTU1NTZkNDJmZWZkYiA9ICQoJzxkaXYgaWQ9Imh0bWxfM2FkNjNlZTc0ZjYxNDI2Yjg1OTk1NTU2ZDQyZmVmZGIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkVhc3QgSGFybGVtLCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzI2M2M4YTJmMTI4NTRlYTQ4YzZkZjkwMmU1MTIyYjlkLnNldENvbnRlbnQoaHRtbF8zYWQ2M2VlNzRmNjE0MjZiODU5OTU1NTZkNDJmZWZkYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82MWVmZjZkMWZmZmM0YTFmOGY4ZmFmODI0ZmYwNjNhZC5iaW5kUG9wdXAocG9wdXBfMjYzYzhhMmYxMjg1NGVhNDhjNmRmOTAyZTUxMjJiOWQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZmFiY2UyMzNjNzVmNDU0NmI4NDU3NGRiOGY0MWU1M2YgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43NzU2Mzg1NzMzMDE4MDUsLTczLjk2MDUwNzYzMTM1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RmZThjY2I4ODRhNDRmNWU5MGIwY2RiYTNiNjdjYzUwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzNhM2FkMTc3YjFiZTQ2MmVhYTNmZmRkYTllZGM1YTA1ID0gJCgnPGRpdiBpZD0iaHRtbF8zYTNhZDE3N2IxYmU0NjJlYWEzZmZkZGE5ZWRjNWEwNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VXBwZXIgRWFzdCBTaWRlLCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2RmZThjY2I4ODRhNDRmNWU5MGIwY2RiYTNiNjdjYzUwLnNldENvbnRlbnQoaHRtbF8zYTNhZDE3N2IxYmU0NjJlYWEzZmZkZGE5ZWRjNWEwNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mYWJjZTIzM2M3NWY0NTQ2Yjg0NTc0ZGI4ZjQxZTUzZi5iaW5kUG9wdXAocG9wdXBfZGZlOGNjYjg4NGE0NGY1ZTkwYjBjZGJhM2I2N2NjNTApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTllNTQ0Zjk4YmQ3NGU5ZjhhMzc2M2ZhNjRlYTM3YzYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43NzU5Mjk4NDk4ODQ4NzUsLTczLjk0NzExNzg0NDcxODI2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzE0N2ViNmRkNzA2ODQ1MTk5MDJiMjM2MTkzYmI4MGZjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc3YjEwOWM3OGM4YTRkZDdhM2U3ZmQ3MDY1NWQ0ODdkID0gJCgnPGRpdiBpZD0iaHRtbF83N2IxMDljNzhjOGE0ZGQ3YTNlN2ZkNzA2NTVkNDg3ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+WW9ya3ZpbGxlLCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzE0N2ViNmRkNzA2ODQ1MTk5MDJiMjM2MTkzYmI4MGZjLnNldENvbnRlbnQoaHRtbF83N2IxMDljNzhjOGE0ZGQ3YTNlN2ZkNzA2NTVkNDg3ZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl81OWU1NDRmOThiZDc0ZTlmOGEzNzYzZmE2NGVhMzdjNi5iaW5kUG9wdXAocG9wdXBfMTQ3ZWI2ZGQ3MDY4NDUxOTkwMmIyMzYxOTNiYjgwZmMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYzBjZmNiN2Q2N2QzNDA3NjljYjhhMTlmMzg3OTQ0NTUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43NjgxMTI2NTgyODczMywtNzMuOTU4ODU5Njg4MTM3Nl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zNGJmYmI5ZGMwNWY0NTRmOWVjOTM0NTNkYzVkNmVmNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xZjAzOGExNGU1NmM0NmU2ODBmZDc0MmQxMGM2NjcxYiA9ICQoJzxkaXYgaWQ9Imh0bWxfMWYwMzhhMTRlNTZjNDZlNjgwZmQ3NDJkMTBjNjY3MWIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxlbm94IEhpbGwsIE1hbmhhdHRhbjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzRiZmJiOWRjMDVmNDU0ZjllYzkzNDUzZGM1ZDZlZjcuc2V0Q29udGVudChodG1sXzFmMDM4YTE0ZTU2YzQ2ZTY4MGZkNzQyZDEwYzY2NzFiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2MwY2ZjYjdkNjdkMzQwNzY5Y2I4YTE5ZjM4Nzk0NDU1LmJpbmRQb3B1cChwb3B1cF8zNGJmYmI5ZGMwNWY0NTRmOWVjOTM0NTNkYzVkNmVmNyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kMGE2YTUwNWQ1YWM0N2JiODAwMWYwZDk2OGEwOWIxZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc2MjE1OTYwNTc2MjgzLC03My45NDkxNjc2OTIyNzk1M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xNTNkYjRiYzIxZWM0YWZjODJjNTJhNzRhMWRlM2U0NSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iMThmNzY3NmNlMzE0MjRkOTkyY2JiNmMzZDgzMjAzZiA9ICQoJzxkaXYgaWQ9Imh0bWxfYjE4Zjc2NzZjZTMxNDI0ZDk5MmNiYjZjM2Q4MzIwM2YiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJvb3NldmVsdCBJc2xhbmQsIE1hbmhhdHRhbjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMTUzZGI0YmMyMWVjNGFmYzgyYzUyYTc0YTFkZTNlNDUuc2V0Q29udGVudChodG1sX2IxOGY3Njc2Y2UzMTQyNGQ5OTJjYmI2YzNkODMyMDNmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2QwYTZhNTA1ZDVhYzQ3YmI4MDAxZjBkOTY4YTA5YjFmLmJpbmRQb3B1cChwb3B1cF8xNTNkYjRiYzIxZWM0YWZjODJjNTJhNzRhMWRlM2U0NSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81ZWIwNWMzN2NlNTI0NGI3YmMzMTA0ZDJmN2U4ODhiNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc4NzY1Nzk5ODUzNDg1NCwtNzMuOTc3MDU5MjM2MzA2MDNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzlkOWUyNGM1NzQwNGI0YTgyODU3NjJiN2FmYzVkNTcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDZjZDk4MzQ2YzVjNGM4ZWI4ODkyNDZlZmQ3MDVkNzMgPSAkKCc8ZGl2IGlkPSJodG1sX2Q2Y2Q5ODM0NmM1YzRjOGViODg5MjQ2ZWZkNzA1ZDczIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5VcHBlciBXZXN0IFNpZGUsIE1hbmhhdHRhbjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzlkOWUyNGM1NzQwNGI0YTgyODU3NjJiN2FmYzVkNTcuc2V0Q29udGVudChodG1sX2Q2Y2Q5ODM0NmM1YzRjOGViODg5MjQ2ZWZkNzA1ZDczKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzVlYjA1YzM3Y2U1MjQ0YjdiYzMxMDRkMmY3ZTg4OGI0LmJpbmRQb3B1cChwb3B1cF8zOWQ5ZTI0YzU3NDA0YjRhODI4NTc2MmI3YWZjNWQ1Nyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jOTI1ZDQ0ZGFiYzU0ZWEzOTE4NjRjYWJmZDkxNmFiZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc3MzUyODg4OTQyMTY2LC03My45ODUzMzc3NzAwMTI2Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81ZTIxMDhhMDc0ZTk0YTg4OWM2ZGE5OTk0NTVjMjNiYiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF84YmQyZGJiMGE1MmU0N2I4YmQ4MjQ3YmExNDlmOWVkYSA9ICQoJzxkaXYgaWQ9Imh0bWxfOGJkMmRiYjBhNTJlNDdiOGJkODI0N2JhMTQ5ZjllZGEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxpbmNvbG4gU3F1YXJlLCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzVlMjEwOGEwNzRlOTRhODg5YzZkYTk5OTQ1NWMyM2JiLnNldENvbnRlbnQoaHRtbF84YmQyZGJiMGE1MmU0N2I4YmQ4MjQ3YmExNDlmOWVkYSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jOTI1ZDQ0ZGFiYzU0ZWEzOTE4NjRjYWJmZDkxNmFiZi5iaW5kUG9wdXAocG9wdXBfNWUyMTA4YTA3NGU5NGE4ODljNmRhOTk5NDU1YzIzYmIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNzZhYTNhYjE5ZWRlNDMxMWEwNDgyZTQ5ODJhZjNlZGIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43NTkxMDA4OTE0NjIxMiwtNzMuOTk2MTE5MzYzMDk0NzldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNmYzODdiZTAxOWIxNDZlYjkzMDMzMzFiMmZkZmZmZWEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzhhY2U0ZTdiNjkzNDI3YWFiZjczZGNjY2YwZmZkNjUgPSAkKCc8ZGl2IGlkPSJodG1sXzc4YWNlNGU3YjY5MzQyN2FhYmY3M2RjY2NmMGZmZDY1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DbGludG9uLCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzZmMzg3YmUwMTliMTQ2ZWI5MzAzMzMxYjJmZGZmZmVhLnNldENvbnRlbnQoaHRtbF83OGFjZTRlN2I2OTM0MjdhYWJmNzNkY2NjZjBmZmQ2NSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83NmFhM2FiMTllZGU0MzExYTA0ODJlNDk4MmFmM2VkYi5iaW5kUG9wdXAocG9wdXBfNmYzODdiZTAxOWIxNDZlYjkzMDMzMzFiMmZkZmZmZWEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODE5NDBlYmJiMjM2NDcxYThlODAyYmNhM2U5YWY5NGIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43NTQ2OTExMDI3MDYyMywtNzMuOTgxNjY4ODI3MzAzMDRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjRiYWU2M2VmMjU4NDMzYmEyNDYwMTA3NjE4ODJhNzMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYTI3ZDgzYzM3NGRhNDFhNDkyOWY5YmNhOWQ1NzkxZDQgPSAkKCc8ZGl2IGlkPSJodG1sX2EyN2Q4M2MzNzRkYTQxYTQ5MjlmOWJjYTlkNTc5MWQ0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5NaWR0b3duLCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Y0YmFlNjNlZjI1ODQzM2JhMjQ2MDEwNzYxODgyYTczLnNldENvbnRlbnQoaHRtbF9hMjdkODNjMzc0ZGE0MWE0OTI5ZjliY2E5ZDU3OTFkNCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84MTk0MGViYmIyMzY0NzFhOGU4MDJiY2EzZTlhZjk0Yi5iaW5kUG9wdXAocG9wdXBfZjRiYWU2M2VmMjU4NDMzYmEyNDYwMTA3NjE4ODJhNzMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjU0MTcyNjMyZjBkNGFiNGE3ODZkMjQ3MWMwNzFkNTYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43NDgzMDMwNzcyNTIxNzQsLTczLjk3ODMzMjA3OTI0MTI3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzJhZjJmMjg4ZjJjNjQyYmRhMTZjMmU1YmMyZGYzYWQyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzFmY2I3ZmQyMjE0NjQ0OTlhMTNmZjdlNDRiMDE5ZDgwID0gJCgnPGRpdiBpZD0iaHRtbF8xZmNiN2ZkMjIxNDY0NDk5YTEzZmY3ZTQ0YjAxOWQ4MCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TXVycmF5IEhpbGwsIE1hbmhhdHRhbjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMmFmMmYyODhmMmM2NDJiZGExNmMyZTViYzJkZjNhZDIuc2V0Q29udGVudChodG1sXzFmY2I3ZmQyMjE0NjQ0OTlhMTNmZjdlNDRiMDE5ZDgwKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2I1NDE3MjYzMmYwZDRhYjRhNzg2ZDI0NzFjMDcxZDU2LmJpbmRQb3B1cChwb3B1cF8yYWYyZjI4OGYyYzY0MmJkYTE2YzJlNWJjMmRmM2FkMik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iMDJmZjNkYjBhM2Y0ZDU4OWM4ZTU3ODNmYjk4YjA4MCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc0NDAzNDcwNjc0Nzk3NSwtNzQuMDAzMTE2MzM0NzI4MTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOTBmMDdhNzI0NmYyNDliZGE2ZmQ4Yjc2ZGMzNzBmYTUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDY2M2RhMGQ0Nzk4NDljZWIwNmEyM2ZkZDgxY2MzZjAgPSAkKCc8ZGl2IGlkPSJodG1sX2Q2NjNkYTBkNDc5ODQ5Y2ViMDZhMjNmZGQ4MWNjM2YwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DaGVsc2VhLCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzkwZjA3YTcyNDZmMjQ5YmRhNmZkOGI3NmRjMzcwZmE1LnNldENvbnRlbnQoaHRtbF9kNjYzZGEwZDQ3OTg0OWNlYjA2YTIzZmRkODFjYzNmMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9iMDJmZjNkYjBhM2Y0ZDU4OWM4ZTU3ODNmYjk4YjA4MC5iaW5kUG9wdXAocG9wdXBfOTBmMDdhNzI0NmYyNDliZGE2ZmQ4Yjc2ZGMzNzBmYTUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNGQyZDIwMzA1MmZiNDg2YWIxMTk3OTU4MDRmMGVhMGMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MjY5MzI4ODUzNjEyOCwtNzMuOTk5OTE0MDI5NDU5MDJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYmE3ZDAxMjE5YmQyNDIxY2I5NWViZGM2MjJhNjEyNzMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMzg5OTFiNzNhODFiNGU3OGFhMTI5ZGZjZTIxMTkzNmIgPSAkKCc8ZGl2IGlkPSJodG1sXzM4OTkxYjczYTgxYjRlNzhhYTEyOWRmY2UyMTE5MzZiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5HcmVlbndpY2ggVmlsbGFnZSwgTWFuaGF0dGFuPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iYTdkMDEyMTliZDI0MjFjYjk1ZWJkYzYyMmE2MTI3My5zZXRDb250ZW50KGh0bWxfMzg5OTFiNzNhODFiNGU3OGFhMTI5ZGZjZTIxMTkzNmIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNGQyZDIwMzA1MmZiNDg2YWIxMTk3OTU4MDRmMGVhMGMuYmluZFBvcHVwKHBvcHVwX2JhN2QwMTIxOWJkMjQyMWNiOTVlYmRjNjIyYTYxMjczKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzZhZjU3MDc2ODU3NTRlMTg5ZTIxY2FjZWZmNTA3YWRhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzI3ODQ2Nzc3MjcwMjQ0LC03My45ODIyMjYxNjUwNjQxNl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lMjEzODJkZTRiNGU0Njk5YmZmNzM0NTgwMmIyNWI1MyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mOWJhM2EwZDg1MWM0OTJhODA1ZTBlMWZjODY0YzdhNCA9ICQoJzxkaXYgaWQ9Imh0bWxfZjliYTNhMGQ4NTFjNDkyYTgwNWUwZTFmYzg2NGM3YTQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkVhc3QgVmlsbGFnZSwgTWFuaGF0dGFuPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lMjEzODJkZTRiNGU0Njk5YmZmNzM0NTgwMmIyNWI1My5zZXRDb250ZW50KGh0bWxfZjliYTNhMGQ4NTFjNDkyYTgwNWUwZTFmYzg2NGM3YTQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNmFmNTcwNzY4NTc1NGUxODllMjFjYWNlZmY1MDdhZGEuYmluZFBvcHVwKHBvcHVwX2UyMTM4MmRlNGI0ZTQ2OTliZmY3MzQ1ODAyYjI1YjUzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2NkYWVlMjFjYWI4MzRiZTNiZjk4NjUzMzlmYzRkNjA0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE3ODA2NzQ4OTI3NjUsLTczLjk4MDg5MDMxOTk5MjkxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2E0MjVkNjJmMjA5MzQyZjE5MjU4MGJjMjQ3N2YwNDMzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzFiNjAzZGY0MGQ3NjRiNzJiOGYyNmQzYjhjZDY4MTcyID0gJCgnPGRpdiBpZD0iaHRtbF8xYjYwM2RmNDBkNzY0YjcyYjhmMjZkM2I4Y2Q2ODE3MiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TG93ZXIgRWFzdCBTaWRlLCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2E0MjVkNjJmMjA5MzQyZjE5MjU4MGJjMjQ3N2YwNDMzLnNldENvbnRlbnQoaHRtbF8xYjYwM2RmNDBkNzY0YjcyYjhmMjZkM2I4Y2Q2ODE3Mik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jZGFlZTIxY2FiODM0YmUzYmY5ODY1MzM5ZmM0ZDYwNC5iaW5kUG9wdXAocG9wdXBfYTQyNWQ2MmYyMDkzNDJmMTkyNTgwYmMyNDc3ZjA0MzMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOGE2MTk2MWYyZDNjNGEwOWFkYzM2NTg2YzBkZTc4ZmYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MjE1MjE5Njc0NDMyMTYsLTc0LjAxMDY4MzI4NTU5MDg3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzdkYWVmM2EwMTA2ZjQzYmY5YmZmNjBjNTk3NmI3ZTlkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzI0MDYyODNlNWVlYzRkNjFiNjU0MzIzZWJlYmE0NzNjID0gJCgnPGRpdiBpZD0iaHRtbF8yNDA2MjgzZTVlZWM0ZDYxYjY1NDMyM2ViZWJhNDczYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VHJpYmVjYSwgTWFuaGF0dGFuPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83ZGFlZjNhMDEwNmY0M2JmOWJmZjYwYzU5NzZiN2U5ZC5zZXRDb250ZW50KGh0bWxfMjQwNjI4M2U1ZWVjNGQ2MWI2NTQzMjNlYmViYTQ3M2MpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOGE2MTk2MWYyZDNjNGEwOWFkYzM2NTg2YzBkZTc4ZmYuYmluZFBvcHVwKHBvcHVwXzdkYWVmM2EwMTA2ZjQzYmY5YmZmNjBjNTk3NmI3ZTlkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y3MmFkZTdjMmEwNDQ2ZmU5M2Q0MzQwYzZmNWEzN2FhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE5MzIzNzkzOTU5MDcsLTczLjk5NzMwNDY3MjA4MDczXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzMwYWIxY2ZjOGM3NjQ0NjRiNWExZTY5N2U4YTc2ODUzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzA5MDQ2NjYwNDM0ZDQ4NGJhOWM0NTI3MzMyNzFkZjljID0gJCgnPGRpdiBpZD0iaHRtbF8wOTA0NjY2MDQzNGQ0ODRiYTljNDUyNzMzMjcxZGY5YyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TGl0dGxlIEl0YWx5LCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzMwYWIxY2ZjOGM3NjQ0NjRiNWExZTY5N2U4YTc2ODUzLnNldENvbnRlbnQoaHRtbF8wOTA0NjY2MDQzNGQ0ODRiYTljNDUyNzMzMjcxZGY5Yyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mNzJhZGU3YzJhMDQ0NmZlOTNkNDM0MGM2ZjVhMzdhYS5iaW5kUG9wdXAocG9wdXBfMzBhYjFjZmM4Yzc2NDQ2NGI1YTFlNjk3ZThhNzY4NTMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZWQ5NThlMmE1YTVmNDYzZTkzMGNmZjliNDY5Y2EzNzggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MjIxODM4NDEzMTc5NCwtNzQuMDAwNjU2NjY5NTk3NTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZGQ1MGJhMTQ1YTk0NDZmYTk5M2E5N2JlZTU5M2QyZWUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzYxN2Y3MjA4MDk4NDk1MTkzYjRkZWJlZGFlNjZhNzQgPSAkKCc8ZGl2IGlkPSJodG1sXzc2MTdmNzIwODA5ODQ5NTE5M2I0ZGViZWRhZTY2YTc0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Tb2hvLCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2RkNTBiYTE0NWE5NDQ2ZmE5OTNhOTdiZWU1OTNkMmVlLnNldENvbnRlbnQoaHRtbF83NjE3ZjcyMDgwOTg0OTUxOTNiNGRlYmVkYWU2NmE3NCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9lZDk1OGUyYTVhNWY0NjNlOTMwY2ZmOWI0NjljYTM3OC5iaW5kUG9wdXAocG9wdXBfZGQ1MGJhMTQ1YTk0NDZmYTk5M2E5N2JlZTU5M2QyZWUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYmEyNmMwMmU3MDE0NGJjMjgwYWMyZGM3NWYyYWNlZjMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MzQ0MzM5MzU3MjQzNCwtNzQuMDA2MTc5OTgxMjY4MTJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZWY2YTZiZGUxMjhiNDQyOTk5MTM1NjUwMDY4ZDdmMTUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDI1ZDZlNTg0YWViNGQ1MTgxZjVmYzQ1NDBjOGRhZmIgPSAkKCc8ZGl2IGlkPSJodG1sX2QyNWQ2ZTU4NGFlYjRkNTE4MWY1ZmM0NTQwYzhkYWZiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XZXN0IFZpbGxhZ2UsIE1hbmhhdHRhbjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZWY2YTZiZGUxMjhiNDQyOTk5MTM1NjUwMDY4ZDdmMTUuc2V0Q29udGVudChodG1sX2QyNWQ2ZTU4NGFlYjRkNTE4MWY1ZmM0NTQwYzhkYWZiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2JhMjZjMDJlNzAxNDRiYzI4MGFjMmRjNzVmMmFjZWYzLmJpbmRQb3B1cChwb3B1cF9lZjZhNmJkZTEyOGI0NDI5OTkxMzU2NTAwNjhkN2YxNSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lYWFmOGNjZTUzYjU0NjMzYTAxNjAzZTk1ZmJiOGMwNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc5NzMwNzA0MTcwMjg2NSwtNzMuOTY0Mjg2MTc3NDA2NTVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMjQ5N2MwNGYwYTE5NGZhODgzN2VlMDA5ZjQ5NGViNDQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfM2U3MGNiYWEyNjlkNDEzZjg0Y2Y4ODc3YTJiYTY3ZWUgPSAkKCc8ZGl2IGlkPSJodG1sXzNlNzBjYmFhMjY5ZDQxM2Y4NGNmODg3N2EyYmE2N2VlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5NYW5oYXR0YW4gVmFsbGV5LCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzI0OTdjMDRmMGExOTRmYTg4MzdlZTAwOWY0OTRlYjQ0LnNldENvbnRlbnQoaHRtbF8zZTcwY2JhYTI2OWQ0MTNmODRjZjg4NzdhMmJhNjdlZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9lYWFmOGNjZTUzYjU0NjMzYTAxNjAzZTk1ZmJiOGMwNS5iaW5kUG9wdXAocG9wdXBfMjQ5N2MwNGYwYTE5NGZhODgzN2VlMDA5ZjQ5NGViNDQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDRmOGE2MzJhOGM3NGZkMjk5YWQ5NDhiMGFlZTMwY2EgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44MDc5OTk3MzgxNjU4MjYsLTczLjk2Mzg5NjI3OTA1MzMyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2FjMDM1Nzk0NTNhMTQ2ZGE4MGZiNDQwYTBmNDJlNjJkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzY5NzNjMDJiM2I4MTRhNTE4MzU0N2NiYjE1ZDRhZDRiID0gJCgnPGRpdiBpZD0iaHRtbF82OTczYzAyYjNiODE0YTUxODM1NDdjYmIxNWQ0YWQ0YiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TW9ybmluZ3NpZGUgSGVpZ2h0cywgTWFuaGF0dGFuPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hYzAzNTc5NDUzYTE0NmRhODBmYjQ0MGEwZjQyZTYyZC5zZXRDb250ZW50KGh0bWxfNjk3M2MwMmIzYjgxNGE1MTgzNTQ3Y2JiMTVkNGFkNGIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDRmOGE2MzJhOGM3NGZkMjk5YWQ5NDhiMGFlZTMwY2EuYmluZFBvcHVwKHBvcHVwX2FjMDM1Nzk0NTNhMTQ2ZGE4MGZiNDQwYTBmNDJlNjJkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y3Mzc0M2RmNDJlMjQyOTc4YWQ5MGMyZjJlNGNhMWUxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzM3MjA5ODMyNzE1LC03My45ODEzNzU5NDgzMzU0MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jOGEwMWZjMjc1ZjU0NjlmYTJmNGY0YTE0NGUzZjg5NSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iMDlmYjE0ODNkNmM0MDc2YmU2OGMxZGY3MGM0ZmYyYiA9ICQoJzxkaXYgaWQ9Imh0bWxfYjA5ZmIxNDgzZDZjNDA3NmJlNjhjMWRmNzBjNGZmMmIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkdyYW1lcmN5LCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2M4YTAxZmMyNzVmNTQ2OWZhMmY0ZjRhMTQ0ZTNmODk1LnNldENvbnRlbnQoaHRtbF9iMDlmYjE0ODNkNmM0MDc2YmU2OGMxZGY3MGM0ZmYyYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mNzM3NDNkZjQyZTI0Mjk3OGFkOTBjMmYyZTRjYTFlMS5iaW5kUG9wdXAocG9wdXBfYzhhMDFmYzI3NWY1NDY5ZmEyZjRmNGExNDRlM2Y4OTUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYzAwODdhNWM3MjllNDA2N2EyZmI4NTlkNjFhZWIyOWQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTE5MzE5ODM5NDU2NSwtNzQuMDE2ODY5MzA1MDg2MTddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfODdkMmUyNTM5OWY0NDlmNzkxMWNhMjQwNGNjMGRiOGYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOGVmYzBjYjZkZTBhNGI0MGI2ZTZlNTU0OGZhNjc3ODEgPSAkKCc8ZGl2IGlkPSJodG1sXzhlZmMwY2I2ZGUwYTRiNDBiNmU2ZTU1NDhmYTY3NzgxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CYXR0ZXJ5IFBhcmsgQ2l0eSwgTWFuaGF0dGFuPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84N2QyZTI1Mzk5ZjQ0OWY3OTExY2EyNDA0Y2MwZGI4Zi5zZXRDb250ZW50KGh0bWxfOGVmYzBjYjZkZTBhNGI0MGI2ZTZlNTU0OGZhNjc3ODEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYzAwODdhNWM3MjllNDA2N2EyZmI4NTlkNjFhZWIyOWQuYmluZFBvcHVwKHBvcHVwXzg3ZDJlMjUzOTlmNDQ5Zjc5MTFjYTI0MDRjYzBkYjhmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzYwMjg1MDlkNTIwYTQ0YTE4MmI0Y2RmYjkwYTQ1MjY0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzA3MTA3MTA3MjcwNDgsLTc0LjAxMDY2NTQ0NTIxMjddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzQwMTlmZmE5ODQzNDAzYzlhNzhjZjQzZDM1ZTU4ZGMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOGIyYjA2NmJiOWZkNDU1OTk2MzViZTU5MzllMmJmNzUgPSAkKCc8ZGl2IGlkPSJodG1sXzhiMmIwNjZiYjlmZDQ1NTk5NjM1YmU1OTM5ZTJiZjc1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5GaW5hbmNpYWwgRGlzdHJpY3QsIE1hbmhhdHRhbjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYzQwMTlmZmE5ODQzNDAzYzlhNzhjZjQzZDM1ZTU4ZGMuc2V0Q29udGVudChodG1sXzhiMmIwNjZiYjlmZDQ1NTk5NjM1YmU1OTM5ZTJiZjc1KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzYwMjg1MDlkNTIwYTQ0YTE4MmI0Y2RmYjkwYTQ1MjY0LmJpbmRQb3B1cChwb3B1cF9jNDAxOWZmYTk4NDM0MDNjOWE3OGNmNDNkMzVlNThkYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81NThlODczNjFiMzc0OWUwYWI5OWFhNDMyNzEyZjc1ZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc2ODUwODU5MzM1NDkyLC03My45MTU2NTM3NDMwNDIzNF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lMjFlZTRkNTA2ZDc0ODk2OGQ0YWYzYTI1MTZhNzE0YSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mZjA5YTVjOWYxZjM0YTliYjg4OTQwODFlNGNhZDhkNiA9ICQoJzxkaXYgaWQ9Imh0bWxfZmYwOWE1YzlmMWYzNGE5YmI4ODk0MDgxZTRjYWQ4ZDYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkFzdG9yaWEsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZTIxZWU0ZDUwNmQ3NDg5NjhkNGFmM2EyNTE2YTcxNGEuc2V0Q29udGVudChodG1sX2ZmMDlhNWM5ZjFmMzRhOWJiODg5NDA4MWU0Y2FkOGQ2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU1OGU4NzM2MWIzNzQ5ZTBhYjk5YWE0MzI3MTJmNzVlLmJpbmRQb3B1cChwb3B1cF9lMjFlZTRkNTA2ZDc0ODk2OGQ0YWYzYTI1MTZhNzE0YSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81OWE1NjczNTYwNWE0ODNhOWQ5NjdkZDVmY2EyNWY1ZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc0NjM0OTA4ODYwMjIyLC03My45MDE4NDE2NjgzODI4NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xYWMxZTRjYjhkMjY0OWM2OTM2ZDhmODE2YWNjNDc4NiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80NTJiYTYzM2RmODk0ZmVhOWM5ODVlNmViMmI3YWI3YyA9ICQoJzxkaXYgaWQ9Imh0bWxfNDUyYmE2MzNkZjg5NGZlYTljOTg1ZTZlYjJiN2FiN2MiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldvb2RzaWRlLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzFhYzFlNGNiOGQyNjQ5YzY5MzZkOGY4MTZhY2M0Nzg2LnNldENvbnRlbnQoaHRtbF80NTJiYTYzM2RmODk0ZmVhOWM5ODVlNmViMmI3YWI3Yyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl81OWE1NjczNTYwNWE0ODNhOWQ5NjdkZDVmY2EyNWY1Zi5iaW5kUG9wdXAocG9wdXBfMWFjMWU0Y2I4ZDI2NDljNjkzNmQ4ZjgxNmFjYzQ3ODYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTM5NDJhMDA4NTdjNDcxMGE1YWM1ZGVlNTJmMzdhY2QgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43NTE5ODEzODAwNzM2NywtNzMuODgyODIxMDkxNjQzNjVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZmQ5ODM0ODI2NGIzNDc0MDk4NTU2OTcwOWNjMWJlMTcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZTE1MmFmODA4ZDI2NGI0YjllMmM3YjMzOTcwNzY0N2IgPSAkKCc8ZGl2IGlkPSJodG1sX2UxNTJhZjgwOGQyNjRiNGI5ZTJjN2IzMzk3MDc2NDdiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5KYWNrc29uIEhlaWdodHMsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZmQ5ODM0ODI2NGIzNDc0MDk4NTU2OTcwOWNjMWJlMTcuc2V0Q29udGVudChodG1sX2UxNTJhZjgwOGQyNjRiNGI5ZTJjN2IzMzk3MDc2NDdiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzUzOTQyYTAwODU3YzQ3MTBhNWFjNWRlZTUyZjM3YWNkLmJpbmRQb3B1cChwb3B1cF9mZDk4MzQ4MjY0YjM0NzQwOTg1NTY5NzA5Y2MxYmUxNyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lNDgxMTdlNDUxM2Y0YTc2YTczYmE3ZTFjYWRjZTAzMSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc0NDA0ODUwNTEyMjAyNCwtNzMuODgxNjU2MjIyODgzODhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNzZhOWI1MDIwNzFlNDllMjg4ZTFhMjU0YTQwZjQ0OWQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYjVhYzYwZWJiNzZiNGY4ODlkMzkxZWMyM2Y1ZDUwZWQgPSAkKCc8ZGl2IGlkPSJodG1sX2I1YWM2MGViYjc2YjRmODg5ZDM5MWVjMjNmNWQ1MGVkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FbG1odXJzdCwgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83NmE5YjUwMjA3MWU0OWUyODhlMWEyNTRhNDBmNDQ5ZC5zZXRDb250ZW50KGh0bWxfYjVhYzYwZWJiNzZiNGY4ODlkMzkxZWMyM2Y1ZDUwZWQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZTQ4MTE3ZTQ1MTNmNGE3NmE3M2JhN2UxY2FkY2UwMzEuYmluZFBvcHVwKHBvcHVwXzc2YTliNTAyMDcxZTQ5ZTI4OGUxYTI1NGE0MGY0NDlkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQ3YjQ3OWJlMjE5ODQ3YWI5OWJmNzM0MzhiNjIwNTQ3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjU0MjI1Mjc3Mzg0ODcsLTczLjgzODEzNzY0NjAwMjhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMDRiOGFkNjVkZTg5NGM1NmJhNjY3NDc3NjVkZjVhYjMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYTA2ZGJjZWM3ODNjNDJlYTk3NmU0N2IxNGE3ZDQwZjEgPSAkKCc8ZGl2IGlkPSJodG1sX2EwNmRiY2VjNzgzYzQyZWE5NzZlNDdiMTRhN2Q0MGYxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ib3dhcmQgQmVhY2gsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDRiOGFkNjVkZTg5NGM1NmJhNjY3NDc3NjVkZjVhYjMuc2V0Q29udGVudChodG1sX2EwNmRiY2VjNzgzYzQyZWE5NzZlNDdiMTRhN2Q0MGYxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzQ3YjQ3OWJlMjE5ODQ3YWI5OWJmNzM0MzhiNjIwNTQ3LmJpbmRQb3B1cChwb3B1cF8wNGI4YWQ2NWRlODk0YzU2YmE2Njc0Nzc2NWRmNWFiMyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81YTY2NGYzYTg2ZjA0MjBmOWVhNTdiNDMwNDA4MzlhZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc0MjM4MTc1MDE1NjY3LC03My44NTY4MjQ5NzM0NTI1OF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83ODY3ZDg0MWYyNjE0NmNjYjYzMTUxMzVjMzg3N2IyOCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8yN2U0MzIwNjFlOGE0YTdjOTNmMTgyZjJhMTRlMDZjYyA9ICQoJzxkaXYgaWQ9Imh0bWxfMjdlNDMyMDYxZThhNGE3YzkzZjE4MmYyYTE0ZTA2Y2MiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNvcm9uYSwgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83ODY3ZDg0MWYyNjE0NmNjYjYzMTUxMzVjMzg3N2IyOC5zZXRDb250ZW50KGh0bWxfMjdlNDMyMDYxZThhNGE3YzkzZjE4MmYyYTE0ZTA2Y2MpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNWE2NjRmM2E4NmYwNDIwZjllYTU3YjQzMDQwODM5YWQuYmluZFBvcHVwKHBvcHVwXzc4NjdkODQxZjI2MTQ2Y2NiNjMxNTEzNWMzODc3YjI4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQ1MDBjZTIxN2E0YzQwNWJhNmUzNzcxMzgxNWI1MWQ0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzI1MjYzNzgyMTY1MDMsLTczLjg0NDQ3NTAwNzg4OTgzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzg1Mjk3ZWZkODM5MDRlMWM5Nzc2YjU3YjRjNGRhOGQzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzEyM2E1MDhhZTg3MzRmYzQ4Y2M2MDU4MjU1ZjI3MWYwID0gJCgnPGRpdiBpZD0iaHRtbF8xMjNhNTA4YWU4NzM0ZmM0OGNjNjA1ODI1NWYyNzFmMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Rm9yZXN0IEhpbGxzLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzg1Mjk3ZWZkODM5MDRlMWM5Nzc2YjU3YjRjNGRhOGQzLnNldENvbnRlbnQoaHRtbF8xMjNhNTA4YWU4NzM0ZmM0OGNjNjA1ODI1NWYyNzFmMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80NTAwY2UyMTdhNGM0MDViYTZlMzc3MTM4MTViNTFkNC5iaW5kUG9wdXAocG9wdXBfODUyOTdlZmQ4MzkwNGUxYzk3NzZiNTdiNGM0ZGE4ZDMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMjEyMWM3MjEzMjlhNGZiMzgwZjI5ZTUzNjJhNjEwN2QgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MDUxNzkwMzU0MTQ4LC03My44Mjk4MTkwNTgyNTcwM10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wY2UwNzQxZjY4NmY0Yzk0OWE1MjY5NTE1NWViMGMxNSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lMDY2YWY4OWI4MGQ0ODJkOTAyOTdhZGJhMDcyYTI4YSA9ICQoJzxkaXYgaWQ9Imh0bWxfZTA2NmFmODliODBkNDgyZDkwMjk3YWRiYTA3MmEyOGEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPktldyBHYXJkZW5zLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzBjZTA3NDFmNjg2ZjRjOTQ5YTUyNjk1MTU1ZWIwYzE1LnNldENvbnRlbnQoaHRtbF9lMDY2YWY4OWI4MGQ0ODJkOTAyOTdhZGJhMDcyYTI4YSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yMTIxYzcyMTMyOWE0ZmIzODBmMjllNTM2MmE2MTA3ZC5iaW5kUG9wdXAocG9wdXBfMGNlMDc0MWY2ODZmNGM5NDlhNTI2OTUxNTVlYjBjMTUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjk3ZDgxODk2M2JhNDYzOWI5YTVmM2ZlNzY3YmQ5NjcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42OTc5NDczMTQ3MTc2MywtNzMuODMxODMzMjE0NDY4ODddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYWY0ZDk3MjNhMmMzNDA3YTg0N2QzNDY2MGNiMDc2NjYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZGJhNzFlNTEyNDgwNGYzOWE0Y2U4ZTdkYjIxYzkxNmYgPSAkKCc8ZGl2IGlkPSJodG1sX2RiYTcxZTUxMjQ4MDRmMzlhNGNlOGU3ZGIyMWM5MTZmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5SaWNobW9uZCBIaWxsLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2FmNGQ5NzIzYTJjMzQwN2E4NDdkMzQ2NjBjYjA3NjY2LnNldENvbnRlbnQoaHRtbF9kYmE3MWU1MTI0ODA0ZjM5YTRjZThlN2RiMjFjOTE2Zik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mOTdkODE4OTYzYmE0NjM5YjlhNWYzZmU3NjdiZDk2Ny5iaW5kUG9wdXAocG9wdXBfYWY0ZDk3MjNhMmMzNDA3YTg0N2QzNDY2MGNiMDc2NjYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNzg3MzIyN2FiMDBiNDE3OGI3ZDg2MmQxZmE4ZmNhZDYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43NjQ0NTQxOTY5Nzg0NiwtNzMuODMxNzczMDAzMjk1ODJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZTFjZGJhNWU4ZDhjNDZhZGI5YjI4NjM4MTE3MTY3MzMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfODUzZmIxMTllYTc3NDAxZjljNWNhMWZlNmJkNjdhNDUgPSAkKCc8ZGl2IGlkPSJodG1sXzg1M2ZiMTE5ZWE3NzQwMWY5YzVjYTFmZTZiZDY3YTQ1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5GbHVzaGluZywgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lMWNkYmE1ZThkOGM0NmFkYjliMjg2MzgxMTcxNjczMy5zZXRDb250ZW50KGh0bWxfODUzZmIxMTllYTc3NDAxZjljNWNhMWZlNmJkNjdhNDUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzg3MzIyN2FiMDBiNDE3OGI3ZDg2MmQxZmE4ZmNhZDYuYmluZFBvcHVwKHBvcHVwX2UxY2RiYTVlOGQ4YzQ2YWRiOWIyODYzODExNzE2NzMzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2M0NTIyYTBjM2M5NDRlMDM4NzE3ZDlmYWUxMDM1ZWRhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzUwMjE3MzQ2MTA1MjgsLTczLjkzOTIwMjIzOTE1NTA1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzdmYmM5MTY3ODhhMTRjNzA5Nzk3NWVjMGQ5MDFmODU4ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2UzMWYwMTA2ZGEwMTQ2ODk5ZDRmODNlMzNjNDY2OWI5ID0gJCgnPGRpdiBpZD0iaHRtbF9lMzFmMDEwNmRhMDE0Njg5OWQ0ZjgzZTMzYzQ2NjliOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TG9uZyBJc2xhbmQgQ2l0eSwgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83ZmJjOTE2Nzg4YTE0YzcwOTc5NzVlYzBkOTAxZjg1OC5zZXRDb250ZW50KGh0bWxfZTMxZjAxMDZkYTAxNDY4OTlkNGY4M2UzM2M0NjY5YjkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYzQ1MjJhMGMzYzk0NGUwMzg3MTdkOWZhZTEwMzVlZGEuYmluZFBvcHVwKHBvcHVwXzdmYmM5MTY3ODhhMTRjNzA5Nzk3NWVjMGQ5MDFmODU4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzRjMjRlZTAzMTYyNTQ3ZjdiNWJmMWU0OGE4ZDU2ZmIwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzQwMTc2MjgzNTE5MjQsLTczLjkyNjkxNjE3NTYxNTc3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2JkZDdlYWI2OTFkOTQwZGU4N2ZjZmE1YTQ2MTA2ODkyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzgyNzFiMjJkN2Q1NTRjNjY4NWFlNWI2NzkzNWVhMDRjID0gJCgnPGRpdiBpZD0iaHRtbF84MjcxYjIyZDdkNTU0YzY2ODVhZTViNjc5MzVlYTA0YyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3VubnlzaWRlLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2JkZDdlYWI2OTFkOTQwZGU4N2ZjZmE1YTQ2MTA2ODkyLnNldENvbnRlbnQoaHRtbF84MjcxYjIyZDdkNTU0YzY2ODVhZTViNjc5MzVlYTA0Yyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80YzI0ZWUwMzE2MjU0N2Y3YjViZjFlNDhhOGQ1NmZiMC5iaW5kUG9wdXAocG9wdXBfYmRkN2VhYjY5MWQ5NDBkZTg3ZmNmYTVhNDYxMDY4OTIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYmRlYWYzYmM5ZDZkNDY4OTg0MjRkMjY4MzNkOGYyMjUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43NjQwNzMyMzg4MzA5MSwtNzMuODY3MDQxNDc2NTg3NzJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNzc3MTQ2OWUwMGU4NDkyNWI2OTdlNWM3ODYxZDhmMjUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDEyOGJjYzI1MDVjNGM3NmExODBjOGFhNzA1YWZlYzYgPSAkKCc8ZGl2IGlkPSJodG1sX2QxMjhiY2MyNTA1YzRjNzZhMTgwYzhhYTcwNWFmZWM2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FYXN0IEVsbWh1cnN0LCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzc3NzE0NjllMDBlODQ5MjViNjk3ZTVjNzg2MWQ4ZjI1LnNldENvbnRlbnQoaHRtbF9kMTI4YmNjMjUwNWM0Yzc2YTE4MGM4YWE3MDVhZmVjNik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9iZGVhZjNiYzlkNmQ0Njg5ODQyNGQyNjgzM2Q4ZjIyNS5iaW5kUG9wdXAocG9wdXBfNzc3MTQ2OWUwMGU4NDkyNWI2OTdlNWM3ODYxZDhmMjUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZmNiMDQ2OTNjNTk0NDY3YzhkNTIyOGI1ZTU2NDZjOTMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MjU0MjczNzQwOTM2MDYsLTczLjg5NjIxNzEzNjI2ODU5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2ZhMzBmNGQyZDBkMTQxZTY4ZGYzZGQ2NjAxOWEyMmZiID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzA2MDFkYWJmMzNiNzRjZmVhMjA0ZWI5MGMzNmRiMWQ5ID0gJCgnPGRpdiBpZD0iaHRtbF8wNjAxZGFiZjMzYjc0Y2ZlYTIwNGViOTBjMzZkYjFkOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TWFzcGV0aCwgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mYTMwZjRkMmQwZDE0MWU2OGRmM2RkNjYwMTlhMjJmYi5zZXRDb250ZW50KGh0bWxfMDYwMWRhYmYzM2I3NGNmZWEyMDRlYjkwYzM2ZGIxZDkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZmNiMDQ2OTNjNTk0NDY3YzhkNTIyOGI1ZTU2NDZjOTMuYmluZFBvcHVwKHBvcHVwX2ZhMzBmNGQyZDBkMTQxZTY4ZGYzZGQ2NjAxOWEyMmZiKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzYwMTYyZGQ5ZDZmNDQ0OGU5N2QxYTg5OTQ2MmQ2OWMxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzA4MzIzMTU2MTM4NTgsLTczLjkwMTQzNTE3NTU5NTg5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzk5MjU3Zjk4NTBiNDRkYjdiNGIzYzU0NTc1ZTlkODI4ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2IzNWE1ZWQwNWVkYTQ0OWI4MWVlNDg1ZDBjMDMwMjAwID0gJCgnPGRpdiBpZD0iaHRtbF9iMzVhNWVkMDVlZGE0NDliODFlZTQ4NWQwYzAzMDIwMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UmlkZ2V3b29kLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzk5MjU3Zjk4NTBiNDRkYjdiNGIzYzU0NTc1ZTlkODI4LnNldENvbnRlbnQoaHRtbF9iMzVhNWVkMDVlZGE0NDliODFlZTQ4NWQwYzAzMDIwMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82MDE2MmRkOWQ2ZjQ0NDhlOTdkMWE4OTk0NjJkNjljMS5iaW5kUG9wdXAocG9wdXBfOTkyNTdmOTg1MGI0NGRiN2I0YjNjNTQ1NzVlOWQ4MjgpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMTU3NDM2OGM3YjNhNGIyNjg1MzI1OGQyMGJlMTFmNDIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MDI3NjI0Mjk2NzgzOCwtNzMuODcwNzQxNjc0MzU2MDVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzc5YTFmYjljOThjNGFmYzk3MTc2OWIzNmJlMDBlNTggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfM2Y4OWUxYWNkZjk0NDI3MmE5ZTNmOTI4NmFmOGQ1NDEgPSAkKCc8ZGl2IGlkPSJodG1sXzNmODllMWFjZGY5NDQyNzJhOWUzZjkyODZhZjhkNTQxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5HbGVuZGFsZSwgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jNzlhMWZiOWM5OGM0YWZjOTcxNzY5YjM2YmUwMGU1OC5zZXRDb250ZW50KGh0bWxfM2Y4OWUxYWNkZjk0NDI3MmE5ZTNmOTI4NmFmOGQ1NDEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMTU3NDM2OGM3YjNhNGIyNjg1MzI1OGQyMGJlMTFmNDIuYmluZFBvcHVwKHBvcHVwX2M3OWExZmI5Yzk4YzRhZmM5NzE3NjliMzZiZTAwZTU4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2FjNTljMTdlODYwZjQ0MTBhYWE2ZWY2NGY3MzI0ZjhiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzI4OTc0MDk0ODA3MzUsLTczLjg1NzgyNjg2OTA1MzddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZGYyMGFkNDBiZWY0NDY2ZWE4ZmM4YmMxZWYxM2MyNTIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYTEwYmI0ZDE4ZDFhNGU5NDliYjA0ZWQxYjZhNmRhNjYgPSAkKCc8ZGl2IGlkPSJodG1sX2ExMGJiNGQxOGQxYTRlOTQ5YmIwNGVkMWI2YTZkYTY2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5SZWdvIFBhcmssIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZGYyMGFkNDBiZWY0NDY2ZWE4ZmM4YmMxZWYxM2MyNTIuc2V0Q29udGVudChodG1sX2ExMGJiNGQxOGQxYTRlOTQ5YmIwNGVkMWI2YTZkYTY2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2FjNTljMTdlODYwZjQ0MTBhYWE2ZWY2NGY3MzI0ZjhiLmJpbmRQb3B1cChwb3B1cF9kZjIwYWQ0MGJlZjQ0NjZlYThmYzhiYzFlZjEzYzI1Mik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82ZTdhZDc5NjlhY2I0ZjQxODI0Yjk0MzEzZjdlNTllOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY4OTg4Njg3OTE1Nzg5LC03My44NTgxMTA0NjU1NDMyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzE3YzA3ZjZlZjdhZjRhMDc5ZWM3ZjdmZWQ4OTU4Y2NmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2RiMjQ4OTAzNmJlODQyNWJhZWYwY2FjMGIxZjFjMzdkID0gJCgnPGRpdiBpZD0iaHRtbF9kYjI0ODkwMzZiZTg0MjViYWVmMGNhYzBiMWYxYzM3ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V29vZGhhdmVuLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzE3YzA3ZjZlZjdhZjRhMDc5ZWM3ZjdmZWQ4OTU4Y2NmLnNldENvbnRlbnQoaHRtbF9kYjI0ODkwMzZiZTg0MjViYWVmMGNhYzBiMWYxYzM3ZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82ZTdhZDc5NjlhY2I0ZjQxODI0Yjk0MzEzZjdlNTllOC5iaW5kUG9wdXAocG9wdXBfMTdjMDdmNmVmN2FmNGEwNzllYzdmN2ZlZDg5NThjY2YpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYmYyNzJmN2UwOTNjNGI0YWE2MjEwNTQ0ZDhmMGQ5ZmIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42ODA3MDg0NjgyNjU0MTUsLTczLjg0MzIwMjY2MTczNDQ3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzVmY2EwYzFiY2JhNjRkNDBiZDM3ZjI0YmFjMjI2YjEwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzZhZDcyZjRkNzQxMjQ1OWE5ZWEwNDEyYmQ2NzlkM2ZmID0gJCgnPGRpdiBpZD0iaHRtbF82YWQ3MmY0ZDc0MTI0NTlhOWVhMDQxMmJkNjc5ZDNmZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+T3pvbmUgUGFyaywgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81ZmNhMGMxYmNiYTY0ZDQwYmQzN2YyNGJhYzIyNmIxMC5zZXRDb250ZW50KGh0bWxfNmFkNzJmNGQ3NDEyNDU5YTllYTA0MTJiZDY3OWQzZmYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYmYyNzJmN2UwOTNjNGI0YWE2MjEwNTQ0ZDhmMGQ5ZmIuYmluZFBvcHVwKHBvcHVwXzVmY2EwYzFiY2JhNjRkNDBiZDM3ZjI0YmFjMjI2YjEwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I1MWMwMzI5YWM4MzQ3ZjM4NDU2ODVkNTkwODYwNmQ2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjY4NTQ5NTc3NjcxOTUsLTczLjgwOTg2NDc4NjQ5MDQxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzMwZTkwMWU3Zjc0YjQ0Mjk5ZTY5ZTJkOGIwN2YzZWJkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2RjYjVkZTQ3YzNiZTQwMjE4N2IxOTQ1NTkyYTc1ODQxID0gJCgnPGRpdiBpZD0iaHRtbF9kY2I1ZGU0N2MzYmU0MDIxODdiMTk0NTU5MmE3NTg0MSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U291dGggT3pvbmUgUGFyaywgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zMGU5MDFlN2Y3NGI0NDI5OWU2OWUyZDhiMDdmM2ViZC5zZXRDb250ZW50KGh0bWxfZGNiNWRlNDdjM2JlNDAyMTg3YjE5NDU1OTJhNzU4NDEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjUxYzAzMjlhYzgzNDdmMzg0NTY4NWQ1OTA4NjA2ZDYuYmluZFBvcHVwKHBvcHVwXzMwZTkwMWU3Zjc0YjQ0Mjk5ZTY5ZTJkOGIwN2YzZWJkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzE1ZTAzMWJlZmUyMjQ3MGU4NDRiZGNiNjM4YjJiNmY4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzg0OTAyNzQ5MjYwMjA1LC03My44NDMwNDUyODg5NjEyNV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iMmU3MmMwZTZjZDM0ZWYxODljMTYwMjg2ZDQ3NjNhOSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81YmQwOGI3MTRkZDg0ZDlkODkzZmRiNTQ0NmM4ZDc0NiA9ICQoJzxkaXYgaWQ9Imh0bWxfNWJkMDhiNzE0ZGQ4NGQ5ZDg5M2ZkYjU0NDZjOGQ3NDYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNvbGxlZ2UgUG9pbnQsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjJlNzJjMGU2Y2QzNGVmMTg5YzE2MDI4NmQ0NzYzYTkuc2V0Q29udGVudChodG1sXzViZDA4YjcxNGRkODRkOWQ4OTNmZGI1NDQ2YzhkNzQ2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzE1ZTAzMWJlZmUyMjQ3MGU4NDRiZGNiNjM4YjJiNmY4LmJpbmRQb3B1cChwb3B1cF9iMmU3MmMwZTZjZDM0ZWYxODljMTYwMjg2ZDQ3NjNhOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83ZDJiNjM1Mjg1ODE0MjVhODFjYjc0ZTkyMzAzZWQ1YSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc4MTI5MDc2NjAyNjk0LC03My44MTQyMDIxNjYxMDg2M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mODg1Y2NhMjhiNzY0MDUwOWE2ZGQxYzE1MTQwZGNmNSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wZDQ1MDg3YzQ4ODY0ZWYwYTYwNTA2ZWQxMzg3NGFhMiA9ICQoJzxkaXYgaWQ9Imh0bWxfMGQ0NTA4N2M0ODg2NGVmMGE2MDUwNmVkMTM4NzRhYTIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldoaXRlc3RvbmUsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZjg4NWNjYTI4Yjc2NDA1MDlhNmRkMWMxNTE0MGRjZjUuc2V0Q29udGVudChodG1sXzBkNDUwODdjNDg4NjRlZjBhNjA1MDZlZDEzODc0YWEyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzdkMmI2MzUyODU4MTQyNWE4MWNiNzRlOTIzMDNlZDVhLmJpbmRQb3B1cChwb3B1cF9mODg1Y2NhMjhiNzY0MDUwOWE2ZGQxYzE1MTQwZGNmNSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mMTcxMTNiZTU2YzE0NTQ5YjJmNWU0NjMzOWI5OTdlOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc2NjA0MDYzMjgxMDY0LC03My43NzQyNzM2MzA2ODY3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzQ0NzdmZDBhYzIxZTQxNzlhMmU1MzIxY2M0OWMyYzI3ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2YzYmQyNjk0Yjk2MTQxZTY4NWZhMjgyMWI5OTQzYWY3ID0gJCgnPGRpdiBpZD0iaHRtbF9mM2JkMjY5NGI5NjE0MWU2ODVmYTI4MjFiOTk0M2FmNyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmF5c2lkZSwgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80NDc3ZmQwYWMyMWU0MTc5YTJlNTMyMWNjNDljMmMyNy5zZXRDb250ZW50KGh0bWxfZjNiZDI2OTRiOTYxNDFlNjg1ZmEyODIxYjk5NDNhZjcpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjE3MTEzYmU1NmMxNDU0OWIyZjVlNDYzMzliOTk3ZTguYmluZFBvcHVwKHBvcHVwXzQ0NzdmZDBhYzIxZTQxNzlhMmU1MzIxY2M0OWMyYzI3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2U3NTcxMWE4MzNlYjQ0MjBhY2JjNzU0ZGJmNGEzYWUzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzYxNzI5NTQ5MDMyNjIsLTczLjc5MTc2MjQzNzI4MDYxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzRkNGIwYTMzMzQ4NTQ5M2RiZWIyMGJmYjkwYjFkNzBhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2M0MWYzNDdiNjVkMTQxNDBhMDAxMzMyOTYwZjU0Yjc5ID0gJCgnPGRpdiBpZD0iaHRtbF9jNDFmMzQ3YjY1ZDE0MTQwYTAwMTMzMjk2MGY1NGI3OSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QXVidXJuZGFsZSwgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80ZDRiMGEzMzM0ODU0OTNkYmViMjBiZmI5MGIxZDcwYS5zZXRDb250ZW50KGh0bWxfYzQxZjM0N2I2NWQxNDE0MGEwMDEzMzI5NjBmNTRiNzkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZTc1NzExYTgzM2ViNDQyMGFjYmM3NTRkYmY0YTNhZTMuYmluZFBvcHVwKHBvcHVwXzRkNGIwYTMzMzQ4NTQ5M2RiZWIyMGJmYjkwYjFkNzBhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2FkOWY4ZDcyNmNkYzQ1OGRiMjZhY2I3OGVjNGJkYzhkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzcwODI2MTkyODI2NywtNzMuNzM4ODk3NzU1ODA3NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85MTk2Y2M2NDVlOTM0YWU5ODFlNzk3ZDdlODA2NDc4NiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83ZTU4MTBiY2I2NWU0OGY0YWE2NWMzZTY4ZmE1MjIyZSA9ICQoJzxkaXYgaWQ9Imh0bWxfN2U1ODEwYmNiNjVlNDhmNGFhNjVjM2U2OGZhNTIyMmUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxpdHRsZSBOZWNrLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzkxOTZjYzY0NWU5MzRhZTk4MWU3OTdkN2U4MDY0Nzg2LnNldENvbnRlbnQoaHRtbF83ZTU4MTBiY2I2NWU0OGY0YWE2NWMzZTY4ZmE1MjIyZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hZDlmOGQ3MjZjZGM0NThkYjI2YWNiNzhlYzRiZGM4ZC5iaW5kUG9wdXAocG9wdXBfOTE5NmNjNjQ1ZTkzNGFlOTgxZTc5N2Q3ZTgwNjQ3ODYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYzBmM2JkYjliNTZmNGVhZDkxOGU5MTFjM2I5YTEwZjMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43NjY4NDYwOTc5MDc2MywtNzMuNzQyNDk4MjA3MjczM10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80N2Q5ZGYxOWJlYzM0YjkyYTEwODA4NDVhMzg1MDQyNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81NWY1YzcwODlmZWM0ZGY3ODUyZjFhNWZhZTY2Yzg5OSA9ICQoJzxkaXYgaWQ9Imh0bWxfNTVmNWM3MDg5ZmVjNGRmNzg1MmYxYTVmYWU2NmM4OTkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvdWdsYXN0b24sIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNDdkOWRmMTliZWMzNGI5MmExMDgwODQ1YTM4NTA0Mjcuc2V0Q29udGVudChodG1sXzU1ZjVjNzA4OWZlYzRkZjc4NTJmMWE1ZmFlNjZjODk5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2MwZjNiZGI5YjU2ZjRlYWQ5MThlOTExYzNiOWExMGYzLmJpbmRQb3B1cChwb3B1cF80N2Q5ZGYxOWJlYzM0YjkyYTEwODA4NDVhMzg1MDQyNyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xYmYyZDIwM2RmZTY0N2Q3OTQ3NzUwN2YyMTU0MDFiYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc0OTQ0MDc5OTc0MzMyLC03My43MTU0ODExODk5OTE0NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kN2U5Y2Q2NWFiMDY0ZWI1OWJjOGY1YWViNzAzMTg0NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xNTNmOTFjNzU0ZTY0ODljYTg4NzdjNTc1MWNmZWYyMiA9ICQoJzxkaXYgaWQ9Imh0bWxfMTUzZjkxYzc1NGU2NDg5Y2E4ODc3YzU3NTFjZmVmMjIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkdsZW4gT2FrcywgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9kN2U5Y2Q2NWFiMDY0ZWI1OWJjOGY1YWViNzAzMTg0NC5zZXRDb250ZW50KGh0bWxfMTUzZjkxYzc1NGU2NDg5Y2E4ODc3YzU3NTFjZmVmMjIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMWJmMmQyMDNkZmU2NDdkNzk0Nzc1MDdmMjE1NDAxYmIuYmluZFBvcHVwKHBvcHVwX2Q3ZTljZDY1YWIwNjRlYjU5YmM4ZjVhZWI3MDMxODQ0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzZmZjNkNTViZGM1NjQ2MjdiMjM1ZDM4MjcyOTM1NjM0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzI4NTczMTgxNzY2NzUsLTczLjcyMDEyODE0ODI2OTAzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzMxZGFhNDFjYjIzOTRlY2M4MDM2ZTJjZTQxYzFhZTI4ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2E1MDQ3NTQxM2QzYjQ2ODM5OWQzNDZmMDYxMGI2YmU3ID0gJCgnPGRpdiBpZD0iaHRtbF9hNTA0NzU0MTNkM2I0NjgzOTlkMzQ2ZjA2MTBiNmJlNyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmVsbGVyb3NlLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzMxZGFhNDFjYjIzOTRlY2M4MDM2ZTJjZTQxYzFhZTI4LnNldENvbnRlbnQoaHRtbF9hNTA0NzU0MTNkM2I0NjgzOTlkMzQ2ZjA2MTBiNmJlNyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82ZmYzZDU1YmRjNTY0NjI3YjIzNWQzODI3MjkzNTYzNC5iaW5kUG9wdXAocG9wdXBfMzFkYWE0MWNiMjM5NGVjYzgwMzZlMmNlNDFjMWFlMjgpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODQ3NDliM2E0ZDJlNDE0ODk4OTljZjM5MTI3ZDg2ZGYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MjI1NzgyNDQyMjgwNDYsLTczLjgyMDg3NzY0OTMzNTY2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzk1NWMzMGE0ZjQ4ZjQ0ODJiMjIyNThhNWEzMDVjMjcxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2M3MWJmMTVjY2Y0ZjRlYjZhZGExOWI2MTY1NjExN2JmID0gJCgnPGRpdiBpZD0iaHRtbF9jNzFiZjE1Y2NmNGY0ZWI2YWRhMTliNjE2NTYxMTdiZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+S2V3IEdhcmRlbnMgSGlsbHMsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOTU1YzMwYTRmNDhmNDQ4MmIyMjI1OGE1YTMwNWMyNzEuc2V0Q29udGVudChodG1sX2M3MWJmMTVjY2Y0ZjRlYjZhZGExOWI2MTY1NjExN2JmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzg0NzQ5YjNhNGQyZTQxNDg5ODk5Y2YzOTEyN2Q4NmRmLmJpbmRQb3B1cChwb3B1cF85NTVjMzBhNGY0OGY0NDgyYjIyMjU4YTVhMzA1YzI3MSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hYmM2ZWE5NDI0MTg0N2MzYTdmMzQxNzVkZjQzZWJjOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjczNDM5NDQ2NTMzMTMsLTczLjc4MjcxMzM3MDAzMjY0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2M0Nzk2NTAxOGRhMDQ1YjhiZGFkMjBkOTg1N2ExNGQ1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzk5OGQ0MjVmYjM2YTQ1NmI5MWY1ODY0ODUwMjhiYWRkID0gJCgnPGRpdiBpZD0iaHRtbF85OThkNDI1ZmIzNmE0NTZiOTFmNTg2NDg1MDI4YmFkZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RnJlc2ggTWVhZG93cywgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jNDc5NjUwMThkYTA0NWI4YmRhZDIwZDk4NTdhMTRkNS5zZXRDb250ZW50KGh0bWxfOTk4ZDQyNWZiMzZhNDU2YjkxZjU4NjQ4NTAyOGJhZGQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYWJjNmVhOTQyNDE4NDdjM2E3ZjM0MTc1ZGY0M2ViYzguYmluZFBvcHVwKHBvcHVwX2M0Nzk2NTAxOGRhMDQ1YjhiZGFkMjBkOTg1N2ExNGQ1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY4MjIxZmI3NjZmNjQ4YzY5NTJiOTllOTdhZWYxZjU4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzEwOTM1NDcyNTIyNzEsLTczLjgxMTc0ODIyNDU4NjM0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2YyM2EyYjg5Y2JlYTRjMTNiZTgxZTI1NDllNDg1NWYwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzJlNjU0YjhmNmU4ODRhMjQ4NWEyMTJmODBjYjAyZTk3ID0gJCgnPGRpdiBpZD0iaHRtbF8yZTY1NGI4ZjZlODg0YTI0ODVhMjEyZjgwY2IwMmU5NyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnJpYXJ3b29kLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2YyM2EyYjg5Y2JlYTRjMTNiZTgxZTI1NDllNDg1NWYwLnNldENvbnRlbnQoaHRtbF8yZTY1NGI4ZjZlODg0YTI0ODVhMjEyZjgwY2IwMmU5Nyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82ODIyMWZiNzY2ZjY0OGM2OTUyYjk5ZTk3YWVmMWY1OC5iaW5kUG9wdXAocG9wdXBfZjIzYTJiODljYmVhNGMxM2JlODFlMjU0OWU0ODU1ZjApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODIyNzZlN2I1NDg1NGEzZThiZWM5YjkxNzhjYWFkOWYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MDQ2NTczNjA2ODcxNywtNzMuNzk2OTAxNjU4ODgyODldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfODU4ZjEzMTkwZTlkNDRhOTkxZjg3ZjRhMmQ4OGNhMDggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZTYwZDUxYjE5MzdlNGViMWJlMzY0ZGUzMzNiNTM4NzIgPSAkKCc8ZGl2IGlkPSJodG1sX2U2MGQ1MWIxOTM3ZTRlYjFiZTM2NGRlMzMzYjUzODcyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5KYW1haWNhIENlbnRlciwgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84NThmMTMxOTBlOWQ0NGE5OTFmODdmNGEyZDg4Y2EwOC5zZXRDb250ZW50KGh0bWxfZTYwZDUxYjE5MzdlNGViMWJlMzY0ZGUzMzNiNTM4NzIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODIyNzZlN2I1NDg1NGEzZThiZWM5YjkxNzhjYWFkOWYuYmluZFBvcHVwKHBvcHVwXzg1OGYxMzE5MGU5ZDQ0YTk5MWY4N2Y0YTJkODhjYTA4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I2NmI1MmI2MDliMDRkNjM4ZDZhYTNhNGEwOGU1MTBiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzQ1NjE4NTcxNDE4NTUsLTczLjc1NDk0OTc2MjM0MzMyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzI1ZDU5OWMxZDFiMTRmMGNiN2I3OTdiODIzNzc4YmYyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzk5ODNhYzY4MThiZDQ4NzViOTZhOWM5MGVlNmZjMWNhID0gJCgnPGRpdiBpZD0iaHRtbF85OTgzYWM2ODE4YmQ0ODc1Yjk2YTljOTBlZTZmYzFjYSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+T2FrbGFuZCBHYXJkZW5zLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzI1ZDU5OWMxZDFiMTRmMGNiN2I3OTdiODIzNzc4YmYyLnNldENvbnRlbnQoaHRtbF85OTgzYWM2ODE4YmQ0ODc1Yjk2YTljOTBlZTZmYzFjYSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9iNjZiNTJiNjA5YjA0ZDYzOGQ2YWEzYTRhMDhlNTEwYi5iaW5kUG9wdXAocG9wdXBfMjVkNTk5YzFkMWIxNGYwY2I3Yjc5N2I4MjM3NzhiZjIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMThmYjc5MGFjODQxNDU4OTkzZWNhMDA2ZmVjMjJhYTUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTg4OTMwOTIxNjczNTYsLTczLjczODcxNDg0NTc4NDI0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2Y0NDQyNzk2ZGYzYjQzMmRhYTViYjdmOTk1Nzg4ODM0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2E3ZGYwNWU4Y2Y5MzQ4NmQ4OTQyMGFkYTBiOTM4YzIxID0gJCgnPGRpdiBpZD0iaHRtbF9hN2RmMDVlOGNmOTM0ODZkODk0MjBhZGEwYjkzOGMyMSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UXVlZW5zIFZpbGxhZ2UsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZjQ0NDI3OTZkZjNiNDMyZGFhNWJiN2Y5OTU3ODg4MzQuc2V0Q29udGVudChodG1sX2E3ZGYwNWU4Y2Y5MzQ4NmQ4OTQyMGFkYTBiOTM4YzIxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzE4ZmI3OTBhYzg0MTQ1ODk5M2VjYTAwNmZlYzIyYWE1LmJpbmRQb3B1cChwb3B1cF9mNDQ0Mjc5NmRmM2I0MzJkYWE1YmI3Zjk5NTc4ODgzNCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xNjk4OTRmYThjODE0OTBlOWZhYmEyYzVmMjBiZmQ0YiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcxMTI0MzQ0MTkxOTA0LC03My43NTkyNTAwOTMzNTU5NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85NTE1ZDg3Njk1MWI0ZWQ5YjBhOGU3NGMzYmM2ZDJjMSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zMTVkY2FhNTBkOTc0YTkzYTQ4ZjY4MGJmMjY1YWFlMiA9ICQoJzxkaXYgaWQ9Imh0bWxfMzE1ZGNhYTUwZDk3NGE5M2E0OGY2ODBiZjI2NWFhZTIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhvbGxpcywgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85NTE1ZDg3Njk1MWI0ZWQ5YjBhOGU3NGMzYmM2ZDJjMS5zZXRDb250ZW50KGh0bWxfMzE1ZGNhYTUwZDk3NGE5M2E0OGY2ODBiZjI2NWFhZTIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMTY5ODk0ZmE4YzgxNDkwZTlmYWJhMmM1ZjIwYmZkNGIuYmluZFBvcHVwKHBvcHVwXzk1MTVkODc2OTUxYjRlZDliMGE4ZTc0YzNiYzZkMmMxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzgxNTFjYmZkMTRiODQxNDA4YmEyNTAzMjY4ZTMxNThhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjk2OTExMjUzNzg5ODg1LC03My43OTA0MjYxMzEzNTU0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzI2OWEzNGYzNzVmMDQ2MzBhNWNhOWIwN2FjNzMwMDRmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2NiZDc4NThmYjY3MTRkZThhMGU4ZTYwZDBhZGUyZjI2ID0gJCgnPGRpdiBpZD0iaHRtbF9jYmQ3ODU4ZmI2NzE0ZGU4YTBlOGU2MGQwYWRlMmYyNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U291dGggSmFtYWljYSwgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yNjlhMzRmMzc1ZjA0NjMwYTVjYTliMDdhYzczMDA0Zi5zZXRDb250ZW50KGh0bWxfY2JkNzg1OGZiNjcxNGRlOGEwZThlNjBkMGFkZTJmMjYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODE1MWNiZmQxNGI4NDE0MDhiYTI1MDMyNjhlMzE1OGEuYmluZFBvcHVwKHBvcHVwXzI2OWEzNGYzNzVmMDQ2MzBhNWNhOWIwN2FjNzMwMDRmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzg3YTlhODQwODNkOTQ0MjY4OTM5Y2Y2MjAwNWYxNjU3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjk0NDQ1Mzg1MjIzNTksLTczLjc1ODY3NjAzNzI3NzE3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzUwZDdiNDBjNGYwODQ5MjBiZmI3ODU5YThiMjVmNmYyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzhiYmNmMTk5MjBhZjQzYjFiN2RjYzIzYjY1YmJkNDI5ID0gJCgnPGRpdiBpZD0iaHRtbF84YmJjZjE5OTIwYWY0M2IxYjdkY2MyM2I2NWJiZDQyOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3QuIEFsYmFucywgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81MGQ3YjQwYzRmMDg0OTIwYmZiNzg1OWE4YjI1ZjZmMi5zZXRDb250ZW50KGh0bWxfOGJiY2YxOTkyMGFmNDNiMWI3ZGNjMjNiNjViYmQ0MjkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODdhOWE4NDA4M2Q5NDQyNjg5MzljZjYyMDA1ZjE2NTcuYmluZFBvcHVwKHBvcHVwXzUwZDdiNDBjNGYwODQ5MjBiZmI3ODU5YThiMjVmNmYyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzVmMDg1OWMxNTFlNzQ4NDJiNzlmYzM3NjhkNWE0YTM0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjc1MjExMzk1OTE3MzMsLTczLjc3MjU4Nzg3NjIwOTA2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzJmY2YyN2E0OGMzMzRhNjQ5N2UwNWUwYmZkMGU4Zjk0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzZjY2UxNDlmMmYwMzQyNjE4MmQ5Y2EzOTkxNDI4ODhhID0gJCgnPGRpdiBpZD0iaHRtbF82Y2NlMTQ5ZjJmMDM0MjYxODJkOWNhMzk5MTQyODg4YSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Um9jaGRhbGUsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMmZjZjI3YTQ4YzMzNGE2NDk3ZTA1ZTBiZmQwZThmOTQuc2V0Q29udGVudChodG1sXzZjY2UxNDlmMmYwMzQyNjE4MmQ5Y2EzOTkxNDI4ODhhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzVmMDg1OWMxNTFlNzQ4NDJiNzlmYzM3NjhkNWE0YTM0LmJpbmRQb3B1cChwb3B1cF8yZmNmMjdhNDhjMzM0YTY0OTdlMDVlMGJmZDBlOGY5NCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xZmEwNDZmN2I1NTg0NjBiYjUwYzE3NDVjM2Y2ZGU0ZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY2NjIzMDQ5MDM2ODU4NCwtNzMuNzYwNDIwOTI2ODIyODddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzczZWFjZGYzMjI4NGViOGFlNjYzMDA2MTVhOGQ1M2MgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYjk4OWE4ODg5OWFmNGI0ZjkxMTM0YTgxMjY4M2I5OTggPSAkKCc8ZGl2IGlkPSJodG1sX2I5ODlhODg4OTlhZjRiNGY5MTEzNGE4MTI2ODNiOTk4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TcHJpbmdmaWVsZCBHYXJkZW5zLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzM3M2VhY2RmMzIyODRlYjhhZTY2MzAwNjE1YThkNTNjLnNldENvbnRlbnQoaHRtbF9iOTg5YTg4ODk5YWY0YjRmOTExMzRhODEyNjgzYjk5OCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xZmEwNDZmN2I1NTg0NjBiYjUwYzE3NDVjM2Y2ZGU0ZS5iaW5kUG9wdXAocG9wdXBfMzczZWFjZGYzMjI4NGViOGFlNjYzMDA2MTVhOGQ1M2MpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfM2NlNTY1NDlkMDhjNGQ2NGFjMWQ1ZDhjODNkZjhlZTUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42OTI3NzQ2MzkxNjA4NDUsLTczLjczNTI2ODczNzA4MDI2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2IxNDJiOGZhZjNkYTQ2ZTA4OTg0Y2VhZDI5NzFhZmFiID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzg5ODMyMGY1MThiZDRlNzdhMzhiYWY2MGIxMzUyZTIwID0gJCgnPGRpdiBpZD0iaHRtbF84OTgzMjBmNTE4YmQ0ZTc3YTM4YmFmNjBiMTM1MmUyMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q2FtYnJpYSBIZWlnaHRzLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2IxNDJiOGZhZjNkYTQ2ZTA4OTg0Y2VhZDI5NzFhZmFiLnNldENvbnRlbnQoaHRtbF84OTgzMjBmNTE4YmQ0ZTc3YTM4YmFmNjBiMTM1MmUyMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zY2U1NjU0OWQwOGM0ZDY0YWMxZDVkOGM4M2RmOGVlNS5iaW5kUG9wdXAocG9wdXBfYjE0MmI4ZmFmM2RhNDZlMDg5ODRjZWFkMjk3MWFmYWIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZDUzNjViOTViOTNmNGI3NTgzZjA1OThmZWI5NWNlZmEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42NTk4MTY0MzM0MjgwODQsLTczLjczNTI2MDc5NDI4Mjc4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzlkNTc4MTIwYTA4YzQ3OWJiMjZkNGJiNDdjYzYzYTdkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2U4OTY3Mzk0YzQzMDRlNGE5MDMwZTlhMDE1MjZiZDFlID0gJCgnPGRpdiBpZD0iaHRtbF9lODk2NzM5NGM0MzA0ZTRhOTAzMGU5YTAxNTI2YmQxZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Um9zZWRhbGUsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOWQ1NzgxMjBhMDhjNDc5YmIyNmQ0YmI0N2NjNjNhN2Quc2V0Q29udGVudChodG1sX2U4OTY3Mzk0YzQzMDRlNGE5MDMwZTlhMDE1MjZiZDFlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2Q1MzY1Yjk1YjkzZjRiNzU4M2YwNTk4ZmViOTVjZWZhLmJpbmRQb3B1cChwb3B1cF85ZDU3ODEyMGEwOGM0NzliYjI2ZDRiYjQ3Y2M2M2E3ZCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84MmQzMTNjZjc5YmE0MzM2YjdjMGJmNzM5Yzc5NjEwZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjYwMzEzNDQzMjUwMDg5NCwtNzMuNzU0OTc5NjgwNDM4NzJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjVkYzZlODI5MTY2NDA4ZWJmNjAxNjM1ZDJhMGM0NDYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMTYwOGY2YWFiYTkyNGUzYjhmMDgyOGMwZGEyODVjM2EgPSAkKCc8ZGl2IGlkPSJodG1sXzE2MDhmNmFhYmE5MjRlM2I4ZjA4MjhjMGRhMjg1YzNhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5GYXIgUm9ja2F3YXksIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZjVkYzZlODI5MTY2NDA4ZWJmNjAxNjM1ZDJhMGM0NDYuc2V0Q29udGVudChodG1sXzE2MDhmNmFhYmE5MjRlM2I4ZjA4MjhjMGRhMjg1YzNhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzgyZDMxM2NmNzliYTQzMzZiN2MwYmY3MzljNzk2MTBlLmJpbmRQb3B1cChwb3B1cF9mNWRjNmU4MjkxNjY0MDhlYmY2MDE2MzVkMmEwYzQ0Nik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83M2IxZDBhYmM2MDM0YTZmODA5NTg1ZmYxYTQyNjQwZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjYwMzAyNjU4MzUxMjM4LC03My44MjAwNTQ4OTExMDMyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2I3ZWZmOWM0NjhkNjRjMWM4OTI4ZDIzMTJjOWI3NWM1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2U2M2QwYzBkZTNiNjQ5YTdiMWFhOWYzZDgzODhkNDE0ID0gJCgnPGRpdiBpZD0iaHRtbF9lNjNkMGMwZGUzYjY0OWE3YjFhYTlmM2Q4Mzg4ZDQxNCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnJvYWQgQ2hhbm5lbCwgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iN2VmZjljNDY4ZDY0YzFjODkyOGQyMzEyYzliNzVjNS5zZXRDb250ZW50KGh0bWxfZTYzZDBjMGRlM2I2NDlhN2IxYWE5ZjNkODM4OGQ0MTQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzNiMWQwYWJjNjAzNGE2ZjgwOTU4NWZmMWE0MjY0MGUuYmluZFBvcHVwKHBvcHVwX2I3ZWZmOWM0NjhkNjRjMWM4OTI4ZDIzMTJjOWI3NWM1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzAwMmI5ZGFmZDMzNDRiZDViZDQzYmJiNjgxODhiZTJmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTU3NDAxMjg4NDU0NTIsLTczLjkyNTUxMTk2OTk0MTY4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzA0OWU4OTFlMTI0YzRiN2VhZDBkOWMxZDkxMjVlNjc5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzczZWU3MDZmMzQ2MDRhMzY5NmQ5NDlmMWMxOGYzMTMxID0gJCgnPGRpdiBpZD0iaHRtbF83M2VlNzA2ZjM0NjA0YTM2OTZkOTQ5ZjFjMThmMzEzMSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnJlZXp5IFBvaW50LCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzA0OWU4OTFlMTI0YzRiN2VhZDBkOWMxZDkxMjVlNjc5LnNldENvbnRlbnQoaHRtbF83M2VlNzA2ZjM0NjA0YTM2OTZkOTQ5ZjFjMThmMzEzMSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wMDJiOWRhZmQzMzQ0YmQ1YmQ0M2JiYjY4MTg4YmUyZi5iaW5kUG9wdXAocG9wdXBfMDQ5ZTg5MWUxMjRjNGI3ZWFkMGQ5YzFkOTEyNWU2NzkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZGM1NmYyODAyM2ZiNGJiY2EyZmZiODA0NzZiZjUxYWEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43NzU5MjMwMTU2NDI4OTYsLTczLjkwMjI4OTYwMzkxNjczXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzBjYjA4YmZlZjg1MjRlOWJiOTFjMWI0N2Q2OTk2ZDM0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc1ZGNlZWJjN2RkMzQzY2I4M2Q1ZTQ4ODgzYWU4MTE2ID0gJCgnPGRpdiBpZD0iaHRtbF83NWRjZWViYzdkZDM0M2NiODNkNWU0ODg4M2FlODExNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3RlaW53YXksIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMGNiMDhiZmVmODUyNGU5YmI5MWMxYjQ3ZDY5OTZkMzQuc2V0Q29udGVudChodG1sXzc1ZGNlZWJjN2RkMzQzY2I4M2Q1ZTQ4ODgzYWU4MTE2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2RjNTZmMjgwMjNmYjRiYmNhMmZmYjgwNDc2YmY1MWFhLmJpbmRQb3B1cChwb3B1cF8wY2IwOGJmZWY4NTI0ZTliYjkxYzFiNDdkNjk5NmQzNCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xOGYxNzE4ZGY0MTA0Njg4YjE2NjI2ZjdjNGIxOGQ2MCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc5Mjc4MTQwMzYwMDQ4LC03My44MDQzNjQ1MTcyMDk4OF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zYzZhYzExMGMxZjU0ZmVkYmM5NDM5ODExZDQ0OThhOSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lYmZjNzBiMDYxNDM0OWI4ODc2NTc1M2ExYWRhZTZmZCA9ICQoJzxkaXYgaWQ9Imh0bWxfZWJmYzcwYjA2MTQzNDliODg3NjU3NTNhMWFkYWU2ZmQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJlZWNoaHVyc3QsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfM2M2YWMxMTBjMWY1NGZlZGJjOTQzOTgxMWQ0NDk4YTkuc2V0Q29udGVudChodG1sX2ViZmM3MGIwNjE0MzQ5Yjg4NzY1NzUzYTFhZGFlNmZkKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzE4ZjE3MThkZjQxMDQ2ODhiMTY2MjZmN2M0YjE4ZDYwLmJpbmRQb3B1cChwb3B1cF8zYzZhYzExMGMxZjU0ZmVkYmM5NDM5ODExZDQ0OThhOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yZTcyYTlmNGQ1MDU0ZDYwYTRiYTdjM2E2Yjg2MDhiNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc4Mjg0MjgwNjI0NTU1NCwtNzMuNzc2ODAyMjI2MjE1OF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80ZDk3NTUxYzE5NWE0ZTU4OTY2NTNiZjNiOGY2ZjYzNiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lMTE5ZmI3MDljM2Q0NjkxYTU2ZWJmYWZhYzJhMzk4ZSA9ICQoJzxkaXYgaWQ9Imh0bWxfZTExOWZiNzA5YzNkNDY5MWE1NmViZmFmYWMyYTM5OGUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJheSBUZXJyYWNlLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzRkOTc1NTFjMTk1YTRlNTg5NjY1M2JmM2I4ZjZmNjM2LnNldENvbnRlbnQoaHRtbF9lMTE5ZmI3MDljM2Q0NjkxYTU2ZWJmYWZhYzJhMzk4ZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yZTcyYTlmNGQ1MDU0ZDYwYTRiYTdjM2E2Yjg2MDhiNS5iaW5kUG9wdXAocG9wdXBfNGQ5NzU1MWMxOTVhNGU1ODk2NjUzYmYzYjhmNmY2MzYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMTUxMzYwMGQwMzVkNDg1YThiNTk3NDRmNzk0NDA5YTAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC41OTU2NDE4MDczNjg0OTQsLTczLjc3NjEzMjgyMzkxNzA1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzkwNTUzYTlhZDFiMTQyNTNiN2VmNjJjZTgyODUxY2M4ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzM1ZGEwZjE1YjUwNjRmNDFhNGZhODI0NjkyMDNjOGJmID0gJCgnPGRpdiBpZD0iaHRtbF8zNWRhMGYxNWI1MDY0ZjQxYTRmYTgyNDY5MjAzYzhiZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RWRnZW1lcmUsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOTA1NTNhOWFkMWIxNDI1M2I3ZWY2MmNlODI4NTFjYzguc2V0Q29udGVudChodG1sXzM1ZGEwZjE1YjUwNjRmNDFhNGZhODI0NjkyMDNjOGJmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzE1MTM2MDBkMDM1ZDQ4NWE4YjU5NzQ0Zjc5NDQwOWEwLmJpbmRQb3B1cChwb3B1cF85MDU1M2E5YWQxYjE0MjUzYjdlZjYyY2U4Mjg1MWNjOCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yZTI0NmMxZjI0Nzc0NWJhYTRkZWZlNDkyN2ZkYTU0YSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjU4OTE0Mzk0MzcyOTcxLC03My43OTE5OTIzMzEzNjk0M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82M2RmZjYxYzcxMTQ0Zjg0YmEzOWFiMTQxODMzNDA5MCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wNTMyMDRhYjIwYzU0MWNhYjA4MTBiZTcxZWU0ODJlOCA9ICQoJzxkaXYgaWQ9Imh0bWxfMDUzMjA0YWIyMGM1NDFjYWIwODEwYmU3MWVlNDgyZTgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkFydmVybmUsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNjNkZmY2MWM3MTE0NGY4NGJhMzlhYjE0MTgzMzQwOTAuc2V0Q29udGVudChodG1sXzA1MzIwNGFiMjBjNTQxY2FiMDgxMGJlNzFlZTQ4MmU4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzJlMjQ2YzFmMjQ3NzQ1YmFhNGRlZmU0OTI3ZmRhNTRhLmJpbmRQb3B1cChwb3B1cF82M2RmZjYxYzcxMTQ0Zjg0YmEzOWFiMTQxODMzNDA5MCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lMWE1OWYzZmQ5MjY0ZjEwYjQ4OGQ0MGJlZTAyNDRiNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjU4MjgwMTY5Njg0NTU4NiwtNzMuODIyMzYxMjEwODg3NTFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYmQ5NGIwNDYyNTg2NDE1ZDk5NTYzNjc4NDk0MzVkZjcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMzM2ZGZlMjBmNDI3NGUwZThmOWZhYmViZTc0M2ZlZmYgPSAkKCc8ZGl2IGlkPSJodG1sXzMzNmRmZTIwZjQyNzRlMGU4ZjlmYWJlYmU3NDNmZWZmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Sb2NrYXdheSBCZWFjaCwgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iZDk0YjA0NjI1ODY0MTVkOTk1NjM2Nzg0OTQzNWRmNy5zZXRDb250ZW50KGh0bWxfMzM2ZGZlMjBmNDI3NGUwZThmOWZhYmViZTc0M2ZlZmYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZTFhNTlmM2ZkOTI2NGYxMGI0ODhkNDBiZWUwMjQ0YjQuYmluZFBvcHVwKHBvcHVwX2JkOTRiMDQ2MjU4NjQxNWQ5OTU2MzY3ODQ5NDM1ZGY3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzkyN2EwNDM1ZTc5OTQ1N2E5YmYxMWRjZTIwYzJiZGYyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTcyMDM2NzMwMjE3MDE1LC03My44NTc1NDY3MjQxMDgyN10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wZDI0YzgzZTU5NjE0MDJiOTUxYzEzMjExYjYzZTg0NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85ZGRhMzM4OTc2NTk0ZDUyODIwZmIwNWVmNzEwYjI0YSA9ICQoJzxkaXYgaWQ9Imh0bWxfOWRkYTMzODk3NjU5NGQ1MjgyMGZiMDVlZjcxMGIyNGEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5lcG9uc2l0LCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzBkMjRjODNlNTk2MTQwMmI5NTFjMTMyMTFiNjNlODQ0LnNldENvbnRlbnQoaHRtbF85ZGRhMzM4OTc2NTk0ZDUyODIwZmIwNWVmNzEwYjI0YSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85MjdhMDQzNWU3OTk0NTdhOWJmMTFkY2UyMGMyYmRmMi5iaW5kUG9wdXAocG9wdXBfMGQyNGM4M2U1OTYxNDAyYjk1MWMxMzIxMWI2M2U4NDQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjY4YzdmNzk0M2RkNDVkMTg4NTA1NWVjNWViZTEzMTkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43NjQxMjYxMjI2MTQwNjYsLTczLjgxMjc2MjY5MTM1ODY2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzAyOGU3ODM1NWZlMDRiYjJiMDY3OWRmY2VkYmI5ZjIxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzM3ZWUyZjdiMWY2NTQ0YzdhMGYzNWUyYjU0NDljYzdiID0gJCgnPGRpdiBpZD0iaHRtbF8zN2VlMmY3YjFmNjU0NGM3YTBmMzVlMmI1NDQ5Y2M3YiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TXVycmF5IEhpbGwsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDI4ZTc4MzU1ZmUwNGJiMmIwNjc5ZGZjZWRiYjlmMjEuc2V0Q29udGVudChodG1sXzM3ZWUyZjdiMWY2NTQ0YzdhMGYzNWUyYjU0NDljYzdiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2I2OGM3Zjc5NDNkZDQ1ZDE4ODUwNTVlYzVlYmUxMzE5LmJpbmRQb3B1cChwb3B1cF8wMjhlNzgzNTVmZTA0YmIyYjA2NzlkZmNlZGJiOWYyMSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wNjExMTNiNmU1NDI0M2M2YTU3NTc0ZDNmYzMxN2I5OSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc0MTM3ODQyMTk0NTQzNCwtNzMuNzA4ODQ3MDU4ODkyNDZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYjcxZTBkZWM2MzBjNDgwOWE2MDc3Y2QwMzgzNDc4ZGQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMWVlM2VkODg0OTZmNDRmZmE0MTYyNDhjYzRhYmFlYjUgPSAkKCc8ZGl2IGlkPSJodG1sXzFlZTNlZDg4NDk2ZjQ0ZmZhNDE2MjQ4Y2M0YWJhZWI1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5GbG9yYWwgUGFyaywgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iNzFlMGRlYzYzMGM0ODA5YTYwNzdjZDAzODM0NzhkZC5zZXRDb250ZW50KGh0bWxfMWVlM2VkODg0OTZmNDRmZmE0MTYyNDhjYzRhYmFlYjUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMDYxMTEzYjZlNTQyNDNjNmE1NzU3NGQzZmMzMTdiOTkuYmluZFBvcHVwKHBvcHVwX2I3MWUwZGVjNjMwYzQ4MDlhNjA3N2NkMDM4MzQ3OGRkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2ZmOGZkNDcwN2VhMDQ3MTVhZDE5MmNhOWYzMTZmMjhhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzIwOTU3MjA3NjQ0NCwtNzMuNzY3MTQxNjY3MTQ3MjldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfM2E5YjgyZjAzZDljNDM5OTk3ODQ1Yzg5Mzk4OGVlMzIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNTExYTE0ZDA4ZmJmNGMxYThmZGMwYTRhNDdiMDM3MzAgPSAkKCc8ZGl2IGlkPSJodG1sXzUxMWExNGQwOGZiZjRjMWE4ZmRjMGE0YTQ3YjAzNzMwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ib2xsaXN3b29kLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzNhOWI4MmYwM2Q5YzQzOTk5Nzg0NWM4OTM5ODhlZTMyLnNldENvbnRlbnQoaHRtbF81MTFhMTRkMDhmYmY0YzFhOGZkYzBhNGE0N2IwMzczMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mZjhmZDQ3MDdlYTA0NzE1YWQxOTJjYTlmMzE2ZjI4YS5iaW5kUG9wdXAocG9wdXBfM2E5YjgyZjAzZDljNDM5OTk3ODQ1Yzg5Mzk4OGVlMzIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfN2Q3Y2JlNjJjYWI4NDAxZTkxZTRlMWMyNDM2MTI2ZjMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTY4MDQ4MzAxNDYxMywtNzMuNzg3MjI2OTY5MzY2Nl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82YjFlOWJhYjAwMWQ0ODgwYmU0MDVjZTNlMTk2ZjJjZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81YmJkMGY0NDliNWY0MzQ5YWQ1NWIzYjhiOTJkMjU0OCA9ICQoJzxkaXYgaWQ9Imh0bWxfNWJiZDBmNDQ5YjVmNDM0OWFkNTViM2I4YjkyZDI1NDgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkphbWFpY2EgRXN0YXRlcywgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82YjFlOWJhYjAwMWQ0ODgwYmU0MDVjZTNlMTk2ZjJjZC5zZXRDb250ZW50KGh0bWxfNWJiZDBmNDQ5YjVmNDM0OWFkNTViM2I4YjkyZDI1NDgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfN2Q3Y2JlNjJjYWI4NDAxZTkxZTRlMWMyNDM2MTI2ZjMuYmluZFBvcHVwKHBvcHVwXzZiMWU5YmFiMDAxZDQ4ODBiZTQwNWNlM2UxOTZmMmNkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzgzZmVjN2Y3NWE2ODQ3MDI5ZDdhZThhNGNiNzYyZTlmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzQ0NTcyMzA5Mjg2NywtNzMuODI1ODA5MTUxMTA1NTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNzk4ZmNiNTNjNDdkNGZlZWE4OGQzZGQ2N2EyMTcyMDggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNjEyMjEzMjk3OTIxNDQ0Mjg2ZTU0NmRlMDQ4ZGRkNTggPSAkKCc8ZGl2IGlkPSJodG1sXzYxMjIxMzI5NzkyMTQ0NDI4NmU1NDZkZTA0OGRkZDU4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5RdWVlbnNib3JvIEhpbGwsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNzk4ZmNiNTNjNDdkNGZlZWE4OGQzZGQ2N2EyMTcyMDguc2V0Q29udGVudChodG1sXzYxMjIxMzI5NzkyMTQ0NDI4NmU1NDZkZTA0OGRkZDU4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzgzZmVjN2Y3NWE2ODQ3MDI5ZDdhZThhNGNiNzYyZTlmLmJpbmRQb3B1cChwb3B1cF83OThmY2I1M2M0N2Q0ZmVlYTg4ZDNkZDY3YTIxNzIwOCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84ZmE4OTdmMDczYWY0OTgwOWZmOGNhZDgwYzg2MGE3NiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcyMzgyNDkwMTgyOTIwNCwtNzMuNzk3NjAzMDA5MTI2NzJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYjgwMGQ1OTQ1NDEyNDU5YzliODgyYzc3MTg1ODhkY2IgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMWI4YWExM2U1ZTE5NDM1Nzg3ZTE5YTMzY2JiZGI2ZjIgPSAkKCc8ZGl2IGlkPSJodG1sXzFiOGFhMTNlNWUxOTQzNTc4N2UxOWEzM2NiYmRiNmYyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IaWxsY3Jlc3QsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjgwMGQ1OTQ1NDEyNDU5YzliODgyYzc3MTg1ODhkY2Iuc2V0Q29udGVudChodG1sXzFiOGFhMTNlNWUxOTQzNTc4N2UxOWEzM2NiYmRiNmYyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzhmYTg5N2YwNzNhZjQ5ODA5ZmY4Y2FkODBjODYwYTc2LmJpbmRQb3B1cChwb3B1cF9iODAwZDU5NDU0MTI0NTljOWI4ODJjNzcxODU4OGRjYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yNmRhMmM1OTYzYTM0NmI2OGMxOWE0NGZhNmRlNTQ2MiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc2MTcwNDUyNjA1NDE0NiwtNzMuOTMxNTc1MDYwNzI4NzhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfODI0OGVkNWRmZDJhNDVhZmIwOTkyZDg4ZWFhYWUzMWMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMGJlMzBhY2Y0NzgyNGVhOGFlZWQzMTA3YWRjMTBhMjIgPSAkKCc8ZGl2IGlkPSJodG1sXzBiZTMwYWNmNDc4MjRlYThhZWVkMzEwN2FkYzEwYTIyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5SYXZlbnN3b29kLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzgyNDhlZDVkZmQyYTQ1YWZiMDk5MmQ4OGVhYWFlMzFjLnNldENvbnRlbnQoaHRtbF8wYmUzMGFjZjQ3ODI0ZWE4YWVlZDMxMDdhZGMxMGEyMik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yNmRhMmM1OTYzYTM0NmI2OGMxOWE0NGZhNmRlNTQ2Mi5iaW5kUG9wdXAocG9wdXBfODI0OGVkNWRmZDJhNDVhZmIwOTkyZDg4ZWFhYWUzMWMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYzJiNjExNGIxZTIyNDU3NmEwY2Y3ZWQ5ZGIxNmEyOGUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42NjM5MTg0MTkyNTEzOSwtNzMuODQ5NjM3ODI0MDI0NDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNmNlYTlkYzA3N2Y3NDEwNDliYzBjNTA5YWYyNWZlNjAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNDY2NzA1OGJhMzE4NDU5MjljOGU0YmYyZjBhYTY0MmUgPSAkKCc8ZGl2IGlkPSJodG1sXzQ2NjcwNThiYTMxODQ1OTI5YzhlNGJmMmYwYWE2NDJlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5MaW5kZW53b29kLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzZjZWE5ZGMwNzdmNzQxMDQ5YmMwYzUwOWFmMjVmZTYwLnNldENvbnRlbnQoaHRtbF80NjY3MDU4YmEzMTg0NTkyOWM4ZTRiZjJmMGFhNjQyZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jMmI2MTE0YjFlMjI0NTc2YTBjZjdlZDlkYjE2YTI4ZS5iaW5kUG9wdXAocG9wdXBfNmNlYTlkYzA3N2Y3NDEwNDliYzBjNTA5YWYyNWZlNjApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjYyMGU2MTQ2MzU1NDNjMjlhNWI4YTgxNTdkZjhmM2EgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42Njc4ODM4OTY2MDI0NywtNzMuNzQwMjU2MDc5ODk4MjJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMDc4ZGQxMGY1YWMzNDUwZGE5ZDU0NThhOGQyYmI5ZWQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNjFhNDIxYWQxOTAwNDdlNzlmOWFjZDUyNDRhZDQyNTYgPSAkKCc8ZGl2IGlkPSJodG1sXzYxYTQyMWFkMTkwMDQ3ZTc5ZjlhY2Q1MjQ0YWQ0MjU2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5MYXVyZWx0b24sIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDc4ZGQxMGY1YWMzNDUwZGE5ZDU0NThhOGQyYmI5ZWQuc2V0Q29udGVudChodG1sXzYxYTQyMWFkMTkwMDQ3ZTc5ZjlhY2Q1MjQ0YWQ0MjU2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2Y2MjBlNjE0NjM1NTQzYzI5YTViOGE4MTU3ZGY4ZjNhLmJpbmRQb3B1cChwb3B1cF8wNzhkZDEwZjVhYzM0NTBkYTlkNTQ1OGE4ZDJiYjllZCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kYTZmOGJiNGYzZGI0M2JlYmQ3NzA5NTJkZTcyNjAyMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjczNjA3NDU3MDgzMDc5NSwtNzMuODYyNTI0NzE0MTM3NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xYjlkN2RjNmNiOTA0MWIxOWIzNGIzZWU4OGY3MjAxOSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83ZjE1ZDYzYmQwYzM0NWM0YmY2MDdkYzg0MTlkZTM0MiA9ICQoJzxkaXYgaWQ9Imh0bWxfN2YxNWQ2M2JkMGMzNDVjNGJmNjA3ZGM4NDE5ZGUzNDIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxlZnJhayBDaXR5LCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzFiOWQ3ZGM2Y2I5MDQxYjE5YjM0YjNlZTg4ZjcyMDE5LnNldENvbnRlbnQoaHRtbF83ZjE1ZDYzYmQwYzM0NWM0YmY2MDdkYzg0MTlkZTM0Mik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9kYTZmOGJiNGYzZGI0M2JlYmQ3NzA5NTJkZTcyNjAyMi5iaW5kUG9wdXAocG9wdXBfMWI5ZDdkYzZjYjkwNDFiMTliMzRiM2VlODhmNzIwMTkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYmRlZmExMDM5N2Q4NDhhZWFlYzM4YmQ1ZDcwMTgwZTggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC41NzYxNTU1NjU0MzEwOSwtNzMuODU0MDE3NTAzOTI1Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81Y2FlOWI4OThkODg0M2NhOTIxZTA2NWE0YmFmYmVlMyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iNDA2ZDA2YTliNmE0ZjY2ODRhMDY2YTdjZTg5NGJiNSA9ICQoJzxkaXYgaWQ9Imh0bWxfYjQwNmQwNmE5YjZhNGY2Njg0YTA2NmE3Y2U4OTRiYjUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJlbGxlIEhhcmJvciwgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81Y2FlOWI4OThkODg0M2NhOTIxZTA2NWE0YmFmYmVlMy5zZXRDb250ZW50KGh0bWxfYjQwNmQwNmE5YjZhNGY2Njg0YTA2NmE3Y2U4OTRiYjUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYmRlZmExMDM5N2Q4NDhhZWFlYzM4YmQ1ZDcwMTgwZTguYmluZFBvcHVwKHBvcHVwXzVjYWU5Yjg5OGQ4ODQzY2E5MjFlMDY1YTRiYWZiZWUzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzJiZmQ4NDZmNzVlMzQ3MDU4NTJlMzIyNmQ5NGExZWNlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTgwMzQyOTU2NDYxMzEsLTczLjg0MTUzMzcwMjI2MTg2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzllYWJmMTg1Njg1ZTQyMDY5MmY0Y2FjMzA0ZGQ4MGM2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2U4MTlmZDdiYWYzYjQ5M2JhNGI2ODk3NWVhYjBkZGIwID0gJCgnPGRpdiBpZD0iaHRtbF9lODE5ZmQ3YmFmM2I0OTNiYTRiNjg5NzVlYWIwZGRiMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Um9ja2F3YXkgUGFyaywgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85ZWFiZjE4NTY4NWU0MjA2OTJmNGNhYzMwNGRkODBjNi5zZXRDb250ZW50KGh0bWxfZTgxOWZkN2JhZjNiNDkzYmE0YjY4OTc1ZWFiMGRkYjApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMmJmZDg0NmY3NWUzNDcwNTg1MmUzMjI2ZDk0YTFlY2UuYmluZFBvcHVwKHBvcHVwXzllYWJmMTg1Njg1ZTQyMDY5MmY0Y2FjMzA0ZGQ4MGM2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzU3MDMxMWUxNjk4NTQyMGU4YTM1OTZhODdmNWRmYjc0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTk3NzEwNjE1NjU3NjgsLTczLjc5NjY0NzUwODQ0MDQ3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzZhODU4NDMyY2NkNTQyZjJhYjllZWI3Mzg2ZDBlM2NmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzllM2RhYTYzZGU2YTQ4ZWM4MGE0NmExNzMxNzM4YTAwID0gJCgnPGRpdiBpZD0iaHRtbF85ZTNkYWE2M2RlNmE0OGVjODBhNDZhMTczMTczOGEwMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U29tZXJ2aWxsZSwgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82YTg1ODQzMmNjZDU0MmYyYWI5ZWViNzM4NmQwZTNjZi5zZXRDb250ZW50KGh0bWxfOWUzZGFhNjNkZTZhNDhlYzgwYTQ2YTE3MzE3MzhhMDApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNTcwMzExZTE2OTg1NDIwZThhMzU5NmE4N2Y1ZGZiNzQuYmluZFBvcHVwKHBvcHVwXzZhODU4NDMyY2NkNTQyZjJhYjllZWI3Mzg2ZDBlM2NmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2VjNmY3YWRkMGRlNjRiYjhhOTA4MTUzMGYwYjgyMWNlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjYwMDAzMjI3MzM2MTMsLTczLjc1MTc1MzEwNzMxMTUzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzIzNjIzYjRhMGVlNzQwZDY5ZjM1OGVmOWNmNDE5N2RiID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2FkNjQ3NjMzYjcxNjQ1MjdhZTc5NTI5N2YyMjU5MzUxID0gJCgnPGRpdiBpZD0iaHRtbF9hZDY0NzYzM2I3MTY0NTI3YWU3OTUyOTdmMjI1OTM1MSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnJvb2t2aWxsZSwgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yMzYyM2I0YTBlZTc0MGQ2OWYzNThlZjljZjQxOTdkYi5zZXRDb250ZW50KGh0bWxfYWQ2NDc2MzNiNzE2NDUyN2FlNzk1Mjk3ZjIyNTkzNTEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZWM2ZjdhZGQwZGU2NGJiOGE5MDgxNTMwZjBiODIxY2UuYmluZFBvcHVwKHBvcHVwXzIzNjIzYjRhMGVlNzQwZDY5ZjM1OGVmOWNmNDE5N2RiKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzlhZThkYTE2NGEwYTRhMTA4ZDIxZjYxZDhhMDJhMzcyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzMzMDE0MDQwMjc4MzQsLTczLjczODg5MTk4OTEyNDgxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzM3N2UzNjhkNzJmMjRhNTFiMTM4ZGM0NGNhMWRkNjZhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzE3OTE1MzMyMzIwZjQ0M2Q5MDVmZjk3ODhkMDhiNDE2ID0gJCgnPGRpdiBpZD0iaHRtbF8xNzkxNTMzMjMyMGY0NDNkOTA1ZmY5Nzg4ZDA4YjQxNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmVsbGFpcmUsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzc3ZTM2OGQ3MmYyNGE1MWIxMzhkYzQ0Y2ExZGQ2NmEuc2V0Q29udGVudChodG1sXzE3OTE1MzMyMzIwZjQ0M2Q5MDVmZjk3ODhkMDhiNDE2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzlhZThkYTE2NGEwYTRhMTA4ZDIxZjYxZDhhMDJhMzcyLmJpbmRQb3B1cChwb3B1cF8zNzdlMzY4ZDcyZjI0YTUxYjEzOGRjNDRjYTFkZDY2YSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83OWNkNzg1ZGJhOTU0ZGEwYTgyMTg2Y2NlYzIyZTAxZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc1NDA3MDk5OTA0ODksLTczLjg1NzUxNzkwNjc2NDQ3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RlZjQ5NzVmMmRmODQ5Yjc4ZDc5MTUyNWFkYjliMzlhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzdlMmJhODg3NjU0NDRiYzViOGUzMmJkYjlkMTZkN2U4ID0gJCgnPGRpdiBpZD0iaHRtbF83ZTJiYTg4NzY1NDQ0YmM1YjhlMzJiZGI5ZDE2ZDdlOCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Tm9ydGggQ29yb25hLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2RlZjQ5NzVmMmRmODQ5Yjc4ZDc5MTUyNWFkYjliMzlhLnNldENvbnRlbnQoaHRtbF83ZTJiYTg4NzY1NDQ0YmM1YjhlMzJiZGI5ZDE2ZDdlOCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83OWNkNzg1ZGJhOTU0ZGEwYTgyMTg2Y2NlYzIyZTAxZC5iaW5kUG9wdXAocG9wdXBfZGVmNDk3NWYyZGY4NDliNzhkNzkxNTI1YWRiOWIzOWEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfY2MyOTIzMjBjNzRhNGE4NWJlNTA3MjJkY2JhNGM0NzggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTQ2MTEwODE1MTE3LC03My44NDEwMjIxMTIzNDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzk5ZmJiN2MxMjY5MzQ2MGM4OGYzNDVmZWM5YzMyYzgwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2JjNjk3Yjg4MDU2NDRmMjA4YzZhYmVkMDM5NTczMDQ5ID0gJCgnPGRpdiBpZD0iaHRtbF9iYzY5N2I4ODA1NjQ0ZjIwOGM2YWJlZDAzOTU3MzA0OSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Rm9yZXN0IEhpbGxzIEdhcmRlbnMsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOTlmYmI3YzEyNjkzNDYwYzg4ZjM0NWZlYzljMzJjODAuc2V0Q29udGVudChodG1sX2JjNjk3Yjg4MDU2NDRmMjA4YzZhYmVkMDM5NTczMDQ5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2NjMjkyMzIwYzc0YTRhODViZTUwNzIyZGNiYTRjNDc4LmJpbmRQb3B1cChwb3B1cF85OWZiYjdjMTI2OTM0NjBjODhmMzQ1ZmVjOWMzMmM4MCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hYmE5ZDNkMDVlZTg0MDc4OGE3MDc5NzQxODRlYjk3MCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY0NDk4MTU3MTAwNDQsLTc0LjA3OTM1MzEyNTEyNzk3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzIzYWUxYmZhOWM4YTQyYTQ5YzRiMzMyYTEwNjcyYjg2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2FmMjQyYmYxYTEzYzRhYzRhZTRiN2YxY2Y5MTczN2RlID0gJCgnPGRpdiBpZD0iaHRtbF9hZjI0MmJmMWExM2M0YWM0YWU0YjdmMWNmOTE3MzdkZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3QuIEdlb3JnZSwgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjNhZTFiZmE5YzhhNDJhNDljNGIzMzJhMTA2NzJiODYuc2V0Q29udGVudChodG1sX2FmMjQyYmYxYTEzYzRhYzRhZTRiN2YxY2Y5MTczN2RlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2FiYTlkM2QwNWVlODQwNzg4YTcwNzk3NDE4NGViOTcwLmJpbmRQb3B1cChwb3B1cF8yM2FlMWJmYTljOGE0MmE0OWM0YjMzMmExMDY3MmI4Nik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83N2Y0MjlmYjE2OGY0YjZiYjY2NDUzMmQ1OTEwM2VhZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY0MDYxNDU1OTEzNTExLC03NC4wODcwMTY1MDUxNjYyNV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83ZDY4MTk4NmY3Zjg0NmJmYjVmMzdhZjk3YmVlYjI1YiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mOTAzNDVjMTdhN2M0YmM2YmUwZGNlNTJmODA4OGQzMiA9ICQoJzxkaXYgaWQ9Imh0bWxfZjkwMzQ1YzE3YTdjNGJjNmJlMGRjZTUyZjgwODhkMzIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5ldyBCcmlnaHRvbiwgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfN2Q2ODE5ODZmN2Y4NDZiZmI1ZjM3YWY5N2JlZWIyNWIuc2V0Q29udGVudChodG1sX2Y5MDM0NWMxN2E3YzRiYzZiZTBkY2U1MmY4MDg4ZDMyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzc3ZjQyOWZiMTY4ZjRiNmJiNjY0NTMyZDU5MTAzZWFmLmJpbmRQb3B1cChwb3B1cF83ZDY4MTk4NmY3Zjg0NmJmYjVmMzdhZjk3YmVlYjI1Yik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xMjVlMTUxMmQzZmU0ODBjYWJmNGRiODBjMmVjOTcyNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjYyNjkyNzYyNTM4MTc2LC03NC4wNzc5MDE5MjY2MDA2Nl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xYmI1YjMzNTM0ZTI0NzU5YWQ2MjYxZjJmMzIyMGE3OSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9kOTRjYzMzM2NmYjk0NDExYWQwYzlmYzhlODU4Y2EwNyA9ICQoJzxkaXYgaWQ9Imh0bWxfZDk0Y2MzMzNjZmI5NDQxMWFkMGM5ZmM4ZTg1OGNhMDciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlN0YXBsZXRvbiwgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMWJiNWIzMzUzNGUyNDc1OWFkNjI2MWYyZjMyMjBhNzkuc2V0Q29udGVudChodG1sX2Q5NGNjMzMzY2ZiOTQ0MTFhZDBjOWZjOGU4NThjYTA3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzEyNWUxNTEyZDNmZTQ4MGNhYmY0ZGI4MGMyZWM5NzI3LmJpbmRQb3B1cChwb3B1cF8xYmI1YjMzNTM0ZTI0NzU5YWQ2MjYxZjJmMzIyMGE3OSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80MDZlYmUyZDZmZmE0YWYxYTY1NzFmMGEyNjU3OTRiNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjYxNTMwNDk0NjUyNzYxLC03NC4wNjk4MDUyNjcxNjE0MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iM2JhYzVmNDRmNzE0ZmYxOGZhNDQxN2VhZjBhOGU1ZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8yNGNiZDk2NmVkMjE0MmJmYTY3ZWFiZmFhMGFjNjI1MiA9ICQoJzxkaXYgaWQ9Imh0bWxfMjRjYmQ5NjZlZDIxNDJiZmE2N2VhYmZhYTBhYzYyNTIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJvc2ViYW5rLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iM2JhYzVmNDRmNzE0ZmYxOGZhNDQxN2VhZjBhOGU1ZC5zZXRDb250ZW50KGh0bWxfMjRjYmQ5NjZlZDIxNDJiZmE2N2VhYmZhYTBhYzYyNTIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDA2ZWJlMmQ2ZmZhNGFmMWE2NTcxZjBhMjY1Nzk0YjUuYmluZFBvcHVwKHBvcHVwX2IzYmFjNWY0NGY3MTRmZjE4ZmE0NDE3ZWFmMGE4ZTVkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2VhNTFlMWMyODA2YjQ1NTA4ZGVkMjAzMjIwMDE2Mzc5ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjMxODc4OTI2NTQ2MDcsLTc0LjEwNzE4MTc4MjY1NjFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZTQ4OTQyZmJkNzJiNGQzNTgyNDhmYWI4YTNlYTZhZGUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOWEzNGViMjc5YTljNGE1Mzg0YzgzYTJkMGM3YzM5NmIgPSAkKCc8ZGl2IGlkPSJodG1sXzlhMzRlYjI3OWE5YzRhNTM4NGM4M2EyZDBjN2MzOTZiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XZXN0IEJyaWdodG9uLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lNDg5NDJmYmQ3MmI0ZDM1ODI0OGZhYjhhM2VhNmFkZS5zZXRDb250ZW50KGh0bWxfOWEzNGViMjc5YTljNGE1Mzg0YzgzYTJkMGM3YzM5NmIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZWE1MWUxYzI4MDZiNDU1MDhkZWQyMDMyMjAwMTYzNzkuYmluZFBvcHVwKHBvcHVwX2U0ODk0MmZiZDcyYjRkMzU4MjQ4ZmFiOGEzZWE2YWRlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzMyY2RlODhmN2Y2MjQxYTc4OTY3N2Y0OTNmN2ZjNzJiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjI0MTg0NzkxMzEzMDA2LC03NC4wODcyNDgxOTk4MzcyOV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84NGE1ZjQ0OWQxM2U0NjRlYjY2MDJjY2NhMzg1OTUwZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80ZGM2ZDA4OTQ5ZmE0NGIxODM3NWYxNjE2NzZmYTdhMiA9ICQoJzxkaXYgaWQ9Imh0bWxfNGRjNmQwODk0OWZhNDRiMTgzNzVmMTYxNjc2ZmE3YTIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkdyeW1lcyBIaWxsLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84NGE1ZjQ0OWQxM2U0NjRlYjY2MDJjY2NhMzg1OTUwZC5zZXRDb250ZW50KGh0bWxfNGRjNmQwODk0OWZhNDRiMTgzNzVmMTYxNjc2ZmE3YTIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMzJjZGU4OGY3ZjYyNDFhNzg5Njc3ZjQ5M2Y3ZmM3MmIuYmluZFBvcHVwKHBvcHVwXzg0YTVmNDQ5ZDEzZTQ2NGViNjYwMmNjY2EzODU5NTBkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2E3ZTRjMzJkODI3ZTRjOTY4YWViYzk3NGNjMTBhZDRjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTk3MDY4NTE4MTQ2NzMsLTc0LjExMTMyODgxODAwODhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNWM5YzBhYWQ4ZWFhNGQ4MGIyMzRhZTcyMzNmZDY4OTggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNGIyZjljMjM0OWIxNGJhYmEzMTVjYTA5OTA3NTQ2YTMgPSAkKCc8ZGl2IGlkPSJodG1sXzRiMmY5YzIzNDliMTRiYWJhMzE1Y2EwOTkwNzU0NmEzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ub2R0IEhpbGwsIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzVjOWMwYWFkOGVhYTRkODBiMjM0YWU3MjMzZmQ2ODk4LnNldENvbnRlbnQoaHRtbF80YjJmOWMyMzQ5YjE0YmFiYTMxNWNhMDk5MDc1NDZhMyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hN2U0YzMyZDgyN2U0Yzk2OGFlYmM5NzRjYzEwYWQ0Yy5iaW5kUG9wdXAocG9wdXBfNWM5YzBhYWQ4ZWFhNGQ4MGIyMzRhZTcyMzNmZDY4OTgpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMGMxZmRlOWNmNDdjNDMwZGEyNWM1NWY3YjM1MDMwZmQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC41ODAyNDc0MTM1MDk1NiwtNzQuMDc5NTUyOTI1Mzk4Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kY2Y1NTM4YTlhZGI0MDY0YmJhZjk1ZjQzMDcxZGVhNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82NzAwNjJlOTRhN2E0OTBmYmQ5MWZhMTdhM2Q2ZjRhYiA9ICQoJzxkaXYgaWQ9Imh0bWxfNjcwMDYyZTk0YTdhNDkwZmJkOTFmYTE3YTNkNmY0YWIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlNvdXRoIEJlYWNoLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9kY2Y1NTM4YTlhZGI0MDY0YmJhZjk1ZjQzMDcxZGVhNC5zZXRDb250ZW50KGh0bWxfNjcwMDYyZTk0YTdhNDkwZmJkOTFmYTE3YTNkNmY0YWIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMGMxZmRlOWNmNDdjNDMwZGEyNWM1NWY3YjM1MDMwZmQuYmluZFBvcHVwKHBvcHVwX2RjZjU1MzhhOWFkYjQwNjRiYmFmOTVmNDMwNzFkZWE0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2ViZTZjYThjMjU5ZjRlNGFiMjFkYzJhNjJjZTI5MjczID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjMzNjY5MzA1NTQzNjUsLTc0LjEyOTQzNDI2Nzk3MDA4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2ZlZjM3MTdmYTY5MTQyYzA5NWE5NDczOTg1MmU2NDNmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2JjODUyMDAzZTJiZTRmMzZhN2ZkNmYxODc0YjJhNTFiID0gJCgnPGRpdiBpZD0iaHRtbF9iYzg1MjAwM2UyYmU0ZjM2YTdmZDZmMTg3NGIyYTUxYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UG9ydCBSaWNobW9uZCwgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZmVmMzcxN2ZhNjkxNDJjMDk1YTk0NzM5ODUyZTY0M2Yuc2V0Q29udGVudChodG1sX2JjODUyMDAzZTJiZTRmMzZhN2ZkNmYxODc0YjJhNTFiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2ViZTZjYThjMjU5ZjRlNGFiMjFkYzJhNjJjZTI5MjczLmJpbmRQb3B1cChwb3B1cF9mZWYzNzE3ZmE2OTE0MmMwOTVhOTQ3Mzk4NTJlNjQzZik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lZWI1NTU3M2EwYmQ0OTA2YTkxOTI2ZjgzNTJmZDI4MyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjYzMjU0NjM5MDQ4MTEyNCwtNzQuMTUwMDg1MzcwNDY5ODFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzQ3ZmMzMjllODg3NDBlZGEwMjQ0Y2ZlMzE1NzI2MTUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZmJiYzk0NjkxNTFmNDNhNGJmODIxY2NmZWMyYzBhY2YgPSAkKCc8ZGl2IGlkPSJodG1sX2ZiYmM5NDY5MTUxZjQzYTRiZjgyMWNjZmVjMmMwYWNmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5NYXJpbmVyJiMzOTtzIEhhcmJvciwgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzQ3ZmMzMjllODg3NDBlZGEwMjQ0Y2ZlMzE1NzI2MTUuc2V0Q29udGVudChodG1sX2ZiYmM5NDY5MTUxZjQzYTRiZjgyMWNjZmVjMmMwYWNmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2VlYjU1NTczYTBiZDQ5MDZhOTE5MjZmODM1MmZkMjgzLmJpbmRQb3B1cChwb3B1cF8zNDdmYzMyOWU4ODc0MGVkYTAyNDRjZmUzMTU3MjYxNSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lZGJkMmM0OTc0NWY0NDc2YWJkOGZjN2Y2YzM3MzQzMCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjYzOTY4Mjk3ODQ1NTQyLC03NC4xNzQ2NDUzMjk5MzU0Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wMWY1YmU5YjUwNWU0MDYzYTAwMzIxZTQzMzNkYjcyZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lZjllYjk1YmVhZDU0Y2I0OTFkYjllZjRjYjJmYjQxZiA9ICQoJzxkaXYgaWQ9Imh0bWxfZWY5ZWI5NWJlYWQ1NGNiNDkxZGI5ZWY0Y2IyZmI0MWYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlBvcnQgSXZvcnksIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzAxZjViZTliNTA1ZTQwNjNhMDAzMjFlNDMzM2RiNzJlLnNldENvbnRlbnQoaHRtbF9lZjllYjk1YmVhZDU0Y2I0OTFkYjllZjRjYjJmYjQxZik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9lZGJkMmM0OTc0NWY0NDc2YWJkOGZjN2Y2YzM3MzQzMC5iaW5kUG9wdXAocG9wdXBfMDFmNWJlOWI1MDVlNDA2M2EwMDMyMWU0MzMzZGI3MmUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDFjNzg2NGVlOTc3NDgwMmJkYmU3ZjIyODkzZmY2MzEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42MTMzMzU5Mzc2Njc0MiwtNzQuMTE5MTgwNTg1MzQ4NDJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMTNmNzAxMGYzNzhiNGM0MGE5YWVhZjJjYmQ3OGE1YzggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNWVhM2Y1MWE0ZWU5NGY0ODg5ZjMyODhmNWZiNGY2ZmEgPSAkKCc8ZGl2IGlkPSJodG1sXzVlYTNmNTFhNGVlOTRmNDg4OWYzMjg4ZjVmYjRmNmZhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DYXN0bGV0b24gQ29ybmVycywgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMTNmNzAxMGYzNzhiNGM0MGE5YWVhZjJjYmQ3OGE1Yzguc2V0Q29udGVudChodG1sXzVlYTNmNTFhNGVlOTRmNDg4OWYzMjg4ZjVmYjRmNmZhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzQxYzc4NjRlZTk3NzQ4MDJiZGJlN2YyMjg5M2ZmNjMxLmJpbmRQb3B1cChwb3B1cF8xM2Y3MDEwZjM3OGI0YzQwYTlhZWFmMmNiZDc4YTVjOCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl85MDVhNDM5YjhkOTE0MGNhYjcyNWJiNjQ5NTlkOGNmOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjU5NDI1MjM3OTE2MTY5NSwtNzQuMTY0OTYwMzEzMjk4MjddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMjUzOWFkNjY0NWI0NGYxMThmMTdmOTExOWYxNTJmODggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjFlYjIzZmRkNGNmNGRkNTk1YWRkZDI3N2I3ZmE3N2IgPSAkKCc8ZGl2IGlkPSJodG1sX2YxZWIyM2ZkZDRjZjRkZDU5NWFkZGQyNzdiN2ZhNzdiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5OZXcgU3ByaW5ndmlsbGUsIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzI1MzlhZDY2NDViNDRmMTE4ZjE3ZjkxMTlmMTUyZjg4LnNldENvbnRlbnQoaHRtbF9mMWViMjNmZGQ0Y2Y0ZGQ1OTVhZGRkMjc3YjdmYTc3Yik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85MDVhNDM5YjhkOTE0MGNhYjcyNWJiNjQ5NTlkOGNmOS5iaW5kUG9wdXAocG9wdXBfMjUzOWFkNjY0NWI0NGYxMThmMTdmOTExOWYxNTJmODgpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZDFkM2Y5OTkyOWQ1NDYxYjlhYjhkZmQyYWUxOTJlMjYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC41ODYzMTM3NTEwMzI4MSwtNzQuMTkwNzM3MTc1MzgxMTZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfY2I1NjhlZDZjZDNkNDgzZWI5ZjkyZTVkYTczNjM2ZjcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMzRkZTljMTk3NDlmNDUxYjkyYWEwZGM4OTE3NGI0YzcgPSAkKCc8ZGl2IGlkPSJodG1sXzM0ZGU5YzE5NzQ5ZjQ1MWI5MmFhMGRjODkxNzRiNGM3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UcmF2aXMsIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2NiNTY4ZWQ2Y2QzZDQ4M2ViOWY5MmU1ZGE3MzYzNmY3LnNldENvbnRlbnQoaHRtbF8zNGRlOWMxOTc0OWY0NTFiOTJhYTBkYzg5MTc0YjRjNyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9kMWQzZjk5OTI5ZDU0NjFiOWFiOGRmZDJhZTE5MmUyNi5iaW5kUG9wdXAocG9wdXBfY2I1NjhlZDZjZDNkNDgzZWI5ZjkyZTVkYTczNjM2ZjcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjQ4YjM4N2M3M2RiNDkxNDhhNWI5MDkxOGUyYzFiMDIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC41NzI1NzIzMTgyMDYzMiwtNzQuMTE2NDc5NDM2MDYzOF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84OTlkZWZjMjY1YTY0ZTM1Yjg2YjYxMTdjMjAzMTAwMyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81NTBmOGQ4NDU1YTE0MTEyODIxNjlhMTViY2YwODY2NSA9ICQoJzxkaXYgaWQ9Imh0bWxfNTUwZjhkODQ1NWExNDExMjgyMTY5YTE1YmNmMDg2NjUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5ldyBEb3JwLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84OTlkZWZjMjY1YTY0ZTM1Yjg2YjYxMTdjMjAzMTAwMy5zZXRDb250ZW50KGh0bWxfNTUwZjhkODQ1NWExNDExMjgyMTY5YTE1YmNmMDg2NjUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjQ4YjM4N2M3M2RiNDkxNDhhNWI5MDkxOGUyYzFiMDIuYmluZFBvcHVwKHBvcHVwXzg5OWRlZmMyNjVhNjRlMzViODZiNjExN2MyMDMxMDAzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2IwNzc1YjA0NWQ4MjQwOGI4Njc4ZjhmNGI0ZDFjMDQyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTU4NDYyMjQzMjg4OCwtNzQuMTIxNTY1OTM3NzE4OTZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOWFiOGZmMDA1YTI0NDZmZjlhNTYzYzg0NGJlYmI5NjIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYmViZGQ4ODE4ZjJmNDM2MDkyODE1YjU3ZWUxYWE5NmYgPSAkKCc8ZGl2IGlkPSJodG1sX2JlYmRkODgxOGYyZjQzNjA5MjgxNWI1N2VlMWFhOTZmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5PYWt3b29kLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85YWI4ZmYwMDVhMjQ0NmZmOWE1NjNjODQ0YmViYjk2Mi5zZXRDb250ZW50KGh0bWxfYmViZGQ4ODE4ZjJmNDM2MDkyODE1YjU3ZWUxYWE5NmYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjA3NzViMDQ1ZDgyNDA4Yjg2NzhmOGY0YjRkMWMwNDIuYmluZFBvcHVwKHBvcHVwXzlhYjhmZjAwNWEyNDQ2ZmY5YTU2M2M4NDRiZWJiOTYyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2ZiM2I0OWJjZDAxMTQ0MDhiYjI1Y2JmZjExMmE5ZjNhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTQ5NDgwMjI4NzEzNjA1LC03NC4xNDkzMjM4MTQ5MDk5Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wYmQyN2UwYzZmMTU0ZGVjOTk1MmRmZDczMDVkZmFhMSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80ZGYzNjQwZmQ2ZjA0ZDYxODBjOTdmZTQ2N2Q3NDY3OSA9ICQoJzxkaXYgaWQ9Imh0bWxfNGRmMzY0MGZkNmYwNGQ2MTgwYzk3ZmU0NjdkNzQ2NzkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkdyZWF0IEtpbGxzLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wYmQyN2UwYzZmMTU0ZGVjOTk1MmRmZDczMDVkZmFhMS5zZXRDb250ZW50KGh0bWxfNGRmMzY0MGZkNmYwNGQ2MTgwYzk3ZmU0NjdkNzQ2NzkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZmIzYjQ5YmNkMDExNDQwOGJiMjVjYmZmMTEyYTlmM2EuYmluZFBvcHVwKHBvcHVwXzBiZDI3ZTBjNmYxNTRkZWM5OTUyZGZkNzMwNWRmYWExKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzgxYTAwMWNmOTIxOTRhMjM5Y2M5NTNmMmViYTYyMjczID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTQyMjMwNzQ3NDUwNzQ1LC03NC4xNjQzMzA4MDQxOTM2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzZhOTI2OTFkMzc4MDQ4OWRhOTdkZTI3NmVmMzA2Yzk2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2JiOWJkZjQxNzk1MDQwOTE4ODZmM2UxNWIwY2NhM2UzID0gJCgnPGRpdiBpZD0iaHRtbF9iYjliZGY0MTc5NTA0MDkxODg2ZjNlMTViMGNjYTNlMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RWx0aW5ndmlsbGUsIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzZhOTI2OTFkMzc4MDQ4OWRhOTdkZTI3NmVmMzA2Yzk2LnNldENvbnRlbnQoaHRtbF9iYjliZGY0MTc5NTA0MDkxODg2ZjNlMTViMGNjYTNlMyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84MWEwMDFjZjkyMTk0YTIzOWNjOTUzZjJlYmE2MjI3My5iaW5kUG9wdXAocG9wdXBfNmE5MjY5MWQzNzgwNDg5ZGE5N2RlMjc2ZWYzMDZjOTYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMGU5YzVhMjM0ODg5NDg2OWJjMzA4NjIwOTk1ZTI0OTEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC41MzgxMTQxNzQ3NDUwNywtNzQuMTc4NTQ4NjYxNjU4NzhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfM2E2NWM3M2VjYzg1NDcwOWE2NmVlNDk3NzFkZGEwYWMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfODUxYzk1OGI0NmE1NDRhOGIzNzg0ODUxODZjZTdjNzAgPSAkKCc8ZGl2IGlkPSJodG1sXzg1MWM5NThiNDZhNTQ0YThiMzc4NDg1MTg2Y2U3YzcwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Bbm5hZGFsZSwgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfM2E2NWM3M2VjYzg1NDcwOWE2NmVlNDk3NzFkZGEwYWMuc2V0Q29udGVudChodG1sXzg1MWM5NThiNDZhNTQ0YThiMzc4NDg1MTg2Y2U3YzcwKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzBlOWM1YTIzNDg4OTQ4NjliYzMwODYyMDk5NWUyNDkxLmJpbmRQb3B1cChwb3B1cF8zYTY1YzczZWNjODU0NzA5YTY2ZWU0OTc3MWRkYTBhYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jNGM0MWVjMTYxYzY0NWZjOWMyM2YxMzM5NTlhZjY0MiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjU0MTk2NzYyMjg4ODc1NSwtNzQuMjA1MjQ1ODI0ODAzMjZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjk2NzRkYWE3YjdkNDk4Yzg4MDg2MGEyYzdhYjU5OGIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjBiYmE0YjIwNTc4NDZjOThjNDgwMTM3ODE0ODQyZDMgPSAkKCc8ZGl2IGlkPSJodG1sX2YwYmJhNGIyMDU3ODQ2Yzk4YzQ4MDEzNzgxNDg0MmQzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Xb29kcm93LCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82OTY3NGRhYTdiN2Q0OThjODgwODYwYTJjN2FiNTk4Yi5zZXRDb250ZW50KGh0bWxfZjBiYmE0YjIwNTc4NDZjOThjNDgwMTM3ODE0ODQyZDMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYzRjNDFlYzE2MWM2NDVmYzljMjNmMTMzOTU5YWY2NDIuYmluZFBvcHVwKHBvcHVwXzY5Njc0ZGFhN2I3ZDQ5OGM4ODA4NjBhMmM3YWI1OThiKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY1OWIzMGJkMzQyZDQ0NDdiZWQzZGFhNDMxMzM1NjhiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTA1MzMzNzYxMTU2NDIsLTc0LjI0NjU2OTM0MjM1MjgzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzU0Zjg5YjliNjllNDQzMmFhNmIyMTBjOGY0NDkzZWFlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzViNDZkNmE0ZmNhZTRiMjhiMjlhZmZiN2JkOGY3YTlmID0gJCgnPGRpdiBpZD0iaHRtbF81YjQ2ZDZhNGZjYWU0YjI4YjI5YWZmYjdiZDhmN2E5ZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VG90dGVudmlsbGUsIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzU0Zjg5YjliNjllNDQzMmFhNmIyMTBjOGY0NDkzZWFlLnNldENvbnRlbnQoaHRtbF81YjQ2ZDZhNGZjYWU0YjI4YjI5YWZmYjdiZDhmN2E5Zik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82NTliMzBiZDM0MmQ0NDQ3YmVkM2RhYTQzMTMzNTY4Yi5iaW5kUG9wdXAocG9wdXBfNTRmODliOWI2OWU0NDMyYWE2YjIxMGM4ZjQ0OTNlYWUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZDcyZWJmMGFjMGI2NGY0YWIwMjUyM2E0ZTQ3YTMyMzAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42MzczMTYwNjcxMTAzMjYsLTc0LjA4MDU1MzUxNzkwMTE1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2EzMDJmNDVjZGRmZTQxMzhiMWUwZGNkZDA5NWFkYmRhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzk5MTk1OTM1YWE1MTQ1ZGQ4ZGY1Y2I2ODcwYzg5YmEzID0gJCgnPGRpdiBpZD0iaHRtbF85OTE5NTkzNWFhNTE0NWRkOGRmNWNiNjg3MGM4OWJhMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VG9tcGtpbnN2aWxsZSwgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYTMwMmY0NWNkZGZlNDEzOGIxZTBkY2RkMDk1YWRiZGEuc2V0Q29udGVudChodG1sXzk5MTk1OTM1YWE1MTQ1ZGQ4ZGY1Y2I2ODcwYzg5YmEzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2Q3MmViZjBhYzBiNjRmNGFiMDI1MjNhNGU0N2EzMjMwLmJpbmRQb3B1cChwb3B1cF9hMzAyZjQ1Y2RkZmU0MTM4YjFlMGRjZGQwOTVhZGJkYSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xZmU1MDUyYTRmODc0MzU1YjhkYjkzNjczOThiYWFmZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjYxOTE5MzEwNzkyNjc2LC03NC4wOTYyOTAyOTIzNTQ1OF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80Y2U2YzkwZjBhNDk0ZTdlYjM1ZDJjNmNhZTM0MGZiNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81NjQ3YjAwZjRhNDc0ZTVmOWQzNmRmMTYxYzk5NjJmYiA9ICQoJzxkaXYgaWQ9Imh0bWxfNTY0N2IwMGY0YTQ3NGU1ZjlkMzZkZjE2MWM5OTYyZmIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlNpbHZlciBMYWtlLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80Y2U2YzkwZjBhNDk0ZTdlYjM1ZDJjNmNhZTM0MGZiNC5zZXRDb250ZW50KGh0bWxfNTY0N2IwMGY0YTQ3NGU1ZjlkMzZkZjE2MWM5OTYyZmIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMWZlNTA1MmE0Zjg3NDM1NWI4ZGI5MzY3Mzk4YmFhZmYuYmluZFBvcHVwKHBvcHVwXzRjZTZjOTBmMGE0OTRlN2ViMzVkMmM2Y2FlMzQwZmI0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2FkNTI4YmZlYzM0ZTQ1YjE5NWQxZjRjODlhMDc0OWU3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjEyNzYwMTU3NTY0ODksLTc0LjA5NzEyNTUyMTc4NTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzg3OWU4MmJiZDBlNGRlY2I4ZmY4ODFkMjg4NmUxYjcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOWI3NjE4N2JjOWNmNGIyNjhhOWQ4ODU0M2YyZThlYjUgPSAkKCc8ZGl2IGlkPSJodG1sXzliNzYxODdiYzljZjRiMjY4YTlkODg1NDNmMmU4ZWI1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TdW5ueXNpZGUsIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzM4NzllODJiYmQwZTRkZWNiOGZmODgxZDI4ODZlMWI3LnNldENvbnRlbnQoaHRtbF85Yjc2MTg3YmM5Y2Y0YjI2OGE5ZDg4NTQzZjJlOGViNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hZDUyOGJmZWMzNGU0NWIxOTVkMWY0Yzg5YTA3NDllNy5iaW5kUG9wdXAocG9wdXBfMzg3OWU4MmJiZDBlNGRlY2I4ZmY4ODFkMjg4NmUxYjcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOGNmOWY5MjNlZDAwNDhlMGE5NWVjMDIzYjU0MmJiMDIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42NDM2NzUxODMzNDA5NzQsLTczLjk2MTAxMzEyNDY2Nzc5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzAwZWNkZGZhOTUxMzQ5NzJhODgyMzdhNzE1ZmYwZWM2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2RlNWZiNzZiNjI4MjQ5OTk4N2Q3OWNkNjAzZGIzZThjID0gJCgnPGRpdiBpZD0iaHRtbF9kZTVmYjc2YjYyODI0OTk5ODdkNzljZDYwM2RiM2U4YyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RGl0bWFzIFBhcmssIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wMGVjZGRmYTk1MTM0OTcyYTg4MjM3YTcxNWZmMGVjNi5zZXRDb250ZW50KGh0bWxfZGU1ZmI3NmI2MjgyNDk5OTg3ZDc5Y2Q2MDNkYjNlOGMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOGNmOWY5MjNlZDAwNDhlMGE5NWVjMDIzYjU0MmJiMDIuYmluZFBvcHVwKHBvcHVwXzAwZWNkZGZhOTUxMzQ5NzJhODgyMzdhNzE1ZmYwZWM2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2ZjMWZkMzMyMTU0NDRmZjhiMjI3MDU0ZDliYWEwZjUwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjYwOTQ2NTYxODgxMTEsLTczLjkzNzE4NjgwNTU5MzE0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzMzMWZiODA2ZDUzYjQ1YmZhMWM3ZTU3N2RhODQzYjk0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2MxNjJmNWM0NzY5YjQxMGRhMDQxNzNlNDBkMDljOTgyID0gJCgnPGRpdiBpZD0iaHRtbF9jMTYyZjVjNDc2OWI0MTBkYTA0MTczZTQwZDA5Yzk4MiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2luZ2F0ZSwgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzMzMWZiODA2ZDUzYjQ1YmZhMWM3ZTU3N2RhODQzYjk0LnNldENvbnRlbnQoaHRtbF9jMTYyZjVjNDc2OWI0MTBkYTA0MTczZTQwZDA5Yzk4Mik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mYzFmZDMzMjE1NDQ0ZmY4YjIyNzA1NGQ5YmFhMGY1MC5iaW5kUG9wdXAocG9wdXBfMzMxZmI4MDZkNTNiNDViZmExYzdlNTc3ZGE4NDNiOTQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNmJiNjY0ZTE2ZDM4NGYyZGJkYWQyMDc0NzYzY2M0YTkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42NTU1NzIzMTMyODA3NjQsLTczLjkyNjg4MjEyNjE2OTU1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzFkMzYzYzU4NjAxMzRkMTA5YjlkMTE2ZTA5ODAxYWFmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2YxYTUzNDQ5YzQxNDQyNDk4YWU4ZjVjN2Y3NjBjNmU0ID0gJCgnPGRpdiBpZD0iaHRtbF9mMWE1MzQ0OWM0MTQ0MjQ5OGFlOGY1YzdmNzYwYzZlNCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UnVnYnksIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xZDM2M2M1ODYwMTM0ZDEwOWI5ZDExNmUwOTgwMWFhZi5zZXRDb250ZW50KGh0bWxfZjFhNTM0NDljNDE0NDI0OThhZThmNWM3Zjc2MGM2ZTQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNmJiNjY0ZTE2ZDM4NGYyZGJkYWQyMDc0NzYzY2M0YTkuYmluZFBvcHVwKHBvcHVwXzFkMzYzYzU4NjAxMzRkMTA5YjlkMTE2ZTA5ODAxYWFmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQyMWNkZjNhODFiNTQ1Nzg4MjMzM2YxMjA2NTI0Yzg3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjA5MTkwNDQ0MzQ1NTgsLTc0LjA4MDE1NzM0OTM2Mjk2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2MyOWJlNjA0YWFiOTQzNDVhNjc5NjgxMDkxMzE2OGU3ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2I2NmQxNzAwNTFhYTRkYTNhYjg1NWIxMjU3ZDUzOTdhID0gJCgnPGRpdiBpZD0iaHRtbF9iNjZkMTcwMDUxYWE0ZGEzYWI4NTViMTI1N2Q1Mzk3YSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UGFyayBIaWxsLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jMjliZTYwNGFhYjk0MzQ1YTY3OTY4MTA5MTMxNjhlNy5zZXRDb250ZW50KGh0bWxfYjY2ZDE3MDA1MWFhNGRhM2FiODU1YjEyNTdkNTM5N2EpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDIxY2RmM2E4MWI1NDU3ODgyMzMzZjEyMDY1MjRjODcuYmluZFBvcHVwKHBvcHVwX2MyOWJlNjA0YWFiOTQzNDVhNjc5NjgxMDkxMzE2OGU3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzA2ODJkOTdkNTYzYjRlZDVhNDQwODU4NTliYjhiNmMzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjIxMDkwNDcyNzU0MDksLTc0LjEzMzA0MTQzOTUxNzA0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2E4MjQ1YmQyMTFjYTRiZmE5NDg5OTEyZTJlNzdlZjM2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2I5ZDk5Yjk1ZmRiNTQ4Yjg5MjNhYTljZGYzZGU4ZGQwID0gJCgnPGRpdiBpZD0iaHRtbF9iOWQ5OWI5NWZkYjU0OGI4OTIzYWE5Y2RmM2RlOGRkMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2VzdGVybGVpZ2gsIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2E4MjQ1YmQyMTFjYTRiZmE5NDg5OTEyZTJlNzdlZjM2LnNldENvbnRlbnQoaHRtbF9iOWQ5OWI5NWZkYjU0OGI4OTIzYWE5Y2RmM2RlOGRkMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wNjgyZDk3ZDU2M2I0ZWQ1YTQ0MDg1ODU5YmI4YjZjMy5iaW5kUG9wdXAocG9wdXBfYTgyNDViZDIxMWNhNGJmYTk0ODk5MTJlMmU3N2VmMzYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjgzMDAzZmNiOGNjNDQ0Y2I2YmRkYzFkNjc1ZTAzMzcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42MjAxNzE1MTIyMzE4ODQsLTc0LjE1MzE1MjQ2Mzg3NzYyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2FjZWVjZTcxOGEwYjRhMTU5MGMzNjgxZTUxNmU2M2I0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc1ZTljOTFiOTVjNTQyMjhiOWM3ZjhlMTRlODA5NGRiID0gJCgnPGRpdiBpZD0iaHRtbF83NWU5YzkxYjk1YzU0MjI4YjljN2Y4ZTE0ZTgwOTRkYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+R3Jhbml0ZXZpbGxlLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hY2VlY2U3MThhMGI0YTE1OTBjMzY4MWU1MTZlNjNiNC5zZXRDb250ZW50KGh0bWxfNzVlOWM5MWI5NWM1NDIyOGI5YzdmOGUxNGU4MDk0ZGIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjgzMDAzZmNiOGNjNDQ0Y2I2YmRkYzFkNjc1ZTAzMzcuYmluZFBvcHVwKHBvcHVwX2FjZWVjZTcxOGEwYjRhMTU5MGMzNjgxZTUxNmU2M2I0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQ0ZDRkNWIyMmI2NjRkMmVhNjBhMWViOTRmOTNkMzlhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjM1MzI1MDk5MTE0OTIsLTc0LjE2NTEwNDIwMjQxMTI0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzkzMGFhNzdkNDllODRhM2Q5OWJhNWRmOWM5Mjk1NWRmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2YyZDY5MTEzZGQ1MjQ5ZDliNDMxNDRmNWNlZGI4NzllID0gJCgnPGRpdiBpZD0iaHRtbF9mMmQ2OTExM2RkNTI0OWQ5YjQzMTQ0ZjVjZWRiODc5ZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QXJsaW5ndG9uLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85MzBhYTc3ZDQ5ZTg0YTNkOTliYTVkZjljOTI5NTVkZi5zZXRDb250ZW50KGh0bWxfZjJkNjkxMTNkZDUyNDlkOWI0MzE0NGY1Y2VkYjg3OWUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDRkNGQ1YjIyYjY2NGQyZWE2MGExZWI5NGY5M2QzOWEuYmluZFBvcHVwKHBvcHVwXzkzMGFhNzdkNDllODRhM2Q5OWJhNWRmOWM5Mjk1NWRmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y5ODNjODYzMzgxNzRhMGQ5NmZkZTU4Y2VhOTUyMjZjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTk2MzEyNTcxMjc2NzM0LC03NC4wNjcxMjM2MzIyNTU3NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81ZGQzYzQyZjQ0MTM0ZTcyYWU3MWY3OWZjYWUyYTUxMCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hYTI5YmRlNWNjMDc0NTM5OWQ5YzNjMWZkZWNiMzUyYiA9ICQoJzxkaXYgaWQ9Imh0bWxfYWEyOWJkZTVjYzA3NDUzOTlkOWMzYzFmZGVjYjM1MmIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkFycm9jaGFyLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81ZGQzYzQyZjQ0MTM0ZTcyYWU3MWY3OWZjYWUyYTUxMC5zZXRDb250ZW50KGh0bWxfYWEyOWJkZTVjYzA3NDUzOTlkOWMzYzFmZGVjYjM1MmIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjk4M2M4NjMzODE3NGEwZDk2ZmRlNThjZWE5NTIyNmMuYmluZFBvcHVwKHBvcHVwXzVkZDNjNDJmNDQxMzRlNzJhZTcxZjc5ZmNhZTJhNTEwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzRjOTE3ZDI2ZDY4YjQ0OTA4ZTgyY2UyYTI3NjQzYmVjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTk4MjY4MzU5NTk5OTEsLTc0LjA3NjY3NDM2Mjc5MDVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMjU1ZGU0NTI4MTc3NDA5ZDhkN2Y5OTVlMTJkM2VjOTIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMzM4ODE0MTVkODgyNGM3ODliMjk2YTEyMTMwNTY5ZGMgPSAkKCc8ZGl2IGlkPSJodG1sXzMzODgxNDE1ZDg4MjRjNzg5YjI5NmExMjEzMDU2OWRjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5HcmFzbWVyZSwgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjU1ZGU0NTI4MTc3NDA5ZDhkN2Y5OTVlMTJkM2VjOTIuc2V0Q29udGVudChodG1sXzMzODgxNDE1ZDg4MjRjNzg5YjI5NmExMjEzMDU2OWRjKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzRjOTE3ZDI2ZDY4YjQ0OTA4ZTgyY2UyYTI3NjQzYmVjLmJpbmRQb3B1cChwb3B1cF8yNTVkZTQ1MjgxNzc0MDlkOGQ3Zjk5NWUxMmQzZWM5Mik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mNDhjMGE5NDBlYmE0MDdiYmY0OWVmM2IzYTVjN2JiZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjU5NjMyODkxMzc5NTEzLC03NC4wODc1MTExODAwNTU3OF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zYWUxMjQ4Y2YxMzM0NjY5YWM3NWVmNGNkMGVkMDVkNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iNzJlZGIwNDBkZWE0MGE4YjYxZjBhZTYzOTlmYzljYyA9ICQoJzxkaXYgaWQ9Imh0bWxfYjcyZWRiMDQwZGVhNDBhOGI2MWYwYWU2Mzk5ZmM5Y2MiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk9sZCBUb3duLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zYWUxMjQ4Y2YxMzM0NjY5YWM3NWVmNGNkMGVkMDVkNC5zZXRDb250ZW50KGh0bWxfYjcyZWRiMDQwZGVhNDBhOGI2MWYwYWU2Mzk5ZmM5Y2MpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjQ4YzBhOTQwZWJhNDA3YmJmNDllZjNiM2E1YzdiYmYuYmluZFBvcHVwKHBvcHVwXzNhZTEyNDhjZjEzMzQ2NjlhYzc1ZWY0Y2QwZWQwNWQ0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2FlNmM0MzU5NGFlNDQ0MzJiZTA2ZjQ1M2JkYTE0ZmM2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTg4NjcyOTQ4MTk5Mjc1LC03NC4wOTYzOTkwNTMxMjUyMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zNGUwOWYxYzBmNTE0NjQyOWJlMjVlNzY3OTg4NzM4MyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iOGZkOWI2ZTBmYzc0ZjZiOGY5OWM0YzUxNDZiNGQ5ZSA9ICQoJzxkaXYgaWQ9Imh0bWxfYjhmZDliNmUwZmM3NGY2YjhmOTljNGM1MTQ2YjRkOWUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvbmdhbiBIaWxscywgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzRlMDlmMWMwZjUxNDY0MjliZTI1ZTc2Nzk4ODczODMuc2V0Q29udGVudChodG1sX2I4ZmQ5YjZlMGZjNzRmNmI4Zjk5YzRjNTE0NmI0ZDllKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2FlNmM0MzU5NGFlNDQ0MzJiZTA2ZjQ1M2JkYTE0ZmM2LmJpbmRQb3B1cChwb3B1cF8zNGUwOWYxYzBmNTE0NjQyOWJlMjVlNzY3OTg4NzM4Myk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hYTFiY2E0ZWExZjU0YTg3ODRjMmY2YjZmZmZhNTRhNiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjU3MzUyNjkwNTc0MjgzLC03NC4wOTM0ODI2NjMwMzU5MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85NjU0YmYxODg1YmY0OTE0ODBjNDI5NmM1MWJkYmI4MCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81YmQyMmI3MDcwYzg0OGU2OTU1NTZjY2IzNTFiMTAzNCA9ICQoJzxkaXYgaWQ9Imh0bWxfNWJkMjJiNzA3MGM4NDhlNjk1NTU2Y2NiMzUxYjEwMzQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1pZGxhbmQgQmVhY2gsIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzk2NTRiZjE4ODViZjQ5MTQ4MGM0Mjk2YzUxYmRiYjgwLnNldENvbnRlbnQoaHRtbF81YmQyMmI3MDcwYzg0OGU2OTU1NTZjY2IzNTFiMTAzNCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hYTFiY2E0ZWExZjU0YTg3ODRjMmY2YjZmZmZhNTRhNi5iaW5kUG9wdXAocG9wdXBfOTY1NGJmMTg4NWJmNDkxNDgwYzQyOTZjNTFiZGJiODApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMTkzNTBjMGQzOWQ4NDgwY2JmMjQ1ODlkMGJmNDkyNzQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC41NzYyMTU1ODcxMTc4OCwtNzQuMTA1ODU1OTg1NDU0MzRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMWZiMmVmNGQ0YjE4NDY0Nzk2NGVjMjQyY2MxMDc5OWYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMTNkMzc0YzRmZDQ1NDBjMmE1YTQ5NzgyOWY0NmI3ZDYgPSAkKCc8ZGl2IGlkPSJodG1sXzEzZDM3NGM0ZmQ0NTQwYzJhNWE0OTc4MjlmNDZiN2Q2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5HcmFudCBDaXR5LCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xZmIyZWY0ZDRiMTg0NjQ3OTY0ZWMyNDJjYzEwNzk5Zi5zZXRDb250ZW50KGh0bWxfMTNkMzc0YzRmZDQ1NDBjMmE1YTQ5NzgyOWY0NmI3ZDYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMTkzNTBjMGQzOWQ4NDgwY2JmMjQ1ODlkMGJmNDkyNzQuYmluZFBvcHVwKHBvcHVwXzFmYjJlZjRkNGIxODQ2NDc5NjRlYzI0MmNjMTA3OTlmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQ5NmMwODE4NjkxYzRmYjBhZmRhYTBmOWJiZmE5ODFjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTY0MjU1NDkzMDczMzUsLTc0LjEwNDMyNzA3NDY5MTI0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2Y3Nzk0OWUxMTc1OTRmMzk5NjNjYjQ1NTA3YWI3NDBlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzgxZGQ3YzNkNDUwODQ1N2E5OTdiOTY0NjcwMDJiZjRiID0gJCgnPGRpdiBpZD0iaHRtbF84MWRkN2MzZDQ1MDg0NTdhOTk3Yjk2NDY3MDAyYmY0YiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TmV3IERvcnAgQmVhY2gsIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Y3Nzk0OWUxMTc1OTRmMzk5NjNjYjQ1NTA3YWI3NDBlLnNldENvbnRlbnQoaHRtbF84MWRkN2MzZDQ1MDg0NTdhOTk3Yjk2NDY3MDAyYmY0Yik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80OTZjMDgxODY5MWM0ZmIwYWZkYWEwZjliYmZhOTgxYy5iaW5kUG9wdXAocG9wdXBfZjc3OTQ5ZTExNzU5NGYzOTk2M2NiNDU1MDdhYjc0MGUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTBmOTM5ZDM5MjljNGRhZGFmNWE3MzY0ZWE1NTFmY2EgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC41NTM5ODgwMDg1ODQ2MiwtNzQuMTM5MTY2MjIxNzU3NjhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjg2MzA4ZTVkN2Y4NDhlMzk2MWMwM2NjZjk2ZmI1NjkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMTdkOWJlYzg2NTNhNDdmOGJhMDQwZDBjMmVmMTE1MjMgPSAkKCc8ZGl2IGlkPSJodG1sXzE3ZDliZWM4NjUzYTQ3ZjhiYTA0MGQwYzJlZjExNTIzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CYXkgVGVycmFjZSwgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZjg2MzA4ZTVkN2Y4NDhlMzk2MWMwM2NjZjk2ZmI1Njkuc2V0Q29udGVudChodG1sXzE3ZDliZWM4NjUzYTQ3ZjhiYTA0MGQwYzJlZjExNTIzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzUwZjkzOWQzOTI5YzRkYWRhZjVhNzM2NGVhNTUxZmNhLmJpbmRQb3B1cChwb3B1cF9mODYzMDhlNWQ3Zjg0OGUzOTYxYzAzY2NmOTZmYjU2OSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl85ZTdlODJkNmJjYmE0NjM1OWYzOWVlZDJmOGFlMjM5MSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjUzMTkxMTkyMDQ4OTYwNSwtNzQuMTkxNzQxMDU3NDc4MTRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMDE0ZGYwMjQ2N2Y2NGI2ZDgzODhlMmUxYTA3ZGFiMGUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfN2FiNjBiY2IwMWZhNGM3OWEwYWI2NGRhNzUzYzRiNmUgPSAkKCc8ZGl2IGlkPSJodG1sXzdhYjYwYmNiMDFmYTRjNzlhMGFiNjRkYTc1M2M0YjZlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IdWd1ZW5vdCwgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDE0ZGYwMjQ2N2Y2NGI2ZDgzODhlMmUxYTA3ZGFiMGUuc2V0Q29udGVudChodG1sXzdhYjYwYmNiMDFmYTRjNzlhMGFiNjRkYTc1M2M0YjZlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzllN2U4MmQ2YmNiYTQ2MzU5ZjM5ZWVkMmY4YWUyMzkxLmJpbmRQb3B1cChwb3B1cF8wMTRkZjAyNDY3ZjY0YjZkODM4OGUyZTFhMDdkYWIwZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84YjAwMzRiZDQ2ZmM0YjIyOGNmNjMzYTM1ODFlY2ExYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjUyNDY5OTM3NjExODEzNiwtNzQuMjE5ODMxMDY2MTY3NzddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYjVmYmZmOTlkZTk1NDBlN2E3N2YwMjE1OWJkODM4ODQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYzE0MTg2YWIxYjIyNGY1NDhiOTFjMDRlMmNiZTRkMTUgPSAkKCc8ZGl2IGlkPSJodG1sX2MxNDE4NmFiMWIyMjRmNTQ4YjkxYzA0ZTJjYmU0ZDE1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5QbGVhc2FudCBQbGFpbnMsIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2I1ZmJmZjk5ZGU5NTQwZTdhNzdmMDIxNTliZDgzODg0LnNldENvbnRlbnQoaHRtbF9jMTQxODZhYjFiMjI0ZjU0OGI5MWMwNGUyY2JlNGQxNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84YjAwMzRiZDQ2ZmM0YjIyOGNmNjMzYTM1ODFlY2ExYi5iaW5kUG9wdXAocG9wdXBfYjVmYmZmOTlkZTk1NDBlN2E3N2YwMjE1OWJkODM4ODQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfM2NiNDY1MGU4Y2RmNDhmODlhMmIyMzEyZDZkOGZjMWMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC41MDYwODE2NTM0NjMwNSwtNzQuMjI5NTAzNTAyNjAwMjddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYTY0ZTJjMjU4YjNjNGNmODhkODkzZmMzNzg3ZTUwNmMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMTdkNGJiZmRhZjRkNGExMzliN2Y4OGYzYThiNmE3ZmQgPSAkKCc8ZGl2IGlkPSJodG1sXzE3ZDRiYmZkYWY0ZDRhMTM5YjdmODhmM2E4YjZhN2ZkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CdXRsZXIgTWFub3IsIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2E2NGUyYzI1OGIzYzRjZjg4ZDg5M2ZjMzc4N2U1MDZjLnNldENvbnRlbnQoaHRtbF8xN2Q0YmJmZGFmNGQ0YTEzOWI3Zjg4ZjNhOGI2YTdmZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zY2I0NjUwZThjZGY0OGY4OWEyYjIzMTJkNmQ4ZmMxYy5iaW5kUG9wdXAocG9wdXBfYTY0ZTJjMjU4YjNjNGNmODhkODkzZmMzNzg3ZTUwNmMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZmM4MDcxMWM3Nzc2NDEwZjllYjkwMThjYWQyMjc2NzcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC41MzA1MzE0ODI4MzMxNCwtNzQuMjMyMTU3NzU4OTY1MjZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOGNhYTYwYmU5YzExNDM1YjkyMmUxZGYzMDcxNmUxMmQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYjc3NjAzMTk4Njg1NDRlOWIwZDM2ZTE1NzcyNTUzNDcgPSAkKCc8ZGl2IGlkPSJodG1sX2I3NzYwMzE5ODY4NTQ0ZTliMGQzNmUxNTc3MjU1MzQ3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DaGFybGVzdG9uLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84Y2FhNjBiZTljMTE0MzViOTIyZTFkZjMwNzE2ZTEyZC5zZXRDb250ZW50KGh0bWxfYjc3NjAzMTk4Njg1NDRlOWIwZDM2ZTE1NzcyNTUzNDcpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZmM4MDcxMWM3Nzc2NDEwZjllYjkwMThjYWQyMjc2NzcuYmluZFBvcHVwKHBvcHVwXzhjYWE2MGJlOWMxMTQzNWI5MjJlMWRmMzA3MTZlMTJkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2NmZDJkMjc3ZDdmNTQ0YmRiNzEzNGJhYTVlNTQ4NGMzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTQ5NDA0MDA2NTAwNzIsLTc0LjIxNTcyODUxMTEzOTUyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzY5ZmUzNmU4NjlhODRkOWRiNTlmNmM4YzlkYjNjMzJlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2YyNzg2OWE1YjY3ODQyMTJiYTE3MGJmNzA2NTAzYmMwID0gJCgnPGRpdiBpZD0iaHRtbF9mMjc4NjlhNWI2Nzg0MjEyYmExNzBiZjcwNjUwM2JjMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Um9zc3ZpbGxlLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82OWZlMzZlODY5YTg0ZDlkYjU5ZjZjOGM5ZGIzYzMyZS5zZXRDb250ZW50KGh0bWxfZjI3ODY5YTViNjc4NDIxMmJhMTcwYmY3MDY1MDNiYzApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfY2ZkMmQyNzdkN2Y1NDRiZGI3MTM0YmFhNWU1NDg0YzMuYmluZFBvcHVwKHBvcHVwXzY5ZmUzNmU4NjlhODRkOWRiNTlmNmM4YzlkYjNjMzJlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzgxYzM1NTViYjNjMjRiNWU5NGRjZTZkODBkODY5ZDcwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTQ5Mjg1ODIyNzgzMjEsLTc0LjE4NTg4Njc0NTgzODkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2FkYWEzZWViZDYwNjRiOTdhMGI2MjMyMDFmYWZjMDBjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc2ZTUxYTVlOGFhMzRlOTZhMmRkMzQ2MTJhNzAxYTdkID0gJCgnPGRpdiBpZD0iaHRtbF83NmU1MWE1ZThhYTM0ZTk2YTJkZDM0NjEyYTcwMWE3ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QXJkZW4gSGVpZ2h0cywgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYWRhYTNlZWJkNjA2NGI5N2EwYjYyMzIwMWZhZmMwMGMuc2V0Q29udGVudChodG1sXzc2ZTUxYTVlOGFhMzRlOTZhMmRkMzQ2MTJhNzAxYTdkKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzgxYzM1NTViYjNjMjRiNWU5NGRjZTZkODBkODY5ZDcwLmJpbmRQb3B1cChwb3B1cF9hZGFhM2VlYmQ2MDY0Yjk3YTBiNjIzMjAxZmFmYzAwYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82NjBiNTk0YzFjY2Q0NDgxYWU4MmMwNjVlYzhhMmYwZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjU1NTI5NTIzNjE3MzE5NCwtNzQuMTcwNzk0MTQ3ODYwOTJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMDM2YTAyYTdkYzkwNDI4ZWFmN2U2NTEwODkyYTE0YjkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNGViYzM1Njg1M2MxNDQ4OWJlYTUyZTk4NjBkZjQzOWIgPSAkKCc8ZGl2IGlkPSJodG1sXzRlYmMzNTY4NTNjMTQ0ODliZWE1MmU5ODYwZGY0MzliIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5HcmVlbnJpZGdlLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wMzZhMDJhN2RjOTA0MjhlYWY3ZTY1MTA4OTJhMTRiOS5zZXRDb250ZW50KGh0bWxfNGViYzM1Njg1M2MxNDQ4OWJlYTUyZTk4NjBkZjQzOWIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNjYwYjU5NGMxY2NkNDQ4MWFlODJjMDY1ZWM4YTJmMGYuYmluZFBvcHVwKHBvcHVwXzAzNmEwMmE3ZGM5MDQyOGVhZjdlNjUxMDg5MmExNGI5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzlhN2Y4ODI1ZmExMzQ4NjdiZmQ0NGFjN2E3MzI4MmZkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTg5MTM4OTQ4NzUyODEsLTc0LjE1OTAyMjA4MTU2NjAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzFiZGRkMmEwNjFhMDRkMmY5MWNkNjc2Y2VlMGY1MmVhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2M5YTEyN2RiZmEwNjQ2Y2NiOWQzOWVmNzc1MWYxOTljID0gJCgnPGRpdiBpZD0iaHRtbF9jOWExMjdkYmZhMDY0NmNjYjlkMzllZjc3NTFmMTk5YyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SGVhcnRsYW5kIFZpbGxhZ2UsIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzFiZGRkMmEwNjFhMDRkMmY5MWNkNjc2Y2VlMGY1MmVhLnNldENvbnRlbnQoaHRtbF9jOWExMjdkYmZhMDY0NmNjYjlkMzllZjc3NTFmMTk5Yyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85YTdmODgyNWZhMTM0ODY3YmZkNDRhYzdhNzMyODJmZC5iaW5kUG9wdXAocG9wdXBfMWJkZGQyYTA2MWEwNGQyZjkxY2Q2NzZjZWUwZjUyZWEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMTRiNTQ3YmVkNTY3NGQzMjkwMTlhOTE4OTcwNjhjZGUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC41OTQ3MjYwMjc0NjI5NSwtNzQuMTg5NTYwNDU1MTk2OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84NjQzODQzOWZjODI0OTU5OTc4ZGJhNWM2YzQ4YTQxMiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hNWM4YmY2MDAzMjY0YzkyODkyNWIyYjJlNWJlYWY0MyA9ICQoJzxkaXYgaWQ9Imh0bWxfYTVjOGJmNjAwMzI2NGM5Mjg5MjViMmIyZTViZWFmNDMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNoZWxzZWEsIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzg2NDM4NDM5ZmM4MjQ5NTk5NzhkYmE1YzZjNDhhNDEyLnNldENvbnRlbnQoaHRtbF9hNWM4YmY2MDAzMjY0YzkyODkyNWIyYjJlNWJlYWY0Myk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xNGI1NDdiZWQ1Njc0ZDMyOTAxOWE5MTg5NzA2OGNkZS5iaW5kUG9wdXAocG9wdXBfODY0Mzg0MzlmYzgyNDk1OTk3OGRiYTVjNmM0OGE0MTIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjdhNmNlMDAyYTIxNDQ3ODgwYTZhOGI1MzEwMmQyOWEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42MDU3Nzg2ODQ1MjM1OCwtNzQuMTg3MjU2MzgzODE1NjddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYTdiYjkyM2ZmNDE3NGQ1YmJhOWE5NGE3YzY5YWM5MDYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMDFmOWJmNWE2ZDNhNDlhY2JmZDg4NTZkYmRmZDFkNzEgPSAkKCc8ZGl2IGlkPSJodG1sXzAxZjliZjVhNmQzYTQ5YWNiZmQ4ODU2ZGJkZmQxZDcxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CbG9vbWZpZWxkLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hN2JiOTIzZmY0MTc0ZDViYmE5YTk0YTdjNjlhYzkwNi5zZXRDb250ZW50KGh0bWxfMDFmOWJmNWE2ZDNhNDlhY2JmZDg4NTZkYmRmZDFkNzEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjdhNmNlMDAyYTIxNDQ3ODgwYTZhOGI1MzEwMmQyOWEuYmluZFBvcHVwKHBvcHVwX2E3YmI5MjNmZjQxNzRkNWJiYTlhOTRhN2M2OWFjOTA2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzFmOTczZjMwZGYzYzRmZjNhNWUwMjAxMTk2ZGJlYjVkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjA5NTkxODAwNDIwMywtNzQuMTU5NDA5NDg2NTcxMjJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNDhhMjQxZjgzMTNiNGIwNTljNGI5MzkyNmZkNjlhMjUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOTM5NzA5NTE2Mjc0NDQ0MmFiZjZlMDllODE3MDhiM2MgPSAkKCc8ZGl2IGlkPSJodG1sXzkzOTcwOTUxNjI3NDQ0NDJhYmY2ZTA5ZTgxNzA4YjNjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CdWxscyBIZWFkLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80OGEyNDFmODMxM2I0YjA1OWM0YjkzOTI2ZmQ2OWEyNS5zZXRDb250ZW50KGh0bWxfOTM5NzA5NTE2Mjc0NDQ0MmFiZjZlMDllODE3MDhiM2MpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMWY5NzNmMzBkZjNjNGZmM2E1ZTAyMDExOTZkYmViNWQuYmluZFBvcHVwKHBvcHVwXzQ4YTI0MWY4MzEzYjRiMDU5YzRiOTM5MjZmZDY5YTI1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzhhZmY4ZmNiZTE4MzQyMjJiOWIxNzEzOGE3MzgwYjcwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzgyNjgyNTY3MTI1NywtNzMuOTUzMjU2NDY4MzcxMTJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNDA3ODNkYWJiZDliNDZkNGI5Y2JhMTFkMTIzMWM1NzkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDA1YTI0NTZlYzMxNDgyZDk5YTU3ZWQ0Yjg5ZmM2MjAgPSAkKCc8ZGl2IGlkPSJodG1sX2QwNWEyNDU2ZWMzMTQ4MmQ5OWE1N2VkNGI4OWZjNjIwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DYXJuZWdpZSBIaWxsLCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzQwNzgzZGFiYmQ5YjQ2ZDRiOWNiYTExZDEyMzFjNTc5LnNldENvbnRlbnQoaHRtbF9kMDVhMjQ1NmVjMzE0ODJkOTlhNTdlZDRiODlmYzYyMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84YWZmOGZjYmUxODM0MjIyYjliMTcxMzhhNzM4MGI3MC5iaW5kUG9wdXAocG9wdXBfNDA3ODNkYWJiZDliNDZkNGI5Y2JhMTFkMTIzMWM1NzkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZDZmNGRlZWUzOGE3NDE5OGE1MzVhYWI4MTVkYTBlYzMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MjMyNTkwMTg4NTc2OCwtNzMuOTg4NDMzNjgwMjM1OTddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNDFjYmFjM2NhYjc2NDQxYmEzMjc1ODQ0Mzg1ODZkNzIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzgwOTlmYTZmM2RjNDNmZjhjNjQ5ZjU4M2Y1Y2Y4MDIgPSAkKCc8ZGl2IGlkPSJodG1sXzc4MDk5ZmE2ZjNkYzQzZmY4YzY0OWY1ODNmNWNmODAyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ob2hvLCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzQxY2JhYzNjYWI3NjQ0MWJhMzI3NTg0NDM4NTg2ZDcyLnNldENvbnRlbnQoaHRtbF83ODA5OWZhNmYzZGM0M2ZmOGM2NDlmNTgzZjVjZjgwMik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9kNmY0ZGVlZTM4YTc0MTk4YTUzNWFhYjgxNWRhMGVjMy5iaW5kUG9wdXAocG9wdXBfNDFjYmFjM2NhYjc2NDQxYmEzMjc1ODQ0Mzg1ODZkNzIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOWYxOThmMThlYjIxNDgwZDk5MDEyMThjZmE3NzNlZjcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTUyMjg5MjA0NjI4MiwtNzQuMDA1NDE1Mjk4NzMzNTVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZmJmZDgzNTUxNzVjNGNjNWFjNmViZjdkMDYzODJhYTIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYjkwZmMwYTE5MWNiNGQxMjk4MDlkMWExYjIxZDc0MTYgPSAkKCc8ZGl2IGlkPSJodG1sX2I5MGZjMGExOTFjYjRkMTI5ODA5ZDFhMWIyMWQ3NDE2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DaXZpYyBDZW50ZXIsIE1hbmhhdHRhbjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZmJmZDgzNTUxNzVjNGNjNWFjNmViZjdkMDYzODJhYTIuc2V0Q29udGVudChodG1sX2I5MGZjMGExOTFjYjRkMTI5ODA5ZDFhMWIyMWQ3NDE2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzlmMTk4ZjE4ZWIyMTQ4MGQ5OTAxMjE4Y2ZhNzczZWY3LmJpbmRQb3B1cChwb3B1cF9mYmZkODM1NTE3NWM0Y2M1YWM2ZWJmN2QwNjM4MmFhMik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84MmVjNzkxMDhjNjM0M2RjOTA5YzZiNDU1N2E1YzViZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc0ODUwOTY2NDMxMjIsLTczLjk4ODcxMzEzMjg1MjQ3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzRhMjgzNzUzYTc5ZDQ5ZDg4ZmM2Yjg2MjA5OTU2ZDA2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2M1N2ViNDQwNjhiYjQyMGU5ZjJkMDZjMDMwNzE1Y2MxID0gJCgnPGRpdiBpZD0iaHRtbF9jNTdlYjQ0MDY4YmI0MjBlOWYyZDA2YzAzMDcxNWNjMSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TWlkdG93biBTb3V0aCwgTWFuaGF0dGFuPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80YTI4Mzc1M2E3OWQ0OWQ4OGZjNmI4NjIwOTk1NmQwNi5zZXRDb250ZW50KGh0bWxfYzU3ZWI0NDA2OGJiNDIwZTlmMmQwNmMwMzA3MTVjYzEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODJlYzc5MTA4YzYzNDNkYzkwOWM2YjQ1NTdhNWM1YmYuYmluZFBvcHVwKHBvcHVwXzRhMjgzNzUzYTc5ZDQ5ZDg4ZmM2Yjg2MjA5OTU2ZDA2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzdlZTMzZGU3ZGE3ODRjZDk4MDY5OTJlZDQ1NTJkNmQxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTY5NjA1OTQyNzU1MDUsLTc0LjEzNDA1NzI5ODYyNTddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYmZhZDMyZTMxMDBkNDVjMmI2MGM1NmE2NDJlYThlYzMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfM2VhNGFkMTljNWY2NDIxMWFlZjgzMGNhZTExMDBiNWQgPSAkKCc8ZGl2IGlkPSJodG1sXzNlYTRhZDE5YzVmNjQyMTFhZWY4MzBjYWUxMTAwYjVkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5SaWNobW9uZCBUb3duLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iZmFkMzJlMzEwMGQ0NWMyYjYwYzU2YTY0MmVhOGVjMy5zZXRDb250ZW50KGh0bWxfM2VhNGFkMTljNWY2NDIxMWFlZjgzMGNhZTExMDBiNWQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfN2VlMzNkZTdkYTc4NGNkOTgwNjk5MmVkNDU1MmQ2ZDEuYmluZFBvcHVwKHBvcHVwX2JmYWQzMmUzMTAwZDQ1YzJiNjBjNTZhNjQyZWE4ZWMzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzBjOGU4ZDUwZWNjNTQxNjI5MjEyNjhiMTU4OTQwM2JlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjA5NzE5MzQwNzkyODQsLTc0LjA2NjY3NzY2MDYxNzcxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzY1NTY2YjE3MjM2MjQ1NWQ4ZjczNGM4YmUxZjk3YmE0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc5YzljOTFjYTJkMzRhYThiYjRmMGNhY2Q3NDY0NWYwID0gJCgnPGRpdiBpZD0iaHRtbF83OWM5YzkxY2EyZDM0YWE4YmI0ZjBjYWNkNzQ2NDVmMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U2hvcmUgQWNyZXMsIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzY1NTY2YjE3MjM2MjQ1NWQ4ZjczNGM4YmUxZjk3YmE0LnNldENvbnRlbnQoaHRtbF83OWM5YzkxY2EyZDM0YWE4YmI0ZjBjYWNkNzQ2NDVmMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wYzhlOGQ1MGVjYzU0MTYyOTIxMjY4YjE1ODk0MDNiZS5iaW5kUG9wdXAocG9wdXBfNjU1NjZiMTcyMzYyNDU1ZDhmNzM0YzhiZTFmOTdiYTQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjEzOWJjNmM3M2U5NGRiYjhjYjBhYmQ1YjcyYWExY2MgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42MTkxNzg0NTIwMjg0MywtNzQuMDcyNjQyNDQ1NDg0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RiOTIyMjhjYmFiYzRjY2ViN2U1MzM5MWNlMjViY2M5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzNkMWNmNzA2M2JlYTRlNDI4NDRkNGM3MjA2OWY5YTA2ID0gJCgnPGRpdiBpZD0iaHRtbF8zZDFjZjcwNjNiZWE0ZTQyODQ0ZDRjNzIwNjlmOWEwNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q2xpZnRvbiwgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZGI5MjIyOGNiYWJjNGNjZWI3ZTUzMzkxY2UyNWJjYzkuc2V0Q29udGVudChodG1sXzNkMWNmNzA2M2JlYTRlNDI4NDRkNGM3MjA2OWY5YTA2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2IxMzliYzZjNzNlOTRkYmI4Y2IwYWJkNWI3MmFhMWNjLmJpbmRQb3B1cChwb3B1cF9kYjkyMjI4Y2JhYmM0Y2NlYjdlNTMzOTFjZTI1YmNjOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81NzI1Zjg0YmQ5OTE0OTIwODAyYjI1NjZkMjk3OTIyNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjYwNDQ3MzE4OTY4NzksLTc0LjA4NDAyMzY0NzQwMzU4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzBkZjc2MGJiYzUzNjRmMTM5N2JhNmVlNjBjZjBiNjcxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzI4YmI4NTQzZTI0ZDRkODViODVmMjk0MDA4MTI2OTFjID0gJCgnPGRpdiBpZD0iaHRtbF8yOGJiODU0M2UyNGQ0ZDg1Yjg1ZjI5NDAwODEyNjkxYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q29uY29yZCwgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMGRmNzYwYmJjNTM2NGYxMzk3YmE2ZWU2MGNmMGI2NzEuc2V0Q29udGVudChodG1sXzI4YmI4NTQzZTI0ZDRkODViODVmMjk0MDA4MTI2OTFjKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU3MjVmODRiZDk5MTQ5MjA4MDJiMjU2NmQyOTc5MjI1LmJpbmRQb3B1cChwb3B1cF8wZGY3NjBiYmM1MzY0ZjEzOTdiYTZlZTYwY2YwYjY3MSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jYjdiY2Q2MmE4YTg0NTEyYThkMTZkYzQyYWVjZmEwNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjYwNjc5NDM5NDgwMSwtNzQuMDk3NzYyMDY5NzI1MjJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOTNiNGVhOTM0YTg1NDg3ZGJhY2E3NjQxYzc2MWRiMDUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYzdkZTE3ZDIwYzgyNGIyY2IwMGUwZjE2ODdlYWM2NzggPSAkKCc8ZGl2IGlkPSJodG1sX2M3ZGUxN2QyMGM4MjRiMmNiMDBlMGYxNjg3ZWFjNjc4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FbWVyc29uIEhpbGwsIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzkzYjRlYTkzNGE4NTQ4N2RiYWNhNzY0MWM3NjFkYjA1LnNldENvbnRlbnQoaHRtbF9jN2RlMTdkMjBjODI0YjJjYjAwZTBmMTY4N2VhYzY3OCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jYjdiY2Q2MmE4YTg0NTEyYThkMTZkYzQyYWVjZmEwNC5iaW5kUG9wdXAocG9wdXBfOTNiNGVhOTM0YTg1NDg3ZGJhY2E3NjQxYzc2MWRiMDUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfY2U4YWY3MDBjOTk0NGJjZDhkMTg0OGRlMWNkM2E1YzUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42MzU2MzAwMDY4MTE1MSwtNzQuMDk4MDUwNjIzNzM4ODddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZTY3NDI2YWEwZTg4NGUxMGFiZTMyMTFjODdlZTEwNjYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYzI0NzM0NjUwOTYwNDA3NzlkZTJlZTZkMmExODhmNGYgPSAkKCc8ZGl2IGlkPSJodG1sX2MyNDczNDY1MDk2MDQwNzc5ZGUyZWU2ZDJhMTg4ZjRmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5SYW5kYWxsIE1hbm9yLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lNjc0MjZhYTBlODg0ZTEwYWJlMzIxMWM4N2VlMTA2Ni5zZXRDb250ZW50KGh0bWxfYzI0NzM0NjUwOTYwNDA3NzlkZTJlZTZkMmExODhmNGYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfY2U4YWY3MDBjOTk0NGJjZDhkMTg0OGRlMWNkM2E1YzUuYmluZFBvcHVwKHBvcHVwX2U2NzQyNmFhMGU4ODRlMTBhYmUzMjExYzg3ZWUxMDY2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzlkZWU4YzE2NmRjMzQ2ODZiMDcyMzRkM2UxNDQyZWYyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjM4NDMyODM3OTQ3OTUsLTc0LjE4NjIyMzMxNzQ5ODIzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2ViMmZkNjhhZjQzMjQ3OTliMzQzNzE3ZDcxYmRjYmYxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzYwZGNiZWNiOGE4MTQ2YWU5NjliYzA3NGI5NDU3MjM4ID0gJCgnPGRpdiBpZD0iaHRtbF82MGRjYmVjYjhhODE0NmFlOTY5YmMwNzRiOTQ1NzIzOCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SG93bGFuZCBIb29rLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lYjJmZDY4YWY0MzI0Nzk5YjM0MzcxN2Q3MWJkY2JmMS5zZXRDb250ZW50KGh0bWxfNjBkY2JlY2I4YTgxNDZhZTk2OWJjMDc0Yjk0NTcyMzgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOWRlZThjMTY2ZGMzNDY4NmIwNzIzNGQzZTE0NDJlZjIuYmluZFBvcHVwKHBvcHVwX2ViMmZkNjhhZjQzMjQ3OTliMzQzNzE3ZDcxYmRjYmYxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzE4ZTM3NGZlYWI0MjQ0Y2RhNDNlZjI5ZTEzNjRlNTY3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjMwMTQ2NzQxMTkzODI2LC03NC4xNDE4MTY3ODk2ODg5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzk5MzNjMWU0NDhkMzRkN2ViZmRkNTQyYWU3MDZmNzczID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2JmMmZlN2VhMDYzMTQ5ZDZiNTQ2N2U3ZjExY2U0ZTllID0gJCgnPGRpdiBpZD0iaHRtbF9iZjJmZTdlYTA2MzE0OWQ2YjU0NjdlN2YxMWNlNGU5ZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RWxtIFBhcmssIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzk5MzNjMWU0NDhkMzRkN2ViZmRkNTQyYWU3MDZmNzczLnNldENvbnRlbnQoaHRtbF9iZjJmZTdlYTA2MzE0OWQ2YjU0NjdlN2YxMWNlNGU5ZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xOGUzNzRmZWFiNDI0NGNkYTQzZWYyOWUxMzY0ZTU2Ny5iaW5kUG9wdXAocG9wdXBfOTkzM2MxZTQ0OGQzNGQ3ZWJmZGQ1NDJhZTcwNmY3NzMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOWI3NTBmODY1NmExNGVmZGIyMTY2MDJmZDg1NjE3OWMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42NTIxMTc0NTE3OTM0OTQsLTczLjkxNjY1MzMxOTc4MDQ4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2FjMWFiY2I2OGJlZjRiOTA5ZDllZWVkMTI3MTI5ZGNlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc2MGYxOTNmOTRlMDQ0ODNiNjg4M2ZjYmViY2MzYTU5ID0gJCgnPGRpdiBpZD0iaHRtbF83NjBmMTkzZjk0ZTA0NDgzYjY4ODNmY2JlYmNjM2E1OSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UmVtc2VuIFZpbGxhZ2UsIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hYzFhYmNiNjhiZWY0YjkwOWQ5ZWVlZDEyNzEyOWRjZS5zZXRDb250ZW50KGh0bWxfNzYwZjE5M2Y5NGUwNDQ4M2I2ODgzZmNiZWJjYzNhNTkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOWI3NTBmODY1NmExNGVmZGIyMTY2MDJmZDg1NjE3OWMuYmluZFBvcHVwKHBvcHVwX2FjMWFiY2I2OGJlZjRiOTA5ZDllZWVkMTI3MTI5ZGNlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzBlZjUwM2Q1MTVmZDRjZTNhYmE3NGNhODcwYWMzNjdmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjYyNzQ0Mjc5Njk2NiwtNzMuODg1MTE3NzYzNzkyOTJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYmExZDJhZTAwMjQxNGFiMWFjZmRkNDgyNjI4OTQ3NjIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNTJmNjljNWZjZDAwNGNkZDk2OTg3YWQyMjJhNDMzNDUgPSAkKCc8ZGl2IGlkPSJodG1sXzUyZjY5YzVmY2QwMDRjZGQ5Njk4N2FkMjIyYTQzMzQ1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5OZXcgTG90cywgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2JhMWQyYWUwMDI0MTRhYjFhY2ZkZDQ4MjYyODk0NzYyLnNldENvbnRlbnQoaHRtbF81MmY2OWM1ZmNkMDA0Y2RkOTY5ODdhZDIyMmE0MzM0NSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wZWY1MDNkNTE1ZmQ0Y2UzYWJhNzRjYTg3MGFjMzY3Zi5iaW5kUG9wdXAocG9wdXBfYmExZDJhZTAwMjQxNGFiMWFjZmRkNDgyNjI4OTQ3NjIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfM2NlMDBkNzVhYjA5NGVkYjlhOWM0NTNmODFjNjRiMDMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42MzEzMTc1NTAzOTY2NywtNzMuOTAyMzM0NzQyOTU4MzZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjU2OWIzZDdmN2VlNGI3ZWJhODk2YWQ4ZWI4ZjZjMGQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjE4MmRlMDU3OGNiNGMyMGIxZDZlYjcyOTdjMmY3NDIgPSAkKCc8ZGl2IGlkPSJodG1sX2YxODJkZTA1NzhjYjRjMjBiMWQ2ZWI3Mjk3YzJmNzQyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5QYWVyZGVnYXQgQmFzaW4sIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mNTY5YjNkN2Y3ZWU0YjdlYmE4OTZhZDhlYjhmNmMwZC5zZXRDb250ZW50KGh0bWxfZjE4MmRlMDU3OGNiNGMyMGIxZDZlYjcyOTdjMmY3NDIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfM2NlMDBkNzVhYjA5NGVkYjlhOWM0NTNmODFjNjRiMDMuYmluZFBvcHVwKHBvcHVwX2Y1NjliM2Q3ZjdlZTRiN2ViYTg5NmFkOGViOGY2YzBkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y0YWU4ZjFlNjcwNzRiODU5YjU4YmU4NDRkODM4MWY3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjE1OTc0MjM5NjIzMzYsLTczLjkxNTE1MzkxNTUwNDA0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzFhOGI3MjAxOTE1YzRiNzE5ZGQ3ZTcyM2YyNzhiNTY3ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzkyNGJiOWM5NzFhYzRiYTg5NTMzNDliNzMyM2RlZWM5ID0gJCgnPGRpdiBpZD0iaHRtbF85MjRiYjljOTcxYWM0YmE4OTUzMzQ5YjczMjNkZWVjOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TWlsbCBCYXNpbiwgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzFhOGI3MjAxOTE1YzRiNzE5ZGQ3ZTcyM2YyNzhiNTY3LnNldENvbnRlbnQoaHRtbF85MjRiYjljOTcxYWM0YmE4OTUzMzQ5YjczMjNkZWVjOSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mNGFlOGYxZTY3MDc0Yjg1OWI1OGJlODQ0ZDgzODFmNy5iaW5kUG9wdXAocG9wdXBfMWE4YjcyMDE5MTVjNGI3MTlkZDdlNzIzZjI3OGI1NjcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjAyMDA4ZTUzNzExNGY4Zjg4NDk3ZjQ5M2VlMGVlNzcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MTE0NTk2NDM3MDQ4MiwtNzMuNzk2NDY0NjIwODE1OTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZGU0NDdmNTdhM2I0NGI4NWExZTIwNGQxMWI4ZGFiZTcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNjkxMTFkYWY3MGY5NGIwMThjNDNmMDZlMTBjNDNiMGEgPSAkKCc8ZGl2IGlkPSJodG1sXzY5MTExZGFmNzBmOTRiMDE4YzQzZjA2ZTEwYzQzYjBhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5KYW1haWNhIEhpbGxzLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2RlNDQ3ZjU3YTNiNDRiODVhMWUyMDRkMTFiOGRhYmU3LnNldENvbnRlbnQoaHRtbF82OTExMWRhZjcwZjk0YjAxOGM0M2YwNmUxMGM0M2IwYSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mMDIwMDhlNTM3MTE0ZjhmODg0OTdmNDkzZWUwZWU3Ny5iaW5kUG9wdXAocG9wdXBfZGU0NDdmNTdhM2I0NGI4NWExZTIwNGQxMWI4ZGFiZTcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMzYwMTI0MWZjYWNkNDMzMzk5YzYxMWMxZTI1Y2M5NGUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MzM1MDAyNTQyOTc1NywtNzMuNzk2NzE2NzgwMjgzNDldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfN2U2ZjE3YzBhZmI3NDdmYmIwZDdlOTljZDU5NGJhZGUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfY2FjOWY4ODA0YmJjNDQwMzg3YTFiYTVjNGQzMjU2MzYgPSAkKCc8ZGl2IGlkPSJodG1sX2NhYzlmODgwNGJiYzQ0MDM4N2ExYmE1YzRkMzI1NjM2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5VdG9waWEsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfN2U2ZjE3YzBhZmI3NDdmYmIwZDdlOTljZDU5NGJhZGUuc2V0Q29udGVudChodG1sX2NhYzlmODgwNGJiYzQ0MDM4N2ExYmE1YzRkMzI1NjM2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzM2MDEyNDFmY2FjZDQzMzM5OWM2MTFjMWUyNWNjOTRlLmJpbmRQb3B1cChwb3B1cF83ZTZmMTdjMGFmYjc0N2ZiYjBkN2U5OWNkNTk0YmFkZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jOTIyY2M3M2RmZjc0ZTU4YjYzYzgxN2Y4N2YwM2JmYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjczNDkzNjE4MDc1NDc4LC03My44MDQ4NjEyMDA0MDUzN10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wYTg5YWM1MjBjZGI0YWRkYWU1OTk1MmMyMGI2ODU3MCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jMmEyNWNhODYzYmY0MGQ3YTJkY2M5OGE0ZmQwNjVjOCA9ICQoJzxkaXYgaWQ9Imh0bWxfYzJhMjVjYTg2M2JmNDBkN2EyZGNjOThhNGZkMDY1YzgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlBvbW9ub2ssIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMGE4OWFjNTIwY2RiNGFkZGFlNTk5NTJjMjBiNjg1NzAuc2V0Q29udGVudChodG1sX2MyYTI1Y2E4NjNiZjQwZDdhMmRjYzk4YTRmZDA2NWM4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2M5MjJjYzczZGZmNzRlNThiNjNjODE3Zjg3ZjAzYmZiLmJpbmRQb3B1cChwb3B1cF8wYTg5YWM1MjBjZGI0YWRkYWU1OTk1MmMyMGI2ODU3MCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zZWFkM2NjYWYzYWM0MGQ2YjY4NTFhOGIwZWZhZmYwNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc3MDMxNzM5Mjk5ODIsLTczLjg5NDY3OTk2MjcwNTc0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzhiZGU4MWJkNjlhYTQxZTViYmMxNDg1ZTU5YWU3YjA2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2FiODZjMDczZDUzNTQ3MDZhNjdkYmZmMGNmNjFjMTA3ID0gJCgnPGRpdiBpZD0iaHRtbF9hYjg2YzA3M2Q1MzU0NzA2YTY3ZGJmZjBjZjYxYzEwNyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QXN0b3JpYSBIZWlnaHRzLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzhiZGU4MWJkNjlhYTQxZTViYmMxNDg1ZTU5YWU3YjA2LnNldENvbnRlbnQoaHRtbF9hYjg2YzA3M2Q1MzU0NzA2YTY3ZGJmZjBjZjYxYzEwNyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zZWFkM2NjYWYzYWM0MGQ2YjY4NTFhOGIwZWZhZmYwNC5iaW5kUG9wdXAocG9wdXBfOGJkZTgxYmQ2OWFhNDFlNWJiYzE0ODVlNTlhZTdiMDYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMzYyNDIwYzVkZjViNDgyN2I4MDZjMWFjZDQ2MTg1MWYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44MzE0MjgzNDE2MTU0OCwtNzMuOTAxMTk5MDMzODc2NjddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZGEwOGNlNzNiZDEwNGQ5Yzk1MWQxNDQ2Y2NlZTVmMmQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNjliMmMzOTY0ZTFkNDAyYWJkNzQ1ODA5ODUxZjY5NGUgPSAkKCc8ZGl2IGlkPSJodG1sXzY5YjJjMzk2NGUxZDQwMmFiZDc0NTgwOTg1MWY2OTRlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DbGFyZW1vbnQgVmlsbGFnZSwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2RhMDhjZTczYmQxMDRkOWM5NTFkMTQ0NmNjZWU1ZjJkLnNldENvbnRlbnQoaHRtbF82OWIyYzM5NjRlMWQ0MDJhYmQ3NDU4MDk4NTFmNjk0ZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zNjI0MjBjNWRmNWI0ODI3YjgwNmMxYWNkNDYxODUxZi5iaW5kUG9wdXAocG9wdXBfZGEwOGNlNzNiZDEwNGQ5Yzk1MWQxNDQ2Y2NlZTVmMmQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMWNjOTkwYTg0YzM3NGFkY2FiOWIyODE1ZTc5ZjAzOGIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44MjQ3ODA0OTA4NDI5MDUsLTczLjkxNTg0NjUyNzU5MDA5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2VkNTEwNzU5YjAwNTQ4ZDU5NmVhNzBkZGUyYTU4YjMxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzkzNTU4YTJkYzRkNjRiMDk5N2Y4NmVlYzc3MzAyZjk1ID0gJCgnPGRpdiBpZD0iaHRtbF85MzU1OGEyZGM0ZDY0YjA5OTdmODZlZWM3NzMwMmY5NSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q29uY291cnNlIFZpbGxhZ2UsIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lZDUxMDc1OWIwMDU0OGQ1OTZlYTcwZGRlMmE1OGIzMS5zZXRDb250ZW50KGh0bWxfOTM1NThhMmRjNGQ2NGIwOTk3Zjg2ZWVjNzczMDJmOTUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMWNjOTkwYTg0YzM3NGFkY2FiOWIyODE1ZTc5ZjAzOGIuYmluZFBvcHVwKHBvcHVwX2VkNTEwNzU5YjAwNTQ4ZDU5NmVhNzBkZGUyYTU4YjMxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2YyOTBlMTYxMGYxYjRhZjM5YmVjZmJlNzE4MWZmMTgwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODQzODI2MTc2NzE2NTQsLTczLjkxNjU1NTUxOTY0NDE5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzdkNmY1Nzg5MWNlMzQzNDM4YjkwYzRjMTE4MzQyOGI2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzk2M2VjMzQxZDFiMTRlNzliNTk4YTIzZjZiY2ZiZmUwID0gJCgnPGRpdiBpZD0iaHRtbF85NjNlYzM0MWQxYjE0ZTc5YjU5OGEyM2Y2YmNmYmZlMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TW91bnQgRWRlbiwgQnJvbng8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzdkNmY1Nzg5MWNlMzQzNDM4YjkwYzRjMTE4MzQyOGI2LnNldENvbnRlbnQoaHRtbF85NjNlYzM0MWQxYjE0ZTc5YjU5OGEyM2Y2YmNmYmZlMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mMjkwZTE2MTBmMWI0YWYzOWJlY2ZiZTcxODFmZjE4MC5iaW5kUG9wdXAocG9wdXBfN2Q2ZjU3ODkxY2UzNDM0MzhiOTBjNGMxMTgzNDI4YjYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYWZkMjkyZGQyM2NiNDM3MTk3YTAyNjlhYTBiMTAxMGEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44NDg4NDE2MDcyNDY2NSwtNzMuOTA4Mjk5MzA4ODE5ODhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfY2RhMDM1ZThhYThkNDUzNmIyYjc0YmQ0MjRjYTQ4MmIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfN2YyYmU1NjNmN2MxNDliMTgzMzJiN2U2ODU4NjljMjMgPSAkKCc8ZGl2IGlkPSJodG1sXzdmMmJlNTYzZjdjMTQ5YjE4MzMyYjdlNjg1ODY5YzIzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Nb3VudCBIb3BlLCBCcm9ueDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfY2RhMDM1ZThhYThkNDUzNmIyYjc0YmQ0MjRjYTQ4MmIuc2V0Q29udGVudChodG1sXzdmMmJlNTYzZjdjMTQ5YjE4MzMyYjdlNjg1ODY5YzIzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2FmZDI5MmRkMjNjYjQzNzE5N2EwMjY5YWEwYjEwMTBhLmJpbmRQb3B1cChwb3B1cF9jZGEwMzVlOGFhOGQ0NTM2YjJiNzRiZDQyNGNhNDgyYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kOWE5OThkMzVlNDM0OWY3YmE0Njk5ODhlMWEzNDBjNiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc2MDI4MDMzMTMxMzc0LC03My45NjM1NTYxNDA5NDMwM10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84MDZhOTUzZTkzMDk0OWVhOTM5YzllZGI2NDQxNTRlOCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wMTIyMmExNjM4NGU0MDA2YmI2ZWVlYzNlN2I4NjE2OCA9ICQoJzxkaXYgaWQ9Imh0bWxfMDEyMjJhMTYzODRlNDAwNmJiNmVlZWMzZTdiODYxNjgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlN1dHRvbiBQbGFjZSwgTWFuaGF0dGFuPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84MDZhOTUzZTkzMDk0OWVhOTM5YzllZGI2NDQxNTRlOC5zZXRDb250ZW50KGh0bWxfMDEyMjJhMTYzODRlNDAwNmJiNmVlZWMzZTdiODYxNjgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZDlhOTk4ZDM1ZTQzNDlmN2JhNDY5OTg4ZTFhMzQwYzYuYmluZFBvcHVwKHBvcHVwXzgwNmE5NTNlOTMwOTQ5ZWE5MzljOWVkYjY0NDE1NGU4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzhlMzEzNzZmMzVlNDRjYzI4OGE2NzQxOGI1OTI4YmZkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzQzNDE0MDkwMDczNTM2LC03My45NTM4Njc4MjEzMDc0NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wMjA4NzA1Y2VjNDA0NDhiYWEzNGRmMTIxNWZmODFiYiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wNzAwNGU5OTFhYzc0N2M0Yjg2NmQxMTgxMDcxZmY3OSA9ICQoJzxkaXYgaWQ9Imh0bWxfMDcwMDRlOTkxYWM3NDdjNGI4NjZkMTE4MTA3MWZmNzkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkh1bnRlcnMgUG9pbnQsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDIwODcwNWNlYzQwNDQ4YmFhMzRkZjEyMTVmZjgxYmIuc2V0Q29udGVudChodG1sXzA3MDA0ZTk5MWFjNzQ3YzRiODY2ZDExODEwNzFmZjc5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzhlMzEzNzZmMzVlNDRjYzI4OGE2NzQxOGI1OTI4YmZkLmJpbmRQb3B1cChwb3B1cF8wMjA4NzA1Y2VjNDA0NDhiYWEzNGRmMTIxNWZmODFiYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wMzA4ZjQ3NjgxNzI0ZTdiYjU1MTY2MmNlNTU0MjZkMyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc1MjA0MjM2OTUwNzIyLC03My45Njc3MDgyNDU4MTgzNF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zNGFjZDMwNjllNDg0YjM4OGY4YTE0ZGYxZDk5ZTE0MSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81ZmJiZGVkNTlmYTY0MjNlYmY2Yzk2ZDIyNWVmOTNiMSA9ICQoJzxkaXYgaWQ9Imh0bWxfNWZiYmRlZDU5ZmE2NDIzZWJmNmM5NmQyMjVlZjkzYjEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlR1cnRsZSBCYXksIE1hbmhhdHRhbjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzRhY2QzMDY5ZTQ4NGIzODhmOGExNGRmMWQ5OWUxNDEuc2V0Q29udGVudChodG1sXzVmYmJkZWQ1OWZhNjQyM2ViZjZjOTZkMjI1ZWY5M2IxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzAzMDhmNDc2ODE3MjRlN2JiNTUxNjYyY2U1NTQyNmQzLmJpbmRQb3B1cChwb3B1cF8zNGFjZDMwNjllNDg0YjM4OGY4YTE0ZGYxZDk5ZTE0MSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wYzllYzI1MzU1NWY0OWExOWIwYTc3ZjQyOTUwNzVjNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjc0NjkxNzQxMDc0MDE5NSwtNzMuOTcxMjE5Mjg3MjIyNjVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZTIyM2VhN2NiZTgxNDczODljNGM2ZjIwOTA3ZGEwYTIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZmU5ODkzZjRlZjMyNGQ2OTg0NWE1YWNlMzcwOWM3OTkgPSAkKCc8ZGl2IGlkPSJodG1sX2ZlOTg5M2Y0ZWYzMjRkNjk4NDVhNWFjZTM3MDljNzk5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UdWRvciBDaXR5LCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2UyMjNlYTdjYmU4MTQ3Mzg5YzRjNmYyMDkwN2RhMGEyLnNldENvbnRlbnQoaHRtbF9mZTk4OTNmNGVmMzI0ZDY5ODQ1YTVhY2UzNzA5Yzc5OSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wYzllYzI1MzU1NWY0OWExOWIwYTc3ZjQyOTUwNzVjNy5iaW5kUG9wdXAocG9wdXBfZTIyM2VhN2NiZTgxNDczODljNGM2ZjIwOTA3ZGEwYTIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjk5NWJkZDhiNmVjNDZkODg2NGZlZWFkZGM3ZTQ1ZTggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43MzA5OTk1NTQ3NzA2MSwtNzMuOTc0MDUxNzA0NjkyMDNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZWE0MjQ4MTIwMTI2NGRhYTkzMmQ1Mzk0MDlkZWMzYmYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYzBkMWE0NGZiNmY3NDUyMWFiYzRkZmFmYjIzODg4MDMgPSAkKCc8ZGl2IGlkPSJodG1sX2MwZDFhNDRmYjZmNzQ1MjFhYmM0ZGZhZmIyMzg4ODAzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TdHV5dmVzYW50IFRvd24sIE1hbmhhdHRhbjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZWE0MjQ4MTIwMTI2NGRhYTkzMmQ1Mzk0MDlkZWMzYmYuc2V0Q29udGVudChodG1sX2MwZDFhNDRmYjZmNzQ1MjFhYmM0ZGZhZmIyMzg4ODAzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2I5OTViZGQ4YjZlYzQ2ZDg4NjRmZWVhZGRjN2U0NWU4LmJpbmRQb3B1cChwb3B1cF9lYTQyNDgxMjAxMjY0ZGFhOTMyZDUzOTQwOWRlYzNiZik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mMzMwODg4OGI5Y2U0NGRiOWJjYTQwZmNiNjY0MDM3OSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjczOTY3MzA0NzYzODQyNiwtNzMuOTkwOTQ3MTA1MjgyNl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81YjMzMDE1NmZkODc0MDMwYWQ5YWI5NDNkYmJjMDk1NyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mYzM2MzExZGU3YTM0MzJiODk3NWI2NDJiODRhYzU5MCA9ICQoJzxkaXYgaWQ9Imh0bWxfZmMzNjMxMWRlN2EzNDMyYjg5NzViNjQyYjg0YWM1OTAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZsYXRpcm9uLCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzViMzMwMTU2ZmQ4NzQwMzBhZDlhYjk0M2RiYmMwOTU3LnNldENvbnRlbnQoaHRtbF9mYzM2MzExZGU3YTM0MzJiODk3NWI2NDJiODRhYzU5MCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mMzMwODg4OGI5Y2U0NGRiOWJjYTQwZmNiNjY0MDM3OS5iaW5kUG9wdXAocG9wdXBfNWIzMzAxNTZmZDg3NDAzMGFkOWFiOTQzZGJiYzA5NTcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMmZlNDRkZTIxNTNkNGZiNzk2ZjdmOGIxZmJkZDNhNmYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43NDU2NTE4MDYwODA3NiwtNzMuOTE4MTkyODY0MzE2ODJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYWQ2NGQ3MjJjMGE3NGVjNDlhMDViYTI0YWJmODM2ZWEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfM2JlYzMzNTc4MTY3NGEwOGIwMGU5ODRlYTI2MzU0ODUgPSAkKCc8ZGl2IGlkPSJodG1sXzNiZWMzMzU3ODE2NzRhMDhiMDBlOTg0ZWEyNjM1NDg1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TdW5ueXNpZGUgR2FyZGVucywgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hZDY0ZDcyMmMwYTc0ZWM0OWEwNWJhMjRhYmY4MzZlYS5zZXRDb250ZW50KGh0bWxfM2JlYzMzNTc4MTY3NGEwOGIwMGU5ODRlYTI2MzU0ODUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMmZlNDRkZTIxNTNkNGZiNzk2ZjdmOGIxZmJkZDNhNmYuYmluZFBvcHVwKHBvcHVwX2FkNjRkNzIyYzBhNzRlYzQ5YTA1YmEyNGFiZjgzNmVhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzEwMjcwNmMwYzBjNTQxNThiZGEzYTU1NmY3OTg0MDI2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzM3MjUwNzE2OTQ0OTcsLTczLjkzMjQ0MjM1MjYwMTc4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzFjNGJiZWZiOWJhMDQ0OWI5ZDljZDg4NDZmMjAwODBlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzU5NjIyZGJjYzIzZjRlZmM5Y2E2ZTM5Yzk2NTFhMTlkID0gJCgnPGRpdiBpZD0iaHRtbF81OTYyMmRiY2MyM2Y0ZWZjOWNhNmUzOWM5NjUxYTE5ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Qmxpc3N2aWxsZSwgUXVlZW5zPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xYzRiYmVmYjliYTA0NDliOWQ5Y2Q4ODQ2ZjIwMDgwZS5zZXRDb250ZW50KGh0bWxfNTk2MjJkYmNjMjNmNGVmYzljYTZlMzljOTY1MWExOWQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMTAyNzA2YzBjMGM1NDE1OGJkYTNhNTU2Zjc5ODQwMjYuYmluZFBvcHVwKHBvcHVwXzFjNGJiZWZiOWJhMDQ0OWI5ZDljZDg4NDZmMjAwODBlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzNhZThkZWI5MTQ1ZTQ4NmU4YWEzYjI0MzhhNTk4NTBmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzAzMjgxMDkwOTMwMTQsLTczLjk5NTUwNzUxODg4NDE1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2I5YzBjZGUxNWVmYTRjMWM4ZjgwMGQzODdhM2U1YjNjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzRjNmFiZmRjMGNlNzRjMDA5YmQzMWE5YjYwOTk5YjMzID0gJCgnPGRpdiBpZD0iaHRtbF80YzZhYmZkYzBjZTc0YzAwOWJkMzFhOWI2MDk5OWIzMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RnVsdG9uIEZlcnJ5LCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjljMGNkZTE1ZWZhNGMxYzhmODAwZDM4N2EzZTViM2Muc2V0Q29udGVudChodG1sXzRjNmFiZmRjMGNlNzRjMDA5YmQzMWE5YjYwOTk5YjMzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzNhZThkZWI5MTQ1ZTQ4NmU4YWEzYjI0MzhhNTk4NTBmLmJpbmRQb3B1cChwb3B1cF9iOWMwY2RlMTVlZmE0YzFjOGY4MDBkMzg3YTNlNWIzYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yNDY3ZDY0ZmY5MWM0NTIyYTljOGQxMWVkYTA0ODIxNiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcwMzMyMTQ5ODgyODc0LC03My45ODExMTYwMzU5MjM5M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kZTE4ZmJiNzk0NWI0OGI2YjU5NGRkMTIwZWJkY2Y5OSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lNGM4NDgyZWNiZTk0ODlkYWE4N2U1YjFhMjcyMTRmMCA9ICQoJzxkaXYgaWQ9Imh0bWxfZTRjODQ4MmVjYmU5NDg5ZGFhODdlNWIxYTI3MjE0ZjAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlZpbmVnYXIgSGlsbCwgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2RlMThmYmI3OTQ1YjQ4YjZiNTk0ZGQxMjBlYmRjZjk5LnNldENvbnRlbnQoaHRtbF9lNGM4NDgyZWNiZTk0ODlkYWE4N2U1YjFhMjcyMTRmMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yNDY3ZDY0ZmY5MWM0NTIyYTljOGQxMWVkYTA0ODIxNi5iaW5kUG9wdXAocG9wdXBfZGUxOGZiYjc5NDViNDhiNmI1OTRkZDEyMGViZGNmOTkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZTBiYTk2YTc4YTEzNDFjODlhNjA3NTE1MzJmOGNlMzQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42NzUwMzk4NjUwMzIzNywtNzMuOTMwNTMxMDg4MTczMzhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMjAzNzFjODA0NGFkNDM5MGEwM2E5Y2ZhNTE0M2ZlMzYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMTQwNGM4N2QyNmNkNGVlYjhlNDViMWQyNDY0Y2UwOWIgPSAkKCc8ZGl2IGlkPSJodG1sXzE0MDRjODdkMjZjZDRlZWI4ZTQ1YjFkMjQ2NGNlMDliIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XZWVrc3ZpbGxlLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjAzNzFjODA0NGFkNDM5MGEwM2E5Y2ZhNTE0M2ZlMzYuc2V0Q29udGVudChodG1sXzE0MDRjODdkMjZjZDRlZWI4ZTQ1YjFkMjQ2NGNlMDliKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2UwYmE5NmE3OGExMzQxYzg5YTYwNzUxNTMyZjhjZTM0LmJpbmRQb3B1cChwb3B1cF8yMDM3MWM4MDQ0YWQ0MzkwYTAzYTljZmE1MTQzZmUzNik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hYzUxODIwZjVmYjI0NDk0OTZiY2ZmZTZmNjlmOGNlYyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY3Nzg2MTA0NzY5NTMxLC03My45MDMzMTY4NDg1MjU5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83MzMyY2I0YmI1Y2Q0YmU5YjczOTIwM2JjM2VhMjM2MiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85N2NhZjg4YTA4OTU0Zjg1YWIzZWRlYTQzNzAyZjY4YSA9ICQoJzxkaXYgaWQ9Imh0bWxfOTdjYWY4OGEwODk1NGY4NWFiM2VkZWE0MzcwMmY2OGEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJyb2Fkd2F5IEp1bmN0aW9uLCBCcm9va2x5bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNzMzMmNiNGJiNWNkNGJlOWI3MzkyMDNiYzNlYTIzNjIuc2V0Q29udGVudChodG1sXzk3Y2FmODhhMDg5NTRmODVhYjNlZGVhNDM3MDJmNjhhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2FjNTE4MjBmNWZiMjQ0OTQ5NmJjZmZlNmY2OWY4Y2VjLmJpbmRQb3B1cChwb3B1cF83MzMyY2I0YmI1Y2Q0YmU5YjczOTIwM2JjM2VhMjM2Mik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jZGJlODJiNWUxZjA0YTM4OGQ2NGZhYTUzMmU0YjBiMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjcwMzE3NjMyODIyNjkyLC03My45ODg3NTI4MDc0NTA0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2UxZDY2NjFjOTllMTQ5NGM5ZDk3NDIzN2ZiZjZiMjlmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzBlYWMzZjM4MjNkMTQ0NWY4YmMxOWE3YTk5YWEwZThlID0gJCgnPGRpdiBpZD0iaHRtbF8wZWFjM2YzODIzZDE0NDVmOGJjMTlhN2E5OWFhMGU4ZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RHVtYm8sIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lMWQ2NjYxYzk5ZTE0OTRjOWQ5NzQyMzdmYmY2YjI5Zi5zZXRDb250ZW50KGh0bWxfMGVhYzNmMzgyM2QxNDQ1ZjhiYzE5YTdhOTlhYTBlOGUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfY2RiZTgyYjVlMWYwNGEzODhkNjRmYWE1MzJlNGIwYjIuYmluZFBvcHVwKHBvcHVwX2UxZDY2NjFjOTllMTQ5NGM5ZDk3NDIzN2ZiZjZiMjlmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzU5NTFiMmRlNzhmODQ5YTdiYzgzNWU4NWY1ZDM4MmU5ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjAxODA5NTc2MzE0NDQsLTc0LjEyMDU5Mzk5NzE4MDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzEzM2M1NWRlZWU3MzRmZDFhYzE2ZWI2NmVmMWVhYjNhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzcwYTE2ODI0ZGYxMjQ0ZTliOTcwMDhjNTU1NzcyMWVlID0gJCgnPGRpdiBpZD0iaHRtbF83MGExNjgyNGRmMTI0NGU5Yjk3MDA4YzU1NTc3MjFlZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TWFub3IgSGVpZ2h0cywgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMTMzYzU1ZGVlZTczNGZkMWFjMTZlYjY2ZWYxZWFiM2Euc2V0Q29udGVudChodG1sXzcwYTE2ODI0ZGYxMjQ0ZTliOTcwMDhjNTU1NzcyMWVlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU5NTFiMmRlNzhmODQ5YTdiYzgzNWU4NWY1ZDM4MmU5LmJpbmRQb3B1cChwb3B1cF8xMzNjNTVkZWVlNzM0ZmQxYWMxNmViNjZlZjFlYWIzYSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mODQ1YzAxMzI4YTM0ZDI0YWI2N2JjZmExNThkM2VkMyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjYwMzcwNjkyNjI3MzcxLC03NC4xMzIwODQ0NzQ4NDI5OF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mZDUxZjMwOWE0NmU0ZWFhODQzYjY5YjBkZTZmMWY3MiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85MmRkMmYwZWVlNWQ0ZWVkOGM0YTJlMTZmODdkZTgwZiA9ICQoJzxkaXYgaWQ9Imh0bWxfOTJkZDJmMGVlZTVkNGVlZDhjNGEyZTE2Zjg3ZGU4MGYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldpbGxvd2Jyb29rLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mZDUxZjMwOWE0NmU0ZWFhODQzYjY5YjBkZTZmMWY3Mi5zZXRDb250ZW50KGh0bWxfOTJkZDJmMGVlZTVkNGVlZDhjNGEyZTE2Zjg3ZGU4MGYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjg0NWMwMTMyOGEzNGQyNGFiNjdiY2ZhMTU4ZDNlZDMuYmluZFBvcHVwKHBvcHVwX2ZkNTFmMzA5YTQ2ZTRlYWE4NDNiNjliMGRlNmYxZjcyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2U4Mzc3MGM5ZTFiZTQ1MjJiNmFlNmMxODRkODRkMDA5ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTQxMTM5OTIyMDkxNzY2LC03NC4yMTc3NjYzNjA2ODU2N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mYThjOTY4YTQ2Njk0MmY3ODZjNTFjYWE0NGVmZjY5MSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9kNzJiYzRjOTVlMjA0Nzc2YTBkNjc5YjQ1NjNiMGMyNSA9ICQoJzxkaXYgaWQ9Imh0bWxfZDcyYmM0Yzk1ZTIwNDc3NmEwZDY3OWI0NTYzYjBjMjUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlNhbmR5IEdyb3VuZCwgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZmE4Yzk2OGE0NjY5NDJmNzg2YzUxY2FhNDRlZmY2OTEuc2V0Q29udGVudChodG1sX2Q3MmJjNGM5NWUyMDQ3NzZhMGQ2NzliNDU2M2IwYzI1KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2U4Mzc3MGM5ZTFiZTQ1MjJiNmFlNmMxODRkODRkMDA5LmJpbmRQb3B1cChwb3B1cF9mYThjOTY4YTQ2Njk0MmY3ODZjNTFjYWE0NGVmZjY5MSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lODlkZjMzNGM0ZmM0MzFjODU4MThjMDYyNWZmY2NhYyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjU3OTExODc0Mjk2MTIxNCwtNzQuMTI3MjcyNDA2MDQ5NDZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYmZiYjhkZGMyZGZiNGRkNThlNGIxNmZiMWNjMTYyMzEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNjY5YTEzODQwMjc0NGUxZWJlNjZiNzEzNTdjMzMxNGUgPSAkKCc8ZGl2IGlkPSJodG1sXzY2OWExMzg0MDI3NDRlMWViZTY2YjcxMzU3YzMzMTRlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FZ2JlcnR2aWxsZSwgU3RhdGVuIElzbGFuZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYmZiYjhkZGMyZGZiNGRkNThlNGIxNmZiMWNjMTYyMzEuc2V0Q29udGVudChodG1sXzY2OWExMzg0MDI3NDRlMWViZTY2YjcxMzU3YzMzMTRlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2U4OWRmMzM0YzRmYzQzMWM4NTgxOGMwNjI1ZmZjY2FjLmJpbmRQb3B1cChwb3B1cF9iZmJiOGRkYzJkZmI0ZGQ1OGU0YjE2ZmIxY2MxNjIzMSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81MTJmNjk1NzBlMTE0NGI4YWRiM2ViZDA4MGJlNjBmNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjU2NzM3NTg4OTU3MDMyLC03My44OTIxMzc2MDIzMjgyMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iYjVjOTBmNGJhN2M0NmNjOWJjZGJkMzA5YTliNDNkNiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81NjAyMWRhNGQyZWQ0NDcyOWIzYWQxMDU0MTE1YTM4NiA9ICQoJzxkaXYgaWQ9Imh0bWxfNTYwMjFkYTRkMmVkNDQ3MjliM2FkMTA1NDExNWEzODYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJveGJ1cnksIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYmI1YzkwZjRiYTdjNDZjYzliY2RiZDMwOWE5YjQzZDYuc2V0Q29udGVudChodG1sXzU2MDIxZGE0ZDJlZDQ0NzI5YjNhZDEwNTQxMTVhMzg2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzUxMmY2OTU3MGUxMTQ0YjhhZGIzZWJkMDgwYmU2MGY1LmJpbmRQb3B1cChwb3B1cF9iYjVjOTBmNGJhN2M0NmNjOWJjZGJkMzA5YTliNDNkNik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yZGEyZmEwODI4OWQ0YzUwYWU1OGJjM2FmYmUzODNjMSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjU5ODUyNTA5NTEzNzI1NSwtNzMuOTU5MTg0NTk0Mjg3MDJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYjZkZjIyMWVlYWU3NDlmNGFiMTU1MWUzNWQ4N2U1ZjkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDAwZWU2ZDQ5NGYyNGVhYzgxNDNkZmNlYTczNTdkMGEgPSAkKCc8ZGl2IGlkPSJodG1sX2QwMGVlNmQ0OTRmMjRlYWM4MTQzZGZjZWE3MzU3ZDBhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ib21lY3Jlc3QsIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iNmRmMjIxZWVhZTc0OWY0YWIxNTUxZTM1ZDg3ZTVmOS5zZXRDb250ZW50KGh0bWxfZDAwZWU2ZDQ5NGYyNGVhYzgxNDNkZmNlYTczNTdkMGEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMmRhMmZhMDgyODlkNGM1MGFlNThiYzNhZmJlMzgzYzEuYmluZFBvcHVwKHBvcHVwX2I2ZGYyMjFlZWFlNzQ5ZjRhYjE1NTFlMzVkODdlNWY5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2FhZTk3OTA5NTE2YzQzZmU4ZGUyMzFiNTFkN2FiYmQwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzE2NDE0NTExMTU4MTg1LC03My44ODExNDMxOTIwMDYwNF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yYzBhNGJhMjIwZjM0M2EzODMwZjdkMmU2YWU3MGY4OCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jN2Q3MWY0NDM3OWQ0ZmZkYjE2ZjMwOWZhZjEwOGE5YiA9ICQoJzxkaXYgaWQ9Imh0bWxfYzdkNzFmNDQzNzlkNGZmZGIxNmYzMDlmYWYxMDhhOWIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1pZGRsZSBWaWxsYWdlLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzJjMGE0YmEyMjBmMzQzYTM4MzBmN2QyZTZhZTcwZjg4LnNldENvbnRlbnQoaHRtbF9jN2Q3MWY0NDM3OWQ0ZmZkYjE2ZjMwOWZhZjEwOGE5Yik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hYWU5NzkwOTUxNmM0M2ZlOGRlMjMxYjUxZDdhYmJkMC5iaW5kUG9wdXAocG9wdXBfMmMwYTRiYTIyMGYzNDNhMzgzMGY3ZDJlNmFlNzBmODgpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODMwMGRmMDkzOWU0NDIxMzlkNWM0ZWIxNTc1ZTE4OGQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC41MjYyNjQwNjczNDgxMiwtNzQuMjAxNTI1NTY0NTc2NThdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzgwYTA5ODYyMmVkNGE5ZWE0MjkzNjM4NmFkZWYyODkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYzJiZjMyMmNjNTg4NDQ3MjhjMDExMTkxMDU0YTkzNGEgPSAkKCc8ZGl2IGlkPSJodG1sX2MyYmYzMjJjYzU4ODQ0NzI4YzAxMTE5MTA1NGE5MzRhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5QcmluY2UmIzM5O3MgQmF5LCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jODBhMDk4NjIyZWQ0YTllYTQyOTM2Mzg2YWRlZjI4OS5zZXRDb250ZW50KGh0bWxfYzJiZjMyMmNjNTg4NDQ3MjhjMDExMTkxMDU0YTkzNGEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODMwMGRmMDkzOWU0NDIxMzlkNWM0ZWIxNTc1ZTE4OGQuYmluZFBvcHVwKHBvcHVwX2M4MGEwOTg2MjJlZDRhOWVhNDI5MzYzODZhZGVmMjg5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I0ZTJmYjZiMDM4YTQzMGJhMWJiZjkzODI4MjJiN2M4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTc2NTA2MjkzNzk0ODksLTc0LjEzNzkyNjYzNzcxNTY4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzUxYWI0ZTIzYjI5ZTQzM2RhYjY2YWQzOTVkNzY1MTgwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2I2YjQ5N2JhNzNiNzQ5NTJhMGE1ZjdjOGZkYWE4OWQyID0gJCgnPGRpdiBpZD0iaHRtbF9iNmI0OTdiYTczYjc0OTUyYTBhNWY3YzhmZGFhODlkMiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TGlnaHRob3VzZSBIaWxsLCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81MWFiNGUyM2IyOWU0MzNkYWI2NmFkMzk1ZDc2NTE4MC5zZXRDb250ZW50KGh0bWxfYjZiNDk3YmE3M2I3NDk1MmEwYTVmN2M4ZmRhYTg5ZDIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjRlMmZiNmIwMzhhNDMwYmExYmJmOTM4MjgyMmI3YzguYmluZFBvcHVwKHBvcHVwXzUxYWI0ZTIzYjI5ZTQzM2RhYjY2YWQzOTVkNzY1MTgwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzI5YmM3ZjBiMDRlZjQ0MzhhNzBlZTQxZjdkMmVhNzU0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNTE5NTQxNDU3NDg5MDksLTc0LjIyOTU3MDgwNjI2OTQxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzgzOWNiYmYxMGNjYTQ0MjA5MTU4YWY5NTdiNWNiMGIwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzI1NjJmNjExYjViMzQ5Mjc4YjgzMmVkNTA3NGI4NjcxID0gJCgnPGRpdiBpZD0iaHRtbF8yNTYyZjYxMWI1YjM0OTI3OGI4MzJlZDUwNzRiODY3MSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UmljaG1vbmQgVmFsbGV5LCBTdGF0ZW4gSXNsYW5kPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84MzljYmJmMTBjY2E0NDIwOTE1OGFmOTU3YjVjYjBiMC5zZXRDb250ZW50KGh0bWxfMjU2MmY2MTFiNWIzNDkyNzhiODMyZWQ1MDc0Yjg2NzEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjliYzdmMGIwNGVmNDQzOGE3MGVlNDFmN2QyZWE3NTQuYmluZFBvcHVwKHBvcHVwXzgzOWNiYmYxMGNjYTQ0MjA5MTU4YWY5NTdiNWNiMGIwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzE3ZmZlZTI5M2M4NTRlNzI5M2VkYTdmMjdjMTEzMjAzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzkwNjAxNTU2NzAxNDgsLTczLjgyNjY3NzU3MTM4NjQxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzM4NDFhZDRkMDA5MTQxYzU5NmI0ZWRlNjA4NDY1Yzk4ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzJjY2Y2YTE4OTA1NzRlNGM5OWVhYWQ0NjRjMGE4N2I5ID0gJCgnPGRpdiBpZD0iaHRtbF8yY2NmNmExODkwNTc0ZTRjOTllYWFkNDY0YzBhODdiOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TWFsYmEsIFF1ZWVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzg0MWFkNGQwMDkxNDFjNTk2YjRlZGU2MDg0NjVjOTguc2V0Q29udGVudChodG1sXzJjY2Y2YTE4OTA1NzRlNGM5OWVhYWQ0NjRjMGE4N2I5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzE3ZmZlZTI5M2M4NTRlNzI5M2VkYTdmMjdjMTEzMjAzLmJpbmRQb3B1cChwb3B1cF8zODQxYWQ0ZDAwOTE0MWM1OTZiNGVkZTYwODQ2NWM5OCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zYjRiOGU1ODVmYmQ0Yzc3OGJlYjZmMWUzZDQ2NmJmNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY4MTk5ODkzNDUxNzMsLTczLjg5MDM0NTcwOTg3Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81N2ZhNWQ1ZWE3Y2E0YjdhYmZkNmYwYjMzYWIzMmU5YiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iN2JiOWYzZTAzMTk0NThjODJiZjFiMDZlNDQzNjQ4MCA9ICQoJzxkaXYgaWQ9Imh0bWxfYjdiYjlmM2UwMzE5NDU4YzgyYmYxYjA2ZTQ0MzY0ODAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhpZ2hsYW5kIFBhcmssIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81N2ZhNWQ1ZWE3Y2E0YjdhYmZkNmYwYjMzYWIzMmU5Yi5zZXRDb250ZW50KGh0bWxfYjdiYjlmM2UwMzE5NDU4YzgyYmYxYjA2ZTQ0MzY0ODApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfM2I0YjhlNTg1ZmJkNGM3NzhiZWI2ZjFlM2Q0NjZiZjUuYmluZFBvcHVwKHBvcHVwXzU3ZmE1ZDVlYTdjYTRiN2FiZmQ2ZjBiMzNhYjMyZTliKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzdlOGJiNWE2MDc2MDRjY2JiYzJhOTNlMzEwYWI0ODA0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjA5Mzc3NzAxMTM3NjYsLTczLjk0ODQxNTE1MzI4ODkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzRkYjFkNTczNzY3OTQ3ZTdhMjJkYzhiZWU5ZmJmZjlhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzY2YTBkNmQxZGMzMzQ4NThhN2ZjNWI4ZmQ3YTA2ZDJkID0gJCgnPGRpdiBpZD0iaHRtbF82NmEwZDZkMWRjMzM0ODU4YTdmYzViOGZkN2EwNmQyZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TWFkaXNvbiwgQnJvb2tseW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzRkYjFkNTczNzY3OTQ3ZTdhMjJkYzhiZWU5ZmJmZjlhLnNldENvbnRlbnQoaHRtbF82NmEwZDZkMWRjMzM0ODU4YTdmYzViOGZkN2EwNmQyZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83ZThiYjVhNjA3NjA0Y2NiYmMyYTkzZTMxMGFiNDgwNC5iaW5kUG9wdXAocG9wdXBfNGRiMWQ1NzM3Njc5NDdlN2EyMmRjOGJlZTlmYmZmOWEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODY4NjhlOGUyNjM3NDdhYTg5ZjZmODg5ZGQyNDdjY2YgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC44NTI3MjI5NzYzMzAxNywtNzMuODYxNzI1Nzc1NTUxMTVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYjZhZTIyNmIxZDRjNGZlZTkwNTIzOTIxMTBiODBlZmQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDRiYWU0YjQ3M2Q1NDgxZTlmMzg2ZmNmNDU2NjEwNzUgPSAkKCc8ZGl2IGlkPSJodG1sX2Q0YmFlNGI0NzNkNTQ4MWU5ZjM4NmZjZjQ1NjYxMDc1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ccm9ueGRhbGUsIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iNmFlMjI2YjFkNGM0ZmVlOTA1MjM5MjExMGI4MGVmZC5zZXRDb250ZW50KGh0bWxfZDRiYWU0YjQ3M2Q1NDgxZTlmMzg2ZmNmNDU2NjEwNzUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODY4NjhlOGUyNjM3NDdhYTg5ZjZmODg5ZGQyNDdjY2YuYmluZFBvcHVwKHBvcHVwX2I2YWUyMjZiMWQ0YzRmZWU5MDUyMzkyMTEwYjgwZWZkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzI2YThhYzZhMjM3MzRmOGNhZGE2YjBlNmRlMzg2NzE0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODY1Nzg3ODc4MDI5ODIsLTczLjg1OTMxODYzMjIxNjQ3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzRiZGQ2ZDkzYjYzMjRmZmRhNGNkZGNiYThhZmFmMWIwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzZlMzU5MjgyNjgzZTQzNzk4YzY5M2U5MWM4ZTlkZTJmID0gJCgnPGRpdiBpZD0iaHRtbF82ZTM1OTI4MjY4M2U0Mzc5OGM2OTNlOTFjOGU5ZGUyZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QWxsZXJ0b24sIEJyb254PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80YmRkNmQ5M2I2MzI0ZmZkYTRjZGRjYmE4YWZhZjFiMC5zZXRDb250ZW50KGh0bWxfNmUzNTkyODI2ODNlNDM3OThjNjkzZTkxYzhlOWRlMmYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjZhOGFjNmEyMzczNGY4Y2FkYTZiMGU2ZGUzODY3MTQuYmluZFBvcHVwKHBvcHVwXzRiZGQ2ZDkzYjYzMjRmZmRhNGNkZGNiYThhZmFmMWIwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzZkMGI1ZDhkYjE4NDRlZWZiYzUyOGQyZTVlMzlmOGMwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuODcwMzkyMzkxNDE0NywtNzMuOTAxNTIyNjQ1MTMxNDRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzhlYzQwZTA2YTgyNDNlYmI3NDE3OTBlMzY0ZjEyMDkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzI1NTcwYmI3MGVmNGY3ZmEyYjFkNGI2MGEyNTMyNmEgPSAkKCc8ZGl2IGlkPSJodG1sXzcyNTU3MGJiNzBlZjRmN2ZhMmIxZDRiNjBhMjUzMjZhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5LaW5nc2JyaWRnZSBIZWlnaHRzLCBCcm9ueDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYzhlYzQwZTA2YTgyNDNlYmI3NDE3OTBlMzY0ZjEyMDkuc2V0Q29udGVudChodG1sXzcyNTU3MGJiNzBlZjRmN2ZhMmIxZDRiNjBhMjUzMjZhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzZkMGI1ZDhkYjE4NDRlZWZiYzUyOGQyZTVlMzlmOGMwLmJpbmRQb3B1cChwb3B1cF9jOGVjNDBlMDZhODI0M2ViYjc0MTc5MGUzNjRmMTIwOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80YzJiNDJmNzE5OWU0YWVjYmU1ZDNmODgxNmY2ODE5YyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQwLjY0NjkyNjA2NjU4NTc5LC03My45NDgxNzcwOTkyMDE4NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yNDdjNDAzODQ0OTk0NTYxODI1YmMxZjU1YzAwNGEwYSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mMmJhOTc0MjAwYmQ0ZGQwYjE1Y2RjNDIwY2QyMzdjOCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85YjhiYjQxYzY4NDM0YjkzYjVkODc1MTU0NjRjNjAxZiA9ICQoJzxkaXYgaWQ9Imh0bWxfOWI4YmI0MWM2ODQzNGI5M2I1ZDg3NTE1NDY0YzYwMWYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkVyYXNtdXMsIEJyb29rbHluPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mMmJhOTc0MjAwYmQ0ZGQwYjE1Y2RjNDIwY2QyMzdjOC5zZXRDb250ZW50KGh0bWxfOWI4YmI0MWM2ODQzNGI5M2I1ZDg3NTE1NDY0YzYwMWYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNGMyYjQyZjcxOTllNGFlY2JlNWQzZjg4MTZmNjgxOWMuYmluZFBvcHVwKHBvcHVwX2YyYmE5NzQyMDBiZDRkZDBiMTVjZGM0MjBjZDIzN2M4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzA2MmVlNjU2YzRjZDQ0NWZhYzQ4MjVjZTVhNDk0OGVkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNzU2NjU4MDgyMjc1MTksLTc0LjAwMDExMTM2MjAyNjM3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzJhOGY1NGQ5YzU5OTRlMjQ4NDlkMWQ0ZmMwOGRhOWU3ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzNjOTU0ZTI3ODg3OTRjN2NhYTMzZWM0NDMxZjFkZmY0ID0gJCgnPGRpdiBpZD0iaHRtbF8zYzk1NGUyNzg4Nzk0YzdjYWEzM2VjNDQzMWYxZGZmNCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SHVkc29uIFlhcmRzLCBNYW5oYXR0YW48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzJhOGY1NGQ5YzU5OTRlMjQ4NDlkMWQ0ZmMwOGRhOWU3LnNldENvbnRlbnQoaHRtbF8zYzk1NGUyNzg4Nzk0YzdjYWEzM2VjNDQzMWYxZGZmNCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wNjJlZTY1NmM0Y2Q0NDVmYWM0ODI1Y2U1YTQ5NDhlZC5iaW5kUG9wdXAocG9wdXBfMmE4ZjU0ZDljNTk5NGUyNDg0OWQxZDRmYzA4ZGE5ZTcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjg0OTc3ZTZhMDRiNDBmZjlkNmQ0YzZlOTNkNzg2ZDAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC41ODczMzc3NDAxODc0MSwtNzMuODA1NTMwMDI5Njg3MThdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfN2ZmM2JmN2JmYWZlNDU5OGJjYjRkMTYwNjhkOWE0ODIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOTU2Nzk4YWZkODJkNDdjNWFjMmQxOTEyMDhlYmY3MDAgPSAkKCc8ZGl2IGlkPSJodG1sXzk1Njc5OGFmZDgyZDQ3YzVhYzJkMTkxMjA4ZWJmNzAwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IYW1tZWxzLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzdmZjNiZjdiZmFmZTQ1OThiY2I0ZDE2MDY4ZDlhNDgyLnNldENvbnRlbnQoaHRtbF85NTY3OThhZmQ4MmQ0N2M1YWMyZDE5MTIwOGViZjcwMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mODQ5NzdlNmEwNGI0MGZmOWQ2ZDRjNmU5M2Q3ODZkMC5iaW5kUG9wdXAocG9wdXBfN2ZmM2JmN2JmYWZlNDU5OGJjYjRkMTYwNjhkOWE0ODIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYWJhNTgzY2QyMDMzNGFkNWFlMmM4MTk1MjdhOTA0MTIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42MTEzMjE2OTEyODM4MzQsLTczLjc2NTk2NzgxNDQ1NjI3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2UzODQ1NmQ3ZWJkZDRkMGZiMDhjNjBhZDlkNTQ1ODM0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzI1ZGIzZGRhNDJmMTRjZTNiYmVkZjljNDZkODk3ZDJmID0gJCgnPGRpdiBpZD0iaHRtbF8yNWRiM2RkYTQyZjE0Y2UzYmJlZGY5YzQ2ZDg5N2QyZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmF5c3dhdGVyLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2UzODQ1NmQ3ZWJkZDRkMGZiMDhjNjBhZDlkNTQ1ODM0LnNldENvbnRlbnQoaHRtbF8yNWRiM2RkYTQyZjE0Y2UzYmJlZGY5YzQ2ZDg5N2QyZik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hYmE1ODNjZDIwMzM0YWQ1YWUyYzgxOTUyN2E5MDQxMi5iaW5kUG9wdXAocG9wdXBfZTM4NDU2ZDdlYmRkNGQwZmIwOGM2MGFkOWQ1NDU4MzQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTIyNjk0MzNhMWExNDRjZDk5M2ViYWVkNmUwN2Q5OTEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC43NTYwOTEyOTcwOTQ3MDYsLTczLjk0NTYzMDcwMzM0MDkxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzI0N2M0MDM4NDQ5OTQ1NjE4MjViYzFmNTVjMDA0YTBhKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzEzOThmYWI2MDc5NzQyMTNiMWQ4NWQ5ZGZjMmI4YjliID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2VhYTJhYzM1YmY4OTQwOWM5MzMzMjJjMTljYWEwNTY5ID0gJCgnPGRpdiBpZD0iaHRtbF9lYWEyYWMzNWJmODk0MDljOTMzMzIyYzE5Y2FhMDU2OSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UXVlZW5zYnJpZGdlLCBRdWVlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzEzOThmYWI2MDc5NzQyMTNiMWQ4NWQ5ZGZjMmI4YjliLnNldENvbnRlbnQoaHRtbF9lYWEyYWMzNWJmODk0MDljOTMzMzIyYzE5Y2FhMDU2OSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl81MjI2OTQzM2ExYTE0NGNkOTkzZWJhZWQ2ZTA3ZDk5MS5iaW5kUG9wdXAocG9wdXBfMTM5OGZhYjYwNzk3NDIxM2IxZDg1ZDlkZmMyYjhiOWIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNjdiOGUxN2RiZTU3NDcxYmJkM2Y3MGIzNzBjYzU5NjcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0MC42MTczMTA3OTI1Mjk4MywtNzQuMDgxNzM5OTIyMTE5NjJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjQ3YzQwMzg0NDk5NDU2MTgyNWJjMWY1NWMwMDRhMGEpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMjg4ZTQ4YzRlOGQ0NGM0MGJlOWNiMTQ2MjRlYTJkNDMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOTE4ZjMyNjhjNjA0NDY4NWI3NzY0NTNmNDViZGNlZTEgPSAkKCc8ZGl2IGlkPSJodG1sXzkxOGYzMjY4YzYwNDQ2ODViNzc2NDUzZjQ1YmRjZWUxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Gb3ggSGlsbHMsIFN0YXRlbiBJc2xhbmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzI4OGU0OGM0ZThkNDRjNDBiZTljYjE0NjI0ZWEyZDQzLnNldENvbnRlbnQoaHRtbF85MThmMzI2OGM2MDQ0Njg1Yjc3NjQ1M2Y0NWJkY2VlMSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82N2I4ZTE3ZGJlNTc0NzFiYmQzZjcwYjM3MGNjNTk2Ny5iaW5kUG9wdXAocG9wdXBfMjg4ZTQ4YzRlOGQ0NGM0MGJlOWNiMTQ2MjRlYTJkNDMpOwoKICAgICAgICAgICAgCiAgICAgICAgCjwvc2NyaXB0Pg== onload=\"this.contentDocument.open();this.contentDocument.write(atob(this.getAttribute('data-html')));this.contentDocument.close();\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
],
"text/plain": [
"<folium.folium.Map at 0x7fea38af90b8>"
]
},
"execution_count": 317,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Create a map of New York with neighborhoods superimposed on top.\n",
"# create map of New York using latitude and longitude values\n",
"map_newyork = folium.Map(location=[latitude, longitude], zoom_start=10)\n",
"\n",
"# add markers to map\n",
"for lat, lng, borough, neighborhood in zip(neighborhoods_NY['Latitude'], neighborhoods_NY['Longitude'], neighborhoods_NY['Borough'], neighborhoods_NY['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_newyork) \n",
" \n",
"map_newyork"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# **Folium** is a great visualization library.\n",
"# Feel free to zoom into the above map, and click on each circle mark\n",
"# to reveal the name of the neighborhood and its respective borough."
]
},
{
"cell_type": "code",
"execution_count": 318,
"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>Borough</th>\n",
" <th>Neighborhood</th>\n",
" <th>Latitude</th>\n",
" <th>Longitude</th>\n",
" <th>city</th>\n",
" <th>Postalcode</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Bronx</td>\n",
" <td>Wakefield</td>\n",
" <td>40.894705</td>\n",
" <td>-73.847201</td>\n",
" <td>NY</td>\n",
" <td>NY</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Bronx</td>\n",
" <td>Co-op City</td>\n",
" <td>40.874294</td>\n",
" <td>-73.829939</td>\n",
" <td>NY</td>\n",
" <td>NY</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Bronx</td>\n",
" <td>Eastchester</td>\n",
" <td>40.887556</td>\n",
" <td>-73.827806</td>\n",
" <td>NY</td>\n",
" <td>NY</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Bronx</td>\n",
" <td>Fieldston</td>\n",
" <td>40.895437</td>\n",
" <td>-73.905643</td>\n",
" <td>NY</td>\n",
" <td>NY</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Bronx</td>\n",
" <td>Riverdale</td>\n",
" <td>40.890834</td>\n",
" <td>-73.912585</td>\n",
" <td>NY</td>\n",
" <td>NY</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Borough Neighborhood Latitude Longitude city Postalcode\n",
"0 Bronx Wakefield 40.894705 -73.847201 NY NY\n",
"1 Bronx Co-op City 40.874294 -73.829939 NY NY\n",
"2 Bronx Eastchester 40.887556 -73.827806 NY NY\n",
"3 Bronx Fieldston 40.895437 -73.905643 NY NY\n",
"4 Bronx Riverdale 40.890834 -73.912585 NY NY"
]
},
"execution_count": 318,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# We will merge both dataframes, NY and TO, so let's include the city on them\n",
"neighborhoods_NY[\"city\"] = \"NY\"\n",
"neighborhoods_NY[\"Postalcode\"] = \"NY\"\n",
"neighborhoods_NY.head()"
]
},
{
"cell_type": "code",
"execution_count": 319,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/jupyterlab/conda/envs/python/lib/python3.6/site-packages/ipykernel_launcher.py:1: SettingWithCopyWarning: \n",
"A value is trying to be set on a copy of a slice from a DataFrame.\n",
"Try using .loc[row_indexer,col_indexer] = value instead\n",
"\n",
"See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
" \"\"\"Entry point for launching an IPython kernel.\n"
]
},
{
"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>city</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>M3A</td>\n",
" <td>North York</td>\n",
" <td>Parkwoods</td>\n",
" <td>43.753259</td>\n",
" <td>-79.329656</td>\n",
" <td>TO</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>M4A</td>\n",
" <td>North York</td>\n",
" <td>Victoria Village</td>\n",
" <td>43.725882</td>\n",
" <td>-79.315572</td>\n",
" <td>TO</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>M5A</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Regent Park / Harbourfront</td>\n",
" <td>43.654260</td>\n",
" <td>-79.360636</td>\n",
" <td>TO</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>M6A</td>\n",
" <td>North York</td>\n",
" <td>Lawrence Manor / Lawrence Heights</td>\n",
" <td>43.718518</td>\n",
" <td>-79.464763</td>\n",
" <td>TO</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>M7A</td>\n",
" <td>Downtown Toronto</td>\n",
" <td>Queen's Park / Ontario Provincial Government</td>\n",
" <td>43.662301</td>\n",
" <td>-79.389494</td>\n",
" <td>TO</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Postalcode Borough Neighborhood \\\n",
"0 M3A North York Parkwoods \n",
"1 M4A North York Victoria Village \n",
"2 M5A Downtown Toronto Regent Park / Harbourfront \n",
"3 M6A North York Lawrence Manor / Lawrence Heights \n",
"4 M7A Downtown Toronto Queen's Park / Ontario Provincial Government \n",
"\n",
" Latitude Longitude city \n",
"0 43.753259 -79.329656 TO \n",
"1 43.725882 -79.315572 TO \n",
"2 43.654260 -79.360636 TO \n",
"3 43.718518 -79.464763 TO \n",
"4 43.662301 -79.389494 TO "
]
},
"execution_count": 319,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Toronto_Neighb[\"city\"] = \"TO\"\n",
"Toronto_Neighb.head()"
]
},
{
"cell_type": "code",
"execution_count": 320,
"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>Borough</th>\n",
" <th>Neighborhood</th>\n",
" <th>Latitude</th>\n",
" <th>Longitude</th>\n",
" <th>city</th>\n",
" <th>Postalcode</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Bronx</td>\n",
" <td>Wakefield</td>\n",
" <td>40.894705</td>\n",
" <td>-73.847201</td>\n",
" <td>NY</td>\n",
" <td>NY</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Bronx</td>\n",
" <td>Co-op City</td>\n",
" <td>40.874294</td>\n",
" <td>-73.829939</td>\n",
" <td>NY</td>\n",
" <td>NY</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Bronx</td>\n",
" <td>Eastchester</td>\n",
" <td>40.887556</td>\n",
" <td>-73.827806</td>\n",
" <td>NY</td>\n",
" <td>NY</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Bronx</td>\n",
" <td>Fieldston</td>\n",
" <td>40.895437</td>\n",
" <td>-73.905643</td>\n",
" <td>NY</td>\n",
" <td>NY</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Bronx</td>\n",
" <td>Riverdale</td>\n",
" <td>40.890834</td>\n",
" <td>-73.912585</td>\n",
" <td>NY</td>\n",
" <td>NY</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Borough Neighborhood Latitude Longitude city Postalcode\n",
"0 Bronx Wakefield 40.894705 -73.847201 NY NY\n",
"1 Bronx Co-op City 40.874294 -73.829939 NY NY\n",
"2 Bronx Eastchester 40.887556 -73.827806 NY NY\n",
"3 Bronx Fieldston 40.895437 -73.905643 NY NY\n",
"4 Bronx Riverdale 40.890834 -73.912585 NY NY"
]
},
"execution_count": 320,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Finally, we concatenate to one single Dataframe\n",
"neighb_NY_TO = pd.concat([neighborhoods_NY,Toronto_Neighb])\n",
"neighb_NY_TO.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Now here the user process starts!"
]
},
{
"cell_type": "code",
"execution_count": 322,
"metadata": {},
"outputs": [],
"source": [
"# Creating a Picklist with NY Neighborhoods:\n",
"dropdown_Neighb = widgets.Dropdown(options = neighborhoods_NY.Neighborhood.sort_values(ascending=True),\n",
" value = \"Allerton\",description='Neighborhood:',disabled=False,)"
]
},
{
"cell_type": "code",
"execution_count": 323,
"metadata": {},
"outputs": [],
"source": [
"from ipywidgets import interact, interactive, fixed, interact_manual\n",
"\n",
"caption = widgets.Label(value=' ')\n",
"\n",
"caption.value = ' '\n",
"def dropdown_Neighb_eventhandler(change):\n",
" caption.value = change.new\n"
]
},
{
"cell_type": "code",
"execution_count": 324,
"metadata": {},
"outputs": [],
"source": [
"dropdown_Neighb.observe(dropdown_Neighb_eventhandler, names='value') "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Select your NY neighborhood on the list below, so later the system will find similar Neighborhoods in Toronto:"
]
},
{
"cell_type": "code",
"execution_count": 326,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "ea978721274b45e4b07dd38e2cbff218",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Dropdown(description='Neighborhood:', options=('Allerton', 'Annadale', 'Arden Heights', 'Arlington', 'Arrochar…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"display(dropdown_Neighb)"
]
},
{
"cell_type": "code",
"execution_count": 327,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The value selected is: Broad Channel\n"
]
}
],
"source": [
"print(\"The value selected is: \"+caption.value)"
]
},
{
"cell_type": "code",
"execution_count": 330,
"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>Borough</th>\n",
" <th>Neighborhood</th>\n",
" <th>Latitude</th>\n",
" <th>Longitude</th>\n",
" <th>city</th>\n",
" <th>Postalcode</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>171</th>\n",
" <td>Queens</td>\n",
" <td>Broad Channel</td>\n",
" <td>40.603027</td>\n",
" <td>-73.820055</td>\n",
" <td>NY</td>\n",
" <td>NY</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>North York</td>\n",
" <td>Parkwoods</td>\n",
" <td>43.753259</td>\n",
" <td>-79.329656</td>\n",
" <td>TO</td>\n",
" <td>M3A</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>North York</td>\n",
" <td>Victoria Village</td>\n",
" <td>43.725882</td>\n",
" <td>-79.315572</td>\n",
" <td>TO</td>\n",
" <td>M4A</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Regent Park / Harbourfront</td>\n",
" <td>43.654260</td>\n",
" <td>-79.360636</td>\n",
" <td>TO</td>\n",
" <td>M5A</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>North York</td>\n",
" <td>Lawrence Manor / Lawrence Heights</td>\n",
" <td>43.718518</td>\n",
" <td>-79.464763</td>\n",
" <td>TO</td>\n",
" <td>M6A</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Queen's Park / Ontario Provincial Government</td>\n",
" <td>43.662301</td>\n",
" <td>-79.389494</td>\n",
" <td>TO</td>\n",
" <td>M7A</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>Etobicoke</td>\n",
" <td>Islington Avenue</td>\n",
" <td>43.667856</td>\n",
" <td>-79.532242</td>\n",
" <td>TO</td>\n",
" <td>M9A</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>Scarborough</td>\n",
" <td>Malvern / Rouge</td>\n",
" <td>43.806686</td>\n",
" <td>-79.194353</td>\n",
" <td>TO</td>\n",
" <td>M1B</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>North York</td>\n",
" <td>Don Mills</td>\n",
" <td>43.745906</td>\n",
" <td>-79.352188</td>\n",
" <td>TO</td>\n",
" <td>M3B</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>East York</td>\n",
" <td>Parkview Hill / Woodbine Gardens</td>\n",
" <td>43.706397</td>\n",
" <td>-79.309937</td>\n",
" <td>TO</td>\n",
" <td>M4B</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Garden District-Ryerson</td>\n",
" <td>43.657162</td>\n",
" <td>-79.378937</td>\n",
" <td>TO</td>\n",
" <td>M5B</td>\n",
" </tr>\n",
" <tr>\n",
" <th>10</th>\n",
" <td>North York</td>\n",
" <td>Glencairn</td>\n",
" <td>43.709577</td>\n",
" <td>-79.445073</td>\n",
" <td>TO</td>\n",
" <td>M6B</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11</th>\n",
" <td>Etobicoke</td>\n",
" <td>West Deane Park / Princess Gardens / Martin Gr...</td>\n",
" <td>43.650943</td>\n",
" <td>-79.554724</td>\n",
" <td>TO</td>\n",
" <td>M9B</td>\n",
" </tr>\n",
" <tr>\n",
" <th>12</th>\n",
" <td>Scarborough</td>\n",
" <td>Rouge Hill / Port Union / Highland Creek</td>\n",
" <td>43.784535</td>\n",
" <td>-79.160497</td>\n",
" <td>TO</td>\n",
" <td>M1C</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13</th>\n",
" <td>North York</td>\n",
" <td>Don Mills</td>\n",
" <td>43.725900</td>\n",
" <td>-79.340923</td>\n",
" <td>TO</td>\n",
" <td>M3C</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14</th>\n",
" <td>East York</td>\n",
" <td>Woodbine Heights</td>\n",
" <td>43.695344</td>\n",
" <td>-79.318389</td>\n",
" <td>TO</td>\n",
" <td>M4C</td>\n",
" </tr>\n",
" <tr>\n",
" <th>15</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>St. James Town</td>\n",
" <td>43.651494</td>\n",
" <td>-79.375418</td>\n",
" <td>TO</td>\n",
" <td>M5C</td>\n",
" </tr>\n",
" <tr>\n",
" <th>16</th>\n",
" <td>York</td>\n",
" <td>Humewood-Cedarvale</td>\n",
" <td>43.693781</td>\n",
" <td>-79.428191</td>\n",
" <td>TO</td>\n",
" <td>M6C</td>\n",
" </tr>\n",
" <tr>\n",
" <th>17</th>\n",
" <td>Etobicoke</td>\n",
" <td>Eringate / Bloordale Gardens / Old Burnhamthor...</td>\n",
" <td>43.643515</td>\n",
" <td>-79.577201</td>\n",
" <td>TO</td>\n",
" <td>M9C</td>\n",
" </tr>\n",
" <tr>\n",
" <th>18</th>\n",
" <td>Scarborough</td>\n",
" <td>Guildwood / Morningside / West Hill</td>\n",
" <td>43.763573</td>\n",
" <td>-79.188711</td>\n",
" <td>TO</td>\n",
" <td>M1E</td>\n",
" </tr>\n",
" <tr>\n",
" <th>19</th>\n",
" <td>East Toronto</td>\n",
" <td>The Beaches</td>\n",
" <td>43.676357</td>\n",
" <td>-79.293031</td>\n",
" <td>TO</td>\n",
" <td>M4E</td>\n",
" </tr>\n",
" <tr>\n",
" <th>20</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Berczy Park</td>\n",
" <td>43.644771</td>\n",
" <td>-79.373306</td>\n",
" <td>TO</td>\n",
" <td>M5E</td>\n",
" </tr>\n",
" <tr>\n",
" <th>21</th>\n",
" <td>York</td>\n",
" <td>Caledonia-Fairbanks</td>\n",
" <td>43.689026</td>\n",
" <td>-79.453512</td>\n",
" <td>TO</td>\n",
" <td>M6E</td>\n",
" </tr>\n",
" <tr>\n",
" <th>22</th>\n",
" <td>Scarborough</td>\n",
" <td>Woburn</td>\n",
" <td>43.770992</td>\n",
" <td>-79.216917</td>\n",
" <td>TO</td>\n",
" <td>M1G</td>\n",
" </tr>\n",
" <tr>\n",
" <th>23</th>\n",
" <td>East York</td>\n",
" <td>Leaside</td>\n",
" <td>43.709060</td>\n",
" <td>-79.363452</td>\n",
" <td>TO</td>\n",
" <td>M4G</td>\n",
" </tr>\n",
" <tr>\n",
" <th>24</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Central Bay Street</td>\n",
" <td>43.657952</td>\n",
" <td>-79.387383</td>\n",
" <td>TO</td>\n",
" <td>M5G</td>\n",
" </tr>\n",
" <tr>\n",
" <th>25</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Christie</td>\n",
" <td>43.669542</td>\n",
" <td>-79.422564</td>\n",
" <td>TO</td>\n",
" <td>M6G</td>\n",
" </tr>\n",
" <tr>\n",
" <th>26</th>\n",
" <td>Scarborough</td>\n",
" <td>Cedarbrae</td>\n",
" <td>43.773136</td>\n",
" <td>-79.239476</td>\n",
" <td>TO</td>\n",
" <td>M1H</td>\n",
" </tr>\n",
" <tr>\n",
" <th>27</th>\n",
" <td>North York</td>\n",
" <td>Hillcrest Village</td>\n",
" <td>43.803762</td>\n",
" <td>-79.363452</td>\n",
" <td>TO</td>\n",
" <td>M2H</td>\n",
" </tr>\n",
" <tr>\n",
" <th>28</th>\n",
" <td>North York</td>\n",
" <td>Bathurst Manor / Wilson Heights / Downsview North</td>\n",
" <td>43.754328</td>\n",
" <td>-79.442259</td>\n",
" <td>TO</td>\n",
" <td>M3H</td>\n",
" </tr>\n",
" <tr>\n",
" <th>29</th>\n",
" <td>East York</td>\n",
" <td>Thorncliffe Park</td>\n",
" <td>43.705369</td>\n",
" <td>-79.349372</td>\n",
" <td>TO</td>\n",
" <td>M4H</td>\n",
" </tr>\n",
" <tr>\n",
" <th>30</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Richmond / Adelaide / King</td>\n",
" <td>43.650571</td>\n",
" <td>-79.384568</td>\n",
" <td>TO</td>\n",
" <td>M5H</td>\n",
" </tr>\n",
" <tr>\n",
" <th>31</th>\n",
" <td>West Toronto</td>\n",
" <td>Dufferin / Dovercourt Village</td>\n",
" <td>43.669005</td>\n",
" <td>-79.442259</td>\n",
" <td>TO</td>\n",
" <td>M6H</td>\n",
" </tr>\n",
" <tr>\n",
" <th>32</th>\n",
" <td>Scarborough</td>\n",
" <td>Scarborough Village</td>\n",
" <td>43.744734</td>\n",
" <td>-79.239476</td>\n",
" <td>TO</td>\n",
" <td>M1J</td>\n",
" </tr>\n",
" <tr>\n",
" <th>33</th>\n",
" <td>North York</td>\n",
" <td>Fairview / Henry Farm / Oriole</td>\n",
" <td>43.778517</td>\n",
" <td>-79.346556</td>\n",
" <td>TO</td>\n",
" <td>M2J</td>\n",
" </tr>\n",
" <tr>\n",
" <th>34</th>\n",
" <td>North York</td>\n",
" <td>Northwood Park / York University</td>\n",
" <td>43.767980</td>\n",
" <td>-79.487262</td>\n",
" <td>TO</td>\n",
" <td>M3J</td>\n",
" </tr>\n",
" <tr>\n",
" <th>35</th>\n",
" <td>East York</td>\n",
" <td>East Toronto</td>\n",
" <td>43.685347</td>\n",
" <td>-79.338106</td>\n",
" <td>TO</td>\n",
" <td>M4J</td>\n",
" </tr>\n",
" <tr>\n",
" <th>36</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Harbourfront East / Union Station / Toronto Is...</td>\n",
" <td>43.640816</td>\n",
" <td>-79.381752</td>\n",
" <td>TO</td>\n",
" <td>M5J</td>\n",
" </tr>\n",
" <tr>\n",
" <th>37</th>\n",
" <td>West Toronto</td>\n",
" <td>Little Portugal / Trinity</td>\n",
" <td>43.647927</td>\n",
" <td>-79.419750</td>\n",
" <td>TO</td>\n",
" <td>M6J</td>\n",
" </tr>\n",
" <tr>\n",
" <th>38</th>\n",
" <td>Scarborough</td>\n",
" <td>Kennedy Park / Ionview / East Birchmount Park</td>\n",
" <td>43.727929</td>\n",
" <td>-79.262029</td>\n",
" <td>TO</td>\n",
" <td>M1K</td>\n",
" </tr>\n",
" <tr>\n",
" <th>39</th>\n",
" <td>North York</td>\n",
" <td>Bayview Village</td>\n",
" <td>43.786947</td>\n",
" <td>-79.385975</td>\n",
" <td>TO</td>\n",
" <td>M2K</td>\n",
" </tr>\n",
" <tr>\n",
" <th>40</th>\n",
" <td>North York</td>\n",
" <td>Downsview</td>\n",
" <td>43.737473</td>\n",
" <td>-79.464763</td>\n",
" <td>TO</td>\n",
" <td>M3K</td>\n",
" </tr>\n",
" <tr>\n",
" <th>41</th>\n",
" <td>East Toronto</td>\n",
" <td>The Danforth West / Riverdale</td>\n",
" <td>43.679557</td>\n",
" <td>-79.352188</td>\n",
" <td>TO</td>\n",
" <td>M4K</td>\n",
" </tr>\n",
" <tr>\n",
" <th>42</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Toronto Dominion Centre / Design Exchange</td>\n",
" <td>43.647177</td>\n",
" <td>-79.381576</td>\n",
" <td>TO</td>\n",
" <td>M5K</td>\n",
" </tr>\n",
" <tr>\n",
" <th>43</th>\n",
" <td>West Toronto</td>\n",
" <td>Brockton / Parkdale Village / Exhibition Place</td>\n",
" <td>43.636847</td>\n",
" <td>-79.428191</td>\n",
" <td>TO</td>\n",
" <td>M6K</td>\n",
" </tr>\n",
" <tr>\n",
" <th>44</th>\n",
" <td>Scarborough</td>\n",
" <td>Golden Mile / Clairlea / Oakridge</td>\n",
" <td>43.711112</td>\n",
" <td>-79.284577</td>\n",
" <td>TO</td>\n",
" <td>M1L</td>\n",
" </tr>\n",
" <tr>\n",
" <th>45</th>\n",
" <td>North York</td>\n",
" <td>York Mills / Silver Hills</td>\n",
" <td>43.757490</td>\n",
" <td>-79.374714</td>\n",
" <td>TO</td>\n",
" <td>M2L</td>\n",
" </tr>\n",
" <tr>\n",
" <th>46</th>\n",
" <td>North York</td>\n",
" <td>Downsview</td>\n",
" <td>43.739015</td>\n",
" <td>-79.506944</td>\n",
" <td>TO</td>\n",
" <td>M3L</td>\n",
" </tr>\n",
" <tr>\n",
" <th>47</th>\n",
" <td>East Toronto</td>\n",
" <td>India Bazaar / The Beaches West</td>\n",
" <td>43.668999</td>\n",
" <td>-79.315572</td>\n",
" <td>TO</td>\n",
" <td>M4L</td>\n",
" </tr>\n",
" <tr>\n",
" <th>48</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Commerce Court / Victoria Hotel</td>\n",
" <td>43.648198</td>\n",
" <td>-79.379817</td>\n",
" <td>TO</td>\n",
" <td>M5L</td>\n",
" </tr>\n",
" <tr>\n",
" <th>49</th>\n",
" <td>North York</td>\n",
" <td>North Park / Maple Leaf Park / Upwood Park</td>\n",
" <td>43.713756</td>\n",
" <td>-79.490074</td>\n",
" <td>TO</td>\n",
" <td>M6L</td>\n",
" </tr>\n",
" <tr>\n",
" <th>50</th>\n",
" <td>North York</td>\n",
" <td>Humber Summit</td>\n",
" <td>43.756303</td>\n",
" <td>-79.565963</td>\n",
" <td>TO</td>\n",
" <td>M9L</td>\n",
" </tr>\n",
" <tr>\n",
" <th>51</th>\n",
" <td>Scarborough</td>\n",
" <td>Cliffside / Cliffcrest / Scarborough Village West</td>\n",
" <td>43.716316</td>\n",
" <td>-79.239476</td>\n",
" <td>TO</td>\n",
" <td>M1M</td>\n",
" </tr>\n",
" <tr>\n",
" <th>52</th>\n",
" <td>North York</td>\n",
" <td>Willowdale / Newtonbrook</td>\n",
" <td>43.789053</td>\n",
" <td>-79.408493</td>\n",
" <td>TO</td>\n",
" <td>M2M</td>\n",
" </tr>\n",
" <tr>\n",
" <th>53</th>\n",
" <td>North York</td>\n",
" <td>Downsview</td>\n",
" <td>43.728496</td>\n",
" <td>-79.495697</td>\n",
" <td>TO</td>\n",
" <td>M3M</td>\n",
" </tr>\n",
" <tr>\n",
" <th>54</th>\n",
" <td>East Toronto</td>\n",
" <td>Studio District</td>\n",
" <td>43.659526</td>\n",
" <td>-79.340923</td>\n",
" <td>TO</td>\n",
" <td>M4M</td>\n",
" </tr>\n",
" <tr>\n",
" <th>55</th>\n",
" <td>North York</td>\n",
" <td>Bedford Park / Lawrence Manor East</td>\n",
" <td>43.733283</td>\n",
" <td>-79.419750</td>\n",
" <td>TO</td>\n",
" <td>M5M</td>\n",
" </tr>\n",
" <tr>\n",
" <th>56</th>\n",
" <td>York</td>\n",
" <td>Del Ray / Mount Dennis / Keelsdale and Silvert...</td>\n",
" <td>43.691116</td>\n",
" <td>-79.476013</td>\n",
" <td>TO</td>\n",
" <td>M6M</td>\n",
" </tr>\n",
" <tr>\n",
" <th>57</th>\n",
" <td>North York</td>\n",
" <td>Humberlea / Emery</td>\n",
" <td>43.724766</td>\n",
" <td>-79.532242</td>\n",
" <td>TO</td>\n",
" <td>M9M</td>\n",
" </tr>\n",
" <tr>\n",
" <th>58</th>\n",
" <td>Scarborough</td>\n",
" <td>Birch Cliff / Cliffside West</td>\n",
" <td>43.692657</td>\n",
" <td>-79.264848</td>\n",
" <td>TO</td>\n",
" <td>M1N</td>\n",
" </tr>\n",
" <tr>\n",
" <th>59</th>\n",
" <td>North York</td>\n",
" <td>Willowdale</td>\n",
" <td>43.770120</td>\n",
" <td>-79.408493</td>\n",
" <td>TO</td>\n",
" <td>M2N</td>\n",
" </tr>\n",
" <tr>\n",
" <th>60</th>\n",
" <td>North York</td>\n",
" <td>Downsview</td>\n",
" <td>43.761631</td>\n",
" <td>-79.520999</td>\n",
" <td>TO</td>\n",
" <td>M3N</td>\n",
" </tr>\n",
" <tr>\n",
" <th>61</th>\n",
" <td>Central Toronto</td>\n",
" <td>Lawrence Park</td>\n",
" <td>43.728020</td>\n",
" <td>-79.388790</td>\n",
" <td>TO</td>\n",
" <td>M4N</td>\n",
" </tr>\n",
" <tr>\n",
" <th>62</th>\n",
" <td>Central Toronto</td>\n",
" <td>Roselawn</td>\n",
" <td>43.711695</td>\n",
" <td>-79.416936</td>\n",
" <td>TO</td>\n",
" <td>M5N</td>\n",
" </tr>\n",
" <tr>\n",
" <th>63</th>\n",
" <td>York</td>\n",
" <td>Runnymede / The Junction North</td>\n",
" <td>43.673185</td>\n",
" <td>-79.487262</td>\n",
" <td>TO</td>\n",
" <td>M6N</td>\n",
" </tr>\n",
" <tr>\n",
" <th>64</th>\n",
" <td>York</td>\n",
" <td>Weston</td>\n",
" <td>43.706876</td>\n",
" <td>-79.518188</td>\n",
" <td>TO</td>\n",
" <td>M9N</td>\n",
" </tr>\n",
" <tr>\n",
" <th>65</th>\n",
" <td>Scarborough</td>\n",
" <td>Dorset Park / Wexford Heights / Scarborough To...</td>\n",
" <td>43.757410</td>\n",
" <td>-79.273304</td>\n",
" <td>TO</td>\n",
" <td>M1P</td>\n",
" </tr>\n",
" <tr>\n",
" <th>66</th>\n",
" <td>North York</td>\n",
" <td>York Mills West</td>\n",
" <td>43.752758</td>\n",
" <td>-79.400049</td>\n",
" <td>TO</td>\n",
" <td>M2P</td>\n",
" </tr>\n",
" <tr>\n",
" <th>67</th>\n",
" <td>Central Toronto</td>\n",
" <td>Davisville North</td>\n",
" <td>43.712751</td>\n",
" <td>-79.390197</td>\n",
" <td>TO</td>\n",
" <td>M4P</td>\n",
" </tr>\n",
" <tr>\n",
" <th>68</th>\n",
" <td>Central Toronto</td>\n",
" <td>Forest Hill North &amp; West</td>\n",
" <td>43.696948</td>\n",
" <td>-79.411307</td>\n",
" <td>TO</td>\n",
" <td>M5P</td>\n",
" </tr>\n",
" <tr>\n",
" <th>69</th>\n",
" <td>West Toronto</td>\n",
" <td>High Park / The Junction South</td>\n",
" <td>43.661608</td>\n",
" <td>-79.464763</td>\n",
" <td>TO</td>\n",
" <td>M6P</td>\n",
" </tr>\n",
" <tr>\n",
" <th>70</th>\n",
" <td>Etobicoke</td>\n",
" <td>Westmount</td>\n",
" <td>43.696319</td>\n",
" <td>-79.532242</td>\n",
" <td>TO</td>\n",
" <td>M9P</td>\n",
" </tr>\n",
" <tr>\n",
" <th>71</th>\n",
" <td>Scarborough</td>\n",
" <td>Wexford / Maryvale</td>\n",
" <td>43.750072</td>\n",
" <td>-79.295849</td>\n",
" <td>TO</td>\n",
" <td>M1R</td>\n",
" </tr>\n",
" <tr>\n",
" <th>72</th>\n",
" <td>North York</td>\n",
" <td>Willowdale</td>\n",
" <td>43.782736</td>\n",
" <td>-79.442259</td>\n",
" <td>TO</td>\n",
" <td>M2R</td>\n",
" </tr>\n",
" <tr>\n",
" <th>73</th>\n",
" <td>Central Toronto</td>\n",
" <td>North Toronto West</td>\n",
" <td>43.715383</td>\n",
" <td>-79.405678</td>\n",
" <td>TO</td>\n",
" <td>M4R</td>\n",
" </tr>\n",
" <tr>\n",
" <th>74</th>\n",
" <td>Central Toronto</td>\n",
" <td>The Annex / North Midtown / Yorkville</td>\n",
" <td>43.672710</td>\n",
" <td>-79.405678</td>\n",
" <td>TO</td>\n",
" <td>M5R</td>\n",
" </tr>\n",
" <tr>\n",
" <th>75</th>\n",
" <td>West Toronto</td>\n",
" <td>Parkdale / Roncesvalles</td>\n",
" <td>43.648960</td>\n",
" <td>-79.456325</td>\n",
" <td>TO</td>\n",
" <td>M6R</td>\n",
" </tr>\n",
" <tr>\n",
" <th>76</th>\n",
" <td>Mississauga</td>\n",
" <td>Canada Post Gateway Processing Centre</td>\n",
" <td>43.636966</td>\n",
" <td>-79.615819</td>\n",
" <td>TO</td>\n",
" <td>M7R</td>\n",
" </tr>\n",
" <tr>\n",
" <th>77</th>\n",
" <td>Etobicoke</td>\n",
" <td>Kingsview Village / St. Phillips / Martin Grov...</td>\n",
" <td>43.688905</td>\n",
" <td>-79.554724</td>\n",
" <td>TO</td>\n",
" <td>M9R</td>\n",
" </tr>\n",
" <tr>\n",
" <th>78</th>\n",
" <td>Scarborough</td>\n",
" <td>Agincourt</td>\n",
" <td>43.794200</td>\n",
" <td>-79.262029</td>\n",
" <td>TO</td>\n",
" <td>M1S</td>\n",
" </tr>\n",
" <tr>\n",
" <th>79</th>\n",
" <td>Central Toronto</td>\n",
" <td>Davisville</td>\n",
" <td>43.704324</td>\n",
" <td>-79.388790</td>\n",
" <td>TO</td>\n",
" <td>M4S</td>\n",
" </tr>\n",
" <tr>\n",
" <th>80</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>University of Toronto / Harbord</td>\n",
" <td>43.662696</td>\n",
" <td>-79.400049</td>\n",
" <td>TO</td>\n",
" <td>M5S</td>\n",
" </tr>\n",
" <tr>\n",
" <th>81</th>\n",
" <td>West Toronto</td>\n",
" <td>Runnymede / Swansea</td>\n",
" <td>43.651571</td>\n",
" <td>-79.484450</td>\n",
" <td>TO</td>\n",
" <td>M6S</td>\n",
" </tr>\n",
" <tr>\n",
" <th>82</th>\n",
" <td>Scarborough</td>\n",
" <td>Clarks Corners / Tam O'Shanter / Sullivan</td>\n",
" <td>43.781638</td>\n",
" <td>-79.304302</td>\n",
" <td>TO</td>\n",
" <td>M1T</td>\n",
" </tr>\n",
" <tr>\n",
" <th>83</th>\n",
" <td>Central Toronto</td>\n",
" <td>Moore Park / Summerhill East</td>\n",
" <td>43.689574</td>\n",
" <td>-79.383160</td>\n",
" <td>TO</td>\n",
" <td>M4T</td>\n",
" </tr>\n",
" <tr>\n",
" <th>84</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Kensington Market / Chinatown / Grange Park</td>\n",
" <td>43.653206</td>\n",
" <td>-79.400049</td>\n",
" <td>TO</td>\n",
" <td>M5T</td>\n",
" </tr>\n",
" <tr>\n",
" <th>85</th>\n",
" <td>Scarborough</td>\n",
" <td>Milliken / Agincourt North / Steeles East / L'...</td>\n",
" <td>43.815252</td>\n",
" <td>-79.284577</td>\n",
" <td>TO</td>\n",
" <td>M1V</td>\n",
" </tr>\n",
" <tr>\n",
" <th>86</th>\n",
" <td>Central Toronto</td>\n",
" <td>Summerhill West / Rathnelly / South Hill / For...</td>\n",
" <td>43.686412</td>\n",
" <td>-79.400049</td>\n",
" <td>TO</td>\n",
" <td>M4V</td>\n",
" </tr>\n",
" <tr>\n",
" <th>87</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>CN Tower / King and Spadina / Railway Lands / ...</td>\n",
" <td>43.628947</td>\n",
" <td>-79.394420</td>\n",
" <td>TO</td>\n",
" <td>M5V</td>\n",
" </tr>\n",
" <tr>\n",
" <th>88</th>\n",
" <td>Etobicoke</td>\n",
" <td>New Toronto / Mimico South / Humber Bay Shores</td>\n",
" <td>43.605647</td>\n",
" <td>-79.501321</td>\n",
" <td>TO</td>\n",
" <td>M8V</td>\n",
" </tr>\n",
" <tr>\n",
" <th>89</th>\n",
" <td>Etobicoke</td>\n",
" <td>South Steeles / Silverstone / Humbergate / Jam...</td>\n",
" <td>43.739416</td>\n",
" <td>-79.588437</td>\n",
" <td>TO</td>\n",
" <td>M9V</td>\n",
" </tr>\n",
" <tr>\n",
" <th>90</th>\n",
" <td>Scarborough</td>\n",
" <td>Steeles West / L'Amoreaux West</td>\n",
" <td>43.799525</td>\n",
" <td>-79.318389</td>\n",
" <td>TO</td>\n",
" <td>M1W</td>\n",
" </tr>\n",
" <tr>\n",
" <th>91</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Rosedale</td>\n",
" <td>43.679563</td>\n",
" <td>-79.377529</td>\n",
" <td>TO</td>\n",
" <td>M4W</td>\n",
" </tr>\n",
" <tr>\n",
" <th>92</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Stn A PO Boxes</td>\n",
" <td>43.646435</td>\n",
" <td>-79.374846</td>\n",
" <td>TO</td>\n",
" <td>M5W</td>\n",
" </tr>\n",
" <tr>\n",
" <th>93</th>\n",
" <td>Etobicoke</td>\n",
" <td>Alderwood / Long Branch</td>\n",
" <td>43.602414</td>\n",
" <td>-79.543484</td>\n",
" <td>TO</td>\n",
" <td>M8W</td>\n",
" </tr>\n",
" <tr>\n",
" <th>94</th>\n",
" <td>Etobicoke</td>\n",
" <td>Northwest</td>\n",
" <td>43.706748</td>\n",
" <td>-79.594054</td>\n",
" <td>TO</td>\n",
" <td>M9W</td>\n",
" </tr>\n",
" <tr>\n",
" <th>95</th>\n",
" <td>Scarborough</td>\n",
" <td>Upper Rouge</td>\n",
" <td>43.836125</td>\n",
" <td>-79.205636</td>\n",
" <td>TO</td>\n",
" <td>M1X</td>\n",
" </tr>\n",
" <tr>\n",
" <th>96</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>St. James Town / Cabbagetown</td>\n",
" <td>43.667967</td>\n",
" <td>-79.367675</td>\n",
" <td>TO</td>\n",
" <td>M4X</td>\n",
" </tr>\n",
" <tr>\n",
" <th>97</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>First Canadian Place / Underground city</td>\n",
" <td>43.648429</td>\n",
" <td>-79.382280</td>\n",
" <td>TO</td>\n",
" <td>M5X</td>\n",
" </tr>\n",
" <tr>\n",
" <th>98</th>\n",
" <td>Etobicoke</td>\n",
" <td>The Kingsway / Montgomery Road / Old Mill North</td>\n",
" <td>43.653654</td>\n",
" <td>-79.506944</td>\n",
" <td>TO</td>\n",
" <td>M8X</td>\n",
" </tr>\n",
" <tr>\n",
" <th>99</th>\n",
" <td>Downtown Toronto</td>\n",
" <td>Church and Wellesley</td>\n",
" <td>43.665860</td>\n",
" <td>-79.383160</td>\n",
" <td>TO</td>\n",
" <td>M4Y</td>\n",
" </tr>\n",
" <tr>\n",
" <th>100</th>\n",
" <td>East Toronto</td>\n",
" <td>Business reply mail Processing CentrE</td>\n",
" <td>43.662744</td>\n",
" <td>-79.321558</td>\n",
" <td>TO</td>\n",
" <td>M7Y</td>\n",
" </tr>\n",
" <tr>\n",
" <th>101</th>\n",
" <td>Etobicoke</td>\n",
" <td>Old Mill South / King's Mill Park / Sunnylea /...</td>\n",
" <td>43.636258</td>\n",
" <td>-79.498509</td>\n",
" <td>TO</td>\n",
" <td>M8Y</td>\n",
" </tr>\n",
" <tr>\n",
" <th>102</th>\n",
" <td>Etobicoke</td>\n",
" <td>Mimico NW / The Queensway West / South of Bloo...</td>\n",
" <td>43.628841</td>\n",
" <td>-79.520999</td>\n",
" <td>TO</td>\n",
" <td>M8Z</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Borough Neighborhood \\\n",
"171 Queens Broad Channel \n",
"0 North York Parkwoods \n",
"1 North York Victoria Village \n",
"2 Downtown Toronto Regent Park / Harbourfront \n",
"3 North York Lawrence Manor / Lawrence Heights \n",
"4 Downtown Toronto Queen's Park / Ontario Provincial Government \n",
"5 Etobicoke Islington Avenue \n",
"6 Scarborough Malvern / Rouge \n",
"7 North York Don Mills \n",
"8 East York Parkview Hill / Woodbine Gardens \n",
"9 Downtown Toronto Garden District-Ryerson \n",
"10 North York Glencairn \n",
"11 Etobicoke West Deane Park / Princess Gardens / Martin Gr... \n",
"12 Scarborough Rouge Hill / Port Union / Highland Creek \n",
"13 North York Don Mills \n",
"14 East York Woodbine Heights \n",
"15 Downtown Toronto St. James Town \n",
"16 York Humewood-Cedarvale \n",
"17 Etobicoke Eringate / Bloordale Gardens / Old Burnhamthor... \n",
"18 Scarborough Guildwood / Morningside / West Hill \n",
"19 East Toronto The Beaches \n",
"20 Downtown Toronto Berczy Park \n",
"21 York Caledonia-Fairbanks \n",
"22 Scarborough Woburn \n",
"23 East York Leaside \n",
"24 Downtown Toronto Central Bay Street \n",
"25 Downtown Toronto Christie \n",
"26 Scarborough Cedarbrae \n",
"27 North York Hillcrest Village \n",
"28 North York Bathurst Manor / Wilson Heights / Downsview North \n",
"29 East York Thorncliffe Park \n",
"30 Downtown Toronto Richmond / Adelaide / King \n",
"31 West Toronto Dufferin / Dovercourt Village \n",
"32 Scarborough Scarborough Village \n",
"33 North York Fairview / Henry Farm / Oriole \n",
"34 North York Northwood Park / York University \n",
"35 East York East Toronto \n",
"36 Downtown Toronto Harbourfront East / Union Station / Toronto Is... \n",
"37 West Toronto Little Portugal / Trinity \n",
"38 Scarborough Kennedy Park / Ionview / East Birchmount Park \n",
"39 North York Bayview Village \n",
"40 North York Downsview \n",
"41 East Toronto The Danforth West / Riverdale \n",
"42 Downtown Toronto Toronto Dominion Centre / Design Exchange \n",
"43 West Toronto Brockton / Parkdale Village / Exhibition Place \n",
"44 Scarborough Golden Mile / Clairlea / Oakridge \n",
"45 North York York Mills / Silver Hills \n",
"46 North York Downsview \n",
"47 East Toronto India Bazaar / The Beaches West \n",
"48 Downtown Toronto Commerce Court / Victoria Hotel \n",
"49 North York North Park / Maple Leaf Park / Upwood Park \n",
"50 North York Humber Summit \n",
"51 Scarborough Cliffside / Cliffcrest / Scarborough Village West \n",
"52 North York Willowdale / Newtonbrook \n",
"53 North York Downsview \n",
"54 East Toronto Studio District \n",
"55 North York Bedford Park / Lawrence Manor East \n",
"56 York Del Ray / Mount Dennis / Keelsdale and Silvert... \n",
"57 North York Humberlea / Emery \n",
"58 Scarborough Birch Cliff / Cliffside West \n",
"59 North York Willowdale \n",
"60 North York Downsview \n",
"61 Central Toronto Lawrence Park \n",
"62 Central Toronto Roselawn \n",
"63 York Runnymede / The Junction North \n",
"64 York Weston \n",
"65 Scarborough Dorset Park / Wexford Heights / Scarborough To... \n",
"66 North York York Mills West \n",
"67 Central Toronto Davisville North \n",
"68 Central Toronto Forest Hill North & West \n",
"69 West Toronto High Park / The Junction South \n",
"70 Etobicoke Westmount \n",
"71 Scarborough Wexford / Maryvale \n",
"72 North York Willowdale \n",
"73 Central Toronto North Toronto West \n",
"74 Central Toronto The Annex / North Midtown / Yorkville \n",
"75 West Toronto Parkdale / Roncesvalles \n",
"76 Mississauga Canada Post Gateway Processing Centre \n",
"77 Etobicoke Kingsview Village / St. Phillips / Martin Grov... \n",
"78 Scarborough Agincourt \n",
"79 Central Toronto Davisville \n",
"80 Downtown Toronto University of Toronto / Harbord \n",
"81 West Toronto Runnymede / Swansea \n",
"82 Scarborough Clarks Corners / Tam O'Shanter / Sullivan \n",
"83 Central Toronto Moore Park / Summerhill East \n",
"84 Downtown Toronto Kensington Market / Chinatown / Grange Park \n",
"85 Scarborough Milliken / Agincourt North / Steeles East / L'... \n",
"86 Central Toronto Summerhill West / Rathnelly / South Hill / For... \n",
"87 Downtown Toronto CN Tower / King and Spadina / Railway Lands / ... \n",
"88 Etobicoke New Toronto / Mimico South / Humber Bay Shores \n",
"89 Etobicoke South Steeles / Silverstone / Humbergate / Jam... \n",
"90 Scarborough Steeles West / L'Amoreaux West \n",
"91 Downtown Toronto Rosedale \n",
"92 Downtown Toronto Stn A PO Boxes \n",
"93 Etobicoke Alderwood / Long Branch \n",
"94 Etobicoke Northwest \n",
"95 Scarborough Upper Rouge \n",
"96 Downtown Toronto St. James Town / Cabbagetown \n",
"97 Downtown Toronto First Canadian Place / Underground city \n",
"98 Etobicoke The Kingsway / Montgomery Road / Old Mill North \n",
"99 Downtown Toronto Church and Wellesley \n",
"100 East Toronto Business reply mail Processing CentrE \n",
"101 Etobicoke Old Mill South / King's Mill Park / Sunnylea /... \n",
"102 Etobicoke Mimico NW / The Queensway West / South of Bloo... \n",
"\n",
" Latitude Longitude city Postalcode \n",
"171 40.603027 -73.820055 NY NY \n",
"0 43.753259 -79.329656 TO M3A \n",
"1 43.725882 -79.315572 TO M4A \n",
"2 43.654260 -79.360636 TO M5A \n",
"3 43.718518 -79.464763 TO M6A \n",
"4 43.662301 -79.389494 TO M7A \n",
"5 43.667856 -79.532242 TO M9A \n",
"6 43.806686 -79.194353 TO M1B \n",
"7 43.745906 -79.352188 TO M3B \n",
"8 43.706397 -79.309937 TO M4B \n",
"9 43.657162 -79.378937 TO M5B \n",
"10 43.709577 -79.445073 TO M6B \n",
"11 43.650943 -79.554724 TO M9B \n",
"12 43.784535 -79.160497 TO M1C \n",
"13 43.725900 -79.340923 TO M3C \n",
"14 43.695344 -79.318389 TO M4C \n",
"15 43.651494 -79.375418 TO M5C \n",
"16 43.693781 -79.428191 TO M6C \n",
"17 43.643515 -79.577201 TO M9C \n",
"18 43.763573 -79.188711 TO M1E \n",
"19 43.676357 -79.293031 TO M4E \n",
"20 43.644771 -79.373306 TO M5E \n",
"21 43.689026 -79.453512 TO M6E \n",
"22 43.770992 -79.216917 TO M1G \n",
"23 43.709060 -79.363452 TO M4G \n",
"24 43.657952 -79.387383 TO M5G \n",
"25 43.669542 -79.422564 TO M6G \n",
"26 43.773136 -79.239476 TO M1H \n",
"27 43.803762 -79.363452 TO M2H \n",
"28 43.754328 -79.442259 TO M3H \n",
"29 43.705369 -79.349372 TO M4H \n",
"30 43.650571 -79.384568 TO M5H \n",
"31 43.669005 -79.442259 TO M6H \n",
"32 43.744734 -79.239476 TO M1J \n",
"33 43.778517 -79.346556 TO M2J \n",
"34 43.767980 -79.487262 TO M3J \n",
"35 43.685347 -79.338106 TO M4J \n",
"36 43.640816 -79.381752 TO M5J \n",
"37 43.647927 -79.419750 TO M6J \n",
"38 43.727929 -79.262029 TO M1K \n",
"39 43.786947 -79.385975 TO M2K \n",
"40 43.737473 -79.464763 TO M3K \n",
"41 43.679557 -79.352188 TO M4K \n",
"42 43.647177 -79.381576 TO M5K \n",
"43 43.636847 -79.428191 TO M6K \n",
"44 43.711112 -79.284577 TO M1L \n",
"45 43.757490 -79.374714 TO M2L \n",
"46 43.739015 -79.506944 TO M3L \n",
"47 43.668999 -79.315572 TO M4L \n",
"48 43.648198 -79.379817 TO M5L \n",
"49 43.713756 -79.490074 TO M6L \n",
"50 43.756303 -79.565963 TO M9L \n",
"51 43.716316 -79.239476 TO M1M \n",
"52 43.789053 -79.408493 TO M2M \n",
"53 43.728496 -79.495697 TO M3M \n",
"54 43.659526 -79.340923 TO M4M \n",
"55 43.733283 -79.419750 TO M5M \n",
"56 43.691116 -79.476013 TO M6M \n",
"57 43.724766 -79.532242 TO M9M \n",
"58 43.692657 -79.264848 TO M1N \n",
"59 43.770120 -79.408493 TO M2N \n",
"60 43.761631 -79.520999 TO M3N \n",
"61 43.728020 -79.388790 TO M4N \n",
"62 43.711695 -79.416936 TO M5N \n",
"63 43.673185 -79.487262 TO M6N \n",
"64 43.706876 -79.518188 TO M9N \n",
"65 43.757410 -79.273304 TO M1P \n",
"66 43.752758 -79.400049 TO M2P \n",
"67 43.712751 -79.390197 TO M4P \n",
"68 43.696948 -79.411307 TO M5P \n",
"69 43.661608 -79.464763 TO M6P \n",
"70 43.696319 -79.532242 TO M9P \n",
"71 43.750072 -79.295849 TO M1R \n",
"72 43.782736 -79.442259 TO M2R \n",
"73 43.715383 -79.405678 TO M4R \n",
"74 43.672710 -79.405678 TO M5R \n",
"75 43.648960 -79.456325 TO M6R \n",
"76 43.636966 -79.615819 TO M7R \n",
"77 43.688905 -79.554724 TO M9R \n",
"78 43.794200 -79.262029 TO M1S \n",
"79 43.704324 -79.388790 TO M4S \n",
"80 43.662696 -79.400049 TO M5S \n",
"81 43.651571 -79.484450 TO M6S \n",
"82 43.781638 -79.304302 TO M1T \n",
"83 43.689574 -79.383160 TO M4T \n",
"84 43.653206 -79.400049 TO M5T \n",
"85 43.815252 -79.284577 TO M1V \n",
"86 43.686412 -79.400049 TO M4V \n",
"87 43.628947 -79.394420 TO M5V \n",
"88 43.605647 -79.501321 TO M8V \n",
"89 43.739416 -79.588437 TO M9V \n",
"90 43.799525 -79.318389 TO M1W \n",
"91 43.679563 -79.377529 TO M4W \n",
"92 43.646435 -79.374846 TO M5W \n",
"93 43.602414 -79.543484 TO M8W \n",
"94 43.706748 -79.594054 TO M9W \n",
"95 43.836125 -79.205636 TO M1X \n",
"96 43.667967 -79.367675 TO M4X \n",
"97 43.648429 -79.382280 TO M5X \n",
"98 43.653654 -79.506944 TO M8X \n",
"99 43.665860 -79.383160 TO M4Y \n",
"100 43.662744 -79.321558 TO M7Y \n",
"101 43.636258 -79.498509 TO M8Y \n",
"102 43.628841 -79.520999 TO M8Z "
]
},
"execution_count": 330,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Now let's concatenate the Toronto Dataframe with the record selected by the user:\n",
"# You will notice the NY record will be the first on the list.\n",
"\n",
"Toronto_Neighb = Toronto_Neighb[(Toronto_Neighb['city']=='TO')]\n",
"Toronto_Neighb = pd.concat([neighborhoods_NY[(neighborhoods_NY['Neighborhood']==caption.value)],Toronto_Neighb])\n",
"Toronto_Neighb"
]
},
{
"cell_type": "code",
"execution_count": 331,
"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>Borough</th>\n",
" <th>Neighborhood</th>\n",
" <th>Latitude</th>\n",
" <th>Longitude</th>\n",
" <th>city</th>\n",
" <th>Postalcode</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>171</th>\n",
" <td>Queens</td>\n",
" <td>Broad Channel</td>\n",
" <td>40.603027</td>\n",
" <td>-73.820055</td>\n",
" <td>NY</td>\n",
" <td>NY</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Borough Neighborhood Latitude Longitude city Postalcode\n",
"171 Queens Broad Channel 40.603027 -73.820055 NY NY"
]
},
"execution_count": 331,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# here is the isolated record:\n",
"neighborhoods_NY[(neighborhoods_NY['Neighborhood']==caption.value)]"
]
},
{
"cell_type": "code",
"execution_count": 332,
"metadata": {},
"outputs": [],
"source": [
"# Now let's get the venues!"
]
},
{
"cell_type": "code",
"execution_count": 333,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Your credentails:\n",
"CLIENT_ID: VAHUGBJMS1OYZJ5GCHJGF121BRMAOOBZWCD135K3XEJ1ISCG\n",
"CLIENT_SECRET:CNQDHEV0R4P5YU1YPOSUAF0F2Y3QHFNLVETSRFZEEFMW0DUE\n"
]
}
],
"source": [
"#### Define Foursquare Credentials and Version\n",
"\n",
"CLIENT_ID = 'VAHUGBJMS1OYZJ5GCHJGF121BRMAOOBZWCD135K3XEJ1ISCG' # your Foursquare ID\n",
"CLIENT_SECRET = 'CNQDHEV0R4P5YU1YPOSUAF0F2Y3QHFNLVETSRFZEEFMW0DUE' # your Foursquare Secret\n",
"VERSION = '20180605' # Foursquare API version\n",
"\n",
"print('Your credentails:')\n",
"print('CLIENT_ID: ' + CLIENT_ID)\n",
"print('CLIENT_SECRET:' + CLIENT_SECRET)\n",
"\n",
"## Define other variables to Foursquare API\n",
"radius = 500\n",
"LIMIT = 100"
]
},
{
"cell_type": "code",
"execution_count": 334,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The geograpical coordinate of Toronto are 43.6534817, -79.3839347.\n"
]
}
],
"source": [
"#### Putting our Toronto Neighborhoods on the map!\n",
"\n",
"address = 'Toronto, CA'\n",
"\n",
"geolocator = Nominatim(user_agent=\"ny_explorer\")\n",
"location = geolocator.geocode(address)\n",
"latitude = location.latitude\n",
"longitude = location.longitude\n",
"print('The geograpical coordinate of Toronto are {}, {}.'.format(latitude, longitude))"
]
},
{
"cell_type": "code",
"execution_count": 335,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><span style=\"color:#565656\">Make this Notebook Trusted to load map: File -> Trust Notebook</span><iframe src=\"about:blank\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" data-html=PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVMgPSBmYWxzZTsgTF9OT19UT1VDSCA9IGZhbHNlOyBMX0RJU0FCTEVfM0QgPSBmYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdnaXQuY29tL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9tYXN0ZXIvZm9saXVtL3RlbXBsYXRlcy9sZWFmbGV0LmF3ZXNvbWUucm90YXRlLmNzcyIvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogMTAwLjAlOwogICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgICAgICAgICAgdG9wOiAwLjAlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICA8L3N0eWxlPgogICAgICAgIAo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgICAgICAgICA8ZGl2IGNsYXNzPSJmb2xpdW0tbWFwIiBpZD0ibWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2IiA+PC9kaXY+CiAgICAgICAgCjwvYm9keT4KPHNjcmlwdD4gICAgCiAgICAKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGJvdW5kcyA9IG51bGw7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgdmFyIG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3NiA9IEwubWFwKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ21hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3NicsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7Y2VudGVyOiBbNDMuNjUzNDgxNywtNzkuMzgzOTM0N10sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB6b29tOiAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heEJvdW5kczogYm91bmRzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF5ZXJzOiBbXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmxkQ29weUp1bXA6IGZhbHNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JzOiBMLkNSUy5FUFNHMzg1NwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHRpbGVfbGF5ZXJfNjU0ZjdjZDg1YWVkNDg2OGE5ZmI3ZmMzZTYzYjg0NjkgPSBMLnRpbGVMYXllcigKICAgICAgICAgICAgICAgICdodHRwczovL3tzfS50aWxlLm9wZW5zdHJlZXRtYXAub3JnL3t6fS97eH0ve3l9LnBuZycsCiAgICAgICAgICAgICAgICB7CiAgImF0dHJpYnV0aW9uIjogbnVsbCwKICAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsCiAgIm1heFpvb20iOiAxOCwKICAibWluWm9vbSI6IDEsCiAgIm5vV3JhcCI6IGZhbHNlLAogICJzdWJkb21haW5zIjogImFiYyIKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzI4YTE1ZGEwNDYxMjQ2YTY4ZDMwYzU2MzZiYzExYTk1ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDAuNjAzMDI2NTgzNTEyMzgsLTczLjgyMDA1NDg5MTEwMzJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYTEyZmQ2MzliZWY2NGE3ZTljZmY0NzhhODkyNTBkNjMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYWJiZjI2NWMyZTFmNDg5Njg5MTgzNTYwYmQxNDUzMjAgPSAkKCc8ZGl2IGlkPSJodG1sX2FiYmYyNjVjMmUxZjQ4OTY4OTE4MzU2MGJkMTQ1MzIwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ccm9hZCBDaGFubmVsPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hMTJmZDYzOWJlZjY0YTdlOWNmZjQ3OGE4OTI1MGQ2My5zZXRDb250ZW50KGh0bWxfYWJiZjI2NWMyZTFmNDg5Njg5MTgzNTYwYmQxNDUzMjApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjhhMTVkYTA0NjEyNDZhNjhkMzBjNTYzNmJjMTFhOTUuYmluZFBvcHVwKHBvcHVwX2ExMmZkNjM5YmVmNjRhN2U5Y2ZmNDc4YTg5MjUwZDYzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2MzY2I3NWUyMmUyNzRiMTZhYThkYzYyMjg0ZGNiZmNlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzUzMjU4NiwtNzkuMzI5NjU2NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iNDQ3MmU0Y2ZhNmE0ZmRhOWNhNzYxNWVkYzYyZjZiNSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85OGEzY2VlZjUxNzI0MDg2OTBlMDU3MDk4ZDQxZmFjZSA9ICQoJzxkaXYgaWQ9Imh0bWxfOThhM2NlZWY1MTcyNDA4NjkwZTA1NzA5OGQ0MWZhY2UiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlBhcmt3b29kczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjQ0NzJlNGNmYTZhNGZkYTljYTc2MTVlZGM2MmY2YjUuc2V0Q29udGVudChodG1sXzk4YTNjZWVmNTE3MjQwODY5MGUwNTcwOThkNDFmYWNlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2MzY2I3NWUyMmUyNzRiMTZhYThkYzYyMjg0ZGNiZmNlLmJpbmRQb3B1cChwb3B1cF9iNDQ3MmU0Y2ZhNmE0ZmRhOWNhNzYxNWVkYzYyZjZiNSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wYWMzOTQ3YzM3YjQ0ZDg1OGJhNzFmMDRiNzZiNTU2YiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcyNTg4MjI5OTk5OTk5NSwtNzkuMzE1NTcxNTk5OTk5OThdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzNmZmI4MTM5NTYxNDY4OGE4ZjA0YmJhZjU0MWU5YmUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMTg3NjdkZmMxMTBkNDJlODgwYTQ3NzgxODY2ZmU1ZTggPSAkKCc8ZGl2IGlkPSJodG1sXzE4NzY3ZGZjMTEwZDQyZTg4MGE0Nzc4MTg2NmZlNWU4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5WaWN0b3JpYSBWaWxsYWdlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jM2ZmYjgxMzk1NjE0Njg4YThmMDRiYmFmNTQxZTliZS5zZXRDb250ZW50KGh0bWxfMTg3NjdkZmMxMTBkNDJlODgwYTQ3NzgxODY2ZmU1ZTgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMGFjMzk0N2MzN2I0NGQ4NThiYTcxZjA0Yjc2YjU1NmIuYmluZFBvcHVwKHBvcHVwX2MzZmZiODEzOTU2MTQ2ODhhOGYwNGJiYWY1NDFlOWJlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzYyZDNkNTU2MGEzODQzODZiZDNkZjZlY2UxODVhMzFiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjU0MjU5OSwtNzkuMzYwNjM1OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zOWFhM2FlNzIyMTk0Yzg5YmZlZjRkYzNkMDQ2YjE1ZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mYjQwNzIwOWI5MjA0MjQ0OWJjYjg5NTcxNDA0NzU3YiA9ICQoJzxkaXYgaWQ9Imh0bWxfZmI0MDcyMDliOTIwNDI0NDliY2I4OTU3MTQwNDc1N2IiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJlZ2VudCBQYXJrIC8gSGFyYm91cmZyb250PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zOWFhM2FlNzIyMTk0Yzg5YmZlZjRkYzNkMDQ2YjE1ZS5zZXRDb250ZW50KGh0bWxfZmI0MDcyMDliOTIwNDI0NDliY2I4OTU3MTQwNDc1N2IpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNjJkM2Q1NTYwYTM4NDM4NmJkM2RmNmVjZTE4NWEzMWIuYmluZFBvcHVwKHBvcHVwXzM5YWEzYWU3MjIxOTRjODliZmVmNGRjM2QwNDZiMTVlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzRmNjU4Mzk2NjVmYjQzZTBhYzg0NTZmNGVjYmIwYjc3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzE4NTE3OTk5OTk5OTk2LC03OS40NjQ3NjMyOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zMGM3NmE5ZmYzZjY0MWYwYmY3MGYzOTlmM2FlNzhkZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hMTYyZDQ3MTdmZGM0NjFlODVlZjgyM2YyNGQ2NGRjOSA9ICQoJzxkaXYgaWQ9Imh0bWxfYTE2MmQ0NzE3ZmRjNDYxZTg1ZWY4MjNmMjRkNjRkYzkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxhd3JlbmNlIE1hbm9yIC8gTGF3cmVuY2UgSGVpZ2h0czwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzBjNzZhOWZmM2Y2NDFmMGJmNzBmMzk5ZjNhZTc4ZGQuc2V0Q29udGVudChodG1sX2ExNjJkNDcxN2ZkYzQ2MWU4NWVmODIzZjI0ZDY0ZGM5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzRmNjU4Mzk2NjVmYjQzZTBhYzg0NTZmNGVjYmIwYjc3LmJpbmRQb3B1cChwb3B1cF8zMGM3NmE5ZmYzZjY0MWYwYmY3MGYzOTlmM2FlNzhkZCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84MjQxMjgzOGY2ODA0M2Y3YWE0NmMxYjhiOTcwNjZiMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY2MjMwMTUsLTc5LjM4OTQ5MzhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfM2IzOWRlZGMzNGFlNGI5ZmI4YzAxNzM1YjMyYzVmZDEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNWVkNjI0ZTNjMDhkNDNlMGI1YjQ2YTE1YjljYWFkZDQgPSAkKCc8ZGl2IGlkPSJodG1sXzVlZDYyNGUzYzA4ZDQzZTBiNWI0NmExNWI5Y2FhZGQ0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5RdWVlbiYjMzk7cyBQYXJrIC8gT250YXJpbyBQcm92aW5jaWFsIEdvdmVybm1lbnQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzNiMzlkZWRjMzRhZTRiOWZiOGMwMTczNWIzMmM1ZmQxLnNldENvbnRlbnQoaHRtbF81ZWQ2MjRlM2MwOGQ0M2UwYjViNDZhMTViOWNhYWRkNCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84MjQxMjgzOGY2ODA0M2Y3YWE0NmMxYjhiOTcwNjZiMi5iaW5kUG9wdXAocG9wdXBfM2IzOWRlZGMzNGFlNGI5ZmI4YzAxNzM1YjMyYzVmZDEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMzNhMzY1YmJkN2ZhNDE4Njk4MmMzYzk5NmU2NDI5YjAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Njc4NTU2LC03OS41MzIyNDI0MDAwMDAwMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80NGNmODkyODZmNDk0ZTNiYWI0ZTdlY2U3MWZlY2JkYiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xNGUwNWE4NzA3ZDY0ODY3OTY1NzcwY2IwZTY3YzUwNyA9ICQoJzxkaXYgaWQ9Imh0bWxfMTRlMDVhODcwN2Q2NDg2Nzk2NTc3MGNiMGU2N2M1MDciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPklzbGluZ3RvbiBBdmVudWU8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzQ0Y2Y4OTI4NmY0OTRlM2JhYjRlN2VjZTcxZmVjYmRiLnNldENvbnRlbnQoaHRtbF8xNGUwNWE4NzA3ZDY0ODY3OTY1NzcwY2IwZTY3YzUwNyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zM2EzNjViYmQ3ZmE0MTg2OTgyYzNjOTk2ZTY0MjliMC5iaW5kUG9wdXAocG9wdXBfNDRjZjg5Mjg2ZjQ5NGUzYmFiNGU3ZWNlNzFmZWNiZGIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZGQyNTkwMzA4YjZmNDcyMWFkM2RlMGMzMDI0ZjU4NWYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My44MDY2ODYyOTk5OTk5OTYsLTc5LjE5NDM1MzQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzEyY2Q4Mzg0OGNkYzQ2NTRhNDg0NTk1N2RmMTUzMGQ5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2M3NjllZDA5NDQ2MzQyNTk4YjEyN2E2M2M3OTdmNjc0ID0gJCgnPGRpdiBpZD0iaHRtbF9jNzY5ZWQwOTQ0NjM0MjU5OGIxMjdhNjNjNzk3ZjY3NCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TWFsdmVybiAvIFJvdWdlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xMmNkODM4NDhjZGM0NjU0YTQ4NDU5NTdkZjE1MzBkOS5zZXRDb250ZW50KGh0bWxfYzc2OWVkMDk0NDYzNDI1OThiMTI3YTYzYzc5N2Y2NzQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZGQyNTkwMzA4YjZmNDcyMWFkM2RlMGMzMDI0ZjU4NWYuYmluZFBvcHVwKHBvcHVwXzEyY2Q4Mzg0OGNkYzQ2NTRhNDg0NTk1N2RmMTUzMGQ5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzcxM2FlY2E5OTAwNTQyNDQ5NzNkNWJjMjliNmRjMzg1ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzQ1OTA1Nzk5OTk5OTk2LC03OS4zNTIxODhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjljNTVkYWExMWJiNGU2ODk1ODNjOTYwYjczMzkwZTIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYWJhMDI4ZjIwOTRmNDAxZjk3YjY5YmZkMTZkNmIxMTUgPSAkKCc8ZGl2IGlkPSJodG1sX2FiYTAyOGYyMDk0ZjQwMWY5N2I2OWJmZDE2ZDZiMTE1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Eb24gTWlsbHM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzY5YzU1ZGFhMTFiYjRlNjg5NTgzYzk2MGI3MzM5MGUyLnNldENvbnRlbnQoaHRtbF9hYmEwMjhmMjA5NGY0MDFmOTdiNjliZmQxNmQ2YjExNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83MTNhZWNhOTkwMDU0MjQ0OTczZDViYzI5YjZkYzM4NS5iaW5kUG9wdXAocG9wdXBfNjljNTVkYWExMWJiNGU2ODk1ODNjOTYwYjczMzkwZTIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYmQ2MjMwOWU0MmNlNGQ4NDlhMDQxZTdlOWUxZDQ5OGMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MDYzOTcyLC03OS4zMDk5MzddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMGYxMjBjZjQ5YTkxNDE4MTlhMDZiZmUzMmEwNWYyMzkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDcyYjk3YmRmYTE0NDRkOTkxMGJhZWVlMTQzOGQ5YmUgPSAkKCc8ZGl2IGlkPSJodG1sX2Q3MmI5N2JkZmExNDQ0ZDk5MTBiYWVlZTE0MzhkOWJlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5QYXJrdmlldyBIaWxsIC8gV29vZGJpbmUgR2FyZGVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMGYxMjBjZjQ5YTkxNDE4MTlhMDZiZmUzMmEwNWYyMzkuc2V0Q29udGVudChodG1sX2Q3MmI5N2JkZmExNDQ0ZDk5MTBiYWVlZTE0MzhkOWJlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2JkNjIzMDllNDJjZTRkODQ5YTA0MWU3ZTllMWQ0OThjLmJpbmRQb3B1cChwb3B1cF8wZjEyMGNmNDlhOTE0MTgxOWEwNmJmZTMyYTA1ZjIzOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82ZWM1MGNjYjhlZmQ0MDJmYjE3YTRhYWJjN2ViMWVjMCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1NzE2MTgsLTc5LjM3ODkzNzA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzdlNjFiNGIwMDQwYzQ3YWI5NTcwNTFkMmNiYmM5ZDA0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzVkZThkNjJlZmQxOTRlOGE5YzYwOTE0MDgyZWE3NzY2ID0gJCgnPGRpdiBpZD0iaHRtbF81ZGU4ZDYyZWZkMTk0ZThhOWM2MDkxNDA4MmVhNzc2NiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+R2FyZGVuIERpc3RyaWN0LVJ5ZXJzb248L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzdlNjFiNGIwMDQwYzQ3YWI5NTcwNTFkMmNiYmM5ZDA0LnNldENvbnRlbnQoaHRtbF81ZGU4ZDYyZWZkMTk0ZThhOWM2MDkxNDA4MmVhNzc2Nik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82ZWM1MGNjYjhlZmQ0MDJmYjE3YTRhYWJjN2ViMWVjMC5iaW5kUG9wdXAocG9wdXBfN2U2MWI0YjAwNDBjNDdhYjk1NzA1MWQyY2JiYzlkMDQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYzA4YmQ4NGZhZWMyNDA0NWI5ZTAyZGFiM2IwODQ4M2YgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MDk1NzcsLTc5LjQ0NTA3MjU5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzRkYzMzNmJiOGY1NzRlYmNiMzllYTQxMmVjOWRiM2Q4ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2Y2ZjI1ZjU2Mzk2MDRmZmQ4ZGQxYzZlOWQyZjgyZDMzID0gJCgnPGRpdiBpZD0iaHRtbF9mNmYyNWY1NjM5NjA0ZmZkOGRkMWM2ZTlkMmY4MmQzMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+R2xlbmNhaXJuPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80ZGMzMzZiYjhmNTc0ZWJjYjM5ZWE0MTJlYzlkYjNkOC5zZXRDb250ZW50KGh0bWxfZjZmMjVmNTYzOTYwNGZmZDhkZDFjNmU5ZDJmODJkMzMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYzA4YmQ4NGZhZWMyNDA0NWI5ZTAyZGFiM2IwODQ4M2YuYmluZFBvcHVwKHBvcHVwXzRkYzMzNmJiOGY1NzRlYmNiMzllYTQxMmVjOWRiM2Q4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzJiMzZkNjViMGYzMzRjMGQ4NzU0ZmFhMGJhNjJhYzk2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUwOTQzMiwtNzkuNTU0NzI0NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNGNiNDg2Y2IyYjg3NGVjNWIwMzI5NmRiYjQyOWE3NzAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMmRlZjdmMDA0NTFhNGFiNWE1Njc1YTg3NGUyNjRkNjggPSAkKCc8ZGl2IGlkPSJodG1sXzJkZWY3ZjAwNDUxYTRhYjVhNTY3NWE4NzRlMjY0ZDY4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XZXN0IERlYW5lIFBhcmsgLyBQcmluY2VzcyBHYXJkZW5zIC8gTWFydGluIEdyb3ZlIC8gSXNsaW5ndG9uIC8gQ2xvdmVyZGFsZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNGNiNDg2Y2IyYjg3NGVjNWIwMzI5NmRiYjQyOWE3NzAuc2V0Q29udGVudChodG1sXzJkZWY3ZjAwNDUxYTRhYjVhNTY3NWE4NzRlMjY0ZDY4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzJiMzZkNjViMGYzMzRjMGQ4NzU0ZmFhMGJhNjJhYzk2LmJpbmRQb3B1cChwb3B1cF80Y2I0ODZjYjJiODc0ZWM1YjAzMjk2ZGJiNDI5YTc3MCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kZWU4ZTU0YjlhN2Q0MDg1YWJkYTc0NjkxZTViZTQ5OCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc4NDUzNTEsLTc5LjE2MDQ5NzA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzJmYjc3NjY4OGYwODQ4YmJiNjQzZmY0ZmMzOWFlMzU2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2MzNzUwN2UxYWVlNjQxMTk5MTE0MTNmNmY2ZDQyYjdhID0gJCgnPGRpdiBpZD0iaHRtbF9jMzc1MDdlMWFlZTY0MTE5OTExNDEzZjZmNmQ0MmI3YSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Um91Z2UgSGlsbCAvIFBvcnQgVW5pb24gLyBIaWdobGFuZCBDcmVlazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMmZiNzc2Njg4ZjA4NDhiYmI2NDNmZjRmYzM5YWUzNTYuc2V0Q29udGVudChodG1sX2MzNzUwN2UxYWVlNjQxMTk5MTE0MTNmNmY2ZDQyYjdhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2RlZThlNTRiOWE3ZDQwODVhYmRhNzQ2OTFlNWJlNDk4LmJpbmRQb3B1cChwb3B1cF8yZmI3NzY2ODhmMDg0OGJiYjY0M2ZmNGZjMzlhZTM1Nik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81YTQ4ZDAyMmVmNWI0NDMxYmQ2MGVhMGYzMDkyODk1ZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcyNTg5OTcwMDAwMDAxLC03OS4zNDA5MjNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYjRjZDAxOWEwNDA0NDdkNDlkYTdkMTNlMDM4ZjU5OTAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZTkwNTg0NTNjMWZiNGQ1Yjg4OTdmZmRmMDUyZjgwNzggPSAkKCc8ZGl2IGlkPSJodG1sX2U5MDU4NDUzYzFmYjRkNWI4ODk3ZmZkZjA1MmY4MDc4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Eb24gTWlsbHM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2I0Y2QwMTlhMDQwNDQ3ZDQ5ZGE3ZDEzZTAzOGY1OTkwLnNldENvbnRlbnQoaHRtbF9lOTA1ODQ1M2MxZmI0ZDViODg5N2ZmZGYwNTJmODA3OCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl81YTQ4ZDAyMmVmNWI0NDMxYmQ2MGVhMGYzMDkyODk1ZS5iaW5kUG9wdXAocG9wdXBfYjRjZDAxOWEwNDA0NDdkNDlkYTdkMTNlMDM4ZjU5OTApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNWRmMjUyNDU3NmExNGI0YWJiM2EzNDQ4MWExOWI3OTYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42OTUzNDM5MDAwMDAwMDUsLTc5LjMxODM4ODddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMmI2NjRlN2VhM2IxNGI2ZTllZGFlNGJiOWYwZjliNjUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfN2UzNTUwN2IxYTE4NGZiNWExZjFmZjFlMjljNWI3NmEgPSAkKCc8ZGl2IGlkPSJodG1sXzdlMzU1MDdiMWExODRmYjVhMWYxZmYxZTI5YzViNzZhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Xb29kYmluZSBIZWlnaHRzPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yYjY2NGU3ZWEzYjE0YjZlOWVkYWU0YmI5ZjBmOWI2NS5zZXRDb250ZW50KGh0bWxfN2UzNTUwN2IxYTE4NGZiNWExZjFmZjFlMjljNWI3NmEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNWRmMjUyNDU3NmExNGI0YWJiM2EzNDQ4MWExOWI3OTYuYmluZFBvcHVwKHBvcHVwXzJiNjY0ZTdlYTNiMTRiNmU5ZWRhZTRiYjlmMGY5YjY1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY5NzBkYjdhNjViZjRhOTZhYTQ0ODdkNjk3YWNlYTU0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUxNDkzOSwtNzkuMzc1NDE3OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jN2UyMzRjMzg3YWE0MWQ4YTA0MzllZjI1NGRkODQzNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mZGY2MzAyMTJmN2E0N2VjYjMyNGMyMjc2YmI4NjlkMiA9ICQoJzxkaXYgaWQ9Imh0bWxfZmRmNjMwMjEyZjdhNDdlY2IzMjRjMjI3NmJiODY5ZDIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlN0LiBKYW1lcyBUb3duPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jN2UyMzRjMzg3YWE0MWQ4YTA0MzllZjI1NGRkODQzNy5zZXRDb250ZW50KGh0bWxfZmRmNjMwMjEyZjdhNDdlY2IzMjRjMjI3NmJiODY5ZDIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNjk3MGRiN2E2NWJmNGE5NmFhNDQ4N2Q2OTdhY2VhNTQuYmluZFBvcHVwKHBvcHVwX2M3ZTIzNGMzODdhYTQxZDhhMDQzOWVmMjU0ZGQ4NDM3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQ5NTYyOTE5MTEzODRhNzdhZGVjOTJmNzI3ODcyYzE3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjkzNzgxMywtNzkuNDI4MTkxNDAwMDAwMDJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZWNjYTM1YWM2NWM4NGJiNGJiMzkwZjNkZjcxMmI4NTIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYTc1YWQzNjAyZDE2NDRlNjk2M2M2ODUxNzgyZmRjNjcgPSAkKCc8ZGl2IGlkPSJodG1sX2E3NWFkMzYwMmQxNjQ0ZTY5NjNjNjg1MTc4MmZkYzY3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IdW1ld29vZC1DZWRhcnZhbGU8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2VjY2EzNWFjNjVjODRiYjRiYjM5MGYzZGY3MTJiODUyLnNldENvbnRlbnQoaHRtbF9hNzVhZDM2MDJkMTY0NGU2OTYzYzY4NTE3ODJmZGM2Nyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80OTU2MjkxOTExMzg0YTc3YWRlYzkyZjcyNzg3MmMxNy5iaW5kUG9wdXAocG9wdXBfZWNjYTM1YWM2NWM4NGJiNGJiMzkwZjNkZjcxMmI4NTIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjUzNDIxMjVlNzZhNGE5YzhlZjFhNGQ5YzlmYWMwZmQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDM1MTUyLC03OS41NzcyMDA3OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9hMTA1NTU4MjQ5NTU0MWE1YTQ3ZmI3MmEzZTczYzhlZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xZTljNTgxYzY4YTA0ZDQzODM4NWJkYmNiYWFmMTYwMyA9ICQoJzxkaXYgaWQ9Imh0bWxfMWU5YzU4MWM2OGEwNGQ0MzgzODViZGJjYmFhZjE2MDMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkVyaW5nYXRlIC8gQmxvb3JkYWxlIEdhcmRlbnMgLyBPbGQgQnVybmhhbXRob3JwZSAvIE1hcmtsYW5kIFdvb2Q8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2ExMDU1NTgyNDk1NTQxYTVhNDdmYjcyYTNlNzNjOGVmLnNldENvbnRlbnQoaHRtbF8xZTljNTgxYzY4YTA0ZDQzODM4NWJkYmNiYWFmMTYwMyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mNTM0MjEyNWU3NmE0YTljOGVmMWE0ZDljOWZhYzBmZC5iaW5kUG9wdXAocG9wdXBfYTEwNTU1ODI0OTU1NDFhNWE0N2ZiNzJhM2U3M2M4ZWYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOTVhMTRiYTIwY2E4NGIwYmJkZjYwZmQ3MDA0ZDFkZWEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NjM1NzI2LC03OS4xODg3MTE1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzdhODRhMzNhYzVkNDRkZmQ4ZjU3MDAyOWIxZWFmYmZmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzk1NGM1NjI5Y2VlNjQ0MDNhMjUxYzcwYjJiMTY4YmIyID0gJCgnPGRpdiBpZD0iaHRtbF85NTRjNTYyOWNlZTY0NDAzYTI1MWM3MGIyYjE2OGJiMiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+R3VpbGR3b29kIC8gTW9ybmluZ3NpZGUgLyBXZXN0IEhpbGw8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzdhODRhMzNhYzVkNDRkZmQ4ZjU3MDAyOWIxZWFmYmZmLnNldENvbnRlbnQoaHRtbF85NTRjNTYyOWNlZTY0NDAzYTI1MWM3MGIyYjE2OGJiMik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85NWExNGJhMjBjYTg0YjBiYmRmNjBmZDcwMDRkMWRlYS5iaW5kUG9wdXAocG9wdXBfN2E4NGEzM2FjNWQ0NGRmZDhmNTcwMDI5YjFlYWZiZmYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMGI5MzlkMmZhM2E5NDcyZGE0YzdlM2UxZDgxNzlkYzYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NzYzNTczOTk5OTk5OSwtNzkuMjkzMDMxMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zZjFmYmRmYTViZWI0NjA0OWQwZjY3N2U0YWUxNjI5MCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mMWM5YzhiNjM1NDY0MDg1OTQxNDk0YmY3NmQ4ZTkxZiA9ICQoJzxkaXYgaWQ9Imh0bWxfZjFjOWM4YjYzNTQ2NDA4NTk0MTQ5NGJmNzZkOGU5MWYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlRoZSBCZWFjaGVzPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zZjFmYmRmYTViZWI0NjA0OWQwZjY3N2U0YWUxNjI5MC5zZXRDb250ZW50KGh0bWxfZjFjOWM4YjYzNTQ2NDA4NTk0MTQ5NGJmNzZkOGU5MWYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMGI5MzlkMmZhM2E5NDcyZGE0YzdlM2UxZDgxNzlkYzYuYmluZFBvcHVwKHBvcHVwXzNmMWZiZGZhNWJlYjQ2MDQ5ZDBmNjc3ZTRhZTE2MjkwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2E4NGMyM2I0Y2FmZDRhMjliZmIzNDY1ZGRmNzg4NDIzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjQ0NzcwNzk5OTk5OTk2LC03OS4zNzMzMDY0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2I0NDUwNmI0YTc0YzQ3YTdhODllOWNiNWI1YjVhN2MyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzBmNmIyNGQ1MDc1NjQ5ZTY4MDQ3MzQ3MmFkNGVjNmE2ID0gJCgnPGRpdiBpZD0iaHRtbF8wZjZiMjRkNTA3NTY0OWU2ODA0NzM0NzJhZDRlYzZhNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmVyY3p5IFBhcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2I0NDUwNmI0YTc0YzQ3YTdhODllOWNiNWI1YjVhN2MyLnNldENvbnRlbnQoaHRtbF8wZjZiMjRkNTA3NTY0OWU2ODA0NzM0NzJhZDRlYzZhNik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hODRjMjNiNGNhZmQ0YTI5YmZiMzQ2NWRkZjc4ODQyMy5iaW5kUG9wdXAocG9wdXBfYjQ0NTA2YjRhNzRjNDdhN2E4OWU5Y2I1YjViNWE3YzIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMjk4Y2NlY2FjNjliNGQxNjgzMWRiY2JjNjlhMjVlYmYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42ODkwMjU2LC03OS40NTM1MTJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNWM1OWY2ZGI2Yjk3NGUxZDg0NTUxOTY4NjUzMDI4OWEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYmIyYjMyMTE5ZTI2NGM1MThlOTk3M2M1Mzg4OWVjN2QgPSAkKCc8ZGl2IGlkPSJodG1sX2JiMmIzMjExOWUyNjRjNTE4ZTk5NzNjNTM4ODllYzdkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DYWxlZG9uaWEtRmFpcmJhbmtzPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81YzU5ZjZkYjZiOTc0ZTFkODQ1NTE5Njg2NTMwMjg5YS5zZXRDb250ZW50KGh0bWxfYmIyYjMyMTE5ZTI2NGM1MThlOTk3M2M1Mzg4OWVjN2QpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjk4Y2NlY2FjNjliNGQxNjgzMWRiY2JjNjlhMjVlYmYuYmluZFBvcHVwKHBvcHVwXzVjNTlmNmRiNmI5NzRlMWQ4NDU1MTk2ODY1MzAyODlhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzA5MjA1YzBkMjNjZTQ1MTVhYTU3Njg5YjAyODI2MzRjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzcwOTkyMSwtNzkuMjE2OTE3NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYTY0Y2I3NmFhOTZkNDhmZWJlMDkzZDI3Y2Q3NGE1ZDkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMDcyNTMxMzJkNmIzNDVlMGJiM2RmYjMyM2M0ODBhYmUgPSAkKCc8ZGl2IGlkPSJodG1sXzA3MjUzMTMyZDZiMzQ1ZTBiYjNkZmIzMjNjNDgwYWJlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Xb2J1cm48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2E2NGNiNzZhYTk2ZDQ4ZmViZTA5M2QyN2NkNzRhNWQ5LnNldENvbnRlbnQoaHRtbF8wNzI1MzEzMmQ2YjM0NWUwYmIzZGZiMzIzYzQ4MGFiZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wOTIwNWMwZDIzY2U0NTE1YWE1NzY4OWIwMjgyNjM0Yy5iaW5kUG9wdXAocG9wdXBfYTY0Y2I3NmFhOTZkNDhmZWJlMDkzZDI3Y2Q3NGE1ZDkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTA0OWNlZGQxMDU0NDQ5ZWIzMDJkMDNlNDlmZGYxN2EgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MDkwNjA0LC03OS4zNjM0NTE3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2EzMGYwZmRiY2I2MDRkZGFhNGIyMjNjZmNjZTJlZThkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2Y0ZmIxYTJkNWJjZjQyYmQ5YjY2MzRhZjQzYzMwYWI1ID0gJCgnPGRpdiBpZD0iaHRtbF9mNGZiMWEyZDViY2Y0MmJkOWI2NjM0YWY0M2MzMGFiNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TGVhc2lkZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYTMwZjBmZGJjYjYwNGRkYWE0YjIyM2NmY2NlMmVlOGQuc2V0Q29udGVudChodG1sX2Y0ZmIxYTJkNWJjZjQyYmQ5YjY2MzRhZjQzYzMwYWI1KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzUwNDljZWRkMTA1NDQ0OWViMzAyZDAzZTQ5ZmRmMTdhLmJpbmRQb3B1cChwb3B1cF9hMzBmMGZkYmNiNjA0ZGRhYTRiMjIzY2ZjY2UyZWU4ZCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81YzZmMGRiNzAxZDU0MjNiODA3NGNkZTRlZmEwYTMzNiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1Nzk1MjQsLTc5LjM4NzM4MjZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzQ2YjkwNGQ1N2ZlNDMxNWExOTliZTE3MDZiZWM0ODcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYTBlZjhmOWNhNWY3NGYyNjk5OTdkOTgzMmEwNzEwMTUgPSAkKCc8ZGl2IGlkPSJodG1sX2EwZWY4ZjljYTVmNzRmMjY5OTk3ZDk4MzJhMDcxMDE1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DZW50cmFsIEJheSBTdHJlZXQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2M0NmI5MDRkNTdmZTQzMTVhMTk5YmUxNzA2YmVjNDg3LnNldENvbnRlbnQoaHRtbF9hMGVmOGY5Y2E1Zjc0ZjI2OTk5N2Q5ODMyYTA3MTAxNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl81YzZmMGRiNzAxZDU0MjNiODA3NGNkZTRlZmEwYTMzNi5iaW5kUG9wdXAocG9wdXBfYzQ2YjkwNGQ1N2ZlNDMxNWExOTliZTE3MDZiZWM0ODcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjA4YTJiYWJiYWZmNDVmNGE4ZTBiNmIxZTI2NjJmYjEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Njk1NDIsLTc5LjQyMjU2MzddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZDAwMDFkODVjYTliNGEwNzgzM2E1ZTgxZDdkYmMyNjQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZWI3N2E4MzlkMjcxNDNlODliNzI5ZmZiMmNjNWI5ZDkgPSAkKCc8ZGl2IGlkPSJodG1sX2ViNzdhODM5ZDI3MTQzZTg5YjcyOWZmYjJjYzViOWQ5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DaHJpc3RpZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZDAwMDFkODVjYTliNGEwNzgzM2E1ZTgxZDdkYmMyNjQuc2V0Q29udGVudChodG1sX2ViNzdhODM5ZDI3MTQzZTg5YjcyOWZmYjJjYzViOWQ5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2YwOGEyYmFiYmFmZjQ1ZjRhOGUwYjZiMWUyNjYyZmIxLmJpbmRQb3B1cChwb3B1cF9kMDAwMWQ4NWNhOWI0YTA3ODMzYTVlODFkN2RiYzI2NCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83OGRjMTg3NzY4ZmM0MWNmYmJjMTRkNzk3OWUxODA4MCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc3MzEzNiwtNzkuMjM5NDc2MDk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzQwNTMxMWQxZmRhNDYxNmE3MTQ2OGE5OTMxMGU2NjEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYWZhZGIxNmFmOTBjNDkxODhjZDdhNjM3MjA4N2NhNTggPSAkKCc8ZGl2IGlkPSJodG1sX2FmYWRiMTZhZjkwYzQ5MTg4Y2Q3YTYzNzIwODdjYTU4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DZWRhcmJyYWU8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2M0MDUzMTFkMWZkYTQ2MTZhNzE0NjhhOTkzMTBlNjYxLnNldENvbnRlbnQoaHRtbF9hZmFkYjE2YWY5MGM0OTE4OGNkN2E2MzcyMDg3Y2E1OCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83OGRjMTg3NzY4ZmM0MWNmYmJjMTRkNzk3OWUxODA4MC5iaW5kUG9wdXAocG9wdXBfYzQwNTMxMWQxZmRhNDYxNmE3MTQ2OGE5OTMxMGU2NjEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMGEzZDU3ZjdjNzc2NDFmZmEyMWNhZGYwZGI4Y2EzYWMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My44MDM3NjIyLC03OS4zNjM0NTE3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2MxMTA1M2VjMWNhZDQzYjE4ODlmZjA2NGM4NzU1NTY0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2JmM2RlZTE5MjlmYTQ3MDM5ZDJlMWZlMjVlMzIzM2QxID0gJCgnPGRpdiBpZD0iaHRtbF9iZjNkZWUxOTI5ZmE0NzAzOWQyZTFmZTI1ZTMyMzNkMSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SGlsbGNyZXN0IFZpbGxhZ2U8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2MxMTA1M2VjMWNhZDQzYjE4ODlmZjA2NGM4NzU1NTY0LnNldENvbnRlbnQoaHRtbF9iZjNkZWUxOTI5ZmE0NzAzOWQyZTFmZTI1ZTMyMzNkMSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wYTNkNTdmN2M3NzY0MWZmYTIxY2FkZjBkYjhjYTNhYy5iaW5kUG9wdXAocG9wdXBfYzExMDUzZWMxY2FkNDNiMTg4OWZmMDY0Yzg3NTU1NjQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOGQ0ZjQ4ZTcwMDFkNGU1YTg0NTkxNzcxMGQzMjI3ZjEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NTQzMjgzLC03OS40NDIyNTkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2QzODQ4YzU4YjNlZTQ2YTQ4ZTUxMGZhNjIyMTE1N2IyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzViNGMxMGU0Njg1NDRhMmVhNmY2NmU4NTU5NzU0NjgyID0gJCgnPGRpdiBpZD0iaHRtbF81YjRjMTBlNDY4NTQ0YTJlYTZmNjZlODU1OTc1NDY4MiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmF0aHVyc3QgTWFub3IgLyBXaWxzb24gSGVpZ2h0cyAvIERvd25zdmlldyBOb3J0aDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZDM4NDhjNThiM2VlNDZhNDhlNTEwZmE2MjIxMTU3YjIuc2V0Q29udGVudChodG1sXzViNGMxMGU0Njg1NDRhMmVhNmY2NmU4NTU5NzU0NjgyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzhkNGY0OGU3MDAxZDRlNWE4NDU5MTc3MTBkMzIyN2YxLmJpbmRQb3B1cChwb3B1cF9kMzg0OGM1OGIzZWU0NmE0OGU1MTBmYTYyMjExNTdiMik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iMTdjNDE2NjRmOTA0ZTliOTM3YmMzZmMwODU4MTJhMSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcwNTM2ODksLTc5LjM0OTM3MTkwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzMxNjkwOWQxOGU3MTQ5YzA5ZTIzNDgyY2I4OTUxZGQ2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2IxNWYxNjkxZGNhMjQ3ODJiMjM3ZmMzMzMwNjNkZmIzID0gJCgnPGRpdiBpZD0iaHRtbF9iMTVmMTY5MWRjYTI0NzgyYjIzN2ZjMzMzMDYzZGZiMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VGhvcm5jbGlmZmUgUGFyazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzE2OTA5ZDE4ZTcxNDljMDllMjM0ODJjYjg5NTFkZDYuc2V0Q29udGVudChodG1sX2IxNWYxNjkxZGNhMjQ3ODJiMjM3ZmMzMzMwNjNkZmIzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2IxN2M0MTY2NGY5MDRlOWI5MzdiYzNmYzA4NTgxMmExLmJpbmRQb3B1cChwb3B1cF8zMTY5MDlkMThlNzE0OWMwOWUyMzQ4MmNiODk1MWRkNik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lZDJkNmMzYzAwNWU0YTFkYjE2ODFhNDVjODczNjc2NyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1MDU3MTIwMDAwMDAxLC03OS4zODQ1Njc1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzk3N2RlM2FiOGUxMTRkM2I5MGUyNzMwNmNlYTMyYzFkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2ViMWQzZmU3NDk3OTQ5YzFhNjUwMDRkMzNjZWRlMTJlID0gJCgnPGRpdiBpZD0iaHRtbF9lYjFkM2ZlNzQ5Nzk0OWMxYTY1MDA0ZDMzY2VkZTEyZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UmljaG1vbmQgLyBBZGVsYWlkZSAvIEtpbmc8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzk3N2RlM2FiOGUxMTRkM2I5MGUyNzMwNmNlYTMyYzFkLnNldENvbnRlbnQoaHRtbF9lYjFkM2ZlNzQ5Nzk0OWMxYTY1MDA0ZDMzY2VkZTEyZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9lZDJkNmMzYzAwNWU0YTFkYjE2ODFhNDVjODczNjc2Ny5iaW5kUG9wdXAocG9wdXBfOTc3ZGUzYWI4ZTExNGQzYjkwZTI3MzA2Y2VhMzJjMWQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZWE1MzIyNzFkN2MyNGU5ZWFjZGZkY2QzZDhkMzdiZGMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NjkwMDUxMDAwMDAwMSwtNzkuNDQyMjU5M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84M2EwZWQ2YjI3MTQ0MDdkOGMyN2U1NjEyNTgxNTlhNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81MDZjMDQ5ODEwMzA0NWRkYTRlZGQ5ZTljMzViOTgwNyA9ICQoJzxkaXYgaWQ9Imh0bWxfNTA2YzA0OTgxMDMwNDVkZGE0ZWRkOWU5YzM1Yjk4MDciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkR1ZmZlcmluIC8gRG92ZXJjb3VydCBWaWxsYWdlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84M2EwZWQ2YjI3MTQ0MDdkOGMyN2U1NjEyNTgxNTlhNC5zZXRDb250ZW50KGh0bWxfNTA2YzA0OTgxMDMwNDVkZGE0ZWRkOWU5YzM1Yjk4MDcpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZWE1MzIyNzFkN2MyNGU5ZWFjZGZkY2QzZDhkMzdiZGMuYmluZFBvcHVwKHBvcHVwXzgzYTBlZDZiMjcxNDQwN2Q4YzI3ZTU2MTI1ODE1OWE0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzdlYzUxN2Y2MmM5ZTRiM2RhZDdkNGY4NjAzYzMxOTNlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzQ0NzM0MiwtNzkuMjM5NDc2MDk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMjZjNTQwOTAyNjU4NGQ1MGE3MmU4MWY3YjliNmQ4Y2MgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYWY3YTYwMzA2M2YzNGYwODk5YzllOTczZDM1MDQzNmMgPSAkKCc8ZGl2IGlkPSJodG1sX2FmN2E2MDMwNjNmMzRmMDg5OWM5ZTk3M2QzNTA0MzZjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TY2FyYm9yb3VnaCBWaWxsYWdlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yNmM1NDA5MDI2NTg0ZDUwYTcyZTgxZjdiOWI2ZDhjYy5zZXRDb250ZW50KGh0bWxfYWY3YTYwMzA2M2YzNGYwODk5YzllOTczZDM1MDQzNmMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfN2VjNTE3ZjYyYzllNGIzZGFkN2Q0Zjg2MDNjMzE5M2UuYmluZFBvcHVwKHBvcHVwXzI2YzU0MDkwMjY1ODRkNTBhNzJlODFmN2I5YjZkOGNjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I3MDJlZDRlYjFlZTRkYjc4NDg3ODgwMmMwOTk5ZDU4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzc4NTE3NSwtNzkuMzQ2NTU1N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83NzczNzY4MjQ0OTQ0ZmZhYmFkZmU5ZmQ1ZDNjZWYzMCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zOTVmNmJiOWE5MzI0YTVkYWNkNmNkZjJhOWViYzA1YiA9ICQoJzxkaXYgaWQ9Imh0bWxfMzk1ZjZiYjlhOTMyNGE1ZGFjZDZjZGYyYTllYmMwNWIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZhaXJ2aWV3IC8gSGVucnkgRmFybSAvIE9yaW9sZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNzc3Mzc2ODI0NDk0NGZmYWJhZGZlOWZkNWQzY2VmMzAuc2V0Q29udGVudChodG1sXzM5NWY2YmI5YTkzMjRhNWRhY2Q2Y2RmMmE5ZWJjMDViKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2I3MDJlZDRlYjFlZTRkYjc4NDg3ODgwMmMwOTk5ZDU4LmJpbmRQb3B1cChwb3B1cF83NzczNzY4MjQ0OTQ0ZmZhYmFkZmU5ZmQ1ZDNjZWYzMCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jZjU1NjJkOWFlZjg0ZmQ1YTZkZWEwYzVjNzkxN2FlNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc2Nzk4MDMsLTc5LjQ4NzI2MTkwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2Q5ZDI0YWI4ODI5ODQzZjdiNWY2ZWZlODhhZTIzZWU0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzAxOGZhZTM5ODcwOTQyODZiZTg4MmY1NmIyZmVjMDRjID0gJCgnPGRpdiBpZD0iaHRtbF8wMThmYWUzOTg3MDk0Mjg2YmU4ODJmNTZiMmZlYzA0YyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Tm9ydGh3b29kIFBhcmsgLyBZb3JrIFVuaXZlcnNpdHk8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2Q5ZDI0YWI4ODI5ODQzZjdiNWY2ZWZlODhhZTIzZWU0LnNldENvbnRlbnQoaHRtbF8wMThmYWUzOTg3MDk0Mjg2YmU4ODJmNTZiMmZlYzA0Yyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jZjU1NjJkOWFlZjg0ZmQ1YTZkZWEwYzVjNzkxN2FlNy5iaW5kUG9wdXAocG9wdXBfZDlkMjRhYjg4Mjk4NDNmN2I1ZjZlZmU4OGFlMjNlZTQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMmZjMjE2ZTQ4ODNiNDAxNDkyOWJmZmU4MDc4ZGU2MTEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42ODUzNDcsLTc5LjMzODEwNjVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNWMxYjc2YjA4OWQwNDkzMDg0MGY4ZDI0NzE0ZjQ2ODMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYjNhZDdhMDFjNmI0NGQxY2IxNTYwZTRlNGJjODBiM2YgPSAkKCc8ZGl2IGlkPSJodG1sX2IzYWQ3YTAxYzZiNDRkMWNiMTU2MGU0ZTRiYzgwYjNmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FYXN0IFRvcm9udG88L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzVjMWI3NmIwODlkMDQ5MzA4NDBmOGQyNDcxNGY0NjgzLnNldENvbnRlbnQoaHRtbF9iM2FkN2EwMWM2YjQ0ZDFjYjE1NjBlNGU0YmM4MGIzZik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yZmMyMTZlNDg4M2I0MDE0OTI5YmZmZTgwNzhkZTYxMS5iaW5kUG9wdXAocG9wdXBfNWMxYjc2YjA4OWQwNDkzMDg0MGY4ZDI0NzE0ZjQ2ODMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNjhjYzQ3MWMxZjI5NDAzZGE4NmYwNjAxNjA5NTNjMjEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDA4MTU3LC03OS4zODE3NTIyOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iZDYyN2RkNjM2NDA0MjQ1YTQ3ZTdmNWYwY2JmYjAyZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lMGYzNmMyMzlkMGI0ZTEzYmNlNDhhMWM5MzRkN2M4OCA9ICQoJzxkaXYgaWQ9Imh0bWxfZTBmMzZjMjM5ZDBiNGUxM2JjZTQ4YTFjOTM0ZDdjODgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhhcmJvdXJmcm9udCBFYXN0IC8gVW5pb24gU3RhdGlvbiAvIFRvcm9udG8gSXNsYW5kczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYmQ2MjdkZDYzNjQwNDI0NWE0N2U3ZjVmMGNiZmIwMmQuc2V0Q29udGVudChodG1sX2UwZjM2YzIzOWQwYjRlMTNiY2U0OGExYzkzNGQ3Yzg4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzY4Y2M0NzFjMWYyOTQwM2RhODZmMDYwMTYwOTUzYzIxLmJpbmRQb3B1cChwb3B1cF9iZDYyN2RkNjM2NDA0MjQ1YTQ3ZTdmNWYwY2JmYjAyZCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83MDlkOWM3YmNhNzQ0NGFkOTFlOWI1NzBiOGYwYTdkOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY0NzkyNjcwMDAwMDAwNiwtNzkuNDE5NzQ5N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83ZDJhZDBhODkxMzA0NzNkOGI2MmVhMTg4ZDYzOGU4YiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jNTMwY2Y4NzBhMTA0YTg1YTZiNDI1MjdkZDNiYTBjNSA9ICQoJzxkaXYgaWQ9Imh0bWxfYzUzMGNmODcwYTEwNGE4NWE2YjQyNTI3ZGQzYmEwYzUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxpdHRsZSBQb3J0dWdhbCAvIFRyaW5pdHk8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzdkMmFkMGE4OTEzMDQ3M2Q4YjYyZWExODhkNjM4ZThiLnNldENvbnRlbnQoaHRtbF9jNTMwY2Y4NzBhMTA0YTg1YTZiNDI1MjdkZDNiYTBjNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83MDlkOWM3YmNhNzQ0NGFkOTFlOWI1NzBiOGYwYTdkOS5iaW5kUG9wdXAocG9wdXBfN2QyYWQwYTg5MTMwNDczZDhiNjJlYTE4OGQ2MzhlOGIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMThkNGQ3M2VkZDUzNDAzZmE5NjYxYzBjNzA1MjA4MWQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43Mjc5MjkyLC03OS4yNjIwMjk0MDAwMDAwMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xZjEzMjFjM2Y3YzU0ODcwOGQ3NTg1OWFhZWU4YzBlZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83OWU0ZGMwYmYwMmQ0NmI0ODQwNDRhZTNkZjgyYjM4NyA9ICQoJzxkaXYgaWQ9Imh0bWxfNzllNGRjMGJmMDJkNDZiNDg0MDQ0YWUzZGY4MmIzODciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPktlbm5lZHkgUGFyayAvIElvbnZpZXcgLyBFYXN0IEJpcmNobW91bnQgUGFyazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMWYxMzIxYzNmN2M1NDg3MDhkNzU4NTlhYWVlOGMwZWUuc2V0Q29udGVudChodG1sXzc5ZTRkYzBiZjAyZDQ2YjQ4NDA0NGFlM2RmODJiMzg3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzE4ZDRkNzNlZGQ1MzQwM2ZhOTY2MWMwYzcwNTIwODFkLmJpbmRQb3B1cChwb3B1cF8xZjEzMjFjM2Y3YzU0ODcwOGQ3NTg1OWFhZWU4YzBlZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81OWRmNDk3OWJkZmI0Yjk0OWJjMzg5Yjc1NTIwNjA3MyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc4Njk0NzMsLTc5LjM4NTk3NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82N2YwM2ZmOTBmNGM0NWIzYWQwYTJkMzdjMzNlNzY1MCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81Mzg3MWQzYmRlZjA0NDNkOTY1ZDgxYzU3OTNjMjRiZiA9ICQoJzxkaXYgaWQ9Imh0bWxfNTM4NzFkM2JkZWYwNDQzZDk2NWQ4MWM1NzkzYzI0YmYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJheXZpZXcgVmlsbGFnZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNjdmMDNmZjkwZjRjNDViM2FkMGEyZDM3YzMzZTc2NTAuc2V0Q29udGVudChodG1sXzUzODcxZDNiZGVmMDQ0M2Q5NjVkODFjNTc5M2MyNGJmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU5ZGY0OTc5YmRmYjRiOTQ5YmMzODliNzU1MjA2MDczLmJpbmRQb3B1cChwb3B1cF82N2YwM2ZmOTBmNGM0NWIzYWQwYTJkMzdjMzNlNzY1MCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wMDkzMDM0Y2NiNzM0Njg5YmY2ZGZhOWI3YjAxMmI0NyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjczNzQ3MzIwMDAwMDAwNCwtNzkuNDY0NzYzMjk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYTg2NGI3NjA5MGVjNDVmMGE2MDk2NmExYzA2NTg0YmYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZTFhZWU0ZGM4YzFiNDM0ZGI1ZGU5YzhiMjExNTM3OWYgPSAkKCc8ZGl2IGlkPSJodG1sX2UxYWVlNGRjOGMxYjQzNGRiNWRlOWM4YjIxMTUzNzlmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Eb3duc3ZpZXc8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2E4NjRiNzYwOTBlYzQ1ZjBhNjA5NjZhMWMwNjU4NGJmLnNldENvbnRlbnQoaHRtbF9lMWFlZTRkYzhjMWI0MzRkYjVkZTljOGIyMTE1Mzc5Zik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wMDkzMDM0Y2NiNzM0Njg5YmY2ZGZhOWI3YjAxMmI0Ny5iaW5kUG9wdXAocG9wdXBfYTg2NGI3NjA5MGVjNDVmMGE2MDk2NmExYzA2NTg0YmYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMmU0ZDQ5OTQ4YzYwNGI5ODkwYWJlOWVjNDI3MzQ5MzYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Nzk1NTcxLC03OS4zNTIxODhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZWExODFkYzEwNzY2NDk4OGIwNzYxZjY0ZTYzZTM4MjUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZWJlMDc1ODNjZTJkNDA5Mzg3OGI0M2ZiZWMwMmJjZWEgPSAkKCc8ZGl2IGlkPSJodG1sX2ViZTA3NTgzY2UyZDQwOTM4NzhiNDNmYmVjMDJiY2VhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UaGUgRGFuZm9ydGggV2VzdCAvIFJpdmVyZGFsZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZWExODFkYzEwNzY2NDk4OGIwNzYxZjY0ZTYzZTM4MjUuc2V0Q29udGVudChodG1sX2ViZTA3NTgzY2UyZDQwOTM4NzhiNDNmYmVjMDJiY2VhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzJlNGQ0OTk0OGM2MDRiOTg5MGFiZTllYzQyNzM0OTM2LmJpbmRQb3B1cChwb3B1cF9lYTE4MWRjMTA3NjY0OTg4YjA3NjFmNjRlNjNlMzgyNSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83YjQxMWQ5NmUzZTU0YTBjYjg2NWY1NzBhN2VhNzg4YyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY0NzE3NjgsLTc5LjM4MTU3NjQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzFmNzNlOTNjMzc0MDQ2ZjU5M2UzNDIwY2Y4NGFkYmU1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2YxZDVmZDZkZWQ2NDQ5MDE4MmY4MjE4OGQwNTYyZmRjID0gJCgnPGRpdiBpZD0iaHRtbF9mMWQ1ZmQ2ZGVkNjQ0OTAxODJmODIxODhkMDU2MmZkYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VG9yb250byBEb21pbmlvbiBDZW50cmUgLyBEZXNpZ24gRXhjaGFuZ2U8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzFmNzNlOTNjMzc0MDQ2ZjU5M2UzNDIwY2Y4NGFkYmU1LnNldENvbnRlbnQoaHRtbF9mMWQ1ZmQ2ZGVkNjQ0OTAxODJmODIxODhkMDU2MmZkYyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83YjQxMWQ5NmUzZTU0YTBjYjg2NWY1NzBhN2VhNzg4Yy5iaW5kUG9wdXAocG9wdXBfMWY3M2U5M2MzNzQwNDZmNTkzZTM0MjBjZjg0YWRiZTUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNmZkYzY3YzA3MTNiNDcyMDgzYjQ0YjM3ZTVjZjI0MWIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42MzY4NDcyLC03OS40MjgxOTE0MDAwMDAwMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xYmMzOTZmYzhmZDA0NWQ5ODBjNGVkN2Y5Mjc0YTZjMCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81NDliY2MyMjViNmQ0ZmEzOWU4NGU2MzAwN2E5MzdlNSA9ICQoJzxkaXYgaWQ9Imh0bWxfNTQ5YmNjMjI1YjZkNGZhMzllODRlNjMwMDdhOTM3ZTUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJyb2NrdG9uIC8gUGFya2RhbGUgVmlsbGFnZSAvIEV4aGliaXRpb24gUGxhY2U8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzFiYzM5NmZjOGZkMDQ1ZDk4MGM0ZWQ3ZjkyNzRhNmMwLnNldENvbnRlbnQoaHRtbF81NDliY2MyMjViNmQ0ZmEzOWU4NGU2MzAwN2E5MzdlNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82ZmRjNjdjMDcxM2I0NzIwODNiNDRiMzdlNWNmMjQxYi5iaW5kUG9wdXAocG9wdXBfMWJjMzk2ZmM4ZmQwNDVkOTgwYzRlZDdmOTI3NGE2YzApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZGQzZjI5NjhhNzc4NGQxZThlNDQwMjBhMzYzM2RjOGMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MTExMTE3MDAwMDAwMDQsLTc5LjI4NDU3NzJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNTRlNWE0Nzg2NTNmNDI4NTk2ZDE1Y2RkZmZhNzNiY2MgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfY2E3MmNiYzRjZTkwNGJlY2EwYzcyNTM5NjEyMTRjNTYgPSAkKCc8ZGl2IGlkPSJodG1sX2NhNzJjYmM0Y2U5MDRiZWNhMGM3MjUzOTYxMjE0YzU2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Hb2xkZW4gTWlsZSAvIENsYWlybGVhIC8gT2FrcmlkZ2U8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzU0ZTVhNDc4NjUzZjQyODU5NmQxNWNkZGZmYTczYmNjLnNldENvbnRlbnQoaHRtbF9jYTcyY2JjNGNlOTA0YmVjYTBjNzI1Mzk2MTIxNGM1Nik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9kZDNmMjk2OGE3Nzg0ZDFlOGU0NDAyMGEzNjMzZGM4Yy5iaW5kUG9wdXAocG9wdXBfNTRlNWE0Nzg2NTNmNDI4NTk2ZDE1Y2RkZmZhNzNiY2MpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjlhNTAyODFiOTBkNGRlNjgxNWI4ZDI4YmJmNTUwOTQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NTc0OTAyLC03OS4zNzQ3MTQwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kM2E2NWE2NjczZWU0YmY3YWY5NTc5YjIwYWVhMDYyZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lY2IzNWYzZTQ1ZTc0NWJiYjQxNzRiNGI1NzA5ZmVjOCA9ICQoJzxkaXYgaWQ9Imh0bWxfZWNiMzVmM2U0NWU3NDViYmI0MTc0YjRiNTcwOWZlYzgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPllvcmsgTWlsbHMgLyBTaWx2ZXIgSGlsbHM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2QzYTY1YTY2NzNlZTRiZjdhZjk1NzliMjBhZWEwNjJlLnNldENvbnRlbnQoaHRtbF9lY2IzNWYzZTQ1ZTc0NWJiYjQxNzRiNGI1NzA5ZmVjOCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mOWE1MDI4MWI5MGQ0ZGU2ODE1YjhkMjhiYmY1NTA5NC5iaW5kUG9wdXAocG9wdXBfZDNhNjVhNjY3M2VlNGJmN2FmOTU3OWIyMGFlYTA2MmUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODZjZjY1Yjc3MmMzNDZjOThmMzdiM2JlNTQ3MzQ3ODYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MzkwMTQ2LC03OS41MDY5NDM2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2NjNWEwZmJkMWY0ZDQ5ZTdiYjc5NTY4Y2Y4MDQzYTY3ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzU5OWRmZmE0ODkyZDRiN2FhMTUzYjIzNWI0YWE0NjU1ID0gJCgnPGRpdiBpZD0iaHRtbF81OTlkZmZhNDg5MmQ0YjdhYTE1M2IyMzViNGFhNDY1NSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RG93bnN2aWV3PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jYzVhMGZiZDFmNGQ0OWU3YmI3OTU2OGNmODA0M2E2Ny5zZXRDb250ZW50KGh0bWxfNTk5ZGZmYTQ4OTJkNGI3YWExNTNiMjM1YjRhYTQ2NTUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODZjZjY1Yjc3MmMzNDZjOThmMzdiM2JlNTQ3MzQ3ODYuYmluZFBvcHVwKHBvcHVwX2NjNWEwZmJkMWY0ZDQ5ZTdiYjc5NTY4Y2Y4MDQzYTY3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2VkNzFmYWI4ODM3YjRiMTZiZjk5YjkyZDEzMDdlNWZjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjY4OTk4NSwtNzkuMzE1NTcxNTk5OTk5OThdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNzVhNTQwMzI5NzlmNDRiZGE0MjcxOTAyMmY4MzEyODMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZWVjMzc4OGE2NTEzNDllZDkzN2JjNTZjMWUwOTM5NTEgPSAkKCc8ZGl2IGlkPSJodG1sX2VlYzM3ODhhNjUxMzQ5ZWQ5MzdiYzU2YzFlMDkzOTUxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5JbmRpYSBCYXphYXIgLyBUaGUgQmVhY2hlcyBXZXN0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83NWE1NDAzMjk3OWY0NGJkYTQyNzE5MDIyZjgzMTI4My5zZXRDb250ZW50KGh0bWxfZWVjMzc4OGE2NTEzNDllZDkzN2JjNTZjMWUwOTM5NTEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZWQ3MWZhYjg4MzdiNGIxNmJmOTliOTJkMTMwN2U1ZmMuYmluZFBvcHVwKHBvcHVwXzc1YTU0MDMyOTc5ZjQ0YmRhNDI3MTkwMjJmODMxMjgzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQ1OTRiYzY3ZjQyYTQ2ODZhZTg5ZGE4YmY3NDkxMGFmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjQ4MTk4NSwtNzkuMzc5ODE2OTAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNDA3MmMxZWRjMWY0NDllM2I4ZjVjZDc1NWRjMWEzZWYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNDhjYjc0OGM2MDA3NGVhMzlmZWRkOTlhOTVmNzYwYTkgPSAkKCc8ZGl2IGlkPSJodG1sXzQ4Y2I3NDhjNjAwNzRlYTM5ZmVkZDk5YTk1Zjc2MGE5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Db21tZXJjZSBDb3VydCAvIFZpY3RvcmlhIEhvdGVsPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80MDcyYzFlZGMxZjQ0OWUzYjhmNWNkNzU1ZGMxYTNlZi5zZXRDb250ZW50KGh0bWxfNDhjYjc0OGM2MDA3NGVhMzlmZWRkOTlhOTVmNzYwYTkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDU5NGJjNjdmNDJhNDY4NmFlODlkYThiZjc0OTEwYWYuYmluZFBvcHVwKHBvcHVwXzQwNzJjMWVkYzFmNDQ5ZTNiOGY1Y2Q3NTVkYzFhM2VmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzJmM2E1MWIwMWEyMzRlMGViODE0Y2VkMGI3ZjRlMzZmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzEzNzU2MjAwMDAwMDA2LC03OS40OTAwNzM4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzdmZjhhMzZkMmNhNTQ1M2Y5NGNhMWMzNzhkMTRhMjgwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2Y3Zjg1MGJjODM3OTQ0ZjdhM2VlZmJhMDNjMTQ5ZDBjID0gJCgnPGRpdiBpZD0iaHRtbF9mN2Y4NTBiYzgzNzk0NGY3YTNlZWZiYTAzYzE0OWQwYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Tm9ydGggUGFyayAvIE1hcGxlIExlYWYgUGFyayAvIFVwd29vZCBQYXJrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83ZmY4YTM2ZDJjYTU0NTNmOTRjYTFjMzc4ZDE0YTI4MC5zZXRDb250ZW50KGh0bWxfZjdmODUwYmM4Mzc5NDRmN2EzZWVmYmEwM2MxNDlkMGMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMmYzYTUxYjAxYTIzNGUwZWI4MTRjZWQwYjdmNGUzNmYuYmluZFBvcHVwKHBvcHVwXzdmZjhhMzZkMmNhNTQ1M2Y5NGNhMWMzNzhkMTRhMjgwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzM1ODhmODM1NzQ5OTRkZWJiY2FhYjA0ODc4ZmI1YTlmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzU2MzAzMywtNzkuNTY1OTYzMjk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOTBkMGVmZTA4MGM3NDcxMDg3MjViZTY3MmU2NjliZjQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzBjNmQ3MmI3ZjVkNGE0Mzg4YTQ5YzFjZjIxOGZhMmMgPSAkKCc8ZGl2IGlkPSJodG1sXzcwYzZkNzJiN2Y1ZDRhNDM4OGE0OWMxY2YyMThmYTJjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IdW1iZXIgU3VtbWl0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85MGQwZWZlMDgwYzc0NzEwODcyNWJlNjcyZTY2OWJmNC5zZXRDb250ZW50KGh0bWxfNzBjNmQ3MmI3ZjVkNGE0Mzg4YTQ5YzFjZjIxOGZhMmMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMzU4OGY4MzU3NDk5NGRlYmJjYWFiMDQ4NzhmYjVhOWYuYmluZFBvcHVwKHBvcHVwXzkwZDBlZmUwODBjNzQ3MTA4NzI1YmU2NzJlNjY5YmY0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzgxNjBlZGE3YjVhYjRhZDY5MTY5OWFjOTM5OWJmMzBlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzE2MzE2LC03OS4yMzk0NzYwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jMzIxYjY5NWZkMWU0NTkyODVkNWRhOTg5MDY2ZDJmZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82NTk1OTcyZjg3ZWE0OWMwODk3MTQxZWMzZTNjZDMxMiA9ICQoJzxkaXYgaWQ9Imh0bWxfNjU5NTk3MmY4N2VhNDljMDg5NzE0MWVjM2UzY2QzMTIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNsaWZmc2lkZSAvIENsaWZmY3Jlc3QgLyBTY2FyYm9yb3VnaCBWaWxsYWdlIFdlc3Q8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2MzMjFiNjk1ZmQxZTQ1OTI4NWQ1ZGE5ODkwNjZkMmZmLnNldENvbnRlbnQoaHRtbF82NTk1OTcyZjg3ZWE0OWMwODk3MTQxZWMzZTNjZDMxMik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84MTYwZWRhN2I1YWI0YWQ2OTE2OTlhYzkzOTliZjMwZS5iaW5kUG9wdXAocG9wdXBfYzMyMWI2OTVmZDFlNDU5Mjg1ZDVkYTk4OTA2NmQyZmYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNzk4OWIwYjdiYzA3NDk3OTgyZmY5Y2RiZTkwYzljZDkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43ODkwNTMsLTc5LjQwODQ5Mjc5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2NjZjZmOTUxZTYyMzRhOGJhYmQ5NDE3NTk2ZWUyZTk0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzVmMDA1NzdkYWIzNTQyYmY5ZDY3MTE1ZjRiNThhNjc0ID0gJCgnPGRpdiBpZD0iaHRtbF81ZjAwNTc3ZGFiMzU0MmJmOWQ2NzExNWY0YjU4YTY3NCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2lsbG93ZGFsZSAvIE5ld3RvbmJyb29rPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jY2Y2Zjk1MWU2MjM0YThiYWJkOTQxNzU5NmVlMmU5NC5zZXRDb250ZW50KGh0bWxfNWYwMDU3N2RhYjM1NDJiZjlkNjcxMTVmNGI1OGE2NzQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzk4OWIwYjdiYzA3NDk3OTgyZmY5Y2RiZTkwYzljZDkuYmluZFBvcHVwKHBvcHVwX2NjZjZmOTUxZTYyMzRhOGJhYmQ5NDE3NTk2ZWUyZTk0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzhlY2JkNWUzMzlmYzQ0OTVhYzQ4MGIwOWQ5YmFmYzZlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzI4NDk2NCwtNzkuNDk1Njk3NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYjNjZjJjYTY0NTY2NDZjMWI0NDFlYmQzZWIzZDlkNTkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNTlhNTgwZTdhZjg0NGE1MDg1M2Q1OWZmZjUwMmE1ZjIgPSAkKCc8ZGl2IGlkPSJodG1sXzU5YTU4MGU3YWY4NDRhNTA4NTNkNTlmZmY1MDJhNWYyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Eb3duc3ZpZXc8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2IzY2YyY2E2NDU2NjQ2YzFiNDQxZWJkM2ViM2Q5ZDU5LnNldENvbnRlbnQoaHRtbF81OWE1ODBlN2FmODQ0YTUwODUzZDU5ZmZmNTAyYTVmMik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84ZWNiZDVlMzM5ZmM0NDk1YWM0ODBiMDlkOWJhZmM2ZS5iaW5kUG9wdXAocG9wdXBfYjNjZjJjYTY0NTY2NDZjMWI0NDFlYmQzZWIzZDlkNTkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfN2FkMjM2YzdlNTI0NDk1ZmE1MjVkM2IxYzUwYTUwMTIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NTk1MjU1LC03OS4zNDA5MjNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYjM4NmY0YjBhNWVmNDUwNWIyYTdmZGMxMzc2NWE2ODYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNGZlN2U2ZWEzNDFkNGQ4OWE1ZWIzOGU5NGM0NDQxMzIgPSAkKCc8ZGl2IGlkPSJodG1sXzRmZTdlNmVhMzQxZDRkODlhNWViMzhlOTRjNDQ0MTMyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TdHVkaW8gRGlzdHJpY3Q8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2IzODZmNGIwYTVlZjQ1MDViMmE3ZmRjMTM3NjVhNjg2LnNldENvbnRlbnQoaHRtbF80ZmU3ZTZlYTM0MWQ0ZDg5YTVlYjM4ZTk0YzQ0NDEzMik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83YWQyMzZjN2U1MjQ0OTVmYTUyNWQzYjFjNTBhNTAxMi5iaW5kUG9wdXAocG9wdXBfYjM4NmY0YjBhNWVmNDUwNWIyYTdmZGMxMzc2NWE2ODYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYzE3ZTlmMDJmYTExNDM3YWE2ZDQ1ZTQ0NjE3ZDNjNjYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MzMyODI1LC03OS40MTk3NDk3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzAzOTdlMWY3Y2FjMDQwYzc5ZWIxOWQ4NDVkZGJmNWNlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2YwMTdhNjc0NGMxODQ1NzM5YzcyMzdhZTkwYTA5MTA4ID0gJCgnPGRpdiBpZD0iaHRtbF9mMDE3YTY3NDRjMTg0NTczOWM3MjM3YWU5MGEwOTEwOCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmVkZm9yZCBQYXJrIC8gTGF3cmVuY2UgTWFub3IgRWFzdDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDM5N2UxZjdjYWMwNDBjNzllYjE5ZDg0NWRkYmY1Y2Uuc2V0Q29udGVudChodG1sX2YwMTdhNjc0NGMxODQ1NzM5YzcyMzdhZTkwYTA5MTA4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2MxN2U5ZjAyZmExMTQzN2FhNmQ0NWU0NDYxN2QzYzY2LmJpbmRQb3B1cChwb3B1cF8wMzk3ZTFmN2NhYzA0MGM3OWViMTlkODQ1ZGRiZjVjZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84ODdkZTI2OWZjOGQ0M2JjYmMzZGJiM2Y4NzY4YWIxMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY5MTExNTgsLTc5LjQ3NjAxMzI5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzQ2NzEyZmZlNDQ5YjRhYWViOTc2YjExMmZlMDRiYjk5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzMwODdlZTU4NzJiNTQ1Zjc5NjAxZTlmMGM2MWU0MTUyID0gJCgnPGRpdiBpZD0iaHRtbF8zMDg3ZWU1ODcyYjU0NWY3OTYwMWU5ZjBjNjFlNDE1MiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RGVsIFJheSAvIE1vdW50IERlbm5pcyAvIEtlZWxzZGFsZSBhbmQgU2lsdmVydGhvcm48L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzQ2NzEyZmZlNDQ5YjRhYWViOTc2YjExMmZlMDRiYjk5LnNldENvbnRlbnQoaHRtbF8zMDg3ZWU1ODcyYjU0NWY3OTYwMWU5ZjBjNjFlNDE1Mik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84ODdkZTI2OWZjOGQ0M2JjYmMzZGJiM2Y4NzY4YWIxMi5iaW5kUG9wdXAocG9wdXBfNDY3MTJmZmU0NDliNGFhZWI5NzZiMTEyZmUwNGJiOTkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMjI2YjE1ODNhOGZjNGU0ZmFiZTljYzRiYzBlMmYxYTQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MjQ3NjU5LC03OS41MzIyNDI0MDAwMDAwMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81NWExMDE4NjMxOGY0MDdlOTcwOWE0ZTkyNjk4NDQzNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jMDg0YWM2ZjQ4ZDA0ODFkODU1ZGRkYzQ5NmUxOTk0NyA9ICQoJzxkaXYgaWQ9Imh0bWxfYzA4NGFjNmY0OGQwNDgxZDg1NWRkZGM0OTZlMTk5NDciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkh1bWJlcmxlYSAvIEVtZXJ5PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81NWExMDE4NjMxOGY0MDdlOTcwOWE0ZTkyNjk4NDQzNC5zZXRDb250ZW50KGh0bWxfYzA4NGFjNmY0OGQwNDgxZDg1NWRkZGM0OTZlMTk5NDcpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjI2YjE1ODNhOGZjNGU0ZmFiZTljYzRiYzBlMmYxYTQuYmluZFBvcHVwKHBvcHVwXzU1YTEwMTg2MzE4ZjQwN2U5NzA5YTRlOTI2OTg0NDM0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzBlZjA4NTI2NmMyNzQzODliZmJiOTM5MjIwZWUxYTQ1ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjkyNjU3MDAwMDAwMDA0LC03OS4yNjQ4NDgxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzk2Y2ViNTIyMzk2MTQ5NDhiZWUzMDBiYmVlYjAyOGE5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzM2MTAwYTA2ZTc3ZTRmY2NiNWQ1ZWNkNmM2ZDJkZTQzID0gJCgnPGRpdiBpZD0iaHRtbF8zNjEwMGEwNmU3N2U0ZmNjYjVkNWVjZDZjNmQyZGU0MyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmlyY2ggQ2xpZmYgLyBDbGlmZnNpZGUgV2VzdDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOTZjZWI1MjIzOTYxNDk0OGJlZTMwMGJiZWViMDI4YTkuc2V0Q29udGVudChodG1sXzM2MTAwYTA2ZTc3ZTRmY2NiNWQ1ZWNkNmM2ZDJkZTQzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzBlZjA4NTI2NmMyNzQzODliZmJiOTM5MjIwZWUxYTQ1LmJpbmRQb3B1cChwb3B1cF85NmNlYjUyMjM5NjE0OTQ4YmVlMzAwYmJlZWIwMjhhOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xMmRhZDk5NjM3MGY0YTY0OTA0Nzg0ZTljMmYxZGNlOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc3MDExOTksLTc5LjQwODQ5Mjc5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzhiODVlNTJkODA0MjQ0Y2JiZTIzMGNhZWJlOTViMDcyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzRkOGVkYzJlZDUwNDQzZTU4ZTZhYzMyYTZiYzQwNTY4ID0gJCgnPGRpdiBpZD0iaHRtbF80ZDhlZGMyZWQ1MDQ0M2U1OGU2YWMzMmE2YmM0MDU2OCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2lsbG93ZGFsZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOGI4NWU1MmQ4MDQyNDRjYmJlMjMwY2FlYmU5NWIwNzIuc2V0Q29udGVudChodG1sXzRkOGVkYzJlZDUwNDQzZTU4ZTZhYzMyYTZiYzQwNTY4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzEyZGFkOTk2MzcwZjRhNjQ5MDQ3ODRlOWMyZjFkY2U4LmJpbmRQb3B1cChwb3B1cF84Yjg1ZTUyZDgwNDI0NGNiYmUyMzBjYWViZTk1YjA3Mik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yNWNiYmU0NWVkNGQ0MGQwYThhMzQwMTRlNjM1ODIxZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc2MTYzMTMsLTc5LjUyMDk5OTQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzUzNWE5MjY0MzAyNDQ5NjhhZTgxYzhmMGY1ODdiN2M5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzQ2MmFjNGQzYWE3MzQ2Njg5Y2U5ZGE5MGFlZWI3MTYyID0gJCgnPGRpdiBpZD0iaHRtbF80NjJhYzRkM2FhNzM0NjY4OWNlOWRhOTBhZWViNzE2MiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RG93bnN2aWV3PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81MzVhOTI2NDMwMjQ0OTY4YWU4MWM4ZjBmNTg3YjdjOS5zZXRDb250ZW50KGh0bWxfNDYyYWM0ZDNhYTczNDY2ODljZTlkYTkwYWVlYjcxNjIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjVjYmJlNDVlZDRkNDBkMGE4YTM0MDE0ZTYzNTgyMWQuYmluZFBvcHVwKHBvcHVwXzUzNWE5MjY0MzAyNDQ5NjhhZTgxYzhmMGY1ODdiN2M5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzMwMjBhNjUxNjk0NDQ3ZGNhOTgzMTE3ZjkxYzJkNzBjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzI4MDIwNSwtNzkuMzg4NzkwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yMTg4OTQyMjMzMGQ0YjY5YWVmNTcxOGNkMDZiMmIzYSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lYzgwMDJkMTdjZTA0ZWM2OGM5YjkzYTU2NDFlMTdiMCA9ICQoJzxkaXYgaWQ9Imh0bWxfZWM4MDAyZDE3Y2UwNGVjNjhjOWI5M2E1NjQxZTE3YjAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxhd3JlbmNlIFBhcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzIxODg5NDIyMzMwZDRiNjlhZWY1NzE4Y2QwNmIyYjNhLnNldENvbnRlbnQoaHRtbF9lYzgwMDJkMTdjZTA0ZWM2OGM5YjkzYTU2NDFlMTdiMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zMDIwYTY1MTY5NDQ0N2RjYTk4MzExN2Y5MWMyZDcwYy5iaW5kUG9wdXAocG9wdXBfMjE4ODk0MjIzMzBkNGI2OWFlZjU3MThjZDA2YjJiM2EpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODEwYjJhYzk1NDQ0NGE0ODk4MjBkOWFjYzVhNTc2NGYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MTE2OTQ4LC03OS40MTY5MzU1OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83OTY4OTliZmEyNWE0NzU4OTIzZDkzY2Y1NzhlYTVlZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82ODRlNTIwMmI2YTc0YTA5YjZhZjFiMTJjNTdjMzdhNiA9ICQoJzxkaXYgaWQ9Imh0bWxfNjg0ZTUyMDJiNmE3NGEwOWI2YWYxYjEyYzU3YzM3YTYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJvc2VsYXduPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83OTY4OTliZmEyNWE0NzU4OTIzZDkzY2Y1NzhlYTVlZi5zZXRDb250ZW50KGh0bWxfNjg0ZTUyMDJiNmE3NGEwOWI2YWYxYjEyYzU3YzM3YTYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODEwYjJhYzk1NDQ0NGE0ODk4MjBkOWFjYzVhNTc2NGYuYmluZFBvcHVwKHBvcHVwXzc5Njg5OWJmYTI1YTQ3NTg5MjNkOTNjZjU3OGVhNWVmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzRhZTQ4NjdiN2Y1MjQ1MDNiYmEzMjc0YmY2YTU1NGFiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjczMTg1Mjk5OTk5OTksLTc5LjQ4NzI2MTkwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzg1YjE1Zjg5MzUzYjQ5OGI4MDhmZjA2OWZiNjEzMDhlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzllOGNmYmEyNzc1YTQ1NjA4N2UxYTFkNjNjMDBiNTI5ID0gJCgnPGRpdiBpZD0iaHRtbF85ZThjZmJhMjc3NWE0NTYwODdlMWExZDYzYzAwYjUyOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UnVubnltZWRlIC8gVGhlIEp1bmN0aW9uIE5vcnRoPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84NWIxNWY4OTM1M2I0OThiODA4ZmYwNjlmYjYxMzA4ZS5zZXRDb250ZW50KGh0bWxfOWU4Y2ZiYTI3NzVhNDU2MDg3ZTFhMWQ2M2MwMGI1MjkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNGFlNDg2N2I3ZjUyNDUwM2JiYTMyNzRiZjZhNTU0YWIuYmluZFBvcHVwKHBvcHVwXzg1YjE1Zjg5MzUzYjQ5OGI4MDhmZjA2OWZiNjEzMDhlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzA3YzYxYjEyMWJjMTRiZjViZGRlNTA4ODYzOTdlZjc3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzA2ODc2LC03OS41MTgxODg0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jN2E5ZTgzNjYxZDQ0YjkwYjY4YTc5MjBlOGY1ODEyMiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zMDZkZTZmOGFkY2Q0YmQzYTIyZWJjMTdmMzMxNjc0OSA9ICQoJzxkaXYgaWQ9Imh0bWxfMzA2ZGU2ZjhhZGNkNGJkM2EyMmViYzE3ZjMzMTY3NDkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldlc3RvbjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYzdhOWU4MzY2MWQ0NGI5MGI2OGE3OTIwZThmNTgxMjIuc2V0Q29udGVudChodG1sXzMwNmRlNmY4YWRjZDRiZDNhMjJlYmMxN2YzMzE2NzQ5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzA3YzYxYjEyMWJjMTRiZjViZGRlNTA4ODYzOTdlZjc3LmJpbmRQb3B1cChwb3B1cF9jN2E5ZTgzNjYxZDQ0YjkwYjY4YTc5MjBlOGY1ODEyMik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mMTQ2ODM5ODZlZTc0YjBiODY2ZDk2ZDc0NGJjODYwNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc1NzQwOTYsLTc5LjI3MzMwNDAwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzFlOGE2N2NlZGY2NDQ1ZGI4YzllZjA4YmIwOGY2MTRlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzcwODY5ZDU2OGQ3MzQwNmU5MTQ1NjQ1YTA3ZjhhOTMzID0gJCgnPGRpdiBpZD0iaHRtbF83MDg2OWQ1NjhkNzM0MDZlOTE0NTY0NWEwN2Y4YTkzMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RG9yc2V0IFBhcmsgLyBXZXhmb3JkIEhlaWdodHMgLyBTY2FyYm9yb3VnaCBUb3duIENlbnRyZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMWU4YTY3Y2VkZjY0NDVkYjhjOWVmMDhiYjA4ZjYxNGUuc2V0Q29udGVudChodG1sXzcwODY5ZDU2OGQ3MzQwNmU5MTQ1NjQ1YTA3ZjhhOTMzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2YxNDY4Mzk4NmVlNzRiMGI4NjZkOTZkNzQ0YmM4NjA1LmJpbmRQb3B1cChwb3B1cF8xZThhNjdjZWRmNjQ0NWRiOGM5ZWYwOGJiMDhmNjE0ZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83OWU2ZTI0YWU0NTY0NTRlOTZiMzVhY2ZmMTRjMDhlOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc1Mjc1ODI5OTk5OTk5NiwtNzkuNDAwMDQ5M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iZmM3MDliMzQ5YmI0MzY0YTdkYmRjYzRmOWFlNGU5YSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9kMzY3YjM1ZWQ1ZGU0MWQxYWMyOTlkOTY0YTFmNjdkOSA9ICQoJzxkaXYgaWQ9Imh0bWxfZDM2N2IzNWVkNWRlNDFkMWFjMjk5ZDk2NGExZjY3ZDkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPllvcmsgTWlsbHMgV2VzdDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYmZjNzA5YjM0OWJiNDM2NGE3ZGJkY2M0ZjlhZTRlOWEuc2V0Q29udGVudChodG1sX2QzNjdiMzVlZDVkZTQxZDFhYzI5OWQ5NjRhMWY2N2Q5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzc5ZTZlMjRhZTQ1NjQ1NGU5NmIzNWFjZmYxNGMwOGU4LmJpbmRQb3B1cChwb3B1cF9iZmM3MDliMzQ5YmI0MzY0YTdkYmRjYzRmOWFlNGU5YSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83MGQxNTkyOTYzNDI0OWM3OWFmMTlhYmEzODUwNzFjZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcxMjc1MTEsLTc5LjM5MDE5NzVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOWI0OTg5MzAwZWJiNDYyNWI5ZGJkZTZhNzczNGNlMzAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMjQ1MjhhMmQwODcyNDljZjg2MDVkYWNkN2E4OTY2NTEgPSAkKCc8ZGl2IGlkPSJodG1sXzI0NTI4YTJkMDg3MjQ5Y2Y4NjA1ZGFjZDdhODk2NjUxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5EYXZpc3ZpbGxlIE5vcnRoPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85YjQ5ODkzMDBlYmI0NjI1YjlkYmRlNmE3NzM0Y2UzMC5zZXRDb250ZW50KGh0bWxfMjQ1MjhhMmQwODcyNDljZjg2MDVkYWNkN2E4OTY2NTEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzBkMTU5Mjk2MzQyNDljNzlhZjE5YWJhMzg1MDcxY2YuYmluZFBvcHVwKHBvcHVwXzliNDk4OTMwMGViYjQ2MjViOWRiZGU2YTc3MzRjZTMwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2M2MzY5YzI3YzI1MTQ1OTE4NzQwOTljY2ExY2UwYjcxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjk2OTQ3NiwtNzkuNDExMzA3MjAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZmUyOWVhNTI3OGQzNGJmOWFiZDM2MGMxMjhmNjFlMzUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfY2Q3Y2UyMDllYWYzNDMzNmEwMmRhYjQ2Mjk2OWI2NzMgPSAkKCc8ZGl2IGlkPSJodG1sX2NkN2NlMjA5ZWFmMzQzMzZhMDJkYWI0NjI5NjliNjczIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Gb3Jlc3QgSGlsbCBOb3J0aCAmYW1wOyBXZXN0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mZTI5ZWE1Mjc4ZDM0YmY5YWJkMzYwYzEyOGY2MWUzNS5zZXRDb250ZW50KGh0bWxfY2Q3Y2UyMDllYWYzNDMzNmEwMmRhYjQ2Mjk2OWI2NzMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYzYzNjljMjdjMjUxNDU5MTg3NDA5OWNjYTFjZTBiNzEuYmluZFBvcHVwKHBvcHVwX2ZlMjllYTUyNzhkMzRiZjlhYmQzNjBjMTI4ZjYxZTM1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzFkODAwMDIwZDQ3MTQxMzFiNjdhYmYyYzY5N2VjMzk2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjYxNjA4MywtNzkuNDY0NzYzMjk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYTUwN2YwNDVlNzA4NDk1OGJmYzRjODVhODMzNDc4MzggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMjJjMzFkNmJiZDUyNGQ2MzhhZTU4NjE5YzBkOTI1YjMgPSAkKCc8ZGl2IGlkPSJodG1sXzIyYzMxZDZiYmQ1MjRkNjM4YWU1ODYxOWMwZDkyNWIzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IaWdoIFBhcmsgLyBUaGUgSnVuY3Rpb24gU291dGg8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2E1MDdmMDQ1ZTcwODQ5NThiZmM0Yzg1YTgzMzQ3ODM4LnNldENvbnRlbnQoaHRtbF8yMmMzMWQ2YmJkNTI0ZDYzOGFlNTg2MTljMGQ5MjViMyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xZDgwMDAyMGQ0NzE0MTMxYjY3YWJmMmM2OTdlYzM5Ni5iaW5kUG9wdXAocG9wdXBfYTUwN2YwNDVlNzA4NDk1OGJmYzRjODVhODMzNDc4MzgpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTI4MDhmM2RmYjBmNGRhZGE2YTFjYzcwZWU1NjI0NzEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42OTYzMTksLTc5LjUzMjI0MjQwMDAwMDAyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2FiOWEwYzRmMzY3MzQyZGQ4YTBhMGZhMmJkN2I5YzZlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzgxYTJjM2IyZWQyNTQ2NmY4YTcwNTlhZmM3ZDQzZTQ0ID0gJCgnPGRpdiBpZD0iaHRtbF84MWEyYzNiMmVkMjU0NjZmOGE3MDU5YWZjN2Q0M2U0NCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2VzdG1vdW50PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hYjlhMGM0ZjM2NzM0MmRkOGEwYTBmYTJiZDdiOWM2ZS5zZXRDb250ZW50KGh0bWxfODFhMmMzYjJlZDI1NDY2ZjhhNzA1OWFmYzdkNDNlNDQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNTI4MDhmM2RmYjBmNGRhZGE2YTFjYzcwZWU1NjI0NzEuYmluZFBvcHVwKHBvcHVwX2FiOWEwYzRmMzY3MzQyZGQ4YTBhMGZhMmJkN2I5YzZlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzU1OThiNjVhZGNlYTQ4ZTdhMjgwZjJhOWZjODZkZjdkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzUwMDcxNTAwMDAwMDA0LC03OS4yOTU4NDkxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2I4NDhiMDc3MWQwZDQ2Yjc4ZjIxYzYxM2U0ZDBiOGZhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzgwYjgyMTk1MmYxMjQ0YzFhZmRmNjJmNDZiZWRmZDQ0ID0gJCgnPGRpdiBpZD0iaHRtbF84MGI4MjE5NTJmMTI0NGMxYWZkZjYyZjQ2YmVkZmQ0NCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2V4Zm9yZCAvIE1hcnl2YWxlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iODQ4YjA3NzFkMGQ0NmI3OGYyMWM2MTNlNGQwYjhmYS5zZXRDb250ZW50KGh0bWxfODBiODIxOTUyZjEyNDRjMWFmZGY2MmY0NmJlZGZkNDQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNTU5OGI2NWFkY2VhNDhlN2EyODBmMmE5ZmM4NmRmN2QuYmluZFBvcHVwKHBvcHVwX2I4NDhiMDc3MWQwZDQ2Yjc4ZjIxYzYxM2U0ZDBiOGZhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzE3MWVmYmM0MTNhMzQxNTM5NTVjYmEyYzFjNTFlYzM4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzgyNzM2NCwtNzkuNDQyMjU5M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iZjdhNTJhN2RiNDM0OTkwYTAwYTgxYWU2YzRjMGY2NyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mYWNhNjU3YjczNjI0ZTM3OTc2YTk1MDI5ZDQxZjZkZiA9ICQoJzxkaXYgaWQ9Imh0bWxfZmFjYTY1N2I3MzYyNGUzNzk3NmE5NTAyOWQ0MWY2ZGYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldpbGxvd2RhbGU8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2JmN2E1MmE3ZGI0MzQ5OTBhMDBhODFhZTZjNGMwZjY3LnNldENvbnRlbnQoaHRtbF9mYWNhNjU3YjczNjI0ZTM3OTc2YTk1MDI5ZDQxZjZkZik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xNzFlZmJjNDEzYTM0MTUzOTU1Y2JhMmMxYzUxZWMzOC5iaW5kUG9wdXAocG9wdXBfYmY3YTUyYTdkYjQzNDk5MGEwMGE4MWFlNmM0YzBmNjcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTUzNDgwYTcyNjYyNDA0OGJmMjQzZWE4Y2M4NDQ0MzMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MTUzODM0LC03OS40MDU2Nzg0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xZjA0NTkzYjM5MTk0NjJhODI2MjgwMGFiYzRjM2Y5MCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mYWViZTE5MjkwZTc0YTdhYjQ1ZWNiMTgwYmIyOGU0NyA9ICQoJzxkaXYgaWQ9Imh0bWxfZmFlYmUxOTI5MGU3NGE3YWI0NWVjYjE4MGJiMjhlNDciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5vcnRoIFRvcm9udG8gV2VzdDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMWYwNDU5M2IzOTE5NDYyYTgyNjI4MDBhYmM0YzNmOTAuc2V0Q29udGVudChodG1sX2ZhZWJlMTkyOTBlNzRhN2FiNDVlY2IxODBiYjI4ZTQ3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU1MzQ4MGE3MjY2MjQwNDhiZjI0M2VhOGNjODQ0NDMzLmJpbmRQb3B1cChwb3B1cF8xZjA0NTkzYjM5MTk0NjJhODI2MjgwMGFiYzRjM2Y5MCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wMmVmOTYwNmQwODk0YjYyOGJiY2UwYmVlYzdlZDI3MiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY3MjcwOTcsLTc5LjQwNTY3ODQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2ZkMjJjNjYxMDVmYjQ3OGFhNzk3NDU2MjdmNTk0OWJjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2FjZWZlM2VhMmNjODQ4ZWNiOTBiYzU4Nzc0ZDdlMzAzID0gJCgnPGRpdiBpZD0iaHRtbF9hY2VmZTNlYTJjYzg0OGVjYjkwYmM1ODc3NGQ3ZTMwMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VGhlIEFubmV4IC8gTm9ydGggTWlkdG93biAvIFlvcmt2aWxsZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZmQyMmM2NjEwNWZiNDc4YWE3OTc0NTYyN2Y1OTQ5YmMuc2V0Q29udGVudChodG1sX2FjZWZlM2VhMmNjODQ4ZWNiOTBiYzU4Nzc0ZDdlMzAzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzAyZWY5NjA2ZDA4OTRiNjI4YmJjZTBiZWVjN2VkMjcyLmJpbmRQb3B1cChwb3B1cF9mZDIyYzY2MTA1ZmI0NzhhYTc5NzQ1NjI3ZjU5NDliYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yMzEyODA3ZDViYmM0NmI3ODVhNGQwNjUzNDQxZjE2NyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY0ODk1OTcsLTc5LjQ1NjMyNV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82ZTQxNWM4OTcyYWE0YWVkYTBhNDUyNGRiODRmYzdjNiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jYTIxYjQ0MjFlYjY0MGNlYWE3YzFkMDI3MzU4YzA4MSA9ICQoJzxkaXYgaWQ9Imh0bWxfY2EyMWI0NDIxZWI2NDBjZWFhN2MxZDAyNzM1OGMwODEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlBhcmtkYWxlIC8gUm9uY2VzdmFsbGVzPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82ZTQxNWM4OTcyYWE0YWVkYTBhNDUyNGRiODRmYzdjNi5zZXRDb250ZW50KGh0bWxfY2EyMWI0NDIxZWI2NDBjZWFhN2MxZDAyNzM1OGMwODEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjMxMjgwN2Q1YmJjNDZiNzg1YTRkMDY1MzQ0MWYxNjcuYmluZFBvcHVwKHBvcHVwXzZlNDE1Yzg5NzJhYTRhZWRhMGE0NTI0ZGI4NGZjN2M2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQ2Yjg2MzExNTI3MzQ5ODZhODczMWNhODM5ZDdhYjhiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjM2OTY1NiwtNzkuNjE1ODE4OTk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMTA4M2JiMmU1Mzc2NGJjYmI5YzZkYTUzYjJhMTM4NWIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfM2FlNTdhNzY2NDQ5NGE4MjgwMDg4ODBkMTUwZmY4ZTkgPSAkKCc8ZGl2IGlkPSJodG1sXzNhZTU3YTc2NjQ0OTRhODI4MDA4ODgwZDE1MGZmOGU5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DYW5hZGEgUG9zdCBHYXRld2F5IFByb2Nlc3NpbmcgQ2VudHJlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xMDgzYmIyZTUzNzY0YmNiYjljNmRhNTNiMmExMzg1Yi5zZXRDb250ZW50KGh0bWxfM2FlNTdhNzY2NDQ5NGE4MjgwMDg4ODBkMTUwZmY4ZTkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDZiODYzMTE1MjczNDk4NmE4NzMxY2E4MzlkN2FiOGIuYmluZFBvcHVwKHBvcHVwXzEwODNiYjJlNTM3NjRiY2JiOWM2ZGE1M2IyYTEzODViKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzc2YjAwODAyMWNlZDQ4NTU4MDYwYjJmNjMxOWJmODk2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjg4OTA1NCwtNzkuNTU0NzI0NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzhjNmNmZjYzNGYzNDUwNmJlZDU3OWUyNzQyMDM4ZWMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOGYxMDM5Y2FkZDVjNGE2YTk4YjYzZDAyZDlkYTU2YTQgPSAkKCc8ZGl2IGlkPSJodG1sXzhmMTAzOWNhZGQ1YzRhNmE5OGI2M2QwMmQ5ZGE1NmE0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5LaW5nc3ZpZXcgVmlsbGFnZSAvIFN0LiBQaGlsbGlwcyAvIE1hcnRpbiBHcm92ZSBHYXJkZW5zIC8gUmljaHZpZXcgR2FyZGVuczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzhjNmNmZjYzNGYzNDUwNmJlZDU3OWUyNzQyMDM4ZWMuc2V0Q29udGVudChodG1sXzhmMTAzOWNhZGQ1YzRhNmE5OGI2M2QwMmQ5ZGE1NmE0KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzc2YjAwODAyMWNlZDQ4NTU4MDYwYjJmNjMxOWJmODk2LmJpbmRQb3B1cChwb3B1cF8zOGM2Y2ZmNjM0ZjM0NTA2YmVkNTc5ZTI3NDIwMzhlYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kNjg0ZWQ4NWUzYjc0ZTBhOTdmNDQzYmY3ZmEzODU2NCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc5NDIwMDMsLTc5LjI2MjAyOTQwMDAwMDAyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzQzYjI5MDA0OTI1MjRjNzlhMDY0N2FhN2I3NTljN2VmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2Q3MTkyYmQxMDk4YjQyYWQ5MjIxNDdhMWYxMWMwNDI1ID0gJCgnPGRpdiBpZD0iaHRtbF9kNzE5MmJkMTA5OGI0MmFkOTIyMTQ3YTFmMTFjMDQyNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QWdpbmNvdXJ0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80M2IyOTAwNDkyNTI0Yzc5YTA2NDdhYTdiNzU5YzdlZi5zZXRDb250ZW50KGh0bWxfZDcxOTJiZDEwOThiNDJhZDkyMjE0N2ExZjExYzA0MjUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZDY4NGVkODVlM2I3NGUwYTk3ZjQ0M2JmN2ZhMzg1NjQuYmluZFBvcHVwKHBvcHVwXzQzYjI5MDA0OTI1MjRjNzlhMDY0N2FhN2I3NTljN2VmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzc0YTRlMjMzMGM1NzQ1YWNhN2I1YjZhYWI3MWE4NTNhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzA0MzI0NCwtNzkuMzg4NzkwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zMGQ0MzkzNmVlMWY0YWJmOTYyYjYyMmUyMmExNWExMiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xMWNlOTdiYWUzOWM0YWQyYWRkYTA4OTUzZjVmOTlhOCA9ICQoJzxkaXYgaWQ9Imh0bWxfMTFjZTk3YmFlMzljNGFkMmFkZGEwODk1M2Y1Zjk5YTgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRhdmlzdmlsbGU8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzMwZDQzOTM2ZWUxZjRhYmY5NjJiNjIyZTIyYTE1YTEyLnNldENvbnRlbnQoaHRtbF8xMWNlOTdiYWUzOWM0YWQyYWRkYTA4OTUzZjVmOTlhOCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83NGE0ZTIzMzBjNTc0NWFjYTdiNWI2YWFiNzFhODUzYS5iaW5kUG9wdXAocG9wdXBfMzBkNDM5MzZlZTFmNGFiZjk2MmI2MjJlMjJhMTVhMTIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMTE5ZTk1YjllZDViNDhjOWFkMmI1NjI1M2ZmOWE0ZDIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NjI2OTU2LC03OS40MDAwNDkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2VjZWYyOTk4OWE2NzRiMjI5NTY1OGM0YjlkMGQ0MzRjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzlhYzI4NzIwZDRhZjQ1ZjA4NTFjNGVhNjA1MmE3OWMxID0gJCgnPGRpdiBpZD0iaHRtbF85YWMyODcyMGQ0YWY0NWYwODUxYzRlYTYwNTJhNzljMSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VW5pdmVyc2l0eSBvZiBUb3JvbnRvIC8gSGFyYm9yZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZWNlZjI5OTg5YTY3NGIyMjk1NjU4YzRiOWQwZDQzNGMuc2V0Q29udGVudChodG1sXzlhYzI4NzIwZDRhZjQ1ZjA4NTFjNGVhNjA1MmE3OWMxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzExOWU5NWI5ZWQ1YjQ4YzlhZDJiNTYyNTNmZjlhNGQyLmJpbmRQb3B1cChwb3B1cF9lY2VmMjk5ODlhNjc0YjIyOTU2NThjNGI5ZDBkNDM0Yyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wOWZmYmJkMWE2NjI0N2YxODVlOWMyOTdiMjMxNDIyMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1MTU3MDYsLTc5LjQ4NDQ0OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzEzMmMzYjdhN2JlNGJhYTkzOTQ0YTA1OTZjNWQ3MDMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfODA5ZjY5NDkxMDE1NGI4NmI0NDYwMWFmYThjNDVhMjggPSAkKCc8ZGl2IGlkPSJodG1sXzgwOWY2OTQ5MTAxNTRiODZiNDQ2MDFhZmE4YzQ1YTI4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5SdW5ueW1lZGUgLyBTd2Fuc2VhPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jMTMyYzNiN2E3YmU0YmFhOTM5NDRhMDU5NmM1ZDcwMy5zZXRDb250ZW50KGh0bWxfODA5ZjY5NDkxMDE1NGI4NmI0NDYwMWFmYThjNDVhMjgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMDlmZmJiZDFhNjYyNDdmMTg1ZTljMjk3YjIzMTQyMjIuYmluZFBvcHVwKHBvcHVwX2MxMzJjM2I3YTdiZTRiYWE5Mzk0NGEwNTk2YzVkNzAzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzNmZTM2MjMzYmU5MjQwM2M4Y2E4ZjI3ZjMwZTMxYWIwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzgxNjM3NSwtNzkuMzA0MzAyMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xZWU3MThjYWVhMmU0ZDI3OWJjNTYxMzViNzVjNWE0ZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wOGI3NjNmNjRmYjY0MTM5Yjg2ZDRiZTdmMDQ3YzIxNCA9ICQoJzxkaXYgaWQ9Imh0bWxfMDhiNzYzZjY0ZmI2NDEzOWI4NmQ0YmU3ZjA0N2MyMTQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNsYXJrcyBDb3JuZXJzIC8gVGFtIE8mIzM5O1NoYW50ZXIgLyBTdWxsaXZhbjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMWVlNzE4Y2FlYTJlNGQyNzliYzU2MTM1Yjc1YzVhNGYuc2V0Q29udGVudChodG1sXzA4Yjc2M2Y2NGZiNjQxMzliODZkNGJlN2YwNDdjMjE0KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzNmZTM2MjMzYmU5MjQwM2M4Y2E4ZjI3ZjMwZTMxYWIwLmJpbmRQb3B1cChwb3B1cF8xZWU3MThjYWVhMmU0ZDI3OWJjNTYxMzViNzVjNWE0Zik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kMzZiYWNhNzkzNGQ0NzA0YjExZWIwZDA1Y2E5YWE4OSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY4OTU3NDMsLTc5LjM4MzE1OTkwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzU1YjliY2QwZTE3YjRmMGI4MmZhOGRlMTY4NTQxOTAzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzA5NTlkNmNkYWZkZDRkMTM5NGFlOTQ3M2I5MTJjYmViID0gJCgnPGRpdiBpZD0iaHRtbF8wOTU5ZDZjZGFmZGQ0ZDEzOTRhZTk0NzNiOTEyY2JlYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TW9vcmUgUGFyayAvIFN1bW1lcmhpbGwgRWFzdDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNTViOWJjZDBlMTdiNGYwYjgyZmE4ZGUxNjg1NDE5MDMuc2V0Q29udGVudChodG1sXzA5NTlkNmNkYWZkZDRkMTM5NGFlOTQ3M2I5MTJjYmViKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2QzNmJhY2E3OTM0ZDQ3MDRiMTFlYjBkMDVjYTlhYTg5LmJpbmRQb3B1cChwb3B1cF81NWI5YmNkMGUxN2I0ZjBiODJmYThkZTE2ODU0MTkwMyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kZmMxNjgyYTMzZjI0YzQ1YTlhODg0YmRiYTMzODljOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1MzIwNTcsLTc5LjQwMDA0OTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjMyNDQ4NGRkZmI0NDYwOTk4MWRmOWQ4NDkyZDEzOTIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMTdjNjU1MTlkODBiNGY3ZWIxM2FkOTU3NTY4ZGYxMGMgPSAkKCc8ZGl2IGlkPSJodG1sXzE3YzY1NTE5ZDgwYjRmN2ViMTNhZDk1NzU2OGRmMTBjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5LZW5zaW5ndG9uIE1hcmtldCAvIENoaW5hdG93biAvIEdyYW5nZSBQYXJrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82MzI0NDg0ZGRmYjQ0NjA5OTgxZGY5ZDg0OTJkMTM5Mi5zZXRDb250ZW50KGh0bWxfMTdjNjU1MTlkODBiNGY3ZWIxM2FkOTU3NTY4ZGYxMGMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZGZjMTY4MmEzM2YyNGM0NWE5YTg4NGJkYmEzMzg5YzguYmluZFBvcHVwKHBvcHVwXzYzMjQ0ODRkZGZiNDQ2MDk5ODFkZjlkODQ5MmQxMzkyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Q5NDk3MDZmODY1YTQyOTlhOGY1ZGYyZGMyODAyNWUwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuODE1MjUyMiwtNzkuMjg0NTc3Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wZGZiZDA2MGY1OGU0MGE0YTRiZmVjZTlmMmNlMGI3ZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wMzU0NjQ5NDk1YTY0ZDAxODBiMTYyNDMzMjE4N2E4YSA9ICQoJzxkaXYgaWQ9Imh0bWxfMDM1NDY0OTQ5NWE2NGQwMTgwYjE2MjQzMzIxODdhOGEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1pbGxpa2VuIC8gQWdpbmNvdXJ0IE5vcnRoIC8gU3RlZWxlcyBFYXN0IC8gTCYjMzk7QW1vcmVhdXggRWFzdDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMGRmYmQwNjBmNThlNDBhNGE0YmZlY2U5ZjJjZTBiN2Uuc2V0Q29udGVudChodG1sXzAzNTQ2NDk0OTVhNjRkMDE4MGIxNjI0MzMyMTg3YThhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2Q5NDk3MDZmODY1YTQyOTlhOGY1ZGYyZGMyODAyNWUwLmJpbmRQb3B1cChwb3B1cF8wZGZiZDA2MGY1OGU0MGE0YTRiZmVjZTlmMmNlMGI3ZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84YmFhYjBiZjZhOTA0YWU4YjAxODAzYjkxYTdlNGFkNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY4NjQxMjI5OTk5OTk5LC03OS40MDAwNDkzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2NiZDZmNWI1ZjEyYTQ5Y2ViMTgzYWZjZTllNmFiNDcwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzEyYzM1NTgzYmEyYTQxOTI5N2NlZjk4NTAyZjQ5YWY5ID0gJCgnPGRpdiBpZD0iaHRtbF8xMmMzNTU4M2JhMmE0MTkyOTdjZWY5ODUwMmY0OWFmOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3VtbWVyaGlsbCBXZXN0IC8gUmF0aG5lbGx5IC8gU291dGggSGlsbCAvIEZvcmVzdCBIaWxsIFNFIC8gRGVlciBQYXJrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jYmQ2ZjViNWYxMmE0OWNlYjE4M2FmY2U5ZTZhYjQ3MC5zZXRDb250ZW50KGh0bWxfMTJjMzU1ODNiYTJhNDE5Mjk3Y2VmOTg1MDJmNDlhZjkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOGJhYWIwYmY2YTkwNGFlOGIwMTgwM2I5MWE3ZTRhZDcuYmluZFBvcHVwKHBvcHVwX2NiZDZmNWI1ZjEyYTQ5Y2ViMTgzYWZjZTllNmFiNDcwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzUwOGJjNzk1MWZkODQ4MjM4Y2ViZjRkZTY3ZDNjYjdhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjI4OTQ2NywtNzkuMzk0NDE5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jMjBlZmE3OTFjNWU0ZTg0YjA3ODBhNzhhMTI2NjI5NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hMDJlOTYxZTQ0ZWQ0YzNjYjllY2I0NzYyNjlmZGYyMSA9ICQoJzxkaXYgaWQ9Imh0bWxfYTAyZTk2MWU0NGVkNGMzY2I5ZWNiNDc2MjY5ZmRmMjEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNOIFRvd2VyIC8gS2luZyBhbmQgU3BhZGluYSAvIFJhaWx3YXkgTGFuZHMgLyBIYXJib3VyZnJvbnQgV2VzdCAvIEJhdGh1cnN0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jMjBlZmE3OTFjNWU0ZTg0YjA3ODBhNzhhMTI2NjI5NC5zZXRDb250ZW50KGh0bWxfYTAyZTk2MWU0NGVkNGMzY2I5ZWNiNDc2MjY5ZmRmMjEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNTA4YmM3OTUxZmQ4NDgyMzhjZWJmNGRlNjdkM2NiN2EuYmluZFBvcHVwKHBvcHVwX2MyMGVmYTc5MWM1ZTRlODRiMDc4MGE3OGExMjY2Mjk0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzMxY2I5ZDQ4NmMzMDRjNDFiODJmYjc0OTQyZTYzODJiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjA1NjQ2NiwtNzkuNTAxMzIwNzAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNGU5ZjY4MzYyYjY4NDdlOThmNDA2ZjM0YmJlOWIxZmYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMDk1MmI2MGM0NGQ0NDIwOWE0NjExYTM3MWQyOGE1NjIgPSAkKCc8ZGl2IGlkPSJodG1sXzA5NTJiNjBjNDRkNDQyMDlhNDYxMWEzNzFkMjhhNTYyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5OZXcgVG9yb250byAvIE1pbWljbyBTb3V0aCAvIEh1bWJlciBCYXkgU2hvcmVzPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80ZTlmNjgzNjJiNjg0N2U5OGY0MDZmMzRiYmU5YjFmZi5zZXRDb250ZW50KGh0bWxfMDk1MmI2MGM0NGQ0NDIwOWE0NjExYTM3MWQyOGE1NjIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMzFjYjlkNDg2YzMwNGM0MWI4MmZiNzQ5NDJlNjM4MmIuYmluZFBvcHVwKHBvcHVwXzRlOWY2ODM2MmI2ODQ3ZTk4ZjQwNmYzNGJiZTliMWZmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2QyZGFlNWJlNjM3MzRlMDVhMTc3Yjg3MDgwY2ViNGZiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzM5NDE2Mzk5OTk5OTk2LC03OS41ODg0MzY5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RhMTNlNmJlNDNmNzQ5ZTI4MTEyNTE2MzA5ZWViYTNkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc1Yzg2ZDBkNTA4OTQ0YWE5M2NkMjA1ZjFhYjJiZDY3ID0gJCgnPGRpdiBpZD0iaHRtbF83NWM4NmQwZDUwODk0NGFhOTNjZDIwNWYxYWIyYmQ2NyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U291dGggU3RlZWxlcyAvIFNpbHZlcnN0b25lIC8gSHVtYmVyZ2F0ZSAvIEphbWVzdG93biAvIE1vdW50IE9saXZlIC8gQmVhdW1vbmQgSGVpZ2h0cyAvIFRoaXN0bGV0b3duIC8gQWxiaW9uIEdhcmRlbnM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2RhMTNlNmJlNDNmNzQ5ZTI4MTEyNTE2MzA5ZWViYTNkLnNldENvbnRlbnQoaHRtbF83NWM4NmQwZDUwODk0NGFhOTNjZDIwNWYxYWIyYmQ2Nyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9kMmRhZTViZTYzNzM0ZTA1YTE3N2I4NzA4MGNlYjRmYi5iaW5kUG9wdXAocG9wdXBfZGExM2U2YmU0M2Y3NDllMjgxMTI1MTYzMDllZWJhM2QpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZmU0M2U3YjFjM2FmNDIzYmJkZjU3Y2EzMGRlYThkNjUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43OTk1MjUyMDAwMDAwMDUsLTc5LjMxODM4ODddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOThkMDkzYWZkMDQzNDM4OTk0ZmI4YjY3M2NkNTFmZDcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZGViZmU3NzU3NTgzNGM1Yzg3OWI3ZTE4MGVlY2NmZjUgPSAkKCc8ZGl2IGlkPSJodG1sX2RlYmZlNzc1NzU4MzRjNWM4NzliN2UxODBlZWNjZmY1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TdGVlbGVzIFdlc3QgLyBMJiMzOTtBbW9yZWF1eCBXZXN0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85OGQwOTNhZmQwNDM0Mzg5OTRmYjhiNjczY2Q1MWZkNy5zZXRDb250ZW50KGh0bWxfZGViZmU3NzU3NTgzNGM1Yzg3OWI3ZTE4MGVlY2NmZjUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZmU0M2U3YjFjM2FmNDIzYmJkZjU3Y2EzMGRlYThkNjUuYmluZFBvcHVwKHBvcHVwXzk4ZDA5M2FmZDA0MzQzODk5NGZiOGI2NzNjZDUxZmQ3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2VkYWEzNDJiNjg2NDQ1MDdiYTZmZGM0NmQ3Y2JlYjBhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjc5NTYyNiwtNzkuMzc3NTI5NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjcwZTM5YzlhNjRkNDkwNmEwNmJmMGRhZDQ1NTU2YjAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYjJjOGQ4MzIzMzAwNDJjNTk3MTUwMDBiMzQxNzkzMGIgPSAkKCc8ZGl2IGlkPSJodG1sX2IyYzhkODMyMzMwMDQyYzU5NzE1MDAwYjM0MTc5MzBiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Sb3NlZGFsZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNjcwZTM5YzlhNjRkNDkwNmEwNmJmMGRhZDQ1NTU2YjAuc2V0Q29udGVudChodG1sX2IyYzhkODMyMzMwMDQyYzU5NzE1MDAwYjM0MTc5MzBiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2VkYWEzNDJiNjg2NDQ1MDdiYTZmZGM0NmQ3Y2JlYjBhLmJpbmRQb3B1cChwb3B1cF82NzBlMzljOWE2NGQ0OTA2YTA2YmYwZGFkNDU1NTZiMCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84ZDkzMGYxMTkyMmU0MzI0YWM2OGIxMTZhYjM2NWUwMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY0NjQzNTIsLTc5LjM3NDg0NTk5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzY0NzI3ZTc4MWNkNjRjZTdhNjVlNTA3Nzg5YzkzZTcyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2FiNTJkY2M4YTVlMzQ4NjdiYWFlNzYzYzYwZmI5ZmVkID0gJCgnPGRpdiBpZD0iaHRtbF9hYjUyZGNjOGE1ZTM0ODY3YmFhZTc2M2M2MGZiOWZlZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3RuIEEgUE8gQm94ZXM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzY0NzI3ZTc4MWNkNjRjZTdhNjVlNTA3Nzg5YzkzZTcyLnNldENvbnRlbnQoaHRtbF9hYjUyZGNjOGE1ZTM0ODY3YmFhZTc2M2M2MGZiOWZlZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84ZDkzMGYxMTkyMmU0MzI0YWM2OGIxMTZhYjM2NWUwMi5iaW5kUG9wdXAocG9wdXBfNjQ3MjdlNzgxY2Q2NGNlN2E2NWU1MDc3ODljOTNlNzIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZTRkYWFkYzkyZTU4NDJlM2FkMTA0YTUwOWY0NjU4ODMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42MDI0MTM3MDAwMDAwMSwtNzkuNTQzNDg0MDk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMDQyMGY2YTQxN2RmNDhmNGJhNWFhZmUwYmI1Y2Q0ODUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZTVjMmQ1MzhkYTIyNDEwNmI2MDg2MDZiZGIwMzZhODAgPSAkKCc8ZGl2IGlkPSJodG1sX2U1YzJkNTM4ZGEyMjQxMDZiNjA4NjA2YmRiMDM2YTgwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5BbGRlcndvb2QgLyBMb25nIEJyYW5jaDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDQyMGY2YTQxN2RmNDhmNGJhNWFhZmUwYmI1Y2Q0ODUuc2V0Q29udGVudChodG1sX2U1YzJkNTM4ZGEyMjQxMDZiNjA4NjA2YmRiMDM2YTgwKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2U0ZGFhZGM5MmU1ODQyZTNhZDEwNGE1MDlmNDY1ODgzLmJpbmRQb3B1cChwb3B1cF8wNDIwZjZhNDE3ZGY0OGY0YmE1YWFmZTBiYjVjZDQ4NSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80YjEyYTEzZjQyOTg0Yjk3YmUzOGQxNGVmNWNiNjBmZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcwNjc0ODI5OTk5OTk5NCwtNzkuNTk0MDU0NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81Njc0Mzg2OGFiNzU0Njk3YWI2ZjA5MTU5NzE0ODU1OSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iMWM2OWM2NzQzMzY0MzU2YWE4OGU4NDEwZWNiYzlhNyA9ICQoJzxkaXYgaWQ9Imh0bWxfYjFjNjljNjc0MzM2NDM1NmFhODhlODQxMGVjYmM5YTciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5vcnRod2VzdDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNTY3NDM4NjhhYjc1NDY5N2FiNmYwOTE1OTcxNDg1NTkuc2V0Q29udGVudChodG1sX2IxYzY5YzY3NDMzNjQzNTZhYTg4ZTg0MTBlY2JjOWE3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzRiMTJhMTNmNDI5ODRiOTdiZTM4ZDE0ZWY1Y2I2MGZlLmJpbmRQb3B1cChwb3B1cF81Njc0Mzg2OGFiNzU0Njk3YWI2ZjA5MTU5NzE0ODU1OSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wZTczNDVmYzYwMGI0MmYxYjQ5MDNhOGE1MTA3MGY4YyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjgzNjEyNDcwMDAwMDAwNiwtNzkuMjA1NjM2MDk5OTk5OTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfMTVlMzhhMDIyYTAyNDlhNTlhOGE0ZTk0NGRhNGFkNzYpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOGZkMTlhMWNlYTU1NDY1MWFhZTEyYzI1ZDE0NzY4OTQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMmMzZTVkY2ZiNGE1NDQ5NjliMzg2YWRiYmNlNjI1ZmIgPSAkKCc8ZGl2IGlkPSJodG1sXzJjM2U1ZGNmYjRhNTQ0OTY5YjM4NmFkYmJjZTYyNWZiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5VcHBlciBSb3VnZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOGZkMTlhMWNlYTU1NDY1MWFhZTEyYzI1ZDE0NzY4OTQuc2V0Q29udGVudChodG1sXzJjM2U1ZGNmYjRhNTQ0OTY5YjM4NmFkYmJjZTYyNWZiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzBlNzM0NWZjNjAwYjQyZjFiNDkwM2E4YTUxMDcwZjhjLmJpbmRQb3B1cChwb3B1cF84ZmQxOWExY2VhNTU0NjUxYWFlMTJjMjVkMTQ3Njg5NCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83OGJjN2Q1M2M2YmQ0Yzk5YjY4MDY3MjI1ZWIzZTlhMyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY2Nzk2NywtNzkuMzY3Njc1M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82YjJhODE2NzU5MWM0NmY4OGVlYjIyODg0NGU1YzAyMCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82Njg5ZDE3ZmM0ODI0ZDlhYjY2YjQxM2Y4NGI4Y2RmOSA9ICQoJzxkaXYgaWQ9Imh0bWxfNjY4OWQxN2ZjNDgyNGQ5YWI2NmI0MTNmODRiOGNkZjkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlN0LiBKYW1lcyBUb3duIC8gQ2FiYmFnZXRvd248L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzZiMmE4MTY3NTkxYzQ2Zjg4ZWViMjI4ODQ0ZTVjMDIwLnNldENvbnRlbnQoaHRtbF82Njg5ZDE3ZmM0ODI0ZDlhYjY2YjQxM2Y4NGI4Y2RmOSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83OGJjN2Q1M2M2YmQ0Yzk5YjY4MDY3MjI1ZWIzZTlhMy5iaW5kUG9wdXAocG9wdXBfNmIyYTgxNjc1OTFjNDZmODhlZWIyMjg4NDRlNWMwMjApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYTZmNDdlZDhmNGY2NDlkNGE5ZmQyNGRmNzJhN2ZhMzUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDg0MjkyLC03OS4zODIyODAyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzQ2ZGM5ZDhmZjRjZDQwNWY4NTc0MjRjMzgyZWIxZGUzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzMwYTdhY2IwNmE5NDQwMzZhYWUwMmRmYzhkNTI4OWE4ID0gJCgnPGRpdiBpZD0iaHRtbF8zMGE3YWNiMDZhOTQ0MDM2YWFlMDJkZmM4ZDUyODlhOCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Rmlyc3QgQ2FuYWRpYW4gUGxhY2UgLyBVbmRlcmdyb3VuZCBjaXR5PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80NmRjOWQ4ZmY0Y2Q0MDVmODU3NDI0YzM4MmViMWRlMy5zZXRDb250ZW50KGh0bWxfMzBhN2FjYjA2YTk0NDAzNmFhZTAyZGZjOGQ1Mjg5YTgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYTZmNDdlZDhmNGY2NDlkNGE5ZmQyNGRmNzJhN2ZhMzUuYmluZFBvcHVwKHBvcHVwXzQ2ZGM5ZDhmZjRjZDQwNWY4NTc0MjRjMzgyZWIxZGUzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzRiNmU1Y2E1YTIwYTQ3Y2RhOTY1M2I1YWE4MzNmYzFjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUzNjUzNjAwMDAwMDA1LC03OS41MDY5NDM2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2MwNDU1MDFmYTk5NjRlMzI5MjcwMWNhZjRmYjZkOTNiID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzg0MDhiMzMzNDQwZjRjOWE4N2Q5YjA0NTE5MDVjNzBhID0gJCgnPGRpdiBpZD0iaHRtbF84NDA4YjMzMzQ0MGY0YzlhODdkOWIwNDUxOTA1YzcwYSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VGhlIEtpbmdzd2F5IC8gTW9udGdvbWVyeSBSb2FkIC8gT2xkIE1pbGwgTm9ydGg8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2MwNDU1MDFmYTk5NjRlMzI5MjcwMWNhZjRmYjZkOTNiLnNldENvbnRlbnQoaHRtbF84NDA4YjMzMzQ0MGY0YzlhODdkOWIwNDUxOTA1YzcwYSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80YjZlNWNhNWEyMGE0N2NkYTk2NTNiNWFhODMzZmMxYy5iaW5kUG9wdXAocG9wdXBfYzA0NTUwMWZhOTk2NGUzMjkyNzAxY2FmNGZiNmQ5M2IpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMjhiN2NlOTEzYzcwNGQzZWIzYjExZWMwMDI2MWZjYTQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NjU4NTk5LC03OS4zODMxNTk5MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8xNWUzOGEwMjJhMDI0OWE1OWE4YTRlOTQ0ZGE0YWQ3Nik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83MGRjMTBjNGMyMjI0MGE1YTg5MmZiZmMwNDQ3NDhmNSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mN2VjYjBhMGYwNjg0MTE1YmY2MDE5MmFmODExZmNmYyA9ICQoJzxkaXYgaWQ9Imh0bWxfZjdlY2IwYTBmMDY4NDExNWJmNjAxOTJhZjgxMWZjZmMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNodXJjaCBhbmQgV2VsbGVzbGV5PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83MGRjMTBjNGMyMjI0MGE1YTg5MmZiZmMwNDQ3NDhmNS5zZXRDb250ZW50KGh0bWxfZjdlY2IwYTBmMDY4NDExNWJmNjAxOTJhZjgxMWZjZmMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjhiN2NlOTEzYzcwNGQzZWIzYjExZWMwMDI2MWZjYTQuYmluZFBvcHVwKHBvcHVwXzcwZGMxMGM0YzIyMjQwYTVhODkyZmJmYzA0NDc0OGY1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2UzNGZiN2FmMTU0MjRkODA5NDY2ZWYwMGFhZTcwZmQ1ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjYyNzQzOSwtNzkuMzIxNTU4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzg2NDc2YTA4ZDRjZTQxYjQ5MzBjMmIwNjdhMTZlMDllID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzA0ZjY1MzE2ZWE2MDQ4NGRhNjU3M2Y0Yjc1YzAzYjE4ID0gJCgnPGRpdiBpZD0iaHRtbF8wNGY2NTMxNmVhNjA0ODRkYTY1NzNmNGI3NWMwM2IxOCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnVzaW5lc3MgcmVwbHkgbWFpbCBQcm9jZXNzaW5nIENlbnRyRTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfODY0NzZhMDhkNGNlNDFiNDkzMGMyYjA2N2ExNmUwOWUuc2V0Q29udGVudChodG1sXzA0ZjY1MzE2ZWE2MDQ4NGRhNjU3M2Y0Yjc1YzAzYjE4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2UzNGZiN2FmMTU0MjRkODA5NDY2ZWYwMGFhZTcwZmQ1LmJpbmRQb3B1cChwb3B1cF84NjQ3NmEwOGQ0Y2U0MWI0OTMwYzJiMDY3YTE2ZTA5ZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zMjEzOGQ1ODI3MjE0ZDBhOWViYTlmY2E0MWY2NmJkOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjYzNjI1NzksLTc5LjQ5ODUwOTA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzA0OTJhMDVjOWUxYTQyZDhhNzZmMDMwZDlhMjczOTdmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzk4NTNhNzJkZjc1ODRiZmFhOTA2MDUwY2ExMTFiZmEzID0gJCgnPGRpdiBpZD0iaHRtbF85ODUzYTcyZGY3NTg0YmZhYTkwNjA1MGNhMTExYmZhMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+T2xkIE1pbGwgU291dGggLyBLaW5nJiMzOTtzIE1pbGwgUGFyayAvIFN1bm55bGVhIC8gSHVtYmVyIEJheSAvIE1pbWljbyBORSAvIFRoZSBRdWVlbnN3YXkgRWFzdCAvIFJveWFsIFlvcmsgU291dGggRWFzdCAvIEtpbmdzd2F5IFBhcmsgU291dGggRWFzdDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDQ5MmEwNWM5ZTFhNDJkOGE3NmYwMzBkOWEyNzM5N2Yuc2V0Q29udGVudChodG1sXzk4NTNhNzJkZjc1ODRiZmFhOTA2MDUwY2ExMTFiZmEzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzMyMTM4ZDU4MjcyMTRkMGE5ZWJhOWZjYTQxZjY2YmQ4LmJpbmRQb3B1cChwb3B1cF8wNDkyYTA1YzllMWE0MmQ4YTc2ZjAzMGQ5YTI3Mzk3Zik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jNGEzYzIzOWVjY2Q0ZDM1OTM5YzVhOTY1ZTJjMmY3OSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjYyODg0MDgsLTc5LjUyMDk5OTQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwXzE1ZTM4YTAyMmEwMjQ5YTU5YThhNGU5NDRkYTRhZDc2KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzkwNWIyMTRlM2IzMTQ3Yjg5OTIwZjEzMTJhNDA0Y2I4ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2ExZDFiZTAzYTg3NzQ2NDI5OTVlZTI0ZTZkZGJlOWNlID0gJCgnPGRpdiBpZD0iaHRtbF9hMWQxYmUwM2E4Nzc0NjQyOTk1ZWUyNGU2ZGRiZTljZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TWltaWNvIE5XIC8gVGhlIFF1ZWVuc3dheSBXZXN0IC8gU291dGggb2YgQmxvb3IgLyBLaW5nc3dheSBQYXJrIFNvdXRoIFdlc3QgLyBSb3lhbCBZb3JrIFNvdXRoIFdlc3Q8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzkwNWIyMTRlM2IzMTQ3Yjg5OTIwZjEzMTJhNDA0Y2I4LnNldENvbnRlbnQoaHRtbF9hMWQxYmUwM2E4Nzc0NjQyOTk1ZWUyNGU2ZGRiZTljZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jNGEzYzIzOWVjY2Q0ZDM1OTM5YzVhOTY1ZTJjMmY3OS5iaW5kUG9wdXAocG9wdXBfOTA1YjIxNGUzYjMxNDdiODk5MjBmMTMxMmE0MDRjYjgpOwoKICAgICAgICAgICAgCiAgICAgICAgCjwvc2NyaXB0Pg== onload=\"this.contentDocument.open();this.contentDocument.write(atob(this.getAttribute('data-html')));this.contentDocument.close();\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
],
"text/plain": [
"<folium.folium.Map at 0x7fea38648080>"
]
},
"execution_count": 335,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# create map of Manhattan 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, label in zip(Toronto_Neighb['Latitude'], Toronto_Neighb['Longitude'], Toronto_Neighb['Neighborhood']):\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": []
},
{
"cell_type": "code",
"execution_count": 336,
"metadata": {},
"outputs": [],
"source": [
"## Exploring Neighborhoods in Toronto!\n",
"\n",
"def getNearbyVenues(names, latitudes, longitudes, radius=500):\n",
" \n",
" venues_list=[]\n",
" for name, lat, lng in zip(names, latitudes, longitudes):\n",
" print(name)\n",
" \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": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 337,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
},
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Broad Channel\n",
"Parkwoods\n",
"Victoria Village\n",
"Regent Park / Harbourfront\n",
"Lawrence Manor / Lawrence Heights\n",
"Queen's Park / Ontario Provincial Government\n",
"Islington Avenue\n",
"Malvern / Rouge\n",
"Don Mills\n",
"Parkview Hill / Woodbine Gardens\n",
"Garden District-Ryerson\n",
"Glencairn\n",
"West Deane Park / Princess Gardens / Martin Grove / Islington / Cloverdale\n",
"Rouge Hill / Port Union / Highland Creek\n",
"Don Mills\n",
"Woodbine Heights\n",
"St. James Town\n",
"Humewood-Cedarvale\n",
"Eringate / Bloordale Gardens / Old Burnhamthorpe / Markland Wood\n",
"Guildwood / Morningside / West Hill\n",
"The Beaches\n",
"Berczy Park\n",
"Caledonia-Fairbanks\n",
"Woburn\n",
"Leaside\n",
"Central Bay Street\n",
"Christie\n",
"Cedarbrae\n",
"Hillcrest Village\n",
"Bathurst Manor / Wilson Heights / Downsview North\n",
"Thorncliffe Park\n",
"Richmond / Adelaide / King\n",
"Dufferin / Dovercourt Village\n",
"Scarborough Village\n",
"Fairview / Henry Farm / Oriole\n",
"Northwood Park / York University\n",
"East Toronto\n",
"Harbourfront East / Union Station / Toronto Islands\n",
"Little Portugal / Trinity\n",
"Kennedy Park / Ionview / East Birchmount Park\n",
"Bayview Village\n",
"Downsview\n",
"The Danforth West / Riverdale\n",
"Toronto Dominion Centre / Design Exchange\n",
"Brockton / Parkdale Village / Exhibition Place\n",
"Golden Mile / Clairlea / Oakridge\n",
"York Mills / Silver Hills\n",
"Downsview\n",
"India Bazaar / The Beaches West\n",
"Commerce Court / Victoria Hotel\n",
"North Park / Maple Leaf Park / Upwood Park\n",
"Humber Summit\n",
"Cliffside / Cliffcrest / Scarborough Village West\n",
"Willowdale / Newtonbrook\n",
"Downsview\n",
"Studio District\n",
"Bedford Park / Lawrence Manor East\n",
"Del Ray / Mount Dennis / Keelsdale and Silverthorn\n",
"Humberlea / Emery\n",
"Birch Cliff / Cliffside West\n",
"Willowdale\n",
"Downsview\n",
"Lawrence Park\n",
"Roselawn\n",
"Runnymede / The Junction North\n",
"Weston\n",
"Dorset Park / Wexford Heights / Scarborough Town Centre\n",
"York Mills West\n",
"Davisville North\n",
"Forest Hill North & West\n",
"High Park / The Junction South\n",
"Westmount\n",
"Wexford / Maryvale\n",
"Willowdale\n",
"North Toronto West\n",
"The Annex / North Midtown / Yorkville\n",
"Parkdale / Roncesvalles\n",
"Canada Post Gateway Processing Centre\n",
"Kingsview Village / St. Phillips / Martin Grove Gardens / Richview Gardens\n",
"Agincourt\n",
"Davisville\n",
"University of Toronto / Harbord\n",
"Runnymede / Swansea\n",
"Clarks Corners / Tam O'Shanter / Sullivan\n",
"Moore Park / Summerhill East\n",
"Kensington Market / Chinatown / Grange Park\n",
"Milliken / Agincourt North / Steeles East / L'Amoreaux East\n",
"Summerhill West / Rathnelly / South Hill / Forest Hill SE / Deer Park\n",
"CN Tower / King and Spadina / Railway Lands / Harbourfront West / Bathurst\n",
"New Toronto / Mimico South / Humber Bay Shores\n",
"South Steeles / Silverstone / Humbergate / Jamestown / Mount Olive / Beaumond Heights / Thistletown / Albion Gardens\n",
"Steeles West / L'Amoreaux West\n",
"Rosedale\n",
"Stn A PO Boxes\n",
"Alderwood / Long Branch\n",
"Northwest\n",
"Upper Rouge\n",
"St. James Town / Cabbagetown\n",
"First Canadian Place / Underground city\n",
"The Kingsway / Montgomery Road / Old Mill North\n",
"Church and Wellesley\n",
"Business reply mail Processing CentrE\n",
"Old Mill South / King's Mill Park / Sunnylea / Humber Bay / Mimico NE / The Queensway East / Royal York South East / Kingsway Park South East\n",
"Mimico NW / The Queensway West / South of Bloor / Kingsway Park South West / Royal York South West\n"
]
}
],
"source": [
"#### Running the above function on each neighborhood and\n",
"## creating a new dataframe called *toronto_venues*.\n",
"\n",
"toronto_venues = getNearbyVenues(names=Toronto_Neighb['Neighborhood'],\n",
" latitudes=Toronto_Neighb['Latitude'],\n",
" longitudes=Toronto_Neighb['Longitude'],\n",
" )\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 338,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(2134, 7)\n"
]
},
{
"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>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",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Broad Channel</td>\n",
" <td>40.603027</td>\n",
" <td>-73.820055</td>\n",
" <td>Buster's Marine Service</td>\n",
" <td>40.599103</td>\n",
" <td>-73.820974</td>\n",
" <td>Sporting Goods Shop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Broad Channel</td>\n",
" <td>40.603027</td>\n",
" <td>-73.820055</td>\n",
" <td>All American Deli</td>\n",
" <td>40.605988</td>\n",
" <td>-73.819876</td>\n",
" <td>Deli / Bodega</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Broad Channel</td>\n",
" <td>40.603027</td>\n",
" <td>-73.820055</td>\n",
" <td>Iroquois Yacht Club</td>\n",
" <td>40.604626</td>\n",
" <td>-73.817993</td>\n",
" <td>Other Nightlife</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Broad Channel</td>\n",
" <td>40.603027</td>\n",
" <td>-73.820055</td>\n",
" <td>Grassy Point Bar And Grill</td>\n",
" <td>40.600190</td>\n",
" <td>-73.820306</td>\n",
" <td>Dive Bar</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Broad Channel</td>\n",
" <td>40.603027</td>\n",
" <td>-73.820055</td>\n",
" <td>Tommy's Pizza</td>\n",
" <td>40.606454</td>\n",
" <td>-73.819819</td>\n",
" <td>Pizza Place</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Neighborhood Neighborhood Latitude Neighborhood Longitude \\\n",
"0 Broad Channel 40.603027 -73.820055 \n",
"1 Broad Channel 40.603027 -73.820055 \n",
"2 Broad Channel 40.603027 -73.820055 \n",
"3 Broad Channel 40.603027 -73.820055 \n",
"4 Broad Channel 40.603027 -73.820055 \n",
"\n",
" Venue Venue Latitude Venue Longitude \\\n",
"0 Buster's Marine Service 40.599103 -73.820974 \n",
"1 All American Deli 40.605988 -73.819876 \n",
"2 Iroquois Yacht Club 40.604626 -73.817993 \n",
"3 Grassy Point Bar And Grill 40.600190 -73.820306 \n",
"4 Tommy's Pizza 40.606454 -73.819819 \n",
"\n",
" Venue Category \n",
"0 Sporting Goods Shop \n",
"1 Deli / Bodega \n",
"2 Other Nightlife \n",
"3 Dive Bar \n",
"4 Pizza Place "
]
},
"execution_count": 338,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#### Let's check the size of the resulting dataframe\n",
"\n",
"print(toronto_venues.shape)\n",
"toronto_venues.head()"
]
},
{
"cell_type": "code",
"execution_count": 341,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>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>Agincourt</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>Alderwood / Long Branch</th>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Bathurst Manor / Wilson Heights / Downsview North</th>\n",
" <td>22</td>\n",
" <td>22</td>\n",
" <td>22</td>\n",
" <td>22</td>\n",
" <td>22</td>\n",
" <td>22</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Bayview Village</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>Bedford Park / Lawrence Manor East</th>\n",
" <td>22</td>\n",
" <td>22</td>\n",
" <td>22</td>\n",
" <td>22</td>\n",
" <td>22</td>\n",
" <td>22</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Berczy Park</th>\n",
" <td>56</td>\n",
" <td>56</td>\n",
" <td>56</td>\n",
" <td>56</td>\n",
" <td>56</td>\n",
" <td>56</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Birch Cliff / Cliffside West</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>Broad Channel</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>Brockton / Parkdale Village / Exhibition Place</th>\n",
" <td>24</td>\n",
" <td>24</td>\n",
" <td>24</td>\n",
" <td>24</td>\n",
" <td>24</td>\n",
" <td>24</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Business reply mail Processing CentrE</th>\n",
" <td>18</td>\n",
" <td>18</td>\n",
" <td>18</td>\n",
" <td>18</td>\n",
" <td>18</td>\n",
" <td>18</td>\n",
" </tr>\n",
" <tr>\n",
" <th>CN Tower / King and Spadina / Railway Lands / Harbourfront West / Bathurst</th>\n",
" <td>18</td>\n",
" <td>18</td>\n",
" <td>18</td>\n",
" <td>18</td>\n",
" <td>18</td>\n",
" <td>18</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Caledonia-Fairbanks</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>Canada Post Gateway Processing Centre</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>Cedarbrae</th>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Central Bay Street</th>\n",
" <td>64</td>\n",
" <td>64</td>\n",
" <td>64</td>\n",
" <td>64</td>\n",
" <td>64</td>\n",
" <td>64</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Christie</th>\n",
" <td>17</td>\n",
" <td>17</td>\n",
" <td>17</td>\n",
" <td>17</td>\n",
" <td>17</td>\n",
" <td>17</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Church and Wellesley</th>\n",
" <td>80</td>\n",
" <td>80</td>\n",
" <td>80</td>\n",
" <td>80</td>\n",
" <td>80</td>\n",
" <td>80</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Clarks Corners / Tam O'Shanter / Sullivan</th>\n",
" <td>14</td>\n",
" <td>14</td>\n",
" <td>14</td>\n",
" <td>14</td>\n",
" <td>14</td>\n",
" <td>14</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Cliffside / Cliffcrest / Scarborough Village West</th>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Commerce Court / Victoria Hotel</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>Davisville</th>\n",
" <td>33</td>\n",
" <td>33</td>\n",
" <td>33</td>\n",
" <td>33</td>\n",
" <td>33</td>\n",
" <td>33</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Davisville North</th>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Del Ray / Mount Dennis / Keelsdale and Silverthorn</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>Don Mills</th>\n",
" <td>28</td>\n",
" <td>28</td>\n",
" <td>28</td>\n",
" <td>28</td>\n",
" <td>28</td>\n",
" <td>28</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Dorset Park / Wexford Heights / Scarborough Town Centre</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>Downsview</th>\n",
" <td>15</td>\n",
" <td>15</td>\n",
" <td>15</td>\n",
" <td>15</td>\n",
" <td>15</td>\n",
" <td>15</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Dufferin / Dovercourt Village</th>\n",
" <td>15</td>\n",
" <td>15</td>\n",
" <td>15</td>\n",
" <td>15</td>\n",
" <td>15</td>\n",
" <td>15</td>\n",
" </tr>\n",
" <tr>\n",
" <th>East Toronto</th>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Eringate / Bloordale Gardens / Old Burnhamthorpe / Markland Wood</th>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Fairview / Henry Farm / Oriole</th>\n",
" <td>65</td>\n",
" <td>65</td>\n",
" <td>65</td>\n",
" <td>65</td>\n",
" <td>65</td>\n",
" <td>65</td>\n",
" </tr>\n",
" <tr>\n",
" <th>First Canadian Place / Underground city</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>Forest Hill North &amp; 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",
" <tr>\n",
" <th>Garden District-Ryerson</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>Glencairn</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>Golden Mile / Clairlea / Oakridge</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>Guildwood / Morningside / West Hill</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>Harbourfront East / Union Station / Toronto Islands</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>High Park / The Junction South</th>\n",
" <td>23</td>\n",
" <td>23</td>\n",
" <td>23</td>\n",
" <td>23</td>\n",
" <td>23</td>\n",
" <td>23</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Hillcrest Village</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>Humber Summit</th>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Humberlea / Emery</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>Humewood-Cedarvale</th>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>India Bazaar / The Beaches West</th>\n",
" <td>19</td>\n",
" <td>19</td>\n",
" <td>19</td>\n",
" <td>19</td>\n",
" <td>19</td>\n",
" <td>19</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Kennedy Park / Ionview / East Birchmount Park</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>Kensington Market / Chinatown / Grange Park</th>\n",
" <td>61</td>\n",
" <td>61</td>\n",
" <td>61</td>\n",
" <td>61</td>\n",
" <td>61</td>\n",
" <td>61</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Kingsview Village / St. Phillips / Martin Grove Gardens / Richview Gardens</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>Lawrence Manor / Lawrence Heights</th>\n",
" <td>15</td>\n",
" <td>15</td>\n",
" <td>15</td>\n",
" <td>15</td>\n",
" <td>15</td>\n",
" <td>15</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Lawrence Park</th>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Leaside</th>\n",
" <td>34</td>\n",
" <td>34</td>\n",
" <td>34</td>\n",
" <td>34</td>\n",
" <td>34</td>\n",
" <td>34</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Little Portugal / Trinity</th>\n",
" <td>45</td>\n",
" <td>45</td>\n",
" <td>45</td>\n",
" <td>45</td>\n",
" <td>45</td>\n",
" <td>45</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Malvern / Rouge</th>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Milliken / Agincourt North / Steeles East / L'Amoreaux East</th>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Mimico NW / The Queensway West / South of Bloor / Kingsway Park South West / Royal York South West</th>\n",
" <td>14</td>\n",
" <td>14</td>\n",
" <td>14</td>\n",
" <td>14</td>\n",
" <td>14</td>\n",
" <td>14</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Moore Park / Summerhill East</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>New Toronto / Mimico South / Humber Bay Shores</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>North Park / Maple Leaf Park / Upwood Park</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>North Toronto West</th>\n",
" <td>21</td>\n",
" <td>21</td>\n",
" <td>21</td>\n",
" <td>21</td>\n",
" <td>21</td>\n",
" <td>21</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Northwest</th>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Northwood Park / York University</th>\n",
" <td>6</td>\n",
" <td>6</td>\n",
" <td>6</td>\n",
" <td>6</td>\n",
" <td>6</td>\n",
" <td>6</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Old Mill South / King's Mill Park / Sunnylea / Humber Bay / Mimico NE / The Queensway East / Royal York South East / Kingsway Park South 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>Parkdale / Roncesvalles</th>\n",
" <td>14</td>\n",
" <td>14</td>\n",
" <td>14</td>\n",
" <td>14</td>\n",
" <td>14</td>\n",
" <td>14</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Parkview Hill / Woodbine Gardens</th>\n",
" <td>11</td>\n",
" <td>11</td>\n",
" <td>11</td>\n",
" <td>11</td>\n",
" <td>11</td>\n",
" <td>11</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Parkwoods</th>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Queen's Park / Ontario Provincial Government</th>\n",
" <td>31</td>\n",
" <td>31</td>\n",
" <td>31</td>\n",
" <td>31</td>\n",
" <td>31</td>\n",
" <td>31</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Regent Park / Harbourfront</th>\n",
" <td>46</td>\n",
" <td>46</td>\n",
" <td>46</td>\n",
" <td>46</td>\n",
" <td>46</td>\n",
" <td>46</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Richmond / Adelaide / King</th>\n",
" <td>95</td>\n",
" <td>95</td>\n",
" <td>95</td>\n",
" <td>95</td>\n",
" <td>95</td>\n",
" <td>95</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Rosedale</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>Roselawn</th>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Rouge Hill / Port Union / Highland Creek</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>Runnymede / Swansea</th>\n",
" <td>38</td>\n",
" <td>38</td>\n",
" <td>38</td>\n",
" <td>38</td>\n",
" <td>38</td>\n",
" <td>38</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Runnymede / The Junction North</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>Scarborough Village</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>South Steeles / Silverstone / Humbergate / Jamestown / Mount Olive / Beaumond Heights / Thistletown / Albion Gardens</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>St. James Town</th>\n",
" <td>79</td>\n",
" <td>79</td>\n",
" <td>79</td>\n",
" <td>79</td>\n",
" <td>79</td>\n",
" <td>79</td>\n",
" </tr>\n",
" <tr>\n",
" <th>St. James Town / Cabbagetown</th>\n",
" <td>45</td>\n",
" <td>45</td>\n",
" <td>45</td>\n",
" <td>45</td>\n",
" <td>45</td>\n",
" <td>45</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Steeles West / L'Amoreaux West</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>Stn A PO Boxes</th>\n",
" <td>94</td>\n",
" <td>94</td>\n",
" <td>94</td>\n",
" <td>94</td>\n",
" <td>94</td>\n",
" <td>94</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Studio District</th>\n",
" <td>40</td>\n",
" <td>40</td>\n",
" <td>40</td>\n",
" <td>40</td>\n",
" <td>40</td>\n",
" <td>40</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Summerhill West / Rathnelly / South Hill / Forest Hill SE / Deer Park</th>\n",
" <td>17</td>\n",
" <td>17</td>\n",
" <td>17</td>\n",
" <td>17</td>\n",
" <td>17</td>\n",
" <td>17</td>\n",
" </tr>\n",
" <tr>\n",
" <th>The Annex / North Midtown / Yorkville</th>\n",
" <td>21</td>\n",
" <td>21</td>\n",
" <td>21</td>\n",
" <td>21</td>\n",
" <td>21</td>\n",
" <td>21</td>\n",
" </tr>\n",
" <tr>\n",
" <th>The Beaches</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>The Danforth West / Riverdale</th>\n",
" <td>43</td>\n",
" <td>43</td>\n",
" <td>43</td>\n",
" <td>43</td>\n",
" <td>43</td>\n",
" <td>43</td>\n",
" </tr>\n",
" <tr>\n",
" <th>The Kingsway / Montgomery Road / Old Mill North</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>Thorncliffe Park</th>\n",
" <td>20</td>\n",
" <td>20</td>\n",
" <td>20</td>\n",
" <td>20</td>\n",
" <td>20</td>\n",
" <td>20</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Toronto Dominion Centre / Design Exchange</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>University of Toronto / Harbord</th>\n",
" <td>34</td>\n",
" <td>34</td>\n",
" <td>34</td>\n",
" <td>34</td>\n",
" <td>34</td>\n",
" <td>34</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Victoria Village</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>West Deane Park / Princess Gardens / Martin Grove / Islington / Cloverdale</th>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Westmount</th>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" <td>8</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Weston</th>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Wexford / Maryvale</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>Willowdale</th>\n",
" <td>39</td>\n",
" <td>39</td>\n",
" <td>39</td>\n",
" <td>39</td>\n",
" <td>39</td>\n",
" <td>39</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 Heights</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>York Mills West</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",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Neighborhood Latitude \\\n",
"Neighborhood \n",
"Agincourt 4 \n",
"Alderwood / Long Branch 8 \n",
"Bathurst Manor / Wilson Heights / Downsview North 22 \n",
"Bayview Village 4 \n",
"Bedford Park / Lawrence Manor East 22 \n",
"Berczy Park 56 \n",
"Birch Cliff / Cliffside West 4 \n",
"Broad Channel 5 \n",
"Brockton / Parkdale Village / Exhibition Place 24 \n",
"Business reply mail Processing CentrE 18 \n",
"CN Tower / King and Spadina / Railway Lands / H... 18 \n",
"Caledonia-Fairbanks 4 \n",
"Canada Post Gateway Processing Centre 13 \n",
"Cedarbrae 8 \n",
"Central Bay Street 64 \n",
"Christie 17 \n",
"Church and Wellesley 80 \n",
"Clarks Corners / Tam O'Shanter / Sullivan 14 \n",
"Cliffside / Cliffcrest / Scarborough Village West 3 \n",
"Commerce Court / Victoria Hotel 100 \n",
"Davisville 33 \n",
"Davisville North 8 \n",
"Del Ray / Mount Dennis / Keelsdale and Silverthorn 5 \n",
"Don Mills 28 \n",
"Dorset Park / Wexford Heights / Scarborough Tow... 7 \n",
"Downsview 15 \n",
"Dufferin / Dovercourt Village 15 \n",
"East Toronto 3 \n",
"Eringate / Bloordale Gardens / Old Burnhamthorp... 8 \n",
"Fairview / Henry Farm / Oriole 65 \n",
"First Canadian Place / Underground city 100 \n",
"Forest Hill North & West 5 \n",
"Garden District-Ryerson 100 \n",
"Glencairn 4 \n",
"Golden Mile / Clairlea / Oakridge 10 \n",
"Guildwood / Morningside / West Hill 7 \n",
"Harbourfront East / Union Station / Toronto Isl... 100 \n",
"High Park / The Junction South 23 \n",
"Hillcrest Village 5 \n",
"Humber Summit 1 \n",
"Humberlea / Emery 2 \n",
"Humewood-Cedarvale 3 \n",
"India Bazaar / The Beaches West 19 \n",
"Kennedy Park / Ionview / East Birchmount Park 4 \n",
"Kensington Market / Chinatown / Grange Park 61 \n",
"Kingsview Village / St. Phillips / Martin Grove... 4 \n",
"Lawrence Manor / Lawrence Heights 15 \n",
"Lawrence Park 3 \n",
"Leaside 34 \n",
"Little Portugal / Trinity 45 \n",
"Malvern / Rouge 1 \n",
"Milliken / Agincourt North / Steeles East / L'A... 3 \n",
"Mimico NW / The Queensway West / South of Bloor... 14 \n",
"Moore Park / Summerhill East 4 \n",
"New Toronto / Mimico South / Humber Bay Shores 13 \n",
"North Park / Maple Leaf Park / Upwood Park 4 \n",
"North Toronto West 21 \n",
"Northwest 3 \n",
"Northwood Park / York University 6 \n",
"Old Mill South / King's Mill Park / Sunnylea / ... 2 \n",
"Parkdale / Roncesvalles 14 \n",
"Parkview Hill / Woodbine Gardens 11 \n",
"Parkwoods 3 \n",
"Queen's Park / Ontario Provincial Government 31 \n",
"Regent Park / Harbourfront 46 \n",
"Richmond / Adelaide / King 95 \n",
"Rosedale 4 \n",
"Roselawn 1 \n",
"Rouge Hill / Port Union / Highland Creek 2 \n",
"Runnymede / Swansea 38 \n",
"Runnymede / The Junction North 4 \n",
"Scarborough Village 2 \n",
"South Steeles / Silverstone / Humbergate / Jame... 9 \n",
"St. James Town 79 \n",
"St. James Town / Cabbagetown 45 \n",
"Steeles West / L'Amoreaux West 12 \n",
"Stn A PO Boxes 94 \n",
"Studio District 40 \n",
"Summerhill West / Rathnelly / South Hill / Fore... 17 \n",
"The Annex / North Midtown / Yorkville 21 \n",
"The Beaches 4 \n",
"The Danforth West / Riverdale 43 \n",
"The Kingsway / Montgomery Road / Old Mill North 2 \n",
"Thorncliffe Park 20 \n",
"Toronto Dominion Centre / Design Exchange 100 \n",
"University of Toronto / Harbord 34 \n",
"Victoria Village 4 \n",
"West Deane Park / Princess Gardens / Martin Gro... 1 \n",
"Westmount 8 \n",
"Weston 1 \n",
"Wexford / Maryvale 4 \n",
"Willowdale 39 \n",
"Woburn 4 \n",
"Woodbine Heights 7 \n",
"York Mills West 4 \n",
"\n",
" Neighborhood Longitude \\\n",
"Neighborhood \n",
"Agincourt 4 \n",
"Alderwood / Long Branch 8 \n",
"Bathurst Manor / Wilson Heights / Downsview North 22 \n",
"Bayview Village 4 \n",
"Bedford Park / Lawrence Manor East 22 \n",
"Berczy Park 56 \n",
"Birch Cliff / Cliffside West 4 \n",
"Broad Channel 5 \n",
"Brockton / Parkdale Village / Exhibition Place 24 \n",
"Business reply mail Processing CentrE 18 \n",
"CN Tower / King and Spadina / Railway Lands / H... 18 \n",
"Caledonia-Fairbanks 4 \n",
"Canada Post Gateway Processing Centre 13 \n",
"Cedarbrae 8 \n",
"Central Bay Street 64 \n",
"Christie 17 \n",
"Church and Wellesley 80 \n",
"Clarks Corners / Tam O'Shanter / Sullivan 14 \n",
"Cliffside / Cliffcrest / Scarborough Village West 3 \n",
"Commerce Court / Victoria Hotel 100 \n",
"Davisville 33 \n",
"Davisville North 8 \n",
"Del Ray / Mount Dennis / Keelsdale and Silverthorn 5 \n",
"Don Mills 28 \n",
"Dorset Park / Wexford Heights / Scarborough Tow... 7 \n",
"Downsview 15 \n",
"Dufferin / Dovercourt Village 15 \n",
"East Toronto 3 \n",
"Eringate / Bloordale Gardens / Old Burnhamthorp... 8 \n",
"Fairview / Henry Farm / Oriole 65 \n",
"First Canadian Place / Underground city 100 \n",
"Forest Hill North & West 5 \n",
"Garden District-Ryerson 100 \n",
"Glencairn 4 \n",
"Golden Mile / Clairlea / Oakridge 10 \n",
"Guildwood / Morningside / West Hill 7 \n",
"Harbourfront East / Union Station / Toronto Isl... 100 \n",
"High Park / The Junction South 23 \n",
"Hillcrest Village 5 \n",
"Humber Summit 1 \n",
"Humberlea / Emery 2 \n",
"Humewood-Cedarvale 3 \n",
"India Bazaar / The Beaches West 19 \n",
"Kennedy Park / Ionview / East Birchmount Park 4 \n",
"Kensington Market / Chinatown / Grange Park 61 \n",
"Kingsview Village / St. Phillips / Martin Grove... 4 \n",
"Lawrence Manor / Lawrence Heights 15 \n",
"Lawrence Park 3 \n",
"Leaside 34 \n",
"Little Portugal / Trinity 45 \n",
"Malvern / Rouge 1 \n",
"Milliken / Agincourt North / Steeles East / L'A... 3 \n",
"Mimico NW / The Queensway West / South of Bloor... 14 \n",
"Moore Park / Summerhill East 4 \n",
"New Toronto / Mimico South / Humber Bay Shores 13 \n",
"North Park / Maple Leaf Park / Upwood Park 4 \n",
"North Toronto West 21 \n",
"Northwest 3 \n",
"Northwood Park / York University 6 \n",
"Old Mill South / King's Mill Park / Sunnylea / ... 2 \n",
"Parkdale / Roncesvalles 14 \n",
"Parkview Hill / Woodbine Gardens 11 \n",
"Parkwoods 3 \n",
"Queen's Park / Ontario Provincial Government 31 \n",
"Regent Park / Harbourfront 46 \n",
"Richmond / Adelaide / King 95 \n",
"Rosedale 4 \n",
"Roselawn 1 \n",
"Rouge Hill / Port Union / Highland Creek 2 \n",
"Runnymede / Swansea 38 \n",
"Runnymede / The Junction North 4 \n",
"Scarborough Village 2 \n",
"South Steeles / Silverstone / Humbergate / Jame... 9 \n",
"St. James Town 79 \n",
"St. James Town / Cabbagetown 45 \n",
"Steeles West / L'Amoreaux West 12 \n",
"Stn A PO Boxes 94 \n",
"Studio District 40 \n",
"Summerhill West / Rathnelly / South Hill / Fore... 17 \n",
"The Annex / North Midtown / Yorkville 21 \n",
"The Beaches 4 \n",
"The Danforth West / Riverdale 43 \n",
"The Kingsway / Montgomery Road / Old Mill North 2 \n",
"Thorncliffe Park 20 \n",
"Toronto Dominion Centre / Design Exchange 100 \n",
"University of Toronto / Harbord 34 \n",
"Victoria Village 4 \n",
"West Deane Park / Princess Gardens / Martin Gro... 1 \n",
"Westmount 8 \n",
"Weston 1 \n",
"Wexford / Maryvale 4 \n",
"Willowdale 39 \n",
"Woburn 4 \n",
"Woodbine Heights 7 \n",
"York Mills West 4 \n",
"\n",
" Venue Venue Latitude \\\n",
"Neighborhood \n",
"Agincourt 4 4 \n",
"Alderwood / Long Branch 8 8 \n",
"Bathurst Manor / Wilson Heights / Downsview North 22 22 \n",
"Bayview Village 4 4 \n",
"Bedford Park / Lawrence Manor East 22 22 \n",
"Berczy Park 56 56 \n",
"Birch Cliff / Cliffside West 4 4 \n",
"Broad Channel 5 5 \n",
"Brockton / Parkdale Village / Exhibition Place 24 24 \n",
"Business reply mail Processing CentrE 18 18 \n",
"CN Tower / King and Spadina / Railway Lands / H... 18 18 \n",
"Caledonia-Fairbanks 4 4 \n",
"Canada Post Gateway Processing Centre 13 13 \n",
"Cedarbrae 8 8 \n",
"Central Bay Street 64 64 \n",
"Christie 17 17 \n",
"Church and Wellesley 80 80 \n",
"Clarks Corners / Tam O'Shanter / Sullivan 14 14 \n",
"Cliffside / Cliffcrest / Scarborough Village West 3 3 \n",
"Commerce Court / Victoria Hotel 100 100 \n",
"Davisville 33 33 \n",
"Davisville North 8 8 \n",
"Del Ray / Mount Dennis / Keelsdale and Silverthorn 5 5 \n",
"Don Mills 28 28 \n",
"Dorset Park / Wexford Heights / Scarborough Tow... 7 7 \n",
"Downsview 15 15 \n",
"Dufferin / Dovercourt Village 15 15 \n",
"East Toronto 3 3 \n",
"Eringate / Bloordale Gardens / Old Burnhamthorp... 8 8 \n",
"Fairview / Henry Farm / Oriole 65 65 \n",
"First Canadian Place / Underground city 100 100 \n",
"Forest Hill North & West 5 5 \n",
"Garden District-Ryerson 100 100 \n",
"Glencairn 4 4 \n",
"Golden Mile / Clairlea / Oakridge 10 10 \n",
"Guildwood / Morningside / West Hill 7 7 \n",
"Harbourfront East / Union Station / Toronto Isl... 100 100 \n",
"High Park / The Junction South 23 23 \n",
"Hillcrest Village 5 5 \n",
"Humber Summit 1 1 \n",
"Humberlea / Emery 2 2 \n",
"Humewood-Cedarvale 3 3 \n",
"India Bazaar / The Beaches West 19 19 \n",
"Kennedy Park / Ionview / East Birchmount Park 4 4 \n",
"Kensington Market / Chinatown / Grange Park 61 61 \n",
"Kingsview Village / St. Phillips / Martin Grove... 4 4 \n",
"Lawrence Manor / Lawrence Heights 15 15 \n",
"Lawrence Park 3 3 \n",
"Leaside 34 34 \n",
"Little Portugal / Trinity 45 45 \n",
"Malvern / Rouge 1 1 \n",
"Milliken / Agincourt North / Steeles East / L'A... 3 3 \n",
"Mimico NW / The Queensway West / South of Bloor... 14 14 \n",
"Moore Park / Summerhill East 4 4 \n",
"New Toronto / Mimico South / Humber Bay Shores 13 13 \n",
"North Park / Maple Leaf Park / Upwood Park 4 4 \n",
"North Toronto West 21 21 \n",
"Northwest 3 3 \n",
"Northwood Park / York University 6 6 \n",
"Old Mill South / King's Mill Park / Sunnylea / ... 2 2 \n",
"Parkdale / Roncesvalles 14 14 \n",
"Parkview Hill / Woodbine Gardens 11 11 \n",
"Parkwoods 3 3 \n",
"Queen's Park / Ontario Provincial Government 31 31 \n",
"Regent Park / Harbourfront 46 46 \n",
"Richmond / Adelaide / King 95 95 \n",
"Rosedale 4 4 \n",
"Roselawn 1 1 \n",
"Rouge Hill / Port Union / Highland Creek 2 2 \n",
"Runnymede / Swansea 38 38 \n",
"Runnymede / The Junction North 4 4 \n",
"Scarborough Village 2 2 \n",
"South Steeles / Silverstone / Humbergate / Jame... 9 9 \n",
"St. James Town 79 79 \n",
"St. James Town / Cabbagetown 45 45 \n",
"Steeles West / L'Amoreaux West 12 12 \n",
"Stn A PO Boxes 94 94 \n",
"Studio District 40 40 \n",
"Summerhill West / Rathnelly / South Hill / Fore... 17 17 \n",
"The Annex / North Midtown / Yorkville 21 21 \n",
"The Beaches 4 4 \n",
"The Danforth West / Riverdale 43 43 \n",
"The Kingsway / Montgomery Road / Old Mill North 2 2 \n",
"Thorncliffe Park 20 20 \n",
"Toronto Dominion Centre / Design Exchange 100 100 \n",
"University of Toronto / Harbord 34 34 \n",
"Victoria Village 4 4 \n",
"West Deane Park / Princess Gardens / Martin Gro... 1 1 \n",
"Westmount 8 8 \n",
"Weston 1 1 \n",
"Wexford / Maryvale 4 4 \n",
"Willowdale 39 39 \n",
"Woburn 4 4 \n",
"Woodbine Heights 7 7 \n",
"York Mills West 4 4 \n",
"\n",
" Venue Longitude \\\n",
"Neighborhood \n",
"Agincourt 4 \n",
"Alderwood / Long Branch 8 \n",
"Bathurst Manor / Wilson Heights / Downsview North 22 \n",
"Bayview Village 4 \n",
"Bedford Park / Lawrence Manor East 22 \n",
"Berczy Park 56 \n",
"Birch Cliff / Cliffside West 4 \n",
"Broad Channel 5 \n",
"Brockton / Parkdale Village / Exhibition Place 24 \n",
"Business reply mail Processing CentrE 18 \n",
"CN Tower / King and Spadina / Railway Lands / H... 18 \n",
"Caledonia-Fairbanks 4 \n",
"Canada Post Gateway Processing Centre 13 \n",
"Cedarbrae 8 \n",
"Central Bay Street 64 \n",
"Christie 17 \n",
"Church and Wellesley 80 \n",
"Clarks Corners / Tam O'Shanter / Sullivan 14 \n",
"Cliffside / Cliffcrest / Scarborough Village West 3 \n",
"Commerce Court / Victoria Hotel 100 \n",
"Davisville 33 \n",
"Davisville North 8 \n",
"Del Ray / Mount Dennis / Keelsdale and Silverthorn 5 \n",
"Don Mills 28 \n",
"Dorset Park / Wexford Heights / Scarborough Tow... 7 \n",
"Downsview 15 \n",
"Dufferin / Dovercourt Village 15 \n",
"East Toronto 3 \n",
"Eringate / Bloordale Gardens / Old Burnhamthorp... 8 \n",
"Fairview / Henry Farm / Oriole 65 \n",
"First Canadian Place / Underground city 100 \n",
"Forest Hill North & West 5 \n",
"Garden District-Ryerson 100 \n",
"Glencairn 4 \n",
"Golden Mile / Clairlea / Oakridge 10 \n",
"Guildwood / Morningside / West Hill 7 \n",
"Harbourfront East / Union Station / Toronto Isl... 100 \n",
"High Park / The Junction South 23 \n",
"Hillcrest Village 5 \n",
"Humber Summit 1 \n",
"Humberlea / Emery 2 \n",
"Humewood-Cedarvale 3 \n",
"India Bazaar / The Beaches West 19 \n",
"Kennedy Park / Ionview / East Birchmount Park 4 \n",
"Kensington Market / Chinatown / Grange Park 61 \n",
"Kingsview Village / St. Phillips / Martin Grove... 4 \n",
"Lawrence Manor / Lawrence Heights 15 \n",
"Lawrence Park 3 \n",
"Leaside 34 \n",
"Little Portugal / Trinity 45 \n",
"Malvern / Rouge 1 \n",
"Milliken / Agincourt North / Steeles East / L'A... 3 \n",
"Mimico NW / The Queensway West / South of Bloor... 14 \n",
"Moore Park / Summerhill East 4 \n",
"New Toronto / Mimico South / Humber Bay Shores 13 \n",
"North Park / Maple Leaf Park / Upwood Park 4 \n",
"North Toronto West 21 \n",
"Northwest 3 \n",
"Northwood Park / York University 6 \n",
"Old Mill South / King's Mill Park / Sunnylea / ... 2 \n",
"Parkdale / Roncesvalles 14 \n",
"Parkview Hill / Woodbine Gardens 11 \n",
"Parkwoods 3 \n",
"Queen's Park / Ontario Provincial Government 31 \n",
"Regent Park / Harbourfront 46 \n",
"Richmond / Adelaide / King 95 \n",
"Rosedale 4 \n",
"Roselawn 1 \n",
"Rouge Hill / Port Union / Highland Creek 2 \n",
"Runnymede / Swansea 38 \n",
"Runnymede / The Junction North 4 \n",
"Scarborough Village 2 \n",
"South Steeles / Silverstone / Humbergate / Jame... 9 \n",
"St. James Town 79 \n",
"St. James Town / Cabbagetown 45 \n",
"Steeles West / L'Amoreaux West 12 \n",
"Stn A PO Boxes 94 \n",
"Studio District 40 \n",
"Summerhill West / Rathnelly / South Hill / Fore... 17 \n",
"The Annex / North Midtown / Yorkville 21 \n",
"The Beaches 4 \n",
"The Danforth West / Riverdale 43 \n",
"The Kingsway / Montgomery Road / Old Mill North 2 \n",
"Thorncliffe Park 20 \n",
"Toronto Dominion Centre / Design Exchange 100 \n",
"University of Toronto / Harbord 34 \n",
"Victoria Village 4 \n",
"West Deane Park / Princess Gardens / Martin Gro... 1 \n",
"Westmount 8 \n",
"Weston 1 \n",
"Wexford / Maryvale 4 \n",
"Willowdale 39 \n",
"Woburn 4 \n",
"Woodbine Heights 7 \n",
"York Mills West 4 \n",
"\n",
" Venue Category \n",
"Neighborhood \n",
"Agincourt 4 \n",
"Alderwood / Long Branch 8 \n",
"Bathurst Manor / Wilson Heights / Downsview North 22 \n",
"Bayview Village 4 \n",
"Bedford Park / Lawrence Manor East 22 \n",
"Berczy Park 56 \n",
"Birch Cliff / Cliffside West 4 \n",
"Broad Channel 5 \n",
"Brockton / Parkdale Village / Exhibition Place 24 \n",
"Business reply mail Processing CentrE 18 \n",
"CN Tower / King and Spadina / Railway Lands / H... 18 \n",
"Caledonia-Fairbanks 4 \n",
"Canada Post Gateway Processing Centre 13 \n",
"Cedarbrae 8 \n",
"Central Bay Street 64 \n",
"Christie 17 \n",
"Church and Wellesley 80 \n",
"Clarks Corners / Tam O'Shanter / Sullivan 14 \n",
"Cliffside / Cliffcrest / Scarborough Village West 3 \n",
"Commerce Court / Victoria Hotel 100 \n",
"Davisville 33 \n",
"Davisville North 8 \n",
"Del Ray / Mount Dennis / Keelsdale and Silverthorn 5 \n",
"Don Mills 28 \n",
"Dorset Park / Wexford Heights / Scarborough Tow... 7 \n",
"Downsview 15 \n",
"Dufferin / Dovercourt Village 15 \n",
"East Toronto 3 \n",
"Eringate / Bloordale Gardens / Old Burnhamthorp... 8 \n",
"Fairview / Henry Farm / Oriole 65 \n",
"First Canadian Place / Underground city 100 \n",
"Forest Hill North & West 5 \n",
"Garden District-Ryerson 100 \n",
"Glencairn 4 \n",
"Golden Mile / Clairlea / Oakridge 10 \n",
"Guildwood / Morningside / West Hill 7 \n",
"Harbourfront East / Union Station / Toronto Isl... 100 \n",
"High Park / The Junction South 23 \n",
"Hillcrest Village 5 \n",
"Humber Summit 1 \n",
"Humberlea / Emery 2 \n",
"Humewood-Cedarvale 3 \n",
"India Bazaar / The Beaches West 19 \n",
"Kennedy Park / Ionview / East Birchmount Park 4 \n",
"Kensington Market / Chinatown / Grange Park 61 \n",
"Kingsview Village / St. Phillips / Martin Grove... 4 \n",
"Lawrence Manor / Lawrence Heights 15 \n",
"Lawrence Park 3 \n",
"Leaside 34 \n",
"Little Portugal / Trinity 45 \n",
"Malvern / Rouge 1 \n",
"Milliken / Agincourt North / Steeles East / L'A... 3 \n",
"Mimico NW / The Queensway West / South of Bloor... 14 \n",
"Moore Park / Summerhill East 4 \n",
"New Toronto / Mimico South / Humber Bay Shores 13 \n",
"North Park / Maple Leaf Park / Upwood Park 4 \n",
"North Toronto West 21 \n",
"Northwest 3 \n",
"Northwood Park / York University 6 \n",
"Old Mill South / King's Mill Park / Sunnylea / ... 2 \n",
"Parkdale / Roncesvalles 14 \n",
"Parkview Hill / Woodbine Gardens 11 \n",
"Parkwoods 3 \n",
"Queen's Park / Ontario Provincial Government 31 \n",
"Regent Park / Harbourfront 46 \n",
"Richmond / Adelaide / King 95 \n",
"Rosedale 4 \n",
"Roselawn 1 \n",
"Rouge Hill / Port Union / Highland Creek 2 \n",
"Runnymede / Swansea 38 \n",
"Runnymede / The Junction North 4 \n",
"Scarborough Village 2 \n",
"South Steeles / Silverstone / Humbergate / Jame... 9 \n",
"St. James Town 79 \n",
"St. James Town / Cabbagetown 45 \n",
"Steeles West / L'Amoreaux West 12 \n",
"Stn A PO Boxes 94 \n",
"Studio District 40 \n",
"Summerhill West / Rathnelly / South Hill / Fore... 17 \n",
"The Annex / North Midtown / Yorkville 21 \n",
"The Beaches 4 \n",
"The Danforth West / Riverdale 43 \n",
"The Kingsway / Montgomery Road / Old Mill North 2 \n",
"Thorncliffe Park 20 \n",
"Toronto Dominion Centre / Design Exchange 100 \n",
"University of Toronto / Harbord 34 \n",
"Victoria Village 4 \n",
"West Deane Park / Princess Gardens / Martin Gro... 1 \n",
"Westmount 8 \n",
"Weston 1 \n",
"Wexford / Maryvale 4 \n",
"Willowdale 39 \n",
"Woburn 4 \n",
"Woodbine Heights 7 \n",
"York Mills West 4 "
]
},
"execution_count": 341,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Let's check how many venues were returned for each neighborhood\n",
"toronto_venues.groupby('Neighborhood').count()"
]
},
{
"cell_type": "code",
"execution_count": 342,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"There are 272 uniques categories.\n"
]
}
],
"source": [
"## Let's find out how many unique categories can be curated from all the returned venues\n",
"print('There are {} uniques categories.'.format(len(toronto_venues['Venue Category'].unique())))"
]
},
{
"cell_type": "code",
"execution_count": 343,
"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>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",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Broad Channel</td>\n",
" <td>40.603027</td>\n",
" <td>-73.820055</td>\n",
" <td>Buster's Marine Service</td>\n",
" <td>40.599103</td>\n",
" <td>-73.820974</td>\n",
" <td>Sporting Goods Shop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Broad Channel</td>\n",
" <td>40.603027</td>\n",
" <td>-73.820055</td>\n",
" <td>All American Deli</td>\n",
" <td>40.605988</td>\n",
" <td>-73.819876</td>\n",
" <td>Deli / Bodega</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Broad Channel</td>\n",
" <td>40.603027</td>\n",
" <td>-73.820055</td>\n",
" <td>Iroquois Yacht Club</td>\n",
" <td>40.604626</td>\n",
" <td>-73.817993</td>\n",
" <td>Other Nightlife</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Broad Channel</td>\n",
" <td>40.603027</td>\n",
" <td>-73.820055</td>\n",
" <td>Grassy Point Bar And Grill</td>\n",
" <td>40.600190</td>\n",
" <td>-73.820306</td>\n",
" <td>Dive Bar</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Broad Channel</td>\n",
" <td>40.603027</td>\n",
" <td>-73.820055</td>\n",
" <td>Tommy's Pizza</td>\n",
" <td>40.606454</td>\n",
" <td>-73.819819</td>\n",
" <td>Pizza Place</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Neighborhood Neighborhood Latitude Neighborhood Longitude \\\n",
"0 Broad Channel 40.603027 -73.820055 \n",
"1 Broad Channel 40.603027 -73.820055 \n",
"2 Broad Channel 40.603027 -73.820055 \n",
"3 Broad Channel 40.603027 -73.820055 \n",
"4 Broad Channel 40.603027 -73.820055 \n",
"\n",
" Venue Venue Latitude Venue Longitude \\\n",
"0 Buster's Marine Service 40.599103 -73.820974 \n",
"1 All American Deli 40.605988 -73.819876 \n",
"2 Iroquois Yacht Club 40.604626 -73.817993 \n",
"3 Grassy Point Bar And Grill 40.600190 -73.820306 \n",
"4 Tommy's Pizza 40.606454 -73.819819 \n",
"\n",
" Venue Category \n",
"0 Sporting Goods Shop \n",
"1 Deli / Bodega \n",
"2 Other Nightlife \n",
"3 Dive Bar \n",
"4 Pizza Place "
]
},
"execution_count": 343,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"toronto_venues.head()"
]
},
{
"cell_type": "code",
"execution_count": 344,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Venue Category\n",
"Coffee Shop 175\n",
"Café 103\n",
"Restaurant 69\n",
"Pizza Place 51\n",
"Park 50\n",
"Italian Restaurant 46\n",
"Bakery 41\n",
"Japanese Restaurant 39\n",
"Sandwich Place 39\n",
"Hotel 38\n",
"Clothing Store 33\n",
"Bar 32\n",
"Gym 32\n",
"Sushi Restaurant 32\n",
"Grocery Store 30\n",
"Pub 27\n",
"Bank 26\n",
"American Restaurant 26\n",
"Fast Food Restaurant 25\n",
"Breakfast Spot 24\n",
"Seafood Restaurant 22\n",
"Pharmacy 21\n",
"Thai Restaurant 20\n",
"Gastropub 18\n",
"Beer Bar 18\n",
"Name: Neighborhood, dtype: int64"
]
},
"execution_count": 344,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Let's get only the venues that appears more than 25 times, so our clustering gets easier\n",
"venues_count = toronto_venues.groupby(\"Venue Category\")[\"Neighborhood\"].count().sort_values(ascending=False)\n",
"venues_count = venues_count.head(25)\n",
"venues_count "
]
},
{
"cell_type": "code",
"execution_count": 345,
"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>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",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Broad Channel</td>\n",
" <td>40.603027</td>\n",
" <td>-73.820055</td>\n",
" <td>Tommy's Pizza</td>\n",
" <td>40.606454</td>\n",
" <td>-73.819819</td>\n",
" <td>Pizza Place</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>Parkwoods</td>\n",
" <td>43.753259</td>\n",
" <td>-79.329656</td>\n",
" <td>Brookbanks Park</td>\n",
" <td>43.751976</td>\n",
" <td>-79.332140</td>\n",
" <td>Park</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>Victoria Village</td>\n",
" <td>43.725882</td>\n",
" <td>-79.315572</td>\n",
" <td>Tim Hortons</td>\n",
" <td>43.725517</td>\n",
" <td>-79.313103</td>\n",
" <td>Coffee Shop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>12</th>\n",
" <td>Regent Park / Harbourfront</td>\n",
" <td>43.654260</td>\n",
" <td>-79.360636</td>\n",
" <td>Roselle Desserts</td>\n",
" <td>43.653447</td>\n",
" <td>-79.362017</td>\n",
" <td>Bakery</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13</th>\n",
" <td>Regent Park / Harbourfront</td>\n",
" <td>43.654260</td>\n",
" <td>-79.360636</td>\n",
" <td>Tandem Coffee</td>\n",
" <td>43.653559</td>\n",
" <td>-79.361809</td>\n",
" <td>Coffee Shop</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Neighborhood Neighborhood Latitude Neighborhood Longitude \\\n",
"4 Broad Channel 40.603027 -73.820055 \n",
"5 Parkwoods 43.753259 -79.329656 \n",
"9 Victoria Village 43.725882 -79.315572 \n",
"12 Regent Park / Harbourfront 43.654260 -79.360636 \n",
"13 Regent Park / Harbourfront 43.654260 -79.360636 \n",
"\n",
" Venue Venue Latitude Venue Longitude Venue Category \n",
"4 Tommy's Pizza 40.606454 -73.819819 Pizza Place \n",
"5 Brookbanks Park 43.751976 -79.332140 Park \n",
"9 Tim Hortons 43.725517 -79.313103 Coffee Shop \n",
"12 Roselle Desserts 43.653447 -79.362017 Bakery \n",
"13 Tandem Coffee 43.653559 -79.361809 Coffee Shop "
]
},
"execution_count": 345,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"toronto_venues = toronto_venues[toronto_venues[\"Venue Category\"].isin(venues_count.index)]\n",
"toronto_venues.head()"
]
},
{
"cell_type": "code",
"execution_count": 346,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>American Restaurant</th>\n",
" <th>Bakery</th>\n",
" <th>Bank</th>\n",
" <th>Bar</th>\n",
" <th>Beer Bar</th>\n",
" <th>Breakfast Spot</th>\n",
" <th>Café</th>\n",
" <th>Clothing Store</th>\n",
" <th>Coffee Shop</th>\n",
" <th>Fast Food Restaurant</th>\n",
" <th>Gastropub</th>\n",
" <th>Grocery Store</th>\n",
" <th>Gym</th>\n",
" <th>Hotel</th>\n",
" <th>Italian Restaurant</th>\n",
" <th>Japanese Restaurant</th>\n",
" <th>Park</th>\n",
" <th>Pharmacy</th>\n",
" <th>Pizza Place</th>\n",
" <th>Pub</th>\n",
" <th>Restaurant</th>\n",
" <th>Sandwich Place</th>\n",
" <th>Seafood Restaurant</th>\n",
" <th>Sushi Restaurant</th>\n",
" <th>Thai Restaurant</th>\n",
" <th>Neighborhood</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\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>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>1</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>Broad Channel</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</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>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</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>Parkwoods</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</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>1</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",
" <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>Victoria Village</td>\n",
" </tr>\n",
" <tr>\n",
" <th>12</th>\n",
" <td>0</td>\n",
" <td>1</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",
" <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>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>Regent Park / Harbourfront</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13</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>1</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",
" <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>Regent Park / Harbourfront</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" American Restaurant Bakery Bank Bar Beer Bar Breakfast Spot Café \\\n",
"4 0 0 0 0 0 0 0 \n",
"5 0 0 0 0 0 0 0 \n",
"9 0 0 0 0 0 0 0 \n",
"12 0 1 0 0 0 0 0 \n",
"13 0 0 0 0 0 0 0 \n",
"\n",
" Clothing Store Coffee Shop Fast Food Restaurant Gastropub \\\n",
"4 0 0 0 0 \n",
"5 0 0 0 0 \n",
"9 0 1 0 0 \n",
"12 0 0 0 0 \n",
"13 0 1 0 0 \n",
"\n",
" Grocery Store Gym Hotel Italian Restaurant Japanese Restaurant Park \\\n",
"4 0 0 0 0 0 0 \n",
"5 0 0 0 0 0 1 \n",
"9 0 0 0 0 0 0 \n",
"12 0 0 0 0 0 0 \n",
"13 0 0 0 0 0 0 \n",
"\n",
" Pharmacy Pizza Place Pub Restaurant Sandwich Place \\\n",
"4 0 1 0 0 0 \n",
"5 0 0 0 0 0 \n",
"9 0 0 0 0 0 \n",
"12 0 0 0 0 0 \n",
"13 0 0 0 0 0 \n",
"\n",
" Seafood Restaurant Sushi Restaurant Thai Restaurant \\\n",
"4 0 0 0 \n",
"5 0 0 0 \n",
"9 0 0 0 \n",
"12 0 0 0 \n",
"13 0 0 0 \n",
"\n",
" Neighborhood \n",
"4 Broad Channel \n",
"5 Parkwoods \n",
"9 Victoria Village \n",
"12 Regent Park / Harbourfront \n",
"13 Regent Park / Harbourfront "
]
},
"execution_count": 346,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"## Analyze Each Neighborhood\n",
"\n",
"# one hot encoding\n",
"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": "code",
"execution_count": 347,
"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>American Restaurant</th>\n",
" <th>Bakery</th>\n",
" <th>Bank</th>\n",
" <th>Bar</th>\n",
" <th>Beer Bar</th>\n",
" <th>Breakfast Spot</th>\n",
" <th>Café</th>\n",
" <th>Clothing Store</th>\n",
" <th>Coffee Shop</th>\n",
" <th>Fast Food Restaurant</th>\n",
" <th>Gastropub</th>\n",
" <th>Grocery Store</th>\n",
" <th>Gym</th>\n",
" <th>Hotel</th>\n",
" <th>Italian Restaurant</th>\n",
" <th>Japanese Restaurant</th>\n",
" <th>Park</th>\n",
" <th>Pharmacy</th>\n",
" <th>Pizza Place</th>\n",
" <th>Pub</th>\n",
" <th>Restaurant</th>\n",
" <th>Sandwich Place</th>\n",
" <th>Seafood Restaurant</th>\n",
" <th>Sushi Restaurant</th>\n",
" <th>Thai Restaurant</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Broad Channel</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",
" <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>1</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>5</th>\n",
" <td>Parkwoods</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",
" <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>1</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>9</th>\n",
" <td>Victoria Village</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>1</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",
" <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>12</th>\n",
" <td>Regent Park / Harbourfront</td>\n",
" <td>0</td>\n",
" <td>1</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",
" <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>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13</th>\n",
" <td>Regent Park / Harbourfront</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>1</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",
" <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",
"</div>"
],
"text/plain": [
" Neighborhood American Restaurant Bakery Bank Bar \\\n",
"4 Broad Channel 0 0 0 0 \n",
"5 Parkwoods 0 0 0 0 \n",
"9 Victoria Village 0 0 0 0 \n",
"12 Regent Park / Harbourfront 0 1 0 0 \n",
"13 Regent Park / Harbourfront 0 0 0 0 \n",
"\n",
" Beer Bar Breakfast Spot Café Clothing Store Coffee Shop \\\n",
"4 0 0 0 0 0 \n",
"5 0 0 0 0 0 \n",
"9 0 0 0 0 1 \n",
"12 0 0 0 0 0 \n",
"13 0 0 0 0 1 \n",
"\n",
" Fast Food Restaurant Gastropub Grocery Store Gym Hotel \\\n",
"4 0 0 0 0 0 \n",
"5 0 0 0 0 0 \n",
"9 0 0 0 0 0 \n",
"12 0 0 0 0 0 \n",
"13 0 0 0 0 0 \n",
"\n",
" Italian Restaurant Japanese Restaurant Park Pharmacy Pizza Place Pub \\\n",
"4 0 0 0 0 1 0 \n",
"5 0 0 1 0 0 0 \n",
"9 0 0 0 0 0 0 \n",
"12 0 0 0 0 0 0 \n",
"13 0 0 0 0 0 0 \n",
"\n",
" Restaurant Sandwich Place Seafood Restaurant Sushi Restaurant \\\n",
"4 0 0 0 0 \n",
"5 0 0 0 0 \n",
"9 0 0 0 0 \n",
"12 0 0 0 0 \n",
"13 0 0 0 0 \n",
"\n",
" Thai Restaurant \n",
"4 0 \n",
"5 0 \n",
"9 0 \n",
"12 0 \n",
"13 0 "
]
},
"execution_count": 347,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"## Moving the Neighborhood column to front:\n",
"\n",
"cols = toronto_onehot.columns.tolist()\n",
"cols.remove('Neighborhood') ## removing the column from the middle... \n",
"cols.insert(0,'Neighborhood') ## ...and reinserting it on the first position\n",
"toronto_onehot = toronto_onehot[cols]\n",
"toronto_onehot.head()"
]
},
{
"cell_type": "code",
"execution_count": 348,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"data": {
"text/plain": [
"(1037, 26)"
]
},
"execution_count": 348,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# And let's examine the new dataframe size.\n",
"toronto_onehot.shape"
]
},
{
"cell_type": "code",
"execution_count": 349,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Neighborhood</th>\n",
" <th>American Restaurant</th>\n",
" <th>Bakery</th>\n",
" <th>Bank</th>\n",
" <th>Bar</th>\n",
" <th>Beer Bar</th>\n",
" <th>Breakfast Spot</th>\n",
" <th>Café</th>\n",
" <th>Clothing Store</th>\n",
" <th>Coffee Shop</th>\n",
" <th>Fast Food Restaurant</th>\n",
" <th>Gastropub</th>\n",
" <th>Grocery Store</th>\n",
" <th>Gym</th>\n",
" <th>Hotel</th>\n",
" <th>Italian Restaurant</th>\n",
" <th>Japanese Restaurant</th>\n",
" <th>Park</th>\n",
" <th>Pharmacy</th>\n",
" <th>Pizza Place</th>\n",
" <th>Pub</th>\n",
" <th>Restaurant</th>\n",
" <th>Sandwich Place</th>\n",
" <th>Seafood Restaurant</th>\n",
" <th>Sushi Restaurant</th>\n",
" <th>Thai Restaurant</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Agincourt</td>\n",
" <td>0.0000</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Alderwood / Long Branch</td>\n",
" <td>0.0000</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.142857</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.142857</td>\n",
" <td>0.0</td>\n",
" <td>0.000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.142857</td>\n",
" <td>0.285714</td>\n",
" <td>0.142857</td>\n",
" <td>0.000000</td>\n",
" <td>0.142857</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Bathurst Manor / Wilson Heights / Downsview North</td>\n",
" <td>0.0000</td>\n",
" <td>0.0</td>\n",
" <td>0.181818</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.181818</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.090909</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.000</td>\n",
" <td>0.000000</td>\n",
" <td>0.090909</td>\n",
" <td>0.090909</td>\n",
" <td>0.090909</td>\n",
" <td>0.000000</td>\n",
" <td>0.090909</td>\n",
" <td>0.090909</td>\n",
" <td>0.0</td>\n",
" <td>0.090909</td>\n",
" <td>0.0000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Bayview Village</td>\n",
" <td>0.0000</td>\n",
" <td>0.0</td>\n",
" <td>0.333333</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.333333</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.000</td>\n",
" <td>0.333333</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Bedford Park / Lawrence Manor East</td>\n",
" <td>0.0625</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.062500</td>\n",
" <td>0.0</td>\n",
" <td>0.125000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.062500</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.125</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.062500</td>\n",
" <td>0.062500</td>\n",
" <td>0.062500</td>\n",
" <td>0.125000</td>\n",
" <td>0.125000</td>\n",
" <td>0.0</td>\n",
" <td>0.062500</td>\n",
" <td>0.0625</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Neighborhood American Restaurant \\\n",
"0 Agincourt 0.0000 \n",
"1 Alderwood / Long Branch 0.0000 \n",
"2 Bathurst Manor / Wilson Heights / Downsview North 0.0000 \n",
"3 Bayview Village 0.0000 \n",
"4 Bedford Park / Lawrence Manor East 0.0625 \n",
"\n",
" Bakery Bank Bar Beer Bar Breakfast Spot Café Clothing Store \\\n",
"0 0.0 0.000000 0.0 0.0 1.0 0.000000 0.0 \n",
"1 0.0 0.000000 0.0 0.0 0.0 0.000000 0.0 \n",
"2 0.0 0.181818 0.0 0.0 0.0 0.000000 0.0 \n",
"3 0.0 0.333333 0.0 0.0 0.0 0.333333 0.0 \n",
"4 0.0 0.000000 0.0 0.0 0.0 0.062500 0.0 \n",
"\n",
" Coffee Shop Fast Food Restaurant Gastropub Grocery Store Gym \\\n",
"0 0.000000 0.0 0.0 0.000000 0.000000 \n",
"1 0.142857 0.0 0.0 0.000000 0.142857 \n",
"2 0.181818 0.0 0.0 0.090909 0.000000 \n",
"3 0.000000 0.0 0.0 0.000000 0.000000 \n",
"4 0.125000 0.0 0.0 0.062500 0.000000 \n",
"\n",
" Hotel Italian Restaurant Japanese Restaurant Park Pharmacy \\\n",
"0 0.0 0.000 0.000000 0.000000 0.000000 \n",
"1 0.0 0.000 0.000000 0.000000 0.142857 \n",
"2 0.0 0.000 0.000000 0.090909 0.090909 \n",
"3 0.0 0.000 0.333333 0.000000 0.000000 \n",
"4 0.0 0.125 0.000000 0.000000 0.062500 \n",
"\n",
" Pizza Place Pub Restaurant Sandwich Place Seafood Restaurant \\\n",
"0 0.000000 0.000000 0.000000 0.000000 0.0 \n",
"1 0.285714 0.142857 0.000000 0.142857 0.0 \n",
"2 0.090909 0.000000 0.090909 0.090909 0.0 \n",
"3 0.000000 0.000000 0.000000 0.000000 0.0 \n",
"4 0.062500 0.062500 0.125000 0.125000 0.0 \n",
"\n",
" Sushi Restaurant Thai Restaurant \n",
"0 0.000000 0.0000 \n",
"1 0.000000 0.0000 \n",
"2 0.090909 0.0000 \n",
"3 0.000000 0.0000 \n",
"4 0.062500 0.0625 "
]
},
"execution_count": 349,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Next, let's group rows by neighborhood and by taking the mean of the frequency\n",
"# of occurrence of each category\n",
"\n",
"toronto_grouped = toronto_onehot.groupby('Neighborhood').mean().reset_index()\n",
"toronto_grouped.head()"
]
},
{
"cell_type": "code",
"execution_count": 350,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"data": {
"text/plain": [
"(86, 26)"
]
},
"execution_count": 350,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#### Let's confirm the new size\n",
"toronto_grouped.shape"
]
},
{
"cell_type": "code",
"execution_count": 351,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"----Agincourt----\n",
" venue freq\n",
"0 Breakfast Spot 1.0\n",
"1 American Restaurant 0.0\n",
"2 Hotel 0.0\n",
"3 Sushi Restaurant 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----Alderwood / Long Branch----\n",
" venue freq\n",
"0 Pizza Place 0.29\n",
"1 Gym 0.14\n",
"2 Sandwich Place 0.14\n",
"3 Pub 0.14\n",
"4 Coffee Shop 0.14\n",
"\n",
"\n",
"----Bathurst Manor / Wilson Heights / Downsview North----\n",
" venue freq\n",
"0 Bank 0.18\n",
"1 Coffee Shop 0.18\n",
"2 Sushi Restaurant 0.09\n",
"3 Sandwich Place 0.09\n",
"4 Restaurant 0.09\n",
"\n",
"\n",
"----Bayview Village----\n",
" venue freq\n",
"0 Bank 0.33\n",
"1 Café 0.33\n",
"2 Japanese Restaurant 0.33\n",
"3 American Restaurant 0.00\n",
"4 Italian Restaurant 0.00\n",
"\n",
"\n",
"----Bedford Park / Lawrence Manor East----\n",
" venue freq\n",
"0 Sandwich Place 0.12\n",
"1 Restaurant 0.12\n",
"2 Coffee Shop 0.12\n",
"3 Italian Restaurant 0.12\n",
"4 American Restaurant 0.06\n",
"\n",
"\n",
"----Berczy Park----\n",
" venue freq\n",
"0 Coffee Shop 0.17\n",
"1 Restaurant 0.09\n",
"2 Seafood Restaurant 0.09\n",
"3 Beer Bar 0.09\n",
"4 Café 0.09\n",
"\n",
"\n",
"----Birch Cliff / Cliffside West----\n",
" venue freq\n",
"0 Café 1.0\n",
"1 American Restaurant 0.0\n",
"2 Hotel 0.0\n",
"3 Sushi Restaurant 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----Broad Channel----\n",
" venue freq\n",
"0 Pizza Place 1.0\n",
"1 American Restaurant 0.0\n",
"2 Hotel 0.0\n",
"3 Sushi Restaurant 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----Brockton / Parkdale Village / Exhibition Place----\n",
" venue freq\n",
"0 Café 0.21\n",
"1 Breakfast Spot 0.14\n",
"2 Coffee Shop 0.14\n",
"3 Bakery 0.14\n",
"4 Gym 0.07\n",
"\n",
"\n",
"----Business reply mail Processing CentrE----\n",
" venue freq\n",
"0 Restaurant 0.25\n",
"1 Pizza Place 0.25\n",
"2 Fast Food Restaurant 0.25\n",
"3 Park 0.25\n",
"4 American Restaurant 0.00\n",
"\n",
"\n",
"----CN Tower / King and Spadina / Railway Lands / Harbourfront West / Bathurst----\n",
" venue freq\n",
"0 Bar 0.5\n",
"1 Coffee Shop 0.5\n",
"2 American Restaurant 0.0\n",
"3 Italian Restaurant 0.0\n",
"4 Sushi Restaurant 0.0\n",
"\n",
"\n",
"----Caledonia-Fairbanks----\n",
" venue freq\n",
"0 Park 1.0\n",
"1 American Restaurant 0.0\n",
"2 Hotel 0.0\n",
"3 Sushi Restaurant 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----Canada Post Gateway Processing Centre----\n",
" venue freq\n",
"0 Coffee Shop 0.29\n",
"1 Hotel 0.29\n",
"2 American Restaurant 0.14\n",
"3 Sandwich Place 0.14\n",
"4 Gym 0.14\n",
"\n",
"\n",
"----Cedarbrae----\n",
" venue freq\n",
"0 Thai Restaurant 0.33\n",
"1 Bank 0.33\n",
"2 Bakery 0.33\n",
"3 Italian Restaurant 0.00\n",
"4 Sushi Restaurant 0.00\n",
"\n",
"\n",
"----Central Bay Street----\n",
" venue freq\n",
"0 Coffee Shop 0.33\n",
"1 Café 0.15\n",
"2 Italian Restaurant 0.12\n",
"3 Sandwich Place 0.09\n",
"4 Japanese Restaurant 0.06\n",
"\n",
"\n",
"----Christie----\n",
" venue freq\n",
"0 Grocery Store 0.33\n",
"1 Café 0.25\n",
"2 Park 0.17\n",
"3 Italian Restaurant 0.08\n",
"4 Restaurant 0.08\n",
"\n",
"\n",
"----Church and Wellesley----\n",
" venue freq\n",
"0 Coffee Shop 0.18\n",
"1 Sushi Restaurant 0.15\n",
"2 Japanese Restaurant 0.12\n",
"3 Restaurant 0.09\n",
"4 Pub 0.06\n",
"\n",
"\n",
"----Clarks Corners / Tam O'Shanter / Sullivan----\n",
" venue freq\n",
"0 Pizza Place 0.25\n",
"1 Pharmacy 0.25\n",
"2 Thai Restaurant 0.12\n",
"3 Italian Restaurant 0.12\n",
"4 Bank 0.12\n",
"\n",
"\n",
"----Cliffside / Cliffcrest / Scarborough Village West----\n",
" venue freq\n",
"0 American Restaurant 1.0\n",
"1 Hotel 0.0\n",
"2 Sushi Restaurant 0.0\n",
"3 Seafood Restaurant 0.0\n",
"4 Sandwich Place 0.0\n",
"\n",
"\n",
"----Commerce Court / Victoria Hotel----\n",
" venue freq\n",
"0 Coffee Shop 0.17\n",
"1 Café 0.11\n",
"2 Restaurant 0.11\n",
"3 Hotel 0.08\n",
"4 American Restaurant 0.06\n",
"\n",
"\n",
"----Davisville----\n",
" venue freq\n",
"0 Sandwich Place 0.15\n",
"1 Gym 0.10\n",
"2 Italian Restaurant 0.10\n",
"3 Sushi Restaurant 0.10\n",
"4 Café 0.10\n",
"\n",
"\n",
"----Davisville North----\n",
" venue freq\n",
"0 Hotel 0.2\n",
"1 Sandwich Place 0.2\n",
"2 Breakfast Spot 0.2\n",
"3 Pizza Place 0.2\n",
"4 Park 0.2\n",
"\n",
"\n",
"----Del Ray / Mount Dennis / Keelsdale and Silverthorn----\n",
" venue freq\n",
"0 Bar 0.33\n",
"1 Sandwich Place 0.33\n",
"2 Restaurant 0.33\n",
"3 American Restaurant 0.00\n",
"4 Hotel 0.00\n",
"\n",
"\n",
"----Don Mills----\n",
" venue freq\n",
"0 Gym 0.15\n",
"1 Restaurant 0.15\n",
"2 Café 0.15\n",
"3 Coffee Shop 0.15\n",
"4 Japanese Restaurant 0.15\n",
"\n",
"\n",
"----Downsview----\n",
" venue freq\n",
"0 Grocery Store 0.50\n",
"1 Park 0.33\n",
"2 Bank 0.17\n",
"3 American Restaurant 0.00\n",
"4 Italian Restaurant 0.00\n",
"\n",
"\n",
"----Dufferin / Dovercourt Village----\n",
" venue freq\n",
"0 Bakery 0.2\n",
"1 Pharmacy 0.2\n",
"2 Bank 0.1\n",
"3 Bar 0.1\n",
"4 Café 0.1\n",
"\n",
"\n",
"----East Toronto----\n",
" venue freq\n",
"0 Pizza Place 0.5\n",
"1 Park 0.5\n",
"2 American Restaurant 0.0\n",
"3 Hotel 0.0\n",
"4 Sushi Restaurant 0.0\n",
"\n",
"\n",
"----Eringate / Bloordale Gardens / Old Burnhamthorpe / Markland Wood----\n",
" venue freq\n",
"0 Café 0.25\n",
"1 Coffee Shop 0.25\n",
"2 Pizza Place 0.25\n",
"3 Pharmacy 0.25\n",
"4 American Restaurant 0.00\n",
"\n",
"\n",
"----Fairview / Henry Farm / Oriole----\n",
" venue freq\n",
"0 Clothing Store 0.24\n",
"1 Coffee Shop 0.17\n",
"2 Fast Food Restaurant 0.14\n",
"3 Restaurant 0.10\n",
"4 Bank 0.07\n",
"\n",
"\n",
"----First Canadian Place / Underground city----\n",
" venue freq\n",
"0 Coffee Shop 0.17\n",
"1 Café 0.14\n",
"2 Gym 0.07\n",
"3 Restaurant 0.07\n",
"4 Japanese Restaurant 0.07\n",
"\n",
"\n",
"----Forest Hill North & West----\n",
" venue freq\n",
"0 Sushi Restaurant 0.5\n",
"1 Park 0.5\n",
"2 American Restaurant 0.0\n",
"3 Hotel 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----Garden District-Ryerson----\n",
" venue freq\n",
"0 Clothing Store 0.20\n",
"1 Coffee Shop 0.18\n",
"2 Japanese Restaurant 0.07\n",
"3 Café 0.07\n",
"4 Italian Restaurant 0.07\n",
"\n",
"\n",
"----Glencairn----\n",
" venue freq\n",
"0 Pub 0.25\n",
"1 Pizza Place 0.25\n",
"2 Park 0.25\n",
"3 Japanese Restaurant 0.25\n",
"4 American Restaurant 0.00\n",
"\n",
"\n",
"----Golden Mile / Clairlea / Oakridge----\n",
" venue freq\n",
"0 Bakery 0.67\n",
"1 Park 0.33\n",
"2 American Restaurant 0.00\n",
"3 Hotel 0.00\n",
"4 Sushi Restaurant 0.00\n",
"\n",
"\n",
"----Guildwood / Morningside / West Hill----\n",
" venue freq\n",
"0 Bank 0.5\n",
"1 Breakfast Spot 0.5\n",
"2 American Restaurant 0.0\n",
"3 Italian Restaurant 0.0\n",
"4 Sushi Restaurant 0.0\n",
"\n",
"\n",
"----Harbourfront East / Union Station / Toronto Islands----\n",
" venue freq\n",
"0 Coffee Shop 0.32\n",
"1 Café 0.10\n",
"2 Hotel 0.10\n",
"3 Italian Restaurant 0.07\n",
"4 Restaurant 0.07\n",
"\n",
"\n",
"----High Park / The Junction South----\n",
" venue freq\n",
"0 Thai Restaurant 0.18\n",
"1 Café 0.18\n",
"2 Park 0.09\n",
"3 Bar 0.09\n",
"4 Fast Food Restaurant 0.09\n",
"\n",
"\n",
"----Humber Summit----\n",
" venue freq\n",
"0 Pizza Place 1.0\n",
"1 American Restaurant 0.0\n",
"2 Hotel 0.0\n",
"3 Sushi Restaurant 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----India Bazaar / The Beaches West----\n",
" venue freq\n",
"0 Fast Food Restaurant 0.18\n",
"1 Park 0.18\n",
"2 Gym 0.09\n",
"3 Sushi Restaurant 0.09\n",
"4 Sandwich Place 0.09\n",
"\n",
"\n",
"----Kennedy Park / Ionview / East Birchmount Park----\n",
" venue freq\n",
"0 Coffee Shop 1.0\n",
"1 American Restaurant 0.0\n",
"2 Hotel 0.0\n",
"3 Sushi Restaurant 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----Kensington Market / Chinatown / Grange Park----\n",
" venue freq\n",
"0 Café 0.22\n",
"1 Coffee Shop 0.17\n",
"2 Pizza Place 0.09\n",
"3 Bakery 0.09\n",
"4 Grocery Store 0.09\n",
"\n",
"\n",
"----Kingsview Village / St. Phillips / Martin Grove Gardens / Richview Gardens----\n",
" venue freq\n",
"0 Sandwich Place 0.5\n",
"1 Pizza Place 0.5\n",
"2 American Restaurant 0.0\n",
"3 Hotel 0.0\n",
"4 Sushi Restaurant 0.0\n",
"\n",
"\n",
"----Lawrence Manor / Lawrence Heights----\n",
" venue freq\n",
"0 Clothing Store 0.8\n",
"1 Coffee Shop 0.2\n",
"2 American Restaurant 0.0\n",
"3 Italian Restaurant 0.0\n",
"4 Sushi Restaurant 0.0\n",
"\n",
"\n",
"----Lawrence Park----\n",
" venue freq\n",
"0 Park 1.0\n",
"1 American Restaurant 0.0\n",
"2 Hotel 0.0\n",
"3 Sushi Restaurant 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----Leaside----\n",
" venue freq\n",
"0 Coffee Shop 0.33\n",
"1 Bank 0.17\n",
"2 Gym 0.08\n",
"3 Sushi Restaurant 0.08\n",
"4 Breakfast Spot 0.08\n",
"\n",
"\n",
"----Little Portugal / Trinity----\n",
" venue freq\n",
"0 Bar 0.33\n",
"1 Café 0.13\n",
"2 Restaurant 0.13\n",
"3 Coffee Shop 0.13\n",
"4 Italian Restaurant 0.07\n",
"\n",
"\n",
"----Malvern / Rouge----\n",
" venue freq\n",
"0 Fast Food Restaurant 1.0\n",
"1 American Restaurant 0.0\n",
"2 Hotel 0.0\n",
"3 Sushi Restaurant 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----Milliken / Agincourt North / Steeles East / L'Amoreaux East----\n",
" venue freq\n",
"0 Park 1.0\n",
"1 American Restaurant 0.0\n",
"2 Hotel 0.0\n",
"3 Sushi Restaurant 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----Mimico NW / The Queensway West / South of Bloor / Kingsway Park South West / Royal York South West----\n",
" venue freq\n",
"0 Gym 0.2\n",
"1 Sandwich Place 0.2\n",
"2 Fast Food Restaurant 0.2\n",
"3 Grocery Store 0.2\n",
"4 Bakery 0.2\n",
"\n",
"\n",
"----Moore Park / Summerhill East----\n",
" venue freq\n",
"0 Restaurant 0.5\n",
"1 Park 0.5\n",
"2 American Restaurant 0.0\n",
"3 Hotel 0.0\n",
"4 Sushi Restaurant 0.0\n",
"\n",
"\n",
"----New Toronto / Mimico South / Humber Bay Shores----\n",
" venue freq\n",
"0 American Restaurant 0.1\n",
"1 Coffee Shop 0.1\n",
"2 Seafood Restaurant 0.1\n",
"3 Restaurant 0.1\n",
"4 Pizza Place 0.1\n",
"\n",
"\n",
"----North Park / Maple Leaf Park / Upwood Park----\n",
" venue freq\n",
"0 Park 0.5\n",
"1 Bakery 0.5\n",
"2 American Restaurant 0.0\n",
"3 Hotel 0.0\n",
"4 Sushi Restaurant 0.0\n",
"\n",
"\n",
"----North Toronto West----\n",
" venue freq\n",
"0 Clothing Store 0.22\n",
"1 Coffee Shop 0.22\n",
"2 Restaurant 0.11\n",
"3 Café 0.11\n",
"4 Fast Food Restaurant 0.11\n",
"\n",
"\n",
"----Northwest----\n",
" venue freq\n",
"0 Bar 1.0\n",
"1 American Restaurant 0.0\n",
"2 Hotel 0.0\n",
"3 Sushi Restaurant 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----Northwood Park / York University----\n",
" venue freq\n",
"0 Bar 0.5\n",
"1 Coffee Shop 0.5\n",
"2 American Restaurant 0.0\n",
"3 Italian Restaurant 0.0\n",
"4 Sushi Restaurant 0.0\n",
"\n",
"\n",
"----Old Mill South / King's Mill Park / Sunnylea / Humber Bay / Mimico NE / The Queensway East / Royal York South East / Kingsway Park South East----\n",
" venue freq\n",
"0 Park 1.0\n",
"1 American Restaurant 0.0\n",
"2 Hotel 0.0\n",
"3 Sushi Restaurant 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----Parkdale / Roncesvalles----\n",
" venue freq\n",
"0 Breakfast Spot 0.33\n",
"1 Italian Restaurant 0.17\n",
"2 Bar 0.17\n",
"3 Restaurant 0.17\n",
"4 Coffee Shop 0.17\n",
"\n",
"\n",
"----Parkview Hill / Woodbine Gardens----\n",
" venue freq\n",
"0 Pizza Place 0.25\n",
"1 Bank 0.12\n",
"2 Breakfast Spot 0.12\n",
"3 Café 0.12\n",
"4 Fast Food Restaurant 0.12\n",
"\n",
"\n",
"----Parkwoods----\n",
" venue freq\n",
"0 Park 1.0\n",
"1 American Restaurant 0.0\n",
"2 Hotel 0.0\n",
"3 Sushi Restaurant 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----Queen's Park / Ontario Provincial Government----\n",
" venue freq\n",
"0 Coffee Shop 0.41\n",
"1 Sushi Restaurant 0.12\n",
"2 Gym 0.06\n",
"3 Park 0.06\n",
"4 Bank 0.06\n",
"\n",
"\n",
"----Regent Park / Harbourfront----\n",
" venue freq\n",
"0 Coffee Shop 0.32\n",
"1 Park 0.12\n",
"2 Pub 0.12\n",
"3 Bakery 0.12\n",
"4 Breakfast Spot 0.08\n",
"\n",
"\n",
"----Richmond / Adelaide / King----\n",
" venue freq\n",
"0 Coffee Shop 0.20\n",
"1 Café 0.11\n",
"2 Restaurant 0.11\n",
"3 Gym 0.07\n",
"4 Hotel 0.07\n",
"\n",
"\n",
"----Rosedale----\n",
" venue freq\n",
"0 Park 1.0\n",
"1 American Restaurant 0.0\n",
"2 Hotel 0.0\n",
"3 Sushi Restaurant 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----Rouge Hill / Port Union / Highland Creek----\n",
" venue freq\n",
"0 Bar 1.0\n",
"1 American Restaurant 0.0\n",
"2 Hotel 0.0\n",
"3 Sushi Restaurant 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----Runnymede / Swansea----\n",
" venue freq\n",
"0 Sushi Restaurant 0.14\n",
"1 Café 0.14\n",
"2 Coffee Shop 0.14\n",
"3 Pizza Place 0.14\n",
"4 Restaurant 0.09\n",
"\n",
"\n",
"----Runnymede / The Junction North----\n",
" venue freq\n",
"0 Pizza Place 0.5\n",
"1 Grocery Store 0.5\n",
"2 American Restaurant 0.0\n",
"3 Hotel 0.0\n",
"4 Sushi Restaurant 0.0\n",
"\n",
"\n",
"----South Steeles / Silverstone / Humbergate / Jamestown / Mount Olive / Beaumond Heights / Thistletown / Albion Gardens----\n",
" venue freq\n",
"0 Grocery Store 0.33\n",
"1 Sandwich Place 0.17\n",
"2 Pizza Place 0.17\n",
"3 Pharmacy 0.17\n",
"4 Fast Food Restaurant 0.17\n",
"\n",
"\n",
"----St. James Town----\n",
" venue freq\n",
"0 Coffee Shop 0.14\n",
"1 Café 0.14\n",
"2 American Restaurant 0.09\n",
"3 Gastropub 0.09\n",
"4 Restaurant 0.06\n",
"\n",
"\n",
"----St. James Town / Cabbagetown----\n",
" venue freq\n",
"0 Coffee Shop 0.15\n",
"1 Café 0.12\n",
"2 Italian Restaurant 0.08\n",
"3 Pizza Place 0.08\n",
"4 Bakery 0.08\n",
"\n",
"\n",
"----Steeles West / L'Amoreaux West----\n",
" venue freq\n",
"0 Grocery Store 0.22\n",
"1 Bank 0.11\n",
"2 Breakfast Spot 0.11\n",
"3 Sandwich Place 0.11\n",
"4 Coffee Shop 0.11\n",
"\n",
"\n",
"----Stn A PO Boxes----\n",
" venue freq\n",
"0 Coffee Shop 0.19\n",
"1 Café 0.09\n",
"2 Japanese Restaurant 0.06\n",
"3 Seafood Restaurant 0.06\n",
"4 Beer Bar 0.06\n",
"\n",
"\n",
"----Studio District----\n",
" venue freq\n",
"0 Café 0.19\n",
"1 Coffee Shop 0.14\n",
"2 American Restaurant 0.10\n",
"3 Gastropub 0.10\n",
"4 Bakery 0.10\n",
"\n",
"\n",
"----Summerhill West / Rathnelly / South Hill / Forest Hill SE / Deer Park----\n",
" venue freq\n",
"0 Coffee Shop 0.2\n",
"1 Pub 0.2\n",
"2 American Restaurant 0.1\n",
"3 Bank 0.1\n",
"4 Sushi Restaurant 0.1\n",
"\n",
"\n",
"----The Annex / North Midtown / Yorkville----\n",
" venue freq\n",
"0 Sandwich Place 0.25\n",
"1 Café 0.25\n",
"2 Coffee Shop 0.17\n",
"3 Pub 0.08\n",
"4 Pizza Place 0.08\n",
"\n",
"\n",
"----The Beaches----\n",
" venue freq\n",
"0 Pub 1.0\n",
"1 American Restaurant 0.0\n",
"2 Hotel 0.0\n",
"3 Sushi Restaurant 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----The Danforth West / Riverdale----\n",
" venue freq\n",
"0 Coffee Shop 0.20\n",
"1 Italian Restaurant 0.20\n",
"2 Restaurant 0.13\n",
"3 American Restaurant 0.07\n",
"4 Japanese Restaurant 0.07\n",
"\n",
"\n",
"----Thorncliffe Park----\n",
" venue freq\n",
"0 Gym 0.1\n",
"1 Bank 0.1\n",
"2 Sandwich Place 0.1\n",
"3 Restaurant 0.1\n",
"4 Coffee Shop 0.1\n",
"\n",
"\n",
"----Toronto Dominion Centre / Design Exchange----\n",
" venue freq\n",
"0 Coffee Shop 0.18\n",
"1 Hotel 0.13\n",
"2 Café 0.11\n",
"3 Restaurant 0.07\n",
"4 American Restaurant 0.05\n",
"\n",
"\n",
"----University of Toronto / Harbord----\n",
" venue freq\n",
"0 Café 0.25\n",
"1 Bar 0.10\n",
"2 Restaurant 0.10\n",
"3 Bakery 0.10\n",
"4 Italian Restaurant 0.10\n",
"\n",
"\n",
"----Victoria Village----\n",
" venue freq\n",
"0 Coffee Shop 1.0\n",
"1 American Restaurant 0.0\n",
"2 Hotel 0.0\n",
"3 Sushi Restaurant 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----Westmount----\n",
" venue freq\n",
"0 Pizza Place 0.50\n",
"1 Sandwich Place 0.25\n",
"2 Coffee Shop 0.25\n",
"3 American Restaurant 0.00\n",
"4 Hotel 0.00\n",
"\n",
"\n",
"----Wexford / Maryvale----\n",
" venue freq\n",
"0 Breakfast Spot 0.5\n",
"1 Bakery 0.5\n",
"2 American Restaurant 0.0\n",
"3 Italian Restaurant 0.0\n",
"4 Sushi Restaurant 0.0\n",
"\n",
"\n",
"----Willowdale----\n",
" venue freq\n",
"0 Coffee Shop 0.15\n",
"1 Pizza Place 0.15\n",
"2 Sushi Restaurant 0.10\n",
"3 Sandwich Place 0.10\n",
"4 Café 0.10\n",
"\n",
"\n",
"----Woburn----\n",
" venue freq\n",
"0 Coffee Shop 1.0\n",
"1 American Restaurant 0.0\n",
"2 Hotel 0.0\n",
"3 Sushi Restaurant 0.0\n",
"4 Seafood Restaurant 0.0\n",
"\n",
"\n",
"----Woodbine Heights----\n",
" venue freq\n",
"0 Pharmacy 0.5\n",
"1 Park 0.5\n",
"2 American Restaurant 0.0\n",
"3 Hotel 0.0\n",
"4 Sushi Restaurant 0.0\n",
"\n",
"\n",
"----York Mills West----\n",
" venue freq\n",
"0 Bar 0.5\n",
"1 Park 0.5\n",
"2 American Restaurant 0.0\n",
"3 Hotel 0.0\n",
"4 Sushi Restaurant 0.0\n",
"\n",
"\n"
]
}
],
"source": [
"#### Let's print each neighborhood along with the top 5 most common venues\n",
"\n",
"num_top_venues = 5\n",
"\n",
"for hood in toronto_grouped['Neighborhood']:\n",
" print(\"----\"+hood+\"----\")\n",
" temp = toronto_grouped[toronto_grouped['Neighborhood'] == hood].T.reset_index()\n",
" temp.columns = ['venue','freq']\n",
" temp = temp.iloc[1:]\n",
" temp['freq'] = temp['freq'].astype(float)\n",
" temp = temp.round({'freq': 2})\n",
" print(temp.sort_values('freq', ascending=False).reset_index(drop=True).head(num_top_venues))\n",
" print('\\n')"
]
},
{
"cell_type": "code",
"execution_count": 184,
"metadata": {},
"outputs": [],
"source": [
"# Let's put that into a *pandas* dataframe\n",
"# First, let's write a function to sort the venues in descending order.\n",
"\n",
"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": 352,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>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>Agincourt</td>\n",
" <td>Breakfast Spot</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Grocery Store</td>\n",
" <td>Bakery</td>\n",
" <td>Bank</td>\n",
" <td>Bar</td>\n",
" <td>Beer Bar</td>\n",
" <td>Café</td>\n",
" <td>Clothing Store</td>\n",
" <td>Coffee Shop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Alderwood / Long Branch</td>\n",
" <td>Pizza Place</td>\n",
" <td>Gym</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Pub</td>\n",
" <td>Pharmacy</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Fast Food Restaurant</td>\n",
" <td>Bakery</td>\n",
" <td>Bank</td>\n",
" <td>Bar</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Bathurst Manor / Wilson Heights / Downsview North</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Bank</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Restaurant</td>\n",
" <td>Pizza Place</td>\n",
" <td>Pharmacy</td>\n",
" <td>Park</td>\n",
" <td>Sushi Restaurant</td>\n",
" <td>Grocery Store</td>\n",
" <td>Thai Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Bayview Village</td>\n",
" <td>Bank</td>\n",
" <td>Café</td>\n",
" <td>Japanese Restaurant</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Grocery Store</td>\n",
" <td>Bakery</td>\n",
" <td>Bar</td>\n",
" <td>Beer Bar</td>\n",
" <td>Breakfast Spot</td>\n",
" <td>Clothing Store</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Bedford Park / Lawrence Manor East</td>\n",
" <td>Italian Restaurant</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Restaurant</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Café</td>\n",
" <td>Grocery Store</td>\n",
" <td>Sushi Restaurant</td>\n",
" <td>American Restaurant</td>\n",
" <td>Pharmacy</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Neighborhood 1st Most Common Venue \\\n",
"0 Agincourt Breakfast Spot \n",
"1 Alderwood / Long Branch Pizza Place \n",
"2 Bathurst Manor / Wilson Heights / Downsview North Coffee Shop \n",
"3 Bayview Village Bank \n",
"4 Bedford Park / Lawrence Manor East Italian Restaurant \n",
"\n",
" 2nd Most Common Venue 3rd Most Common Venue 4th Most Common Venue \\\n",
"0 Thai Restaurant Grocery Store Bakery \n",
"1 Gym Sandwich Place Pub \n",
"2 Bank Sandwich Place Restaurant \n",
"3 Café Japanese Restaurant Thai Restaurant \n",
"4 Sandwich Place Restaurant Coffee Shop \n",
"\n",
" 5th Most Common Venue 6th Most Common Venue 7th Most Common Venue \\\n",
"0 Bank Bar Beer Bar \n",
"1 Pharmacy Coffee Shop Fast Food Restaurant \n",
"2 Pizza Place Pharmacy Park \n",
"3 Grocery Store Bakery Bar \n",
"4 Thai Restaurant Café Grocery Store \n",
"\n",
" 8th Most Common Venue 9th Most Common Venue 10th Most Common Venue \n",
"0 Café Clothing Store Coffee Shop \n",
"1 Bakery Bank Bar \n",
"2 Sushi Restaurant Grocery Store Thai Restaurant \n",
"3 Beer Bar Breakfast Spot Clothing Store \n",
"4 Sushi Restaurant American Restaurant Pharmacy "
]
},
"execution_count": 352,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Now let's create the new dataframe and display the top 10 venues for each neighborhood.\n",
"\n",
"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": "markdown",
"metadata": {},
"source": [
"<a id='item4'></a>"
]
},
{
"cell_type": "code",
"execution_count": 353,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(86, 11)"
]
},
"execution_count": 353,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"neighborhoods_venues_sorted.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Cluster Neighborhoods"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Running *k*-means to cluster the neighborhood into 5 clusters."
]
},
{
"cell_type": "code",
"execution_count": 354,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"data": {
"text/plain": [
"array([0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 2, 0, 1,\n",
" 0, 0, 0, 1, 0, 1, 0, 1, 0, 3, 0, 1, 0, 0, 1, 0, 0, 0, 1, 3, 0, 2,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 0, 0, 4, 1, 1],\n",
" dtype=int32)"
]
},
"execution_count": 354,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# set number of clusters\n",
"kclusters = 5\n",
"\n",
"toronto_grouped_clustering = toronto_grouped.drop('Neighborhood', 1)\n",
"\n",
"# run k-means clustering\n",
"kmeans = KMeans(n_clusters=kclusters, random_state=0).fit(toronto_grouped_clustering)\n",
"\n",
"# check cluster labels generated for each row in the dataframe\n",
"kmeans.labels_"
]
},
{
"cell_type": "code",
"execution_count": 355,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(86, 25)"
]
},
"execution_count": 355,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"toronto_grouped_clustering.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's create a new dataframe that includes the cluster as well as the top 10 venues for each neighborhood."
]
},
{
"cell_type": "code",
"execution_count": 356,
"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>Agincourt</td>\n",
" <td>Breakfast Spot</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Grocery Store</td>\n",
" <td>Bakery</td>\n",
" <td>Bank</td>\n",
" <td>Bar</td>\n",
" <td>Beer Bar</td>\n",
" <td>Café</td>\n",
" <td>Clothing Store</td>\n",
" <td>Coffee Shop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Alderwood / Long Branch</td>\n",
" <td>Pizza Place</td>\n",
" <td>Gym</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Pub</td>\n",
" <td>Pharmacy</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Fast Food Restaurant</td>\n",
" <td>Bakery</td>\n",
" <td>Bank</td>\n",
" <td>Bar</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Bathurst Manor / Wilson Heights / Downsview North</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Bank</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Restaurant</td>\n",
" <td>Pizza Place</td>\n",
" <td>Pharmacy</td>\n",
" <td>Park</td>\n",
" <td>Sushi Restaurant</td>\n",
" <td>Grocery Store</td>\n",
" <td>Thai Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Bayview Village</td>\n",
" <td>Bank</td>\n",
" <td>Café</td>\n",
" <td>Japanese Restaurant</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Grocery Store</td>\n",
" <td>Bakery</td>\n",
" <td>Bar</td>\n",
" <td>Beer Bar</td>\n",
" <td>Breakfast Spot</td>\n",
" <td>Clothing Store</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Bedford Park / Lawrence Manor East</td>\n",
" <td>Italian Restaurant</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Restaurant</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Café</td>\n",
" <td>Grocery Store</td>\n",
" <td>Sushi Restaurant</td>\n",
" <td>American Restaurant</td>\n",
" <td>Pharmacy</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Neighborhood 1st Most Common Venue \\\n",
"0 Agincourt Breakfast Spot \n",
"1 Alderwood / Long Branch Pizza Place \n",
"2 Bathurst Manor / Wilson Heights / Downsview North Coffee Shop \n",
"3 Bayview Village Bank \n",
"4 Bedford Park / Lawrence Manor East Italian Restaurant \n",
"\n",
" 2nd Most Common Venue 3rd Most Common Venue 4th Most Common Venue \\\n",
"0 Thai Restaurant Grocery Store Bakery \n",
"1 Gym Sandwich Place Pub \n",
"2 Bank Sandwich Place Restaurant \n",
"3 Café Japanese Restaurant Thai Restaurant \n",
"4 Sandwich Place Restaurant Coffee Shop \n",
"\n",
" 5th Most Common Venue 6th Most Common Venue 7th Most Common Venue \\\n",
"0 Bank Bar Beer Bar \n",
"1 Pharmacy Coffee Shop Fast Food Restaurant \n",
"2 Pizza Place Pharmacy Park \n",
"3 Grocery Store Bakery Bar \n",
"4 Thai Restaurant Café Grocery Store \n",
"\n",
" 8th Most Common Venue 9th Most Common Venue 10th Most Common Venue \n",
"0 Café Clothing Store Coffee Shop \n",
"1 Bakery Bank Bar \n",
"2 Sushi Restaurant Grocery Store Thai Restaurant \n",
"3 Beer Bar Breakfast Spot Clothing Store \n",
"4 Sushi Restaurant American Restaurant Pharmacy "
]
},
"execution_count": 356,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"neighborhoods_venues_sorted.head()"
]
},
{
"cell_type": "code",
"execution_count": 357,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"# add clustering labels\n",
"neighborhoods_venues_sorted.insert(0, 'Cluster Labels', kmeans.labels_)\n"
]
},
{
"cell_type": "code",
"execution_count": 358,
"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>Borough</th>\n",
" <th>Neighborhood</th>\n",
" <th>Latitude</th>\n",
" <th>Longitude</th>\n",
" <th>city</th>\n",
" <th>Postalcode</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>171</th>\n",
" <td>Queens</td>\n",
" <td>Broad Channel</td>\n",
" <td>40.603027</td>\n",
" <td>-73.820055</td>\n",
" <td>NY</td>\n",
" <td>NY</td>\n",
" <td>2.0</td>\n",
" <td>Pizza Place</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Grocery Store</td>\n",
" <td>Bakery</td>\n",
" <td>Bank</td>\n",
" <td>Bar</td>\n",
" <td>Beer Bar</td>\n",
" <td>Breakfast Spot</td>\n",
" <td>Café</td>\n",
" <td>Clothing Store</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>North York</td>\n",
" <td>Parkwoods</td>\n",
" <td>43.753259</td>\n",
" <td>-79.329656</td>\n",
" <td>TO</td>\n",
" <td>M3A</td>\n",
" <td>1.0</td>\n",
" <td>Park</td>\n",
" <td
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment