Created
August 30, 2020 19:22
-
-
Save e-roux/d37c6ad78a46ab00147948dde32dc20a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"%load_ext lab_black\n", | |
"%load_ext watermark" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"2020-08-30 \n", | |
"\n", | |
"CPython 3.8.3\n", | |
"IPython 7.18.1\n", | |
"\n", | |
"pandas 1.1.1\n", | |
"geocoder 1.38.1\n", | |
"geopy 2.0.0\n", | |
"folium 0.11.0\n", | |
"\n", | |
"compiler : GCC 9.2.1 20191008\n", | |
"system : Linux\n", | |
"release : 5.3.0-64-generic\n", | |
"machine : x86_64\n", | |
"processor : x86_64\n", | |
"CPU cores : 8\n", | |
"interpreter: 64bit\n" | |
] | |
} | |
], | |
"source": [ | |
"%watermark -mvdp pandas,geocoder,geopy,folium" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 93, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from typing import Mapping, Dict, List, Tuple\n", | |
"\n", | |
"from matplotlib.colors import to_hex\n", | |
"import matplotlib.cm as cm\n", | |
"import matplotlib.colors as colors\n", | |
"import numpy as np\n", | |
"import pandas as pd\n", | |
"from pandas import DataFrame\n", | |
"from pandas.io.json import json_normalize # tranform JSON file into a pandas dataframe\n", | |
"from sklearn.cluster import KMeans\n", | |
"\n", | |
"from IPython.display import JSON\n", | |
"\n", | |
"# For getting the data from the foursquare API\n", | |
"import requests\n", | |
"from requests import Request\n", | |
"import asyncio\n", | |
"from aiohttp import ClientSession\n", | |
"\n", | |
"import geocoder\n", | |
"\n", | |
"# convert an address into latitude and longitude values\n", | |
"from geopy import Location\n", | |
"from geopy.geocoders import Nominatim\n", | |
"import folium" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# DataFrame creation" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"url = \"https://en.wikipedia.org/wiki/List_of_postal_codes_of_Canada:_M\"\n", | |
"dfs: List[DataFrame] = pd.read_html(url)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"I read first the data from the given url, web scrapping is made by pandas :smile:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"df, *_ = pd.read_html(url, na_values=\"Not assigned\")" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The dataframe will consist of three columns: PostalCode, Borough, and Neighborhood" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"df.columns = [\"PostalCode\", \"Borough\", \"Neighborhood\"]" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"I process the cells that have an assigned borough and ignore cells with a borough that is Not assigned." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# equivalent to df = df[~df.Borough.isna()]\n", | |
"df.dropna(subset=[\"Borough\"], inplace=True)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"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>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", | |
" <tr>\n", | |
" <th>5</th>\n", | |
" <td>M6A</td>\n", | |
" <td>North York</td>\n", | |
" <td>Lawrence Manor, Lawrence Heights</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>6</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", | |
"2 M3A North York Parkwoods\n", | |
"3 M4A North York Victoria Village\n", | |
"4 M5A Downtown Toronto Regent Park, Harbourfront\n", | |
"5 M6A North York Lawrence Manor, Lawrence Heights\n", | |
"6 M7A Downtown Toronto Queen's Park, Ontario Provincial Government" | |
] | |
}, | |
"execution_count": 8, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"df.head()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"<class 'pandas.core.frame.DataFrame'>\n", | |
"Int64Index: 103 entries, 2 to 178\n", | |
"Data columns (total 3 columns):\n", | |
" # Column Non-Null Count Dtype \n", | |
"--- ------ -------------- ----- \n", | |
" 0 PostalCode 103 non-null object\n", | |
" 1 Borough 103 non-null object\n", | |
" 2 Neighborhood 103 non-null object\n", | |
"dtypes: object(3)\n", | |
"memory usage: 3.2+ KB\n" | |
] | |
} | |
], | |
"source": [ | |
"df.info()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"More than one neighborhood can exist in one postal code area. For example, in the table on the Wikipedia page, you will notice that M5A is listed twice and has two neighborhoods: Harbourfront and Regent Park. These two rows will be combined into one row with the neighborhoods separated with a comma as shown in row 11 in the above table.\n", | |
"\n", | |
"`.groupby()` use by creating a function doing that ope" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"df = (\n", | |
" df.fillna({\"Neighborhood\": df.Borough})\n", | |
" .groupby(\"PostalCode\")\n", | |
" .agg(\n", | |
" {\n", | |
" \"Borough\": lambda g: g,\n", | |
" \"Neighborhood\": lambda g: \", \".join(g),\n", | |
" }\n", | |
" )\n", | |
" .reset_index()\n", | |
" .astype(\"string\")\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"<class 'pandas.core.frame.DataFrame'>\n", | |
"RangeIndex: 103 entries, 0 to 102\n", | |
"Data columns (total 3 columns):\n", | |
" # Column Non-Null Count Dtype \n", | |
"--- ------ -------------- ----- \n", | |
" 0 PostalCode 103 non-null string\n", | |
" 1 Borough 103 non-null string\n", | |
" 2 Neighborhood 103 non-null string\n", | |
"dtypes: string(3)\n", | |
"memory usage: 2.5 KB\n" | |
] | |
} | |
], | |
"source": [ | |
"df.info()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Reset the index and drop the former index values" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>PostalCode</th>\n", | |
" <th>Borough</th>\n", | |
" <th>Neighborhood</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>M1B</td>\n", | |
" <td>Scarborough</td>\n", | |
" <td>Malvern, Rouge</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>M1C</td>\n", | |
" <td>Scarborough</td>\n", | |
" <td>Rouge Hill, Port Union, Highland Creek</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2</th>\n", | |
" <td>M1E</td>\n", | |
" <td>Scarborough</td>\n", | |
" <td>Guildwood, Morningside, West Hill</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>3</th>\n", | |
" <td>M1G</td>\n", | |
" <td>Scarborough</td>\n", | |
" <td>Woburn</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>4</th>\n", | |
" <td>M1H</td>\n", | |
" <td>Scarborough</td>\n", | |
" <td>Cedarbrae</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" PostalCode Borough Neighborhood\n", | |
"0 M1B Scarborough Malvern, Rouge\n", | |
"1 M1C Scarborough Rouge Hill, Port Union, Highland Creek\n", | |
"2 M1E Scarborough Guildwood, Morningside, West Hill\n", | |
"3 M1G Scarborough Woburn\n", | |
"4 M1H Scarborough Cedarbrae" | |
] | |
}, | |
"execution_count": 12, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"df.head()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# DataFrame with latitude and longitude" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Using the PostalCode and Borough data from the dataframe to build a query string for google geocoding API" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 13, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"'M1G, Scarborough'" | |
] | |
}, | |
"execution_count": 13, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"search_query = \", \".join(df.iloc[3][[\"PostalCode\", \"Borough\"]])\n", | |
"search_query" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Unfortunalty, no [API key](https://geocoder.readthedocs.io/providers/Google.html#environment-variables) available" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"<[REQUEST_DENIED] Google - Geocode [empty]>" | |
] | |
}, | |
"execution_count": 14, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"geocoder.google(search_query)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"I go for the csv data and rename one column" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 15, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>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", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" PostalCode Latitude Longitude\n", | |
"0 M1B 43.806686 -79.194353\n", | |
"1 M1C 43.784535 -79.160497" | |
] | |
}, | |
"execution_count": 15, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"gd: DataFrame = pd.read_csv(\"https://cocl.us/Geospatial_data\").rename(\n", | |
" mapper={\"Postal Code\": \"PostalCode\"}, axis=1\n", | |
")\n", | |
"gd.head(2)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Join the two DataFrame" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 16, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>PostalCode</th>\n", | |
" <th>Borough</th>\n", | |
" <th>Neighborhood</th>\n", | |
" <th>Latitude</th>\n", | |
" <th>Longitude</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>M1B</td>\n", | |
" <td>Scarborough</td>\n", | |
" <td>Malvern, Rouge</td>\n", | |
" <td>43.806686</td>\n", | |
" <td>-79.194353</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>M1C</td>\n", | |
" <td>Scarborough</td>\n", | |
" <td>Rouge Hill, Port Union, Highland Creek</td>\n", | |
" <td>43.784535</td>\n", | |
" <td>-79.160497</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2</th>\n", | |
" <td>M1E</td>\n", | |
" <td>Scarborough</td>\n", | |
" <td>Guildwood, Morningside, West Hill</td>\n", | |
" <td>43.763573</td>\n", | |
" <td>-79.188711</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>3</th>\n", | |
" <td>M1G</td>\n", | |
" <td>Scarborough</td>\n", | |
" <td>Woburn</td>\n", | |
" <td>43.770992</td>\n", | |
" <td>-79.216917</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>4</th>\n", | |
" <td>M1H</td>\n", | |
" <td>Scarborough</td>\n", | |
" <td>Cedarbrae</td>\n", | |
" <td>43.773136</td>\n", | |
" <td>-79.239476</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" PostalCode Borough Neighborhood Latitude \\\n", | |
"0 M1B Scarborough Malvern, Rouge 43.806686 \n", | |
"1 M1C Scarborough Rouge Hill, Port Union, Highland Creek 43.784535 \n", | |
"2 M1E Scarborough Guildwood, Morningside, West Hill 43.763573 \n", | |
"3 M1G Scarborough Woburn 43.770992 \n", | |
"4 M1H Scarborough Cedarbrae 43.773136 \n", | |
"\n", | |
" Longitude \n", | |
"0 -79.194353 \n", | |
"1 -79.160497 \n", | |
"2 -79.188711 \n", | |
"3 -79.216917 \n", | |
"4 -79.239476 " | |
] | |
}, | |
"execution_count": 16, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"dfc: DataFrame = (\n", | |
" df.set_index(\"PostalCode\")\n", | |
" .join(gd.set_index(\"PostalCode\"))\n", | |
" .reset_index()\n", | |
" .astype({\"PostalCode\": \"string\"})\n", | |
")\n", | |
"dfc.head()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 17, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"<class 'pandas.core.frame.DataFrame'>\n", | |
"RangeIndex: 103 entries, 0 to 102\n", | |
"Data columns (total 5 columns):\n", | |
" # Column Non-Null Count Dtype \n", | |
"--- ------ -------------- ----- \n", | |
" 0 PostalCode 103 non-null string \n", | |
" 1 Borough 103 non-null string \n", | |
" 2 Neighborhood 103 non-null string \n", | |
" 3 Latitude 103 non-null float64\n", | |
" 4 Longitude 103 non-null float64\n", | |
"dtypes: float64(2), string(3)\n", | |
"memory usage: 4.1 KB\n" | |
] | |
} | |
], | |
"source": [ | |
"dfc.info()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 18, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"<StringArray>\n", | |
"[ 'Scarborough', 'North York', 'East York',\n", | |
" 'East Toronto', 'Central Toronto', 'Downtown Toronto',\n", | |
" 'York', 'West Toronto', 'Mississauga',\n", | |
" 'Etobicoke']\n", | |
"Length: 10, dtype: string" | |
] | |
}, | |
"execution_count": 18, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"dfc.Borough.unique()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Exploration and clustering of the neighborhoods in Toronto" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Map of Toronto with neighborhoods" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Create a map of Toronto with neighborhoods superimposed on top. Let's get the geographical coordinates of Toronto." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 19, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def get_geocoord_from(address: str) -> Location:\n", | |
" geolocator = Nominatim(user_agent=\"ny_explorer\")\n", | |
" location = geolocator.geocode(address)\n", | |
" return location\n", | |
"\n", | |
"\n", | |
"def print_geocoord_from(address: str) -> None:\n", | |
" location = get_geocoord_from(address)\n", | |
"\n", | |
" print(\n", | |
" f'The geograpical coordinates of \"{address}\" are ({location.latitude}, {location.longitude})'\n", | |
" )" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 20, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"The geograpical coordinates of \"Toronto, ON\" are (43.6534817, -79.3839347)\n" | |
] | |
} | |
], | |
"source": [ | |
"print_geocoord_from(\"Toronto, ON\")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 227, | |
"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+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgCiAgICAgICAgPHNjcmlwdD4KICAgICAgICAgICAgTF9OT19UT1VDSCA9IGZhbHNlOwogICAgICAgICAgICBMX0RJU0FCTEVfM0QgPSBmYWxzZTsKICAgICAgICA8L3NjcmlwdD4KICAgIAogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjYuMC9kaXN0L2xlYWZsZXQuanMiPjwvc2NyaXB0PgogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY29kZS5qcXVlcnkuY29tL2pxdWVyeS0xLjEyLjQubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9qcy9ib290c3RyYXAubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5qcyI+PC9zY3JpcHQ+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjYuMC9kaXN0L2xlYWZsZXQuY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vYm9vdHN0cmFwLzMuMi4wL2Nzcy9ib290c3RyYXAubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLXRoZW1lLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9mb250LWF3ZXNvbWUvNC42LjMvY3NzL2ZvbnQtYXdlc29tZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL0xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLzIuMC4yL2xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL3Jhd2Nkbi5naXRoYWNrLmNvbS9weXRob24tdmlzdWFsaXphdGlvbi9mb2xpdW0vbWFzdGVyL2ZvbGl1bS90ZW1wbGF0ZXMvbGVhZmxldC5hd2Vzb21lLnJvdGF0ZS5jc3MiLz4KICAgIDxzdHlsZT5odG1sLCBib2R5IHt3aWR0aDogMTAwJTtoZWlnaHQ6IDEwMCU7bWFyZ2luOiAwO3BhZGRpbmc6IDA7fTwvc3R5bGU+CiAgICA8c3R5bGU+I21hcCB7cG9zaXRpb246YWJzb2x1dGU7dG9wOjA7Ym90dG9tOjA7cmlnaHQ6MDtsZWZ0OjA7fTwvc3R5bGU+CiAgICAKICAgICAgICAgICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwKICAgICAgICAgICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgICAgICAgICAgPHN0eWxlPgogICAgICAgICAgICAgICAgI21hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYiB7CiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlOwogICAgICAgICAgICAgICAgICAgIHdpZHRoOiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgbGVmdDogMC4wJTsKICAgICAgICAgICAgICAgICAgICB0b3A6IDAuMCU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDwvc3R5bGU+CiAgICAgICAgCjwvaGVhZD4KPGJvZHk+ICAgIAogICAgCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvbGl1bS1tYXAiIGlkPSJtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIiID48L2Rpdj4KICAgICAgICAKPC9ib2R5Pgo8c2NyaXB0PiAgICAKICAgIAogICAgICAgICAgICB2YXIgbWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiID0gTC5tYXAoCiAgICAgICAgICAgICAgICAibWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiIiwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBjZW50ZXI6IFs0My42NTM0ODE3LCAtNzkuMzgzOTM0N10sCiAgICAgICAgICAgICAgICAgICAgY3JzOiBMLkNSUy5FUFNHMzg1NywKICAgICAgICAgICAgICAgICAgICB6b29tOiAxMCwKICAgICAgICAgICAgICAgICAgICB6b29tQ29udHJvbDogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICBwcmVmZXJDYW52YXM6IGZhbHNlLAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICApOwoKICAgICAgICAgICAgCgogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciB0aWxlX2xheWVyXzNlZTZmNDUxMzE0YTRmMWViOGU5ZTE4OGY3Yzg0ODBhID0gTC50aWxlTGF5ZXIoCiAgICAgICAgICAgICAgICAiaHR0cHM6Ly97c30udGlsZS5vcGVuc3RyZWV0bWFwLm9yZy97en0ve3h9L3t5fS5wbmciLAogICAgICAgICAgICAgICAgeyJhdHRyaWJ1dGlvbiI6ICJEYXRhIGJ5IFx1MDAyNmNvcHk7IFx1MDAzY2EgaHJlZj1cImh0dHA6Ly9vcGVuc3RyZWV0bWFwLm9yZ1wiXHUwMDNlT3BlblN0cmVldE1hcFx1MDAzYy9hXHUwMDNlLCB1bmRlciBcdTAwM2NhIGhyZWY9XCJodHRwOi8vd3d3Lm9wZW5zdHJlZXRtYXAub3JnL2NvcHlyaWdodFwiXHUwMDNlT0RiTFx1MDAzYy9hXHUwMDNlLiIsICJkZXRlY3RSZXRpbmEiOiBmYWxzZSwgIm1heE5hdGl2ZVpvb20iOiAxOCwgIm1heFpvb20iOiAxOCwgIm1pblpvb20iOiAwLCAibm9XcmFwIjogZmFsc2UsICJvcGFjaXR5IjogMSwgInN1YmRvbWFpbnMiOiAiYWJjIiwgInRtcyI6IGZhbHNlfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMDBmODkwNTYxNjliNGQyYWExOWZjN2MxZDNhMGJiYTYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My44MDY2ODYyOTk5OTk5OTYsIC03OS4xOTQzNTM0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzZhNGI1YyIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNmE0YjVjIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9lYWE3NDkyNWE3NTc0OGM0OTRlNjFjNmZlNzI4ZTZhNiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfOWM2MzZmM2NiNDIyNDVlNGIyZDZjMzc2MDI1MzczNTUgPSAkKGA8ZGl2IGlkPSJodG1sXzljNjM2ZjNjYjQyMjQ1ZTRiMmQ2YzM3NjAyNTM3MzU1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5NYWx2ZXJuLCBSb3VnZSwgU2NhcmJvcm91Z2g8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfZWFhNzQ5MjVhNzU3NDhjNDk0ZTYxYzZmZTcyOGU2YTYuc2V0Q29udGVudChodG1sXzljNjM2ZjNjYjQyMjQ1ZTRiMmQ2YzM3NjAyNTM3MzU1KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl8wMGY4OTA1NjE2OWI0ZDJhYTE5ZmM3YzFkM2EwYmJhNi5iaW5kUG9wdXAocG9wdXBfZWFhNzQ5MjVhNzU3NDhjNDk0ZTYxYzZmZTcyOGU2YTYpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzk3MDc0MjQwNzBlZTQwZTQ5ZjcyMDA3OGVhZTU0ZTAwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzg0NTM1MSwgLTc5LjE2MDQ5NzA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNmE0YjVjIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM2YTRiNWMiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzFkNWRiNTFiYjc0NzQxMWE5N2JhMjhjNzUxNjQxMTFmID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9kYjQyNGY1MTNkZjA0ODUxYTBjM2M3NjY5NGFjMjdjYSA9ICQoYDxkaXYgaWQ9Imh0bWxfZGI0MjRmNTEzZGYwNDg1MWEwYzNjNzY2OTRhYzI3Y2EiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJvdWdlIEhpbGwsIFBvcnQgVW5pb24sIEhpZ2hsYW5kIENyZWVrLCBTY2FyYm9yb3VnaDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8xZDVkYjUxYmI3NDc0MTFhOTdiYTI4Yzc1MTY0MTExZi5zZXRDb250ZW50KGh0bWxfZGI0MjRmNTEzZGYwNDg1MWEwYzNjNzY2OTRhYzI3Y2EpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzk3MDc0MjQwNzBlZTQwZTQ5ZjcyMDA3OGVhZTU0ZTAwLmJpbmRQb3B1cChwb3B1cF8xZDVkYjUxYmI3NDc0MTFhOTdiYTI4Yzc1MTY0MTExZikKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNWY1YjkzMDkzODA1NGFiMDhiNTZlZDU5ODM4NDliY2MgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NjM1NzI2LCAtNzkuMTg4NzExNV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzZhNGI1YyIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNmE0YjVjIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF8yMmVlNDI2OGQ5YjE0NmY3YTdmZjQ5MjI2M2UyM2FkOCA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfN2Y2NDkyNjA2Y2NiNDU1MTk1MjE0YTlhNTg2YTA3MWMgPSAkKGA8ZGl2IGlkPSJodG1sXzdmNjQ5MjYwNmNjYjQ1NTE5NTIxNGE5YTU4NmEwNzFjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5HdWlsZHdvb2QsIE1vcm5pbmdzaWRlLCBXZXN0IEhpbGwsIFNjYXJib3JvdWdoPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzIyZWU0MjY4ZDliMTQ2ZjdhN2ZmNDkyMjYzZTIzYWQ4LnNldENvbnRlbnQoaHRtbF83ZjY0OTI2MDZjY2I0NTUxOTUyMTRhOWE1ODZhMDcxYyk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNWY1YjkzMDkzODA1NGFiMDhiNTZlZDU5ODM4NDliY2MuYmluZFBvcHVwKHBvcHVwXzIyZWU0MjY4ZDliMTQ2ZjdhN2ZmNDkyMjYzZTIzYWQ4KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80MWUxZDM1ZmUwMTk0YjBiYjUxYzNiYTU3NTgwODMyMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc3MDk5MjEsIC03OS4yMTY5MTc0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzZhNGI1YyIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNmE0YjVjIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9hYTY2NGQ2MDYzMDQ0NzNlYmIyYTM4N2U1MGU1MmZiOCA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfYTNhMGQyYTAzMTg4NDc2ODliNmFhMjI1YmJhZDQ0OWQgPSAkKGA8ZGl2IGlkPSJodG1sX2EzYTBkMmEwMzE4ODQ3Njg5YjZhYTIyNWJiYWQ0NDlkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Xb2J1cm4sIFNjYXJib3JvdWdoPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2FhNjY0ZDYwNjMwNDQ3M2ViYjJhMzg3ZTUwZTUyZmI4LnNldENvbnRlbnQoaHRtbF9hM2EwZDJhMDMxODg0NzY4OWI2YWEyMjViYmFkNDQ5ZCk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNDFlMWQzNWZlMDE5NGIwYmI1MWMzYmE1NzU4MDgzMjIuYmluZFBvcHVwKHBvcHVwX2FhNjY0ZDYwNjMwNDQ3M2ViYjJhMzg3ZTUwZTUyZmI4KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zOTFiNDc5NGJmYWQ0Y2U0YmQwODlhMDNlNDdmOGM0OSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc3MzEzNiwgLTc5LjIzOTQ3NjA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNmE0YjVjIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM2YTRiNWMiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2VkODY0MTNjODMxMjRlYzc4MGM5ZjI5ZTQ2OGQ0MmZlID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF83NDVkODRlMDI3MWY0NWFkYWZhM2EyOWNhNjRlNjAwNSA9ICQoYDxkaXYgaWQ9Imh0bWxfNzQ1ZDg0ZTAyNzFmNDVhZGFmYTNhMjljYTY0ZTYwMDUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNlZGFyYnJhZSwgU2NhcmJvcm91Z2g8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfZWQ4NjQxM2M4MzEyNGVjNzgwYzlmMjllNDY4ZDQyZmUuc2V0Q29udGVudChodG1sXzc0NWQ4NGUwMjcxZjQ1YWRhZmEzYTI5Y2E2NGU2MDA1KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl8zOTFiNDc5NGJmYWQ0Y2U0YmQwODlhMDNlNDdmOGM0OS5iaW5kUG9wdXAocG9wdXBfZWQ4NjQxM2M4MzEyNGVjNzgwYzlmMjllNDY4ZDQyZmUpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzMzZTkxYmMwYzZiYTQ1M2E5N2RiNjI4NzlhNWU5MmRjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzQ0NzM0MiwgLTc5LjIzOTQ3NjA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNmE0YjVjIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM2YTRiNWMiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzVjMTY1YTE1OGIyMDQwNTBhNzI4Y2U5NTkxOTcxYWU3ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF84MGM5YzE3MGMyMmI0NjlkOGVjZGEwN2ZlYjVkYmUxMyA9ICQoYDxkaXYgaWQ9Imh0bWxfODBjOWMxNzBjMjJiNDY5ZDhlY2RhMDdmZWI1ZGJlMTMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlNjYXJib3JvdWdoIFZpbGxhZ2UsIFNjYXJib3JvdWdoPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzVjMTY1YTE1OGIyMDQwNTBhNzI4Y2U5NTkxOTcxYWU3LnNldENvbnRlbnQoaHRtbF84MGM5YzE3MGMyMmI0NjlkOGVjZGEwN2ZlYjVkYmUxMyk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMzNlOTFiYzBjNmJhNDUzYTk3ZGI2Mjg3OWE1ZTkyZGMuYmluZFBvcHVwKHBvcHVwXzVjMTY1YTE1OGIyMDQwNTBhNzI4Y2U5NTkxOTcxYWU3KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83Yzg2NTU5ZWI0ZjU0M2Q3YmIzMDBkOTNiMjE3YzkwZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcyNzkyOTIsIC03OS4yNjIwMjk0MDAwMDAwMl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzZhNGI1YyIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNmE0YjVjIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9jNjIxYmI1OGU1NTk0ODRjYTdlYmM4ZTlmZDBhZWVkOSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfNmQ1NzAyYjQ3YjQ0NDBjOTkxNzY5NTg2ZWRmMTI3ZWEgPSAkKGA8ZGl2IGlkPSJodG1sXzZkNTcwMmI0N2I0NDQwYzk5MTc2OTU4NmVkZjEyN2VhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5LZW5uZWR5IFBhcmssIElvbnZpZXcsIEVhc3QgQmlyY2htb3VudCBQYXJrLCBTY2FyYm9yb3VnaDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9jNjIxYmI1OGU1NTk0ODRjYTdlYmM4ZTlmZDBhZWVkOS5zZXRDb250ZW50KGh0bWxfNmQ1NzAyYjQ3YjQ0NDBjOTkxNzY5NTg2ZWRmMTI3ZWEpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzdjODY1NTllYjRmNTQzZDdiYjMwMGQ5M2IyMTdjOTBlLmJpbmRQb3B1cChwb3B1cF9jNjIxYmI1OGU1NTk0ODRjYTdlYmM4ZTlmZDBhZWVkOSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMjRiMzRhZDQyOTNiNDIwNzhiMDU3ZDc0YmE1NWY4ZTcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MTExMTE3MDAwMDAwMDQsIC03OS4yODQ1NzcyXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNmE0YjVjIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM2YTRiNWMiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzA0Nzg0YzU5NTU0MDRhNTI5YTYyYTNiZDFmZDA4YmU0ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF83MzYxZjE3YWNjNzE0YzcxYWVjMmNhYWQxNDRiYWNiYSA9ICQoYDxkaXYgaWQ9Imh0bWxfNzM2MWYxN2FjYzcxNGM3MWFlYzJjYWFkMTQ0YmFjYmEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkdvbGRlbiBNaWxlLCBDbGFpcmxlYSwgT2FrcmlkZ2UsIFNjYXJib3JvdWdoPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzA0Nzg0YzU5NTU0MDRhNTI5YTYyYTNiZDFmZDA4YmU0LnNldENvbnRlbnQoaHRtbF83MzYxZjE3YWNjNzE0YzcxYWVjMmNhYWQxNDRiYWNiYSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMjRiMzRhZDQyOTNiNDIwNzhiMDU3ZDc0YmE1NWY4ZTcuYmluZFBvcHVwKHBvcHVwXzA0Nzg0YzU5NTU0MDRhNTI5YTYyYTNiZDFmZDA4YmU0KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lZDZlMjkwYTk1YmY0NmNiOGE0MzJhMjI0MTM5N2QwYyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcxNjMxNiwgLTc5LjIzOTQ3NjA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNmE0YjVjIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM2YTRiNWMiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2UxMWI2ZjRhMzYwNTRlNjA4NGY4N2RlNzlkNGY0Njk1ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9jNTMyOTI5ZWY3MzI0MTc3YmMyZjg5OGU1MTcxM2IzYiA9ICQoYDxkaXYgaWQ9Imh0bWxfYzUzMjkyOWVmNzMyNDE3N2JjMmY4OThlNTE3MTNiM2IiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNsaWZmc2lkZSwgQ2xpZmZjcmVzdCwgU2NhcmJvcm91Z2ggVmlsbGFnZSBXZXN0LCBTY2FyYm9yb3VnaDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9lMTFiNmY0YTM2MDU0ZTYwODRmODdkZTc5ZDRmNDY5NS5zZXRDb250ZW50KGh0bWxfYzUzMjkyOWVmNzMyNDE3N2JjMmY4OThlNTE3MTNiM2IpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2VkNmUyOTBhOTViZjQ2Y2I4YTQzMmEyMjQxMzk3ZDBjLmJpbmRQb3B1cChwb3B1cF9lMTFiNmY0YTM2MDU0ZTYwODRmODdkZTc5ZDRmNDY5NSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMTQ4M2Q3YjhjMTA1NDEzMGEyZmJhY2RmY2QzMTFmMzYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42OTI2NTcwMDAwMDAwMDQsIC03OS4yNjQ4NDgxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNmE0YjVjIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM2YTRiNWMiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2RlYWMzYWY3OTM3MTRhOTY4ZTU4MzUyMmJhOTBhY2YwID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF80NGFjYjBiNTNmNzc0YzM1OGRiMWNkYzgxNGUxY2FmNiA9ICQoYDxkaXYgaWQ9Imh0bWxfNDRhY2IwYjUzZjc3NGMzNThkYjFjZGM4MTRlMWNhZjYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJpcmNoIENsaWZmLCBDbGlmZnNpZGUgV2VzdCwgU2NhcmJvcm91Z2g8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfZGVhYzNhZjc5MzcxNGE5NjhlNTgzNTIyYmE5MGFjZjAuc2V0Q29udGVudChodG1sXzQ0YWNiMGI1M2Y3NzRjMzU4ZGIxY2RjODE0ZTFjYWY2KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl8xNDgzZDdiOGMxMDU0MTMwYTJmYmFjZGZjZDMxMWYzNi5iaW5kUG9wdXAocG9wdXBfZGVhYzNhZjc5MzcxNGE5NjhlNTgzNTIyYmE5MGFjZjApCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzU5ZmM1ZWQ0NTc3ODRkYWU5YTY4ZWQ4MWI3MzgzNDdjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzU3NDA5NiwgLTc5LjI3MzMwNDAwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNmE0YjVjIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM2YTRiNWMiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzNiMzBhNDBmZTEzNDQyNWJhN2YxZjc1OGU4Nzc0MGY2ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF81NTE4ZjIyNTE4YTA0ZTMzYmU0ODVmNWNmODNhNGY0ZiA9ICQoYDxkaXYgaWQ9Imh0bWxfNTUxOGYyMjUxOGEwNGUzM2JlNDg1ZjVjZjgzYTRmNGYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvcnNldCBQYXJrLCBXZXhmb3JkIEhlaWdodHMsIFNjYXJib3JvdWdoIFRvd24gQ2VudHJlLCBTY2FyYm9yb3VnaDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8zYjMwYTQwZmUxMzQ0MjViYTdmMWY3NThlODc3NDBmNi5zZXRDb250ZW50KGh0bWxfNTUxOGYyMjUxOGEwNGUzM2JlNDg1ZjVjZjgzYTRmNGYpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzU5ZmM1ZWQ0NTc3ODRkYWU5YTY4ZWQ4MWI3MzgzNDdjLmJpbmRQb3B1cChwb3B1cF8zYjMwYTQwZmUxMzQ0MjViYTdmMWY3NThlODc3NDBmNikKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMzlkNDNlNWNkNDE2NDVhOWI0NzM0YTE4OTY5ZGZmOGIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NTAwNzE1MDAwMDAwMDQsIC03OS4yOTU4NDkxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNmE0YjVjIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM2YTRiNWMiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzFjZDI5MGRlZDQ0YjQ3YjM5MDUzZTU5MDM5ZDZiMTJhID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9jZWRiMWMyNDhlZjY0NjY2YTE3MDRjMzYyNzM0N2E3OSA9ICQoYDxkaXYgaWQ9Imh0bWxfY2VkYjFjMjQ4ZWY2NDY2NmExNzA0YzM2MjczNDdhNzkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldleGZvcmQsIE1hcnl2YWxlLCBTY2FyYm9yb3VnaDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8xY2QyOTBkZWQ0NGI0N2IzOTA1M2U1OTAzOWQ2YjEyYS5zZXRDb250ZW50KGh0bWxfY2VkYjFjMjQ4ZWY2NDY2NmExNzA0YzM2MjczNDdhNzkpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzM5ZDQzZTVjZDQxNjQ1YTliNDczNGExODk2OWRmZjhiLmJpbmRQb3B1cChwb3B1cF8xY2QyOTBkZWQ0NGI0N2IzOTA1M2U1OTAzOWQ2YjEyYSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjM3YTEwZGQyZTlkNDMwMzlmM2VmYjY3YWM5MDM2MTYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43OTQyMDAzLCAtNzkuMjYyMDI5NDAwMDAwMDJdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM2YTRiNWMiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzZhNGI1YyIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMDQ5ZmUyMzgxMzc5NGE0NzllOWJjYjdmNTMzZDQyZjAgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzM3YWY2MmEwMWM4ZTRiNTM4OTk2NGU3NTUwOGI5ZTFkID0gJChgPGRpdiBpZD0iaHRtbF8zN2FmNjJhMDFjOGU0YjUzODk5NjRlNzU1MDhiOWUxZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QWdpbmNvdXJ0LCBTY2FyYm9yb3VnaDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8wNDlmZTIzODEzNzk0YTQ3OWU5YmNiN2Y1MzNkNDJmMC5zZXRDb250ZW50KGh0bWxfMzdhZjYyYTAxYzhlNGI1Mzg5OTY0ZTc1NTA4YjllMWQpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2YzN2ExMGRkMmU5ZDQzMDM5ZjNlZmI2N2FjOTAzNjE2LmJpbmRQb3B1cChwb3B1cF8wNDlmZTIzODEzNzk0YTQ3OWU5YmNiN2Y1MzNkNDJmMCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMjc1NzlmMDc4ODdmNGIwYzhmY2YwNGExZjNlZWY1ZTQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43ODE2Mzc1LCAtNzkuMzA0MzAyMV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzZhNGI1YyIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNmE0YjVjIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF85ZGRmZGFjYTgxNDM0MWRkOWIzYzhlZGI4Yzk1ZmRkNyA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfMGMwMGI2NzBhM2QyNDc5Yzg2NzEwYjBhMjdiN2I0MDMgPSAkKGA8ZGl2IGlkPSJodG1sXzBjMDBiNjcwYTNkMjQ3OWM4NjcxMGIwYTI3YjdiNDAzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DbGFya3MgQ29ybmVycywgVGFtIE8mIzM5O1NoYW50ZXIsIFN1bGxpdmFuLCBTY2FyYm9yb3VnaDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF85ZGRmZGFjYTgxNDM0MWRkOWIzYzhlZGI4Yzk1ZmRkNy5zZXRDb250ZW50KGh0bWxfMGMwMGI2NzBhM2QyNDc5Yzg2NzEwYjBhMjdiN2I0MDMpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzI3NTc5ZjA3ODg3ZjRiMGM4ZmNmMDRhMWYzZWVmNWU0LmJpbmRQb3B1cChwb3B1cF85ZGRmZGFjYTgxNDM0MWRkOWIzYzhlZGI4Yzk1ZmRkNykKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNzY2MmMxOWRkNmI3NDUxNWI0NmVhYTZmYzZmYmYzMTUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My44MTUyNTIyLCAtNzkuMjg0NTc3Ml0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzZhNGI1YyIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNmE0YjVjIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9jYjBhNWQxZDNlMjA0YTQwYTI3MjIwMDBjZjkxNTBiNSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfMDk2OTU5MGNkOTYyNGYxYTk2NTI4YzViNTdkZDYxODMgPSAkKGA8ZGl2IGlkPSJodG1sXzA5Njk1OTBjZDk2MjRmMWE5NjUyOGM1YjU3ZGQ2MTgzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5NaWxsaWtlbiwgQWdpbmNvdXJ0IE5vcnRoLCBTdGVlbGVzIEVhc3QsIEwmIzM5O0Ftb3JlYXV4IEVhc3QsIFNjYXJib3JvdWdoPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2NiMGE1ZDFkM2UyMDRhNDBhMjcyMjAwMGNmOTE1MGI1LnNldENvbnRlbnQoaHRtbF8wOTY5NTkwY2Q5NjI0ZjFhOTY1MjhjNWI1N2RkNjE4Myk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNzY2MmMxOWRkNmI3NDUxNWI0NmVhYTZmYzZmYmYzMTUuYmluZFBvcHVwKHBvcHVwX2NiMGE1ZDFkM2UyMDRhNDBhMjcyMjAwMGNmOTE1MGI1KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jYjMzYmFkYzYzZmM0ZWE2OWI1ZWRlOWE2MWM5ZmM1OSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc5OTUyNTIwMDAwMDAwNSwgLTc5LjMxODM4ODddLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM2YTRiNWMiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzZhNGI1YyIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMGEzMjM4NDI0YWZjNDhjM2E3ZGJkODhlMWE1MmU3MDMgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2NhYzM5ZjlhMTg3NDRmNmQ5MmMyMjRlNDUwN2YzOGM0ID0gJChgPGRpdiBpZD0iaHRtbF9jYWMzOWY5YTE4NzQ0ZjZkOTJjMjI0ZTQ1MDdmMzhjNCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3RlZWxlcyBXZXN0LCBMJiMzOTtBbW9yZWF1eCBXZXN0LCBTY2FyYm9yb3VnaDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8wYTMyMzg0MjRhZmM0OGMzYTdkYmQ4OGUxYTUyZTcwMy5zZXRDb250ZW50KGh0bWxfY2FjMzlmOWExODc0NGY2ZDkyYzIyNGU0NTA3ZjM4YzQpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2NiMzNiYWRjNjNmYzRlYTY5YjVlZGU5YTYxYzlmYzU5LmJpbmRQb3B1cChwb3B1cF8wYTMyMzg0MjRhZmM0OGMzYTdkYmQ4OGUxYTUyZTcwMykKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMTE1MDhjNmIyZGVjNGM1NWE5ZDQzODY3MTM3NDEyMTkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My44MzYxMjQ3MDAwMDAwMDYsIC03OS4yMDU2MzYwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzZhNGI1YyIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNmE0YjVjIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF8wYWNjYzhkNmJiZjM0M2FkYjU4ZDhmMWI0NDJhYmY2ZCA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfMmE1OTI4NWMwZTJjNDUwMjkzMmIzNTE5MjAzMWQzNDkgPSAkKGA8ZGl2IGlkPSJodG1sXzJhNTkyODVjMGUyYzQ1MDI5MzJiMzUxOTIwMzFkMzQ5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5VcHBlciBSb3VnZSwgU2NhcmJvcm91Z2g8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfMGFjY2M4ZDZiYmYzNDNhZGI1OGQ4ZjFiNDQyYWJmNmQuc2V0Q29udGVudChodG1sXzJhNTkyODVjMGUyYzQ1MDI5MzJiMzUxOTIwMzFkMzQ5KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl8xMTUwOGM2YjJkZWM0YzU1YTlkNDM4NjcxMzc0MTIxOS5iaW5kUG9wdXAocG9wdXBfMGFjY2M4ZDZiYmYzNDNhZGI1OGQ4ZjFiNDQyYWJmNmQpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY3NjQ4NTg2NjkyOTQ3YTk4OGRmNTQ3YjJhYzUwYTJjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuODAzNzYyMiwgLTc5LjM2MzQ1MTddLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM1MGIxMmMiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzUwYjEyYyIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMmU0YjA3ZDc0MzdiNDkzMTgzMjQ1YTVjMTI3YzgzNzIgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzA0NjI2ZWZhYzEyZTQzNDM5N2VmMGY3YzhmMjg1YjA2ID0gJChgPGRpdiBpZD0iaHRtbF8wNDYyNmVmYWMxMmU0MzQzOTdlZjBmN2M4ZjI4NWIwNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SGlsbGNyZXN0IFZpbGxhZ2UsIE5vcnRoIFlvcms8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfMmU0YjA3ZDc0MzdiNDkzMTgzMjQ1YTVjMTI3YzgzNzIuc2V0Q29udGVudChodG1sXzA0NjI2ZWZhYzEyZTQzNDM5N2VmMGY3YzhmMjg1YjA2KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl82NzY0ODU4NjY5Mjk0N2E5ODhkZjU0N2IyYWM1MGEyYy5iaW5kUG9wdXAocG9wdXBfMmU0YjA3ZDc0MzdiNDkzMTgzMjQ1YTVjMTI3YzgzNzIpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Q0YjBiMThmZDZhMDQ4YmRhM2E3YWQ0ODI1ZjZkOTI2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzc4NTE3NSwgLTc5LjM0NjU1NTddLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM1MGIxMmMiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzUwYjEyYyIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfZjQyNjBiYTY2MmQzNDAyNmExMzBkODkyOTFlZTQyMmUgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzI3MjYwYWU1OTNhZDRhMTI5MDk2ZmU2YTRjMDkyNjczID0gJChgPGRpdiBpZD0iaHRtbF8yNzI2MGFlNTkzYWQ0YTEyOTA5NmZlNmE0YzA5MjY3MyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RmFpcnZpZXcsIEhlbnJ5IEZhcm0sIE9yaW9sZSwgTm9ydGggWW9yazwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9mNDI2MGJhNjYyZDM0MDI2YTEzMGQ4OTI5MWVlNDIyZS5zZXRDb250ZW50KGh0bWxfMjcyNjBhZTU5M2FkNGExMjkwOTZmZTZhNGMwOTI2NzMpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2Q0YjBiMThmZDZhMDQ4YmRhM2E3YWQ0ODI1ZjZkOTI2LmJpbmRQb3B1cChwb3B1cF9mNDI2MGJhNjYyZDM0MDI2YTEzMGQ4OTI5MWVlNDIyZSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYTA3YzRmZTE1N2NiNGIyNzhlYjY1ZTRjMTJhMDQ0ZDAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43ODY5NDczLCAtNzkuMzg1OTc1XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNTBiMTJjIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM1MGIxMmMiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzAyZmJkYjRkNzdlMjQ2ZjRiNGJmNzU0MmZhM2YzOWJiID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF80Yjk5YTczNGM1YTk0YWQ0YWJlM2JjYmE2YmQ1ZmU4OSA9ICQoYDxkaXYgaWQ9Imh0bWxfNGI5OWE3MzRjNWE5NGFkNGFiZTNiY2JhNmJkNWZlODkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJheXZpZXcgVmlsbGFnZSwgTm9ydGggWW9yazwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8wMmZiZGI0ZDc3ZTI0NmY0YjRiZjc1NDJmYTNmMzliYi5zZXRDb250ZW50KGh0bWxfNGI5OWE3MzRjNWE5NGFkNGFiZTNiY2JhNmJkNWZlODkpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2EwN2M0ZmUxNTdjYjRiMjc4ZWI2NWU0YzEyYTA0NGQwLmJpbmRQb3B1cChwb3B1cF8wMmZiZGI0ZDc3ZTI0NmY0YjRiZjc1NDJmYTNmMzliYikKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZGU1Y2RmODY3M2ZlNGJkNDk4YTdlZDI5ODJkMGI2ODIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NTc0OTAyLCAtNzkuMzc0NzE0MDk5OTk5OTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM1MGIxMmMiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzUwYjEyYyIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfNzZkNzhjYTQxYzdmNDk4MmJmMjE2ZGEzMDJkY2RjNGQgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzBlMTgzNjY2MmMyNzQxYmNhODMzNWY4ZDEzZTAzNDc3ID0gJChgPGRpdiBpZD0iaHRtbF8wZTE4MzY2NjJjMjc0MWJjYTgzMzVmOGQxM2UwMzQ3NyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+WW9yayBNaWxscywgU2lsdmVyIEhpbGxzLCBOb3J0aCBZb3JrPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzc2ZDc4Y2E0MWM3ZjQ5ODJiZjIxNmRhMzAyZGNkYzRkLnNldENvbnRlbnQoaHRtbF8wZTE4MzY2NjJjMjc0MWJjYTgzMzVmOGQxM2UwMzQ3Nyk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfZGU1Y2RmODY3M2ZlNGJkNDk4YTdlZDI5ODJkMGI2ODIuYmluZFBvcHVwKHBvcHVwXzc2ZDc4Y2E0MWM3ZjQ5ODJiZjIxNmRhMzAyZGNkYzRkKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84MGMzNzIwYjlkOTM0NTAyODgxNjA2OWEzNGQ0NGE2YiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc4OTA1MywgLTc5LjQwODQ5Mjc5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNTBiMTJjIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM1MGIxMmMiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzA3YWZmYmY0ODcwZDQwMjFhMTU4MzZlMjAxYTU0MDUyID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9iYjE2MTAxYzY1Yjc0NzQyYmM1OGI2OWQ4YjEzMWRjNSA9ICQoYDxkaXYgaWQ9Imh0bWxfYmIxNjEwMWM2NWI3NDc0MmJjNThiNjlkOGIxMzFkYzUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldpbGxvd2RhbGUsIE5ld3RvbmJyb29rLCBOb3J0aCBZb3JrPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzA3YWZmYmY0ODcwZDQwMjFhMTU4MzZlMjAxYTU0MDUyLnNldENvbnRlbnQoaHRtbF9iYjE2MTAxYzY1Yjc0NzQyYmM1OGI2OWQ4YjEzMWRjNSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfODBjMzcyMGI5ZDkzNDUwMjg4MTYwNjlhMzRkNDRhNmIuYmluZFBvcHVwKHBvcHVwXzA3YWZmYmY0ODcwZDQwMjFhMTU4MzZlMjAxYTU0MDUyKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl85NzMxMmEzZmI2MzM0N2U2OTVmODc0MzAzZGZiZDY0NSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc3MDExOTksIC03OS40MDg0OTI3OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzUwYjEyYyIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNTBiMTJjIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9jZTRlOWIxNzZkZDM0ZWQxODJhOTZmNDA2NTY2Yzc2OSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfMjIyMDI0N2I4NDYwNDRlZjk3NWU1OWY3ZmU0YzNmY2UgPSAkKGA8ZGl2IGlkPSJodG1sXzIyMjAyNDdiODQ2MDQ0ZWY5NzVlNTlmN2ZlNGMzZmNlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XaWxsb3dkYWxlLCBXaWxsb3dkYWxlIEVhc3QsIE5vcnRoIFlvcms8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfY2U0ZTliMTc2ZGQzNGVkMTgyYTk2ZjQwNjU2NmM3Njkuc2V0Q29udGVudChodG1sXzIyMjAyNDdiODQ2MDQ0ZWY5NzVlNTlmN2ZlNGMzZmNlKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl85NzMxMmEzZmI2MzM0N2U2OTVmODc0MzAzZGZiZDY0NS5iaW5kUG9wdXAocG9wdXBfY2U0ZTliMTc2ZGQzNGVkMTgyYTk2ZjQwNjU2NmM3NjkpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzI0MTg5MzYxZGMzYjRiZWQ4MzNjYzA3MjY1YTYwN2ZhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzUyNzU4Mjk5OTk5OTk2LCAtNzkuNDAwMDQ5M10sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzUwYjEyYyIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNTBiMTJjIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9iNmVhZWE2OTA1ZjU0YjYxYmIxYThhNWI4YWM5OWMxNCA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfNDg0OTY5Nzg5Zjk1NDk1ZTg4OWNiODkzMjNhMmUxM2MgPSAkKGA8ZGl2IGlkPSJodG1sXzQ4NDk2OTc4OWY5NTQ5NWU4ODljYjg5MzIzYTJlMTNjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Zb3JrIE1pbGxzIFdlc3QsIE5vcnRoIFlvcms8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfYjZlYWVhNjkwNWY1NGI2MWJiMWE4YTViOGFjOTljMTQuc2V0Q29udGVudChodG1sXzQ4NDk2OTc4OWY5NTQ5NWU4ODljYjg5MzIzYTJlMTNjKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl8yNDE4OTM2MWRjM2I0YmVkODMzY2MwNzI2NWE2MDdmYS5iaW5kUG9wdXAocG9wdXBfYjZlYWVhNjkwNWY1NGI2MWJiMWE4YTViOGFjOTljMTQpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2FhN2U5YzcxOWY4MDRlMDBhZTYyNzY3NDNkZWU0NjY0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzgyNzM2NCwgLTc5LjQ0MjI1OTNdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM1MGIxMmMiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzUwYjEyYyIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfYmE0NjhiMzM1MGI3NGRkNDk3YjgzMmY3YjhkYjc4YWEgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzM0NDg4Yzc0MjcyZDQxNGNhZDFmODM2OTcyMjRiYTgyID0gJChgPGRpdiBpZD0iaHRtbF8zNDQ4OGM3NDI3MmQ0MTRjYWQxZjgzNjk3MjI0YmE4MiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2lsbG93ZGFsZSwgV2lsbG93ZGFsZSBXZXN0LCBOb3J0aCBZb3JrPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2JhNDY4YjMzNTBiNzRkZDQ5N2I4MzJmN2I4ZGI3OGFhLnNldENvbnRlbnQoaHRtbF8zNDQ4OGM3NDI3MmQ0MTRjYWQxZjgzNjk3MjI0YmE4Mik7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfYWE3ZTljNzE5ZjgwNGUwMGFlNjI3Njc0M2RlZTQ2NjQuYmluZFBvcHVwKHBvcHVwX2JhNDY4YjMzNTBiNzRkZDQ5N2I4MzJmN2I4ZGI3OGFhKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83ODJlZWI2MmI2ZTM0MDk3OGY0M2RlNjE2MDBkYzY2NyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc1MzI1ODYsIC03OS4zMjk2NTY1XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNTBiMTJjIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM1MGIxMmMiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2Y1ZjYzMDk3NmJlMjQ5MzhiN2I0MmRkNDk4YTkxOTQ0ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9mZGMxNDNmYjlkZDg0M2VlYmY3NTg1YjZmMDZjMTA0ZiA9ICQoYDxkaXYgaWQ9Imh0bWxfZmRjMTQzZmI5ZGQ4NDNlZWJmNzU4NWI2ZjA2YzEwNGYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlBhcmt3b29kcywgTm9ydGggWW9yazwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9mNWY2MzA5NzZiZTI0OTM4YjdiNDJkZDQ5OGE5MTk0NC5zZXRDb250ZW50KGh0bWxfZmRjMTQzZmI5ZGQ4NDNlZWJmNzU4NWI2ZjA2YzEwNGYpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzc4MmVlYjYyYjZlMzQwOTc4ZjQzZGU2MTYwMGRjNjY3LmJpbmRQb3B1cChwb3B1cF9mNWY2MzA5NzZiZTI0OTM4YjdiNDJkZDQ5OGE5MTk0NCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDMyNmZhYTJkOTA0NDk2YmJmMzRhMDUwOGRkNzFiNjcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NDU5MDU3OTk5OTk5OTYsIC03OS4zNTIxODhdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM1MGIxMmMiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzUwYjEyYyIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfOTNmMThkNmUxNDMzNDYwM2JkNDExNjI2YjY4ZjcwZWIgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2RiMzBmMTI2NjI3MDRmM2I5YzhjNWFkNjFlM2E4MDU0ID0gJChgPGRpdiBpZD0iaHRtbF9kYjMwZjEyNjYyNzA0ZjNiOWM4YzVhZDYxZTNhODA1NCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RG9uIE1pbGxzLCBOb3J0aCBZb3JrPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzkzZjE4ZDZlMTQzMzQ2MDNiZDQxMTYyNmI2OGY3MGViLnNldENvbnRlbnQoaHRtbF9kYjMwZjEyNjYyNzA0ZjNiOWM4YzVhZDYxZTNhODA1NCk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNDMyNmZhYTJkOTA0NDk2YmJmMzRhMDUwOGRkNzFiNjcuYmluZFBvcHVwKHBvcHVwXzkzZjE4ZDZlMTQzMzQ2MDNiZDQxMTYyNmI2OGY3MGViKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80NDg4M2Y2ZDNiZmU0MGY4YTY5NjhlYmU3MGFhZDc1YyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcyNTg5OTcwMDAwMDAxLCAtNzkuMzQwOTIzXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNTBiMTJjIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM1MGIxMmMiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzExZmZmNTg5OGFiZTQ0MjA5NThjOTU1YmJiYTljMzM2ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF80ZDMyMjE0OTU1OGY0NWUxOGZlY2U2MTVlY2YwMzkwZCA9ICQoYDxkaXYgaWQ9Imh0bWxfNGQzMjIxNDk1NThmNDVlMThmZWNlNjE1ZWNmMDM5MGQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvbiBNaWxscywgTm9ydGggWW9yazwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8xMWZmZjU4OThhYmU0NDIwOTU4Yzk1NWJiYmE5YzMzNi5zZXRDb250ZW50KGh0bWxfNGQzMjIxNDk1NThmNDVlMThmZWNlNjE1ZWNmMDM5MGQpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzQ0ODgzZjZkM2JmZTQwZjhhNjk2OGViZTcwYWFkNzVjLmJpbmRQb3B1cChwb3B1cF8xMWZmZjU4OThhYmU0NDIwOTU4Yzk1NWJiYmE5YzMzNikKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOTQ3NjE0NmRjZTYwNDBkN2IwODE1NDJhNTE2MjdlYWQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NTQzMjgzLCAtNzkuNDQyMjU5M10sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzUwYjEyYyIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNTBiMTJjIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9mNmYzM2Y2MDE3MjY0Mjk1YjJmZjc5OTI1ZDQyYmZiYiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfN2MxYTM0ZWQ4NzU5NDVhNjhiOGM2MzNkM2JmNDZlNGMgPSAkKGA8ZGl2IGlkPSJodG1sXzdjMWEzNGVkODc1OTQ1YTY4YjhjNjMzZDNiZjQ2ZTRjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CYXRodXJzdCBNYW5vciwgV2lsc29uIEhlaWdodHMsIERvd25zdmlldyBOb3J0aCwgTm9ydGggWW9yazwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9mNmYzM2Y2MDE3MjY0Mjk1YjJmZjc5OTI1ZDQyYmZiYi5zZXRDb250ZW50KGh0bWxfN2MxYTM0ZWQ4NzU5NDVhNjhiOGM2MzNkM2JmNDZlNGMpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzk0NzYxNDZkY2U2MDQwZDdiMDgxNTQyYTUxNjI3ZWFkLmJpbmRQb3B1cChwb3B1cF9mNmYzM2Y2MDE3MjY0Mjk1YjJmZjc5OTI1ZDQyYmZiYikKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfY2RiNTExNzI2ZDMwNDQ3OWIxYWQ1OWU1MjgxNmY4NjAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43Njc5ODAzLCAtNzkuNDg3MjYxOTAwMDAwMDFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM1MGIxMmMiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzUwYjEyYyIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMTU0ZDc3NzIxOTQwNGNkMGExY2Q5ZjE1Mzg1MDMzNDUgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzBkNjQwMDNmMmE0MDRhOGZiMDdlMjcyN2VkODA5Yjk0ID0gJChgPGRpdiBpZD0iaHRtbF8wZDY0MDAzZjJhNDA0YThmYjA3ZTI3MjdlZDgwOWI5NCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Tm9ydGh3b29kIFBhcmssIFlvcmsgVW5pdmVyc2l0eSwgTm9ydGggWW9yazwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8xNTRkNzc3MjE5NDA0Y2QwYTFjZDlmMTUzODUwMzM0NS5zZXRDb250ZW50KGh0bWxfMGQ2NDAwM2YyYTQwNGE4ZmIwN2UyNzI3ZWQ4MDliOTQpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2NkYjUxMTcyNmQzMDQ0NzliMWFkNTllNTI4MTZmODYwLmJpbmRQb3B1cChwb3B1cF8xNTRkNzc3MjE5NDA0Y2QwYTFjZDlmMTUzODUwMzM0NSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNjM4NzljNzdiMTZhNDFiMGIyYjFmNjExOWI4ZDY2N2YgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43Mzc0NzMyMDAwMDAwMDQsIC03OS40NjQ3NjMyOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzUwYjEyYyIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNTBiMTJjIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9iMWEzYjgyNjIzNjY0NmU0YjQ1YjVhZGJkYTM5NGU5MSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfYzkzMGMyMWY5ZTA5NGQ3ZDgzODUyMzU2Yjc1OTNhMDUgPSAkKGA8ZGl2IGlkPSJodG1sX2M5MzBjMjFmOWUwOTRkN2Q4Mzg1MjM1NmI3NTkzYTA1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Eb3duc3ZpZXcsIE5vcnRoIFlvcms8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfYjFhM2I4MjYyMzY2NDZlNGI0NWI1YWRiZGEzOTRlOTEuc2V0Q29udGVudChodG1sX2M5MzBjMjFmOWUwOTRkN2Q4Mzg1MjM1NmI3NTkzYTA1KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl82Mzg3OWM3N2IxNmE0MWIwYjJiMWY2MTE5YjhkNjY3Zi5iaW5kUG9wdXAocG9wdXBfYjFhM2I4MjYyMzY2NDZlNGI0NWI1YWRiZGEzOTRlOTEpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzJmODI2ZDNlNjg3MDQyZTU5OTM3ZTY3OTUyMTA4YjU4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzM5MDE0NiwgLTc5LjUwNjk0MzZdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM1MGIxMmMiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzUwYjEyYyIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMWZkZDE3NWJjNmU1NDg0NTkwYzg2YmRjZmNlMGZmYjEgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2Q2OGM1MjA0YjBhMzQ0ZWQ5NTA0NjViOWRkZjAwZmQ0ID0gJChgPGRpdiBpZD0iaHRtbF9kNjhjNTIwNGIwYTM0NGVkOTUwNDY1YjlkZGYwMGZkNCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RG93bnN2aWV3LCBOb3J0aCBZb3JrPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzFmZGQxNzViYzZlNTQ4NDU5MGM4NmJkY2ZjZTBmZmIxLnNldENvbnRlbnQoaHRtbF9kNjhjNTIwNGIwYTM0NGVkOTUwNDY1YjlkZGYwMGZkNCk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMmY4MjZkM2U2ODcwNDJlNTk5MzdlNjc5NTIxMDhiNTguYmluZFBvcHVwKHBvcHVwXzFmZGQxNzViYzZlNTQ4NDU5MGM4NmJkY2ZjZTBmZmIxKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl85OWQxMDAyYTljOTE0ZjdjYjk4MzY1YTlkMWM1MDU4MiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcyODQ5NjQsIC03OS40OTU2OTc0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzUwYjEyYyIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNTBiMTJjIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF85MmY4YTZjYjBiODc0MzU1ODMzZDE0ODZmMTRkMmJmNCA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfYTA4ZGViNzA1NGJlNDM0MmE5ZDEzZjlmZTgyN2IxOWIgPSAkKGA8ZGl2IGlkPSJodG1sX2EwOGRlYjcwNTRiZTQzNDJhOWQxM2Y5ZmU4MjdiMTliIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Eb3duc3ZpZXcsIE5vcnRoIFlvcms8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfOTJmOGE2Y2IwYjg3NDM1NTgzM2QxNDg2ZjE0ZDJiZjQuc2V0Q29udGVudChodG1sX2EwOGRlYjcwNTRiZTQzNDJhOWQxM2Y5ZmU4MjdiMTliKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl85OWQxMDAyYTljOTE0ZjdjYjk4MzY1YTlkMWM1MDU4Mi5iaW5kUG9wdXAocG9wdXBfOTJmOGE2Y2IwYjg3NDM1NTgzM2QxNDg2ZjE0ZDJiZjQpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2U0ODI0YTU1NWU1NTQ2YjVhMTU1YTUwYjg3MTY2NzcwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzYxNjMxMywgLTc5LjUyMDk5OTQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNTBiMTJjIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM1MGIxMmMiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2Q5MzQ5Njg5NmE0ZDQ1NDE4ZjkzN2VmMzBjN2ZlNzk5ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF84MGNlZTVkYzc2NmY0MjkxYWUwZGRkNTdjMTBjYzE0YiA9ICQoYDxkaXYgaWQ9Imh0bWxfODBjZWU1ZGM3NjZmNDI5MWFlMGRkZDU3YzEwY2MxNGIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvd25zdmlldywgTm9ydGggWW9yazwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9kOTM0OTY4OTZhNGQ0NTQxOGY5MzdlZjMwYzdmZTc5OS5zZXRDb250ZW50KGh0bWxfODBjZWU1ZGM3NjZmNDI5MWFlMGRkZDU3YzEwY2MxNGIpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2U0ODI0YTU1NWU1NTQ2YjVhMTU1YTUwYjg3MTY2NzcwLmJpbmRQb3B1cChwb3B1cF9kOTM0OTY4OTZhNGQ0NTQxOGY5MzdlZjMwYzdmZTc5OSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZDliMmU5N2VmNmI4NDFiYTgzMzI0ODNmOWM5NDA4NjUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MjU4ODIyOTk5OTk5OTUsIC03OS4zMTU1NzE1OTk5OTk5OF0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzUwYjEyYyIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNTBiMTJjIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF82Njc0ODNiODJhZjI0OTJiOTA2OWIyNDRmODA0OGYxZCA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfMjYzOTM1NTE4NjI3NDRkNjk0MDI2YTRmOTc4NTgwZTcgPSAkKGA8ZGl2IGlkPSJodG1sXzI2MzkzNTUxODYyNzQ0ZDY5NDAyNmE0Zjk3ODU4MGU3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5WaWN0b3JpYSBWaWxsYWdlLCBOb3J0aCBZb3JrPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzY2NzQ4M2I4MmFmMjQ5MmI5MDY5YjI0NGY4MDQ4ZjFkLnNldENvbnRlbnQoaHRtbF8yNjM5MzU1MTg2Mjc0NGQ2OTQwMjZhNGY5Nzg1ODBlNyk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfZDliMmU5N2VmNmI4NDFiYTgzMzI0ODNmOWM5NDA4NjUuYmluZFBvcHVwKHBvcHVwXzY2NzQ4M2I4MmFmMjQ5MmI5MDY5YjI0NGY4MDQ4ZjFkKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kYzk2NzJmNDQxMjM0ZjA4OTk4ZDUxZTY4NmEwZDMxMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcwNjM5NzIsIC03OS4zMDk5MzddLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM5M2M2NzkiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzkzYzY3OSIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfNzI2YTRhYzY1YzIxNGUxYTg3ZGFiYzM5OWIzNTBhMTAgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2Q4ZDU4NDNkNjE3YTRkNzM5ZDQ1MjAzN2MwNGZjZTE0ID0gJChgPGRpdiBpZD0iaHRtbF9kOGQ1ODQzZDYxN2E0ZDczOWQ0NTIwMzdjMDRmY2UxNCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UGFya3ZpZXcgSGlsbCwgV29vZGJpbmUgR2FyZGVucywgRWFzdCBZb3JrPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzcyNmE0YWM2NWMyMTRlMWE4N2RhYmMzOTliMzUwYTEwLnNldENvbnRlbnQoaHRtbF9kOGQ1ODQzZDYxN2E0ZDczOWQ0NTIwMzdjMDRmY2UxNCk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfZGM5NjcyZjQ0MTIzNGYwODk5OGQ1MWU2ODZhMGQzMTIuYmluZFBvcHVwKHBvcHVwXzcyNmE0YWM2NWMyMTRlMWE4N2RhYmMzOTliMzUwYTEwKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yMzIwODA1NTVlYWQ0NGVhYTQ0MzZmZjNjNzc0NWNjNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY5NTM0MzkwMDAwMDAwNSwgLTc5LjMxODM4ODddLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM5M2M2NzkiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzkzYzY3OSIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfYmM4Y2NmOWU5OGE3NGJkODkyNzFjOWJlOWQzNjA2NDggPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzdiNDczZjY4NTFiMzRkM2NhYzQ4MzNjZDhjNTFhYWI5ID0gJChgPGRpdiBpZD0iaHRtbF83YjQ3M2Y2ODUxYjM0ZDNjYWM0ODMzY2Q4YzUxYWFiOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V29vZGJpbmUgSGVpZ2h0cywgRWFzdCBZb3JrPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2JjOGNjZjllOThhNzRiZDg5MjcxYzliZTlkMzYwNjQ4LnNldENvbnRlbnQoaHRtbF83YjQ3M2Y2ODUxYjM0ZDNjYWM0ODMzY2Q4YzUxYWFiOSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMjMyMDgwNTU1ZWFkNDRlYWE0NDM2ZmYzYzc3NDVjYzcuYmluZFBvcHVwKHBvcHVwX2JjOGNjZjllOThhNzRiZDg5MjcxYzliZTlkMzYwNjQ4KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82MmQxMzVjNTg2YWI0ODU1OGI5NjVlZTY0NTJiODk4YyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY3NjM1NzM5OTk5OTk5LCAtNzkuMjkzMDMxMl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzg2NDkzMyIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODY0OTMzIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF8zZmE4YzNmNTJiNzM0NWMwYjdiYWVlZDZkZmEwMTlmYyA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfODdkYjVmNjVlYjYwNDZhYmE3NjAxMmM1ZWQ3MTljOTUgPSAkKGA8ZGl2IGlkPSJodG1sXzg3ZGI1ZjY1ZWI2MDQ2YWJhNzYwMTJjNWVkNzE5Yzk1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UaGUgQmVhY2hlcywgRWFzdCBUb3JvbnRvPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzNmYThjM2Y1MmI3MzQ1YzBiN2JhZWVkNmRmYTAxOWZjLnNldENvbnRlbnQoaHRtbF84N2RiNWY2NWViNjA0NmFiYTc2MDEyYzVlZDcxOWM5NSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNjJkMTM1YzU4NmFiNDg1NThiOTY1ZWU2NDUyYjg5OGMuYmluZFBvcHVwKHBvcHVwXzNmYThjM2Y1MmI3MzQ1YzBiN2JhZWVkNmRmYTAxOWZjKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81MmNhNzc3YmNhMzc0Yjc4YTRlMDkzMDIyOTAzODU1MSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcwOTA2MDQsIC03OS4zNjM0NTE3XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjOTNjNjc5IiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM5M2M2NzkiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzFhMzNmMzcyNmRlMzRhMDFhMDQzZWQzYmU2Mzg0MGIwID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF8yZTE3OTYwOTVlYjY0MGQxYjM5NmNjYjdmODFmNDI1ZSA9ICQoYDxkaXYgaWQ9Imh0bWxfMmUxNzk2MDk1ZWI2NDBkMWIzOTZjY2I3ZjgxZjQyNWUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxlYXNpZGUsIEVhc3QgWW9yazwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8xYTMzZjM3MjZkZTM0YTAxYTA0M2VkM2JlNjM4NDBiMC5zZXRDb250ZW50KGh0bWxfMmUxNzk2MDk1ZWI2NDBkMWIzOTZjY2I3ZjgxZjQyNWUpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzUyY2E3NzdiY2EzNzRiNzhhNGUwOTMwMjI5MDM4NTUxLmJpbmRQb3B1cChwb3B1cF8xYTMzZjM3MjZkZTM0YTAxYTA0M2VkM2JlNjM4NDBiMCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZTc5ZTVjYjE1N2EwNGU2ZTk4NTViNzcyYTkzMjFkNmEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MDUzNjg5LCAtNzkuMzQ5MzcxOTAwMDAwMDFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM5M2M2NzkiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzkzYzY3OSIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMWE5ZWIxZjQxYmI0NDhkNGJlNGI3MWM5YzZlMTVjOWQgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzJlN2UyYzQyYmY4MDQ2ZjY5NDIwYWQwOGE4OTY0YmRjID0gJChgPGRpdiBpZD0iaHRtbF8yZTdlMmM0MmJmODA0NmY2OTQyMGFkMDhhODk2NGJkYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VGhvcm5jbGlmZmUgUGFyaywgRWFzdCBZb3JrPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzFhOWViMWY0MWJiNDQ4ZDRiZTRiNzFjOWM2ZTE1YzlkLnNldENvbnRlbnQoaHRtbF8yZTdlMmM0MmJmODA0NmY2OTQyMGFkMDhhODk2NGJkYyk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfZTc5ZTVjYjE1N2EwNGU2ZTk4NTViNzcyYTkzMjFkNmEuYmluZFBvcHVwKHBvcHVwXzFhOWViMWY0MWJiNDQ4ZDRiZTRiNzFjOWM2ZTE1YzlkKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kYmM2Yzk3MTNkMzk0ZDM2ODMzM2RlNjY2YWVjMGZhZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY4NTM0NywgLTc5LjMzODEwNjVdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM5M2M2NzkiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzkzYzY3OSIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfNGNhNTczOGUzOTI0NGJiMWJlNmE3OWIwOWQzZWY0NDEgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2NlYmIyNWRlZTlmYTRlMGViZmZhMWNmMzNkMjgxZGU2ID0gJChgPGRpdiBpZD0iaHRtbF9jZWJiMjVkZWU5ZmE0ZTBlYmZmYTFjZjMzZDI4MWRlNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RWFzdCBUb3JvbnRvLCBCcm9hZHZpZXcgTm9ydGggKE9sZCBFYXN0IFlvcmspLCBFYXN0IFlvcms8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfNGNhNTczOGUzOTI0NGJiMWJlNmE3OWIwOWQzZWY0NDEuc2V0Q29udGVudChodG1sX2NlYmIyNWRlZTlmYTRlMGViZmZhMWNmMzNkMjgxZGU2KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9kYmM2Yzk3MTNkMzk0ZDM2ODMzM2RlNjY2YWVjMGZhZC5iaW5kUG9wdXAocG9wdXBfNGNhNTczOGUzOTI0NGJiMWJlNmE3OWIwOWQzZWY0NDEpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzljMmRlOWQyNmRjZDRiMzViYmQ1OTg5YjUzYTY4NzIzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjc5NTU3MSwgLTc5LjM1MjE4OF0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzg2NDkzMyIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODY0OTMzIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF83MWUwYzUzM2MxYmI0YzM5YjMwMDYxYTE4ZjNmOTFhZiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfZDU3NTcyOWEyMGZlNDY3ZmExYTliYzA5MzM4NmU3ZDMgPSAkKGA8ZGl2IGlkPSJodG1sX2Q1NzU3MjlhMjBmZTQ2N2ZhMWE5YmMwOTMzODZlN2QzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UaGUgRGFuZm9ydGggV2VzdCwgUml2ZXJkYWxlLCBFYXN0IFRvcm9udG88L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfNzFlMGM1MzNjMWJiNGMzOWIzMDA2MWExOGYzZjkxYWYuc2V0Q29udGVudChodG1sX2Q1NzU3MjlhMjBmZTQ2N2ZhMWE5YmMwOTMzODZlN2QzKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl85YzJkZTlkMjZkY2Q0YjM1YmJkNTk4OWI1M2E2ODcyMy5iaW5kUG9wdXAocG9wdXBfNzFlMGM1MzNjMWJiNGMzOWIzMDA2MWExOGYzZjkxYWYpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzA4YTNjZTI4MjY2NjQ0OGE4YTVkMzQ5NTRjZTQ5MTFlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjY4OTk4NSwgLTc5LjMxNTU3MTU5OTk5OTk4XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODY0OTMzIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4NjQ5MzMiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2U0Y2I4NGZiNDk1NzQ2M2M5ZDhjZjIyYjk3YWI0OTg2ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF8zMzc0YjE0MTBjNTU0OTNhODY3N2E4MDZhMjJlNTIwMSA9ICQoYDxkaXYgaWQ9Imh0bWxfMzM3NGIxNDEwYzU1NDkzYTg2NzdhODA2YTIyZTUyMDEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkluZGlhIEJhemFhciwgVGhlIEJlYWNoZXMgV2VzdCwgRWFzdCBUb3JvbnRvPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2U0Y2I4NGZiNDk1NzQ2M2M5ZDhjZjIyYjk3YWI0OTg2LnNldENvbnRlbnQoaHRtbF8zMzc0YjE0MTBjNTU0OTNhODY3N2E4MDZhMjJlNTIwMSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMDhhM2NlMjgyNjY2NDQ4YThhNWQzNDk1NGNlNDkxMWUuYmluZFBvcHVwKHBvcHVwX2U0Y2I4NGZiNDk1NzQ2M2M5ZDhjZjIyYjk3YWI0OTg2KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jZmFhYWRkNTQ1YTE0Y2VkYmQ2MDU2NjU0ZTdjMWI2NiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1OTUyNTUsIC03OS4zNDA5MjNdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4NjQ5MzMiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzg2NDkzMyIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfOTVhMTRlMGVhYzE4NDlkMTllN2UxZGI5OGQ5NjA3ZTggPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzIxMTBlYTA4YzRmODQ2ZGViMmVjMjI5OGJhM2EzOTEyID0gJChgPGRpdiBpZD0iaHRtbF8yMTEwZWEwOGM0Zjg0NmRlYjJlYzIyOThiYTNhMzkxMiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3R1ZGlvIERpc3RyaWN0LCBFYXN0IFRvcm9udG88L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfOTVhMTRlMGVhYzE4NDlkMTllN2UxZGI5OGQ5NjA3ZTguc2V0Q29udGVudChodG1sXzIxMTBlYTA4YzRmODQ2ZGViMmVjMjI5OGJhM2EzOTEyKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9jZmFhYWRkNTQ1YTE0Y2VkYmQ2MDU2NjU0ZTdjMWI2Ni5iaW5kUG9wdXAocG9wdXBfOTVhMTRlMGVhYzE4NDlkMTllN2UxZGI5OGQ5NjA3ZTgpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQwOThmN2Q3YjZlMzQ3NjE4N2NhMDEzZmM3MzliNjI3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzI4MDIwNSwgLTc5LjM4ODc5MDFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM0OTViOTIiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzQ5NWI5MiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfZDFhOGMzYjljMWJiNGRlOGIyNWZiODkzMDJkYTYxN2IgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzdjYzJhMDY5NzEwNTRhMTBiNzI0ZWYzMDU0OWNmNDljID0gJChgPGRpdiBpZD0iaHRtbF83Y2MyYTA2OTcxMDU0YTEwYjcyNGVmMzA1NDljZjQ5YyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TGF3cmVuY2UgUGFyaywgQ2VudHJhbCBUb3JvbnRvPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2QxYThjM2I5YzFiYjRkZThiMjVmYjg5MzAyZGE2MTdiLnNldENvbnRlbnQoaHRtbF83Y2MyYTA2OTcxMDU0YTEwYjcyNGVmMzA1NDljZjQ5Yyk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNDA5OGY3ZDdiNmUzNDc2MTg3Y2EwMTNmYzczOWI2MjcuYmluZFBvcHVwKHBvcHVwX2QxYThjM2I5YzFiYjRkZThiMjVmYjg5MzAyZGE2MTdiKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81YmNiMjM5OGIxYTc0MWNmODJkOThhMTI5MzZjNTdhMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcxMjc1MTEsIC03OS4zOTAxOTc1XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNDk1YjkyIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM0OTViOTIiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzcxOGQ2NmM0NDYxOTRlYTA4MzZlZTc2NmUxZGMzNTVjID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF84NWE0MDdmOTU5MTA0OTAxYmFmOGEzNDc5MzgxNDRlNCA9ICQoYDxkaXYgaWQ9Imh0bWxfODVhNDA3Zjk1OTEwNDkwMWJhZjhhMzQ3OTM4MTQ0ZTQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRhdmlzdmlsbGUgTm9ydGgsIENlbnRyYWwgVG9yb250bzwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF83MThkNjZjNDQ2MTk0ZWEwODM2ZWU3NjZlMWRjMzU1Yy5zZXRDb250ZW50KGh0bWxfODVhNDA3Zjk1OTEwNDkwMWJhZjhhMzQ3OTM4MTQ0ZTQpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzViY2IyMzk4YjFhNzQxY2Y4MmQ5OGExMjkzNmM1N2EyLmJpbmRQb3B1cChwb3B1cF83MThkNjZjNDQ2MTk0ZWEwODM2ZWU3NjZlMWRjMzU1YykKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYWMzMzdiMzc2MDIwNGUyODk1M2EzMzU3MWQ2MGFlZWEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MTUzODM0LCAtNzkuNDA1Njc4NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM0OTViOTIiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzQ5NWI5MiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfNjIzZDE2MWE3MWFkNGRkMGFhOGJmMjFkNjE5NDQzMTQgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzI4MjQxYzg0NTEwNjQxZDU5MTQzNWQ1MDZiNTI3MDBiID0gJChgPGRpdiBpZD0iaHRtbF8yODI0MWM4NDUxMDY0MWQ1OTE0MzVkNTA2YjUyNzAwYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Tm9ydGggVG9yb250byBXZXN0LCBMYXdyZW5jZSBQYXJrLCBDZW50cmFsIFRvcm9udG88L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfNjIzZDE2MWE3MWFkNGRkMGFhOGJmMjFkNjE5NDQzMTQuc2V0Q29udGVudChodG1sXzI4MjQxYzg0NTEwNjQxZDU5MTQzNWQ1MDZiNTI3MDBiKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9hYzMzN2IzNzYwMjA0ZTI4OTUzYTMzNTcxZDYwYWVlYS5iaW5kUG9wdXAocG9wdXBfNjIzZDE2MWE3MWFkNGRkMGFhOGJmMjFkNjE5NDQzMTQpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y3MTUxZjZjMzE5ZTQwZDk5YzkxZDc1ZTUyZGM3YzQyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzA0MzI0NCwgLTc5LjM4ODc5MDFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM0OTViOTIiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzQ5NWI5MiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfM2VjMGM3YTBkZmFmNGViZDkxMzc4Y2NjMmE5MTQ3MDIgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzU4MWFhNmM3MjgzODQ0MWNhYmFkNDIyMDgyMThjYmNiID0gJChgPGRpdiBpZD0iaHRtbF81ODFhYTZjNzI4Mzg0NDFjYWJhZDQyMjA4MjE4Y2JjYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RGF2aXN2aWxsZSwgQ2VudHJhbCBUb3JvbnRvPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzNlYzBjN2EwZGZhZjRlYmQ5MTM3OGNjYzJhOTE0NzAyLnNldENvbnRlbnQoaHRtbF81ODFhYTZjNzI4Mzg0NDFjYWJhZDQyMjA4MjE4Y2JjYik7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfZjcxNTFmNmMzMTllNDBkOTljOTFkNzVlNTJkYzdjNDIuYmluZFBvcHVwKHBvcHVwXzNlYzBjN2EwZGZhZjRlYmQ5MTM3OGNjYzJhOTE0NzAyKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83ZTkyMDI4NGFmODg0MzFiYWMyOWI0NDU1Y2VmZTVmNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY4OTU3NDMsIC03OS4zODMxNTk5MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzQ5NWI5MiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNDk1YjkyIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF8wYjA1OWNiZGRiNDI0NTM5YmMzOWU1YzhkYzRiN2FkZSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfN2NkMmI2YjRmN2I1NGVkMmIxMTBmZjE3MjVjNTI2YzcgPSAkKGA8ZGl2IGlkPSJodG1sXzdjZDJiNmI0ZjdiNTRlZDJiMTEwZmYxNzI1YzUyNmM3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Nb29yZSBQYXJrLCBTdW1tZXJoaWxsIEVhc3QsIENlbnRyYWwgVG9yb250bzwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8wYjA1OWNiZGRiNDI0NTM5YmMzOWU1YzhkYzRiN2FkZS5zZXRDb250ZW50KGh0bWxfN2NkMmI2YjRmN2I1NGVkMmIxMTBmZjE3MjVjNTI2YzcpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzdlOTIwMjg0YWY4ODQzMWJhYzI5YjQ0NTVjZWZlNWY3LmJpbmRQb3B1cChwb3B1cF8wYjA1OWNiZGRiNDI0NTM5YmMzOWU1YzhkYzRiN2FkZSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMTkwOTE4OWQ2YmVlNDIwYTg0NjBlZjlhNWZiNmYwZmMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42ODY0MTIyOTk5OTk5OSwgLTc5LjQwMDA0OTNdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM0OTViOTIiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzQ5NWI5MiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfZmEwN2JjNmJmZjNkNDkyMDg5MTlmMjk3YjllYmUxYWUgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2M3MjNlNmNmZjE0YTRkZTFiMmViMDcxN2Y0NjZjZGNjID0gJChgPGRpdiBpZD0iaHRtbF9jNzIzZTZjZmYxNGE0ZGUxYjJlYjA3MTdmNDY2Y2RjYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3VtbWVyaGlsbCBXZXN0LCBSYXRobmVsbHksIFNvdXRoIEhpbGwsIEZvcmVzdCBIaWxsIFNFLCBEZWVyIFBhcmssIENlbnRyYWwgVG9yb250bzwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9mYTA3YmM2YmZmM2Q0OTIwODkxOWYyOTdiOWViZTFhZS5zZXRDb250ZW50KGh0bWxfYzcyM2U2Y2ZmMTRhNGRlMWIyZWIwNzE3ZjQ2NmNkY2MpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzE5MDkxODlkNmJlZTQyMGE4NDYwZWY5YTVmYjZmMGZjLmJpbmRQb3B1cChwb3B1cF9mYTA3YmM2YmZmM2Q0OTIwODkxOWYyOTdiOWViZTFhZSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYTI5ZDNhZWRhOTdmNGIzZGFhZDA3MTVjNTZhODE4M2IgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Nzk1NjI2LCAtNzkuMzc3NTI5NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM3YTdkYTEiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzdhN2RhMSIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMmM2MTg1OWM0ZDljNDFlNzgzN2I1MThmOWUyODZhZjEgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2Y1ZjJmMmQ1OTc3ZTRmYjhiOWJkNmM4YTMwNTI2ZjYxID0gJChgPGRpdiBpZD0iaHRtbF9mNWYyZjJkNTk3N2U0ZmI4YjliZDZjOGEzMDUyNmY2MSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Um9zZWRhbGUsIERvd250b3duIFRvcm9udG88L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfMmM2MTg1OWM0ZDljNDFlNzgzN2I1MThmOWUyODZhZjEuc2V0Q29udGVudChodG1sX2Y1ZjJmMmQ1OTc3ZTRmYjhiOWJkNmM4YTMwNTI2ZjYxKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9hMjlkM2FlZGE5N2Y0YjNkYWFkMDcxNWM1NmE4MTgzYi5iaW5kUG9wdXAocG9wdXBfMmM2MTg1OWM0ZDljNDFlNzgzN2I1MThmOWUyODZhZjEpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzkyZGFlNjcyMmY3MTQ3OGQ4OGZlMTlkNzQ3YzlkNDNhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjY3OTY3LCAtNzkuMzY3Njc1M10sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzdhN2RhMSIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjN2E3ZGExIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF84OGYzODgwYzVlYWI0M2Y4YTlmOTExMDhkMGZjYzgxZiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfNGEyMGNiOTk3ODE3NDU0NmEwNzE0MTEwMmUxM2MyMzQgPSAkKGA8ZGl2IGlkPSJodG1sXzRhMjBjYjk5NzgxNzQ1NDZhMDcxNDExMDJlMTNjMjM0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TdC4gSmFtZXMgVG93biwgQ2FiYmFnZXRvd24sIERvd250b3duIFRvcm9udG88L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfODhmMzg4MGM1ZWFiNDNmOGE5ZjkxMTA4ZDBmY2M4MWYuc2V0Q29udGVudChodG1sXzRhMjBjYjk5NzgxNzQ1NDZhMDcxNDExMDJlMTNjMjM0KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl85MmRhZTY3MjJmNzE0NzhkODhmZTE5ZDc0N2M5ZDQzYS5iaW5kUG9wdXAocG9wdXBfODhmMzg4MGM1ZWFiNDNmOGE5ZjkxMTA4ZDBmY2M4MWYpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzYxN2QzZWViZWY5MTRmYTFiYzYyODhhNTk3ODk0NzAyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjY1ODU5OSwgLTc5LjM4MzE1OTkwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjN2E3ZGExIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM3YTdkYTEiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2EwZTRjZjgyMDFiMzQwNmZhNDgyYjc2ODhmMWJmYTJjID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF8yM2YyNzQ0M2MyNTc0NjgxODJiMmUyYTMwMmM4M2MyNyA9ICQoYDxkaXYgaWQ9Imh0bWxfMjNmMjc0NDNjMjU3NDY4MTgyYjJlMmEzMDJjODNjMjciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNodXJjaCBhbmQgV2VsbGVzbGV5LCBEb3dudG93biBUb3JvbnRvPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2EwZTRjZjgyMDFiMzQwNmZhNDgyYjc2ODhmMWJmYTJjLnNldENvbnRlbnQoaHRtbF8yM2YyNzQ0M2MyNTc0NjgxODJiMmUyYTMwMmM4M2MyNyk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNjE3ZDNlZWJlZjkxNGZhMWJjNjI4OGE1OTc4OTQ3MDIuYmluZFBvcHVwKHBvcHVwX2EwZTRjZjgyMDFiMzQwNmZhNDgyYjc2ODhmMWJmYTJjKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kNTE0NGM5YjJiMzE0YzU4ODYzNmZmNGJkMWNhMTM3ZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1NDI1OTksIC03OS4zNjA2MzU5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjN2E3ZGExIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM3YTdkYTEiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2Q1MGExMWMzMmI2ZTRjOGI4MDEyYmFjMjE5MDExNTNkID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF8yMTQ0NWQwYmYxOGE0YjIwOWFlODQxNDk0MTcwNWMwMyA9ICQoYDxkaXYgaWQ9Imh0bWxfMjE0NDVkMGJmMThhNGIyMDlhZTg0MTQ5NDE3MDVjMDMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJlZ2VudCBQYXJrLCBIYXJib3VyZnJvbnQsIERvd250b3duIFRvcm9udG88L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfZDUwYTExYzMyYjZlNGM4YjgwMTJiYWMyMTkwMTE1M2Quc2V0Q29udGVudChodG1sXzIxNDQ1ZDBiZjE4YTRiMjA5YWU4NDE0OTQxNzA1YzAzKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9kNTE0NGM5YjJiMzE0YzU4ODYzNmZmNGJkMWNhMTM3ZC5iaW5kUG9wdXAocG9wdXBfZDUwYTExYzMyYjZlNGM4YjgwMTJiYWMyMTkwMTE1M2QpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzdkNGE0MTNiZTYyYjQzZmE4MDkzNzVhNmE2Y2ZjMDFlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjU3MTYxOCwgLTc5LjM3ODkzNzA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjN2E3ZGExIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM3YTdkYTEiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzc3YmJiODQxMzBlYjRlODJhMmFlYjIyNjM4YTA5ZGQyID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF83NzE5ODk1NDAxNzQ0M2U3YWFjY2U4ZjI5NzM1ODQxOSA9ICQoYDxkaXYgaWQ9Imh0bWxfNzcxOTg5NTQwMTc0NDNlN2FhY2NlOGYyOTczNTg0MTkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkdhcmRlbiBEaXN0cmljdCwgUnllcnNvbiwgRG93bnRvd24gVG9yb250bzwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF83N2JiYjg0MTMwZWI0ZTgyYTJhZWIyMjYzOGEwOWRkMi5zZXRDb250ZW50KGh0bWxfNzcxOTg5NTQwMTc0NDNlN2FhY2NlOGYyOTczNTg0MTkpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzdkNGE0MTNiZTYyYjQzZmE4MDkzNzVhNmE2Y2ZjMDFlLmJpbmRQb3B1cChwb3B1cF83N2JiYjg0MTMwZWI0ZTgyYTJhZWIyMjYzOGEwOWRkMikKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOWJiMmMyYjcwYzQzNDRhODkyNjI3NGJjN2ZlYzZjZGUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NTE0OTM5LCAtNzkuMzc1NDE3OV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzdhN2RhMSIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjN2E3ZGExIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF85ZTAwYzMxZjdjZjg0ODEyOWNlNWM5NTQ1Yjg0Yzg5MSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfN2VlNTgyOGJmMDQ2NGYzZDk0YTI2ZDI4NTM0MDBiNzEgPSAkKGA8ZGl2IGlkPSJodG1sXzdlZTU4MjhiZjA0NjRmM2Q5NGEyNmQyODUzNDAwYjcxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TdC4gSmFtZXMgVG93biwgRG93bnRvd24gVG9yb250bzwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF85ZTAwYzMxZjdjZjg0ODEyOWNlNWM5NTQ1Yjg0Yzg5MS5zZXRDb250ZW50KGh0bWxfN2VlNTgyOGJmMDQ2NGYzZDk0YTI2ZDI4NTM0MDBiNzEpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzliYjJjMmI3MGM0MzQ0YTg5MjYyNzRiYzdmZWM2Y2RlLmJpbmRQb3B1cChwb3B1cF85ZTAwYzMxZjdjZjg0ODEyOWNlNWM5NTQ1Yjg0Yzg5MSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMmQ3ZTUxY2U2OTEyNGRmNmIyMGQzOTdlYTc1NjBkYjMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDQ3NzA3OTk5OTk5OTYsIC03OS4zNzMzMDY0XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjN2E3ZGExIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM3YTdkYTEiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzM0MjRkY2U1ODU2YTRmNTc5N2IyOTU1Y2I0ZWRkY2QyID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9mMGIzMTBkZWRlMmE0ZWQyYmY2NTEwYzRkYTBlNjJjMiA9ICQoYDxkaXYgaWQ9Imh0bWxfZjBiMzEwZGVkZTJhNGVkMmJmNjUxMGM0ZGEwZTYyYzIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJlcmN6eSBQYXJrLCBEb3dudG93biBUb3JvbnRvPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzM0MjRkY2U1ODU2YTRmNTc5N2IyOTU1Y2I0ZWRkY2QyLnNldENvbnRlbnQoaHRtbF9mMGIzMTBkZWRlMmE0ZWQyYmY2NTEwYzRkYTBlNjJjMik7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMmQ3ZTUxY2U2OTEyNGRmNmIyMGQzOTdlYTc1NjBkYjMuYmluZFBvcHVwKHBvcHVwXzM0MjRkY2U1ODU2YTRmNTc5N2IyOTU1Y2I0ZWRkY2QyKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xZjkzODBkY2UyYWY0MjNjYWMxZDA3NDEyMmM2OTdkOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1Nzk1MjQsIC03OS4zODczODI2XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjN2E3ZGExIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM3YTdkYTEiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzlhM2E3NWUzZWNjMjQ5YjliNzFhODAwNjBjOTBkYTJjID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9iZTJlM2NhOGQ5YmQ0M2ZmODIyMGFhNzQwNmNkNDFlYiA9ICQoYDxkaXYgaWQ9Imh0bWxfYmUyZTNjYThkOWJkNDNmZjgyMjBhYTc0MDZjZDQxZWIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNlbnRyYWwgQmF5IFN0cmVldCwgRG93bnRvd24gVG9yb250bzwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF85YTNhNzVlM2VjYzI0OWI5YjcxYTgwMDYwYzkwZGEyYy5zZXRDb250ZW50KGh0bWxfYmUyZTNjYThkOWJkNDNmZjgyMjBhYTc0MDZjZDQxZWIpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzFmOTM4MGRjZTJhZjQyM2NhYzFkMDc0MTIyYzY5N2Q4LmJpbmRQb3B1cChwb3B1cF85YTNhNzVlM2VjYzI0OWI5YjcxYTgwMDYwYzkwZGEyYykKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMjY3N2M3M2M0NTI1NDRlNThkZTcyYjA1YWM2ZmQxNWMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NTA1NzEyMDAwMDAwMSwgLTc5LjM4NDU2NzVdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM3YTdkYTEiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzdhN2RhMSIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfYjc0MDJjZGUwOWM2NDUzYTk3ZDQxYTQyMGVjYmM5ZTcgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2Q0M2U1NjdmMzU4ZjQ2NDc4NDhmZDUxODI3ODE2ZjVlID0gJChgPGRpdiBpZD0iaHRtbF9kNDNlNTY3ZjM1OGY0NjQ3ODQ4ZmQ1MTgyNzgxNmY1ZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UmljaG1vbmQsIEFkZWxhaWRlLCBLaW5nLCBEb3dudG93biBUb3JvbnRvPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2I3NDAyY2RlMDljNjQ1M2E5N2Q0MWE0MjBlY2JjOWU3LnNldENvbnRlbnQoaHRtbF9kNDNlNTY3ZjM1OGY0NjQ3ODQ4ZmQ1MTgyNzgxNmY1ZSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMjY3N2M3M2M0NTI1NDRlNThkZTcyYjA1YWM2ZmQxNWMuYmluZFBvcHVwKHBvcHVwX2I3NDAyY2RlMDljNjQ1M2E5N2Q0MWE0MjBlY2JjOWU3KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hNGViYzQyMjNjMzA0OWViOTBjNDBmYWE5N2Q4YzQ2MyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY0MDgxNTcsIC03OS4zODE3NTIyOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzdhN2RhMSIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjN2E3ZGExIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9hYjM1MTRhNmUwNTQ0YTg4OGIzNmUzNWI3NTQ4MWQzZiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfMTBlZjE0ODU3NmRhNDRiMWEyYWRlZmZiOWRlMTA2MjMgPSAkKGA8ZGl2IGlkPSJodG1sXzEwZWYxNDg1NzZkYTQ0YjFhMmFkZWZmYjlkZTEwNjIzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IYXJib3VyZnJvbnQgRWFzdCwgVW5pb24gU3RhdGlvbiwgVG9yb250byBJc2xhbmRzLCBEb3dudG93biBUb3JvbnRvPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2FiMzUxNGE2ZTA1NDRhODg4YjM2ZTM1Yjc1NDgxZDNmLnNldENvbnRlbnQoaHRtbF8xMGVmMTQ4NTc2ZGE0NGIxYTJhZGVmZmI5ZGUxMDYyMyk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfYTRlYmM0MjIzYzMwNDllYjkwYzQwZmFhOTdkOGM0NjMuYmluZFBvcHVwKHBvcHVwX2FiMzUxNGE2ZTA1NDRhODg4YjM2ZTM1Yjc1NDgxZDNmKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kMWU2YmQzYzI2NjA0MjU3ODgyZmUwYzkzMGEwYmYxOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY0NzE3NjgsIC03OS4zODE1NzY0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzdhN2RhMSIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjN2E3ZGExIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9hZTU3M2U1MzNmYzQ0Y2MwYTBhMThiOWZkYjJjZWI1OSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfNWE4OGZlMzNjYmMzNDIyMmI4MDBmMjY5YzI5YzFlYzQgPSAkKGA8ZGl2IGlkPSJodG1sXzVhODhmZTMzY2JjMzQyMjJiODAwZjI2OWMyOWMxZWM0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ub3JvbnRvIERvbWluaW9uIENlbnRyZSwgRGVzaWduIEV4Y2hhbmdlLCBEb3dudG93biBUb3JvbnRvPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2FlNTczZTUzM2ZjNDRjYzBhMGExOGI5ZmRiMmNlYjU5LnNldENvbnRlbnQoaHRtbF81YTg4ZmUzM2NiYzM0MjIyYjgwMGYyNjljMjljMWVjNCk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfZDFlNmJkM2MyNjYwNDI1Nzg4MmZlMGM5MzBhMGJmMTguYmluZFBvcHVwKHBvcHVwX2FlNTczZTUzM2ZjNDRjYzBhMGExOGI5ZmRiMmNlYjU5KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83NjZkNGUzMzlhMzA0ODhkYmFjMzEzNzFjODQ2NTA2YyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY0ODE5ODUsIC03OS4zNzk4MTY5MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzdhN2RhMSIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjN2E3ZGExIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF83ZTEwODE2ZDRjZDg0MjUzYTliMDU0YzI4YzdlOGQzNCA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfMWE3YTA0MzhlYzZiNGJiOWE2ZDc0ZTlhZmYxMTg2Y2IgPSAkKGA8ZGl2IGlkPSJodG1sXzFhN2EwNDM4ZWM2YjRiYjlhNmQ3NGU5YWZmMTE4NmNiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Db21tZXJjZSBDb3VydCwgVmljdG9yaWEgSG90ZWwsIERvd250b3duIFRvcm9udG88L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfN2UxMDgxNmQ0Y2Q4NDI1M2E5YjA1NGMyOGM3ZThkMzQuc2V0Q29udGVudChodG1sXzFhN2EwNDM4ZWM2YjRiYjlhNmQ3NGU5YWZmMTE4NmNiKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl83NjZkNGUzMzlhMzA0ODhkYmFjMzEzNzFjODQ2NTA2Yy5iaW5kUG9wdXAocG9wdXBfN2UxMDgxNmQ0Y2Q4NDI1M2E5YjA1NGMyOGM3ZThkMzQpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2M0ZDY3M2NhZGNlYzRhZmU4NjJhOTFjN2JmOWI4NjY4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzMzMjgyNSwgLTc5LjQxOTc0OTddLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM1MGIxMmMiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzUwYjEyYyIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfNjkyZmM5ZWUwMTc1NDRlZGJkNzFhNmFhNzc1NzRhZmQgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2I1MDRiM2U5NWZkMzQyMDNhMWE3YzBmZjdmMTJiNGFmID0gJChgPGRpdiBpZD0iaHRtbF9iNTA0YjNlOTVmZDM0MjAzYTFhN2MwZmY3ZjEyYjRhZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmVkZm9yZCBQYXJrLCBMYXdyZW5jZSBNYW5vciBFYXN0LCBOb3J0aCBZb3JrPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzY5MmZjOWVlMDE3NTQ0ZWRiZDcxYTZhYTc3NTc0YWZkLnNldENvbnRlbnQoaHRtbF9iNTA0YjNlOTVmZDM0MjAzYTFhN2MwZmY3ZjEyYjRhZik7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfYzRkNjczY2FkY2VjNGFmZTg2MmE5MWM3YmY5Yjg2NjguYmluZFBvcHVwKHBvcHVwXzY5MmZjOWVlMDE3NTQ0ZWRiZDcxYTZhYTc3NTc0YWZkKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83ZjRlNzFjNzJjNTg0YzNmODRjMjE1M2M1ZWQ2YTY0NiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcxMTY5NDgsIC03OS40MTY5MzU1OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzQ5NWI5MiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNDk1YjkyIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF85YWIyMmRkNTQ0ZGQ0MTczOTA3NmJiNDlmZGVjMjdjMiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfYjQzNWExZThjZWFhNDQ2ZDg2NDZiYjI2NDczZDMxZDcgPSAkKGA8ZGl2IGlkPSJodG1sX2I0MzVhMWU4Y2VhYTQ0NmQ4NjQ2YmIyNjQ3M2QzMWQ3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Sb3NlbGF3biwgQ2VudHJhbCBUb3JvbnRvPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzlhYjIyZGQ1NDRkZDQxNzM5MDc2YmI0OWZkZWMyN2MyLnNldENvbnRlbnQoaHRtbF9iNDM1YTFlOGNlYWE0NDZkODY0NmJiMjY0NzNkMzFkNyk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfN2Y0ZTcxYzcyYzU4NGMzZjg0YzIxNTNjNWVkNmE2NDYuYmluZFBvcHVwKHBvcHVwXzlhYjIyZGQ1NDRkZDQxNzM5MDc2YmI0OWZkZWMyN2MyKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jMzcyOTkxMzhiNTE0OTE5YTg5ODE0YzE0ZWVhOGVjMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY5Njk0NzYsIC03OS40MTEzMDcyMDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzQ5NWI5MiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNDk1YjkyIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF83NTRmOGY2NTQ1Yzk0MmNhYjJjOGZlZTgxZDViMDQxZiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfNDEzZmFiMmQ0ZDMxNDEyNzljMzI2OGI1NTJjY2Q1ZGYgPSAkKGA8ZGl2IGlkPSJodG1sXzQxM2ZhYjJkNGQzMTQxMjc5YzMyNjhiNTUyY2NkNWRmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Gb3Jlc3QgSGlsbCBOb3J0aCAmYW1wOyBXZXN0LCBGb3Jlc3QgSGlsbCBSb2FkIFBhcmssIENlbnRyYWwgVG9yb250bzwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF83NTRmOGY2NTQ1Yzk0MmNhYjJjOGZlZTgxZDViMDQxZi5zZXRDb250ZW50KGh0bWxfNDEzZmFiMmQ0ZDMxNDEyNzljMzI2OGI1NTJjY2Q1ZGYpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2MzNzI5OTEzOGI1MTQ5MTlhODk4MTRjMTRlZWE4ZWMyLmJpbmRQb3B1cChwb3B1cF83NTRmOGY2NTQ1Yzk0MmNhYjJjOGZlZTgxZDViMDQxZikKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMmMzMzhhZDdkNTk3NDc0OTgzN2I4NGUzYmFlZmEyNDYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NzI3MDk3LCAtNzkuNDA1Njc4NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM0OTViOTIiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzQ5NWI5MiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfOTQ2ZWY0OTJhZTBjNDhkMzkyYzA5NzQwNDM3YTVjZjIgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzNjOGE4Yzg2ZWZiNTQ1MzM4YjI0YzMxOGI2MWM1MjlhID0gJChgPGRpdiBpZD0iaHRtbF8zYzhhOGM4NmVmYjU0NTMzOGIyNGMzMThiNjFjNTI5YSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VGhlIEFubmV4LCBOb3J0aCBNaWR0b3duLCBZb3JrdmlsbGUsIENlbnRyYWwgVG9yb250bzwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF85NDZlZjQ5MmFlMGM0OGQzOTJjMDk3NDA0MzdhNWNmMi5zZXRDb250ZW50KGh0bWxfM2M4YThjODZlZmI1NDUzMzhiMjRjMzE4YjYxYzUyOWEpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzJjMzM4YWQ3ZDU5NzQ3NDk4MzdiODRlM2JhZWZhMjQ2LmJpbmRQb3B1cChwb3B1cF85NDZlZjQ5MmFlMGM0OGQzOTJjMDk3NDA0MzdhNWNmMikKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMzQ5ZDI4Yzc5ZjQ4NDRjNmEyNDBhMGFmOTg1MjM0MDMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NjI2OTU2LCAtNzkuNDAwMDQ5M10sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzdhN2RhMSIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjN2E3ZGExIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF83N2M1NTBkMzFhYzg0YzM5ODc0MzNhMjUzNmNjYjlhMiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfN2M4YmVjMjAxYWRmNGQwMTg4MTg5ZjM5NjMyODVmZGYgPSAkKGA8ZGl2IGlkPSJodG1sXzdjOGJlYzIwMWFkZjRkMDE4ODE4OWYzOTYzMjg1ZmRmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Vbml2ZXJzaXR5IG9mIFRvcm9udG8sIEhhcmJvcmQsIERvd250b3duIFRvcm9udG88L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfNzdjNTUwZDMxYWM4NGMzOTg3NDMzYTI1MzZjY2I5YTIuc2V0Q29udGVudChodG1sXzdjOGJlYzIwMWFkZjRkMDE4ODE4OWYzOTYzMjg1ZmRmKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl8zNDlkMjhjNzlmNDg0NGM2YTI0MGEwYWY5ODUyMzQwMy5iaW5kUG9wdXAocG9wdXBfNzdjNTUwZDMxYWM4NGMzOTg3NDMzYTI1MzZjY2I5YTIpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2NkNjFhZDBiZDU3ZTRlZWY5MjFiNDVlNzZhNWVlMThlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUzMjA1NywgLTc5LjQwMDA0OTNdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM3YTdkYTEiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzdhN2RhMSIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMTZmMmI3YjBjYjcwNGZjZWI5ZDU1MmQ0MGM5Mjg4ZDMgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzNjMGM2ODA1NWNjZDRjOWY5MzI2NzI0ZTBhNGNkM2RiID0gJChgPGRpdiBpZD0iaHRtbF8zYzBjNjgwNTVjY2Q0YzlmOTMyNjcyNGUwYTRjZDNkYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+S2Vuc2luZ3RvbiBNYXJrZXQsIENoaW5hdG93biwgR3JhbmdlIFBhcmssIERvd250b3duIFRvcm9udG88L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfMTZmMmI3YjBjYjcwNGZjZWI5ZDU1MmQ0MGM5Mjg4ZDMuc2V0Q29udGVudChodG1sXzNjMGM2ODA1NWNjZDRjOWY5MzI2NzI0ZTBhNGNkM2RiKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9jZDYxYWQwYmQ1N2U0ZWVmOTIxYjQ1ZTc2YTVlZTE4ZS5iaW5kUG9wdXAocG9wdXBfMTZmMmI3YjBjYjcwNGZjZWI5ZDU1MmQ0MGM5Mjg4ZDMpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2VkNGYzY2Y1MDEzZjQ5NTBiMWMxZGRlZDg1OTNiNjdmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjI4OTQ2NywgLTc5LjM5NDQxOTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM3YTdkYTEiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzdhN2RhMSIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfZGVjMjA1ZTIyYzI5NDNmZGFmNTI2ZjIwYjMxYWNjNmQgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzhhYWZjMzhhMjc4OTQzNWRiMTgxMmI2MTExYTliYzM5ID0gJChgPGRpdiBpZD0iaHRtbF84YWFmYzM4YTI3ODk0MzVkYjE4MTJiNjExMWE5YmMzOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q04gVG93ZXIsIEtpbmcgYW5kIFNwYWRpbmEsIFJhaWx3YXkgTGFuZHMsIEhhcmJvdXJmcm9udCBXZXN0LCBCYXRodXJzdCBRdWF5LCBTb3V0aCBOaWFnYXJhLCBJc2xhbmQgYWlycG9ydCwgRG93bnRvd24gVG9yb250bzwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9kZWMyMDVlMjJjMjk0M2ZkYWY1MjZmMjBiMzFhY2M2ZC5zZXRDb250ZW50KGh0bWxfOGFhZmMzOGEyNzg5NDM1ZGIxODEyYjYxMTFhOWJjMzkpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2VkNGYzY2Y1MDEzZjQ5NTBiMWMxZGRlZDg1OTNiNjdmLmJpbmRQb3B1cChwb3B1cF9kZWMyMDVlMjJjMjk0M2ZkYWY1MjZmMjBiMzFhY2M2ZCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZGZhZTcxNjI5YjdkNDZlZTgwMzliNTQ2N2NiZjM1ZTEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDY0MzUyLCAtNzkuMzc0ODQ1OTk5OTk5OTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM3YTdkYTEiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzdhN2RhMSIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMmZiMmE5M2IyYzViNGNmZTg2OWQyMjliOTk4OGRiMDAgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2VjZjFiMjNmNmZlNjRkNDliNDA5Zjc5YTk0ZTM5MTU2ID0gJChgPGRpdiBpZD0iaHRtbF9lY2YxYjIzZjZmZTY0ZDQ5YjQwOWY3OWE5NGUzOTE1NiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3RuIEEgUE8gQm94ZXMsIERvd250b3duIFRvcm9udG88L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfMmZiMmE5M2IyYzViNGNmZTg2OWQyMjliOTk4OGRiMDAuc2V0Q29udGVudChodG1sX2VjZjFiMjNmNmZlNjRkNDliNDA5Zjc5YTk0ZTM5MTU2KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9kZmFlNzE2MjliN2Q0NmVlODAzOWI1NDY3Y2JmMzVlMS5iaW5kUG9wdXAocG9wdXBfMmZiMmE5M2IyYzViNGNmZTg2OWQyMjliOTk4OGRiMDApCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2FiMTk2OTg5ZGNkOTRiZTlhY2M0MzFjMTEzODZlYmI3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjQ4NDI5MiwgLTc5LjM4MjI4MDJdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM3YTdkYTEiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzdhN2RhMSIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfYjZiNzhmZDVmMDlmNDI4M2FlNmMzZjJlNDdlMzFmNGIgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzVjYzY1ZWEzMjdkZTRhYmZiNjc3NjU3NGRhMDA1OGU4ID0gJChgPGRpdiBpZD0iaHRtbF81Y2M2NWVhMzI3ZGU0YWJmYjY3NzY1NzRkYTAwNThlOCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Rmlyc3QgQ2FuYWRpYW4gUGxhY2UsIFVuZGVyZ3JvdW5kIGNpdHksIERvd250b3duIFRvcm9udG88L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfYjZiNzhmZDVmMDlmNDI4M2FlNmMzZjJlNDdlMzFmNGIuc2V0Q29udGVudChodG1sXzVjYzY1ZWEzMjdkZTRhYmZiNjc3NjU3NGRhMDA1OGU4KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9hYjE5Njk4OWRjZDk0YmU5YWNjNDMxYzExMzg2ZWJiNy5iaW5kUG9wdXAocG9wdXBfYjZiNzhmZDVmMDlmNDI4M2FlNmMzZjJlNDdlMzFmNGIpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2UwMTcyMGU2ZmNjNTRiMGM4MWQwNzFjMGJmMjA3MWFkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzE4NTE3OTk5OTk5OTk2LCAtNzkuNDY0NzYzMjk5OTk5OTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM1MGIxMmMiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzUwYjEyYyIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfN2I0ZWZiODFhZWQ2NDFjNTg0Njc2MzdhNDQzMWY3ZTggPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2ZiMTE5YTE1YjlhZDRlZjI4MDNlNjJkZDRlOGQzZGZhID0gJChgPGRpdiBpZD0iaHRtbF9mYjExOWExNWI5YWQ0ZWYyODAzZTYyZGQ0ZThkM2RmYSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TGF3cmVuY2UgTWFub3IsIExhd3JlbmNlIEhlaWdodHMsIE5vcnRoIFlvcms8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfN2I0ZWZiODFhZWQ2NDFjNTg0Njc2MzdhNDQzMWY3ZTguc2V0Q29udGVudChodG1sX2ZiMTE5YTE1YjlhZDRlZjI4MDNlNjJkZDRlOGQzZGZhKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9lMDE3MjBlNmZjYzU0YjBjODFkMDcxYzBiZjIwNzFhZC5iaW5kUG9wdXAocG9wdXBfN2I0ZWZiODFhZWQ2NDFjNTg0Njc2MzdhNDQzMWY3ZTgpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2QwN2U0NmRlZjg2OTRlZmRhZDI1MjRlODYxYmFkZTNjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzA5NTc3LCAtNzkuNDQ1MDcyNTk5OTk5OTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM1MGIxMmMiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzUwYjEyYyIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfODgwZWZlMWFhNmRhNGYyZWEyODdiYTgxMTg4YzZkNGQgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzBhNjJhZGM0ZjkzMzQ4ZmE4ZDVjN2JiN2Y5MDVjNWM0ID0gJChgPGRpdiBpZD0iaHRtbF8wYTYyYWRjNGY5MzM0OGZhOGQ1YzdiYjdmOTA1YzVjNCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+R2xlbmNhaXJuLCBOb3J0aCBZb3JrPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzg4MGVmZTFhYTZkYTRmMmVhMjg3YmE4MTE4OGM2ZDRkLnNldENvbnRlbnQoaHRtbF8wYTYyYWRjNGY5MzM0OGZhOGQ1YzdiYjdmOTA1YzVjNCk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfZDA3ZTQ2ZGVmODY5NGVmZGFkMjUyNGU4NjFiYWRlM2MuYmluZFBvcHVwKHBvcHVwXzg4MGVmZTFhYTZkYTRmMmVhMjg3YmE4MTE4OGM2ZDRkKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hYWYxODc4ODAxYmM0OGUxOGUxNTM0Y2RlMTY1NTlhOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY5Mzc4MTMsIC03OS40MjgxOTE0MDAwMDAwMl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiI2JiODUwNSIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjYmI4NTA1IiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9mZDM1MjA4Zjk2MWM0MTkzYjcyNmNhNTUwNDVlMjA5NCA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfOGM3NDQyMWU2ZTZiNDY4ODk3NDdkYWMxMjlhNzgxZjEgPSAkKGA8ZGl2IGlkPSJodG1sXzhjNzQ0MjFlNmU2YjQ2ODg5NzQ3ZGFjMTI5YTc4MWYxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IdW1ld29vZC1DZWRhcnZhbGUsIFlvcms8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfZmQzNTIwOGY5NjFjNDE5M2I3MjZjYTU1MDQ1ZTIwOTQuc2V0Q29udGVudChodG1sXzhjNzQ0MjFlNmU2YjQ2ODg5NzQ3ZGFjMTI5YTc4MWYxKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9hYWYxODc4ODAxYmM0OGUxOGUxNTM0Y2RlMTY1NTlhOC5iaW5kUG9wdXAocG9wdXBfZmQzNTIwOGY5NjFjNDE5M2I3MjZjYTU1MDQ1ZTIwOTQpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzkzY2ZlYzkzYmRmOTRjZDM5OTMxMjNlYWVhOTU3OTEwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjg5MDI1NiwgLTc5LjQ1MzUxMl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiI2JiODUwNSIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjYmI4NTA1IiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF82NjFmMzIwYzRkMTA0ZWZiYjUxNjhkYzJjOTFlNzY2MyA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfOTJiNGRiYTA3YzA1NDI0NGJiODU4ZThkYTdkOGJmNTYgPSAkKGA8ZGl2IGlkPSJodG1sXzkyYjRkYmEwN2MwNTQyNDRiYjg1OGU4ZGE3ZDhiZjU2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DYWxlZG9uaWEtRmFpcmJhbmtzLCBZb3JrPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzY2MWYzMjBjNGQxMDRlZmJiNTE2OGRjMmM5MWU3NjYzLnNldENvbnRlbnQoaHRtbF85MmI0ZGJhMDdjMDU0MjQ0YmI4NThlOGRhN2Q4YmY1Nik7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfOTNjZmVjOTNiZGY5NGNkMzk5MzEyM2VhZWE5NTc5MTAuYmluZFBvcHVwKHBvcHVwXzY2MWYzMjBjNGQxMDRlZmJiNTE2OGRjMmM5MWU3NjYzKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80YzNlYzNiNGI2YmU0ZThkOTNiMDlmMmZjODQyNDdhMSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY2OTU0MiwgLTc5LjQyMjU2MzddLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM3YTdkYTEiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzdhN2RhMSIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMWNkZGMyMDZhZGUwNDY2NzlmNDBhOGM4OGZlYzVhMmMgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzNhMzRiNjFhNjYyMjRlYzFiZjM3OTNmMzk3ZDE0YzBmID0gJChgPGRpdiBpZD0iaHRtbF8zYTM0YjYxYTY2MjI0ZWMxYmYzNzkzZjM5N2QxNGMwZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q2hyaXN0aWUsIERvd250b3duIFRvcm9udG88L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfMWNkZGMyMDZhZGUwNDY2NzlmNDBhOGM4OGZlYzVhMmMuc2V0Q29udGVudChodG1sXzNhMzRiNjFhNjYyMjRlYzFiZjM3OTNmMzk3ZDE0YzBmKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl80YzNlYzNiNGI2YmU0ZThkOTNiMDlmMmZjODQyNDdhMS5iaW5kUG9wdXAocG9wdXBfMWNkZGMyMDZhZGUwNDY2NzlmNDBhOGM4OGZlYzVhMmMpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2VlOTc2MjE5ZjgyOTQ0ZTVhMGQ4ZmZlYzY5M2I4OTllID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjY5MDA1MTAwMDAwMDEsIC03OS40NDIyNTkzXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMTc5MGFlIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiMxNzkwYWUiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzdhNjMzMjc0MzY1NzQ4MDNiMjdkMjYyYzE0M2E4NjU4ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9mYmZkNWMzN2Q1MGM0OGJlYjVlNTY4ZjUzZTg2YjhmYyA9ICQoYDxkaXYgaWQ9Imh0bWxfZmJmZDVjMzdkNTBjNDhiZWI1ZTU2OGY1M2U4NmI4ZmMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkR1ZmZlcmluLCBEb3ZlcmNvdXJ0IFZpbGxhZ2UsIFdlc3QgVG9yb250bzwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF83YTYzMzI3NDM2NTc0ODAzYjI3ZDI2MmMxNDNhODY1OC5zZXRDb250ZW50KGh0bWxfZmJmZDVjMzdkNTBjNDhiZWI1ZTU2OGY1M2U4NmI4ZmMpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2VlOTc2MjE5ZjgyOTQ0ZTVhMGQ4ZmZlYzY5M2I4OTllLmJpbmRQb3B1cChwb3B1cF83YTYzMzI3NDM2NTc0ODAzYjI3ZDI2MmMxNDNhODY1OCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfY2JmZGY2MTllYWIxNGU5NWJmMzc0MTkzYTI5ZTY4ODAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDc5MjY3MDAwMDAwMDYsIC03OS40MTk3NDk3XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMTc5MGFlIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiMxNzkwYWUiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzdkOGVmZjI2NzFmMzQ0MTg4NWY3ZjUwNTU0NGUxNmQxID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF8wZTY4NzNlOWQ0OGI0MzVkODQ4OGVkMzc4Y2VkMjhhYSA9ICQoYDxkaXYgaWQ9Imh0bWxfMGU2ODczZTlkNDhiNDM1ZDg0ODhlZDM3OGNlZDI4YWEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxpdHRsZSBQb3J0dWdhbCwgVHJpbml0eSwgV2VzdCBUb3JvbnRvPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzdkOGVmZjI2NzFmMzQ0MTg4NWY3ZjUwNTU0NGUxNmQxLnNldENvbnRlbnQoaHRtbF8wZTY4NzNlOWQ0OGI0MzVkODQ4OGVkMzc4Y2VkMjhhYSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfY2JmZGY2MTllYWIxNGU5NWJmMzc0MTkzYTI5ZTY4ODAuYmluZFBvcHVwKHBvcHVwXzdkOGVmZjI2NzFmMzQ0MTg4NWY3ZjUwNTU0NGUxNmQxKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83NmVkZGU5ZTA3Y2M0NTRmOWQ2NDBlZGViZmM3ODM4OSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjYzNjg0NzIsIC03OS40MjgxOTE0MDAwMDAwMl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzE3OTBhZSIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjMTc5MGFlIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF81NzI1YTA0NGJkYjE0ODVhYjFlMDgxYmRkNTA1NTc1YiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfNDY4OGM4ODk0Mjg1NDFiZDg0NzQzM2E2YjU1NGQzYWEgPSAkKGA8ZGl2IGlkPSJodG1sXzQ2ODhjODg5NDI4NTQxYmQ4NDc0MzNhNmI1NTRkM2FhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ccm9ja3RvbiwgUGFya2RhbGUgVmlsbGFnZSwgRXhoaWJpdGlvbiBQbGFjZSwgV2VzdCBUb3JvbnRvPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzU3MjVhMDQ0YmRiMTQ4NWFiMWUwODFiZGQ1MDU1NzViLnNldENvbnRlbnQoaHRtbF80Njg4Yzg4OTQyODU0MWJkODQ3NDMzYTZiNTU0ZDNhYSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNzZlZGRlOWUwN2NjNDU0ZjlkNjQwZWRlYmZjNzgzODkuYmluZFBvcHVwKHBvcHVwXzU3MjVhMDQ0YmRiMTQ4NWFiMWUwODFiZGQ1MDU1NzViKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mNDdhMTY2ZDIzZjc0NjE2YTRhZDE2OGMxNzNiOGJiZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcxMzc1NjIwMDAwMDAwNiwgLTc5LjQ5MDA3MzhdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM1MGIxMmMiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzUwYjEyYyIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMDcxMjhkY2ZhOTZjNGJlYmEyZDNhZTUxZWVhYjlmZTggPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzUwZGM1ODBjMTUzODQ3ZDBhZjNhMDQ0OTViMjI5YmU1ID0gJChgPGRpdiBpZD0iaHRtbF81MGRjNTgwYzE1Mzg0N2QwYWYzYTA0NDk1YjIyOWJlNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Tm9ydGggUGFyaywgTWFwbGUgTGVhZiBQYXJrLCBVcHdvb2QgUGFyaywgTm9ydGggWW9yazwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8wNzEyOGRjZmE5NmM0YmViYTJkM2FlNTFlZWFiOWZlOC5zZXRDb250ZW50KGh0bWxfNTBkYzU4MGMxNTM4NDdkMGFmM2EwNDQ5NWIyMjliZTUpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2Y0N2ExNjZkMjNmNzQ2MTZhNGFkMTY4YzE3M2I4YmJkLmJpbmRQb3B1cChwb3B1cF8wNzEyOGRjZmE5NmM0YmViYTJkM2FlNTFlZWFiOWZlOCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNzY0YTY1ZDU1N2Q2NGU3ZjlhNmNlZDM2MjBjMzk1NTcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42OTExMTU4LCAtNzkuNDc2MDEzMjk5OTk5OTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiNiYjg1MDUiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiI2JiODUwNSIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfZWYwZTFiZDVmYmU2NGFjZWI5ZTI3ZGVlZmM4MzdkNzQgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzg0OTU1NDUxYTE0OTQ5ZGU4MzNiZWQ1Mjc5OGJjM2UzID0gJChgPGRpdiBpZD0iaHRtbF84NDk1NTQ1MWExNDk0OWRlODMzYmVkNTI3OThiYzNlMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RGVsIFJheSwgTW91bnQgRGVubmlzLCBLZWVsc2RhbGUgYW5kIFNpbHZlcnRob3JuLCBZb3JrPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2VmMGUxYmQ1ZmJlNjRhY2ViOWUyN2RlZWZjODM3ZDc0LnNldENvbnRlbnQoaHRtbF84NDk1NTQ1MWExNDk0OWRlODMzYmVkNTI3OThiYzNlMyk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNzY0YTY1ZDU1N2Q2NGU3ZjlhNmNlZDM2MjBjMzk1NTcuYmluZFBvcHVwKHBvcHVwX2VmMGUxYmQ1ZmJlNjRhY2ViOWUyN2RlZWZjODM3ZDc0KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iNGYwNDM0ZTM0NWY0ZWI3OGY2ODhmNzQ4NGMxZDE3NSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY3MzE4NTI5OTk5OTk5LCAtNzkuNDg3MjYxOTAwMDAwMDFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiNiYjg1MDUiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiI2JiODUwNSIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfNjNkMmFlMTEwNTgzNGMxOTgzNjA5YTQzYjlhNTc1YjggPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzUzZjE1OTFlMWY1MDQ1NWJiYjA1MDIxYTM3M2E0MjQ2ID0gJChgPGRpdiBpZD0iaHRtbF81M2YxNTkxZTFmNTA0NTViYmIwNTAyMWEzNzNhNDI0NiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UnVubnltZWRlLCBUaGUgSnVuY3Rpb24gTm9ydGgsIFlvcms8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfNjNkMmFlMTEwNTgzNGMxOTgzNjA5YTQzYjlhNTc1Yjguc2V0Q29udGVudChodG1sXzUzZjE1OTFlMWY1MDQ1NWJiYjA1MDIxYTM3M2E0MjQ2KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9iNGYwNDM0ZTM0NWY0ZWI3OGY2ODhmNzQ4NGMxZDE3NS5iaW5kUG9wdXAocG9wdXBfNjNkMmFlMTEwNTgzNGMxOTgzNjA5YTQzYjlhNTc1YjgpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzhjYzY4ZmYzNjI0NDRjZWY5MzlkMWJhOTkwNWE5ZWZhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjYxNjA4MywgLTc5LjQ2NDc2MzI5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMTc5MGFlIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiMxNzkwYWUiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2I2YzMyNDhlMmQ2NTQwMTg5ZjA2NGQyZTI5YTFiMTA0ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF82NTM3NTE5MmVhYjk0MGU4YjI5OGFkNjc1NDhmMzEyYSA9ICQoYDxkaXYgaWQ9Imh0bWxfNjUzNzUxOTJlYWI5NDBlOGIyOThhZDY3NTQ4ZjMxMmEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhpZ2ggUGFyaywgVGhlIEp1bmN0aW9uIFNvdXRoLCBXZXN0IFRvcm9udG88L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfYjZjMzI0OGUyZDY1NDAxODlmMDY0ZDJlMjlhMWIxMDQuc2V0Q29udGVudChodG1sXzY1Mzc1MTkyZWFiOTQwZThiMjk4YWQ2NzU0OGYzMTJhKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl84Y2M2OGZmMzYyNDQ0Y2VmOTM5ZDFiYTk5MDVhOWVmYS5iaW5kUG9wdXAocG9wdXBfYjZjMzI0OGUyZDY1NDAxODlmMDY0ZDJlMjlhMWIxMDQpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2ZhNTA0NmEyMjNmMzQ2NzE5NTkxNWRkNmM1OTViYzYyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjQ4OTU5NywgLTc5LjQ1NjMyNV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzE3OTBhZSIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjMTc5MGFlIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9kNTE5Mzg5ZjYyYmE0OTZkYjFmYWM5N2RkZGE4NmMwMSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfZWRmMjRlMDg2MTNkNDkyYmE1YTU3MDYwNjMwNDNkNjAgPSAkKGA8ZGl2IGlkPSJodG1sX2VkZjI0ZTA4NjEzZDQ5MmJhNWE1NzA2MDYzMDQzZDYwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5QYXJrZGFsZSwgUm9uY2VzdmFsbGVzLCBXZXN0IFRvcm9udG88L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfZDUxOTM4OWY2MmJhNDk2ZGIxZmFjOTdkZGRhODZjMDEuc2V0Q29udGVudChodG1sX2VkZjI0ZTA4NjEzZDQ5MmJhNWE1NzA2MDYzMDQzZDYwKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9mYTUwNDZhMjIzZjM0NjcxOTU5MTVkZDZjNTk1YmM2Mi5iaW5kUG9wdXAocG9wdXBfZDUxOTM4OWY2MmJhNDk2ZGIxZmFjOTdkZGRhODZjMDEpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzFlMTY0NDZiMTE0ZDQ0NGQ4ZGE3YTFhMDY2MmNmMGRlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUxNTcwNiwgLTc5LjQ4NDQ0OTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMxNzkwYWUiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzE3OTBhZSIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfM2U4NGJhMjBmNjg0NDE2NWJjOGQyZmMwMmY4OGFhZGQgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzRjYjlhMGQ1OTFhOTQyZjc4MDM3MjRlNDI3MmE5NzVkID0gJChgPGRpdiBpZD0iaHRtbF80Y2I5YTBkNTkxYTk0MmY3ODAzNzI0ZTQyNzJhOTc1ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UnVubnltZWRlLCBTd2Fuc2VhLCBXZXN0IFRvcm9udG88L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfM2U4NGJhMjBmNjg0NDE2NWJjOGQyZmMwMmY4OGFhZGQuc2V0Q29udGVudChodG1sXzRjYjlhMGQ1OTFhOTQyZjc4MDM3MjRlNDI3MmE5NzVkKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl8xZTE2NDQ2YjExNGQ0NDRkOGRhN2ExYTA2NjJjZjBkZS5iaW5kUG9wdXAocG9wdXBfM2U4NGJhMjBmNjg0NDE2NWJjOGQyZmMwMmY4OGFhZGQpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2UxMmZkOTM3MGUzZDQ0NjliNGJlNmUyOTJkOGIwMzdiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjYyMzAxNSwgLTc5LjM4OTQ5MzhdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM3YTdkYTEiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzdhN2RhMSIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMmMxNjQyYTdmMDdjNGExZDhlOWI0MTU3ODQ4NTQ4ZDEgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2IxYWUxNDYzOGQyOTQ2YzE4YjNmNDU3MjE2OTE3YmI1ID0gJChgPGRpdiBpZD0iaHRtbF9iMWFlMTQ2MzhkMjk0NmMxOGIzZjQ1NzIxNjkxN2JiNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UXVlZW4mIzM5O3MgUGFyaywgT250YXJpbyBQcm92aW5jaWFsIEdvdmVybm1lbnQsIERvd250b3duIFRvcm9udG88L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfMmMxNjQyYTdmMDdjNGExZDhlOWI0MTU3ODQ4NTQ4ZDEuc2V0Q29udGVudChodG1sX2IxYWUxNDYzOGQyOTQ2YzE4YjNmNDU3MjE2OTE3YmI1KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9lMTJmZDkzNzBlM2Q0NDY5YjRiZTZlMjkyZDhiMDM3Yi5iaW5kUG9wdXAocG9wdXBfMmMxNjQyYTdmMDdjNGExZDhlOWI0MTU3ODQ4NTQ4ZDEpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I0NTAwMzMxMjE4MzQwM2VhODFhODJmMDk4MGY5YWUzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjM2OTY1NiwgLTc5LjYxNTgxODk5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjYTFhMWEwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNhMWExYTAiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzM0NThmYmRkZTg3NTQ1YWE5YmMwMjQzMjBlMzQ5NGE5ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF85YmM2YzEyNDgwOWM0NzhjODhhZDNhZjQxZTQ2NDEyNiA9ICQoYDxkaXYgaWQ9Imh0bWxfOWJjNmMxMjQ4MDljNDc4Yzg4YWQzYWY0MWU0NjQxMjYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNhbmFkYSBQb3N0IEdhdGV3YXkgUHJvY2Vzc2luZyBDZW50cmUsIE1pc3Npc3NhdWdhPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzM0NThmYmRkZTg3NTQ1YWE5YmMwMjQzMjBlMzQ5NGE5LnNldENvbnRlbnQoaHRtbF85YmM2YzEyNDgwOWM0NzhjODhhZDNhZjQxZTQ2NDEyNik7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfYjQ1MDAzMzEyMTgzNDAzZWE4MWE4MmYwOTgwZjlhZTMuYmluZFBvcHVwKHBvcHVwXzM0NThmYmRkZTg3NTQ1YWE5YmMwMjQzMjBlMzQ5NGE5KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mYTUxMGYwNjlhMmU0YTVhYTU1OGRkYjRlNjMzOTkxOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY2Mjc0MzksIC03OS4zMjE1NThdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4NjQ5MzMiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzg2NDkzMyIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfYWRjMGFlYWFiYzc5NGNlMTg4NmZjYTI5ZjRiMDE3YzUgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzRiMDBlMzRiNTcyMzQzNTA5MjUwODZmNTY4NTcwMTE1ID0gJChgPGRpdiBpZD0iaHRtbF80YjAwZTM0YjU3MjM0MzUwOTI1MDg2ZjU2ODU3MDExNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnVzaW5lc3MgcmVwbHkgbWFpbCBQcm9jZXNzaW5nIENlbnRyZSwgU291dGggQ2VudHJhbCBMZXR0ZXIgUHJvY2Vzc2luZyBQbGFudCBUb3JvbnRvLCBFYXN0IFRvcm9udG88L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfYWRjMGFlYWFiYzc5NGNlMTg4NmZjYTI5ZjRiMDE3YzUuc2V0Q29udGVudChodG1sXzRiMDBlMzRiNTcyMzQzNTA5MjUwODZmNTY4NTcwMTE1KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9mYTUxMGYwNjlhMmU0YTVhYTU1OGRkYjRlNjMzOTkxOC5iaW5kUG9wdXAocG9wdXBfYWRjMGFlYWFiYzc5NGNlMTg4NmZjYTI5ZjRiMDE3YzUpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2E1NmE5MjI5YjBlNzQyMTY4Njk2NzgzODkzODQ4ZGQ1ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjA1NjQ2NiwgLTc5LjUwMTMyMDcwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNTliMmE0IiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM1OWIyYTQiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2JiMzgyN2YxY2Y0NzQ2YjU4NzgzZDk3ZTkxNDQ0MmUzID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9mY2ZjMWFjZTk0ZDM0MDE5YmE0ZmM5MjkwODE1YzRiZiA9ICQoYDxkaXYgaWQ9Imh0bWxfZmNmYzFhY2U5NGQzNDAxOWJhNGZjOTI5MDgxNWM0YmYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5ldyBUb3JvbnRvLCBNaW1pY28gU291dGgsIEh1bWJlciBCYXkgU2hvcmVzLCBFdG9iaWNva2U8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfYmIzODI3ZjFjZjQ3NDZiNTg3ODNkOTdlOTE0NDQyZTMuc2V0Q29udGVudChodG1sX2ZjZmMxYWNlOTRkMzQwMTliYTRmYzkyOTA4MTVjNGJmKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9hNTZhOTIyOWIwZTc0MjE2ODY5Njc4Mzg5Mzg0OGRkNS5iaW5kUG9wdXAocG9wdXBfYmIzODI3ZjFjZjQ3NDZiNTg3ODNkOTdlOTE0NDQyZTMpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzRjNzg5YTU5OTViNDRjZWRhZjk2MzY3ZDZmNzk1NDRjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjAyNDEzNzAwMDAwMDEsIC03OS41NDM0ODQwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzU5YjJhNCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNTliMmE0IiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF84MTIxYTgyYTFlZDQ0YjVkYTM0YTcxM2Y3NzFhYWVjNiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfNzNmZjYyMDQ0ZGQ2NGY0YjgzZmVjZWRhMWM1NDFkY2UgPSAkKGA8ZGl2IGlkPSJodG1sXzczZmY2MjA0NGRkNjRmNGI4M2ZlY2VkYTFjNTQxZGNlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5BbGRlcndvb2QsIExvbmcgQnJhbmNoLCBFdG9iaWNva2U8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfODEyMWE4MmExZWQ0NGI1ZGEzNGE3MTNmNzcxYWFlYzYuc2V0Q29udGVudChodG1sXzczZmY2MjA0NGRkNjRmNGI4M2ZlY2VkYTFjNTQxZGNlKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl80Yzc4OWE1OTk1YjQ0Y2VkYWY5NjM2N2Q2Zjc5NTQ0Yy5iaW5kUG9wdXAocG9wdXBfODEyMWE4MmExZWQ0NGI1ZGEzNGE3MTNmNzcxYWFlYzYpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2JjNzE2Mjg4OTRiZTQ1YWNhZmZjZGQ0MmYzODJhYzRhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUzNjUzNjAwMDAwMDA1LCAtNzkuNTA2OTQzNl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzU5YjJhNCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNTliMmE0IiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF81MzA2NzE4MGQyYjQ0ZWNiYjE3NzU0NTI4MmVjMmNiYiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfZjJiOTMxNGU3NWQ4NDNjNDhkNmMxNDhiOWEzZGZhNjMgPSAkKGA8ZGl2IGlkPSJodG1sX2YyYjkzMTRlNzVkODQzYzQ4ZDZjMTQ4YjlhM2RmYTYzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UaGUgS2luZ3N3YXksIE1vbnRnb21lcnkgUm9hZCwgT2xkIE1pbGwgTm9ydGgsIEV0b2JpY29rZTwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF81MzA2NzE4MGQyYjQ0ZWNiYjE3NzU0NTI4MmVjMmNiYi5zZXRDb250ZW50KGh0bWxfZjJiOTMxNGU3NWQ4NDNjNDhkNmMxNDhiOWEzZGZhNjMpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2JjNzE2Mjg4OTRiZTQ1YWNhZmZjZGQ0MmYzODJhYzRhLmJpbmRQb3B1cChwb3B1cF81MzA2NzE4MGQyYjQ0ZWNiYjE3NzU0NTI4MmVjMmNiYikKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjNmM2I2ZDExYWQ5NGM0YmIzNTNhMTk3YThjOTFmZjggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42MzYyNTc5LCAtNzkuNDk4NTA5MDk5OTk5OTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM1OWIyYTQiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzU5YjJhNCIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfYzAzMmZmM2UwZTIyNDc2YTlmNDY1OTczOTA5MDhkYTggPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2YwYzU0ZTQxZmE5MjQ2MDk5ZGMyNDBjZmU0MzkwOGYwID0gJChgPGRpdiBpZD0iaHRtbF9mMGM1NGU0MWZhOTI0NjA5OWRjMjQwY2ZlNDM5MDhmMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+T2xkIE1pbGwgU291dGgsIEtpbmcmIzM5O3MgTWlsbCBQYXJrLCBTdW5ueWxlYSwgSHVtYmVyIEJheSwgTWltaWNvIE5FLCBUaGUgUXVlZW5zd2F5IEVhc3QsIFJveWFsIFlvcmsgU291dGggRWFzdCwgS2luZ3N3YXkgUGFyayBTb3V0aCBFYXN0LCBFdG9iaWNva2U8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfYzAzMmZmM2UwZTIyNDc2YTlmNDY1OTczOTA5MDhkYTguc2V0Q29udGVudChodG1sX2YwYzU0ZTQxZmE5MjQ2MDk5ZGMyNDBjZmU0MzkwOGYwKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9mM2YzYjZkMTFhZDk0YzRiYjM1M2ExOTdhOGM5MWZmOC5iaW5kUG9wdXAocG9wdXBfYzAzMmZmM2UwZTIyNDc2YTlmNDY1OTczOTA5MDhkYTgpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzJlODFiNzI0N2ZmODRkNmQ5ZjE2MjdlZjk2MDYwMDc3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjI4ODQwOCwgLTc5LjUyMDk5OTQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNTliMmE0IiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM1OWIyYTQiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzk0ZjFmZmE3YjA2NzQ1OGQ4YjU5ZDJhNWYzODU1NTVlID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9kNWQzNTk0M2VhYmU0ZDI5ODVlYmM3OWExMTNkOTVmMCA9ICQoYDxkaXYgaWQ9Imh0bWxfZDVkMzU5NDNlYWJlNGQyOTg1ZWJjNzlhMTEzZDk1ZjAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1pbWljbyBOVywgVGhlIFF1ZWVuc3dheSBXZXN0LCBTb3V0aCBvZiBCbG9vciwgS2luZ3N3YXkgUGFyayBTb3V0aCBXZXN0LCBSb3lhbCBZb3JrIFNvdXRoIFdlc3QsIEV0b2JpY29rZTwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF85NGYxZmZhN2IwNjc0NThkOGI1OWQyYTVmMzg1NTU1ZS5zZXRDb250ZW50KGh0bWxfZDVkMzU5NDNlYWJlNGQyOTg1ZWJjNzlhMTEzZDk1ZjApOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzJlODFiNzI0N2ZmODRkNmQ5ZjE2MjdlZjk2MDYwMDc3LmJpbmRQb3B1cChwb3B1cF85NGYxZmZhN2IwNjc0NThkOGI1OWQyYTVmMzg1NTU1ZSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfM2RlMjhhMThhY2IwNGZkYjk4ODZmODYzMmM2ZmFlZmUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Njc4NTU2LCAtNzkuNTMyMjQyNDAwMDAwMDJdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM1OWIyYTQiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzU5YjJhNCIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMWY3NDdhZmNkZGYxNGY2MTk1YWZmMGU2NjgyN2M0NjcgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzQ4ZmQ5OThiNzM4OTQ3YzM5Yjc3M2VjNWMwNGU3YjkwID0gJChgPGRpdiBpZD0iaHRtbF80OGZkOTk4YjczODk0N2MzOWI3NzNlYzVjMDRlN2I5MCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SXNsaW5ndG9uIEF2ZW51ZSwgSHVtYmVyIFZhbGxleSBWaWxsYWdlLCBFdG9iaWNva2U8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfMWY3NDdhZmNkZGYxNGY2MTk1YWZmMGU2NjgyN2M0Njcuc2V0Q29udGVudChodG1sXzQ4ZmQ5OThiNzM4OTQ3YzM5Yjc3M2VjNWMwNGU3YjkwKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl8zZGUyOGExOGFjYjA0ZmRiOTg4NmY4NjMyYzZmYWVmZS5iaW5kUG9wdXAocG9wdXBfMWY3NDdhZmNkZGYxNGY2MTk1YWZmMGU2NjgyN2M0NjcpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzZjZTg2NzMxMTQ3MDQ0YTU5ZjE1NjA0N2RmZWQ2YzdjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUwOTQzMiwgLTc5LjU1NDcyNDQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNTliMmE0IiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM1OWIyYTQiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzMxZjFlNTM2YWZmNzQ3ZWNhNWQ1YzBjMDA0OGMwOGNkID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF8wZmU4MDk2ZmIzYmU0YTg5YWM1OTZmZWNiMGQ5MzNjZSA9ICQoYDxkaXYgaWQ9Imh0bWxfMGZlODA5NmZiM2JlNGE4OWFjNTk2ZmVjYjBkOTMzY2UiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldlc3QgRGVhbmUgUGFyaywgUHJpbmNlc3MgR2FyZGVucywgTWFydGluIEdyb3ZlLCBJc2xpbmd0b24sIENsb3ZlcmRhbGUsIEV0b2JpY29rZTwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8zMWYxZTUzNmFmZjc0N2VjYTVkNWMwYzAwNDhjMDhjZC5zZXRDb250ZW50KGh0bWxfMGZlODA5NmZiM2JlNGE4OWFjNTk2ZmVjYjBkOTMzY2UpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzZjZTg2NzMxMTQ3MDQ0YTU5ZjE1NjA0N2RmZWQ2YzdjLmJpbmRQb3B1cChwb3B1cF8zMWYxZTUzNmFmZjc0N2VjYTVkNWMwYzAwNDhjMDhjZCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYzcyNmE1OTg2MjdjNDA2MjhiMDNiYWNmZTZmNDg5ZGEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDM1MTUyLCAtNzkuNTc3MjAwNzk5OTk5OTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM1OWIyYTQiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzU5YjJhNCIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfNzFlNTYxYWZhZmY4NDVkNTk4MDJkZmU5ZDJmMzQ5NTMgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzM2YjJjOWNhNDgwODRhZjBhYmExODVkZTJjZjdjODU4ID0gJChgPGRpdiBpZD0iaHRtbF8zNmIyYzljYTQ4MDg0YWYwYWJhMTg1ZGUyY2Y3Yzg1OCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RXJpbmdhdGUsIEJsb29yZGFsZSBHYXJkZW5zLCBPbGQgQnVybmhhbXRob3JwZSwgTWFya2xhbmQgV29vZCwgRXRvYmljb2tlPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzcxZTU2MWFmYWZmODQ1ZDU5ODAyZGZlOWQyZjM0OTUzLnNldENvbnRlbnQoaHRtbF8zNmIyYzljYTQ4MDg0YWYwYWJhMTg1ZGUyY2Y3Yzg1OCk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfYzcyNmE1OTg2MjdjNDA2MjhiMDNiYWNmZTZmNDg5ZGEuYmluZFBvcHVwKHBvcHVwXzcxZTU2MWFmYWZmODQ1ZDU5ODAyZGZlOWQyZjM0OTUzKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80MGEyNjUwYWYwMjg0ZWJiOWI5ZDY2MTRlZTIyZDU2OSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc1NjMwMzMsIC03OS41NjU5NjMyOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzUwYjEyYyIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNTBiMTJjIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF80Y2M2MDMyNGEzNDA0M2NmOTA0MWU1NDhlMGQ1YTBjMiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfZDViN2FiNjMyNWQ1NDg5ZjhjMWIzY2UwYTU4YWU4YTYgPSAkKGA8ZGl2IGlkPSJodG1sX2Q1YjdhYjYzMjVkNTQ4OWY4YzFiM2NlMGE1OGFlOGE2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IdW1iZXIgU3VtbWl0LCBOb3J0aCBZb3JrPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzRjYzYwMzI0YTM0MDQzY2Y5MDQxZTU0OGUwZDVhMGMyLnNldENvbnRlbnQoaHRtbF9kNWI3YWI2MzI1ZDU0ODlmOGMxYjNjZTBhNThhZThhNik7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNDBhMjY1MGFmMDI4NGViYjliOWQ2NjE0ZWUyMmQ1NjkuYmluZFBvcHVwKHBvcHVwXzRjYzYwMzI0YTM0MDQzY2Y5MDQxZTU0OGUwZDVhMGMyKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mZjA5MzEyYmVmNDk0ZTQ4OGFkNmJiYmY5MTlmODAxMSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcyNDc2NTksIC03OS41MzIyNDI0MDAwMDAwMl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzUwYjEyYyIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNTBiMTJjIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9mNzNmMzNmNTBkMTY0NWJkYTFmNDllYmQ5YzQ2MWFhZCA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfOWU2NjRjMjk1ODYzNDU4ZmFiOWZiNWFhZWQzM2NmYjEgPSAkKGA8ZGl2IGlkPSJodG1sXzllNjY0YzI5NTg2MzQ1OGZhYjlmYjVhYWVkMzNjZmIxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IdW1iZXJsZWEsIEVtZXJ5LCBOb3J0aCBZb3JrPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2Y3M2YzM2Y1MGQxNjQ1YmRhMWY0OWViZDljNDYxYWFkLnNldENvbnRlbnQoaHRtbF85ZTY2NGMyOTU4NjM0NThmYWI5ZmI1YWFlZDMzY2ZiMSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfZmYwOTMxMmJlZjQ5NGU0ODhhZDZiYmJmOTE5ZjgwMTEuYmluZFBvcHVwKHBvcHVwX2Y3M2YzM2Y1MGQxNjQ1YmRhMWY0OWViZDljNDYxYWFkKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mYTY2ZmI4ODNlMTU0ZmVlOTY2NDZkN2ZiODQ3NDZiMCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcwNjg3NiwgLTc5LjUxODE4ODQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjYmI4NTA1IiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNiYjg1MDUiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzA0MTRjM2JjN2ZhNDQ5ZTlhNmY3YzIxMWY0OWJkZWExID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF85ZjFhYjU5MjMzMjY0MDhlOGIyNDQ1ODZhYTg1NjkxNSA9ICQoYDxkaXYgaWQ9Imh0bWxfOWYxYWI1OTIzMzI2NDA4ZThiMjQ0NTg2YWE4NTY5MTUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldlc3RvbiwgWW9yazwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8wNDE0YzNiYzdmYTQ0OWU5YTZmN2MyMTFmNDliZGVhMS5zZXRDb250ZW50KGh0bWxfOWYxYWI1OTIzMzI2NDA4ZThiMjQ0NTg2YWE4NTY5MTUpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2ZhNjZmYjg4M2UxNTRmZWU5NjY0NmQ3ZmI4NDc0NmIwLmJpbmRQb3B1cChwb3B1cF8wNDE0YzNiYzdmYTQ0OWU5YTZmN2MyMTFmNDliZGVhMSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYWY1ZDA3MDI2ZmZkNDM5MDliMjJiNmM0ZmVlNzI1NWEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42OTYzMTksIC03OS41MzIyNDI0MDAwMDAwMl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzU5YjJhNCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjNTliMmE0IiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzRmNzE3ZjE3ZTE2YzRiZGRiZjg3MDQ2N2MyMGQ3OTJiKTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9hMjA5ZGI2YTFlNzQ0YWM3OGIxM2I3OWRkZGFlZTVlYyA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfOWVkZGI4ZWM2YzNjNDMyZjgyNmZkZTZkNDQ1OWRkMDIgPSAkKGA8ZGl2IGlkPSJodG1sXzllZGRiOGVjNmMzYzQzMmY4MjZmZGU2ZDQ0NTlkZDAyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XZXN0bW91bnQsIEV0b2JpY29rZTwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9hMjA5ZGI2YTFlNzQ0YWM3OGIxM2I3OWRkZGFlZTVlYy5zZXRDb250ZW50KGh0bWxfOWVkZGI4ZWM2YzNjNDMyZjgyNmZkZTZkNDQ1OWRkMDIpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2FmNWQwNzAyNmZmZDQzOTA5YjIyYjZjNGZlZTcyNTVhLmJpbmRQb3B1cChwb3B1cF9hMjA5ZGI2YTFlNzQ0YWM3OGIxM2I3OWRkZGFlZTVlYykKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZWQ2MjlmMmE4MDUzNDI4YmFlY2I5MmNlMzFhZDlmOWYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42ODg5MDU0LCAtNzkuNTU0NzI0NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM1OWIyYTQiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzU5YjJhNCIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF80ZjcxN2YxN2UxNmM0YmRkYmY4NzA0NjdjMjBkNzkyYik7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfNWNjNTMyYzJlNGVjNGI1Y2JmY2U5MjI5NDc0MDZmNzEgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzkyZWQ0Mjc1MDQyYTQzZjQ4YmQ5YjQ1MmViYjQxNGEyID0gJChgPGRpdiBpZD0iaHRtbF85MmVkNDI3NTA0MmE0M2Y0OGJkOWI0NTJlYmI0MTRhMiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+S2luZ3N2aWV3IFZpbGxhZ2UsIFN0LiBQaGlsbGlwcywgTWFydGluIEdyb3ZlIEdhcmRlbnMsIFJpY2h2aWV3IEdhcmRlbnMsIEV0b2JpY29rZTwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF81Y2M1MzJjMmU0ZWM0YjVjYmZjZTkyMjk0NzQwNmY3MS5zZXRDb250ZW50KGh0bWxfOTJlZDQyNzUwNDJhNDNmNDhiZDliNDUyZWJiNDE0YTIpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2VkNjI5ZjJhODA1MzQyOGJhZWNiOTJjZTMxYWQ5ZjlmLmJpbmRQb3B1cChwb3B1cF81Y2M1MzJjMmU0ZWM0YjVjYmZjZTkyMjk0NzQwNmY3MSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjFkMTRjZGZkZTMxNDY4ODk0NWUzM2FlMjJhMjRmYWMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43Mzk0MTYzOTk5OTk5OTYsIC03OS41ODg0MzY5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNTliMmE0IiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM1OWIyYTQiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzBlYWFjYzllY2VkNjQwNjJhYjE3NTAyYmY0ZjYxNWZiID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF84ZDI0YmI2NGFiNjE0MzFmYWQ0MWFhNmIzNTYwNWJjYyA9ICQoYDxkaXYgaWQ9Imh0bWxfOGQyNGJiNjRhYjYxNDMxZmFkNDFhYTZiMzU2MDViY2MiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlNvdXRoIFN0ZWVsZXMsIFNpbHZlcnN0b25lLCBIdW1iZXJnYXRlLCBKYW1lc3Rvd24sIE1vdW50IE9saXZlLCBCZWF1bW9uZCBIZWlnaHRzLCBUaGlzdGxldG93biwgQWxiaW9uIEdhcmRlbnMsIEV0b2JpY29rZTwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8wZWFhY2M5ZWNlZDY0MDYyYWIxNzUwMmJmNGY2MTVmYi5zZXRDb250ZW50KGh0bWxfOGQyNGJiNjRhYjYxNDMxZmFkNDFhYTZiMzU2MDViY2MpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2IxZDE0Y2RmZGUzMTQ2ODg5NDVlMzNhZTIyYTI0ZmFjLmJpbmRQb3B1cChwb3B1cF8wZWFhY2M5ZWNlZDY0MDYyYWIxNzUwMmJmNGY2MTVmYikKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfN2U2NjQ5NmFlMmM3NGUxMjhiZjc5MDU2MzZlYTU0YjEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MDY3NDgyOTk5OTk5OTQsIC03OS41OTQwNTQ0XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjNTliMmE0IiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM1OWIyYTQiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfNGY3MTdmMTdlMTZjNGJkZGJmODcwNDY3YzIwZDc5MmIpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2MxYjc2NzJmNDA0ZDRhY2RiNGFjZWZhNjVmNDY3M2JmID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9lZGY2MGJkMmZiNWQ0OWFjOTEwZGI3NGIyMThmZWJmMSA9ICQoYDxkaXYgaWQ9Imh0bWxfZWRmNjBiZDJmYjVkNDlhYzkxMGRiNzRiMjE4ZmViZjEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5vcnRod2VzdCwgV2VzdCBIdW1iZXIgLSBDbGFpcnZpbGxlLCBFdG9iaWNva2U8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfYzFiNzY3MmY0MDRkNGFjZGI0YWNlZmE2NWY0NjczYmYuc2V0Q29udGVudChodG1sX2VkZjYwYmQyZmI1ZDQ5YWM5MTBkYjc0YjIxOGZlYmYxKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl83ZTY2NDk2YWUyYzc0ZTEyOGJmNzkwNTYzNmVhNTRiMS5iaW5kUG9wdXAocG9wdXBfYzFiNzY3MmY0MDRkNGFjZGI0YWNlZmE2NWY0NjczYmYpCiAgICAgICAgOwoKICAgICAgICAKICAgIAo8L3NjcmlwdD4= 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 0x7f4188cbfbe0>" | |
] | |
}, | |
"execution_count": 227, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"def plot_location(latitude, longitude) -> folium.Map:\n", | |
"\n", | |
" map_location = folium.Map(location=[latitude, longitude], zoom_start=10)\n", | |
"\n", | |
" map_colors = (\n", | |
" dfc.Borough.value_counts()\n", | |
" .apply(lambda x: to_hex(np.random.random(size=3).tolist()))\n", | |
" .to_dict()\n", | |
" )\n", | |
"\n", | |
" # add markers to map\n", | |
" for _, (lat, lng, borough, neighborhood) in dfc[\n", | |
" [\"Latitude\", \"Longitude\", \"Borough\", \"Neighborhood\"]\n", | |
" ].iterrows():\n", | |
" label = f\"{neighborhood}, {borough}\"\n", | |
" label = folium.Popup(label, parse_html=True)\n", | |
" folium.CircleMarker(\n", | |
" [lat, lng],\n", | |
" radius=5,\n", | |
" popup=label,\n", | |
" color=map_colors[borough],\n", | |
" fill=True,\n", | |
" fill_color=map_colors[borough],\n", | |
" fill_opacity=0.7,\n", | |
" parse_html=False,\n", | |
" ).add_to(map_location)\n", | |
"\n", | |
" return map_location\n", | |
"\n", | |
"\n", | |
"# create map of Toronto using latitude and longitude values\n", | |
"toronto: Location = get_geocoord_from(\"Toronto, ON\")\n", | |
"latitude, longitude = toronto.latitude, toronto.longitude\n", | |
"\n", | |
"plot_location(latitude, longitude)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Clustering with the foursquare API" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Credentials are put in environment variables" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 22, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"CLIENT_ID = %env FOURSQUARE_CLIENT_ID\n", | |
"CLIENT_SECRET = %env FOURSQUARE_CLIENT_SECRET\n", | |
"API_VERSION = \"20180605\" # Foursquare API version" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"api url and client parameters, *id* and *secret* are stored in environment variables. *latitude* and *longitude* will be specified in requests" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 126, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"api_root: str = \"https://api.foursquare.com/v2/venues/explore\"\n", | |
"\n", | |
"params: Dict = dict(\n", | |
" client_id=CLIENT_ID,\n", | |
" client_secret=CLIENT_SECRET,\n", | |
" v=API_VERSION,\n", | |
" radius=500,\n", | |
" limit=100,\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Foursquare API response" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 127, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"req = requests.get(api_root, params=dict(ll=f\"{latitude},{longitude}\", **params))\n", | |
"res = req.json()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 128, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/json": { | |
"meta": { | |
"code": 200, | |
"requestId": "5f4bed01c7db236072d0a022" | |
}, | |
"response": { | |
"groups": [ | |
{ | |
"items": [ | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-5227bb01498e17bf485e6202-0", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/parks_outdoors/neighborhood_", | |
"suffix": ".png" | |
}, | |
"id": "4f2a25ac4b909258e854f55f", | |
"name": "Neighborhood", | |
"pluralName": "Neighborhoods", | |
"primary": true, | |
"shortName": "Neighborhood" | |
} | |
], | |
"id": "5227bb01498e17bf485e6202", | |
"location": { | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 113, | |
"formattedAddress": [ | |
"Toronto ON", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65323167517444, | |
"lng": -79.38529600606677 | |
} | |
], | |
"lat": 43.65323167517444, | |
"lng": -79.38529600606677, | |
"state": "ON" | |
}, | |
"name": "Downtown Toronto", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ad4c05ef964a520a6f620e3-1", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/parks_outdoors/plaza_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d164941735", | |
"name": "Plaza", | |
"pluralName": "Plazas", | |
"primary": true, | |
"shortName": "Plaza" | |
} | |
], | |
"id": "4ad4c05ef964a520a6f620e3", | |
"location": { | |
"address": "100 Queen St W", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Bay St", | |
"distance": 138, | |
"formattedAddress": [ | |
"100 Queen St W (at Bay St)", | |
"Toronto ON M5H 2N1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65227047322295, | |
"lng": -79.38351631164551 | |
} | |
], | |
"lat": 43.65227047322295, | |
"lng": -79.38351631164551, | |
"postalCode": "M5H 2N1", | |
"state": "ON" | |
}, | |
"name": "Nathan Phillips Square", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ae7b27df964a52068ad21e3-2", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/sushi_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1d2941735", | |
"name": "Sushi Restaurant", | |
"pluralName": "Sushi Restaurants", | |
"primary": true, | |
"shortName": "Sushi" | |
} | |
], | |
"id": "4ae7b27df964a52068ad21e3", | |
"location": { | |
"address": "122 Elizabeth St.", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Dundas St. W", | |
"distance": 222, | |
"formattedAddress": [ | |
"122 Elizabeth St. (at Dundas St. W)", | |
"Toronto ON M5G 1P5", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65526771691681, | |
"lng": -79.38516506734886 | |
} | |
], | |
"lat": 43.65526771691681, | |
"lng": -79.38516506734886, | |
"postalCode": "M5G 1P5", | |
"state": "ON" | |
}, | |
"name": "Japango", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-537773d1498e74a75bb75c1e-3", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/breakfast_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d143941735", | |
"name": "Breakfast Spot", | |
"pluralName": "Breakfast Spots", | |
"primary": true, | |
"shortName": "Breakfast" | |
} | |
], | |
"id": "537773d1498e74a75bb75c1e", | |
"location": { | |
"address": "483 Bay Street", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "Albert Street", | |
"distance": 161, | |
"formattedAddress": [ | |
"483 Bay Street (Albert Street)", | |
"Toronto ON M5G 2C9", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65314383888587, | |
"lng": -79.38198016678167 | |
} | |
], | |
"lat": 43.65314383888587, | |
"lng": -79.38198016678167, | |
"postalCode": "M5G 2C9", | |
"state": "ON" | |
}, | |
"name": "Eggspectation Bell Trinity Square", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
}, | |
"venuePage": { | |
"id": "97507838" | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4e2284b11fc7c0ef9857d143-4", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/bubble_", | |
"suffix": ".png" | |
}, | |
"id": "52e81612bcbc57f1066b7a0c", | |
"name": "Bubble Tea Shop", | |
"pluralName": "Bubble Tea Shops", | |
"primary": true, | |
"shortName": "Bubble Tea" | |
} | |
], | |
"id": "4e2284b11fc7c0ef9857d143", | |
"location": { | |
"address": "132 Dundas St W", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "btwn Bay & University", | |
"distance": 237, | |
"formattedAddress": [ | |
"132 Dundas St W (btwn Bay & University)", | |
"Toronto ON M5G 1C3", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65554164147378, | |
"lng": -79.38468427043244 | |
} | |
], | |
"lat": 43.65554164147378, | |
"lng": -79.38468427043244, | |
"postalCode": "M5G 1C3", | |
"state": "ON" | |
}, | |
"name": "Chatime 日出茶太", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4b2a6eb8f964a52012a924e3-5", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/bookstore_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d114951735", | |
"name": "Bookstore", | |
"pluralName": "Bookstores", | |
"primary": true, | |
"shortName": "Bookstore" | |
} | |
], | |
"id": "4b2a6eb8f964a52012a924e3", | |
"location": { | |
"address": "220 Yonge St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 260, | |
"formattedAddress": [ | |
"220 Yonge St", | |
"Toronto ON M5B 2H1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65351471121164, | |
"lng": -79.38069591056922 | |
} | |
], | |
"lat": 43.65351471121164, | |
"lng": -79.38069591056922, | |
"neighborhood": "Downtown Yonge", | |
"postalCode": "M5B 2H1", | |
"state": "ON" | |
}, | |
"name": "Indigo", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-57bcd3b7498e652a678d0378-6", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/default_", | |
"suffix": ".png" | |
}, | |
"id": "5bae9231bedf3950379f89d4", | |
"name": "Poke Place", | |
"pluralName": "Poke Places", | |
"primary": true, | |
"shortName": "Poke Place" | |
} | |
], | |
"id": "57bcd3b7498e652a678d0378", | |
"location": { | |
"address": "112 Elizabeth St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Dundas St W", | |
"distance": 181, | |
"formattedAddress": [ | |
"112 Elizabeth St (at Dundas St W)", | |
"Toronto ON M5G 1P5", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65489527525682, | |
"lng": -79.38505238381624 | |
} | |
], | |
"lat": 43.65489527525682, | |
"lng": -79.38505238381624, | |
"postalCode": "M5G 1P5", | |
"state": "ON" | |
}, | |
"name": "Poke Guys", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ad4c05ef964a5208ef620e3-7", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/building/government_monument_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d12d941735", | |
"name": "Monument / Landmark", | |
"pluralName": "Monuments / Landmarks", | |
"primary": true, | |
"shortName": "Landmark" | |
} | |
], | |
"id": "4ad4c05ef964a5208ef620e3", | |
"location": { | |
"address": "60 Queen Street West", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 240, | |
"formattedAddress": [ | |
"60 Queen Street West", | |
"Toronto ON M5H 1A1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.652008800876125, | |
"lng": -79.3817442232328 | |
} | |
], | |
"lat": 43.652008800876125, | |
"lng": -79.3817442232328, | |
"postalCode": "M5H 1A1", | |
"state": "ON" | |
}, | |
"name": "Old City Hall", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ad77a12f964a520260b21e3-8", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/mall_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1fd941735", | |
"name": "Shopping Mall", | |
"pluralName": "Shopping Malls", | |
"primary": true, | |
"shortName": "Mall" | |
} | |
], | |
"id": "4ad77a12f964a520260b21e3", | |
"location": { | |
"address": "220 Yonge St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "btwn Queen & Dundas", | |
"distance": 287, | |
"formattedAddress": [ | |
"220 Yonge St (btwn Queen & Dundas)", | |
"Toronto ON M5B 2H1", | |
"Canada" | |
], | |
"lat": 43.654540112988535, | |
"lng": -79.38067738352993, | |
"neighborhood": "Downtown Toronto, Toronto, ON", | |
"postalCode": "M5B 2H1", | |
"state": "ON" | |
}, | |
"name": "CF Toronto Eaton Centre", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-50885719498ea7b5aab3a74c-9", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/building/gym_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d176941735", | |
"name": "Gym", | |
"pluralName": "Gyms", | |
"primary": true, | |
"shortName": "Gym" | |
} | |
], | |
"id": "50885719498ea7b5aab3a74c", | |
"location": { | |
"address": "483 Bay St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 130, | |
"formattedAddress": [ | |
"483 Bay St", | |
"Toronto ON M5G 2C9", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.653436, | |
"lng": -79.382314 | |
} | |
], | |
"lat": 43.653436, | |
"lng": -79.382314, | |
"postalCode": "M5G 2C9", | |
"state": "ON" | |
}, | |
"name": "GoodLife Fitness Toronto Bell Trinity Centre", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ad4c05ef964a520e2f620e3-10", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/arts_entertainment/museum_art_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d18f941735", | |
"name": "Art Museum", | |
"pluralName": "Art Museums", | |
"primary": true, | |
"shortName": "Art Museum" | |
} | |
], | |
"id": "4ad4c05ef964a520e2f620e3", | |
"location": { | |
"address": "55 Centre Avenue", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "University Ave. and Dundas St W.", | |
"distance": 230, | |
"formattedAddress": [ | |
"55 Centre Avenue (University Ave. and Dundas St W.)", | |
"Toronto ON M5G 2H5", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65439630500274, | |
"lng": -79.38650010906946 | |
} | |
], | |
"lat": 43.65439630500274, | |
"lng": -79.38650010906946, | |
"postalCode": "M5G 2H5", | |
"state": "ON" | |
}, | |
"name": "Textile Museum of Canada", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
}, | |
"venuePage": { | |
"id": "56305293" | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-56ccd5cfcd1069ca160a797e-11", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/tearoom_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1dc931735", | |
"name": "Tea Room", | |
"pluralName": "Tea Rooms", | |
"primary": true, | |
"shortName": "Tea Room" | |
} | |
], | |
"id": "56ccd5cfcd1069ca160a797e", | |
"location": { | |
"address": "147 Dundas St W", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Elizabeth St", | |
"distance": 239, | |
"formattedAddress": [ | |
"147 Dundas St W (at Elizabeth St)", | |
"Toronto ON M5G 1P5", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65537430780922, | |
"lng": -79.38535434742991 | |
} | |
], | |
"lat": 43.65537430780922, | |
"lng": -79.38535434742991, | |
"postalCode": "M5G 1P5", | |
"state": "ON" | |
}, | |
"name": "Tsujiri", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4bd0b30d41b9ef3b8fa0fae5-12", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/beauty_cosmetic_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d10c951735", | |
"name": "Cosmetics Shop", | |
"pluralName": "Cosmetics Shops", | |
"primary": true, | |
"shortName": "Cosmetics" | |
} | |
], | |
"id": "4bd0b30d41b9ef3b8fa0fae5", | |
"location": { | |
"address": "220 Yonge St, Unit B215-A", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "in Toronto Eaton Centre", | |
"distance": 284, | |
"formattedAddress": [ | |
"220 Yonge St, Unit B215-A (in Toronto Eaton Centre)", | |
"Toronto ON M5B 2H1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.653557, | |
"lng": -79.3804 | |
} | |
], | |
"lat": 43.653557, | |
"lng": -79.3804, | |
"postalCode": "M5B 2H1", | |
"state": "ON" | |
}, | |
"name": "LUSH", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-54132b3b498ee9ca9332e189-13", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/coffeeshop_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1e0931735", | |
"name": "Coffee Shop", | |
"pluralName": "Coffee Shops", | |
"primary": true, | |
"shortName": "Coffee Shop" | |
} | |
], | |
"id": "54132b3b498ee9ca9332e189", | |
"location": { | |
"address": "C24 - 123 Queen St W", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 253, | |
"formattedAddress": [ | |
"C24 - 123 Queen St W", | |
"Toronto ON", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65121797253777, | |
"lng": -79.38355459932247 | |
} | |
], | |
"lat": 43.65121797253777, | |
"lng": -79.38355459932247, | |
"state": "ON" | |
}, | |
"name": "M Square Coffee Co", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ae5df5af964a520c4a221e3-14", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/building/default_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d124941735", | |
"name": "Office", | |
"pluralName": "Offices", | |
"primary": true, | |
"shortName": "Office" | |
} | |
], | |
"id": "4ae5df5af964a520c4a221e3", | |
"location": { | |
"address": "483 Bay St.", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Albert St.", | |
"distance": 117, | |
"formattedAddress": [ | |
"483 Bay St. (at Albert St.)", | |
"Toronto ON M5G 2C9", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65347479872822, | |
"lng": -79.38246987630343 | |
} | |
], | |
"lat": 43.65347479872822, | |
"lng": -79.38246987630343, | |
"postalCode": "M5G 2C9", | |
"state": "ON" | |
}, | |
"name": "Bell Trinity Square", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-504bbf2ce4b0168121235cbe-15", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/ramen_", | |
"suffix": ".png" | |
}, | |
"id": "55a59bace4b013909087cb24", | |
"name": "Ramen Restaurant", | |
"pluralName": "Ramen Restaurants", | |
"primary": true, | |
"shortName": "Ramen" | |
} | |
], | |
"id": "504bbf2ce4b0168121235cbe", | |
"location": { | |
"address": "179 Dundas St. W", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "btwn Centre Ave. & Chestnut St.", | |
"distance": 278, | |
"formattedAddress": [ | |
"179 Dundas St. W (btwn Centre Ave. & Chestnut St.)", | |
"Toronto ON M5G 1Z8", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.655157467561246, | |
"lng": -79.38650067479335 | |
} | |
], | |
"lat": 43.655157467561246, | |
"lng": -79.38650067479335, | |
"postalCode": "M5G 1Z8", | |
"state": "ON" | |
}, | |
"name": "Sansotei Ramen 三草亭", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4e5d8181a8092f63968617ee-16", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/fastfood_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d16e941735", | |
"name": "Fast Food Restaurant", | |
"pluralName": "Fast Food Restaurants", | |
"primary": true, | |
"shortName": "Fast Food" | |
} | |
], | |
"id": "4e5d8181a8092f63968617ee", | |
"location": { | |
"address": "220 Yonge St.", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 271, | |
"formattedAddress": [ | |
"220 Yonge St.", | |
"Toronto ON M5B 2H1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.654536488277245, | |
"lng": -79.38088885547485 | |
} | |
], | |
"lat": 43.654536488277245, | |
"lng": -79.38088885547485, | |
"postalCode": "M5B 2H1", | |
"state": "ON" | |
}, | |
"name": "Crepe Delicious", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
}, | |
"venuePage": { | |
"id": "48449575" | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-57eda381498ebe0e6ef40972-17", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/apparel_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d103951735", | |
"name": "Clothing Store", | |
"pluralName": "Clothing Stores", | |
"primary": true, | |
"shortName": "Apparel" | |
} | |
], | |
"id": "57eda381498ebe0e6ef40972", | |
"location": { | |
"address": "220 Yonge St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Dundas St W", | |
"distance": 378, | |
"formattedAddress": [ | |
"220 Yonge St (at Dundas St W)", | |
"Toronto ON M5B 2H1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65591027779457, | |
"lng": -79.38064099181345 | |
} | |
], | |
"lat": 43.65591027779457, | |
"lng": -79.38064099181345, | |
"neighborhood": "Downtown Toronto", | |
"postalCode": "M5B 2H1", | |
"state": "ON" | |
}, | |
"name": "UNIQLO ユニクロ", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-5479da4f498e8569fb44985c-18", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/default_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1ff941735", | |
"name": "Miscellaneous Shop", | |
"pluralName": "Miscellaneous Shops", | |
"primary": true, | |
"shortName": "Shop" | |
} | |
], | |
"id": "5479da4f498e8569fb44985c", | |
"location": { | |
"address": "595 Bay St E", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Dundas St W", | |
"distance": 287, | |
"formattedAddress": [ | |
"595 Bay St E (at Dundas St W)", | |
"Toronto ON", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.656024, | |
"lng": -79.383284 | |
} | |
], | |
"lat": 43.656024, | |
"lng": -79.383284, | |
"state": "ON" | |
}, | |
"name": "MUJI", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-57d1e1a2498e96cce6f32217-19", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/apparel_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d103951735", | |
"name": "Clothing Store", | |
"pluralName": "Clothing Stores", | |
"primary": true, | |
"shortName": "Apparel" | |
} | |
], | |
"id": "57d1e1a2498e96cce6f32217", | |
"location": { | |
"address": "260 Yonge Street", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 295, | |
"formattedAddress": [ | |
"260 Yonge Street", | |
"Toronto ON M5B 2L9", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.655041, | |
"lng": -79.3809665 | |
} | |
], | |
"lat": 43.655041, | |
"lng": -79.3809665, | |
"postalCode": "M5B 2L9", | |
"state": "ON" | |
}, | |
"name": "Nordstrom", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ad4c062f964a520e5f720e3-20", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/arts_entertainment/musicvenue_", | |
"suffix": ".png" | |
}, | |
"id": "5032792091d4c4b30a586d5c", | |
"name": "Concert Hall", | |
"pluralName": "Concert Halls", | |
"primary": true, | |
"shortName": "Concert Hall" | |
} | |
], | |
"id": "4ad4c062f964a520e5f720e3", | |
"location": { | |
"address": "145 Queen St. W", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at University Ave.", | |
"distance": 355, | |
"formattedAddress": [ | |
"145 Queen St. W (at University Ave.)", | |
"Toronto ON M5H 4G1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.650592, | |
"lng": -79.385806 | |
} | |
], | |
"lat": 43.650592, | |
"lng": -79.385806, | |
"postalCode": "M5H 4G1", | |
"state": "ON" | |
}, | |
"name": "Four Seasons Centre for the Performing Arts", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-52ce14b0498e50457ce11780-21", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/travel/hotel_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1fa931735", | |
"name": "Hotel", | |
"pluralName": "Hotels", | |
"primary": true, | |
"shortName": "Hotel" | |
} | |
], | |
"id": "52ce14b0498e50457ce11780", | |
"location": { | |
"address": "108 Chestnut Street", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "Dundas St W", | |
"distance": 204, | |
"formattedAddress": [ | |
"108 Chestnut Street (Dundas St W)", | |
"Toronto ON M5G 1R3", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.6546083, | |
"lng": -79.3859415 | |
} | |
], | |
"lat": 43.6546083, | |
"lng": -79.3859415, | |
"postalCode": "M5G 1R3", | |
"state": "ON" | |
}, | |
"name": "DoubleTree by Hilton", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4adf85e1f964a5206e7b21e3-22", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/departmentstore_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1f6941735", | |
"name": "Department Store", | |
"pluralName": "Department Stores", | |
"primary": true, | |
"shortName": "Department Store" | |
} | |
], | |
"id": "4adf85e1f964a5206e7b21e3", | |
"location": { | |
"address": "176 Yonge St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "Queen St W", | |
"distance": 327, | |
"formattedAddress": [ | |
"176 Yonge St (Queen St W)", | |
"Toronto ON M5C 2L7", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.652039815876805, | |
"lng": -79.38039146122816 | |
} | |
], | |
"lat": 43.652039815876805, | |
"lng": -79.38039146122816, | |
"postalCode": "M5C 2L7", | |
"state": "ON" | |
}, | |
"name": "Hudson's Bay", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ad788c8f964a520e40b21e3-23", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/technology_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d122951735", | |
"name": "Electronics Store", | |
"pluralName": "Electronics Stores", | |
"primary": true, | |
"shortName": "Electronics" | |
} | |
], | |
"id": "4ad788c8f964a520e40b21e3", | |
"location": { | |
"address": "220 Yonge St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "Queen St W", | |
"distance": 271, | |
"formattedAddress": [ | |
"220 Yonge St (Queen St W)", | |
"Toronto ON M5B 2H1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.6529455, | |
"lng": -79.3806448 | |
} | |
], | |
"lat": 43.6529455, | |
"lng": -79.3806448, | |
"postalCode": "M5B 2H1", | |
"state": "ON" | |
}, | |
"name": "Apple Eaton Centre", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4b40f62ef964a52050be25e3-24", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/apparel_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d103951735", | |
"name": "Clothing Store", | |
"pluralName": "Clothing Stores", | |
"primary": true, | |
"shortName": "Apparel" | |
} | |
], | |
"id": "4b40f62ef964a52050be25e3", | |
"location": { | |
"address": "220 Yonge Street, Unit C 32", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 297, | |
"formattedAddress": [ | |
"220 Yonge Street, Unit C 32", | |
"Toronto ON M5B 2H1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65361341708363, | |
"lng": -79.38024401664734 | |
} | |
], | |
"lat": 43.65361341708363, | |
"lng": -79.38024401664734, | |
"neighborhood": "Downtown Yonge", | |
"postalCode": "M5B 2H1", | |
"state": "ON" | |
}, | |
"name": "Roots", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ad69511f964a520e40721e3-25", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/default_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1c4941735", | |
"name": "Restaurant", | |
"pluralName": "Restaurants", | |
"primary": true, | |
"shortName": "Restaurant" | |
} | |
], | |
"id": "4ad69511f964a520e40721e3", | |
"location": { | |
"address": "165 York St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "btwn Richmond St. & Adelaide St.", | |
"distance": 389, | |
"formattedAddress": [ | |
"165 York St (btwn Richmond St. & Adelaide St.)", | |
"Toronto ON M5H 3R8", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.64998659318569, | |
"lng": -79.38410336664538 | |
} | |
], | |
"lat": 43.64998659318569, | |
"lng": -79.38410336664538, | |
"postalCode": "M5H 3R8", | |
"state": "ON" | |
}, | |
"name": "The Keg Steakhouse + Bar - York Street", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-50ecb1fae4b0beb13294f0aa-26", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/seafood_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1ce941735", | |
"name": "Seafood Restaurant", | |
"pluralName": "Seafood Restaurants", | |
"primary": true, | |
"shortName": "Seafood" | |
} | |
], | |
"id": "50ecb1fae4b0beb13294f0aa", | |
"location": { | |
"address": "56 Temperance Street", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 365, | |
"formattedAddress": [ | |
"56 Temperance Street", | |
"Toronto ON M5H 3V5", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65065642537144, | |
"lng": -79.38161285228475 | |
} | |
], | |
"lat": 43.65065642537144, | |
"lng": -79.38161285228475, | |
"postalCode": "M5H 3V5", | |
"state": "ON" | |
}, | |
"name": "John & Sons Oyster House", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
}, | |
"venuePage": { | |
"id": "122923005" | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-506db1a9e4b0a3f3b31412f0-27", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/default_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d14e941735", | |
"name": "American Restaurant", | |
"pluralName": "American Restaurants", | |
"primary": true, | |
"shortName": "American" | |
} | |
], | |
"id": "506db1a9e4b0a3f3b31412f0", | |
"location": { | |
"address": "1 Richmond Street West", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "Yonge Street", | |
"distance": 432, | |
"formattedAddress": [ | |
"1 Richmond Street West (Yonge Street)", | |
"Toronto ON", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65156872562108, | |
"lng": -79.37926594000328 | |
} | |
], | |
"lat": 43.65156872562108, | |
"lng": -79.37926594000328, | |
"state": "ON" | |
}, | |
"name": "Richmond Station", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-5a43c3ddacb00b66ac2ee7d8-28", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/technology_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d122951735", | |
"name": "Electronics Store", | |
"pluralName": "Electronics Stores", | |
"primary": true, | |
"shortName": "Electronics" | |
} | |
], | |
"id": "5a43c3ddacb00b66ac2ee7d8", | |
"location": { | |
"address": "Toronto Eaton Centre", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 337, | |
"formattedAddress": [ | |
"Toronto Eaton Centre", | |
"Toronto ON M5B", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65564777812532, | |
"lng": -79.3810108074576 | |
} | |
], | |
"lat": 43.65564777812532, | |
"lng": -79.3810108074576, | |
"postalCode": "M5B", | |
"state": "ON" | |
}, | |
"name": "Samsung Experience Store (Eaton Centre)", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ad4c062f964a520b5f720e3-29", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/arts_entertainment/performingarts_theater_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d137941735", | |
"name": "Theater", | |
"pluralName": "Theaters", | |
"primary": true, | |
"shortName": "Theater" | |
} | |
], | |
"id": "4ad4c062f964a520b5f720e3", | |
"location": { | |
"address": "189 Yonge St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "btwn Queen St E & Shuter St", | |
"distance": 437, | |
"formattedAddress": [ | |
"189 Yonge St (btwn Queen St E & Shuter St)", | |
"Toronto ON M5B 2H1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.653393796019586, | |
"lng": -79.3785073962175 | |
} | |
], | |
"lat": 43.653393796019586, | |
"lng": -79.3785073962175, | |
"postalCode": "M5B 2H1", | |
"state": "ON" | |
}, | |
"name": "Elgin And Winter Garden Theatres", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ad8cd16f964a520c91421e3-30", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/parks_outdoors/plaza_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d164941735", | |
"name": "Plaza", | |
"pluralName": "Plazas", | |
"primary": true, | |
"shortName": "Plaza" | |
} | |
], | |
"id": "4ad8cd16f964a520c91421e3", | |
"location": { | |
"address": "1 Dundas St E", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Yonge St", | |
"distance": 398, | |
"formattedAddress": [ | |
"1 Dundas St E (at Yonge St)", | |
"Toronto ON M5B 2R8", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65605389742188, | |
"lng": -79.38049504264389 | |
} | |
], | |
"lat": 43.65605389742188, | |
"lng": -79.38049504264389, | |
"postalCode": "M5B 2R8", | |
"state": "ON" | |
}, | |
"name": "Yonge-Dundas Square", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
}, | |
"venuePage": { | |
"id": "68861986" | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-5aff06ca6e4650002cc6286b-31", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/vegetarian_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1d3941735", | |
"name": "Vegetarian / Vegan Restaurant", | |
"pluralName": "Vegetarian / Vegan Restaurants", | |
"primary": true, | |
"shortName": "Vegetarian / Vegan" | |
} | |
], | |
"id": "5aff06ca6e4650002cc6286b", | |
"location": { | |
"address": "133 Richmond St W", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 372, | |
"formattedAddress": [ | |
"133 Richmond St W", | |
"Toronto ON M5H 2L2", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.650252483069295, | |
"lng": -79.38515575620075 | |
} | |
], | |
"lat": 43.650252483069295, | |
"lng": -79.38515575620075, | |
"postalCode": "M5H 2L2", | |
"state": "ON" | |
}, | |
"name": "Rosalinda", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4b749e98f964a5202ce82de3-32", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/beauty_cosmetic_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d10c951735", | |
"name": "Cosmetics Shop", | |
"pluralName": "Cosmetics Shops", | |
"primary": true, | |
"shortName": "Cosmetics" | |
} | |
], | |
"id": "4b749e98f964a5202ce82de3", | |
"location": { | |
"address": "220 Yonge Street, Space #3-131", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "in Toronto Eaton Centre", | |
"distance": 304, | |
"formattedAddress": [ | |
"220 Yonge Street, Space #3-131 (in Toronto Eaton Centre)", | |
"Toronto ON M5B 2H1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.6535272, | |
"lng": -79.3801543 | |
} | |
], | |
"lat": 43.6535272, | |
"lng": -79.3801543, | |
"postalCode": "M5B 2H1", | |
"state": "ON" | |
}, | |
"name": "SEPHORA", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4af72034f964a5202b0622e3-33", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/furniture_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1f8941735", | |
"name": "Furniture / Home Store", | |
"pluralName": "Furniture / Home Stores", | |
"primary": true, | |
"shortName": "Furniture / Home" | |
} | |
], | |
"id": "4af72034f964a5202b0622e3", | |
"location": { | |
"address": "195 Yonge Street", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Queen St E", | |
"distance": 364, | |
"formattedAddress": [ | |
"195 Yonge Street (at Queen St E)", | |
"Toronto ON M5B 1M4", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.6530533, | |
"lng": -79.3794496 | |
} | |
], | |
"lat": 43.6530533, | |
"lng": -79.3794496, | |
"postalCode": "M5B 1M4", | |
"state": "ON" | |
}, | |
"name": "HomeSense", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-5a32970da42362290203a9d6-34", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/food_foodcourt_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d120951735", | |
"name": "Food Court", | |
"pluralName": "Food Courts", | |
"primary": true, | |
"shortName": "Food Court" | |
} | |
], | |
"id": "5a32970da42362290203a9d6", | |
"location": { | |
"address": "111 Richmond St W", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "btwn York & Bay St", | |
"distance": 325, | |
"formattedAddress": [ | |
"111 Richmond St W (btwn York & Bay St)", | |
"Toronto ON M5H 2G4", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.650578865093934, | |
"lng": -79.3834119303614 | |
} | |
], | |
"lat": 43.650578865093934, | |
"lng": -79.3834119303614, | |
"neighborhood": "Financial District", | |
"postalCode": "M5H 2G4", | |
"state": "ON" | |
}, | |
"name": "Assembly Chef's Hall", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-522a616311d2b982aa3b8111-35", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/toys_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1f3941735", | |
"name": "Toy / Game Store", | |
"pluralName": "Toy / Game Stores", | |
"primary": true, | |
"shortName": "Toys & Games" | |
} | |
], | |
"id": "522a616311d2b982aa3b8111", | |
"location": { | |
"address": "220 Yonge Street", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "Eaton Centre", | |
"distance": 233, | |
"formattedAddress": [ | |
"220 Yonge Street (Eaton Centre)", | |
"Toronto ON M5B 2H1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.654248, | |
"lng": -79.381232 | |
} | |
], | |
"lat": 43.654248, | |
"lng": -79.381232, | |
"postalCode": "M5B 2H1", | |
"state": "ON" | |
}, | |
"name": "Disney Store", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4b844f98f964a520fe2d31e3-36", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/apparel_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d103951735", | |
"name": "Clothing Store", | |
"pluralName": "Clothing Stores", | |
"primary": true, | |
"shortName": "Apparel" | |
} | |
], | |
"id": "4b844f98f964a520fe2d31e3", | |
"location": { | |
"address": "220 Yonge Street", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "in Toronto Eaton Centre", | |
"distance": 284, | |
"formattedAddress": [ | |
"220 Yonge Street (in Toronto Eaton Centre)", | |
"Toronto ON M5B 2H1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65291548392747, | |
"lng": -79.38049525090148 | |
} | |
], | |
"lat": 43.65291548392747, | |
"lng": -79.38049525090148, | |
"postalCode": "M5B 2H1", | |
"state": "ON" | |
}, | |
"name": "Abercrombie & Fitch", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ad4c062f964a520c5f720e3-37", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/arts_entertainment/performingarts_theater_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d137941735", | |
"name": "Theater", | |
"pluralName": "Theaters", | |
"primary": true, | |
"shortName": "Theater" | |
} | |
], | |
"id": "4ad4c062f964a520c5f720e3", | |
"location": { | |
"address": "244 Victoria St.", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "btwn Dundas St E and Shuter St", | |
"distance": 380, | |
"formattedAddress": [ | |
"244 Victoria St. (btwn Dundas St E and Shuter St)", | |
"Toronto ON M5B 1V8", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.655101567321054, | |
"lng": -79.37976762131545 | |
} | |
], | |
"lat": 43.655101567321054, | |
"lng": -79.37976762131545, | |
"postalCode": "M5B 1V8", | |
"state": "ON" | |
}, | |
"name": "Ed Mirvish Theatre", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4dc16c718877c00d6ad7f2a6-38", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/financial_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d10a951735", | |
"name": "Bank", | |
"pluralName": "Banks", | |
"primary": true, | |
"shortName": "Bank" | |
} | |
], | |
"id": "4dc16c718877c00d6ad7f2a6", | |
"location": { | |
"address": "221 Yonge Street", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Shuter St", | |
"distance": 343, | |
"formattedAddress": [ | |
"221 Yonge Street (at Shuter St)", | |
"Toronto ON M5B 1M4", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.653936903308185, | |
"lng": -79.37972202364307 | |
} | |
], | |
"lat": 43.653936903308185, | |
"lng": -79.37972202364307, | |
"postalCode": "M5B 1M4", | |
"state": "ON" | |
}, | |
"name": "Tangerine Café", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
}, | |
"venuePage": { | |
"id": "34282013" | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ad4c062f964a5200bf820e3-39", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/comic_", | |
"suffix": ".png" | |
}, | |
"id": "52f2ab2ebcbc57f1066b8b18", | |
"name": "Comic Shop", | |
"pluralName": "Comic Shops", | |
"primary": true, | |
"shortName": "Comic Shop" | |
} | |
], | |
"id": "4ad4c062f964a5200bf820e3", | |
"location": { | |
"address": "329 Yonge St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Dundas St E", | |
"distance": 444, | |
"formattedAddress": [ | |
"329 Yonge St (at Dundas St E)", | |
"Toronto ON M5B 1R7", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65703137958407, | |
"lng": -79.38140310220501 | |
} | |
], | |
"lat": 43.65703137958407, | |
"lng": -79.38140310220501, | |
"postalCode": "M5B 1R7", | |
"state": "ON" | |
}, | |
"name": "Silver Snail Comics", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ba5208ff964a520f5e038e3-40", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/tanning_salon_", | |
"suffix": ".png" | |
}, | |
"id": "4d1cf8421a97d635ce361c31", | |
"name": "Tanning Salon", | |
"pluralName": "Tanning Salons", | |
"primary": true, | |
"shortName": "Tanning Salon" | |
} | |
], | |
"id": "4ba5208ff964a520f5e038e3", | |
"location": { | |
"address": "239 Yonge St.", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "Shuter", | |
"distance": 328, | |
"formattedAddress": [ | |
"239 Yonge St. (Shuter)", | |
"Toronto ON M5B 1N8", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.654734082347616, | |
"lng": -79.38024826065258 | |
} | |
], | |
"lat": 43.654734082347616, | |
"lng": -79.38024826065258, | |
"postalCode": "M5B 1N8", | |
"state": "ON" | |
}, | |
"name": "Solei Tanning Salon", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
}, | |
"venuePage": { | |
"id": "98199950" | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4df909dfe4cd2129701c0690-41", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/newamerican_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d157941735", | |
"name": "New American Restaurant", | |
"pluralName": "New American Restaurants", | |
"primary": true, | |
"shortName": "New American" | |
} | |
], | |
"id": "4df909dfe4cd2129701c0690", | |
"location": { | |
"address": "1 Dundas St W", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 334, | |
"formattedAddress": [ | |
"1 Dundas St W", | |
"Toronto ON M5G 1Z3", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.6560936540828, | |
"lng": -79.38187792357716 | |
} | |
], | |
"lat": 43.6560936540828, | |
"lng": -79.38187792357716, | |
"postalCode": "M5G 1Z3", | |
"state": "ON" | |
}, | |
"name": "JOEY Eaton Centre", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-5894c1f9266c1121f0a757d1-42", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/nightlife/pub_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d116941735", | |
"name": "Bar", | |
"pluralName": "Bars", | |
"primary": true, | |
"shortName": "Bar" | |
} | |
], | |
"id": "5894c1f9266c1121f0a757d1", | |
"location": { | |
"address": "70 Temperance Street", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 362, | |
"formattedAddress": [ | |
"70 Temperance Street", | |
"Toronto ON M5H 0B1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65055725249405, | |
"lng": -79.38195634640063 | |
} | |
], | |
"lat": 43.65055725249405, | |
"lng": -79.38195634640063, | |
"postalCode": "M5H 0B1", | |
"state": "ON" | |
}, | |
"name": "Boxcar Social Temperance", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4e91f9b546908c033fb57c50-43", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/apparel_women_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d108951735", | |
"name": "Women's Store", | |
"pluralName": "Women's Stores", | |
"primary": true, | |
"shortName": "Women's Store" | |
} | |
], | |
"id": "4e91f9b546908c033fb57c50", | |
"location": { | |
"address": "176 Yonge St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "in the Bay", | |
"distance": 328, | |
"formattedAddress": [ | |
"176 Yonge St (in the Bay)", | |
"Toronto ON M5C 2L7", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65225092432807, | |
"lng": -79.3802210071282 | |
} | |
], | |
"lat": 43.65225092432807, | |
"lng": -79.3802210071282, | |
"postalCode": "M5C 2L7", | |
"state": "ON" | |
}, | |
"name": "Topshop", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ab2b0b9f964a520e56b20e3-44", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/gastropub_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d155941735", | |
"name": "Gastropub", | |
"pluralName": "Gastropubs", | |
"primary": true, | |
"shortName": "Gastropub" | |
} | |
], | |
"id": "4ab2b0b9f964a520e56b20e3", | |
"location": { | |
"address": "35 Elm St.", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Bay St.", | |
"distance": 445, | |
"formattedAddress": [ | |
"35 Elm St. (at Bay St.)", | |
"Toronto ON M5G 1H1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65747228208784, | |
"lng": -79.38352412327917 | |
} | |
], | |
"lat": 43.65747228208784, | |
"lng": -79.38352412327917, | |
"postalCode": "M5G 1H1", | |
"state": "ON" | |
}, | |
"name": "The Queen and Beaver Public House", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4bd8cde92e6f0f47dcb20808-45", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/steakhouse_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1cc941735", | |
"name": "Steakhouse", | |
"pluralName": "Steakhouses", | |
"primary": true, | |
"shortName": "Steakhouse" | |
} | |
], | |
"id": "4bd8cde92e6f0f47dcb20808", | |
"location": { | |
"address": "120 Adelaide St. W", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at York St", | |
"distance": 450, | |
"formattedAddress": [ | |
"120 Adelaide St. W (at York St)", | |
"Toronto ON M5H 1T1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.649504756476944, | |
"lng": -79.38291850488223 | |
} | |
], | |
"lat": 43.649504756476944, | |
"lng": -79.38291850488223, | |
"postalCode": "M5H 1T1", | |
"state": "ON" | |
}, | |
"name": "Hy's Steakhouse", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-539c6f13498e06f4cc765165-46", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/default_", | |
"suffix": ".png" | |
}, | |
"id": "52e81612bcbc57f1066b79f9", | |
"name": "Modern European Restaurant", | |
"pluralName": "Modern European Restaurants", | |
"primary": true, | |
"shortName": "Modern European" | |
} | |
], | |
"id": "539c6f13498e06f4cc765165", | |
"location": { | |
"address": "43 Elm St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "Bay", | |
"distance": 436, | |
"formattedAddress": [ | |
"43 Elm St (Bay)", | |
"Toronto ON M5G 1H1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65739749535259, | |
"lng": -79.38376054171513 | |
} | |
], | |
"lat": 43.65739749535259, | |
"lng": -79.38376054171513, | |
"postalCode": "M5G 1H1", | |
"state": "ON" | |
}, | |
"name": "The Elm Tree Restaurant", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
}, | |
"venuePage": { | |
"id": "88534436" | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-5615b6c4498e3c32c67ad78f-47", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/pizza_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1ca941735", | |
"name": "Pizza Place", | |
"pluralName": "Pizza Places", | |
"primary": true, | |
"shortName": "Pizza" | |
} | |
], | |
"id": "5615b6c4498e3c32c67ad78f", | |
"location": { | |
"address": "10 Dundas Street East, #124", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 462, | |
"formattedAddress": [ | |
"10 Dundas Street East, #124", | |
"Toronto ON M5B 2G9", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.656518, | |
"lng": -79.380015 | |
} | |
], | |
"lat": 43.656518, | |
"lng": -79.380015, | |
"postalCode": "M5B 2G9", | |
"state": "ON" | |
}, | |
"name": "Blaze Pizza", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ea43642be7ba4918efc5afa-48", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/building/gym_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d175941735", | |
"name": "Gym / Fitness Center", | |
"pluralName": "Gyms or Fitness Centers", | |
"primary": true, | |
"shortName": "Gym / Fitness" | |
} | |
], | |
"id": "4ea43642be7ba4918efc5afa", | |
"location": { | |
"address": "1 First Canadian Place", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 495, | |
"formattedAddress": [ | |
"1 First Canadian Place", | |
"Toronto ON M5X 1C8", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.64927944291712, | |
"lng": -79.38192123284551 | |
} | |
], | |
"lat": 43.64927944291712, | |
"lng": -79.38192123284551, | |
"postalCode": "M5X 1C8", | |
"state": "ON" | |
}, | |
"name": "Adelaide Club Toronto", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-5214e7c111d2a83379eae21f-49", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/newamerican_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d157941735", | |
"name": "New American Restaurant", | |
"pluralName": "New American Restaurants", | |
"primary": true, | |
"shortName": "New American" | |
} | |
], | |
"id": "5214e7c111d2a83379eae21f", | |
"location": { | |
"address": "10 Temperance St fl 5", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "Yonge St", | |
"distance": 459, | |
"formattedAddress": [ | |
"10 Temperance St fl 5 (Yonge St)", | |
"Toronto ON M5H 1Y4", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.650951982093595, | |
"lng": -79.37942201983014 | |
} | |
], | |
"lat": 43.650951982093595, | |
"lng": -79.37942201983014, | |
"postalCode": "M5H 1Y4", | |
"state": "ON" | |
}, | |
"name": "The Chase", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4afc79c8f964a520182322e3-50", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/apparel_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d103951735", | |
"name": "Clothing Store", | |
"pluralName": "Clothing Stores", | |
"primary": true, | |
"shortName": "Apparel" | |
} | |
], | |
"id": "4afc79c8f964a520182322e3", | |
"location": { | |
"address": "2G-211 Yonge Street", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "Shuter", | |
"distance": 338, | |
"formattedAddress": [ | |
"2G-211 Yonge Street (Shuter)", | |
"Toronto ON", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65374158228865, | |
"lng": -79.37974523881418 | |
} | |
], | |
"lat": 43.65374158228865, | |
"lng": -79.37974523881418, | |
"state": "ON" | |
}, | |
"name": "Magic Tailor", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4adbbae6f964a520402a21e3-51", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/arts_entertainment/movietheater_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d17f941735", | |
"name": "Movie Theater", | |
"pluralName": "Movie Theaters", | |
"primary": true, | |
"shortName": "Movie Theater" | |
} | |
], | |
"events": { | |
"count": 3, | |
"summary": "3 movies" | |
}, | |
"id": "4adbbae6f964a520402a21e3", | |
"location": { | |
"address": "10 Dundas St E", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Yonge St", | |
"distance": 410, | |
"formattedAddress": [ | |
"10 Dundas St E (at Yonge St)", | |
"Toronto ON M5B 2G9", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65612555948613, | |
"lng": -79.38039005666784 | |
} | |
], | |
"lat": 43.65612555948613, | |
"lng": -79.38039005666784, | |
"postalCode": "M5B 2G9", | |
"state": "ON" | |
}, | |
"name": "Cineplex Cinemas", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4b6609b3f964a5200c102be3-52", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/travel/default_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1f6931735", | |
"name": "General Travel", | |
"pluralName": "General Travel", | |
"primary": true, | |
"shortName": "Travel" | |
} | |
], | |
"id": "4b6609b3f964a5200c102be3", | |
"location": { | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "btwn John St., Yonge St., Elm St. and Front St.", | |
"distance": 404, | |
"formattedAddress": [ | |
"All Around Downtown Toronto (btwn John St., Yonge St., Elm St. and Front St.)", | |
"Toronto ON", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.64990340698978, | |
"lng": -79.3830527039004 | |
} | |
], | |
"lat": 43.64990340698978, | |
"lng": -79.3830527039004, | |
"state": "ON" | |
}, | |
"name": "Toronto PATH System", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-514cc159e4b0e4f73af4eced-53", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/arts_entertainment/musicvenue_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1e5931735", | |
"name": "Music Venue", | |
"pluralName": "Music Venues", | |
"primary": true, | |
"shortName": "Music Venue" | |
} | |
], | |
"id": "514cc159e4b0e4f73af4eced", | |
"location": { | |
"address": "251 Victoria St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "btwn Dundas St. E & Shuter St.", | |
"distance": 447, | |
"formattedAddress": [ | |
"251 Victoria St (btwn Dundas St. E & Shuter St.)", | |
"Toronto ON M5B 1T8", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65567828473835, | |
"lng": -79.37927565514764 | |
} | |
], | |
"lat": 43.65567828473835, | |
"lng": -79.37927565514764, | |
"postalCode": "M5B 1T8", | |
"state": "ON" | |
}, | |
"name": "Jazz Bistro", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
}, | |
"venuePage": { | |
"id": "424851737" | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4c9cd4d37c096dcb9034c5d1-54", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/middleeastern_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d115941735", | |
"name": "Middle Eastern Restaurant", | |
"pluralName": "Middle Eastern Restaurants", | |
"primary": true, | |
"shortName": "Middle Eastern" | |
} | |
], | |
"id": "4c9cd4d37c096dcb9034c5d1", | |
"location": { | |
"address": "253 Yonge St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "btwn Dundas St E & Shuter St", | |
"distance": 343, | |
"formattedAddress": [ | |
"253 Yonge St (btwn Dundas St E & Shuter St)", | |
"Toronto ON M5B 1N8", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65502870847598, | |
"lng": -79.38024513018975 | |
} | |
], | |
"lat": 43.65502870847598, | |
"lng": -79.38024513018975, | |
"postalCode": "M5B 1N8", | |
"state": "ON" | |
}, | |
"name": "Paramount Fine Foods", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-55fc571f498ec35023360858-55", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/default_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d14e941735", | |
"name": "American Restaurant", | |
"pluralName": "American Restaurants", | |
"primary": true, | |
"shortName": "American" | |
} | |
], | |
"id": "55fc571f498ec35023360858", | |
"location": { | |
"address": "77 Adelaide St W", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "btwn Bay & York St", | |
"distance": 473, | |
"formattedAddress": [ | |
"77 Adelaide St W (btwn Bay & York St)", | |
"Toronto ON M5X 1C1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.6495520142626, | |
"lng": -79.38167072512041 | |
} | |
], | |
"lat": 43.6495520142626, | |
"lng": -79.38167072512041, | |
"postalCode": "M5X 1C1", | |
"state": "ON" | |
}, | |
"name": "Cactus Club Cafe", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4f513029e4b07c3382c9fdb9-56", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/cafe_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d16d941735", | |
"name": "Café", | |
"pluralName": "Cafés", | |
"primary": true, | |
"shortName": "Café" | |
} | |
], | |
"id": "4f513029e4b07c3382c9fdb9", | |
"location": { | |
"address": "250 Dundas Street West", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "Simcoe Street", | |
"distance": 460, | |
"formattedAddress": [ | |
"250 Dundas Street West (Simcoe Street)", | |
"Toronto ON M5T 2Z5", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65457125894357, | |
"lng": -79.38944976536852 | |
} | |
], | |
"lat": 43.65457125894357, | |
"lng": -79.38944976536852, | |
"postalCode": "M5T 2Z5", | |
"state": "ON" | |
}, | |
"name": "Cafe Plenty", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4c057c32d3842d7fd03fbe41-57", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/coffeeshop_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1e0931735", | |
"name": "Coffee Shop", | |
"pluralName": "Coffee Shops", | |
"primary": true, | |
"shortName": "Coffee Shop" | |
} | |
], | |
"id": "4c057c32d3842d7fd03fbe41", | |
"location": { | |
"address": "65 Dundas St. W, Unit 303", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Bay St.", | |
"distance": 294, | |
"formattedAddress": [ | |
"65 Dundas St. W, Unit 303 (at Bay St.)", | |
"Toronto ON M5G 2C5", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65596912045543, | |
"lng": -79.38268426666406 | |
} | |
], | |
"lat": 43.65596912045543, | |
"lng": -79.38268426666406, | |
"postalCode": "M5G 2C5", | |
"state": "ON" | |
}, | |
"name": "Starbucks", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-5a62412b1108ba191da5ba06-58", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/japanese_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d111941735", | |
"name": "Japanese Restaurant", | |
"pluralName": "Japanese Restaurants", | |
"primary": true, | |
"shortName": "Japanese" | |
} | |
], | |
"id": "5a62412b1108ba191da5ba06", | |
"location": { | |
"address": "655 Bay Street", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "( Bay st & Elm st)", | |
"distance": 443, | |
"formattedAddress": [ | |
"655 Bay Street (( Bay st & Elm st))", | |
"Toronto ON M5G 1Z4", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65745745164475, | |
"lng": -79.38419169987876 | |
} | |
], | |
"lat": 43.65745745164475, | |
"lng": -79.38419169987876, | |
"postalCode": "M5G 1Z4", | |
"state": "ON" | |
}, | |
"name": "KAKA", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4e88e0d1d3e39d6f4e81a1dd-59", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/apparel_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d103951735", | |
"name": "Clothing Store", | |
"pluralName": "Clothing Stores", | |
"primary": true, | |
"shortName": "Apparel" | |
} | |
], | |
"id": "4e88e0d1d3e39d6f4e81a1dd", | |
"location": { | |
"address": "176 Yonge St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Queen St", | |
"distance": 342, | |
"formattedAddress": [ | |
"176 Yonge St (at Queen St)", | |
"Toronto ON", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.652281488745565, | |
"lng": -79.38001554865625 | |
} | |
], | |
"lat": 43.652281488745565, | |
"lng": -79.38001554865625, | |
"state": "ON" | |
}, | |
"name": "Topman", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ad7929cf964a520500c21e3-60", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/diner_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d147941735", | |
"name": "Diner", | |
"pluralName": "Diners", | |
"primary": true, | |
"shortName": "Diner" | |
} | |
], | |
"id": "4ad7929cf964a520500c21e3", | |
"location": { | |
"address": "249 Victoria Street", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "btwn Dundas St E and Shuter St", | |
"distance": 450, | |
"formattedAddress": [ | |
"249 Victoria Street (btwn Dundas St E and Shuter St)", | |
"Toronto ON M5B 1T8", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65564091455335, | |
"lng": -79.37919882575557 | |
} | |
], | |
"lat": 43.65564091455335, | |
"lng": -79.37919882575557, | |
"postalCode": "M5B 1T8", | |
"state": "ON" | |
}, | |
"name": "The Senator Restaurant", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
}, | |
"venuePage": { | |
"id": "55585058" | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-54516134498e019be8e568fc-61", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/apparel_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d103951735", | |
"name": "Clothing Store", | |
"pluralName": "Clothing Stores", | |
"primary": true, | |
"shortName": "Apparel" | |
} | |
], | |
"id": "54516134498e019be8e568fc", | |
"location": { | |
"address": "220 Yonge St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 299, | |
"formattedAddress": [ | |
"220 Yonge St", | |
"Toronto ON", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65284284567131, | |
"lng": -79.38032491863406 | |
} | |
], | |
"lat": 43.65284284567131, | |
"lng": -79.38032491863406, | |
"state": "ON" | |
}, | |
"name": "Ted Baker", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4fe4a773e4b0ef61f5212ecd-62", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/sushi_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1d2941735", | |
"name": "Sushi Restaurant", | |
"pluralName": "Sushi Restaurants", | |
"primary": true, | |
"shortName": "Sushi" | |
} | |
], | |
"id": "4fe4a773e4b0ef61f5212ecd", | |
"location": { | |
"address": "10 Dundas St. E", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Yonge St.", | |
"distance": 405, | |
"formattedAddress": [ | |
"10 Dundas St. E (at Yonge St.)", | |
"Toronto ON M5B 2G9", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.656252529816086, | |
"lng": -79.38065954471074 | |
} | |
], | |
"lat": 43.656252529816086, | |
"lng": -79.38065954471074, | |
"postalCode": "M5B 2G9", | |
"state": "ON" | |
}, | |
"name": "Spring Sushi", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4d2c55ea55a8b60c5004efc0-63", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/icecream_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1c9941735", | |
"name": "Ice Cream Shop", | |
"pluralName": "Ice Cream Shops", | |
"primary": true, | |
"shortName": "Ice Cream" | |
} | |
], | |
"id": "4d2c55ea55a8b60c5004efc0", | |
"location": { | |
"address": "333 Bay St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Adelaide St W", | |
"distance": 498, | |
"formattedAddress": [ | |
"333 Bay St (at Adelaide St W)", | |
"Toronto ON M5H 2R2", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65043319523819, | |
"lng": -79.37939324949957 | |
} | |
], | |
"lat": 43.65043319523819, | |
"lng": -79.37939324949957, | |
"postalCode": "M5H 2R2", | |
"state": "ON" | |
}, | |
"name": "deKEFIR", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-57d0a3fb498e0fb29e892eed-64", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/latinamerican_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1be941735", | |
"name": "Latin American Restaurant", | |
"pluralName": "Latin American Restaurants", | |
"primary": true, | |
"shortName": "Latin American" | |
} | |
], | |
"id": "57d0a3fb498e0fb29e892eed", | |
"location": { | |
"address": "176 Yonge St.", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 428, | |
"formattedAddress": [ | |
"176 Yonge St.", | |
"Toronto ON M5C 2L7", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.651722, | |
"lng": -79.379205 | |
} | |
], | |
"lat": 43.651722, | |
"lng": -79.379205, | |
"postalCode": "M5C 2L7", | |
"state": "ON" | |
}, | |
"name": "Leña", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
}, | |
"venuePage": { | |
"id": "385912443" | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4b8eaea1f964a520b03033e3-65", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/juicebar_", | |
"suffix": ".png" | |
}, | |
"id": "52f2ab2ebcbc57f1066b8b41", | |
"name": "Smoothie Shop", | |
"pluralName": "Smoothie Shops", | |
"primary": true, | |
"shortName": "Smoothie Shop" | |
} | |
], | |
"id": "4b8eaea1f964a520b03033e3", | |
"location": { | |
"address": "2 Queen Street East, Suite #110", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "Suite #110", | |
"distance": 450, | |
"formattedAddress": [ | |
"2 Queen Street East, Suite #110 (Suite #110)", | |
"Toronto ON M5C 3G7", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65265752, | |
"lng": -79.37845927 | |
} | |
], | |
"lat": 43.65265752, | |
"lng": -79.37845927, | |
"postalCode": "M5C 3G7", | |
"state": "ON" | |
}, | |
"name": "Booster Juice", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ad4c061f964a52095f720e3-66", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/thai_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d149941735", | |
"name": "Thai Restaurant", | |
"pluralName": "Thai Restaurants", | |
"primary": true, | |
"shortName": "Thai" | |
} | |
], | |
"id": "4ad4c061f964a52095f720e3", | |
"location": { | |
"address": "340 Yonge St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Gould St", | |
"distance": 495, | |
"formattedAddress": [ | |
"340 Yonge St (at Gould St)", | |
"Toronto ON M5B 1R7", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65760101432665, | |
"lng": -79.38161963017174 | |
} | |
], | |
"lat": 43.65760101432665, | |
"lng": -79.38161963017174, | |
"postalCode": "M5B 1R7", | |
"state": "ON" | |
}, | |
"name": "Salad King", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4b9e7418f964a52032e536e3-67", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/coffeeshop_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1e0931735", | |
"name": "Coffee Shop", | |
"pluralName": "Coffee Shops", | |
"primary": true, | |
"shortName": "Coffee Shop" | |
} | |
], | |
"id": "4b9e7418f964a52032e536e3", | |
"location": { | |
"address": "220 Yonge St., Unit D102", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "in Toronto Eaton Centre", | |
"distance": 391, | |
"formattedAddress": [ | |
"220 Yonge St., Unit D102 (in Toronto Eaton Centre)", | |
"Toronto ON M5B 2H1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65602745564191, | |
"lng": -79.38057491935326 | |
} | |
], | |
"lat": 43.65602745564191, | |
"lng": -79.38057491935326, | |
"neighborhood": "Downtown Toronto", | |
"postalCode": "M5B 2H1", | |
"state": "ON" | |
}, | |
"name": "Second Cup", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4adc9148f964a520512d21e3-68", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/mexican_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1c1941735", | |
"name": "Mexican Restaurant", | |
"pluralName": "Mexican Restaurants", | |
"primary": true, | |
"shortName": "Mexican" | |
} | |
], | |
"id": "4adc9148f964a520512d21e3", | |
"location": { | |
"address": "323 Yonge St, Unit 114", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "Yonge & Dundas", | |
"distance": 448, | |
"formattedAddress": [ | |
"323 Yonge St, Unit 114 (Yonge & Dundas)", | |
"Toronto ON M5B 1R7", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65686, | |
"lng": -79.38091 | |
} | |
], | |
"lat": 43.65686, | |
"lng": -79.38091, | |
"postalCode": "M5B 1R7", | |
"state": "ON" | |
}, | |
"name": "Chipotle Mexican Grill", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4d9c674c48b6224baa310c9f-69", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/videogames_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d10b951735", | |
"name": "Video Game Store", | |
"pluralName": "Video Game Stores", | |
"primary": true, | |
"shortName": "Video Games" | |
} | |
], | |
"id": "4d9c674c48b6224baa310c9f", | |
"location": { | |
"address": "267 Yonge St.", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "btwn Dundas St E and Shuter St", | |
"distance": 353, | |
"formattedAddress": [ | |
"267 Yonge St. (btwn Dundas St E and Shuter St)", | |
"Toronto ON M5B 2H1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65529344166874, | |
"lng": -79.38032812642462 | |
} | |
], | |
"lat": 43.65529344166874, | |
"lng": -79.38032812642462, | |
"postalCode": "M5B 2H1", | |
"state": "ON" | |
}, | |
"name": "EB Games", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4af057daf964a5204edb21e3-70", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/building/default_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d124941735", | |
"name": "Office", | |
"pluralName": "Offices", | |
"primary": true, | |
"shortName": "Office" | |
} | |
], | |
"id": "4af057daf964a5204edb21e3", | |
"location": { | |
"address": "333 Bay St.", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Adelaide St. W", | |
"distance": 429, | |
"formattedAddress": [ | |
"333 Bay St. (at Adelaide St. W)", | |
"Toronto ON M5H 2R2", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.650878539102386, | |
"lng": -79.38000310739676 | |
} | |
], | |
"lat": 43.650878539102386, | |
"lng": -79.38000310739676, | |
"postalCode": "M5H 2R2", | |
"state": "ON" | |
}, | |
"name": "Bay Adelaide Centre", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4b68aed1f964a520de862be3-71", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/arts_entertainment/musicvenue_jazzclub_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1e7931735", | |
"name": "Jazz Club", | |
"pluralName": "Jazz Clubs", | |
"primary": true, | |
"shortName": "Jazz Club" | |
} | |
], | |
"id": "4b68aed1f964a520de862be3", | |
"location": { | |
"address": "194 Queen St W", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "Queen & St. Patrick", | |
"distance": 499, | |
"formattedAddress": [ | |
"194 Queen St W (Queen & St. Patrick)", | |
"Toronto ON M5V 1Z1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65050475544005, | |
"lng": -79.38857723389897 | |
} | |
], | |
"lat": 43.65050475544005, | |
"lng": -79.38857723389897, | |
"postalCode": "M5V 1Z1", | |
"state": "ON" | |
}, | |
"name": "The Rex Hotel Jazz & Blues Bar", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
}, | |
"venuePage": { | |
"id": "62225795" | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4e186b29183880768f406e17-72", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/breakfast_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d143941735", | |
"name": "Breakfast Spot", | |
"pluralName": "Breakfast Spots", | |
"primary": true, | |
"shortName": "Breakfast" | |
} | |
], | |
"id": "4e186b29183880768f406e17", | |
"location": { | |
"address": "1 Richmond St. W.", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Yonge St.", | |
"distance": 440, | |
"formattedAddress": [ | |
"1 Richmond St. W. (at Yonge St.)", | |
"Toronto ON M5H 3W4", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65166162378037, | |
"lng": -79.3790751303271 | |
} | |
], | |
"lat": 43.65166162378037, | |
"lng": -79.3790751303271, | |
"postalCode": "M5H 3W4", | |
"state": "ON" | |
}, | |
"name": "Sunset Grill", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-5b1a76586f0aa2002c5d9a0c-73", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/argentinian_", | |
"suffix": ".png" | |
}, | |
"id": "58daa1558bbb0b01f18ec1f4", | |
"name": "Colombian Restaurant", | |
"pluralName": "Colombian Restaurants", | |
"primary": true, | |
"shortName": "Colombian" | |
} | |
], | |
"id": "5b1a76586f0aa2002c5d9a0c", | |
"location": { | |
"address": "190 University Avenue", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "Adelaide St", | |
"distance": 486, | |
"formattedAddress": [ | |
"190 University Avenue (Adelaide St)", | |
"Toronto ON M5H 0A3", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.64939770725357, | |
"lng": -79.38609106624851 | |
} | |
], | |
"lat": 43.64939770725357, | |
"lng": -79.38609106624851, | |
"postalCode": "M5H 0A3", | |
"state": "ON" | |
}, | |
"name": "Kojin", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
}, | |
"venuePage": { | |
"id": "499264138" | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4e9de9fbb803b7506dcf4c41-74", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/coffeeshop_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1e0931735", | |
"name": "Coffee Shop", | |
"pluralName": "Coffee Shops", | |
"primary": true, | |
"shortName": "Coffee Shop" | |
} | |
], | |
"id": "4e9de9fbb803b7506dcf4c41", | |
"location": { | |
"address": "209 Victoria St.", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "in Keenan Research Centre lobby", | |
"distance": 418, | |
"formattedAddress": [ | |
"209 Victoria St. (in Keenan Research Centre lobby)", | |
"Toronto ON", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65446528594945, | |
"lng": -79.37891894388453 | |
} | |
], | |
"lat": 43.65446528594945, | |
"lng": -79.37891894388453, | |
"neighborhood": "Downtown Toronto", | |
"state": "ON" | |
}, | |
"name": "Starbucks", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-505125b2e4b0253ca4e47351-75", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/ramen_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1d1941735", | |
"name": "Noodle House", | |
"pluralName": "Noodle Houses", | |
"primary": true, | |
"shortName": "Noodles" | |
} | |
], | |
"id": "505125b2e4b0253ca4e47351", | |
"location": { | |
"address": "190 University Ave", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "btwn Richmond & Adelaide St W", | |
"distance": 493, | |
"formattedAddress": [ | |
"190 University Ave (btwn Richmond & Adelaide St W)", | |
"Toronto ON M5H 0A3", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.6493658716176, | |
"lng": -79.38621652451032 | |
} | |
], | |
"lat": 43.6493658716176, | |
"lng": -79.38621652451032, | |
"neighborhood": "Entertainment District", | |
"postalCode": "M5H 0A3", | |
"state": "ON" | |
}, | |
"name": "Momofuku Noodle Bar", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
}, | |
"venuePage": { | |
"id": "167827980" | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ad9ffbbf964a520091d21e3-76", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/default_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1c4941735", | |
"name": "Restaurant", | |
"pluralName": "Restaurants", | |
"primary": true, | |
"shortName": "Restaurant" | |
} | |
], | |
"id": "4ad9ffbbf964a520091d21e3", | |
"location": { | |
"address": "10 Dundas St. E", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Yonge St.", | |
"distance": 405, | |
"formattedAddress": [ | |
"10 Dundas St. E (at Yonge St.)", | |
"Toronto ON M5B 0A1", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65601939992059, | |
"lng": -79.38032551379719 | |
} | |
], | |
"lat": 43.65601939992059, | |
"lng": -79.38032551379719, | |
"postalCode": "M5B 0A1", | |
"state": "ON" | |
}, | |
"name": "Jack Astor's Bar & Grill", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ada04eff964a520571d21e3-77", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/diner_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d147941735", | |
"name": "Diner", | |
"pluralName": "Diners", | |
"primary": true, | |
"shortName": "Diner" | |
} | |
], | |
"id": "4ada04eff964a520571d21e3", | |
"location": { | |
"address": "200 Victoria St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Shuter St", | |
"distance": 397, | |
"formattedAddress": [ | |
"200 Victoria St (at Shuter St)", | |
"Toronto ON M5B 2R3", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65426474929814, | |
"lng": -79.37912005538317 | |
} | |
], | |
"lat": 43.65426474929814, | |
"lng": -79.37912005538317, | |
"postalCode": "M5B 2R3", | |
"state": "ON" | |
}, | |
"name": "Fran's", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-50a2c200e4b00b5527eb54a0-78", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/apparel_shoestore_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d107951735", | |
"name": "Shoe Store", | |
"pluralName": "Shoe Stores", | |
"primary": true, | |
"shortName": "Shoes" | |
} | |
], | |
"id": "50a2c200e4b00b5527eb54a0", | |
"location": { | |
"address": "245 Yonge St.", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 333, | |
"formattedAddress": [ | |
"245 Yonge St.", | |
"Toronto ON", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.654825509733335, | |
"lng": -79.38024076741966 | |
} | |
], | |
"lat": 43.654825509733335, | |
"lng": -79.38024076741966, | |
"state": "ON" | |
}, | |
"name": "Vans", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ad4c063f964a5204af820e3-79", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/shops/apparel_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d103951735", | |
"name": "Clothing Store", | |
"pluralName": "Clothing Stores", | |
"primary": true, | |
"shortName": "Apparel" | |
} | |
], | |
"id": "4ad4c063f964a5204af820e3", | |
"location": { | |
"address": "235 Yonge St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Shuter St", | |
"distance": 329, | |
"formattedAddress": [ | |
"235 Yonge St (at Shuter St)", | |
"Toronto ON M5B 1N8", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65441107845698, | |
"lng": -79.38005491917738 | |
} | |
], | |
"lat": 43.65441107845698, | |
"lng": -79.38005491917738, | |
"postalCode": "M5B 1N8", | |
"state": "ON" | |
}, | |
"name": "Urban Outfitters", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4b461f97f964a5202e1726e3-80", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/salad_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1bd941735", | |
"name": "Salad Place", | |
"pluralName": "Salad Places", | |
"primary": true, | |
"shortName": "Salad" | |
} | |
], | |
"id": "4b461f97f964a5202e1726e3", | |
"location": { | |
"address": "130 King St. W", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "in Exchange Tower", | |
"distance": 468, | |
"formattedAddress": [ | |
"130 King St. W (in Exchange Tower)", | |
"Toronto ON M5X 2A2", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.649273084327184, | |
"lng": -79.38374831204301 | |
} | |
], | |
"lat": 43.649273084327184, | |
"lng": -79.38374831204301, | |
"postalCode": "M5X 2A2", | |
"state": "ON" | |
}, | |
"name": "Freshii", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4b50d070f964a5206d3327e3-81", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/thai_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d149941735", | |
"name": "Thai Restaurant", | |
"pluralName": "Thai Restaurants", | |
"primary": true, | |
"shortName": "Thai" | |
} | |
], | |
"id": "4b50d070f964a5206d3327e3", | |
"location": { | |
"address": "130 King St. W", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "in Exchange Tower", | |
"distance": 482, | |
"formattedAddress": [ | |
"130 King St. W (in Exchange Tower)", | |
"Toronto ON M5H 3T9", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.64914597811404, | |
"lng": -79.38379835292523 | |
} | |
], | |
"lat": 43.64914597811404, | |
"lng": -79.38379835292523, | |
"postalCode": "M5H 3T9", | |
"state": "ON" | |
}, | |
"name": "Thai Island", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4aea2b14f964a520ebb921e3-82", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/vietnamese_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d14a941735", | |
"name": "Vietnamese Restaurant", | |
"pluralName": "Vietnamese Restaurants", | |
"primary": true, | |
"shortName": "Vietnamese" | |
} | |
], | |
"id": "4aea2b14f964a520ebb921e3", | |
"location": { | |
"address": "271 Yonge St.", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "btwn Dundas St. E & Shuter St.", | |
"distance": 359, | |
"formattedAddress": [ | |
"271 Yonge St. (btwn Dundas St. E & Shuter St.)", | |
"Toronto ON M5B 1N8", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.6553866, | |
"lng": -79.3803264 | |
} | |
], | |
"lat": 43.6553866, | |
"lng": -79.3803264, | |
"postalCode": "M5B 1N8", | |
"state": "ON" | |
}, | |
"name": "Fine Asian Bowl", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4b7aa994f964a5200c362fe3-83", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/coffeeshop_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1e0931735", | |
"name": "Coffee Shop", | |
"pluralName": "Coffee Shops", | |
"primary": true, | |
"shortName": "Coffee Shop" | |
} | |
], | |
"id": "4b7aa994f964a5200c362fe3", | |
"location": { | |
"address": "261 Yonge St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"distance": 366, | |
"formattedAddress": [ | |
"261 Yonge St", | |
"Toronto ON M5B 1N8", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65521249025681, | |
"lng": -79.38006296753883 | |
} | |
], | |
"lat": 43.65521249025681, | |
"lng": -79.38006296753883, | |
"postalCode": "M5B 1N8", | |
"state": "ON" | |
}, | |
"name": "Tim Hortons", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4ae61cf6f964a520caa421e3-84", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/travel/hotel_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1fa931735", | |
"name": "Hotel", | |
"pluralName": "Hotels", | |
"primary": true, | |
"shortName": "Hotel" | |
} | |
], | |
"id": "4ae61cf6f964a520caa421e3", | |
"location": { | |
"address": "200 Victoria St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Shuter St", | |
"distance": 410, | |
"formattedAddress": [ | |
"200 Victoria St (at Shuter St)", | |
"Toronto ON", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.65449797039222, | |
"lng": -79.37903488923283 | |
} | |
], | |
"lat": 43.65449797039222, | |
"lng": -79.37903488923283, | |
"state": "ON" | |
}, | |
"name": "Pantages Hotel & Spa", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4b6a0069f964a520f3c02be3-85", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/nightlife/cocktails_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d11e941735", | |
"name": "Cocktail Bar", | |
"pluralName": "Cocktail Bars", | |
"primary": true, | |
"shortName": "Cocktail" | |
} | |
], | |
"id": "4b6a0069f964a520f3c02be3", | |
"location": { | |
"address": "200 Victoria St.", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "at Shuter St.", | |
"distance": 413, | |
"formattedAddress": [ | |
"200 Victoria St. (at Shuter St.)", | |
"Toronto ON M5B 1W8", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.654493431269564, | |
"lng": -79.3789996004105 | |
} | |
], | |
"lat": 43.654493431269564, | |
"lng": -79.3789996004105, | |
"postalCode": "M5B 1W8", | |
"state": "ON" | |
}, | |
"name": "Pantages Lounge & Bar", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
}, | |
{ | |
"reasons": { | |
"count": 0, | |
"items": [ | |
{ | |
"reasonName": "globalInteractionReason", | |
"summary": "This spot is popular", | |
"type": "general" | |
} | |
] | |
}, | |
"referralId": "e-0-4b5219ccf964a520d56727e3-86", | |
"venue": { | |
"categories": [ | |
{ | |
"icon": { | |
"prefix": "https://ss3.4sqi.net/img/categories_v2/food/coffeeshop_", | |
"suffix": ".png" | |
}, | |
"id": "4bf58dd8d48988d1e0931735", | |
"name": "Coffee Shop", | |
"pluralName": "Coffee Shops", | |
"primary": true, | |
"shortName": "Coffee Shop" | |
} | |
], | |
"id": "4b5219ccf964a520d56727e3", | |
"location": { | |
"address": "30 Bond St", | |
"cc": "CA", | |
"city": "Toronto", | |
"country": "Canada", | |
"crossStreet": "in St. Michael's Hospital", | |
"distance": 449, | |
"formattedAddress": [ | |
"30 Bond St (in St. Michael's Hospital)", | |
"Toronto ON M5B 1W8", | |
"Canada" | |
], | |
"labeledLatLngs": [ | |
{ | |
"label": "display", | |
"lat": 43.6536897, | |
"lng": -79.3783564 | |
} | |
], | |
"lat": 43.6536897, | |
"lng": -79.3783564, | |
"postalCode": "M5B 1W8", | |
"state": "ON" | |
}, | |
"name": "Tim Hortons", | |
"photos": { | |
"count": 0, | |
"groups": [] | |
} | |
} | |
} | |
], | |
"name": "recommended", | |
"type": "Recommended Places" | |
} | |
], | |
"headerFullLocation": "Bay Street Corridor, Toronto", | |
"headerLocation": "Bay Street Corridor", | |
"headerLocationGranularity": "neighborhood", | |
"suggestedBounds": { | |
"ne": { | |
"lat": 43.6579817045, | |
"lng": -79.37772678059432 | |
}, | |
"sw": { | |
"lat": 43.6489816955, | |
"lng": -79.39014261940568 | |
} | |
}, | |
"suggestedFilters": { | |
"filters": [ | |
{ | |
"key": "openNow", | |
"name": "Open now" | |
} | |
], | |
"header": "Tap to show:" | |
}, | |
"totalResults": 87 | |
} | |
}, | |
"text/plain": [ | |
"<IPython.core.display.JSON object>" | |
] | |
}, | |
"execution_count": 128, | |
"metadata": { | |
"application/json": { | |
"expanded": false, | |
"root": "root" | |
} | |
}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"JSON(res)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Get the tops venues in Toronto" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"We define a small utility to fetch the data asynchronously" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 129, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"Venue = Tuple[str, float, float, str, float, float, str]\n", | |
"\n", | |
"\n", | |
"async def get_json(\n", | |
" session: ClientSession, name: str, latitude: float, longitude: float\n", | |
") -> List[Venue]:\n", | |
" \"\"\"return selected informations on a venue\"\"\"\n", | |
"\n", | |
" req = await session.get(\n", | |
" api_root, params=dict(ll=f\"{latitude},{longitude}\", **params)\n", | |
" )\n", | |
"\n", | |
" res = await req.json()\n", | |
" venues = res[\"response\"][\"groups\"][0][\"items\"]\n", | |
" return [\n", | |
" (\n", | |
" name,\n", | |
" latitude,\n", | |
" longitude,\n", | |
" v[\"venue\"][\"name\"],\n", | |
" v[\"venue\"][\"location\"][\"lat\"],\n", | |
" v[\"venue\"][\"location\"][\"lng\"],\n", | |
" v[\"venue\"][\"categories\"][0][\"name\"].lower(),\n", | |
" )\n", | |
" for v in venues\n", | |
" ]" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Are there any na values in the DataFrame view dfc[[\"Neighborhood\", \"Latitude\", \"Longitude\"]]?" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 130, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"Neighborhood False\n", | |
"Latitude False\n", | |
"Longitude False\n", | |
"dtype: bool" | |
] | |
}, | |
"execution_count": 130, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"dfc[[\"Neighborhood\", \"Latitude\", \"Longitude\"]].isna().any()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"No... good, let's request the data" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 32, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"async with ClientSession() as session:\n", | |
" df_view = dfc[[\"Neighborhood\", \"Latitude\", \"Longitude\"]]\n", | |
"\n", | |
" futures = [\n", | |
" get_json(session, name, latitude, longitude)\n", | |
" for _, (name, latitude, longitude) in df_view.iterrows()\n", | |
" ]\n", | |
" v = await asyncio.gather(*futures)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Another possibility would be to work with a thread pool\n", | |
"```\n", | |
"from concurrent.futures import ThreadPoolExecutor\n", | |
"\n", | |
"with ThreadPoolExecutor(max_workers=4) as executor:\n", | |
"\n", | |
" # Get current loop\n", | |
" loop = asyncio.get_running_loop()\n", | |
" futures = [loop.run_in_executor(executor, <long_task>, <i>) for <i> in <inputs>]\n", | |
" results = await asyncio.gather(*futures)\n", | |
"```" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"We can now create a `DataFrame` out of the result. *v* is a nested list of *Venue*" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 67, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"venues_type = {\n", | |
" \"Neighborhood\": \"string\",\n", | |
" \"Neighborhood Latitude\": float,\n", | |
" \"Neighborhood Longitude\": float,\n", | |
" \"Venue\": \"string\",\n", | |
" \"Venue Latitude\": float,\n", | |
" \"Venue Longitude\": float,\n", | |
" \"Venue Category\": \"category\",\n", | |
"}\n", | |
"\n", | |
"# Make a set comprehension out of the nest list of venues\n", | |
"venues_flattened = (item for venue_list in v for item in venue_list)\n", | |
"\n", | |
"# Create a DataFrame with it and use the column name from venues_type (dict are ordered in python > 3.6)\n", | |
"toronto_venues = pd.DataFrame(venues_flattened, columns=list(venues_type)).astype(\n", | |
" venues_type\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 68, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"<class 'pandas.core.frame.DataFrame'>\n", | |
"RangeIndex: 2138 entries, 0 to 2137\n", | |
"Data columns (total 7 columns):\n", | |
" # Column Non-Null Count Dtype \n", | |
"--- ------ -------------- ----- \n", | |
" 0 Neighborhood 2138 non-null string \n", | |
" 1 Neighborhood Latitude 2138 non-null float64 \n", | |
" 2 Neighborhood Longitude 2138 non-null float64 \n", | |
" 3 Venue 2138 non-null string \n", | |
" 4 Venue Latitude 2138 non-null float64 \n", | |
" 5 Venue Longitude 2138 non-null float64 \n", | |
" 6 Venue Category 2138 non-null category\n", | |
"dtypes: category(1), float64(4), string(2)\n", | |
"memory usage: 116.6 KB\n" | |
] | |
} | |
], | |
"source": [ | |
"toronto_venues.info()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 69, | |
"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>Malvern, Rouge</td>\n", | |
" <td>43.806686</td>\n", | |
" <td>-79.194353</td>\n", | |
" <td>Wendy’s</td>\n", | |
" <td>43.807448</td>\n", | |
" <td>-79.199056</td>\n", | |
" <td>fast food restaurant</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>Malvern, Rouge</td>\n", | |
" <td>43.806686</td>\n", | |
" <td>-79.194353</td>\n", | |
" <td>Interprovincial Group</td>\n", | |
" <td>43.805630</td>\n", | |
" <td>-79.200378</td>\n", | |
" <td>print shop</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Neighborhood Neighborhood Latitude Neighborhood Longitude \\\n", | |
"0 Malvern, Rouge 43.806686 -79.194353 \n", | |
"1 Malvern, Rouge 43.806686 -79.194353 \n", | |
"\n", | |
" Venue Venue Latitude Venue Longitude \\\n", | |
"0 Wendy’s 43.807448 -79.199056 \n", | |
"1 Interprovincial Group 43.805630 -79.200378 \n", | |
"\n", | |
" Venue Category \n", | |
"0 fast food restaurant \n", | |
"1 print shop " | |
] | |
}, | |
"execution_count": 69, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"toronto_venues.head(2)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### One hot encoding" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
" If columns is None then all the columns with object or category dtype will be converted" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 59, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"Neighborhood string\n", | |
"Neighborhood Latitude float64\n", | |
"Neighborhood Longitude float64\n", | |
"Venue string\n", | |
"Venue Latitude float64\n", | |
"Venue Longitude float64\n", | |
"Venue Category category\n", | |
"dtype: object" | |
] | |
}, | |
"execution_count": 59, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"toronto_venues.dtypes" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 64, | |
"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>accessories store</th>\n", | |
" <th>afghan restaurant</th>\n", | |
" <th>airport</th>\n", | |
" <th>airport food court</th>\n", | |
" <th>airport gate</th>\n", | |
" <th>airport lounge</th>\n", | |
" <th>airport service</th>\n", | |
" <th>airport terminal</th>\n", | |
" <th>american restaurant</th>\n", | |
" <th>...</th>\n", | |
" <th>trail</th>\n", | |
" <th>train station</th>\n", | |
" <th>vegetarian / vegan restaurant</th>\n", | |
" <th>video game store</th>\n", | |
" <th>vietnamese restaurant</th>\n", | |
" <th>warehouse store</th>\n", | |
" <th>wine bar</th>\n", | |
" <th>wings joint</th>\n", | |
" <th>women's store</th>\n", | |
" <th>yoga studio</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>Malvern, Rouge</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>...</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>Malvern, Rouge</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>...</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" <td>0</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"<p>2 rows × 272 columns</p>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Neighborhood accessories store afghan restaurant airport \\\n", | |
"0 Malvern, Rouge 0 0 0 \n", | |
"1 Malvern, Rouge 0 0 0 \n", | |
"\n", | |
" airport food court airport gate airport lounge airport service \\\n", | |
"0 0 0 0 0 \n", | |
"1 0 0 0 0 \n", | |
"\n", | |
" airport terminal american restaurant ... trail train station \\\n", | |
"0 0 0 ... 0 0 \n", | |
"1 0 0 ... 0 0 \n", | |
"\n", | |
" vegetarian / vegan restaurant video game store vietnamese restaurant \\\n", | |
"0 0 0 0 \n", | |
"1 0 0 0 \n", | |
"\n", | |
" warehouse store wine bar wings joint women's store yoga studio \n", | |
"0 0 0 0 0 0 \n", | |
"1 0 0 0 0 0 \n", | |
"\n", | |
"[2 rows x 272 columns]" | |
] | |
}, | |
"execution_count": 64, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"toronto_onehot = pd.get_dummies(\n", | |
" toronto_venues[[\"Neighborhood\", \"Venue Category\"]],\n", | |
" prefix=\"\",\n", | |
" prefix_sep=\"\",\n", | |
" columns=[\"Venue Category\"],\n", | |
")\n", | |
"toronto_onehot.head(2)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 65, | |
"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>accessories store</th>\n", | |
" <th>afghan restaurant</th>\n", | |
" <th>airport</th>\n", | |
" <th>airport food court</th>\n", | |
" <th>airport gate</th>\n", | |
" <th>airport lounge</th>\n", | |
" <th>airport service</th>\n", | |
" <th>airport terminal</th>\n", | |
" <th>american restaurant</th>\n", | |
" <th>...</th>\n", | |
" <th>trail</th>\n", | |
" <th>train station</th>\n", | |
" <th>vegetarian / vegan restaurant</th>\n", | |
" <th>video game store</th>\n", | |
" <th>vietnamese restaurant</th>\n", | |
" <th>warehouse store</th>\n", | |
" <th>wine bar</th>\n", | |
" <th>wings joint</th>\n", | |
" <th>women's store</th>\n", | |
" <th>yoga studio</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>Agincourt</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>...</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>Alderwood, Long Branch</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>...</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" <td>0.0</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"<p>2 rows × 272 columns</p>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Neighborhood accessories store afghan restaurant airport \\\n", | |
"0 Agincourt 0.0 0.0 0.0 \n", | |
"1 Alderwood, Long Branch 0.0 0.0 0.0 \n", | |
"\n", | |
" airport food court airport gate airport lounge airport service \\\n", | |
"0 0.0 0.0 0.0 0.0 \n", | |
"1 0.0 0.0 0.0 0.0 \n", | |
"\n", | |
" airport terminal american restaurant ... trail train station \\\n", | |
"0 0.0 0.0 ... 0.0 0.0 \n", | |
"1 0.0 0.0 ... 0.0 0.0 \n", | |
"\n", | |
" vegetarian / vegan restaurant video game store vietnamese restaurant \\\n", | |
"0 0.0 0.0 0.0 \n", | |
"1 0.0 0.0 0.0 \n", | |
"\n", | |
" warehouse store wine bar wings joint women's store yoga studio \n", | |
"0 0.0 0.0 0.0 0.0 0.0 \n", | |
"1 0.0 0.0 0.0 0.0 0.0 \n", | |
"\n", | |
"[2 rows x 272 columns]" | |
] | |
}, | |
"execution_count": 65, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"toronto_grouped = toronto_onehot.groupby(\"Neighborhood\").mean().reset_index()\n", | |
"toronto_grouped.head(2)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"We recreate a `DataFrame` joining Neighborhood and most common venues" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 104, | |
"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 common venue</th>\n", | |
" <th>2nd common venue</th>\n", | |
" <th>3rd common venue</th>\n", | |
" <th>4th common venue</th>\n", | |
" <th>5th common venue</th>\n", | |
" <th>6th common venue</th>\n", | |
" <th>7th common venue</th>\n", | |
" <th>8th common venue</th>\n", | |
" <th>9th common venue</th>\n", | |
" <th>10th common venue</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>Agincourt</td>\n", | |
" <td>lounge</td>\n", | |
" <td>latin american restaurant</td>\n", | |
" <td>breakfast spot</td>\n", | |
" <td>dumpling restaurant</td>\n", | |
" <td>distribution center</td>\n", | |
" <td>dog run</td>\n", | |
" <td>doner restaurant</td>\n", | |
" <td>donut shop</td>\n", | |
" <td>drugstore</td>\n", | |
" <td>electronics store</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>dance studio</td>\n", | |
" <td>coffee shop</td>\n", | |
" <td>pub</td>\n", | |
" <td>pharmacy</td>\n", | |
" <td>sandwich place</td>\n", | |
" <td>dog run</td>\n", | |
" <td>dim sum restaurant</td>\n", | |
" <td>diner</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>fried chicken joint</td>\n", | |
" <td>sandwich place</td>\n", | |
" <td>bridal shop</td>\n", | |
" <td>restaurant</td>\n", | |
" <td>diner</td>\n", | |
" <td>supermarket</td>\n", | |
" <td>middle eastern restaurant</td>\n", | |
" <td>sushi restaurant</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>3</th>\n", | |
" <td>Bayview Village</td>\n", | |
" <td>café</td>\n", | |
" <td>bank</td>\n", | |
" <td>chinese restaurant</td>\n", | |
" <td>japanese restaurant</td>\n", | |
" <td>diner</td>\n", | |
" <td>distribution center</td>\n", | |
" <td>dog run</td>\n", | |
" <td>doner restaurant</td>\n", | |
" <td>donut shop</td>\n", | |
" <td>drugstore</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>4</th>\n", | |
" <td>Bedford Park, Lawrence Manor East</td>\n", | |
" <td>coffee shop</td>\n", | |
" <td>hobby shop</td>\n", | |
" <td>sandwich place</td>\n", | |
" <td>italian restaurant</td>\n", | |
" <td>pharmacy</td>\n", | |
" <td>pizza place</td>\n", | |
" <td>café</td>\n", | |
" <td>butcher</td>\n", | |
" <td>pub</td>\n", | |
" <td>restaurant</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Neighborhood 1st common venue \\\n", | |
"0 Agincourt lounge \n", | |
"1 Alderwood, Long Branch pizza place \n", | |
"2 Bathurst Manor, Wilson Heights, Downsview North coffee shop \n", | |
"3 Bayview Village café \n", | |
"4 Bedford Park, Lawrence Manor East coffee shop \n", | |
"\n", | |
" 2nd common venue 3rd common venue 4th common venue \\\n", | |
"0 latin american restaurant breakfast spot dumpling restaurant \n", | |
"1 gym dance studio coffee shop \n", | |
"2 bank fried chicken joint sandwich place \n", | |
"3 bank chinese restaurant japanese restaurant \n", | |
"4 hobby shop sandwich place italian restaurant \n", | |
"\n", | |
" 5th common venue 6th common venue 7th common venue \\\n", | |
"0 distribution center dog run doner restaurant \n", | |
"1 pub pharmacy sandwich place \n", | |
"2 bridal shop restaurant diner \n", | |
"3 diner distribution center dog run \n", | |
"4 pharmacy pizza place café \n", | |
"\n", | |
" 8th common venue 9th common venue 10th common venue \n", | |
"0 donut shop drugstore electronics store \n", | |
"1 dog run dim sum restaurant diner \n", | |
"2 supermarket middle eastern restaurant sushi restaurant \n", | |
"3 doner restaurant donut shop drugstore \n", | |
"4 butcher pub restaurant " | |
] | |
}, | |
"execution_count": 104, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"def return_most_common_venues(row, num_top_venues):\n", | |
" row_categories = row.iloc[1:]\n", | |
" row_categories_sorted = row_categories.sort_values(ascending=False)\n", | |
"\n", | |
" return row_categories_sorted.index.values[0:num_top_venues]\n", | |
"\n", | |
"\n", | |
"num_top_venues = 10\n", | |
"\n", | |
"# Column names: \"Neighborhood\" +\n", | |
"columns = (\n", | |
" [\"Neighborhood\"]\n", | |
" + [\"1st common venue\", \"2nd common venue\", \"3rd common venue\"]\n", | |
" + [f\"{n}th common venue\" for n in range(4, num_top_venues + 1)]\n", | |
")\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(\n", | |
" toronto_grouped.iloc[ind, :], num_top_venues\n", | |
" )\n", | |
"\n", | |
"neighborhoods_venues_sorted.head()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Apply kmeans algorithm" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 147, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int32)" | |
] | |
}, | |
"execution_count": 147, | |
"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=42, n_init=20).fit(\n", | |
" toronto_grouped_clustering\n", | |
")\n", | |
"\n", | |
"# check cluster labels generated for each row in the dataframe\n", | |
"kmeans.labels_[0:10]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 148, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>PostalCode</th>\n", | |
" <th>Borough</th>\n", | |
" <th>Neighborhood</th>\n", | |
" <th>Latitude</th>\n", | |
" <th>Longitude</th>\n", | |
" <th>Cluster</th>\n", | |
" <th>1st common venue</th>\n", | |
" <th>2nd common venue</th>\n", | |
" <th>3rd common venue</th>\n", | |
" <th>4th common venue</th>\n", | |
" <th>5th common venue</th>\n", | |
" <th>6th common venue</th>\n", | |
" <th>7th common venue</th>\n", | |
" <th>8th common venue</th>\n", | |
" <th>9th common venue</th>\n", | |
" <th>10th common venue</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>M1B</td>\n", | |
" <td>Scarborough</td>\n", | |
" <td>Malvern, Rouge</td>\n", | |
" <td>43.806686</td>\n", | |
" <td>-79.194353</td>\n", | |
" <td>1.0</td>\n", | |
" <td>fast food restaurant</td>\n", | |
" <td>print shop</td>\n", | |
" <td>drugstore</td>\n", | |
" <td>discount store</td>\n", | |
" <td>distribution center</td>\n", | |
" <td>dog run</td>\n", | |
" <td>doner restaurant</td>\n", | |
" <td>donut shop</td>\n", | |
" <td>dumpling restaurant</td>\n", | |
" <td>dim sum restaurant</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>M1C</td>\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>1.0</td>\n", | |
" <td>moving target</td>\n", | |
" <td>bar</td>\n", | |
" <td>yoga studio</td>\n", | |
" <td>drugstore</td>\n", | |
" <td>distribution center</td>\n", | |
" <td>dog run</td>\n", | |
" <td>doner restaurant</td>\n", | |
" <td>donut shop</td>\n", | |
" <td>dumpling restaurant</td>\n", | |
" <td>diner</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" PostalCode Borough Neighborhood Latitude \\\n", | |
"0 M1B Scarborough Malvern, Rouge 43.806686 \n", | |
"1 M1C Scarborough Rouge Hill, Port Union, Highland Creek 43.784535 \n", | |
"\n", | |
" Longitude Cluster 1st common venue 2nd common venue 3rd common venue \\\n", | |
"0 -79.194353 1.0 fast food restaurant print shop drugstore \n", | |
"1 -79.160497 1.0 moving target bar yoga studio \n", | |
"\n", | |
" 4th common venue 5th common venue 6th common venue 7th common venue \\\n", | |
"0 discount store distribution center dog run doner restaurant \n", | |
"1 drugstore distribution center dog run doner restaurant \n", | |
"\n", | |
" 8th common venue 9th common venue 10th common venue \n", | |
"0 donut shop dumpling restaurant dim sum restaurant \n", | |
"1 donut shop dumpling restaurant diner " | |
] | |
}, | |
"execution_count": 148, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# add clustering labels\n", | |
"if \"Cluster\" not in neighborhoods_venues_sorted.columns:\n", | |
" neighborhoods_venues_sorted.insert(0, \"Cluster\", kmeans.labels_)\n", | |
"\n", | |
"toronto_merged = dfc\n", | |
"\n", | |
"# merge toronto_grouped with toronto_data to add latitude/longitude for each neighborhood\n", | |
"toronto_merged = toronto_merged.join(\n", | |
" neighborhoods_venues_sorted.set_index(\"Neighborhood\"), on=\"Neighborhood\"\n", | |
") # .astype({\"Cluster\": int})\n", | |
"\n", | |
"toronto_merged.head(2) # check the last columns!" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Some Borough have no venue ?" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 149, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>PostalCode</th>\n", | |
" <th>Borough</th>\n", | |
" <th>Neighborhood</th>\n", | |
" <th>Latitude</th>\n", | |
" <th>Longitude</th>\n", | |
" <th>Cluster</th>\n", | |
" <th>1st common venue</th>\n", | |
" <th>2nd common venue</th>\n", | |
" <th>3rd common venue</th>\n", | |
" <th>4th common venue</th>\n", | |
" <th>5th common venue</th>\n", | |
" <th>6th common venue</th>\n", | |
" <th>7th common venue</th>\n", | |
" <th>8th common venue</th>\n", | |
" <th>9th common venue</th>\n", | |
" <th>10th common venue</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>16</th>\n", | |
" <td>M1X</td>\n", | |
" <td>Scarborough</td>\n", | |
" <td>Upper Rouge</td>\n", | |
" <td>43.836125</td>\n", | |
" <td>-79.205636</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>93</th>\n", | |
" <td>M9A</td>\n", | |
" <td>Etobicoke</td>\n", | |
" <td>Islington Avenue, Humber Valley Village</td>\n", | |
" <td>43.667856</td>\n", | |
" <td>-79.532242</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" <td>NaN</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" PostalCode Borough Neighborhood \\\n", | |
"16 M1X Scarborough Upper Rouge \n", | |
"93 M9A Etobicoke Islington Avenue, Humber Valley Village \n", | |
"\n", | |
" Latitude Longitude Cluster 1st common venue 2nd common venue \\\n", | |
"16 43.836125 -79.205636 NaN NaN NaN \n", | |
"93 43.667856 -79.532242 NaN NaN NaN \n", | |
"\n", | |
" 3rd common venue 4th common venue 5th common venue 6th common venue \\\n", | |
"16 NaN NaN NaN NaN \n", | |
"93 NaN NaN NaN NaN \n", | |
"\n", | |
" 7th common venue 8th common venue 9th common venue 10th common venue \n", | |
"16 NaN NaN NaN NaN \n", | |
"93 NaN NaN NaN NaN " | |
] | |
}, | |
"execution_count": 149, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"toronto_merged[toronto_merged.Cluster.isna()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 150, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>PostalCode</th>\n", | |
" <th>Borough</th>\n", | |
" <th>Neighborhood</th>\n", | |
" <th>Latitude</th>\n", | |
" <th>Longitude</th>\n", | |
" <th>Cluster</th>\n", | |
" <th>1st common venue</th>\n", | |
" <th>2nd common venue</th>\n", | |
" <th>3rd common venue</th>\n", | |
" <th>4th common venue</th>\n", | |
" <th>5th common venue</th>\n", | |
" <th>6th common venue</th>\n", | |
" <th>7th common venue</th>\n", | |
" <th>8th common venue</th>\n", | |
" <th>9th common venue</th>\n", | |
" <th>10th common venue</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>M1B</td>\n", | |
" <td>Scarborough</td>\n", | |
" <td>Malvern, Rouge</td>\n", | |
" <td>43.806686</td>\n", | |
" <td>-79.194353</td>\n", | |
" <td>1</td>\n", | |
" <td>fast food restaurant</td>\n", | |
" <td>print shop</td>\n", | |
" <td>drugstore</td>\n", | |
" <td>discount store</td>\n", | |
" <td>distribution center</td>\n", | |
" <td>dog run</td>\n", | |
" <td>doner restaurant</td>\n", | |
" <td>donut shop</td>\n", | |
" <td>dumpling restaurant</td>\n", | |
" <td>dim sum restaurant</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>M1C</td>\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>1</td>\n", | |
" <td>moving target</td>\n", | |
" <td>bar</td>\n", | |
" <td>yoga studio</td>\n", | |
" <td>drugstore</td>\n", | |
" <td>distribution center</td>\n", | |
" <td>dog run</td>\n", | |
" <td>doner restaurant</td>\n", | |
" <td>donut shop</td>\n", | |
" <td>dumpling restaurant</td>\n", | |
" <td>diner</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" PostalCode Borough Neighborhood Latitude \\\n", | |
"0 M1B Scarborough Malvern, Rouge 43.806686 \n", | |
"1 M1C Scarborough Rouge Hill, Port Union, Highland Creek 43.784535 \n", | |
"\n", | |
" Longitude Cluster 1st common venue 2nd common venue 3rd common venue \\\n", | |
"0 -79.194353 1 fast food restaurant print shop drugstore \n", | |
"1 -79.160497 1 moving target bar yoga studio \n", | |
"\n", | |
" 4th common venue 5th common venue 6th common venue 7th common venue \\\n", | |
"0 discount store distribution center dog run doner restaurant \n", | |
"1 drugstore distribution center dog run doner restaurant \n", | |
"\n", | |
" 8th common venue 9th common venue 10th common venue \n", | |
"0 donut shop dumpling restaurant dim sum restaurant \n", | |
"1 donut shop dumpling restaurant diner " | |
] | |
}, | |
"execution_count": 150, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"toronto_merged.dropna().astype({\"Cluster\": int}).head(2)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 153, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def plot_clusters(df: DataFrame) -> folium.Map:\n", | |
" map_clusters = folium.Map(location=[latitude, longitude], zoom_start=10)\n", | |
"\n", | |
" # set color scheme for the clusters\n", | |
" x = np.arange(kclusters)\n", | |
" ys = [i + x + (i * x) ** 2 for i in range(kclusters)]\n", | |
" colors_array = cm.rainbow(np.linspace(0, 1, len(ys)))\n", | |
" rainbow = [colors.rgb2hex(i) for i in colors_array]\n", | |
"\n", | |
" # add markers to the map\n", | |
" markers_colors = []\n", | |
" for lat, lon, poi, cluster in zip(\n", | |
" df[\"Latitude\"], df[\"Longitude\"], df[\"Neighborhood\"], df[\"Cluster\"]\n", | |
" ):\n", | |
" label = folium.Popup(str(poi) + \" Cluster \" + str(cluster), parse_html=True)\n", | |
"\n", | |
" cluster = int(cluster)\n", | |
" folium.CircleMarker(\n", | |
" [lat, lon],\n", | |
" radius=5,\n", | |
" popup=label,\n", | |
" color=rainbow[cluster - 1],\n", | |
" fill=True,\n", | |
" fill_color=rainbow[cluster - 1],\n", | |
" fill_opacity=0.7,\n", | |
" ).add_to(map_clusters)\n", | |
"\n", | |
" return map_clusters" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 225, | |
"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+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgCiAgICAgICAgPHNjcmlwdD4KICAgICAgICAgICAgTF9OT19UT1VDSCA9IGZhbHNlOwogICAgICAgICAgICBMX0RJU0FCTEVfM0QgPSBmYWxzZTsKICAgICAgICA8L3NjcmlwdD4KICAgIAogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjYuMC9kaXN0L2xlYWZsZXQuanMiPjwvc2NyaXB0PgogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY29kZS5qcXVlcnkuY29tL2pxdWVyeS0xLjEyLjQubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9qcy9ib290c3RyYXAubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5qcyI+PC9zY3JpcHQ+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjYuMC9kaXN0L2xlYWZsZXQuY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vYm9vdHN0cmFwLzMuMi4wL2Nzcy9ib290c3RyYXAubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLXRoZW1lLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9mb250LWF3ZXNvbWUvNC42LjMvY3NzL2ZvbnQtYXdlc29tZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL0xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLzIuMC4yL2xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL3Jhd2Nkbi5naXRoYWNrLmNvbS9weXRob24tdmlzdWFsaXphdGlvbi9mb2xpdW0vbWFzdGVyL2ZvbGl1bS90ZW1wbGF0ZXMvbGVhZmxldC5hd2Vzb21lLnJvdGF0ZS5jc3MiLz4KICAgIDxzdHlsZT5odG1sLCBib2R5IHt3aWR0aDogMTAwJTtoZWlnaHQ6IDEwMCU7bWFyZ2luOiAwO3BhZGRpbmc6IDA7fTwvc3R5bGU+CiAgICA8c3R5bGU+I21hcCB7cG9zaXRpb246YWJzb2x1dGU7dG9wOjA7Ym90dG9tOjA7cmlnaHQ6MDtsZWZ0OjA7fTwvc3R5bGU+CiAgICAKICAgICAgICAgICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwKICAgICAgICAgICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgICAgICAgICAgPHN0eWxlPgogICAgICAgICAgICAgICAgI21hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSB7CiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlOwogICAgICAgICAgICAgICAgICAgIHdpZHRoOiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgbGVmdDogMC4wJTsKICAgICAgICAgICAgICAgICAgICB0b3A6IDAuMCU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDwvc3R5bGU+CiAgICAgICAgCjwvaGVhZD4KPGJvZHk+ICAgIAogICAgCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvbGl1bS1tYXAiIGlkPSJtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUiID48L2Rpdj4KICAgICAgICAKPC9ib2R5Pgo8c2NyaXB0PiAgICAKICAgIAogICAgICAgICAgICB2YXIgbWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1ID0gTC5tYXAoCiAgICAgICAgICAgICAgICAibWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1IiwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBjZW50ZXI6IFs0My42NTM0ODE3LCAtNzkuMzgzOTM0N10sCiAgICAgICAgICAgICAgICAgICAgY3JzOiBMLkNSUy5FUFNHMzg1NywKICAgICAgICAgICAgICAgICAgICB6b29tOiAxMCwKICAgICAgICAgICAgICAgICAgICB6b29tQ29udHJvbDogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICBwcmVmZXJDYW52YXM6IGZhbHNlLAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICApOwoKICAgICAgICAgICAgCgogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciB0aWxlX2xheWVyXzVmYTg0MzBiYzg0YjQ5MGVhMjRmNzdkZTA1YjQxY2VlID0gTC50aWxlTGF5ZXIoCiAgICAgICAgICAgICAgICAiaHR0cHM6Ly97c30udGlsZS5vcGVuc3RyZWV0bWFwLm9yZy97en0ve3h9L3t5fS5wbmciLAogICAgICAgICAgICAgICAgeyJhdHRyaWJ1dGlvbiI6ICJEYXRhIGJ5IFx1MDAyNmNvcHk7IFx1MDAzY2EgaHJlZj1cImh0dHA6Ly9vcGVuc3RyZWV0bWFwLm9yZ1wiXHUwMDNlT3BlblN0cmVldE1hcFx1MDAzYy9hXHUwMDNlLCB1bmRlciBcdTAwM2NhIGhyZWY9XCJodHRwOi8vd3d3Lm9wZW5zdHJlZXRtYXAub3JnL2NvcHlyaWdodFwiXHUwMDNlT0RiTFx1MDAzYy9hXHUwMDNlLiIsICJkZXRlY3RSZXRpbmEiOiBmYWxzZSwgIm1heE5hdGl2ZVpvb20iOiAxOCwgIm1heFpvb20iOiAxOCwgIm1pblpvb20iOiAwLCAibm9XcmFwIjogZmFsc2UsICJvcGFjaXR5IjogMSwgInN1YmRvbWFpbnMiOiAiYWJjIiwgInRtcyI6IGZhbHNlfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfN2EyNzIzOTAzZmFkNDE4OTk3ZjlmNTUyNTcwNWU4ZGUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My44MDY2ODYyOTk5OTk5OTYsIC03OS4xOTQzNTM0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF8xYmY2NGZmNTBmNTE0YzhiYTY0NzA3NThiOThjYjU0MSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfZTNmZjRlZjkxZjMxNGZjZjhiYTA4ODdlYjMwZmE3MjUgPSAkKGA8ZGl2IGlkPSJodG1sX2UzZmY0ZWY5MWYzMTRmY2Y4YmEwODg3ZWIzMGZhNzI1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5NYWx2ZXJuLCBSb3VnZSBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8xYmY2NGZmNTBmNTE0YzhiYTY0NzA3NThiOThjYjU0MS5zZXRDb250ZW50KGh0bWxfZTNmZjRlZjkxZjMxNGZjZjhiYTA4ODdlYjMwZmE3MjUpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzdhMjcyMzkwM2ZhZDQxODk5N2Y5ZjU1MjU3MDVlOGRlLmJpbmRQb3B1cChwb3B1cF8xYmY2NGZmNTBmNTE0YzhiYTY0NzA3NThiOThjYjU0MSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYTMxZTJhYWM4NmIzNGVmYWE4YjcwNzk0ZDRlMjMyNzQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43ODQ1MzUxLCAtNzkuMTYwNDk3MDk5OTk5OTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfYTliNWE0Y2JjNWRmNGM1NmJjZTIxM2JiYzhiYWJlNGYgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzUyMDVkNzBhMzI1MTRmNjU5NjEzZmUxNmJlYzJlZDVkID0gJChgPGRpdiBpZD0iaHRtbF81MjA1ZDcwYTMyNTE0ZjY1OTYxM2ZlMTZiZWMyZWQ1ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Um91Z2UgSGlsbCwgUG9ydCBVbmlvbiwgSGlnaGxhbmQgQ3JlZWsgQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfYTliNWE0Y2JjNWRmNGM1NmJjZTIxM2JiYzhiYWJlNGYuc2V0Q29udGVudChodG1sXzUyMDVkNzBhMzI1MTRmNjU5NjEzZmUxNmJlYzJlZDVkKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9hMzFlMmFhYzg2YjM0ZWZhYThiNzA3OTRkNGUyMzI3NC5iaW5kUG9wdXAocG9wdXBfYTliNWE0Y2JjNWRmNGM1NmJjZTIxM2JiYzhiYWJlNGYpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2FkNzQwZTYwZDVlYTRiOWRhMTYzNzA1ZTRlNDEyMDU4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzYzNTcyNiwgLTc5LjE4ODcxMTVdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfNWI4YTA1YzRmYWQwNDEyMTllMWRkMGZhOGJiMTllMmQgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2M3MWJjYTEwYTU2MzRmY2U4OTk4YjFjYWEwMjA1OTczID0gJChgPGRpdiBpZD0iaHRtbF9jNzFiY2ExMGE1NjM0ZmNlODk5OGIxY2FhMDIwNTk3MyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+R3VpbGR3b29kLCBNb3JuaW5nc2lkZSwgV2VzdCBIaWxsIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzViOGEwNWM0ZmFkMDQxMjE5ZTFkZDBmYThiYjE5ZTJkLnNldENvbnRlbnQoaHRtbF9jNzFiY2ExMGE1NjM0ZmNlODk5OGIxY2FhMDIwNTk3Myk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfYWQ3NDBlNjBkNWVhNGI5ZGExNjM3MDVlNGU0MTIwNTguYmluZFBvcHVwKHBvcHVwXzViOGEwNWM0ZmFkMDQxMjE5ZTFkZDBmYThiYjE5ZTJkKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83NTEzY2EzNWY3YjQ0YTJlODUxNGQ1YWUyZDI1YWYyMCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc3MDk5MjEsIC03OS4yMTY5MTc0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF82MjAxYTVkZWU4N2U0OTYyYjVmNWMwOGIzYWIwOWZkYSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfZDNmYTUwNGY3NmI4NDBiYmI5NmI2MDliMzJjZmQ5OTEgPSAkKGA8ZGl2IGlkPSJodG1sX2QzZmE1MDRmNzZiODQwYmJiOTZiNjA5YjMyY2ZkOTkxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Xb2J1cm4gQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfNjIwMWE1ZGVlODdlNDk2MmI1ZjVjMDhiM2FiMDlmZGEuc2V0Q29udGVudChodG1sX2QzZmE1MDRmNzZiODQwYmJiOTZiNjA5YjMyY2ZkOTkxKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl83NTEzY2EzNWY3YjQ0YTJlODUxNGQ1YWUyZDI1YWYyMC5iaW5kUG9wdXAocG9wdXBfNjIwMWE1ZGVlODdlNDk2MmI1ZjVjMDhiM2FiMDlmZGEpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzg0ZGEzNjgxNjdmZDQ1MGFiYjdlM2E5NzM3ZWVhMWVjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzczMTM2LCAtNzkuMjM5NDc2MDk5OTk5OTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfZWI1ZjQyYjc5NGNkNDMwZjlmNTkzYTdlNjFlMzBmNjYgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzkxYjQzZTc3MTgxYzQzYmU4NDU0NjEwZTZjNmZlNzM5ID0gJChgPGRpdiBpZD0iaHRtbF85MWI0M2U3NzE4MWM0M2JlODQ1NDYxMGU2YzZmZTczOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q2VkYXJicmFlIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2ViNWY0MmI3OTRjZDQzMGY5ZjU5M2E3ZTYxZTMwZjY2LnNldENvbnRlbnQoaHRtbF85MWI0M2U3NzE4MWM0M2JlODQ1NDYxMGU2YzZmZTczOSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfODRkYTM2ODE2N2ZkNDUwYWJiN2UzYTk3MzdlZWExZWMuYmluZFBvcHVwKHBvcHVwX2ViNWY0MmI3OTRjZDQzMGY5ZjU5M2E3ZTYxZTMwZjY2KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84MDE3MWM5MGQ5ZmI0MTM1OTliOGUwNTk5NDYxNTFmYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc0NDczNDIsIC03OS4yMzk0NzYwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiI2ZmYjM2MCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjZmZiMzYwIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF8wZWIxYTM2NjhiNmY0NTg5OTUxY2U4Y2M2ZTliOTlmOCA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfNjJkZDZkZjkwMzYzNGIzM2FjYWFjNDk4OTU5NjMzYTAgPSAkKGA8ZGl2IGlkPSJodG1sXzYyZGQ2ZGY5MDM2MzRiMzNhY2FhYzQ5ODk1OTYzM2EwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TY2FyYm9yb3VnaCBWaWxsYWdlIENsdXN0ZXIgNC4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzBlYjFhMzY2OGI2ZjQ1ODk5NTFjZThjYzZlOWI5OWY4LnNldENvbnRlbnQoaHRtbF82MmRkNmRmOTAzNjM0YjMzYWNhYWM0OTg5NTk2MzNhMCk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfODAxNzFjOTBkOWZiNDEzNTk5YjhlMDU5OTQ2MTUxZmIuYmluZFBvcHVwKHBvcHVwXzBlYjFhMzY2OGI2ZjQ1ODk5NTFjZThjYzZlOWI5OWY4KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl85MjJkODYwNjhhNjQ0MWM1OGYxYTQzNWQyMTg2MDMzYSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcyNzkyOTIsIC03OS4yNjIwMjk0MDAwMDAwMl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9iZWVhNzQ4NDIwN2Q0ZTAzYmIwNmQyNjM4YTMyNTE1OSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfOTUzMTdjMzIxODNkNGUyMWFhNDE5NjI3ZDMzOTU2ZjcgPSAkKGA8ZGl2IGlkPSJodG1sXzk1MzE3YzMyMTgzZDRlMjFhYTQxOTYyN2QzMzk1NmY3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5LZW5uZWR5IFBhcmssIElvbnZpZXcsIEVhc3QgQmlyY2htb3VudCBQYXJrIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2JlZWE3NDg0MjA3ZDRlMDNiYjA2ZDI2MzhhMzI1MTU5LnNldENvbnRlbnQoaHRtbF85NTMxN2MzMjE4M2Q0ZTIxYWE0MTk2MjdkMzM5NTZmNyk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfOTIyZDg2MDY4YTY0NDFjNThmMWE0MzVkMjE4NjAzM2EuYmluZFBvcHVwKHBvcHVwX2JlZWE3NDg0MjA3ZDRlMDNiYjA2ZDI2MzhhMzI1MTU5KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kMWI3ODgyZjM3ZDc0MjA2OGM2YmViYjYzNDhhODg0MiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcxMTExMTcwMDAwMDAwNCwgLTc5LjI4NDU3NzJdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfZmFmN2ViNTc3Mjk2NGFiZjkzMTViYzBlMDY0YjgzM2MgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzY0NWY3NjM5ZTlmZTQ2ZTA4ODBjNmM2ZjY5ZWU1ODEzID0gJChgPGRpdiBpZD0iaHRtbF82NDVmNzYzOWU5ZmU0NmUwODgwYzZjNmY2OWVlNTgxMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+R29sZGVuIE1pbGUsIENsYWlybGVhLCBPYWtyaWRnZSBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9mYWY3ZWI1NzcyOTY0YWJmOTMxNWJjMGUwNjRiODMzYy5zZXRDb250ZW50KGh0bWxfNjQ1Zjc2MzllOWZlNDZlMDg4MGM2YzZmNjllZTU4MTMpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2QxYjc4ODJmMzdkNzQyMDY4YzZiZWJiNjM0OGE4ODQyLmJpbmRQb3B1cChwb3B1cF9mYWY3ZWI1NzcyOTY0YWJmOTMxNWJjMGUwNjRiODMzYykKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZGI1M2EyMDY1MjQ4NDM3NGIyNDJhNTVhY2JlN2MxZjIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MTYzMTYsIC03OS4yMzk0NzYwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF81YjBiZWRhYWVjMzQ0ZmY3OTNmZjdhMTc4YWM4ZjE0YiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfZWRiZmY5NTAyMmI5NGRlY2FiOTQwYzIzZmQ5MDE1YzMgPSAkKGA8ZGl2IGlkPSJodG1sX2VkYmZmOTUwMjJiOTRkZWNhYjk0MGMyM2ZkOTAxNWMzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DbGlmZnNpZGUsIENsaWZmY3Jlc3QsIFNjYXJib3JvdWdoIFZpbGxhZ2UgV2VzdCBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF81YjBiZWRhYWVjMzQ0ZmY3OTNmZjdhMTc4YWM4ZjE0Yi5zZXRDb250ZW50KGh0bWxfZWRiZmY5NTAyMmI5NGRlY2FiOTQwYzIzZmQ5MDE1YzMpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2RiNTNhMjA2NTI0ODQzNzRiMjQyYTU1YWNiZTdjMWYyLmJpbmRQb3B1cChwb3B1cF81YjBiZWRhYWVjMzQ0ZmY3OTNmZjdhMTc4YWM4ZjE0YikKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfY2YwMzgyNWMxZTFkNDU0Y2FjZjcyZjI2OGM5MTc5ODEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42OTI2NTcwMDAwMDAwMDQsIC03OS4yNjQ4NDgxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzQzNzBmNGJjMzRjOTRiZmY5ZTBkZDI2ZTU1MzM2YzYyID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9jYjcyYTdiMjAzMDA0OWM2OGUyNWE3YmFlODk3MzY4YSA9ICQoYDxkaXYgaWQ9Imh0bWxfY2I3MmE3YjIwMzAwNDljNjhlMjVhN2JhZTg5NzM2OGEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJpcmNoIENsaWZmLCBDbGlmZnNpZGUgV2VzdCBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF80MzcwZjRiYzM0Yzk0YmZmOWUwZGQyNmU1NTMzNmM2Mi5zZXRDb250ZW50KGh0bWxfY2I3MmE3YjIwMzAwNDljNjhlMjVhN2JhZTg5NzM2OGEpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2NmMDM4MjVjMWUxZDQ1NGNhY2Y3MmYyNjhjOTE3OTgxLmJpbmRQb3B1cChwb3B1cF80MzcwZjRiYzM0Yzk0YmZmOWUwZGQyNmU1NTMzNmM2MikKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNGFkYmFlZTY2YmIwNDE3Nzg3NDUwN2IyZjA4YjRiNjcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NTc0MDk2LCAtNzkuMjczMzA0MDAwMDAwMDFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfNmQ0M2NlNzU0ZWUzNDY4ZGE3MDVlYzc5M2FhYjljN2EgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2JhYzc4OTExYTRlOTRmODY4NjU0ZDBjNDY0ZDU3M2NmID0gJChgPGRpdiBpZD0iaHRtbF9iYWM3ODkxMWE0ZTk0Zjg2ODY1NGQwYzQ2NGQ1NzNjZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RG9yc2V0IFBhcmssIFdleGZvcmQgSGVpZ2h0cywgU2NhcmJvcm91Z2ggVG93biBDZW50cmUgQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfNmQ0M2NlNzU0ZWUzNDY4ZGE3MDVlYzc5M2FhYjljN2Euc2V0Q29udGVudChodG1sX2JhYzc4OTExYTRlOTRmODY4NjU0ZDBjNDY0ZDU3M2NmKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl80YWRiYWVlNjZiYjA0MTc3ODc0NTA3YjJmMDhiNGI2Ny5iaW5kUG9wdXAocG9wdXBfNmQ0M2NlNzU0ZWUzNDY4ZGE3MDVlYzc5M2FhYjljN2EpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzYyOWFlNTU0YjYxZjRlNjBiODcwODk4NzgwZTdjYmU2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzUwMDcxNTAwMDAwMDA0LCAtNzkuMjk1ODQ5MV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9hN2QxYzlkNzg3MDA0YjBmYjgzZDcxNTg0NTkwZDgyMSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfNGJlNzczYzU4NmQ4NGZiNWFjMzJlZTczNGZmMmQ4YmUgPSAkKGA8ZGl2IGlkPSJodG1sXzRiZTc3M2M1ODZkODRmYjVhYzMyZWU3MzRmZjJkOGJlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XZXhmb3JkLCBNYXJ5dmFsZSBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9hN2QxYzlkNzg3MDA0YjBmYjgzZDcxNTg0NTkwZDgyMS5zZXRDb250ZW50KGh0bWxfNGJlNzczYzU4NmQ4NGZiNWFjMzJlZTczNGZmMmQ4YmUpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzYyOWFlNTU0YjYxZjRlNjBiODcwODk4NzgwZTdjYmU2LmJpbmRQb3B1cChwb3B1cF9hN2QxYzlkNzg3MDA0YjBmYjgzZDcxNTg0NTkwZDgyMSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNjk1NjZmYzRkODAzNDc0NGE5ODU3OTIwNjkzMmYyMzkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43OTQyMDAzLCAtNzkuMjYyMDI5NDAwMDAwMDJdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfZjZjZmE0MzJmNzE0NGZhMTk1ZmUwNmIyMTA3MTEwYTMgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzdiMTk0OTkyMTIxMjQ0MTA5OWVlYTJhOWEyMGIyM2JmID0gJChgPGRpdiBpZD0iaHRtbF83YjE5NDk5MjEyMTI0NDEwOTllZWEyYTlhMjBiMjNiZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QWdpbmNvdXJ0IENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2Y2Y2ZhNDMyZjcxNDRmYTE5NWZlMDZiMjEwNzExMGEzLnNldENvbnRlbnQoaHRtbF83YjE5NDk5MjEyMTI0NDEwOTllZWEyYTlhMjBiMjNiZik7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNjk1NjZmYzRkODAzNDc0NGE5ODU3OTIwNjkzMmYyMzkuYmluZFBvcHVwKHBvcHVwX2Y2Y2ZhNDMyZjcxNDRmYTE5NWZlMDZiMjEwNzExMGEzKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yODllMjFmMjZlMmY0MmRkYWI5ODY3ZTBlOGQ0MDQ3NyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc4MTYzNzUsIC03OS4zMDQzMDIxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzZlZjUyNjY4YWRjZTQ2NzlhMjliMzdiZWY5MzMwMWU2ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF82MjJjN2VlNmVkNzQ0MWI5YWIxZDEwZTQ0NGY0NjJlYyA9ICQoYDxkaXYgaWQ9Imh0bWxfNjIyYzdlZTZlZDc0NDFiOWFiMWQxMGU0NDRmNDYyZWMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNsYXJrcyBDb3JuZXJzLCBUYW0gTyYjMzk7U2hhbnRlciwgU3VsbGl2YW4gQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfNmVmNTI2NjhhZGNlNDY3OWEyOWIzN2JlZjkzMzAxZTYuc2V0Q29udGVudChodG1sXzYyMmM3ZWU2ZWQ3NDQxYjlhYjFkMTBlNDQ0ZjQ2MmVjKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl8yODllMjFmMjZlMmY0MmRkYWI5ODY3ZTBlOGQ0MDQ3Ny5iaW5kUG9wdXAocG9wdXBfNmVmNTI2NjhhZGNlNDY3OWEyOWIzN2JlZjkzMzAxZTYpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzFmY2E1ZGFhYzhkYzQyNzU4ZGYwNzQwNjUxZjkyMDFjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuODE1MjUyMiwgLTc5LjI4NDU3NzJdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiNmZjAwMDAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfNTA0ZTg1YzJkNzViNDZmNmE3YTc5ZGI5ZTVmYTk1YzcgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzQxODgzMmQyN2U4ZjRhZTE4OTlmMGFlY2JmOGJhOTk4ID0gJChgPGRpdiBpZD0iaHRtbF80MTg4MzJkMjdlOGY0YWUxODk5ZjBhZWNiZjhiYTk5OCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TWlsbGlrZW4sIEFnaW5jb3VydCBOb3J0aCwgU3RlZWxlcyBFYXN0LCBMJiMzOTtBbW9yZWF1eCBFYXN0IENsdXN0ZXIgMC4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzUwNGU4NWMyZDc1YjQ2ZjZhN2E3OWRiOWU1ZmE5NWM3LnNldENvbnRlbnQoaHRtbF80MTg4MzJkMjdlOGY0YWUxODk5ZjBhZWNiZjhiYTk5OCk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMWZjYTVkYWFjOGRjNDI3NThkZjA3NDA2NTFmOTIwMWMuYmluZFBvcHVwKHBvcHVwXzUwNGU4NWMyZDc1YjQ2ZjZhN2E3OWRiOWU1ZmE5NWM3KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jMGVkY2Q2ZDY4MDg0MmZhOWE2ZjhlY2ZkYTEzNjZkNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc5OTUyNTIwMDAwMDAwNSwgLTc5LjMxODM4ODddLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfOTRiZmFiZGQyY2ViNDkzY2FmZDg1ZWIzZjk5NDNkOGUgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzIwYWE3MTgxOTViMjQ5MWI5NWVjNGNhZDI1ZDMzNmIzID0gJChgPGRpdiBpZD0iaHRtbF8yMGFhNzE4MTk1YjI0OTFiOTVlYzRjYWQyNWQzMzZiMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3RlZWxlcyBXZXN0LCBMJiMzOTtBbW9yZWF1eCBXZXN0IENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzk0YmZhYmRkMmNlYjQ5M2NhZmQ4NWViM2Y5OTQzZDhlLnNldENvbnRlbnQoaHRtbF8yMGFhNzE4MTk1YjI0OTFiOTVlYzRjYWQyNWQzMzZiMyk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfYzBlZGNkNmQ2ODA4NDJmYTlhNmY4ZWNmZGExMzY2ZDQuYmluZFBvcHVwKHBvcHVwXzk0YmZhYmRkMmNlYjQ5M2NhZmQ4NWViM2Y5OTQzZDhlKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kZDUxNzkxYmM2OTg0YmE4YTJhMmQyYzNhZDY1NzAxYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjgwMzc2MjIsIC03OS4zNjM0NTE3XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2NiOTc1MWE3MGM3NDRkZjk4N2EzZTRhY2MwM2Y4ZTI1ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF80MGU3MTA1OWVjYmI0MzVhYTA4YjI5NTdkZjU4YTE1OCA9ICQoYDxkaXYgaWQ9Imh0bWxfNDBlNzEwNTllY2JiNDM1YWEwOGIyOTU3ZGY1OGExNTgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhpbGxjcmVzdCBWaWxsYWdlIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2NiOTc1MWE3MGM3NDRkZjk4N2EzZTRhY2MwM2Y4ZTI1LnNldENvbnRlbnQoaHRtbF80MGU3MTA1OWVjYmI0MzVhYTA4YjI5NTdkZjU4YTE1OCk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfZGQ1MTc5MWJjNjk4NGJhOGEyYTJkMmMzYWQ2NTcwMWIuYmluZFBvcHVwKHBvcHVwX2NiOTc1MWE3MGM3NDRkZjk4N2EzZTRhY2MwM2Y4ZTI1KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wN2RmZWM0NTBkN2M0YmQ4YjJkNTU5OGY5ZmJiM2EwOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc3ODUxNzUsIC03OS4zNDY1NTU3XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzVlOTRhMTgxOGRmNjRhMDFiNWVmOTc5YzlkODdmMjI1ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF8yNGRkODZkMTRhMTU0N2QyYmFkZTQyOWE0Y2ZhZGI3ZiA9ICQoYDxkaXYgaWQ9Imh0bWxfMjRkZDg2ZDE0YTE1NDdkMmJhZGU0MjlhNGNmYWRiN2YiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZhaXJ2aWV3LCBIZW5yeSBGYXJtLCBPcmlvbGUgQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfNWU5NGExODE4ZGY2NGEwMWI1ZWY5NzljOWQ4N2YyMjUuc2V0Q29udGVudChodG1sXzI0ZGQ4NmQxNGExNTQ3ZDJiYWRlNDI5YTRjZmFkYjdmKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl8wN2RmZWM0NTBkN2M0YmQ4YjJkNTU5OGY5ZmJiM2EwOC5iaW5kUG9wdXAocG9wdXBfNWU5NGExODE4ZGY2NGEwMWI1ZWY5NzljOWQ4N2YyMjUpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzc2NTU3NzJmNjkyODRmMjE5Yzk0Y2E3ZTAxM2UwMTQ5ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzg2OTQ3MywgLTc5LjM4NTk3NV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9mYmQ3ZjkyODkyZGQ0OTE0YTk0NzFjZDA4NjI1YTI2MCA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfMzA2ZWMyOGU0ZGI2NGFiYzhmODBhZjBhMjU2ZjMyNTEgPSAkKGA8ZGl2IGlkPSJodG1sXzMwNmVjMjhlNGRiNjRhYmM4ZjgwYWYwYTI1NmYzMjUxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CYXl2aWV3IFZpbGxhZ2UgQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfZmJkN2Y5Mjg5MmRkNDkxNGE5NDcxY2QwODYyNWEyNjAuc2V0Q29udGVudChodG1sXzMwNmVjMjhlNGRiNjRhYmM4ZjgwYWYwYTI1NmYzMjUxKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl83NjU1NzcyZjY5Mjg0ZjIxOWM5NGNhN2UwMTNlMDE0OS5iaW5kUG9wdXAocG9wdXBfZmJkN2Y5Mjg5MmRkNDkxNGE5NDcxY2QwODYyNWEyNjApCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzAzMmU2OTc0ZDI2ODRkYTZhNmU5ZDhiOTU2Mjc4NDUxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzU3NDkwMiwgLTc5LjM3NDcxNDA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDBiNWViIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiMwMGI1ZWIiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2Q0MmNkMTY5MzBkMjQ0YjJhZDQ0NjlhMTM4NGNmZmQ3ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9iMWYzMmI5MmFmMDQ0MTBjOTNhNTg5ZjgzNzA3NzYxNyA9ICQoYDxkaXYgaWQ9Imh0bWxfYjFmMzJiOTJhZjA0NDEwYzkzYTU4OWY4MzcwNzc2MTciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPllvcmsgTWlsbHMsIFNpbHZlciBIaWxscyBDbHVzdGVyIDIuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9kNDJjZDE2OTMwZDI0NGIyYWQ0NDY5YTEzODRjZmZkNy5zZXRDb250ZW50KGh0bWxfYjFmMzJiOTJhZjA0NDEwYzkzYTU4OWY4MzcwNzc2MTcpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzAzMmU2OTc0ZDI2ODRkYTZhNmU5ZDhiOTU2Mjc4NDUxLmJpbmRQb3B1cChwb3B1cF9kNDJjZDE2OTMwZDI0NGIyYWQ0NDY5YTEzODRjZmZkNykKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDUzYWRhNzdiNmUxNDcxNmE5NWVjMjJiOWZjZjZhZDMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43ODkwNTMsIC03OS40MDg0OTI3OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiI2ZmMDAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9jZDFiY2YzNWFmNjg0OGNmOTI2NDNhY2ZlMDRjZDI3NiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfYjcyOGVhYWYxZGYwNDhmNDgyMzJkMjc4MWIzNGI1YjIgPSAkKGA8ZGl2IGlkPSJodG1sX2I3MjhlYWFmMWRmMDQ4ZjQ4MjMyZDI3ODFiMzRiNWIyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XaWxsb3dkYWxlLCBOZXd0b25icm9vayBDbHVzdGVyIDAuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9jZDFiY2YzNWFmNjg0OGNmOTI2NDNhY2ZlMDRjZDI3Ni5zZXRDb250ZW50KGh0bWxfYjcyOGVhYWYxZGYwNDhmNDgyMzJkMjc4MWIzNGI1YjIpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzQ1M2FkYTc3YjZlMTQ3MTZhOTVlYzIyYjlmY2Y2YWQzLmJpbmRQb3B1cChwb3B1cF9jZDFiY2YzNWFmNjg0OGNmOTI2NDNhY2ZlMDRjZDI3NikKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODEzZmJjYTFiNjc2NGUzZmJiZjJiY2UxNDRlNzI5MmYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NzAxMTk5LCAtNzkuNDA4NDkyNzk5OTk5OTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfZDViOTU0Y2Y0ZTQ0NDgzNmJjY2FiYzFjOTI0MTIxM2QgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzE1YWI2YjU2MzY1ZjQwOGJiN2QwMWQwNTdjZmIzYTQ3ID0gJChgPGRpdiBpZD0iaHRtbF8xNWFiNmI1NjM2NWY0MDhiYjdkMDFkMDU3Y2ZiM2E0NyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2lsbG93ZGFsZSwgV2lsbG93ZGFsZSBFYXN0IENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2Q1Yjk1NGNmNGU0NDQ4MzZiY2NhYmMxYzkyNDEyMTNkLnNldENvbnRlbnQoaHRtbF8xNWFiNmI1NjM2NWY0MDhiYjdkMDFkMDU3Y2ZiM2E0Nyk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfODEzZmJjYTFiNjc2NGUzZmJiZjJiY2UxNDRlNzI5MmYuYmluZFBvcHVwKHBvcHVwX2Q1Yjk1NGNmNGU0NDQ4MzZiY2NhYmMxYzkyNDEyMTNkKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82MjYxYjY1MTg2MTc0NWI5ODMyODEyYjRmODNmMTUwNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc1Mjc1ODI5OTk5OTk5NiwgLTc5LjQwMDA0OTNdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiNmZjAwMDAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMGE1ZDU1MTIxMjE1NDUyZWEzZDgxYTJhMjQ2MzU5OTkgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzExZGQ3M2JlNTgzMjQ3YWRhNWE3YTc1ZTgwZWM4OTk1ID0gJChgPGRpdiBpZD0iaHRtbF8xMWRkNzNiZTU4MzI0N2FkYTVhN2E3NWU4MGVjODk5NSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+WW9yayBNaWxscyBXZXN0IENsdXN0ZXIgMC4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzBhNWQ1NTEyMTIxNTQ1MmVhM2Q4MWEyYTI0NjM1OTk5LnNldENvbnRlbnQoaHRtbF8xMWRkNzNiZTU4MzI0N2FkYTVhN2E3NWU4MGVjODk5NSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNjI2MWI2NTE4NjE3NDViOTgzMjgxMmI0ZjgzZjE1MDUuYmluZFBvcHVwKHBvcHVwXzBhNWQ1NTEyMTIxNTQ1MmVhM2Q4MWEyYTI0NjM1OTk5KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yN2E5ODIzNjY3OWI0N2E0YWIzN2IyNTQ3YWIzYmMyNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc4MjczNjQsIC03OS40NDIyNTkzXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzZlZDkxYmRmNGQ5MzQwMGY4MmMxNDRhM2JjZGM5YjFkID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF8yMThmYWZjYmI4OTM0NTQyOTcwZTk2ZWIzNTQ2NWJlMSA9ICQoYDxkaXYgaWQ9Imh0bWxfMjE4ZmFmY2JiODkzNDU0Mjk3MGU5NmViMzU0NjViZTEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldpbGxvd2RhbGUsIFdpbGxvd2RhbGUgV2VzdCBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF82ZWQ5MWJkZjRkOTM0MDBmODJjMTQ0YTNiY2RjOWIxZC5zZXRDb250ZW50KGh0bWxfMjE4ZmFmY2JiODkzNDU0Mjk3MGU5NmViMzU0NjViZTEpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzI3YTk4MjM2Njc5YjQ3YTRhYjM3YjI1NDdhYjNiYzI3LmJpbmRQb3B1cChwb3B1cF82ZWQ5MWJkZjRkOTM0MDBmODJjMTQ0YTNiY2RjOWIxZCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMDRhYmY0MGE2NWFlNDI0ZjgyOTdlY2ZhODQ5MGJhOGUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NTMyNTg2LCAtNzkuMzI5NjU2NV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiI2ZmMDAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF85MzVhYTYwNjNiMzE0MjAzOGEzN2I0OTRiOGFmZGNkYiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfODg2NDhkODI0YzkwNDYzYmExZjc2MzNlNzAyZDQ5YzcgPSAkKGA8ZGl2IGlkPSJodG1sXzg4NjQ4ZDgyNGM5MDQ2M2JhMWY3NjMzZTcwMmQ0OWM3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5QYXJrd29vZHMgQ2x1c3RlciAwLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfOTM1YWE2MDYzYjMxNDIwMzhhMzdiNDk0YjhhZmRjZGIuc2V0Q29udGVudChodG1sXzg4NjQ4ZDgyNGM5MDQ2M2JhMWY3NjMzZTcwMmQ0OWM3KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl8wNGFiZjQwYTY1YWU0MjRmODI5N2VjZmE4NDkwYmE4ZS5iaW5kUG9wdXAocG9wdXBfOTM1YWE2MDYzYjMxNDIwMzhhMzdiNDk0YjhhZmRjZGIpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzYzMzhkMDYxOWU4ZDQ3Mjk4YmRkODRmNzliZDFkYjBiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzQ1OTA1Nzk5OTk5OTk2LCAtNzkuMzUyMTg4XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzdlZmJhODg2Zjc4ZDQyZjhiYjQ1NWI2NWI4OTc5MWEzID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF8yZTkxZWU4YzE3MzQ0YzljYjI1NWI1N2Y4NzkwNTY4ZSA9ICQoYDxkaXYgaWQ9Imh0bWxfMmU5MWVlOGMxNzM0NGM5Y2IyNTViNTdmODc5MDU2OGUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvbiBNaWxscyBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF83ZWZiYTg4NmY3OGQ0MmY4YmI0NTViNjViODk3OTFhMy5zZXRDb250ZW50KGh0bWxfMmU5MWVlOGMxNzM0NGM5Y2IyNTViNTdmODc5MDU2OGUpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzYzMzhkMDYxOWU4ZDQ3Mjk4YmRkODRmNzliZDFkYjBiLmJpbmRQb3B1cChwb3B1cF83ZWZiYTg4NmY3OGQ0MmY4YmI0NTViNjViODk3OTFhMykKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjQ2MTdlM2ZkMzI2NGQwN2JhYTI4NTEyOTQ3NzI0ZjQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MjU4OTk3MDAwMDAwMSwgLTc5LjM0MDkyM10sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF8xZDU3ZWI2Njc0ODg0NDUyOTIzMWI4MjYyNzAwYTUyOCA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfNzZjNTQwZjMzZGIyNDIwMmI1Y2U5ODUxYzU0MDA5NjQgPSAkKGA8ZGl2IGlkPSJodG1sXzc2YzU0MGYzM2RiMjQyMDJiNWNlOTg1MWM1NDAwOTY0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Eb24gTWlsbHMgQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfMWQ1N2ViNjY3NDg4NDQ1MjkyMzFiODI2MjcwMGE1Mjguc2V0Q29udGVudChodG1sXzc2YzU0MGYzM2RiMjQyMDJiNWNlOTg1MWM1NDAwOTY0KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9mNDYxN2UzZmQzMjY0ZDA3YmFhMjg1MTI5NDc3MjRmNC5iaW5kUG9wdXAocG9wdXBfMWQ1N2ViNjY3NDg4NDQ1MjkyMzFiODI2MjcwMGE1MjgpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2IwZTYwMzEwZTkzNjRiY2E5OTU0YjBjZjZkZjY2NTExID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzU0MzI4MywgLTc5LjQ0MjI1OTNdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMzMzOTg1M2JjNTIxNDQ3YzlhNjgyYTk5ZTZmNjdlZjAgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzk1NDYyOTEzZWE5YTRhZjdiY2QzZGFiNDBiOWQyZDgwID0gJChgPGRpdiBpZD0iaHRtbF85NTQ2MjkxM2VhOWE0YWY3YmNkM2RhYjQwYjlkMmQ4MCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmF0aHVyc3QgTWFub3IsIFdpbHNvbiBIZWlnaHRzLCBEb3duc3ZpZXcgTm9ydGggQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfMzMzOTg1M2JjNTIxNDQ3YzlhNjgyYTk5ZTZmNjdlZjAuc2V0Q29udGVudChodG1sXzk1NDYyOTEzZWE5YTRhZjdiY2QzZGFiNDBiOWQyZDgwKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9iMGU2MDMxMGU5MzY0YmNhOTk1NGIwY2Y2ZGY2NjUxMS5iaW5kUG9wdXAocG9wdXBfMzMzOTg1M2JjNTIxNDQ3YzlhNjgyYTk5ZTZmNjdlZjApCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2ZlNjQ5ODUzMGJiNDRlN2JhMzYzZjI2Mzk5ZGI0MGNmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzY3OTgwMywgLTc5LjQ4NzI2MTkwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2QzNTFmZDVhZDAwZjQxNDY4NzdmMzg1NjAyNDFhYTE5ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF8yOTI0YmI4YTE3ZGI0Yjk1OWVjYjA0NjZlODRiMTY1YiA9ICQoYDxkaXYgaWQ9Imh0bWxfMjkyNGJiOGExN2RiNGI5NTllY2IwNDY2ZTg0YjE2NWIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5vcnRod29vZCBQYXJrLCBZb3JrIFVuaXZlcnNpdHkgQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfZDM1MWZkNWFkMDBmNDE0Njg3N2YzODU2MDI0MWFhMTkuc2V0Q29udGVudChodG1sXzI5MjRiYjhhMTdkYjRiOTU5ZWNiMDQ2NmU4NGIxNjViKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9mZTY0OTg1MzBiYjQ0ZTdiYTM2M2YyNjM5OWRiNDBjZi5iaW5kUG9wdXAocG9wdXBfZDM1MWZkNWFkMDBmNDE0Njg3N2YzODU2MDI0MWFhMTkpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzAyMzViMGVkZTliYjRkNzE4NDZlNDU3Njc5YjQ3YWE2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzM3NDczMjAwMDAwMDA0LCAtNzkuNDY0NzYzMjk5OTk5OTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMGI1OTg2NGEwMGYyNDRhNjkyM2ZjNTRkM2FmMDEwODkgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2QyOGIzYzBmNTFiMzQ5ODdhN2E5ZTE0ZmFkODkwNmZhID0gJChgPGRpdiBpZD0iaHRtbF9kMjhiM2MwZjUxYjM0OTg3YTdhOWUxNGZhZDg5MDZmYSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RG93bnN2aWV3IENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzBiNTk4NjRhMDBmMjQ0YTY5MjNmYzU0ZDNhZjAxMDg5LnNldENvbnRlbnQoaHRtbF9kMjhiM2MwZjUxYjM0OTg3YTdhOWUxNGZhZDg5MDZmYSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMDIzNWIwZWRlOWJiNGQ3MTg0NmU0NTc2NzliNDdhYTYuYmluZFBvcHVwKHBvcHVwXzBiNTk4NjRhMDBmMjQ0YTY5MjNmYzU0ZDNhZjAxMDg5KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83MDYzM2Y0ODdkMzE0ZWZiYWQ0YmY2NDRiZDBhZTBjNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjczOTAxNDYsIC03OS41MDY5NDM2XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzM4M2IzZTNkOGMzNjRiNmNhOTZlYzdmNmVhZjNkNDM3ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9iZmI4YTk1NDAwYjM0MWZjYTQzM2M0MjFiZmU5ZmQ4MyA9ICQoYDxkaXYgaWQ9Imh0bWxfYmZiOGE5NTQwMGIzNDFmY2E0MzNjNDIxYmZlOWZkODMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvd25zdmlldyBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8zODNiM2UzZDhjMzY0YjZjYTk2ZWM3ZjZlYWYzZDQzNy5zZXRDb250ZW50KGh0bWxfYmZiOGE5NTQwMGIzNDFmY2E0MzNjNDIxYmZlOWZkODMpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzcwNjMzZjQ4N2QzMTRlZmJhZDRiZjY0NGJkMGFlMGM0LmJpbmRQb3B1cChwb3B1cF8zODNiM2UzZDhjMzY0YjZjYTk2ZWM3ZjZlYWYzZDQzNykKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMjY1OTlkOGViY2EzNGQ1NWIwZTE0Zjk2MTE0YTQ1OGQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43Mjg0OTY0LCAtNzkuNDk1Njk3NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfNmI1MTc2NmMxMGI4NGEyYzg4NTMyMDFjM2FiOTM5ZWMgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2NmMThkZmEwZGRkODQyYWJhNmQxNGQxOGI4M2FjZTQ5ID0gJChgPGRpdiBpZD0iaHRtbF9jZjE4ZGZhMGRkZDg0MmFiYTZkMTRkMThiODNhY2U0OSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RG93bnN2aWV3IENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzZiNTE3NjZjMTBiODRhMmM4ODUzMjAxYzNhYjkzOWVjLnNldENvbnRlbnQoaHRtbF9jZjE4ZGZhMGRkZDg0MmFiYTZkMTRkMThiODNhY2U0OSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMjY1OTlkOGViY2EzNGQ1NWIwZTE0Zjk2MTE0YTQ1OGQuYmluZFBvcHVwKHBvcHVwXzZiNTE3NjZjMTBiODRhMmM4ODUzMjAxYzNhYjkzOWVjKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yMjQ3NDBhNjQyYTQ0OWZhOWMzOWU4ZTQ2ZmYyOTE1YyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjc2MTYzMTMsIC03OS41MjA5OTk0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF80N2M3YWRkZDFjNDA0MjUxYTU1NmM0ZDdjNTk4OTZhYyA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfZGUzY2VhNDNjNjM5NDQ4ZjgyMmZjMzhkNGZjM2M4NDcgPSAkKGA8ZGl2IGlkPSJodG1sX2RlM2NlYTQzYzYzOTQ0OGY4MjJmYzM4ZDRmYzNjODQ3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Eb3duc3ZpZXcgQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfNDdjN2FkZGQxYzQwNDI1MWE1NTZjNGQ3YzU5ODk2YWMuc2V0Q29udGVudChodG1sX2RlM2NlYTQzYzYzOTQ0OGY4MjJmYzM4ZDRmYzNjODQ3KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl8yMjQ3NDBhNjQyYTQ0OWZhOWMzOWU4ZTQ2ZmYyOTE1Yy5iaW5kUG9wdXAocG9wdXBfNDdjN2FkZGQxYzQwNDI1MWE1NTZjNGQ3YzU5ODk2YWMpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2ZhMDkzNTQwMmU5NDRmN2M4MWZlZTVlYTdkNDUwODE2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzI1ODgyMjk5OTk5OTk1LCAtNzkuMzE1NTcxNTk5OTk5OThdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMGFmNjg3OWUxMjBjNDkyODgwN2JiYTljMGU1N2MxMTAgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzE1NzM1ZmUxMzVjNjQwNzFhYjhkZjhkZWUyMWNmNjhmID0gJChgPGRpdiBpZD0iaHRtbF8xNTczNWZlMTM1YzY0MDcxYWI4ZGY4ZGVlMjFjZjY4ZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VmljdG9yaWEgVmlsbGFnZSBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8wYWY2ODc5ZTEyMGM0OTI4ODA3YmJhOWMwZTU3YzExMC5zZXRDb250ZW50KGh0bWxfMTU3MzVmZTEzNWM2NDA3MWFiOGRmOGRlZTIxY2Y2OGYpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2ZhMDkzNTQwMmU5NDRmN2M4MWZlZTVlYTdkNDUwODE2LmJpbmRQb3B1cChwb3B1cF8wYWY2ODc5ZTEyMGM0OTI4ODA3YmJhOWMwZTU3YzExMCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZmM4NjllNzQ4Y2FiNGM5ZDlhOGY4Yzc1ODhlZjYzYTkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MDYzOTcyLCAtNzkuMzA5OTM3XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2E1MjczZjg3NGVmZDQ4Yjg5NzZiOWE4MGExM2MxZTY3ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9hOGJmODI2YWU4NjE0Nzc3ODQ4YTAxNWM2OTRkYzExNiA9ICQoYDxkaXYgaWQ9Imh0bWxfYThiZjgyNmFlODYxNDc3Nzg0OGEwMTVjNjk0ZGMxMTYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlBhcmt2aWV3IEhpbGwsIFdvb2RiaW5lIEdhcmRlbnMgQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfYTUyNzNmODc0ZWZkNDhiODk3NmI5YTgwYTEzYzFlNjcuc2V0Q29udGVudChodG1sX2E4YmY4MjZhZTg2MTQ3Nzc4NDhhMDE1YzY5NGRjMTE2KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9mYzg2OWU3NDhjYWI0YzlkOWE4ZjhjNzU4OGVmNjNhOS5iaW5kUG9wdXAocG9wdXBfYTUyNzNmODc0ZWZkNDhiODk3NmI5YTgwYTEzYzFlNjcpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzIyY2UwNGE4OWM5YTRmMzA5NDQ2YzBkMWNmODNjOTcxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjk1MzQzOTAwMDAwMDA1LCAtNzkuMzE4Mzg4N10sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF8zMjYyODg5ZmY2MjM0ZjI2OGE5ZmQ3NzQyZjkwOWI3MiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfOTRkZjY5YjdlZDIxNDJhYmEyNzM5M2FjZDc4NmVhYTUgPSAkKGA8ZGl2IGlkPSJodG1sXzk0ZGY2OWI3ZWQyMTQyYWJhMjczOTNhY2Q3ODZlYWE1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Xb29kYmluZSBIZWlnaHRzIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzMyNjI4ODlmZjYyMzRmMjY4YTlmZDc3NDJmOTA5YjcyLnNldENvbnRlbnQoaHRtbF85NGRmNjliN2VkMjE0MmFiYTI3MzkzYWNkNzg2ZWFhNSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMjJjZTA0YTg5YzlhNGYzMDk0NDZjMGQxY2Y4M2M5NzEuYmluZFBvcHVwKHBvcHVwXzMyNjI4ODlmZjYyMzRmMjY4YTlmZDc3NDJmOTA5YjcyKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iOTNkNjc2OGQ2ZDY0ZTQ1YjUyMTUzNWE2MDdmNDJkNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY3NjM1NzM5OTk5OTk5LCAtNzkuMjkzMDMxMl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9mMDgzNzQ2NzZlYTE0MDNmYjMzYTU5NzcxMmQxZTIxOCA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfMWRlOWY5OTI5ZGQyNGNkYzhjMmZmNjA4MmM5NjQ1OTMgPSAkKGA8ZGl2IGlkPSJodG1sXzFkZTlmOTkyOWRkMjRjZGM4YzJmZjYwODJjOTY0NTkzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UaGUgQmVhY2hlcyBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9mMDgzNzQ2NzZlYTE0MDNmYjMzYTU5NzcxMmQxZTIxOC5zZXRDb250ZW50KGh0bWxfMWRlOWY5OTI5ZGQyNGNkYzhjMmZmNjA4MmM5NjQ1OTMpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2I5M2Q2NzY4ZDZkNjRlNDViNTIxNTM1YTYwN2Y0MmQ3LmJpbmRQb3B1cChwb3B1cF9mMDgzNzQ2NzZlYTE0MDNmYjMzYTU5NzcxMmQxZTIxOCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDZiMGY4MThhN2EzNDE5N2JlYzUwOGM2MTdjZDY2MzcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MDkwNjA0LCAtNzkuMzYzNDUxN10sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF84M2U2NzQzNzEzNzI0MGYzOWQxMTU4N2Y3NmZjOWMxZSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfYTZjMTFlMDlmZTVmNGY4OWEwN2JkYjhhYzQxNDk0MzEgPSAkKGA8ZGl2IGlkPSJodG1sX2E2YzExZTA5ZmU1ZjRmODlhMDdiZGI4YWM0MTQ5NDMxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5MZWFzaWRlIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzgzZTY3NDM3MTM3MjQwZjM5ZDExNTg3Zjc2ZmM5YzFlLnNldENvbnRlbnQoaHRtbF9hNmMxMWUwOWZlNWY0Zjg5YTA3YmRiOGFjNDE0OTQzMSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNDZiMGY4MThhN2EzNDE5N2JlYzUwOGM2MTdjZDY2MzcuYmluZFBvcHVwKHBvcHVwXzgzZTY3NDM3MTM3MjQwZjM5ZDExNTg3Zjc2ZmM5YzFlKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kN2U1Nzc2ZDgyYmQ0Y2NmYTVjMDVmYzBjYzJjNGM1ZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcwNTM2ODksIC03OS4zNDkzNzE5MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9mMWJhZWFjN2M1Njc0MmVkYmJlNDBiNTRlMTRiODEwMSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfNDBiNmYyMDk1NTJjNGM5ZmE5MmY4ZGQyODUyNTA1NWEgPSAkKGA8ZGl2IGlkPSJodG1sXzQwYjZmMjA5NTUyYzRjOWZhOTJmOGRkMjg1MjUwNTVhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UaG9ybmNsaWZmZSBQYXJrIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2YxYmFlYWM3YzU2NzQyZWRiYmU0MGI1NGUxNGI4MTAxLnNldENvbnRlbnQoaHRtbF80MGI2ZjIwOTU1MmM0YzlmYTkyZjhkZDI4NTI1MDU1YSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfZDdlNTc3NmQ4MmJkNGNjZmE1YzA1ZmMwY2MyYzRjNWYuYmluZFBvcHVwKHBvcHVwX2YxYmFlYWM3YzU2NzQyZWRiYmU0MGI1NGUxNGI4MTAxKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zZDg3NjQzMTg1Y2Q0ZjM3OTFlMDcxOTAxOTM1YmVhNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY4NTM0NywgLTc5LjMzODEwNjVdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiNmZjAwMDAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMjhiYmMxZGQ1MDAzNDY1MzlkNGY1NDdjMTc0NDAxOTYgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzVjYjUzMWJhYTA0YTQ1YWFiOWU1Y2UyNzNhZDcxZTVkID0gJChgPGRpdiBpZD0iaHRtbF81Y2I1MzFiYWEwNGE0NWFhYjllNWNlMjczYWQ3MWU1ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RWFzdCBUb3JvbnRvLCBCcm9hZHZpZXcgTm9ydGggKE9sZCBFYXN0IFlvcmspIENsdXN0ZXIgMC4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzI4YmJjMWRkNTAwMzQ2NTM5ZDRmNTQ3YzE3NDQwMTk2LnNldENvbnRlbnQoaHRtbF81Y2I1MzFiYWEwNGE0NWFhYjllNWNlMjczYWQ3MWU1ZCk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfM2Q4NzY0MzE4NWNkNGYzNzkxZTA3MTkwMTkzNWJlYTQuYmluZFBvcHVwKHBvcHVwXzI4YmJjMWRkNTAwMzQ2NTM5ZDRmNTQ3YzE3NDQwMTk2KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wNmMzYTJlYjVlNzk0MWM2YTUwNDlhMjVmZDNlYzY5ZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY3OTU1NzEsIC03OS4zNTIxODhdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfNzQ4NDg1MDgzM2M1NGZhNjk1MWM2MDQ4MWY2YTM5MzAgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2UxMjhiNWVlOTlkZDQ0ZWI5MDQ0ZjRjMTIzOWYzODAwID0gJChgPGRpdiBpZD0iaHRtbF9lMTI4YjVlZTk5ZGQ0NGViOTA0NGY0YzEyMzlmMzgwMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VGhlIERhbmZvcnRoIFdlc3QsIFJpdmVyZGFsZSBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF83NDg0ODUwODMzYzU0ZmE2OTUxYzYwNDgxZjZhMzkzMC5zZXRDb250ZW50KGh0bWxfZTEyOGI1ZWU5OWRkNDRlYjkwNDRmNGMxMjM5ZjM4MDApOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzA2YzNhMmViNWU3OTQxYzZhNTA0OWEyNWZkM2VjNjlmLmJpbmRQb3B1cChwb3B1cF83NDg0ODUwODMzYzU0ZmE2OTUxYzYwNDgxZjZhMzkzMCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjQ3NDAwZDkwMWM4NDE5YjkwZGU3NWJjNGZkNGQyNTIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Njg5OTg1LCAtNzkuMzE1NTcxNTk5OTk5OThdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfZTE3MTJkNDU5N2JlNDExZDllMTVmMWFmOGY2ODQzNDkgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2MwODExNDFmYmEwODQ1ZmNhZWE2ZDExNzAxMDU5ZTlhID0gJChgPGRpdiBpZD0iaHRtbF9jMDgxMTQxZmJhMDg0NWZjYWVhNmQxMTcwMTA1OWU5YSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SW5kaWEgQmF6YWFyLCBUaGUgQmVhY2hlcyBXZXN0IENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2UxNzEyZDQ1OTdiZTQxMWQ5ZTE1ZjFhZjhmNjg0MzQ5LnNldENvbnRlbnQoaHRtbF9jMDgxMTQxZmJhMDg0NWZjYWVhNmQxMTcwMTA1OWU5YSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfYjQ3NDAwZDkwMWM4NDE5YjkwZGU3NWJjNGZkNGQyNTIuYmluZFBvcHVwKHBvcHVwX2UxNzEyZDQ1OTdiZTQxMWQ5ZTE1ZjFhZjhmNjg0MzQ5KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80YTI3ZDZiZTM5YzU0NDhhYjUyOTFmYTY0ODcwY2RiMSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1OTUyNTUsIC03OS4zNDA5MjNdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMDExZTdjZTgzM2E0NDI4NGFjZWI3ZjI4NmNhMDFlNjMgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzY4MDM2ZTFmYzI2ZDQxYTQ5Njk1MmU1ZWQzNWNhMmIwID0gJChgPGRpdiBpZD0iaHRtbF82ODAzNmUxZmMyNmQ0MWE0OTY5NTJlNWVkMzVjYTJiMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3R1ZGlvIERpc3RyaWN0IENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzAxMWU3Y2U4MzNhNDQyODRhY2ViN2YyODZjYTAxZTYzLnNldENvbnRlbnQoaHRtbF82ODAzNmUxZmMyNmQ0MWE0OTY5NTJlNWVkMzVjYTJiMCk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNGEyN2Q2YmUzOWM1NDQ4YWI1MjkxZmE2NDg3MGNkYjEuYmluZFBvcHVwKHBvcHVwXzAxMWU3Y2U4MzNhNDQyODRhY2ViN2YyODZjYTAxZTYzKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82MjllOTI3YWU1ZWY0MDc0OWQyZTc2MjgyNTJlODkyYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcyODAyMDUsIC03OS4zODg3OTAxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjZmYwMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNmZjAwMDAiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzE5MDU2NWYyMGUyMDQyNmI5ZDM2ZTgyYjgxZjgyMDRkID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF8yMmNjMDMyZjkwOTQ0ZDQyOWRiNzNhMDQ2YjE1YzcyMiA9ICQoYDxkaXYgaWQ9Imh0bWxfMjJjYzAzMmY5MDk0NGQ0MjlkYjczYTA0NmIxNWM3MjIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxhd3JlbmNlIFBhcmsgQ2x1c3RlciAwLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfMTkwNTY1ZjIwZTIwNDI2YjlkMzZlODJiODFmODIwNGQuc2V0Q29udGVudChodG1sXzIyY2MwMzJmOTA5NDRkNDI5ZGI3M2EwNDZiMTVjNzIyKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl82MjllOTI3YWU1ZWY0MDc0OWQyZTc2MjgyNTJlODkyYi5iaW5kUG9wdXAocG9wdXBfMTkwNTY1ZjIwZTIwNDI2YjlkMzZlODJiODFmODIwNGQpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQ4YjQxYTlkYjdlZTRhNThhZGNhN2NlOTlmYzdlMmZlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzEyNzUxMSwgLTc5LjM5MDE5NzVdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfODQ3ZWY0ZWUxM2UyNGMxYzk4MjkxNjBkZDcyYjY0NGQgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2NjNzg3N2E3NjM4MjRhNzlhMGRhYjJmMTc1NzIzMjhkID0gJChgPGRpdiBpZD0iaHRtbF9jYzc4NzdhNzYzODI0YTc5YTBkYWIyZjE3NTcyMzI4ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RGF2aXN2aWxsZSBOb3J0aCBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF84NDdlZjRlZTEzZTI0YzFjOTgyOTE2MGRkNzJiNjQ0ZC5zZXRDb250ZW50KGh0bWxfY2M3ODc3YTc2MzgyNGE3OWEwZGFiMmYxNzU3MjMyOGQpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzQ4YjQxYTlkYjdlZTRhNThhZGNhN2NlOTlmYzdlMmZlLmJpbmRQb3B1cChwb3B1cF84NDdlZjRlZTEzZTI0YzFjOTgyOTE2MGRkNzJiNjQ0ZCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDQ1NGI2NGI5MTQ4NDNmZGFjMTFmMzQwMmMwMWY0NTYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MTUzODM0LCAtNzkuNDA1Njc4NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfNTdiNDVjNmI1MTA0NGNhNGJlNjFhMTA5NzNmZGViODggPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzg5OTBhY2JiYmE5MTQ5YjNiMmM5NTRjYjFmYmQxN2M5ID0gJChgPGRpdiBpZD0iaHRtbF84OTkwYWNiYmJhOTE0OWIzYjJjOTU0Y2IxZmJkMTdjOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Tm9ydGggVG9yb250byBXZXN0LCBMYXdyZW5jZSBQYXJrIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzU3YjQ1YzZiNTEwNDRjYTRiZTYxYTEwOTczZmRlYjg4LnNldENvbnRlbnQoaHRtbF84OTkwYWNiYmJhOTE0OWIzYjJjOTU0Y2IxZmJkMTdjOSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNDQ1NGI2NGI5MTQ4NDNmZGFjMTFmMzQwMmMwMWY0NTYuYmluZFBvcHVwKHBvcHVwXzU3YjQ1YzZiNTEwNDRjYTRiZTYxYTEwOTczZmRlYjg4KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mZTE5ZDgyNjQxOGY0MTY1YTVlMGQ2YTE3NmQzYmY3NyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcwNDMyNDQsIC03OS4zODg3OTAxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2NiNDliM2VmMjBiOTQ4OGI4M2UyZWI2YzhlMjVmNjkwID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9hZjI2Y2ZmZTBkNmY0NWQ1YjRhMjhhOGU1ZWVhMTNmOSA9ICQoYDxkaXYgaWQ9Imh0bWxfYWYyNmNmZmUwZDZmNDVkNWI0YTI4YThlNWVlYTEzZjkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRhdmlzdmlsbGUgQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfY2I0OWIzZWYyMGI5NDg4YjgzZTJlYjZjOGUyNWY2OTAuc2V0Q29udGVudChodG1sX2FmMjZjZmZlMGQ2ZjQ1ZDViNGEyOGE4ZTVlZWExM2Y5KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9mZTE5ZDgyNjQxOGY0MTY1YTVlMGQ2YTE3NmQzYmY3Ny5iaW5kUG9wdXAocG9wdXBfY2I0OWIzZWYyMGI5NDg4YjgzZTJlYjZjOGUyNWY2OTApCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2ZlM2ZlNDlkZTUzZjQwMjc5YmQwMmFjYWEyNTA0Mzc3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjg5NTc0MywgLTc5LjM4MzE1OTkwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjZmYwMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNmZjAwMDAiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2ZiYjRhZWUwOTUwODQzYjc5MDkyYzJkOWRjYTMyZjdkID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9mNjIyNjkwYWU3Mzg0ZTU5YjRkOWE1MWVhY2Q2NzE2YyA9ICQoYDxkaXYgaWQ9Imh0bWxfZjYyMjY5MGFlNzM4NGU1OWI0ZDlhNTFlYWNkNjcxNmMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1vb3JlIFBhcmssIFN1bW1lcmhpbGwgRWFzdCBDbHVzdGVyIDAuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9mYmI0YWVlMDk1MDg0M2I3OTA5MmMyZDlkY2EzMmY3ZC5zZXRDb250ZW50KGh0bWxfZjYyMjY5MGFlNzM4NGU1OWI0ZDlhNTFlYWNkNjcxNmMpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2ZlM2ZlNDlkZTUzZjQwMjc5YmQwMmFjYWEyNTA0Mzc3LmJpbmRQb3B1cChwb3B1cF9mYmI0YWVlMDk1MDg0M2I3OTA5MmMyZDlkY2EzMmY3ZCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYmUwNmY4Yjc5MzdjNDRkZWI0ZTA4ODBjNzExN2VmZjggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42ODY0MTIyOTk5OTk5OSwgLTc5LjQwMDA0OTNdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfYTAxMDNkM2FmNjVhNDUyOWFkNjM2MmI1NWEzNTdmZGMgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzJkYjkwOWI2NGUyMzRlY2Y5NWJhZDBlYTllY2JmNDI3ID0gJChgPGRpdiBpZD0iaHRtbF8yZGI5MDliNjRlMjM0ZWNmOTViYWQwZWE5ZWNiZjQyNyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3VtbWVyaGlsbCBXZXN0LCBSYXRobmVsbHksIFNvdXRoIEhpbGwsIEZvcmVzdCBIaWxsIFNFLCBEZWVyIFBhcmsgQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfYTAxMDNkM2FmNjVhNDUyOWFkNjM2MmI1NWEzNTdmZGMuc2V0Q29udGVudChodG1sXzJkYjkwOWI2NGUyMzRlY2Y5NWJhZDBlYTllY2JmNDI3KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9iZTA2ZjhiNzkzN2M0NGRlYjRlMDg4MGM3MTE3ZWZmOC5iaW5kUG9wdXAocG9wdXBfYTAxMDNkM2FmNjVhNDUyOWFkNjM2MmI1NWEzNTdmZGMpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzM2NTExMzdlMGIzYTQxZGE4MGI0ZGM1OWE3NzYyMzQ3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjc5NTYyNiwgLTc5LjM3NzUyOTQwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjZmYwMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNmZjAwMDAiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzhiNGI1OTMyNTJiNjRiMWU4NGRmOThjMzJhYTA5Y2VmID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF8wZjRlM2NjOGJmN2M0YjgwOWY0MGMxZjRmNzdlNDE5NSA9ICQoYDxkaXYgaWQ9Imh0bWxfMGY0ZTNjYzhiZjdjNGI4MDlmNDBjMWY0Zjc3ZTQxOTUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJvc2VkYWxlIENsdXN0ZXIgMC4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzhiNGI1OTMyNTJiNjRiMWU4NGRmOThjMzJhYTA5Y2VmLnNldENvbnRlbnQoaHRtbF8wZjRlM2NjOGJmN2M0YjgwOWY0MGMxZjRmNzdlNDE5NSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMzY1MTEzN2UwYjNhNDFkYTgwYjRkYzU5YTc3NjIzNDcuYmluZFBvcHVwKHBvcHVwXzhiNGI1OTMyNTJiNjRiMWU4NGRmOThjMzJhYTA5Y2VmKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wOGQ0ZjhlZDk5YmQ0ZjcwYjgyNGJkMjg5YTA0NWVhYSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY2Nzk2NywgLTc5LjM2NzY3NTNdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfOTEyMDlmMWE5OWE3NDY1OThlY2YxZTNlNGFkMzJjY2MgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzViYzI3ZDVlODhmOTRmOTI4OTgzY2NjNTFmZWViNWM5ID0gJChgPGRpdiBpZD0iaHRtbF81YmMyN2Q1ZTg4Zjk0ZjkyODk4M2NjYzUxZmVlYjVjOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3QuIEphbWVzIFRvd24sIENhYmJhZ2V0b3duIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzkxMjA5ZjFhOTlhNzQ2NTk4ZWNmMWUzZTRhZDMyY2NjLnNldENvbnRlbnQoaHRtbF81YmMyN2Q1ZTg4Zjk0ZjkyODk4M2NjYzUxZmVlYjVjOSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMDhkNGY4ZWQ5OWJkNGY3MGI4MjRiZDI4OWEwNDVlYWEuYmluZFBvcHVwKHBvcHVwXzkxMjA5ZjFhOTlhNzQ2NTk4ZWNmMWUzZTRhZDMyY2NjKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hYjE4NTQ1M2IzZWU0NWY3YjBlNGI1YTkwMWRmMTRiOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY2NTg1OTksIC03OS4zODMxNTk5MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9hNGU0MzY5MjY5M2Q0MjIwYjhmZDQzNjMzMjk4NmYwMSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfMWViNDFhMTBkZjIwNGZhMDg3ODViZDVhOGYyZWVkMjUgPSAkKGA8ZGl2IGlkPSJodG1sXzFlYjQxYTEwZGYyMDRmYTA4Nzg1YmQ1YThmMmVlZDI1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DaHVyY2ggYW5kIFdlbGxlc2xleSBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9hNGU0MzY5MjY5M2Q0MjIwYjhmZDQzNjMzMjk4NmYwMS5zZXRDb250ZW50KGh0bWxfMWViNDFhMTBkZjIwNGZhMDg3ODViZDVhOGYyZWVkMjUpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2FiMTg1NDUzYjNlZTQ1ZjdiMGU0YjVhOTAxZGYxNGI5LmJpbmRQb3B1cChwb3B1cF9hNGU0MzY5MjY5M2Q0MjIwYjhmZDQzNjMzMjk4NmYwMSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjA0YjkxZjI1YzhkNDY2ZGI0YTBkMWYyYTJjMjQ5MDYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NTQyNTk5LCAtNzkuMzYwNjM1OV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF83YjgzNGUyNTY5MGE0NGY4YTAyZjk4MzQxZDdkMzUzMCA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfODViYWM0YjM3OTIxNDZjMTlhZjYzZWVlOGY5ZTMyY2QgPSAkKGA8ZGl2IGlkPSJodG1sXzg1YmFjNGIzNzkyMTQ2YzE5YWY2M2VlZThmOWUzMmNkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5SZWdlbnQgUGFyaywgSGFyYm91cmZyb250IENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzdiODM0ZTI1NjkwYTQ0ZjhhMDJmOTgzNDFkN2QzNTMwLnNldENvbnRlbnQoaHRtbF84NWJhYzRiMzc5MjE0NmMxOWFmNjNlZWU4ZjllMzJjZCk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfYjA0YjkxZjI1YzhkNDY2ZGI0YTBkMWYyYTJjMjQ5MDYuYmluZFBvcHVwKHBvcHVwXzdiODM0ZTI1NjkwYTQ0ZjhhMDJmOTgzNDFkN2QzNTMwKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xZDNiZjI2NzlmYWY0MzZiODQ1ZmE3MmI0NTRhNGI5MSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1NzE2MTgsIC03OS4zNzg5MzcwOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF8wZDZmOWNjZjA4MGM0YTliYWE0M2NkNDEwYjNmYzYwZSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfOGRlYTRiZTdlNDVjNGU0ZGI5ZjdjZGE4YmRlMjNlMzkgPSAkKGA8ZGl2IGlkPSJodG1sXzhkZWE0YmU3ZTQ1YzRlNGRiOWY3Y2RhOGJkZTIzZTM5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5HYXJkZW4gRGlzdHJpY3QsIFJ5ZXJzb24gQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfMGQ2ZjljY2YwODBjNGE5YmFhNDNjZDQxMGIzZmM2MGUuc2V0Q29udGVudChodG1sXzhkZWE0YmU3ZTQ1YzRlNGRiOWY3Y2RhOGJkZTIzZTM5KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl8xZDNiZjI2NzlmYWY0MzZiODQ1ZmE3MmI0NTRhNGI5MS5iaW5kUG9wdXAocG9wdXBfMGQ2ZjljY2YwODBjNGE5YmFhNDNjZDQxMGIzZmM2MGUpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2UxODVlZDdiOTI3ZjQwNGRhZDhhYjVlNDYxMTdkY2U5ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUxNDkzOSwgLTc5LjM3NTQxNzldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMWM3N2NkZTg3ZjI2NDIzMzgxMDBkYmVhNjQ0NzMxZWEgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzRkMTU4NGU0MmE2YTQ0OGI4MGFmMGRjZGQyY2NiNmFmID0gJChgPGRpdiBpZD0iaHRtbF80ZDE1ODRlNDJhNmE0NDhiODBhZjBkY2RkMmNjYjZhZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3QuIEphbWVzIFRvd24gQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfMWM3N2NkZTg3ZjI2NDIzMzgxMDBkYmVhNjQ0NzMxZWEuc2V0Q29udGVudChodG1sXzRkMTU4NGU0MmE2YTQ0OGI4MGFmMGRjZGQyY2NiNmFmKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9lMTg1ZWQ3YjkyN2Y0MDRkYWQ4YWI1ZTQ2MTE3ZGNlOS5iaW5kUG9wdXAocG9wdXBfMWM3N2NkZTg3ZjI2NDIzMzgxMDBkYmVhNjQ0NzMxZWEpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzkyMDU2OTljYTRiMzQyYTZiMWI1OTU1NzIzNzI2OTI3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjQ0NzcwNzk5OTk5OTk2LCAtNzkuMzczMzA2NF0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF8wMTYwMjk1ZDI1ZjQ0YmQzOTZmM2FmYTA2NTBkMmRkMyA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfZDhkMzhhOGM4MTY0NDAzODk2NzU1MTI2ZDk4NWVlZWUgPSAkKGA8ZGl2IGlkPSJodG1sX2Q4ZDM4YThjODE2NDQwMzg5Njc1NTEyNmQ5ODVlZWVlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CZXJjenkgUGFyayBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8wMTYwMjk1ZDI1ZjQ0YmQzOTZmM2FmYTA2NTBkMmRkMy5zZXRDb250ZW50KGh0bWxfZDhkMzhhOGM4MTY0NDAzODk2NzU1MTI2ZDk4NWVlZWUpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzkyMDU2OTljYTRiMzQyYTZiMWI1OTU1NzIzNzI2OTI3LmJpbmRQb3B1cChwb3B1cF8wMTYwMjk1ZDI1ZjQ0YmQzOTZmM2FmYTA2NTBkMmRkMykKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYTQzZmRjMmY2NDZjNGMxMGE2ZWRhOGZjMmI2NDA1YmEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NTc5NTI0LCAtNzkuMzg3MzgyNl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF8wYjAzNTk5OTE4NTA0ZTYyOTE4YzUwZGQxNDc3NjU3NiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfNGM5MDA3NWYzNWY5NDk0NTlhMGI3MjZjZWZhNTFhZWQgPSAkKGA8ZGl2IGlkPSJodG1sXzRjOTAwNzVmMzVmOTQ5NDU5YTBiNzI2Y2VmYTUxYWVkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DZW50cmFsIEJheSBTdHJlZXQgQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfMGIwMzU5OTkxODUwNGU2MjkxOGM1MGRkMTQ3NzY1NzYuc2V0Q29udGVudChodG1sXzRjOTAwNzVmMzVmOTQ5NDU5YTBiNzI2Y2VmYTUxYWVkKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9hNDNmZGMyZjY0NmM0YzEwYTZlZGE4ZmMyYjY0MDViYS5iaW5kUG9wdXAocG9wdXBfMGIwMzU5OTkxODUwNGU2MjkxOGM1MGRkMTQ3NzY1NzYpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzg2ZGRkMjM3YzU0YzQ3ODQ4NzIxNTMzOGE5NjM4ODhmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUwNTcxMjAwMDAwMDEsIC03OS4zODQ1Njc1XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2RjNzViYjkwMDFhNjRhYmJhM2FmYTcwYzc0MGM3YzIwID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF80ZGVhY2VjYWY1NGQ0NDQ5YTg4MWJlOWJiOTVmODVjNCA9ICQoYDxkaXYgaWQ9Imh0bWxfNGRlYWNlY2FmNTRkNDQ0OWE4ODFiZTliYjk1Zjg1YzQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJpY2htb25kLCBBZGVsYWlkZSwgS2luZyBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9kYzc1YmI5MDAxYTY0YWJiYTNhZmE3MGM3NDBjN2MyMC5zZXRDb250ZW50KGh0bWxfNGRlYWNlY2FmNTRkNDQ0OWE4ODFiZTliYjk1Zjg1YzQpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzg2ZGRkMjM3YzU0YzQ3ODQ4NzIxNTMzOGE5NjM4ODhmLmJpbmRQb3B1cChwb3B1cF9kYzc1YmI5MDAxYTY0YWJiYTNhZmE3MGM3NDBjN2MyMCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjY2M2NhNmJmYWEzNDExYTkwNjc0NmYyYzcxYzFlODEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDA4MTU3LCAtNzkuMzgxNzUyMjk5OTk5OTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMjA0MzFjNjg4MzA5NGVkMWI2NWY2N2U2MGI1NzZiMTQgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzU1YmQxMjVhY2Q0YjQ4YTM5ZTRlZDk2OWQzODNjMTQwID0gJChgPGRpdiBpZD0iaHRtbF81NWJkMTI1YWNkNGI0OGEzOWU0ZWQ5NjlkMzgzYzE0MCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SGFyYm91cmZyb250IEVhc3QsIFVuaW9uIFN0YXRpb24sIFRvcm9udG8gSXNsYW5kcyBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8yMDQzMWM2ODgzMDk0ZWQxYjY1ZjY3ZTYwYjU3NmIxNC5zZXRDb250ZW50KGh0bWxfNTViZDEyNWFjZDRiNDhhMzllNGVkOTY5ZDM4M2MxNDApOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2Y2NjNjYTZiZmFhMzQxMWE5MDY3NDZmMmM3MWMxZTgxLmJpbmRQb3B1cChwb3B1cF8yMDQzMWM2ODgzMDk0ZWQxYjY1ZjY3ZTYwYjU3NmIxNCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYWQ0NTRhNDU5OTA1NDNmMmFkZGU0NjAxMWY4MTFlOWEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDcxNzY4LCAtNzkuMzgxNTc2NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMTExMzhjMTA3ZmQ0NDRlOTk4ZDE4Y2VmZWUwZDg5MjAgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzVmZjE0OTEyZGFjMTQwMjY4OTMwYzk4OGQ4YzJlNGNhID0gJChgPGRpdiBpZD0iaHRtbF81ZmYxNDkxMmRhYzE0MDI2ODkzMGM5ODhkOGMyZTRjYSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VG9yb250byBEb21pbmlvbiBDZW50cmUsIERlc2lnbiBFeGNoYW5nZSBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8xMTEzOGMxMDdmZDQ0NGU5OThkMThjZWZlZTBkODkyMC5zZXRDb250ZW50KGh0bWxfNWZmMTQ5MTJkYWMxNDAyNjg5MzBjOTg4ZDhjMmU0Y2EpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2FkNDU0YTQ1OTkwNTQzZjJhZGRlNDYwMTFmODExZTlhLmJpbmRQb3B1cChwb3B1cF8xMTEzOGMxMDdmZDQ0NGU5OThkMThjZWZlZTBkODkyMCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZTk0YThlNzczMjNkNDM0MTg4YjRiYWRkM2NiM2ZmNjggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDgxOTg1LCAtNzkuMzc5ODE2OTAwMDAwMDFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfYzA1MDcyNmMyNWYyNGNlODgzOTgxZTE3NTZlZWZmYzkgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzNkNzJlOTZhNGYwYzQwNTY5ZThlNDQ5MjEyMDdiNWYyID0gJChgPGRpdiBpZD0iaHRtbF8zZDcyZTk2YTRmMGM0MDU2OWU4ZTQ0OTIxMjA3YjVmMiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q29tbWVyY2UgQ291cnQsIFZpY3RvcmlhIEhvdGVsIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2MwNTA3MjZjMjVmMjRjZTg4Mzk4MWUxNzU2ZWVmZmM5LnNldENvbnRlbnQoaHRtbF8zZDcyZTk2YTRmMGM0MDU2OWU4ZTQ0OTIxMjA3YjVmMik7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfZTk0YThlNzczMjNkNDM0MTg4YjRiYWRkM2NiM2ZmNjguYmluZFBvcHVwKHBvcHVwX2MwNTA3MjZjMjVmMjRjZTg4Mzk4MWUxNzU2ZWVmZmM5KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83MDk5Y2E5ODdkZDE0MGE2OTg4YjQ1ZWIzNzBhMTI0ZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjczMzI4MjUsIC03OS40MTk3NDk3XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzhkY2NjMDE0NjVkOTQ2MjI4NGQ5YjkyMzhkYWUxYTc5ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF8wZDIyNGI3OGYyZjg0NjQ4OTIwYTg5ZWM1ZDcwNmIwMSA9ICQoYDxkaXYgaWQ9Imh0bWxfMGQyMjRiNzhmMmY4NDY0ODkyMGE4OWVjNWQ3MDZiMDEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJlZGZvcmQgUGFyaywgTGF3cmVuY2UgTWFub3IgRWFzdCBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF84ZGNjYzAxNDY1ZDk0NjIyODRkOWI5MjM4ZGFlMWE3OS5zZXRDb250ZW50KGh0bWxfMGQyMjRiNzhmMmY4NDY0ODkyMGE4OWVjNWQ3MDZiMDEpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzcwOTljYTk4N2RkMTQwYTY5ODhiNDVlYjM3MGExMjRmLmJpbmRQb3B1cChwb3B1cF84ZGNjYzAxNDY1ZDk0NjIyODRkOWI5MjM4ZGFlMWE3OSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMWU5MTBmOWM5MGY5NGJhNjk5ZTg2NWZhMjM5NGNkMWIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MTE2OTQ4LCAtNzkuNDE2OTM1NTk5OTk5OTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfNmJjMTJmMjYzYjg5NDNhZTlkM2UyZWQ2M2Q3MTc5M2QgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2U2NTlmZTZkYzBmYTRkODVhYmQ0ODlkOGM2NjgzN2YzID0gJChgPGRpdiBpZD0iaHRtbF9lNjU5ZmU2ZGMwZmE0ZDg1YWJkNDg5ZDhjNjY4MzdmMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Um9zZWxhd24gQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfNmJjMTJmMjYzYjg5NDNhZTlkM2UyZWQ2M2Q3MTc5M2Quc2V0Q29udGVudChodG1sX2U2NTlmZTZkYzBmYTRkODVhYmQ0ODlkOGM2NjgzN2YzKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl8xZTkxMGY5YzkwZjk0YmE2OTllODY1ZmEyMzk0Y2QxYi5iaW5kUG9wdXAocG9wdXBfNmJjMTJmMjYzYjg5NDNhZTlkM2UyZWQ2M2Q3MTc5M2QpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY0YjJlMjI5MzY2NDQxOWRhOGQwMjAwYjg4ZjBiNGRhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjk2OTQ3NiwgLTc5LjQxMTMwNzIwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjZmYwMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNmZjAwMDAiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2ExOTMzNzU1YWE1ODRlYmJhYzk2YzNjZmZmODBkNzE4ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF8wYTYxYzFlZDA5ZjM0NDUwYmRiYjM5NmQ2MDg2NTQ2MiA9ICQoYDxkaXYgaWQ9Imh0bWxfMGE2MWMxZWQwOWYzNDQ1MGJkYmIzOTZkNjA4NjU0NjIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZvcmVzdCBIaWxsIE5vcnRoICZhbXA7IFdlc3QsIEZvcmVzdCBIaWxsIFJvYWQgUGFyayBDbHVzdGVyIDAuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9hMTkzMzc1NWFhNTg0ZWJiYWM5NmMzY2ZmZjgwZDcxOC5zZXRDb250ZW50KGh0bWxfMGE2MWMxZWQwOWYzNDQ1MGJkYmIzOTZkNjA4NjU0NjIpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzY0YjJlMjI5MzY2NDQxOWRhOGQwMjAwYjg4ZjBiNGRhLmJpbmRQb3B1cChwb3B1cF9hMTkzMzc1NWFhNTg0ZWJiYWM5NmMzY2ZmZjgwZDcxOCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjZiNTVkYTNjZTUxNDI2MDljOWFiMzRhYzMyYzhmZWEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NzI3MDk3LCAtNzkuNDA1Njc4NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfN2YyNTYwYWIxMzRkNDVmNGJiNzBlNWVmYTk3M2IzNDYgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzEwMWQ2M2E5ZTQ5NDRmMTRiNTVlNGJmZWQzYjdhNmZiID0gJChgPGRpdiBpZD0iaHRtbF8xMDFkNjNhOWU0OTQ0ZjE0YjU1ZTRiZmVkM2I3YTZmYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VGhlIEFubmV4LCBOb3J0aCBNaWR0b3duLCBZb3JrdmlsbGUgQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfN2YyNTYwYWIxMzRkNDVmNGJiNzBlNWVmYTk3M2IzNDYuc2V0Q29udGVudChodG1sXzEwMWQ2M2E5ZTQ5NDRmMTRiNTVlNGJmZWQzYjdhNmZiKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9iNmI1NWRhM2NlNTE0MjYwOWM5YWIzNGFjMzJjOGZlYS5iaW5kUG9wdXAocG9wdXBfN2YyNTYwYWIxMzRkNDVmNGJiNzBlNWVmYTk3M2IzNDYpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzMwYzNlNGJhMDczZDRkZjE5YWUwMzdiZTQ1NWYzYjlkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjYyNjk1NiwgLTc5LjQwMDA0OTNdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMjExZGYwY2Y4NWMxNDhiOGE4ZWRmYWM0ODhmY2RhMmQgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzNkMTY3NjI3ZGIyMDQxM2VhYzVkMTVhMDIzN2ZlOTZiID0gJChgPGRpdiBpZD0iaHRtbF8zZDE2NzYyN2RiMjA0MTNlYWM1ZDE1YTAyMzdmZTk2YiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VW5pdmVyc2l0eSBvZiBUb3JvbnRvLCBIYXJib3JkIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzIxMWRmMGNmODVjMTQ4YjhhOGVkZmFjNDg4ZmNkYTJkLnNldENvbnRlbnQoaHRtbF8zZDE2NzYyN2RiMjA0MTNlYWM1ZDE1YTAyMzdmZTk2Yik7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMzBjM2U0YmEwNzNkNGRmMTlhZTAzN2JlNDU1ZjNiOWQuYmluZFBvcHVwKHBvcHVwXzIxMWRmMGNmODVjMTQ4YjhhOGVkZmFjNDg4ZmNkYTJkKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80YzhkNzQzZTNiYjA0NzFhYWVjZjgxNzM0N2QyMGU5MCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY1MzIwNTcsIC03OS40MDAwNDkzXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2Q1ZDYzYzBmZDBkYTRmMjc5ZDE2MmZhM2QxNWQ2YTc1ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF8yYTVlNzhlY2IzODA0NGMzODY0ZWI0NTA5ZWE4NWQwZCA9ICQoYDxkaXYgaWQ9Imh0bWxfMmE1ZTc4ZWNiMzgwNDRjMzg2NGViNDUwOWVhODVkMGQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPktlbnNpbmd0b24gTWFya2V0LCBDaGluYXRvd24sIEdyYW5nZSBQYXJrIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2Q1ZDYzYzBmZDBkYTRmMjc5ZDE2MmZhM2QxNWQ2YTc1LnNldENvbnRlbnQoaHRtbF8yYTVlNzhlY2IzODA0NGMzODY0ZWI0NTA5ZWE4NWQwZCk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNGM4ZDc0M2UzYmIwNDcxYWFlY2Y4MTczNDdkMjBlOTAuYmluZFBvcHVwKHBvcHVwX2Q1ZDYzYzBmZDBkYTRmMjc5ZDE2MmZhM2QxNWQ2YTc1KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xYTRhMGNiMTdiYzg0N2M2OTAyNjQ3OWJlOGZlYzQ1ZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjYyODk0NjcsIC03OS4zOTQ0MTk5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzA3YmRlYzQyOWI0MDQzODZiOTIxNjBkOWM2ZGNhZDQ5ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9jOWIxZDk1MWE2ZDk0NmQ2YWUyNTRkMjVhYjkxMWQ3NSA9ICQoYDxkaXYgaWQ9Imh0bWxfYzliMWQ5NTFhNmQ5NDZkNmFlMjU0ZDI1YWI5MTFkNzUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNOIFRvd2VyLCBLaW5nIGFuZCBTcGFkaW5hLCBSYWlsd2F5IExhbmRzLCBIYXJib3VyZnJvbnQgV2VzdCwgQmF0aHVyc3QgUXVheSwgU291dGggTmlhZ2FyYSwgSXNsYW5kIGFpcnBvcnQgQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfMDdiZGVjNDI5YjQwNDM4NmI5MjE2MGQ5YzZkY2FkNDkuc2V0Q29udGVudChodG1sX2M5YjFkOTUxYTZkOTQ2ZDZhZTI1NGQyNWFiOTExZDc1KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl8xYTRhMGNiMTdiYzg0N2M2OTAyNjQ3OWJlOGZlYzQ1Zi5iaW5kUG9wdXAocG9wdXBfMDdiZGVjNDI5YjQwNDM4NmI5MjE2MGQ5YzZkY2FkNDkpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzAwOWNhMGEyNjAyMjQzYmViZmVjODdlZTQ4MmQxYzBhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjQ2NDM1MiwgLTc5LjM3NDg0NTk5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2Y4N2JjODMzMGJkOTQzZTlhZWQ4MTUzM2I4NTQ1ODg0ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9kNTIzZmFjYjNiN2I0N2FhYWYwZTE1YmU0ZjdmMTc1MyA9ICQoYDxkaXYgaWQ9Imh0bWxfZDUyM2ZhY2IzYjdiNDdhYWFmMGUxNWJlNGY3ZjE3NTMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlN0biBBIFBPIEJveGVzIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2Y4N2JjODMzMGJkOTQzZTlhZWQ4MTUzM2I4NTQ1ODg0LnNldENvbnRlbnQoaHRtbF9kNTIzZmFjYjNiN2I0N2FhYWYwZTE1YmU0ZjdmMTc1Myk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMDA5Y2EwYTI2MDIyNDNiZWJmZWM4N2VlNDgyZDFjMGEuYmluZFBvcHVwKHBvcHVwX2Y4N2JjODMzMGJkOTQzZTlhZWQ4MTUzM2I4NTQ1ODg0KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82Y2UyNDk4MzkwYzk0NmU1OGUwZDU2ZmE0YWNkNmQzYSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY0ODQyOTIsIC03OS4zODIyODAyXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2JiOTBiNjBlZjk3MzRlYmQ5OTM5YzIwMjJlNjYzNzUzID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9lMDg0ZmJiYzJlNzU0ZjM1YTExMTIyMjZhM2FhYzJhZCA9ICQoYDxkaXYgaWQ9Imh0bWxfZTA4NGZiYmMyZTc1NGYzNWExMTEyMjI2YTNhYWMyYWQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZpcnN0IENhbmFkaWFuIFBsYWNlLCBVbmRlcmdyb3VuZCBjaXR5IENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2JiOTBiNjBlZjk3MzRlYmQ5OTM5YzIwMjJlNjYzNzUzLnNldENvbnRlbnQoaHRtbF9lMDg0ZmJiYzJlNzU0ZjM1YTExMTIyMjZhM2FhYzJhZCk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNmNlMjQ5ODM5MGM5NDZlNThlMGQ1NmZhNGFjZDZkM2EuYmluZFBvcHVwKHBvcHVwX2JiOTBiNjBlZjk3MzRlYmQ5OTM5YzIwMjJlNjYzNzUzKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yOTQ5MjQ5N2U3ZGE0M2YxODFmNmQzYzMwMWFiMGJiZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcxODUxNzk5OTk5OTk5NiwgLTc5LjQ2NDc2MzI5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzM3ZGI5NjhhYzExYTQwMTI5YTA4NjljNGJjMjEwNGJkID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9iYTQ0ZTY2OGVmMjg0ZTRiYTZkMDliMmYxMzg0YTZjOSA9ICQoYDxkaXYgaWQ9Imh0bWxfYmE0NGU2NjhlZjI4NGU0YmE2ZDA5YjJmMTM4NGE2YzkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxhd3JlbmNlIE1hbm9yLCBMYXdyZW5jZSBIZWlnaHRzIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzM3ZGI5NjhhYzExYTQwMTI5YTA4NjljNGJjMjEwNGJkLnNldENvbnRlbnQoaHRtbF9iYTQ0ZTY2OGVmMjg0ZTRiYTZkMDliMmYxMzg0YTZjOSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMjk0OTI0OTdlN2RhNDNmMTgxZjZkM2MzMDFhYjBiYmYuYmluZFBvcHVwKHBvcHVwXzM3ZGI5NjhhYzExYTQwMTI5YTA4NjljNGJjMjEwNGJkKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mMjRkZGZjOGI5YWE0N2FjYjFmZDNhZGVhZGJjYmVkOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjcwOTU3NywgLTc5LjQ0NTA3MjU5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzIxZjNjM2Q5OGJjMjQwODg4YjUxOGFlYmZlNjU1NzZjID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9mMjc5ZDM0NDkxYTM0ZWQ2YjBiMmEwZWI4NzY0MGNiZSA9ICQoYDxkaXYgaWQ9Imh0bWxfZjI3OWQzNDQ5MWEzNGVkNmIwYjJhMGViODc2NDBjYmUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkdsZW5jYWlybiBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8yMWYzYzNkOThiYzI0MDg4OGI1MThhZWJmZTY1NTc2Yy5zZXRDb250ZW50KGh0bWxfZjI3OWQzNDQ5MWEzNGVkNmIwYjJhMGViODc2NDBjYmUpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2YyNGRkZmM4YjlhYTQ3YWNiMWZkM2FkZWFkYmNiZWQ5LmJpbmRQb3B1cChwb3B1cF8yMWYzYzNkOThiYzI0MDg4OGI1MThhZWJmZTY1NTc2YykKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODJkYzM0ZjA1ZDJhNDFhNzgwZjJiZjQwN2E4YWQ1YWYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42OTM3ODEzLCAtNzkuNDI4MTkxNDAwMDAwMDJdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMGNkODdlMDM3ZjMxNDhjM2FiZTgwZWM2ODBmNDY2OGYgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2U5YTdjMzE1NzYzNDRiMWNhNzNiYWNkZjc4NjcwODYyID0gJChgPGRpdiBpZD0iaHRtbF9lOWE3YzMxNTc2MzQ0YjFjYTczYmFjZGY3ODY3MDg2MiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SHVtZXdvb2QtQ2VkYXJ2YWxlIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzBjZDg3ZTAzN2YzMTQ4YzNhYmU4MGVjNjgwZjQ2NjhmLnNldENvbnRlbnQoaHRtbF9lOWE3YzMxNTc2MzQ0YjFjYTczYmFjZGY3ODY3MDg2Mik7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfODJkYzM0ZjA1ZDJhNDFhNzgwZjJiZjQwN2E4YWQ1YWYuYmluZFBvcHVwKHBvcHVwXzBjZDg3ZTAzN2YzMTQ4YzNhYmU4MGVjNjgwZjQ2NjhmKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84NjNhMjlhMWU1YmE0MWM3OWRmYTg5NDZjMzY2ZjhmNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY4OTAyNTYsIC03OS40NTM1MTJdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiNmZjAwMDAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMzA2MWJiMTk4M2U0NGYxMGFkZDZhNmNkYWNhM2UxODggPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzQxOTIxMzk5OTQ0MjRkNThiMGE2NmEwNTllNGMzYThkID0gJChgPGRpdiBpZD0iaHRtbF80MTkyMTM5OTk0NDI0ZDU4YjBhNjZhMDU5ZTRjM2E4ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q2FsZWRvbmlhLUZhaXJiYW5rcyBDbHVzdGVyIDAuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8zMDYxYmIxOTgzZTQ0ZjEwYWRkNmE2Y2RhY2EzZTE4OC5zZXRDb250ZW50KGh0bWxfNDE5MjEzOTk5NDQyNGQ1OGIwYTY2YTA1OWU0YzNhOGQpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzg2M2EyOWExZTViYTQxYzc5ZGZhODk0NmMzNjZmOGY3LmJpbmRQb3B1cChwb3B1cF8zMDYxYmIxOTgzZTQ0ZjEwYWRkNmE2Y2RhY2EzZTE4OCkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODRiMWY2NTFiNWFjNDhiYWI1NzA2ZDVlNWExZDdhMjIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Njk1NDIsIC03OS40MjI1NjM3XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzc4ZmU0YWIzZTVmNDRjMTRhNTg0NGNlODdlZWY0NTU4ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9hMTdiOWE2YjM1Y2I0MGMzODUxMGVjMmRkY2ZiZmI5NiA9ICQoYDxkaXYgaWQ9Imh0bWxfYTE3YjlhNmIzNWNiNDBjMzg1MTBlYzJkZGNmYmZiOTYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNocmlzdGllIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzc4ZmU0YWIzZTVmNDRjMTRhNTg0NGNlODdlZWY0NTU4LnNldENvbnRlbnQoaHRtbF9hMTdiOWE2YjM1Y2I0MGMzODUxMGVjMmRkY2ZiZmI5Nik7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfODRiMWY2NTFiNWFjNDhiYWI1NzA2ZDVlNWExZDdhMjIuYmluZFBvcHVwKHBvcHVwXzc4ZmU0YWIzZTVmNDRjMTRhNTg0NGNlODdlZWY0NTU4KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jYTQ3ZmVhZGRjMzY0M2Q1OTY1OThiZDE3Y2Y2NTg5NSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY2OTAwNTEwMDAwMDAxLCAtNzkuNDQyMjU5M10sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF85MGE1MGU1MjZkZDc0ZWNhOTVmZGVjN2Q5NWZhYTliMCA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfNTI5OWEzODg4ZmQ0NDBjZGEzZDNmZGVhYWY2YmU2NjMgPSAkKGA8ZGl2IGlkPSJodG1sXzUyOTlhMzg4OGZkNDQwY2RhM2QzZmRlYWFmNmJlNjYzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5EdWZmZXJpbiwgRG92ZXJjb3VydCBWaWxsYWdlIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzkwYTUwZTUyNmRkNzRlY2E5NWZkZWM3ZDk1ZmFhOWIwLnNldENvbnRlbnQoaHRtbF81Mjk5YTM4ODhmZDQ0MGNkYTNkM2ZkZWFhZjZiZTY2Myk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfY2E0N2ZlYWRkYzM2NDNkNTk2NTk4YmQxN2NmNjU4OTUuYmluZFBvcHVwKHBvcHVwXzkwYTUwZTUyNmRkNzRlY2E5NWZkZWM3ZDk1ZmFhOWIwKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lYTc0OWU4NmY0ZjY0NGE2YmQxNTkxNDE3NjNhZDk3YyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY0NzkyNjcwMDAwMDAwNiwgLTc5LjQxOTc0OTddLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfZjEwMmYzOWFmOTkyNGU1Yzk5OTg0OWJkMDE5NTY3NGYgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzdkYWNjZDkyZjBhZTQ0MTZhYmU3YmI4ZmY3ZWU2NDUxID0gJChgPGRpdiBpZD0iaHRtbF83ZGFjY2Q5MmYwYWU0NDE2YWJlN2JiOGZmN2VlNjQ1MSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TGl0dGxlIFBvcnR1Z2FsLCBUcmluaXR5IENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2YxMDJmMzlhZjk5MjRlNWM5OTk4NDliZDAxOTU2NzRmLnNldENvbnRlbnQoaHRtbF83ZGFjY2Q5MmYwYWU0NDE2YWJlN2JiOGZmN2VlNjQ1MSk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfZWE3NDllODZmNGY2NDRhNmJkMTU5MTQxNzYzYWQ5N2MuYmluZFBvcHVwKHBvcHVwX2YxMDJmMzlhZjk5MjRlNWM5OTk4NDliZDAxOTU2NzRmKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wOGE2ZmJiNDg5NTM0OWY3OTE1ZGVlYTI5NzlkMDYzZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjYzNjg0NzIsIC03OS40MjgxOTE0MDAwMDAwMl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9kZTcxYWNiYWVkOTY0MzFkYTMwMThkZWI1ODIyM2E4ZiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfNTdlYmY3ZWUzYzBiNDU3OWFkNGNjMDJhNzYwYWQzNGQgPSAkKGA8ZGl2IGlkPSJodG1sXzU3ZWJmN2VlM2MwYjQ1NzlhZDRjYzAyYTc2MGFkMzRkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ccm9ja3RvbiwgUGFya2RhbGUgVmlsbGFnZSwgRXhoaWJpdGlvbiBQbGFjZSBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9kZTcxYWNiYWVkOTY0MzFkYTMwMThkZWI1ODIyM2E4Zi5zZXRDb250ZW50KGh0bWxfNTdlYmY3ZWUzYzBiNDU3OWFkNGNjMDJhNzYwYWQzNGQpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzA4YTZmYmI0ODk1MzQ5Zjc5MTVkZWVhMjk3OWQwNjNmLmJpbmRQb3B1cChwb3B1cF9kZTcxYWNiYWVkOTY0MzFkYTMwMThkZWI1ODIyM2E4ZikKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNWE5NmE3OTU3N2EzNGMzM2FhNjQ3ZWUyZDVjYWRmNWIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MTM3NTYyMDAwMDAwMDYsIC03OS40OTAwNzM4XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjZmYwMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNmZjAwMDAiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzljZTQ0NGY5OTA2ZjRlMGM4Y2NhN2FlZGMyOWY2YTRhID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF84MzVhOWFkOTFiNDY0NmVlYmQzNDA3NGNlYzEzNzkxOCA9ICQoYDxkaXYgaWQ9Imh0bWxfODM1YTlhZDkxYjQ2NDZlZWJkMzQwNzRjZWMxMzc5MTgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5vcnRoIFBhcmssIE1hcGxlIExlYWYgUGFyaywgVXB3b29kIFBhcmsgQ2x1c3RlciAwLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfOWNlNDQ0Zjk5MDZmNGUwYzhjY2E3YWVkYzI5ZjZhNGEuc2V0Q29udGVudChodG1sXzgzNWE5YWQ5MWI0NjQ2ZWViZDM0MDc0Y2VjMTM3OTE4KTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl81YTk2YTc5NTc3YTM0YzMzYWE2NDdlZTJkNWNhZGY1Yi5iaW5kUG9wdXAocG9wdXBfOWNlNDQ0Zjk5MDZmNGUwYzhjY2E3YWVkYzI5ZjZhNGEpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2FjODVmZjU4MDVmNzRkYTFhMGQzNjM5MTJkOGRhNGM5ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjkxMTE1OCwgLTc5LjQ3NjAxMzI5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2Y4ODNkNTdiOGJjMjQzNWFiNmE1MWMxMWE4ODU4OGVlID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF8yYzg2MTEwNjg3Yjg0OTZiOGYwMjlkZTBhZWI1NzkxMyA9ICQoYDxkaXYgaWQ9Imh0bWxfMmM4NjExMDY4N2I4NDk2YjhmMDI5ZGUwYWViNTc5MTMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRlbCBSYXksIE1vdW50IERlbm5pcywgS2VlbHNkYWxlIGFuZCBTaWx2ZXJ0aG9ybiBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9mODgzZDU3YjhiYzI0MzVhYjZhNTFjMTFhODg1ODhlZS5zZXRDb250ZW50KGh0bWxfMmM4NjExMDY4N2I4NDk2YjhmMDI5ZGUwYWViNTc5MTMpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2FjODVmZjU4MDVmNzRkYTFhMGQzNjM5MTJkOGRhNGM5LmJpbmRQb3B1cChwb3B1cF9mODgzZDU3YjhiYzI0MzVhYjZhNTFjMTFhODg1ODhlZSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNWQwZDdlMDEzZWE5NDUxN2I4MGY3MTUzNzA2OGI3NmEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NzMxODUyOTk5OTk5OSwgLTc5LjQ4NzI2MTkwMDAwMDAxXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2E1OTVkNzQxYzFhMjRjMjRhYTdjZTE0MWQ0YmVmYWFmID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF81NDVhNjcwN2I3ZGQ0MWIyYmM1ZDNmNTQyNmNlMTJhNCA9ICQoYDxkaXYgaWQ9Imh0bWxfNTQ1YTY3MDdiN2RkNDFiMmJjNWQzZjU0MjZjZTEyYTQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJ1bm55bWVkZSwgVGhlIEp1bmN0aW9uIE5vcnRoIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwX2E1OTVkNzQxYzFhMjRjMjRhYTdjZTE0MWQ0YmVmYWFmLnNldENvbnRlbnQoaHRtbF81NDVhNjcwN2I3ZGQ0MWIyYmM1ZDNmNTQyNmNlMTJhNCk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfNWQwZDdlMDEzZWE5NDUxN2I4MGY3MTUzNzA2OGI3NmEuYmluZFBvcHVwKHBvcHVwX2E1OTVkNzQxYzFhMjRjMjRhYTdjZTE0MWQ0YmVmYWFmKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xZWMxYTQ0OWU3YWM0YmMwYWRkZjgzODkyMTA1MTI3NyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY2MTYwODMsIC03OS40NjQ3NjMyOTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9lNWU3YWQxYzA3MzU0MWNmODYwODM1ODVhNWM4NTdhNSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfY2MyMDg1MzNmOTMxNGMxZmEwMmY4OGM3MTYzOWM3MTUgPSAkKGA8ZGl2IGlkPSJodG1sX2NjMjA4NTMzZjkzMTRjMWZhMDJmODhjNzE2MzljNzE1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IaWdoIFBhcmssIFRoZSBKdW5jdGlvbiBTb3V0aCBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9lNWU3YWQxYzA3MzU0MWNmODYwODM1ODVhNWM4NTdhNS5zZXRDb250ZW50KGh0bWxfY2MyMDg1MzNmOTMxNGMxZmEwMmY4OGM3MTYzOWM3MTUpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzFlYzFhNDQ5ZTdhYzRiYzBhZGRmODM4OTIxMDUxMjc3LmJpbmRQb3B1cChwb3B1cF9lNWU3YWQxYzA3MzU0MWNmODYwODM1ODVhNWM4NTdhNSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjE3ZTNiNjU2ZTMzNGRiZGEyMjQ5NjAyYTU3NTg3NDggPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDg5NTk3LCAtNzkuNDU2MzI1XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzVhMjA3NTBjZWEzYTQzMmY5Nzg2NGNhZGQ5OTNjM2U4ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF8yMjg5ZDNhNDY3ZmQ0MTY5ODM5ZDBhYmZkY2FkZjI1MCA9ICQoYDxkaXYgaWQ9Imh0bWxfMjI4OWQzYTQ2N2ZkNDE2OTgzOWQwYWJmZGNhZGYyNTAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlBhcmtkYWxlLCBSb25jZXN2YWxsZXMgQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfNWEyMDc1MGNlYTNhNDMyZjk3ODY0Y2FkZDk5M2MzZTguc2V0Q29udGVudChodG1sXzIyODlkM2E0NjdmZDQxNjk4MzlkMGFiZmRjYWRmMjUwKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9mMTdlM2I2NTZlMzM0ZGJkYTIyNDk2MDJhNTc1ODc0OC5iaW5kUG9wdXAocG9wdXBfNWEyMDc1MGNlYTNhNDMyZjk3ODY0Y2FkZDk5M2MzZTgpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzNmNmIyYTIwNjQxZDRjNmI4OTYyYTgxYzE4YzNkYzZjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUxNTcwNiwgLTc5LjQ4NDQ0OTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfNmViOWVkOTczNTg1NGVjZDgxMTY3ZTc5MmFkMzM1ZDIgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzY5N2YzN2U0ZjE1ZDRmMzlhNDIyNTg2YzY0Y2VlMmY2ID0gJChgPGRpdiBpZD0iaHRtbF82OTdmMzdlNGYxNWQ0ZjM5YTQyMjU4NmM2NGNlZTJmNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UnVubnltZWRlLCBTd2Fuc2VhIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzZlYjllZDk3MzU4NTRlY2Q4MTE2N2U3OTJhZDMzNWQyLnNldENvbnRlbnQoaHRtbF82OTdmMzdlNGYxNWQ0ZjM5YTQyMjU4NmM2NGNlZTJmNik7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfM2Y2YjJhMjA2NDFkNGM2Yjg5NjJhODFjMThjM2RjNmMuYmluZFBvcHVwKHBvcHVwXzZlYjllZDk3MzU4NTRlY2Q4MTE2N2U3OTJhZDMzNWQyKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zMWMxMmEzMjk5MGU0ZDIyOWExNTBmMjhmNmYwOTQwOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY2MjMwMTUsIC03OS4zODk0OTM4XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzE5M2Q5ZDg1OTI0ZjQ1YWU5MTVmYTczZTQ0OThhZWRjID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF84ODRlZjVkNDg2OWM0ODY3YmIxZWI0M2E2ZDE4ZGZiZCA9ICQoYDxkaXYgaWQ9Imh0bWxfODg0ZWY1ZDQ4NjljNDg2N2JiMWViNDNhNmQxOGRmYmQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlF1ZWVuJiMzOTtzIFBhcmssIE9udGFyaW8gUHJvdmluY2lhbCBHb3Zlcm5tZW50IENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzE5M2Q5ZDg1OTI0ZjQ1YWU5MTVmYTczZTQ0OThhZWRjLnNldENvbnRlbnQoaHRtbF84ODRlZjVkNDg2OWM0ODY3YmIxZWI0M2E2ZDE4ZGZiZCk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMzFjMTJhMzI5OTBlNGQyMjlhMTUwZjI4ZjZmMDk0MDguYmluZFBvcHVwKHBvcHVwXzE5M2Q5ZDg1OTI0ZjQ1YWU5MTVmYTczZTQ0OThhZWRjKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jM2ZmYTkxNDE2YjQ0MTk4YjBiMGFmY2Y4OTJmZmQ1MCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjYzNjk2NTYsIC03OS42MTU4MTg5OTk5OTk5OV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF8zNzI3MDIxZTg2NTg0Yzk0YjA5ZDIwNTMzZGQyMTI1NSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfOWU3MWVjODQ2MzJiNDJlYTkxYTg0ZmUxNzU0ZGI1MDcgPSAkKGA8ZGl2IGlkPSJodG1sXzllNzFlYzg0NjMyYjQyZWE5MWE4NGZlMTc1NGRiNTA3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DYW5hZGEgUG9zdCBHYXRld2F5IFByb2Nlc3NpbmcgQ2VudHJlIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzM3MjcwMjFlODY1ODRjOTRiMDlkMjA1MzNkZDIxMjU1LnNldENvbnRlbnQoaHRtbF85ZTcxZWM4NDYzMmI0MmVhOTFhODRmZTE3NTRkYjUwNyk7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfYzNmZmE5MTQxNmI0NDE5OGIwYjBhZmNmODkyZmZkNTAuYmluZFBvcHVwKHBvcHVwXzM3MjcwMjFlODY1ODRjOTRiMDlkMjA1MzNkZDIxMjU1KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zNzg2NzRiNTgyZGM0MDczYmZmMmI5OTlmYzM4MWMyNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY2Mjc0MzksIC03OS4zMjE1NThdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMzQ2OWViNjM3NTJiNDkyMThkZTBlZThkZjIyYmNlZTcgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzg4M2UxZWU1ZGZlZDQyMjFiYmQxMmQ5M2I0ODZhZDM2ID0gJChgPGRpdiBpZD0iaHRtbF84ODNlMWVlNWRmZWQ0MjIxYmJkMTJkOTNiNDg2YWQzNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnVzaW5lc3MgcmVwbHkgbWFpbCBQcm9jZXNzaW5nIENlbnRyZSwgU291dGggQ2VudHJhbCBMZXR0ZXIgUHJvY2Vzc2luZyBQbGFudCBUb3JvbnRvIENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzM0NjllYjYzNzUyYjQ5MjE4ZGUwZWU4ZGYyMmJjZWU3LnNldENvbnRlbnQoaHRtbF84ODNlMWVlNWRmZWQ0MjIxYmJkMTJkOTNiNDg2YWQzNik7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMzc4Njc0YjU4MmRjNDA3M2JmZjJiOTk5ZmMzODFjMjcuYmluZFBvcHVwKHBvcHVwXzM0NjllYjYzNzUyYjQ5MjE4ZGUwZWU4ZGYyMmJjZWU3KQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jZTA4NjQ2ZDUzZGY0MmQ5OTQxODkwZWY2NjgyNGE4MiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjYwNTY0NjYsIC03OS41MDEzMjA3MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF83Yzc0YWI2NjI2ZDM0YzFjOWQ3OGNhNDIyMDI1ZmMxMSA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfOWExYzMxYTQ3MzdlNGM5M2JlN2IzOGM2OWIyNmQ4NjQgPSAkKGA8ZGl2IGlkPSJodG1sXzlhMWMzMWE0NzM3ZTRjOTNiZTdiMzhjNjliMjZkODY0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5OZXcgVG9yb250bywgTWltaWNvIFNvdXRoLCBIdW1iZXIgQmF5IFNob3JlcyBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF83Yzc0YWI2NjI2ZDM0YzFjOWQ3OGNhNDIyMDI1ZmMxMS5zZXRDb250ZW50KGh0bWxfOWExYzMxYTQ3MzdlNGM5M2JlN2IzOGM2OWIyNmQ4NjQpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2NlMDg2NDZkNTNkZjQyZDk5NDE4OTBlZjY2ODI0YTgyLmJpbmRQb3B1cChwb3B1cF83Yzc0YWI2NjI2ZDM0YzFjOWQ3OGNhNDIyMDI1ZmMxMSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZjhjZWIyN2UzNmVlNGQwNTk0NWM3NTg0NzQzMGMyYTIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42MDI0MTM3MDAwMDAwMSwgLTc5LjU0MzQ4NDA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwX2Y0NGQ5OTZiZTFiYTQxM2Q5MDY2OTg3M2QwYzE1M2U2ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF80ZDVmNDcyNjk4ZmE0NTczOTljMGEyYTQ0ZDlmMmYyYyA9ICQoYDxkaXYgaWQ9Imh0bWxfNGQ1ZjQ3MjY5OGZhNDU3Mzk5YzBhMmE0NGQ5ZjJmMmMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkFsZGVyd29vZCwgTG9uZyBCcmFuY2ggQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfZjQ0ZDk5NmJlMWJhNDEzZDkwNjY5ODczZDBjMTUzZTYuc2V0Q29udGVudChodG1sXzRkNWY0NzI2OThmYTQ1NzM5OWMwYTJhNDRkOWYyZjJjKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9mOGNlYjI3ZTM2ZWU0ZDA1OTQ1Yzc1ODQ3NDMwYzJhMi5iaW5kUG9wdXAocG9wdXBfZjQ0ZDk5NmJlMWJhNDEzZDkwNjY5ODczZDBjMTUzZTYpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzdmOWJjYTBhMDY5MzQ1ZWFhMjhkZDQxN2ViNDVlOWUwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjUzNjUzNjAwMDAwMDA1LCAtNzkuNTA2OTQzNl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiI2ZmMDAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF83ZWIzY2JlYWRjNTk0ZDU3OWNmZTZiNzg3MjY1OTY3MCA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfNzhmM2I0YjRmZGY2NGVhMjgzM2E5OGM1NTBhMjU5NmMgPSAkKGA8ZGl2IGlkPSJodG1sXzc4ZjNiNGI0ZmRmNjRlYTI4MzNhOThjNTUwYTI1OTZjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5UaGUgS2luZ3N3YXksIE1vbnRnb21lcnkgUm9hZCwgT2xkIE1pbGwgTm9ydGggQ2x1c3RlciAwLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfN2ViM2NiZWFkYzU5NGQ1NzljZmU2Yjc4NzI2NTk2NzAuc2V0Q29udGVudChodG1sXzc4ZjNiNGI0ZmRmNjRlYTI4MzNhOThjNTUwYTI1OTZjKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl83ZjliY2EwYTA2OTM0NWVhYTI4ZGQ0MTdlYjQ1ZTllMC5iaW5kUG9wdXAocG9wdXBfN2ViM2NiZWFkYzU5NGQ1NzljZmU2Yjc4NzI2NTk2NzApCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2ZiYjMwZmE1MmRmZTQ2MTRiMDY2MmYxOTFhYjU2NTg4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjM2MjU3OSwgLTc5LjQ5ODUwOTA5OTk5OTk5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjZmYwMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNmZjAwMDAiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzk3Njg1ZjQ3OWFkMTQyMzk4YmEyNzViYzU1YTY5MmM3ID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF80Nzc0MmFkOWI5OGE0NDM0YWM4MTdkYjgyY2FlZjk4YyA9ICQoYDxkaXYgaWQ9Imh0bWxfNDc3NDJhZDliOThhNDQzNGFjODE3ZGI4MmNhZWY5OGMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk9sZCBNaWxsIFNvdXRoLCBLaW5nJiMzOTtzIE1pbGwgUGFyaywgU3VubnlsZWEsIEh1bWJlciBCYXksIE1pbWljbyBORSwgVGhlIFF1ZWVuc3dheSBFYXN0LCBSb3lhbCBZb3JrIFNvdXRoIEVhc3QsIEtpbmdzd2F5IFBhcmsgU291dGggRWFzdCBDbHVzdGVyIDAuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF85NzY4NWY0NzlhZDE0MjM5OGJhMjc1YmM1NWE2OTJjNy5zZXRDb250ZW50KGh0bWxfNDc3NDJhZDliOThhNDQzNGFjODE3ZGI4MmNhZWY5OGMpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2ZiYjMwZmE1MmRmZTQ2MTRiMDY2MmYxOTFhYjU2NTg4LmJpbmRQb3B1cChwb3B1cF85NzY4NWY0NzlhZDE0MjM5OGJhMjc1YmM1NWE2OTJjNykKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMGQ1YTVmYjNkOGQ3NDkxNWJjOGY4NWY1MjBhNjk2YTcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42Mjg4NDA4LCAtNzkuNTIwOTk5NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMDE0OGUyYTA3NDFlNDY4Nzg2OTM1YTljZjEzMzIzNmUgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzYyZmY2ODg3MDJhNDQ1ZGVhMDViZjJlZjZlYzBmMTRmID0gJChgPGRpdiBpZD0iaHRtbF82MmZmNjg4NzAyYTQ0NWRlYTA1YmYyZWY2ZWMwZjE0ZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TWltaWNvIE5XLCBUaGUgUXVlZW5zd2F5IFdlc3QsIFNvdXRoIG9mIEJsb29yLCBLaW5nc3dheSBQYXJrIFNvdXRoIFdlc3QsIFJveWFsIFlvcmsgU291dGggV2VzdCBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8wMTQ4ZTJhMDc0MWU0Njg3ODY5MzVhOWNmMTMzMjM2ZS5zZXRDb250ZW50KGh0bWxfNjJmZjY4ODcwMmE0NDVkZWEwNWJmMmVmNmVjMGYxNGYpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzBkNWE1ZmIzZDhkNzQ5MTViYzhmODVmNTIwYTY5NmE3LmJpbmRQb3B1cChwb3B1cF8wMTQ4ZTJhMDc0MWU0Njg3ODY5MzVhOWNmMTMzMjM2ZSkKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTZhNzMyZmY1Njk3NDMxYzg5ZjE2MGNkYTU4MGVmNWMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NTA5NDMyLCAtNzkuNTU0NzI0NDAwMDAwMDFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MGZmYjQiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwZmZiNCIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfZTY5NmFjOTMwYjRmNGQxMmI2NzEwNDJhNTgxZDFiZWIgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzljNTcwZGViMGU0OTQwNmNiMjE2NTY0ODIyM2I2YTViID0gJChgPGRpdiBpZD0iaHRtbF85YzU3MGRlYjBlNDk0MDZjYjIxNjU2NDgyMjNiNmE1YiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2VzdCBEZWFuZSBQYXJrLCBQcmluY2VzcyBHYXJkZW5zLCBNYXJ0aW4gR3JvdmUsIElzbGluZ3RvbiwgQ2xvdmVyZGFsZSBDbHVzdGVyIDMuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9lNjk2YWM5MzBiNGY0ZDEyYjY3MTA0MmE1ODFkMWJlYi5zZXRDb250ZW50KGh0bWxfOWM1NzBkZWIwZTQ5NDA2Y2IyMTY1NjQ4MjIzYjZhNWIpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzU2YTczMmZmNTY5NzQzMWM4OWYxNjBjZGE1ODBlZjVjLmJpbmRQb3B1cChwb3B1cF9lNjk2YWM5MzBiNGY0ZDEyYjY3MTA0MmE1ODFkMWJlYikKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOGJjNjQ1YjdhY2JkNGVmOTkyYWI0MzBiMmQ0NjgzZmYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My42NDM1MTUyLCAtNzkuNTc3MjAwNzk5OTk5OTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfMWI3MTQ5MTVhNjEwNGNhNGI4YzcwZmQxZTYwZmVmNGMgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzFhZmJiNDZlMzllMTQ0NWNiMTIwZjFhMTc0YzBjZmM5ID0gJChgPGRpdiBpZD0iaHRtbF8xYWZiYjQ2ZTM5ZTE0NDVjYjEyMGYxYTE3NGMwY2ZjOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RXJpbmdhdGUsIEJsb29yZGFsZSBHYXJkZW5zLCBPbGQgQnVybmhhbXRob3JwZSwgTWFya2xhbmQgV29vZCBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF8xYjcxNDkxNWE2MTA0Y2E0YjhjNzBmZDFlNjBmZWY0Yy5zZXRDb250ZW50KGh0bWxfMWFmYmI0NmUzOWUxNDQ1Y2IxMjBmMWExNzRjMGNmYzkpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzhiYzY0NWI3YWNiZDRlZjk5MmFiNDMwYjJkNDY4M2ZmLmJpbmRQb3B1cChwb3B1cF8xYjcxNDkxNWE2MTA0Y2E0YjhjNzBmZDFlNjBmZWY0YykKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNGRlYWU1NjQzMGIyNGJmZWIwNWNlZTUyMmQ1MzUyZjcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43NTYzMDMzLCAtNzkuNTY1OTYzMjk5OTk5OTldLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfNmFjYmIwODcwMjc1NDg3NmJjZjljYTNlZGNlZWMyNmMgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sXzMwNjkxZmZkZWRjOTQzMjhiNGI1MjNhYjJhNmY3NWQ4ID0gJChgPGRpdiBpZD0iaHRtbF8zMDY5MWZmZGVkYzk0MzI4YjRiNTIzYWIyYTZmNzVkOCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SHVtYmVyIFN1bW1pdCBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF82YWNiYjA4NzAyNzU0ODc2YmNmOWNhM2VkY2VlYzI2Yy5zZXRDb250ZW50KGh0bWxfMzA2OTFmZmRlZGM5NDMyOGI0YjUyM2FiMmE2Zjc1ZDgpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzRkZWFlNTY0MzBiMjRiZmViMDVjZWU1MjJkNTM1MmY3LmJpbmRQb3B1cChwb3B1cF82YWNiYjA4NzAyNzU0ODc2YmNmOWNhM2VkY2VlYzI2YykKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYmVhNGUwNDU3ZTQxNDAxZTk4ZjIyYzQyMzc5N2YyNmQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MjQ3NjU5LCAtNzkuNTMyMjQyNDAwMDAwMDJdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfYTBkOGUyOGQ3OWVkNDcyZWIwZTY3ODJlZTMzMTM4YjMgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2M0ZDU0OTVlMmIzYTRiNTI4ZWY1ZjhlMDEyMzlkMTRlID0gJChgPGRpdiBpZD0iaHRtbF9jNGQ1NDk1ZTJiM2E0YjUyOGVmNWY4ZTAxMjM5ZDE0ZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SHVtYmVybGVhLCBFbWVyeSBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9hMGQ4ZTI4ZDc5ZWQ0NzJlYjBlNjc4MmVlMzMxMzhiMy5zZXRDb250ZW50KGh0bWxfYzRkNTQ5NWUyYjNhNGI1MjhlZjVmOGUwMTIzOWQxNGUpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyX2JlYTRlMDQ1N2U0MTQwMWU5OGYyMmM0MjM3OTdmMjZkLmJpbmRQb3B1cChwb3B1cF9hMGQ4ZTI4ZDc5ZWQ0NzJlYjBlNjc4MmVlMzMxMzhiMykKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODhhMjhjMWExODgxNDkzMzkyZTIxYWFmODE0MDhmYjYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43MDY4NzYsIC03OS41MTgxODg0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiI2ZmMDAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF80ZDA2NGY4ZGRhMTQ0MGE5YWZjMWJmNWYzNGViMDU0YyA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfMTJhNDY4MTg0ZjIwNDNmNjk1ZDZkZTRkN2IxOTk4NGQgPSAkKGA8ZGl2IGlkPSJodG1sXzEyYTQ2ODE4NGYyMDQzZjY5NWQ2ZGU0ZDdiMTk5ODRkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5XZXN0b24gQ2x1c3RlciAwLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfNGQwNjRmOGRkYTE0NDBhOWFmYzFiZjVmMzRlYjA1NGMuc2V0Q29udGVudChodG1sXzEyYTQ2ODE4NGYyMDQzZjY5NWQ2ZGU0ZDdiMTk5ODRkKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl84OGEyOGMxYTE4ODE0OTMzOTJlMjFhYWY4MTQwOGZiNi5iaW5kUG9wdXAocG9wdXBfNGQwNjRmOGRkYTE0NDBhOWFmYzFiZjVmMzRlYjA1NGMpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzEzNzdjOTRiN2QzOTRjZGJiMjZlNTkwOGU2NmJjNzA4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNjk2MzE5LCAtNzkuNTMyMjQyNDAwMDAwMDJdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiM4MDAwZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsICJmaWxsT3BhY2l0eSI6IDAuNywgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMS4wLCAicmFkaXVzIjogNSwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8zZmQ3MDliZTBmNzI0ZWI0YTVjNjVhZGE1ZmNiZWE1NSk7CiAgICAgICAgCiAgICAKICAgICAgICB2YXIgcG9wdXBfOGQwNDVhMzU0NmQwNDc1ZGJjNDU5YjU4MzNiZmQxNmIgPSBMLnBvcHVwKHsibWF4V2lkdGgiOiAiMTAwJSJ9KTsKCiAgICAgICAgCiAgICAgICAgICAgIHZhciBodG1sX2U0NGYyYzEyNjk4NDQ4MWZiMmJiZGU4NWU4MmZjZDRmID0gJChgPGRpdiBpZD0iaHRtbF9lNDRmMmMxMjY5ODQ0ODFmYjJiYmRlODVlODJmY2Q0ZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2VzdG1vdW50IENsdXN0ZXIgMS4wPC9kaXY+YClbMF07CiAgICAgICAgICAgIHBvcHVwXzhkMDQ1YTM1NDZkMDQ3NWRiYzQ1OWI1ODMzYmZkMTZiLnNldENvbnRlbnQoaHRtbF9lNDRmMmMxMjY5ODQ0ODFmYjJiYmRlODVlODJmY2Q0Zik7CiAgICAgICAgCgogICAgICAgIGNpcmNsZV9tYXJrZXJfMTM3N2M5NGI3ZDM5NGNkYmIyNmU1OTA4ZTY2YmM3MDguYmluZFBvcHVwKHBvcHVwXzhkMDQ1YTM1NDZkMDQ3NWRiYzQ1OWI1ODMzYmZkMTZiKQogICAgICAgIDsKCiAgICAgICAgCiAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84MTVmNzZmMzNlMDE0YmZiOWQ1NTJlYzEzY2NlMTAwYyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQzLjY4ODkwNTQsIC03OS41NTQ3MjQ0MDAwMDAwMV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiI2ZmMDAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjZmYwMDAwIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF80ZTcwMGY2NGM1Mjk0OGQyYmRkNWE5ZmEyNTJkZWU0NiA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfMGJjZDMxM2Q5YjRhNGQ5ZTgyNWJhNWE2MDNlYWIxYWUgPSAkKGA8ZGl2IGlkPSJodG1sXzBiY2QzMTNkOWI0YTRkOWU4MjViYTVhNjAzZWFiMWFlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5LaW5nc3ZpZXcgVmlsbGFnZSwgU3QuIFBoaWxsaXBzLCBNYXJ0aW4gR3JvdmUgR2FyZGVucywgUmljaHZpZXcgR2FyZGVucyBDbHVzdGVyIDAuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF80ZTcwMGY2NGM1Mjk0OGQyYmRkNWE5ZmEyNTJkZWU0Ni5zZXRDb250ZW50KGh0bWxfMGJjZDMxM2Q5YjRhNGQ5ZTgyNWJhNWE2MDNlYWIxYWUpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzgxNWY3NmYzM2UwMTRiZmI5ZDU1MmVjMTNjY2UxMDBjLmJpbmRQb3B1cChwb3B1cF80ZTcwMGY2NGM1Mjk0OGQyYmRkNWE5ZmEyNTJkZWU0NikKICAgICAgICA7CgogICAgICAgIAogICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYzVlMWMyNDBkZTg4NDkwNWI2MmM5ZTlmMWZlZjYzZjAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0My43Mzk0MTYzOTk5OTk5OTYsIC03OS41ODg0MzY5XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjODAwMGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiM4MDAwZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjcsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEuMCwgInJhZGl1cyI6IDUsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfM2ZkNzA5YmUwZjcyNGViNGE1YzY1YWRhNWZjYmVhNTUpOwogICAgICAgIAogICAgCiAgICAgICAgdmFyIHBvcHVwXzcyNTFmODg5NmI5ODRhZGRhMTJlNjFlZDkwZmY0NzVhID0gTC5wb3B1cCh7Im1heFdpZHRoIjogIjEwMCUifSk7CgogICAgICAgIAogICAgICAgICAgICB2YXIgaHRtbF9jZmUwNTQ3MjU1ZmU0ZmVjYmRlYjdkOTVkNGVmOTg3ZiA9ICQoYDxkaXYgaWQ9Imh0bWxfY2ZlMDU0NzI1NWZlNGZlY2JkZWI3ZDk1ZDRlZjk4N2YiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlNvdXRoIFN0ZWVsZXMsIFNpbHZlcnN0b25lLCBIdW1iZXJnYXRlLCBKYW1lc3Rvd24sIE1vdW50IE9saXZlLCBCZWF1bW9uZCBIZWlnaHRzLCBUaGlzdGxldG93biwgQWxiaW9uIEdhcmRlbnMgQ2x1c3RlciAxLjA8L2Rpdj5gKVswXTsKICAgICAgICAgICAgcG9wdXBfNzI1MWY4ODk2Yjk4NGFkZGExMmU2MWVkOTBmZjQ3NWEuc2V0Q29udGVudChodG1sX2NmZTA1NDcyNTVmZTRmZWNiZGViN2Q5NWQ0ZWY5ODdmKTsKICAgICAgICAKCiAgICAgICAgY2lyY2xlX21hcmtlcl9jNWUxYzI0MGRlODg0OTA1YjYyYzllOWYxZmVmNjNmMC5iaW5kUG9wdXAocG9wdXBfNzI1MWY4ODk2Yjk4NGFkZGExMmU2MWVkOTBmZjQ3NWEpCiAgICAgICAgOwoKICAgICAgICAKICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzk5YmMyNWE5ZGM5YjQ3YjdiZWM1M2M1ZjhkNjcwYjViID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDMuNzA2NzQ4Mjk5OTk5OTk0LCAtNzkuNTk0MDU0NF0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzgwMDBmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjODAwMGZmIiwgImZpbGxPcGFjaXR5IjogMC43LCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLjAsICJyYWRpdXMiOiA1LCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzNmZDcwOWJlMGY3MjRlYjRhNWM2NWFkYTVmY2JlYTU1KTsKICAgICAgICAKICAgIAogICAgICAgIHZhciBwb3B1cF9jYzVmNzgwOTYyZGI0MWVlOGY1YzIxNDk3MWRiMTQ2ZCA9IEwucG9wdXAoeyJtYXhXaWR0aCI6ICIxMDAlIn0pOwoKICAgICAgICAKICAgICAgICAgICAgdmFyIGh0bWxfZTc0YTIwMDY2OTc2NDc0NGFjMzY2NTJhMjViMjQ5OTUgPSAkKGA8ZGl2IGlkPSJodG1sX2U3NGEyMDA2Njk3NjQ3NDRhYzM2NjUyYTI1YjI0OTk1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ob3J0aHdlc3QsIFdlc3QgSHVtYmVyIC0gQ2xhaXJ2aWxsZSBDbHVzdGVyIDEuMDwvZGl2PmApWzBdOwogICAgICAgICAgICBwb3B1cF9jYzVmNzgwOTYyZGI0MWVlOGY1YzIxNDk3MWRiMTQ2ZC5zZXRDb250ZW50KGh0bWxfZTc0YTIwMDY2OTc2NDc0NGFjMzY2NTJhMjViMjQ5OTUpOwogICAgICAgIAoKICAgICAgICBjaXJjbGVfbWFya2VyXzk5YmMyNWE5ZGM5YjQ3YjdiZWM1M2M1ZjhkNjcwYjViLmJpbmRQb3B1cChwb3B1cF9jYzVmNzgwOTYyZGI0MWVlOGY1YzIxNDk3MWRiMTQ2ZCkKICAgICAgICA7CgogICAgICAgIAogICAgCjwvc2NyaXB0Pg== 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 0x7f4188aafc70>" | |
] | |
}, | |
"execution_count": 225, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"plot_clusters(toronto_merged.dropna())" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Cluster summary" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The size of the cluster is not very satisfying" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 226, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"Cluster\n", | |
"0.0 15\n", | |
"1.0 83\n", | |
"2.0 1\n", | |
"3.0 1\n", | |
"4.0 1\n", | |
"dtype: int64" | |
] | |
}, | |
"execution_count": 226, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"toronto_merged.dropna().groupby(\"Cluster\").size()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Let's say a word about the cluster however" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 216, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def get_cluster(cluster: int) -> DataFrame:\n", | |
" return toronto_merged.loc[\n", | |
" toronto_merged[\"Cluster\"] == cluster,\n", | |
" toronto_merged.columns[[1] + list(range(5, toronto_merged.shape[1]))],\n", | |
" ]" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Cluster 0: near parks" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 221, | |
"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>Cluster</th>\n", | |
" <th>1st common venue</th>\n", | |
" <th>2nd common venue</th>\n", | |
" <th>3rd common venue</th>\n", | |
" <th>4th common venue</th>\n", | |
" <th>5th common venue</th>\n", | |
" <th>6th common venue</th>\n", | |
" <th>7th common venue</th>\n", | |
" <th>8th common venue</th>\n", | |
" <th>9th common venue</th>\n", | |
" <th>10th common venue</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>14</th>\n", | |
" <td>Scarborough</td>\n", | |
" <td>0.0</td>\n", | |
" <td>park</td>\n", | |
" <td>coffee shop</td>\n", | |
" <td>playground</td>\n", | |
" <td>drugstore</td>\n", | |
" <td>diner</td>\n", | |
" <td>discount store</td>\n", | |
" <td>distribution center</td>\n", | |
" <td>dog run</td>\n", | |
" <td>doner restaurant</td>\n", | |
" <td>donut shop</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>21</th>\n", | |
" <td>North York</td>\n", | |
" <td>0.0</td>\n", | |
" <td>park</td>\n", | |
" <td>gym</td>\n", | |
" <td>drugstore</td>\n", | |
" <td>diner</td>\n", | |
" <td>discount store</td>\n", | |
" <td>distribution center</td>\n", | |
" <td>dog run</td>\n", | |
" <td>doner restaurant</td>\n", | |
" <td>donut shop</td>\n", | |
" <td>dumpling restaurant</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>23</th>\n", | |
" <td>North York</td>\n", | |
" <td>0.0</td>\n", | |
" <td>park</td>\n", | |
" <td>convenience store</td>\n", | |
" <td>dumpling restaurant</td>\n", | |
" <td>discount store</td>\n", | |
" <td>distribution center</td>\n", | |
" <td>dog run</td>\n", | |
" <td>doner restaurant</td>\n", | |
" <td>donut shop</td>\n", | |
" <td>drugstore</td>\n", | |
" <td>eastern european restaurant</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>25</th>\n", | |
" <td>North York</td>\n", | |
" <td>0.0</td>\n", | |
" <td>park</td>\n", | |
" <td>food & drink shop</td>\n", | |
" <td>fast food restaurant</td>\n", | |
" <td>donut shop</td>\n", | |
" <td>diner</td>\n", | |
" <td>discount store</td>\n", | |
" <td>distribution center</td>\n", | |
" <td>dog run</td>\n", | |
" <td>doner restaurant</td>\n", | |
" <td>dumpling restaurant</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>40</th>\n", | |
" <td>East York</td>\n", | |
" <td>0.0</td>\n", | |
" <td>park</td>\n", | |
" <td>pizza place</td>\n", | |
" <td>convenience store</td>\n", | |
" <td>drugstore</td>\n", | |
" <td>diner</td>\n", | |
" <td>discount store</td>\n", | |
" <td>distribution center</td>\n", | |
" <td>dog run</td>\n", | |
" <td>doner restaurant</td>\n", | |
" <td>donut shop</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Borough Cluster 1st common venue 2nd common venue \\\n", | |
"14 Scarborough 0.0 park coffee shop \n", | |
"21 North York 0.0 park gym \n", | |
"23 North York 0.0 park convenience store \n", | |
"25 North York 0.0 park food & drink shop \n", | |
"40 East York 0.0 park pizza place \n", | |
"\n", | |
" 3rd common venue 4th common venue 5th common venue \\\n", | |
"14 playground drugstore diner \n", | |
"21 drugstore diner discount store \n", | |
"23 dumpling restaurant discount store distribution center \n", | |
"25 fast food restaurant donut shop diner \n", | |
"40 convenience store drugstore diner \n", | |
"\n", | |
" 6th common venue 7th common venue 8th common venue \\\n", | |
"14 discount store distribution center dog run \n", | |
"21 distribution center dog run doner restaurant \n", | |
"23 dog run doner restaurant donut shop \n", | |
"25 discount store distribution center dog run \n", | |
"40 discount store distribution center dog run \n", | |
"\n", | |
" 9th common venue 10th common venue \n", | |
"14 doner restaurant donut shop \n", | |
"21 donut shop dumpling restaurant \n", | |
"23 drugstore eastern european restaurant \n", | |
"25 doner restaurant dumpling restaurant \n", | |
"40 doner restaurant donut shop " | |
] | |
}, | |
"execution_count": 221, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"get_cluster(0).head(5)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Cluster 1: restaurant" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 220, | |
"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>Cluster</th>\n", | |
" <th>1st common venue</th>\n", | |
" <th>2nd common venue</th>\n", | |
" <th>3rd common venue</th>\n", | |
" <th>4th common venue</th>\n", | |
" <th>5th common venue</th>\n", | |
" <th>6th common venue</th>\n", | |
" <th>7th common venue</th>\n", | |
" <th>8th common venue</th>\n", | |
" <th>9th common venue</th>\n", | |
" <th>10th common venue</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>Scarborough</td>\n", | |
" <td>1.0</td>\n", | |
" <td>fast food restaurant</td>\n", | |
" <td>print shop</td>\n", | |
" <td>drugstore</td>\n", | |
" <td>discount store</td>\n", | |
" <td>distribution center</td>\n", | |
" <td>dog run</td>\n", | |
" <td>doner restaurant</td>\n", | |
" <td>donut shop</td>\n", | |
" <td>dumpling restaurant</td>\n", | |
" <td>dim sum restaurant</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>Scarborough</td>\n", | |
" <td>1.0</td>\n", | |
" <td>moving target</td>\n", | |
" <td>bar</td>\n", | |
" <td>yoga studio</td>\n", | |
" <td>drugstore</td>\n", | |
" <td>distribution center</td>\n", | |
" <td>dog run</td>\n", | |
" <td>doner restaurant</td>\n", | |
" <td>donut shop</td>\n", | |
" <td>dumpling restaurant</td>\n", | |
" <td>diner</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2</th>\n", | |
" <td>Scarborough</td>\n", | |
" <td>1.0</td>\n", | |
" <td>rental car location</td>\n", | |
" <td>mexican restaurant</td>\n", | |
" <td>breakfast spot</td>\n", | |
" <td>electronics store</td>\n", | |
" <td>intersection</td>\n", | |
" <td>bank</td>\n", | |
" <td>medical center</td>\n", | |
" <td>restaurant</td>\n", | |
" <td>distribution center</td>\n", | |
" <td>dog run</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>3</th>\n", | |
" <td>Scarborough</td>\n", | |
" <td>1.0</td>\n", | |
" <td>coffee shop</td>\n", | |
" <td>korean restaurant</td>\n", | |
" <td>yoga studio</td>\n", | |
" <td>dumpling restaurant</td>\n", | |
" <td>distribution center</td>\n", | |
" <td>dog run</td>\n", | |
" <td>doner restaurant</td>\n", | |
" <td>donut shop</td>\n", | |
" <td>drugstore</td>\n", | |
" <td>electronics store</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>4</th>\n", | |
" <td>Scarborough</td>\n", | |
" <td>1.0</td>\n", | |
" <td>hakka restaurant</td>\n", | |
" <td>fried chicken joint</td>\n", | |
" <td>bank</td>\n", | |
" <td>athletics & sports</td>\n", | |
" <td>gas station</td>\n", | |
" <td>caribbean restaurant</td>\n", | |
" <td>thai restaurant</td>\n", | |
" <td>bakery</td>\n", | |
" <td>dumpling restaurant</td>\n", | |
" <td>drugstore</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Borough Cluster 1st common venue 2nd common venue \\\n", | |
"0 Scarborough 1.0 fast food restaurant print shop \n", | |
"1 Scarborough 1.0 moving target bar \n", | |
"2 Scarborough 1.0 rental car location mexican restaurant \n", | |
"3 Scarborough 1.0 coffee shop korean restaurant \n", | |
"4 Scarborough 1.0 hakka restaurant fried chicken joint \n", | |
"\n", | |
" 3rd common venue 4th common venue 5th common venue \\\n", | |
"0 drugstore discount store distribution center \n", | |
"1 yoga studio drugstore distribution center \n", | |
"2 breakfast spot electronics store intersection \n", | |
"3 yoga studio dumpling restaurant distribution center \n", | |
"4 bank athletics & sports gas station \n", | |
"\n", | |
" 6th common venue 7th common venue 8th common venue \\\n", | |
"0 dog run doner restaurant donut shop \n", | |
"1 dog run doner restaurant donut shop \n", | |
"2 bank medical center restaurant \n", | |
"3 dog run doner restaurant donut shop \n", | |
"4 caribbean restaurant thai restaurant bakery \n", | |
"\n", | |
" 9th common venue 10th common venue \n", | |
"0 dumpling restaurant dim sum restaurant \n", | |
"1 dumpling restaurant diner \n", | |
"2 distribution center dog run \n", | |
"3 drugstore electronics store \n", | |
"4 dumpling restaurant drugstore " | |
] | |
}, | |
"execution_count": 220, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"get_cluster(1).head(5)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Cluster 2: martial+yoga" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 219, | |
"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>Cluster</th>\n", | |
" <th>1st common venue</th>\n", | |
" <th>2nd common venue</th>\n", | |
" <th>3rd common venue</th>\n", | |
" <th>4th common venue</th>\n", | |
" <th>5th common venue</th>\n", | |
" <th>6th common venue</th>\n", | |
" <th>7th common venue</th>\n", | |
" <th>8th common venue</th>\n", | |
" <th>9th common venue</th>\n", | |
" <th>10th common venue</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>20</th>\n", | |
" <td>North York</td>\n", | |
" <td>2.0</td>\n", | |
" <td>martial arts school</td>\n", | |
" <td>yoga studio</td>\n", | |
" <td>dumpling restaurant</td>\n", | |
" <td>discount store</td>\n", | |
" <td>distribution center</td>\n", | |
" <td>dog run</td>\n", | |
" <td>doner restaurant</td>\n", | |
" <td>donut shop</td>\n", | |
" <td>drugstore</td>\n", | |
" <td>eastern european restaurant</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Borough Cluster 1st common venue 2nd common venue \\\n", | |
"20 North York 2.0 martial arts school yoga studio \n", | |
"\n", | |
" 3rd common venue 4th common venue 5th common venue \\\n", | |
"20 dumpling restaurant discount store distribution center \n", | |
"\n", | |
" 6th common venue 7th common venue 8th common venue 9th common venue \\\n", | |
"20 dog run doner restaurant donut shop drugstore \n", | |
"\n", | |
" 10th common venue \n", | |
"20 eastern european restaurant " | |
] | |
}, | |
"execution_count": 219, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"get_cluster(2)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Cluster 3: restaurant too :-)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 218, | |
"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>Cluster</th>\n", | |
" <th>1st common venue</th>\n", | |
" <th>2nd common venue</th>\n", | |
" <th>3rd common venue</th>\n", | |
" <th>4th common venue</th>\n", | |
" <th>5th common venue</th>\n", | |
" <th>6th common venue</th>\n", | |
" <th>7th common venue</th>\n", | |
" <th>8th common venue</th>\n", | |
" <th>9th common venue</th>\n", | |
" <th>10th common venue</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>94</th>\n", | |
" <td>Etobicoke</td>\n", | |
" <td>3.0</td>\n", | |
" <td>filipino restaurant</td>\n", | |
" <td>dim sum restaurant</td>\n", | |
" <td>farmers market</td>\n", | |
" <td>falafel restaurant</td>\n", | |
" <td>event space</td>\n", | |
" <td>ethiopian restaurant</td>\n", | |
" <td>electronics store</td>\n", | |
" <td>eastern european restaurant</td>\n", | |
" <td>dumpling restaurant</td>\n", | |
" <td>drugstore</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Borough Cluster 1st common venue 2nd common venue \\\n", | |
"94 Etobicoke 3.0 filipino restaurant dim sum restaurant \n", | |
"\n", | |
" 3rd common venue 4th common venue 5th common venue \\\n", | |
"94 farmers market falafel restaurant event space \n", | |
"\n", | |
" 6th common venue 7th common venue 8th common venue \\\n", | |
"94 ethiopian restaurant electronics store eastern european restaurant \n", | |
"\n", | |
" 9th common venue 10th common venue \n", | |
"94 dumpling restaurant drugstore " | |
] | |
}, | |
"execution_count": 218, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"get_cluster(3)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Cluster 4: playground" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 217, | |
"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>Cluster</th>\n", | |
" <th>1st common venue</th>\n", | |
" <th>2nd common venue</th>\n", | |
" <th>3rd common venue</th>\n", | |
" <th>4th common venue</th>\n", | |
" <th>5th common venue</th>\n", | |
" <th>6th common venue</th>\n", | |
" <th>7th common venue</th>\n", | |
" <th>8th common venue</th>\n", | |
" <th>9th common venue</th>\n", | |
" <th>10th common venue</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>5</th>\n", | |
" <td>Scarborough</td>\n", | |
" <td>4.0</td>\n", | |
" <td>playground</td>\n", | |
" <td>yoga studio</td>\n", | |
" <td>dumpling restaurant</td>\n", | |
" <td>discount store</td>\n", | |
" <td>distribution center</td>\n", | |
" <td>dog run</td>\n", | |
" <td>doner restaurant</td>\n", | |
" <td>donut shop</td>\n", | |
" <td>drugstore</td>\n", | |
" <td>eastern european restaurant</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Borough Cluster 1st common venue 2nd common venue \\\n", | |
"5 Scarborough 4.0 playground yoga studio \n", | |
"\n", | |
" 3rd common venue 4th common venue 5th common venue 6th common venue \\\n", | |
"5 dumpling restaurant discount store distribution center dog run \n", | |
"\n", | |
" 7th common venue 8th common venue 9th common venue \\\n", | |
"5 doner restaurant donut shop drugstore \n", | |
"\n", | |
" 10th common venue \n", | |
"5 eastern european restaurant " | |
] | |
}, | |
"execution_count": 217, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"get_cluster(4)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "ibm_data_science", | |
"language": "python", | |
"name": "ibm_data_science" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.8.3" | |
}, | |
"toc-autonumbering": true | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 4 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment