Skip to content

Instantly share code, notes, and snippets.

@PatrickRWright
Created June 27, 2019 15:37
Show Gist options
  • Save PatrickRWright/4e909feae4098cbd266773be05ac760d to your computer and use it in GitHub Desktop.
Save PatrickRWright/4e909feae4098cbd266773be05ac760d to your computer and use it in GitHub Desktop.
Created on Cognitive Class Labs
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Capstone final"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### A description of the problem and a discussion of the background. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You are living in one of the 80 biggest German cities. You love your city but because you are looking for a professional change in your life you may have to relocate. Now you will rank the top 80 cities based similarity to your current city to make an informed decision."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Your city is: Frankfurt am Main"
]
},
{
"cell_type": "code",
"execution_count": 145,
"metadata": {},
"outputs": [],
"source": [
"yourCity = \"Frankfurt am Main\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### A description of the data and how it will be used to solve the problem."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The list of the biggest German cities can be retrieved from Wikipedia: https://de.wikipedia.org/wiki/Liste_der_Gro%C3%9Fst%C3%A4dte_in_Deutschland \n",
"The table on the Wikipedia page already contains the key variables that define a city. These are total population, population density, population change and federal region. Using foursquare this dataset will be extended to count the cafes in the city centers because you love cafes."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Methods"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"import python libraries"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"# libs\n",
"import pandas as pd\n",
"from pandas.io.json import json_normalize # tranform JSON file into a pandas dataframe\n",
"import json # library to handle JSON files\n",
"import folium # map rendering library\n",
"from sklearn.preprocessing import MinMaxScaler\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from geopy.geocoders import Nominatim # convert an address into latitude and longitude values\n",
"import requests # library to handle requests\n",
"import re"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"define useful functions"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"# functions\n",
"\n",
"# examples\n",
"# LonLatFinder(\"Berlin\")\n",
"# LonLatFinder(\"München\")\n",
"def LonLatFinder(address):\n",
" geolocator = Nominatim(user_agent=\"explorer\")\n",
" location = geolocator.geocode(address)\n",
" latitude = location.latitude\n",
" longitude = location.longitude\n",
" return([longitude, latitude])\n",
"\n",
"# get the category name from\n",
"# a foursquare query json\n",
"# returns a list\n",
"def CategoryName(json):\n",
" venueTypes = []\n",
" for ven in json['response']['venues']:\n",
" try:\n",
" #print(ven['categories'][0]['name'])\n",
" venueTypes.append(ven['categories'][0]['name'])\n",
" except:\n",
" pass\n",
" return(venueTypes)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"set foursquare parameters (I will not publicly show my ID and SECRET)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# foursquare setup\n",
"CLIENTID = \"\"\n",
"CLIENTSECRET = \"\"\n",
"VERSION = '20180605' # Foursquare API version\n",
"LIMIT = 1000\n",
"radius = 500"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"get table from wikipedia"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--2019-06-27 11:40:09-- https://en.wikipedia.org/wiki/List_of_cities_in_Germany_by_population\n",
"Resolving en.wikipedia.org (en.wikipedia.org)... 208.80.154.224, 2620:0:861:ed1a::1\n",
"Connecting to en.wikipedia.org (en.wikipedia.org)|208.80.154.224|:443... connected.\n",
"HTTP request sent, awaiting response... 200 OK\n",
"Length: 249657 (244K) [text/html]\n",
"Saving to: ‘List_of_cities_in_Germany_by_population.2’\n",
"\n",
"List_of_cities_in_G 100%[===================>] 243.81K --.-KB/s in 0.08s \n",
"\n",
"2019-06-27 11:40:09 (2.86 MB/s) - ‘List_of_cities_in_Germany_by_population.2’ saved [249657/249657]\n",
"\n",
"--2019-06-27 11:40:09-- https://de.wikipedia.org/wiki/Liste_der_Gro%C3%9Fst%C3%A4dte_in_Deutschland\n",
"Resolving de.wikipedia.org (de.wikipedia.org)... 208.80.154.224, 2620:0:861:ed1a::1\n",
"Connecting to de.wikipedia.org (de.wikipedia.org)|208.80.154.224|:443... connected.\n",
"HTTP request sent, awaiting response... 200 OK\n",
"Length: 245283 (240K) [text/html]\n",
"Saving to: ‘Liste_der_Großstädte_in_Deutschland’\n",
"\n",
"Liste_der_Großstädt 100%[===================>] 239.53K --.-KB/s in 0.08s \n",
"\n",
"2019-06-27 11:40:10 (2.93 MB/s) - ‘Liste_der_Großstädte_in_Deutschland’ saved [245283/245283]\n",
"\n"
]
}
],
"source": [
"# external data\n",
"!wget https://de.wikipedia.org/wiki/Liste_der_Gro%C3%9Fst%C3%A4dte_in_Deutschland"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"prepare dataframe for analysis"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Berlin\n",
"Hamburg\n",
"München\n",
"Köln\n",
"Frankfurt am Main\n",
"Stuttgart\n",
"Düsseldorf\n",
"Dortmund\n",
"Essen\n",
"Leipzig\n",
"Bremen\n",
"Dresden\n",
"Hannover\n",
"Nürnberg\n",
"Duisburg\n",
"Bochum\n",
"Wuppertal\n",
"Bielefeld\n",
"Bonn\n",
"Münster\n",
"Karlsruhe\n",
"Mannheim\n",
"Augsburg\n",
"Wiesbaden\n",
"Mönchengladbach \n",
"Gelsenkirchen\n",
"Braunschweig\n",
"Kiel\n",
"Chemnitz\n",
"Aachen\n",
"Halle (Saale)\n",
"Magdeburg\n",
"Freiburg im Breisgau\n",
"Krefeld\n",
"Lübeck\n",
"Mainz\n",
"Erfurt\n",
"Oberhausen\n",
"Rostock\n",
"Kassel\n",
"Hagen\n",
"Saarbrücken\n",
"Hamm\n",
"Potsdam\n",
"Mülheim an der Ruhr\n",
"Ludwigshafen am Rhein\n",
"Oldenburg (Oldb)\n",
"Osnabrück\n",
"Leverkusen\n",
"Heidelberg\n",
"Solingen\n",
"Darmstadt\n",
"Herne\n",
"Neuss\n",
"Regensburg\n",
"Paderborn\n",
"Ingolstadt\n",
"Offenbach am Main\n",
"Würzburg\n",
"Fürth\n",
"Ulm\n",
"Heilbronn\n",
"Pforzheim\n",
"Wolfsburg\n",
"Göttingen\n",
"Bottrop\n",
"Reutlingen\n",
"Koblenz\n",
"Recklinghausen\n",
"Bremerhaven \n",
"Bergisch Gladbach\n",
"Jena\n",
"Erlangen\n",
"Remscheid\n",
"Trier\n",
"Salzgitter \n",
"Moers\n",
"Siegen\n",
"Hildesheim\n",
"Cottbus\n"
]
}
],
"source": [
"# get data from wikipedia\n",
"X = 80\n",
"cities = pd.read_html(\"Liste_der_Großstädte_in_Deutschland\")[0]\n",
"topX = cities.head(X)\n",
"\n",
"# build pandas df\n",
"cities_data = {'name': topX['Name']['Name'],\n",
" 'totalPop2017': topX['Einwohnerzahl']['2017'], \n",
" 'area': topX['Flächein km²(2016)']['Flächein km²(2016)'],\n",
" 'popPerArea': topX['Ew./km²(2016)']['Ew./km²(2016)'],\n",
" 'popChange': topX['Be­völ­ke­rungs­ent­wick­lung [%] (2017 ggü. 2016)']['Be­völ­ke­rungs­ent­wick­lung [%] (2017 ggü. 2016)'],\n",
" 'province': topX['Bun­des­land']['Bun­des­land']}\n",
"cities_df = pd.DataFrame(data=cities_data)\n",
"\n",
"# data curation\n",
"for x in cities_df['popChange']:\n",
" x = int(x)/100\n",
"cities_df['name'] = cities_df['name'].str.replace('\\d', '').str.replace(',', '').str.replace('­', '')\n",
"cities_df['popChange'] = cities_df['popChange'].apply(int)/100\n",
"cities_df['totalPop2017'] = cities_df['totalPop2017'].str.replace('\\.', '').apply(int)\n",
"cities_df['area'] = cities_df['area'].apply(int)\n",
"cities_df['popPerArea'] = cities_df['popPerArea'].str.replace('\\.', '').apply(int)\n",
"\n",
"# add cafe count using foursquare\n",
"cafe_count_all = []\n",
"for city in cities_df[\"name\"].iteritems():\n",
" CurrCity = city[1]\n",
" #print(CurrCity)\n",
" LonLatCurrCity = LonLatFinder(CurrCity)\n",
" lng = LonLatCurrCity[0]\n",
" lat = LonLatCurrCity[1]\n",
" url = 'https://api.foursquare.com/v2/venues/search?client_id={}&client_secret={}&ll={},{}&v={}&radius={}&limit={}'.format(CLIENTID, \n",
" CLIENTSECRET, \n",
" lat, \n",
" lng, \n",
" VERSION, \n",
" radius, \n",
" LIMIT)\n",
" results = requests.get(url).json()\n",
" catNames = CategoryName(results)\n",
" cafe_count = catNames.count('Café')\n",
" cafe_count_all.append(cafe_count)\n",
"\n",
"# add to cities_df \n",
"cities_df['cafeCount'] = cafe_count_all"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"prevent overweighting of bigger numbers"
]
},
{
"cell_type": "code",
"execution_count": 130,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/jupyterlab/conda/lib/python3.6/site-packages/sklearn/preprocessing/data.py:323: DataConversionWarning: Data with input dtype int64, float64 were all converted to float64 by MinMaxScaler.\n",
" return self.partial_fit(X, y)\n"
]
}
],
"source": [
"# Normalize totalPop2017, area, popPerArea, popChange, cafeCount with MinMaxScaler\n",
"# to prevent overweighting of bigger numbers\n",
"\n",
"scaler = MinMaxScaler()\n",
"df_scaled = cities_df[['totalPop2017', \"area\", \"popPerArea\", \"popChange\", \"cafeCount\"]]\n",
"df_scaled = pd.DataFrame(scaler.fit_transform(df_scaled), columns=df_scaled.columns)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"calculate the euclidean distance"
]
},
{
"cell_type": "code",
"execution_count": 147,
"metadata": {},
"outputs": [],
"source": [
"# calculate euclidean distance to Frankfurt\n",
"yourCityIdx = np.where(cities_df['name'] == yourCity)[0][0]\n",
"yourCityLine = df_scaled.iloc[[yourCityIdx]].values\n",
"\n",
"allDists = []\n",
"for row in df_scaled.iterrows():\n",
" #print(row[1].values)\n",
" #print(frankfurtLine)\n",
" eucDist = np.linalg.norm(row[1].values - yourCityLine)\n",
" # exception for 0 distance because this is the town itself\n",
" if eucDist == 0:\n",
" eucDist = 10\n",
" allDists.append(eucDist)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"find minimum distance to your town"
]
},
{
"cell_type": "code",
"execution_count": 151,
"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>name</th>\n",
" <th>totalPop2017</th>\n",
" <th>area</th>\n",
" <th>popPerArea</th>\n",
" <th>popChange</th>\n",
" <th>province</th>\n",
" <th>cafeCount</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>57</th>\n",
" <td>Offenbach am Main</td>\n",
" <td>126658</td>\n",
" <td>4489</td>\n",
" <td>2775</td>\n",
" <td>1.66</td>\n",
" <td>Hessen</td>\n",
" <td>9</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" name totalPop2017 area popPerArea popChange province \\\n",
"57 Offenbach am Main 126658 4489 2775 1.66 Hessen \n",
"\n",
" cafeCount \n",
"57 9 "
]
},
"execution_count": 151,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cities_df.iloc[[np.where(min(allDists) == allDists)[0][0]]]"
]
},
{
"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>name</th>\n",
" <th>totalPop2017</th>\n",
" <th>area</th>\n",
" <th>popPerArea</th>\n",
" <th>popChange</th>\n",
" <th>province</th>\n",
" <th>cafeCount</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Frankfurt am Main</td>\n",
" <td>746878</td>\n",
" <td>24831</td>\n",
" <td>2966</td>\n",
" <td>1.42</td>\n",
" <td>Hessen</td>\n",
" <td>10</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" name totalPop2017 area popPerArea popChange province \\\n",
"4 Frankfurt am Main 746878 24831 2966 1.42 Hessen \n",
"\n",
" cafeCount \n",
"4 10 "
]
},
"execution_count": 149,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cities_df.iloc[[np.where(cities_df[\"name\"] == yourCity)[0][0]]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"folium map of germany"
]
},
{
"cell_type": "code",
"execution_count": 154,
"metadata": {},
"outputs": [],
"source": [
"LonLat = LonLatFinder(\"Germany\")\n",
"longitude = LonLat[0]\n",
"latitude = LonLat[1]\n",
"TheMap = folium.Map(location=[latitude, longitude], zoom_start=6)\n",
"\n",
"MaxSize = max(cities_df[\"totalPop2017\"])\n",
"\n",
"lats = []\n",
"lons = []\n",
"\n",
"# loop the cities and show on folium map\n",
"for line in cities_df[[\"name\", \"totalPop2017\"]].iterrows():\n",
" CurrCity = line[1][\"name\"]\n",
" CurrSize = line[1][\"totalPop2017\"]\n",
" #print(CurrCity)\n",
" LonLatCurrCity = LonLatFinder(CurrCity)\n",
" lng = LonLatCurrCity[0]\n",
" lat = LonLatCurrCity[1]\n",
" lons.append(lng)\n",
" lats.append(lat)\n",
" label = '{}, Inhabitants (2017) {}'.format(CurrCity, CurrSize)\n",
" label = folium.Popup(label, parse_html=True)\n",
" if CurrSize > 500000:\n",
" CurrCol = 'red'\n",
" else:\n",
" CurrCol = 'blue'\n",
" folium.CircleMarker(\n",
" [lat, lng],\n",
" radius=(CurrSize/MaxSize)*15,\n",
" popup=label,\n",
" color=CurrCol,\n",
" fill=True,\n",
" fill_color='#3186cc',\n",
" fill_opacity=0.7,\n",
" parse_html=False).add_to(TheMap)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"find density center with a 2D histogram"
]
},
{
"cell_type": "code",
"execution_count": 155,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"51.159399300000004\n",
"6.9090488699999995\n"
]
}
],
"source": [
"# add densest center\n",
"# x are lats, y are lons\n",
"hist, x, y = np.histogram2d(lats, lons)\n",
"max_loc_hist = np.unravel_index(hist.argmax(), hist.shape)\n",
"lat_densest = x[max_loc_hist[0]]\n",
"lon_densest = y[max_loc_hist[1]]\n",
"\n",
"folium.CircleMarker(\n",
" [lat_densest, lon_densest],\n",
" radius=45,\n",
" #popup=label,\n",
" color=\"yellow\",\n",
" fill=True,\n",
" fill_color='yellow',\n",
" fill_opacity=0.7,\n",
" parse_html=False).add_to(TheMap)\n",
"\n",
"print(lat_densest)\n",
"print(lon_densest)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Results "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The map of Germany and where the cities are located. The circle size is proportionate to the population and cities with more than 500.000 inhabitants are indicated in red. The area with the highest city density is circled in yellow. It is called the Ruhrgebiet. While we see that e.g. Berlin, Munich and Hamburg are all bigger than the individual cities in the Ruhrgebiet, the Ruhrgebiet as a metropolitan area is the most densely populated area in Germany."
]
},
{
"cell_type": "code",
"execution_count": 156,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVMgPSBmYWxzZTsgTF9OT19UT1VDSCA9IGZhbHNlOyBMX0RJU0FCTEVfM0QgPSBmYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdnaXQuY29tL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9tYXN0ZXIvZm9saXVtL3RlbXBsYXRlcy9sZWFmbGV0LmF3ZXNvbWUucm90YXRlLmNzcyIvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogMTAwLjAlOwogICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgICAgICAgICAgdG9wOiAwLjAlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICA8L3N0eWxlPgogICAgICAgIAo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgICAgICAgICA8ZGl2IGNsYXNzPSJmb2xpdW0tbWFwIiBpZD0ibWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiIiA+PC9kaXY+CiAgICAgICAgCjwvYm9keT4KPHNjcmlwdD4gICAgCiAgICAKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGJvdW5kcyA9IG51bGw7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgdmFyIG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYiA9IEwubWFwKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ21hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYicsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7Y2VudGVyOiBbNTEuMDgzNDE5NiwxMC40MjM0NDY5XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHpvb206IDYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhCb3VuZHM6IGJvdW5kcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxheWVyczogW10sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JsZENvcHlKdW1wOiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyczogTC5DUlMuRVBTRzM4NTcKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciB0aWxlX2xheWVyXzg4NTVjMjMzNzUxMzQ0NGY4MWYwNDY5M2ZlYThiZmM3ID0gTC50aWxlTGF5ZXIoCiAgICAgICAgICAgICAgICAnaHR0cHM6Ly97c30udGlsZS5vcGVuc3RyZWV0bWFwLm9yZy97en0ve3h9L3t5fS5wbmcnLAogICAgICAgICAgICAgICAgewogICJhdHRyaWJ1dGlvbiI6IG51bGwsCiAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICJtYXhab29tIjogMTgsCiAgIm1pblpvb20iOiAxLAogICJub1dyYXAiOiBmYWxzZSwKICAic3ViZG9tYWlucyI6ICJhYmMiCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iMjAxMWFjYTNlMWE0NDZmYjQ1ZjllOGUwMmNlNzU2ZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUyLjUxNzAzNjUsMTMuMzg4ODU5OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJyZWQiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxNS4wLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2E1Yzc1ZTlmNjM5ZDQ2MWJhYmM1ZGQzMjliNmY3MzM0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzc2ODJkYjNkNmQwNDQ0NGY4Yzk1YmViYmRkODJlMTRkID0gJCgnPGRpdiBpZD0iaHRtbF83NjgyZGIzZDZkMDQ0NDRmOGM5NWJlYmJkZDgyZTE0ZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmVybGluLCBJbmhhYml0YW50cyAoMjAxNykgMzYxMzQ5NTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYTVjNzVlOWY2MzlkNDYxYmFiYzVkZDMyOWI2ZjczMzQuc2V0Q29udGVudChodG1sXzc2ODJkYjNkNmQwNDQ0NGY4Yzk1YmViYmRkODJlMTRkKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2IyMDExYWNhM2UxYTQ0NmZiNDVmOWU4ZTAyY2U3NTZlLmJpbmRQb3B1cChwb3B1cF9hNWM3NWU5ZjYzOWQ0NjFiYWJjNWRkMzI5YjZmNzMzNCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl85ZDczNWVjN2Q0M2Q0MzM3YmRkZGVmZTJmZGZlMWIzMyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUzLjU1MDM0MSwxMC4wMDA2NTRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAicmVkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNy41OTg5NDc4MzMwNTM1OTUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMGYwMDc1MDUxOTQ3NDg1OTkxYjYwZGRlYmUyMmNiN2IgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZTQ1MzQ4MTc0Mjc3NGY4YmIwYTE0Yzc0YjIxZDY5YTYgPSAkKCc8ZGl2IGlkPSJodG1sX2U0NTM0ODE3NDI3NzRmOGJiMGExNGM3NGIyMWQ2OWE2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IYW1idXJnLCBJbmhhYml0YW50cyAoMjAxNykgMTgzMDU4NDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMGYwMDc1MDUxOTQ3NDg1OTkxYjYwZGRlYmUyMmNiN2Iuc2V0Q29udGVudChodG1sX2U0NTM0ODE3NDI3NzRmOGJiMGExNGM3NGIyMWQ2OWE2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzlkNzM1ZWM3ZDQzZDQzMzdiZGRkZWZlMmZkZmUxYjMzLmJpbmRQb3B1cChwb3B1cF8wZjAwNzUwNTE5NDc0ODU5OTFiNjBkZGViZTIyY2I3Yik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84OWE1ODkyYTAyMDg0MWRmOTdkNjJhMzBjNWY1MzIwMyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ4LjEzNzEwNzksMTEuNTc1MzgyMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJyZWQiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA2LjA0NDE3MTkxNjY2MjQwMSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yNzg3YjJmNWU4NDU0OTIyODE1MDc3ZDgwZTAxMWY4OCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xZDc3NzNmNTdjMTM0YWRkYTc2MzEyYTQ4MzJmZDkwNiA9ICQoJzxkaXYgaWQ9Imh0bWxfMWQ3NzczZjU3YzEzNGFkZGE3NjMxMmE0ODMyZmQ5MDYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk3DvG5jaGVuLCBJbmhhYml0YW50cyAoMjAxNykgMTQ1NjAzOTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjc4N2IyZjVlODQ1NDkyMjgxNTA3N2Q4MGUwMTFmODguc2V0Q29udGVudChodG1sXzFkNzc3M2Y1N2MxMzRhZGRhNzYzMTJhNDgzMmZkOTA2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzg5YTU4OTJhMDIwODQxZGY5N2Q2MmEzMGM1ZjUzMjAzLmJpbmRQb3B1cChwb3B1cF8yNzg3YjJmNWU4NDU0OTIyODE1MDc3ZDgwZTAxMWY4OCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84MmFlMWZmNTQ2NGU0MTQ5YTQ4NGU5MWIyNzljN2JkMyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUwLjkzODM2MSw2Ljk1OTk3NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJyZWQiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA0LjQ4NDgyOTc4MzkwNzI3LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2FmODgwM2MyNzNhNzRkNjRhZWNlZTI1YzllMDk0N2QxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzFkNmQ0OTE2ZDdhMTQ0MTg5ZDhhN2IwM2FjNmQ3ZjI4ID0gJCgnPGRpdiBpZD0iaHRtbF8xZDZkNDkxNmQ3YTE0NDE4OWQ4YTdiMDNhYzZkN2YyOCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+S8O2bG4sIEluaGFiaXRhbnRzICgyMDE3KSAxMDgwMzk0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hZjg4MDNjMjczYTc0ZDY0YWVjZWUyNWM5ZTA5NDdkMS5zZXRDb250ZW50KGh0bWxfMWQ2ZDQ5MTZkN2ExNDQxODlkOGE3YjAzYWM2ZDdmMjgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODJhZTFmZjU0NjRlNDE0OWE0ODRlOTFiMjc5YzdiZDMuYmluZFBvcHVwKHBvcHVwX2FmODgwM2MyNzNhNzRkNjRhZWNlZTI1YzllMDk0N2QxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzU2N2JiNGVhZjBjNjRjYTc5NzZjOTM2MWQ1ODVjOTA2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTAuMTEwNjQ0NCw4LjY4MjA5MTddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAicmVkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMy4xMDAzNjk1ODY3ODUwOTMsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMWQ3ZjkwODM1OTI4NDMxOTljYTQ0NGIzYjZjMGRjODggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOWMxNDExOWY1YjdhNGNkNmI5NTRkNzJmYjkzYmQzMjggPSAkKCc8ZGl2IGlkPSJodG1sXzljMTQxMTlmNWI3YTRjZDZiOTU0ZDcyZmI5M2JkMzI4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5GcmFua2Z1cnQgYW0gTWFpbiwgSW5oYWJpdGFudHMgKDIwMTcpIDc0Njg3ODwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMWQ3ZjkwODM1OTI4NDMxOTljYTQ0NGIzYjZjMGRjODguc2V0Q29udGVudChodG1sXzljMTQxMTlmNWI3YTRjZDZiOTU0ZDcyZmI5M2JkMzI4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU2N2JiNGVhZjBjNjRjYTc5NzZjOTM2MWQ1ODVjOTA2LmJpbmRQb3B1cChwb3B1cF8xZDdmOTA4MzU5Mjg0MzE5OWNhNDQ0YjNiNmMwZGM4OCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hODdhMzc3NmUxYTY0NDhhODJlODFiNDc5ZmNlMmYzZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ4Ljc3ODQ0ODUsOS4xODAwMTMyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogInJlZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDIuNjI2NTgzMTI3OTY4OTA2LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzBmNjE2YTM5ZWM0MzRkYjFiODhjYTRmOWE4NzkwNzM0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzBiNjIwNmUxZjE5YjQ5ZWM5NzU1ZTVkMWM3OTA2NTZhID0gJCgnPGRpdiBpZD0iaHRtbF8wYjYyMDZlMWYxOWI0OWVjOTc1NWU1ZDFjNzkwNjU2YSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U3R1dHRnYXJ0LCBJbmhhYml0YW50cyAoMjAxNykgNjMyNzQzPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wZjYxNmEzOWVjNDM0ZGIxYjg4Y2E0ZjlhODc5MDczNC5zZXRDb250ZW50KGh0bWxfMGI2MjA2ZTFmMTliNDllYzk3NTVlNWQxYzc5MDY1NmEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYTg3YTM3NzZlMWE2NDQ4YTgyZTgxYjQ3OWZjZTJmM2QuYmluZFBvcHVwKHBvcHVwXzBmNjE2YTM5ZWM0MzRkYjFiODhjYTRmOWE4NzkwNzM0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzE1NTEzYzFjNDU3OTQwNTBiNmVjNjAwZjljMTIwODZlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTEuMjI1NDAxOCw2Ljc3NjMxMzddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAicmVkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMi41NjIzOTQ1NzkyMDkzMjUyLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzM0NzM5MTc1ZTEzMzQwYjNhN2I3NDAwZTU1ZGY5MzVmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzJkMzMxMmQ3NTk2OTQwMzZhNzgyZmZjYjk1ZjFjYTc5ID0gJCgnPGRpdiBpZD0iaHRtbF8yZDMzMTJkNzU5Njk0MDM2YTc4MmZmY2I5NWYxY2E3OSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RMO8c3NlbGRvcmYsIEluaGFiaXRhbnRzICgyMDE3KSA2MTcyODA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzM0NzM5MTc1ZTEzMzQwYjNhN2I3NDAwZTU1ZGY5MzVmLnNldENvbnRlbnQoaHRtbF8yZDMzMTJkNzU5Njk0MDM2YTc4MmZmY2I5NWYxY2E3OSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xNTUxM2MxYzQ1Nzk0MDUwYjZlYzYwMGY5YzEyMDg2ZS5iaW5kUG9wdXAocG9wdXBfMzQ3MzkxNzVlMTMzNDBiM2E3Yjc0MDBlNTVkZjkzNWYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODRhMTI2ZTk1MzkwNDk5OGJkYTE1MzkwOWY3Zjk1ZTAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs1MS41MTQyMjczLDcuNDY1Mjc4OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJyZWQiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAyLjQzNTAzODY1MzcxMzM3MiwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81MDk1OGU0MTNkZjI0OWZlOWMxMzYyZDdhNzZiNTViNiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lYmYzM2JjNDAxMTk0NWNiYjQ2Y2Q4MGZmMTFmMTMzYSA9ICQoJzxkaXYgaWQ9Imh0bWxfZWJmMzNiYzQwMTE5NDVjYmI0NmNkODBmZjExZjEzM2EiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvcnRtdW5kLCBJbmhhYml0YW50cyAoMjAxNykgNTg2NjAwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81MDk1OGU0MTNkZjI0OWZlOWMxMzYyZDdhNzZiNTViNi5zZXRDb250ZW50KGh0bWxfZWJmMzNiYzQwMTE5NDVjYmI0NmNkODBmZjExZjEzM2EpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODRhMTI2ZTk1MzkwNDk5OGJkYTE1MzkwOWY3Zjk1ZTAuYmluZFBvcHVwKHBvcHVwXzUwOTU4ZTQxM2RmMjQ5ZmU5YzEzNjJkN2E3NmI1NWI2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2M2Y2I5MTA2MWVkYzQzMjJiYjYzMjczMzYzM2VmN2Y2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTEuNDU3MDg3LDcuMDExNDI5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogInJlZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDIuNDIxNzI2MDU3NDU5NjA2LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2JiOWJjYzZiMWJkNzRlYTNiZGY3OTcxZDBhZTA1MWM0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzYyMzZmZTZhM2E3YzQxMzU5MzA4ZjdjMWU3MjU2YmI3ID0gJCgnPGRpdiBpZD0iaHRtbF82MjM2ZmU2YTNhN2M0MTM1OTMwOGY3YzFlNzI1NmJiNyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RXNzZW4sIEluaGFiaXRhbnRzICgyMDE3KSA1ODMzOTM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2JiOWJjYzZiMWJkNzRlYTNiZGY3OTcxZDBhZTA1MWM0LnNldENvbnRlbnQoaHRtbF82MjM2ZmU2YTNhN2M0MTM1OTMwOGY3YzFlNzI1NmJiNyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jNmNiOTEwNjFlZGM0MzIyYmI2MzI3MzM2MzNlZjdmNi5iaW5kUG9wdXAocG9wdXBfYmI5YmNjNmIxYmQ3NGVhM2JkZjc5NzFkMGFlMDUxYzQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTc3YmQwMzNiYWU2NDI4NWJkY2ZiMDNmZTFlNGZiYzUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs1MS4zNDA2MzIxLDEyLjM3NDczMjldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAicmVkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMi40MTU4NjA1NDQ5ODQ4NDE2LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzQ0NzUxMGQxNjczYTQ0ZTk5ZGJjNDlhYjJkNWJlYWMyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzE5YjIyZWZhMTIwOTRjOTM5MjY0MDk4MWViZDI5MmFiID0gJCgnPGRpdiBpZD0iaHRtbF8xOWIyMmVmYTEyMDk0YzkzOTI2NDA5ODFlYmQyOTJhYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TGVpcHppZywgSW5oYWJpdGFudHMgKDIwMTcpIDU4MTk4MDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNDQ3NTEwZDE2NzNhNDRlOTlkYmM0OWFiMmQ1YmVhYzIuc2V0Q29udGVudChodG1sXzE5YjIyZWZhMTIwOTRjOTM5MjY0MDk4MWViZDI5MmFiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU3N2JkMDMzYmFlNjQyODViZGNmYjAzZmUxZTRmYmM1LmJpbmRQb3B1cChwb3B1cF80NDc1MTBkMTY3M2E0NGU5OWRiYzQ5YWIyZDViZWFjMik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81YzlhNmYzMzdiOWE0NGY4YTllZjBkNDE4OGU1M2RlNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUzLjA3NTgxOTYsOC44MDcxNjQ2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogInJlZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDIuMzU3ODUyOTkyNzM5NzE2LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzA5MDRjNmI2NjRlNjQyMmY4ZGM5NmQ1YzQyYjMwZjUyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2UzMDM4MWViZTMyMTQxNjFhMzA1MDRkZDhkNmFiNDIwID0gJCgnPGRpdiBpZD0iaHRtbF9lMzAzODFlYmUzMjE0MTYxYTMwNTA0ZGQ4ZDZhYjQyMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnJlbWVuLCBJbmhhYml0YW50cyAoMjAxNykgNTY4MDA2PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wOTA0YzZiNjY0ZTY0MjJmOGRjOTZkNWM0MmIzMGY1Mi5zZXRDb250ZW50KGh0bWxfZTMwMzgxZWJlMzIxNDE2MWEzMDUwNGRkOGQ2YWI0MjApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNWM5YTZmMzM3YjlhNDRmOGE5ZWYwZDQxODhlNTNkZTUuYmluZFBvcHVwKHBvcHVwXzA5MDRjNmI2NjRlNjQyMmY4ZGM5NmQ1YzQyYjMwZjUyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzAyMTA3OWUxNzNiOTQ2ZWE4ZWI2ZGU1ZGFkZWNjMGZkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTEuMDQ5MzI4NiwxMy43MzgxNDM3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogInJlZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDIuMjg3NTU4MTY3MzY5ODE3OCwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81ZjQxNzEyYTljMWM0MTE5OTA1MzNmYjYzNGJmMDk0ZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8yMmVhZGJhZTY0NzU0ZmE4YjgzZjFmZjMzY2VjODM4YSA9ICQoJzxkaXYgaWQ9Imh0bWxfMjJlYWRiYWU2NDc1NGZhOGI4M2YxZmYzM2NlYzgzOGEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRyZXNkZW4sIEluaGFiaXRhbnRzICgyMDE3KSA1NTEwNzI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzVmNDE3MTJhOWMxYzQxMTk5MDUzM2ZiNjM0YmYwOTRmLnNldENvbnRlbnQoaHRtbF8yMmVhZGJhZTY0NzU0ZmE4YjgzZjFmZjMzY2VjODM4YSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wMjEwNzllMTczYjk0NmVhOGViNmRlNWRhZGVjYzBmZC5iaW5kUG9wdXAocG9wdXBfNWY0MTcxMmE5YzFjNDExOTkwNTMzZmI2MzRiZjA5NGYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODgwNTU0NzBmMWUyNDA4OTllOGQwYWVjMzVkODA2NTQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs1Mi4zNzQ0Nzc5LDkuNzM4NTUzMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJyZWQiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAyLjIyMTA5NDgxMjYzOTg0LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2VhYTAyMDg2NDc3NTQ3ZjI5N2YwMzE4OGZkNGRmZTVmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzUyNGVkMTRhNDhlNzRkM2ZiZjBmZTQ3YWNkMTQyNTI1ID0gJCgnPGRpdiBpZD0iaHRtbF81MjRlZDE0YTQ4ZTc0ZDNmYmYwZmU0N2FjZDE0MjUyNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SGFubm92ZXIsIEluaGFiaXRhbnRzICgyMDE3KSA1MzUwNjE8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2VhYTAyMDg2NDc3NTQ3ZjI5N2YwMzE4OGZkNGRmZTVmLnNldENvbnRlbnQoaHRtbF81MjRlZDE0YTQ4ZTc0ZDNmYmYwZmU0N2FjZDE0MjUyNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84ODA1NTQ3MGYxZTI0MDg5OWU4ZDBhZWMzNWQ4MDY1NC5iaW5kUG9wdXAocG9wdXBfZWFhMDIwODY0Nzc1NDdmMjk3ZjAzMTg4ZmQ0ZGZlNWYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZDdmOThmNmEyMWU4NGI4NjhhNjMwYWVlMjlkZGNlYjQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OS40NTM4NzIsMTEuMDc3Mjk4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogInJlZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDIuMTM4NjUzODUxNzQxODczLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzdmMzc1YjgyYjY4ZTQ4ODNhZmNiMDA2ZGVjNzMyYzI0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2Y1YjU3MTE4ZGU5MjRkNDY4NzE4ZDE5ZTgxNjQ5ODU1ID0gJCgnPGRpdiBpZD0iaHRtbF9mNWI1NzExOGRlOTI0ZDQ2ODcxOGQxOWU4MTY0OTg1NSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TsO8cm5iZXJnLCBJbmhhYml0YW50cyAoMjAxNykgNTE1MjAxPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83ZjM3NWI4MmI2OGU0ODgzYWZjYjAwNmRlYzczMmMyNC5zZXRDb250ZW50KGh0bWxfZjViNTcxMThkZTkyNGQ0Njg3MThkMTllODE2NDk4NTUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZDdmOThmNmEyMWU4NGI4NjhhNjMwYWVlMjlkZGNlYjQuYmluZFBvcHVwKHBvcHVwXzdmMzc1YjgyYjY4ZTQ4ODNhZmNiMDA2ZGVjNzMyYzI0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2RjOTkxYzc0N2FiMzQ1ZGFhZTM2ODFiOGVkZGY5ZmNiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTEuNDM0OTk5LDYuNzU5NTYyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAyLjA2NzcwNzMwMjc2MzY2OCwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84ZTkzZjA1YWE2YWY0MWVjOTM3MWUxY2M4NmRhMDc1YiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lOWQ4NjZlOTg1ZWU0MjM0ODI4MzFhNmNhNzEyYjIyMCA9ICQoJzxkaXYgaWQ9Imh0bWxfZTlkODY2ZTk4NWVlNDIzNDgyODMxYTZjYTcxMmIyMjAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkR1aXNidXJnLCBJbmhhYml0YW50cyAoMjAxNykgNDk4MTEwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84ZTkzZjA1YWE2YWY0MWVjOTM3MWUxY2M4NmRhMDc1Yi5zZXRDb250ZW50KGh0bWxfZTlkODY2ZTk4NWVlNDIzNDgyODMxYTZjYTcxMmIyMjApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZGM5OTFjNzQ3YWIzNDVkYWFlMzY4MWI4ZWRkZjlmY2IuYmluZFBvcHVwKHBvcHVwXzhlOTNmMDVhYTZhZjQxZWM5MzcxZTFjYzg2ZGEwNzViKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzgyNDZiYWZkZDRkYzQ4ZjFhZDIyZGRjNjY5NGM3ZGI0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTEuNDgxODExMSw3LjIxOTY2MzVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDEuNTE3MzQ5NTQ2NjMwMDYzLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2ZkMDM0NzNkYzFhZDRmODU5YjRhMjY3ZmEwMDNmMjUxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzkxNmMyMTE5MmQxZjQ4M2FiZDkwN2RhYWNlMDAzNjI5ID0gJCgnPGRpdiBpZD0iaHRtbF85MTZjMjExOTJkMWY0ODNhYmQ5MDdkYWFjZTAwMzYyOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Qm9jaHVtLCBJbmhhYml0YW50cyAoMjAxNykgMzY1NTI5PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mZDAzNDczZGMxYWQ0Zjg1OWI0YTI2N2ZhMDAzZjI1MS5zZXRDb250ZW50KGh0bWxfOTE2YzIxMTkyZDFmNDgzYWJkOTA3ZGFhY2UwMDM2MjkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODI0NmJhZmRkNGRjNDhmMWFkMjJkZGM2Njk0YzdkYjQuYmluZFBvcHVwKHBvcHVwX2ZkMDM0NzNkYzFhZDRmODU5YjRhMjY3ZmEwMDNmMjUxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2QxMTIyZGI4M2ZlYzQzMTA4YWNhMDExMGNlZjVmZmUwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTEuMjY0MDE4LDcuMTc4MDM3NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMS40Njc3ODk0OTQ2NTgyMTg2LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzQxYTY0ODg0OTJiYTQ5Mzg4MjY5NjlmNzA1MWQ1M2RhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzM0MThkMjZhYjhiZjQwY2E4NGMyMDBiNTk5NWE2OTY3ID0gJCgnPGRpdiBpZD0iaHRtbF8zNDE4ZDI2YWI4YmY0MGNhODRjMjAwYjU5OTVhNjk2NyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V3VwcGVydGFsLCBJbmhhYml0YW50cyAoMjAxNykgMzUzNTkwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80MWE2NDg4NDkyYmE0OTM4ODI2OTY5ZjcwNTFkNTNkYS5zZXRDb250ZW50KGh0bWxfMzQxOGQyNmFiOGJmNDBjYTg0YzIwMGI1OTk1YTY5NjcpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZDExMjJkYjgzZmVjNDMxMDhhY2EwMTEwY2VmNWZmZTAuYmluZFBvcHVwKHBvcHVwXzQxYTY0ODg0OTJiYTQ5Mzg4MjY5NjlmNzA1MWQ1M2RhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzA4Mzg1ODMzNTUyYjRhY2FiMjczNTQ3MjU3YTYzZWNkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTIuMDEwODc3LDguNTQwODY4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLjM4MDQ1ODUzMTE0NTA1NDgsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYWI5NWQyMTgyYWM1NGVkNzgxMmZlNzQ5NmE0YzBhYjcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfODcxYzkwNmM1ZDVkNDRhNTkyOTU4NTI5ZjU0MjAyYjggPSAkKCc8ZGl2IGlkPSJodG1sXzg3MWM5MDZjNWQ1ZDQ0YTU5Mjk1ODUyOWY1NDIwMmI4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CaWVsZWZlbGQsIEluaGFiaXRhbnRzICgyMDE3KSAzMzI1NTI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2FiOTVkMjE4MmFjNTRlZDc4MTJmZTc0OTZhNGMwYWI3LnNldENvbnRlbnQoaHRtbF84NzFjOTA2YzVkNWQ0NGE1OTI5NTg1MjlmNTQyMDJiOCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wODM4NTgzMzU1MmI0YWNhYjI3MzU0NzI1N2E2M2VjZC5iaW5kUG9wdXAocG9wdXBfYWI5NWQyMTgyYWM1NGVkNzgxMmZlNzQ5NmE0YzBhYjcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMDM3ZDAwMmYzMmI5NDcyZWIzMzE5YjA2MThkOTM1MzIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs1MC43MzU4NTEsNy4xMDA2Nl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMS4zNTExNDM0MjIwODg1ODc0LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzI2MzJhNWZjMzgzNjQzN2Y5NzYyMTZjYmE0ZmFjYzE2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzllMjZiYjJmMmIxZTRlMTJiY2YyYzQ4ZDdkYTY4NzljID0gJCgnPGRpdiBpZD0iaHRtbF85ZTI2YmIyZjJiMWU0ZTEyYmNmMmM0OGQ3ZGE2ODc5YyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Qm9ubiwgSW5oYWJpdGFudHMgKDIwMTcpIDMyNTQ5MDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjYzMmE1ZmMzODM2NDM3Zjk3NjIxNmNiYTRmYWNjMTYuc2V0Q29udGVudChodG1sXzllMjZiYjJmMmIxZTRlMTJiY2YyYzQ4ZDdkYTY4NzljKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzAzN2QwMDJmMzJiOTQ3MmViMzMxOWIwNjE4ZDkzNTMyLmJpbmRQb3B1cChwb3B1cF8yNjMyYTVmYzM4MzY0MzdmOTc2MjE2Y2JhNGZhY2MxNik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lZmU4OWFkMjlhMjQ0MjgyOGRlZTQwYjBjY2ZiODYwMSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUxLjk1MDEzMTcsNy42MTMzMDE2NTAyNjExOV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMS4zMDE2MTY1Nzg5NjMwMjYsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZDdhZTljNTQ5NzZmNDhmN2EzMmI1NzUyMmRmMjgxN2MgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfM2JhMDJiYjRlN2E0NGExMWE2Njk1OGZjM2JjMjFkZmYgPSAkKCc8ZGl2IGlkPSJodG1sXzNiYTAyYmI0ZTdhNDRhMTFhNjY5NThmYzNiYzIxZGZmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Nw7xuc3RlciwgSW5oYWJpdGFudHMgKDIwMTcpIDMxMzU1OTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZDdhZTljNTQ5NzZmNDhmN2EzMmI1NzUyMmRmMjgxN2Muc2V0Q29udGVudChodG1sXzNiYTAyYmI0ZTdhNDRhMTFhNjY5NThmYzNiYzIxZGZmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2VmZTg5YWQyOWEyNDQyODI4ZGVlNDBiMGNjZmI4NjAxLmJpbmRQb3B1cChwb3B1cF9kN2FlOWM1NDk3NmY0OGY3YTMyYjU3NTIyZGYyODE3Yyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wNmRmODViZjk4MmI0ZDFiYjhlOTVmMjdiYjRiZGJhYyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ5LjAwNjg3MDUsOC40MDM0MTk1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLjI5NDgwODc2NTQ3NDk3NjUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjYxMmQ5ZmQwOTc5NDIyY2JjMDE2MjY5MWU4NTYxMDYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZWJkYjE2YTNiNmNiNDc2NWFlNGE0ZWQwZGMzYTA0MzAgPSAkKCc8ZGl2IGlkPSJodG1sX2ViZGIxNmEzYjZjYjQ3NjVhZTRhNGVkMGRjM2EwNDMwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5LYXJsc3J1aGUsIEluaGFiaXRhbnRzICgyMDE3KSAzMTE5MTk8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzY2MTJkOWZkMDk3OTQyMmNiYzAxNjI2OTFlODU2MTA2LnNldENvbnRlbnQoaHRtbF9lYmRiMTZhM2I2Y2I0NzY1YWU0YTRlZDBkYzNhMDQzMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wNmRmODViZjk4MmI0ZDFiYjhlOTVmMjdiYjRiZGJhYy5iaW5kUG9wdXAocG9wdXBfNjYxMmQ5ZmQwOTc5NDIyY2JjMDE2MjY5MWU4NTYxMDYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNmNmNDYxODZhMTM1NGE0NmIzNzk1MWYzZDM1YjQxZWIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OS40ODk1OTEsOC40NjcyMzZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDEuMjc4NTI4MTI4NTg0NjUyOCwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81ZjlmODViMmE3YTA0OWRhOWY2ZThjM2EyMDhmZDUzNiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83MjllYjM0Y2M4ZGM0MGIxODM3MDJiM2RiNmEzZTQwZCA9ICQoJzxkaXYgaWQ9Imh0bWxfNzI5ZWIzNGNjOGRjNDBiMTgzNzAyYjNkYjZhM2U0MGQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1hbm5oZWltLCBJbmhhYml0YW50cyAoMjAxNykgMzA3OTk3PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81ZjlmODViMmE3YTA0OWRhOWY2ZThjM2EyMDhmZDUzNi5zZXRDb250ZW50KGh0bWxfNzI5ZWIzNGNjOGRjNDBiMTgzNzAyYjNkYjZhM2U0MGQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNmNmNDYxODZhMTM1NGE0NmIzNzk1MWYzZDM1YjQxZWIuYmluZFBvcHVwKHBvcHVwXzVmOWY4NWIyYTdhMDQ5ZGE5ZjZlOGMzYTIwOGZkNTM2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzlkNTk0Y2U2MmIwOTQ2Y2I5Yzk0OWJlZWMyMmUwZDY2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguMzY2ODA0MSwxMC44OTg2OTcxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLjIxNTY1NTQ4MDM1OTA0MywKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jYTZjMzk2MGFmNjA0MTAzOTdkNzY1ZWE0ZTU1MTEzMyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iMDQzMGU4MzY3Mjg0ZjU1ODA3ZDAxNDUyYzkxNzEyNCA9ICQoJzxkaXYgaWQ9Imh0bWxfYjA0MzBlODM2NzI4NGY1NTgwN2QwMTQ1MmM5MTcxMjQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkF1Z3NidXJnLCBJbmhhYml0YW50cyAoMjAxNykgMjkyODUxPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jYTZjMzk2MGFmNjA0MTAzOTdkNzY1ZWE0ZTU1MTEzMy5zZXRDb250ZW50KGh0bWxfYjA0MzBlODM2NzI4NGY1NTgwN2QwMTQ1MmM5MTcxMjQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOWQ1OTRjZTYyYjA5NDZjYjljOTQ5YmVlYzIyZTBkNjYuYmluZFBvcHVwKHBvcHVwX2NhNmMzOTYwYWY2MDQxMDM5N2Q3NjVlYTRlNTUxMTMzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I3YzdiNzcxMWI2MjQ0YjdiZjExYzUwZjIyY2UwZTM3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTAuMDgyMDM4NCw4LjI0MTY1NTZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDEuMTU2NzIyMjMxNTIzNzc0MiwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80MDQ1ZWY2MDZhZTU0MTliYTJjOWIzNGVmODUzNWE3NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lOTM2OTdkOTJmODM0ZjkwOWZiZDY0MDhiYTljODkxMiA9ICQoJzxkaXYgaWQ9Imh0bWxfZTkzNjk3ZDkyZjgzNGY5MDlmYmQ2NDA4YmE5Yzg5MTIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldpZXNiYWRlbiwgSW5oYWJpdGFudHMgKDIwMTcpIDI3ODY1NDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNDA0NWVmNjA2YWU1NDE5YmEyYzliMzRlZjg1MzVhNzQuc2V0Q29udGVudChodG1sX2U5MzY5N2Q5MmY4MzRmOTA5ZmJkNjQwOGJhOWM4OTEyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2I3YzdiNzcxMWI2MjQ0YjdiZjExYzUwZjIyY2UwZTM3LmJpbmRQb3B1cChwb3B1cF80MDQ1ZWY2MDZhZTU0MTliYTJjOWIzNGVmODUzNWE3NCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iNDY5YzdlODJhMGY0ZjBjYjYyZjI5M2JmZGE3MDI0YSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUxLjE5NDY5ODMsNi40MzUzNjQxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLjA4ODM3MDEyMzY2MTQ0MTQsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNTVlODk2MzE0ZDczNDEyZmFkZWVjMDkxY2QxOTA5MzQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzJmOWFlZmVhN2NjNDU0Nzk3M2M4NDUzNDZlN2RhOWEgPSAkKCc8ZGl2IGlkPSJodG1sXzcyZjlhZWZlYTdjYzQ1NDc5NzNjODQ1MzQ2ZTdkYTlhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Nw7ZuY2hlbmdsYWRiYWNoICwgSW5oYWJpdGFudHMgKDIwMTcpIDI2MjE4ODwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNTVlODk2MzE0ZDczNDEyZmFkZWVjMDkxY2QxOTA5MzQuc2V0Q29udGVudChodG1sXzcyZjlhZWZlYTdjYzQ1NDc5NzNjODQ1MzQ2ZTdkYTlhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2I0NjljN2U4MmEwZjRmMGNiNjJmMjkzYmZkYTcwMjRhLmJpbmRQb3B1cChwb3B1cF81NWU4OTYzMTRkNzM0MTJmYWRlZWMwOTFjZDE5MDkzNCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wYjkyNDM2YjlmOGE0MjU0YjkyNmJhZmFmOGM3NzU2OCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUxLjUxMTAzMjEsNy4wOTYwMTI0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLjA4MDU1MzU5MTQ2NzU0MDQsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMDljNWVlZjQyODU3NGQwZjg1NTJkYjI5MThlMzU0MDggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNTBkMDM4MGZlZDE5NGMzMzhiNTZjYTgzYjkzMTIxZDQgPSAkKCc8ZGl2IGlkPSJodG1sXzUwZDAzODBmZWQxOTRjMzM4YjU2Y2E4M2I5MzEyMWQ0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5HZWxzZW5raXJjaGVuLCBJbmhhYml0YW50cyAoMjAxNykgMjYwMzA1PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wOWM1ZWVmNDI4NTc0ZDBmODU1MmRiMjkxOGUzNTQwOC5zZXRDb250ZW50KGh0bWxfNTBkMDM4MGZlZDE5NGMzMzhiNTZjYTgzYjkzMTIxZDQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMGI5MjQzNmI5ZjhhNDI1NGI5MjZiYWZhZjhjNzc1NjguYmluZFBvcHVwKHBvcHVwXzA5YzVlZWY0Mjg1NzRkMGY4NTUyZGIyOTE4ZTM1NDA4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzU3NWIzYTMwMjZiYjQzYTE5OGIyMDc1ODVlZGFmNWIwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTIuMjY0NjU3NywxMC41MjM2MDY2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLjAyOTU2OTcxMDIxMTMwNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mZTQyNGM0MTdmOTU0ZjY1YjM1YjVjOGExOWJkYWZkYSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83NGZhYWM1MTg0MWI0MGE5YTcwZTA2ZjRmMDBjOTBmMSA9ICQoJzxkaXYgaWQ9Imh0bWxfNzRmYWFjNTE4NDFiNDBhOWE3MGUwNmY0ZjAwYzkwZjEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJyYXVuc2Nod2VpZywgSW5oYWJpdGFudHMgKDIwMTcpIDI0ODAyMzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZmU0MjRjNDE3Zjk1NGY2NWIzNWI1YzhhMTliZGFmZGEuc2V0Q29udGVudChodG1sXzc0ZmFhYzUxODQxYjQwYTlhNzBlMDZmNGYwMGM5MGYxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU3NWIzYTMwMjZiYjQzYTE5OGIyMDc1ODVlZGFmNWIwLmJpbmRQb3B1cChwb3B1cF9mZTQyNGM0MTdmOTU0ZjY1YjM1YjVjOGExOWJkYWZkYSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xYzc3NjhjYTM1ZjM0NmQzYmVhNjhmYmVlZTM0NzU2NyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzU0LjMyMjcwODUsMTAuMTM1NTU1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLjAyOTIzNzYyMTc0ODQ3MzMsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjVlYjE5Nzk3YWQwNDViNTkwYjA5MTI4ZmQ1YmZlNWMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDk2NzA4MjBmNTQ3NDJlNmFkNWU2MWJiNTM0MzdlZGIgPSAkKCc8ZGl2IGlkPSJodG1sX2Q5NjcwODIwZjU0NzQyZTZhZDVlNjFiYjUzNDM3ZWRiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5LaWVsLCBJbmhhYml0YW50cyAoMjAxNykgMjQ3OTQzPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82NWViMTk3OTdhZDA0NWI1OTBiMDkxMjhmZDViZmU1Yy5zZXRDb250ZW50KGh0bWxfZDk2NzA4MjBmNTQ3NDJlNmFkNWU2MWJiNTM0MzdlZGIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMWM3NzY4Y2EzNWYzNDZkM2JlYTY4ZmJlZWUzNDc1NjcuYmluZFBvcHVwKHBvcHVwXzY1ZWIxOTc5N2FkMDQ1YjU5MGIwOTEyOGZkNWJmZTVjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzRjZGRhZmVlYWVmZTQzNzdhYjhiYmMyMjVmMDEyMjA2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTAuODMyMjYwOCwxMi45MjUyOTc3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAxLjAyNDcyMTIxODY1Mzk2MjUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYjczYzU0MTEwZWEwNGM3Y2FiM2I2MDMxMzA5MDZkZjEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNmQ3YjA1OWM3M2QzNGY1MTljNDI0NzAxYTFmNzBkZWIgPSAkKCc8ZGl2IGlkPSJodG1sXzZkN2IwNTljNzNkMzRmNTE5YzQyNDcwMWExZjcwZGViIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DaGVtbml0eiwgSW5oYWJpdGFudHMgKDIwMTcpIDI0Njg1NTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjczYzU0MTEwZWEwNGM3Y2FiM2I2MDMxMzA5MDZkZjEuc2V0Q29udGVudChodG1sXzZkN2IwNTljNzNkMzRmNTE5YzQyNDcwMWExZjcwZGViKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzRjZGRhZmVlYWVmZTQzNzdhYjhiYmMyMjVmMDEyMjA2LmJpbmRQb3B1cChwb3B1cF9iNzNjNTQxMTBlYTA0YzdjYWIzYjYwMzEzMDkwNmRmMSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yMmY1Y2ZjMDJmY2Y0NmQ4YjIyYTgzY2NmY2RmMjNhMSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUwLjc3NjM1MSw2LjA4Mzg2Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMS4wMjIzMDExMjM5ODEwNzY0LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzY0Y2JkMTJmMDZmYjRmNWU4N2FmZjEwODBkNzZjYzFhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzhiYTNkNzUzY2VmZTQ2MWY4ZjZlMzcyY2Q2ZWRhZTVjID0gJCgnPGRpdiBpZD0iaHRtbF84YmEzZDc1M2NlZmU0NjFmOGY2ZTM3MmNkNmVkYWU1YyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QWFjaGVuLCBJbmhhYml0YW50cyAoMjAxNykgMjQ2MjcyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82NGNiZDEyZjA2ZmI0ZjVlODdhZmYxMDgwZDc2Y2MxYS5zZXRDb250ZW50KGh0bWxfOGJhM2Q3NTNjZWZlNDYxZjhmNmUzNzJjZDZlZGFlNWMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjJmNWNmYzAyZmNmNDZkOGIyMmE4M2NjZmNkZjIzYTEuYmluZFBvcHVwKHBvcHVwXzY0Y2JkMTJmMDZmYjRmNWU4N2FmZjEwODBkNzZjYzFhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY3M2JkNDE0MjIxMzRkMjA5MzI1ODQzMjU3ZmM4ZmRhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTEuNDgyNTA0MSwxMS45NzA1NDUyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjk5MjgzMjQyNDAxMDU0OTMsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOWM0NTg5NjUwM2JlNDA1MmI0N2JhZWVkODM4NzRkODMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOGQwNTY5ZjQ1YWU2NGQwMWFiZjVjODJjMTBlY2UwOGYgPSAkKCc8ZGl2IGlkPSJodG1sXzhkMDU2OWY0NWFlNjRkMDFhYmY1YzgyYzEwZWNlMDhmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IYWxsZSAoU2FhbGUpLCBJbmhhYml0YW50cyAoMjAxNykgMjM5MTczPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85YzQ1ODk2NTAzYmU0MDUyYjQ3YmFlZWQ4Mzg3NGQ4My5zZXRDb250ZW50KGh0bWxfOGQwNTY5ZjQ1YWU2NGQwMWFiZjVjODJjMTBlY2UwOGYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNjczYmQ0MTQyMjEzNGQyMDkzMjU4NDMyNTdmYzhmZGEuYmluZFBvcHVwKHBvcHVwXzljNDU4OTY1MDNiZTQwNTJiNDdiYWVlZDgzODc0ZDgzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2QyNzVjMDhjOWRhYjQ0NGY5MmI5MWEyMjBjMGRkYTQwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTIuMTMxNTg4OSwxMS42Mzk5NjA5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjk4OTk0NzQwNTQ4OTY5OSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wY2I1ZTg0YmI1ZTA0ZDY0YTcyYTY5ZjczZThhZmI5OCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wMzVhMGU2Yjk2MDQ0ZGRjYmFmZWY0OTIyNWYyYTNmYyA9ICQoJzxkaXYgaWQ9Imh0bWxfMDM1YTBlNmI5NjA0NGRkY2JhZmVmNDkyMjVmMmEzZmMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1hZ2RlYnVyZywgSW5oYWJpdGFudHMgKDIwMTcpIDIzODQ3ODwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMGNiNWU4NGJiNWUwNGQ2NGE3MmE2OWY3M2U4YWZiOTguc2V0Q29udGVudChodG1sXzAzNWEwZTZiOTYwNDRkZGNiYWZlZjQ5MjI1ZjJhM2ZjKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2QyNzVjMDhjOWRhYjQ0NGY5MmI5MWEyMjBjMGRkYTQwLmJpbmRQb3B1cChwb3B1cF8wY2I1ZTg0YmI1ZTA0ZDY0YTcyYTY5ZjczZThhZmI5OCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jZDVhNTlhOGI2ZjA0Zjg1YjFkNzM5MmQ2NGM0YjU2NCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3Ljk5NjA5MDEsNy44NDk0MDA1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjk1MzI0MzMyODEzNTIyNjQsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMWVkYWY5YWUyNGNkNDlkODg4ZDFkNDFmZDJjM2Q3NTYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNGFiNzQ2OWNlM2U3NDZlNGFlMjRlZmQyNDFjYzUzMTcgPSAkKCc8ZGl2IGlkPSJodG1sXzRhYjc0NjljZTNlNzQ2ZTRhZTI0ZWZkMjQxY2M1MzE3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5GcmVpYnVyZyBpbSBCcmVpc2dhdSwgSW5oYWJpdGFudHMgKDIwMTcpIDIyOTYzNjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMWVkYWY5YWUyNGNkNDlkODg4ZDFkNDFmZDJjM2Q3NTYuc2V0Q29udGVudChodG1sXzRhYjc0NjljZTNlNzQ2ZTRhZTI0ZWZkMjQxY2M1MzE3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2NkNWE1OWE4YjZmMDRmODViMWQ3MzkyZDY0YzRiNTY0LmJpbmRQb3B1cChwb3B1cF8xZWRhZjlhZTI0Y2Q0OWQ4ODhkMWQ0MWZkMmMzZDc1Nik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iOGIwNTJlMzkzNWI0NmQ3ODMyNWRhMjcxMGMzOTAxMCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUxLjMzMzEyMDUsNi41NjIzMzQzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjk0MTA1MTUzMDQ0MzUxNzksCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMmU4ZWM4Zjc0OGVmNGI5Mzg1YjYwNzVhMWE0NzEzMzUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfY2MyZGZkNjU5YTQ3NDAwY2IwYTY0ZjMxYzAzOTk5M2UgPSAkKCc8ZGl2IGlkPSJodG1sX2NjMmRmZDY1OWE0NzQwMGNiMGE2NGYzMWMwMzk5OTNlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5LcmVmZWxkLCBJbmhhYml0YW50cyAoMjAxNykgMjI2Njk5PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yZThlYzhmNzQ4ZWY0YjkzODViNjA3NWExYTQ3MTMzNS5zZXRDb250ZW50KGh0bWxfY2MyZGZkNjU5YTQ3NDAwY2IwYTY0ZjMxYzAzOTk5M2UpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjhiMDUyZTM5MzViNDZkNzgzMjVkYTI3MTBjMzkwMTAuYmluZFBvcHVwKHBvcHVwXzJlOGVjOGY3NDhlZjRiOTM4NWI2MDc1YTFhNDcxMzM1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzkzNjY2OWNhMTBlOTQ3MGM5MTA4MTBiNDU0YzdiYjkzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTMuODY2NDQ0LDEwLjY4NDczOF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMC44OTc5NTg5MDEyODUzMjA3LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzI4MDAxYzY5MDk5ZDQwYzlhZjYyMWEyYWIyMGYyNWIyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2I5NTA2ZjEyMGUyYzQ3MDJiN2M1ZThlZDM4YTNiODk4ID0gJCgnPGRpdiBpZD0iaHRtbF9iOTUwNmYxMjBlMmM0NzAyYjdjNWU4ZWQzOGEzYjg5OCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TMO8YmVjaywgSW5oYWJpdGFudHMgKDIwMTcpIDIxNjMxODwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjgwMDFjNjkwOTlkNDBjOWFmNjIxYTJhYjIwZjI1YjIuc2V0Q29udGVudChodG1sX2I5NTA2ZjEyMGUyYzQ3MDJiN2M1ZThlZDM4YTNiODk4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzkzNjY2OWNhMTBlOTQ3MGM5MTA4MTBiNDU0YzdiYjkzLmJpbmRQb3B1cChwb3B1cF8yODAwMWM2OTA5OWQ0MGM5YWY2MjFhMmFiMjBmMjViMik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl85NmFkMjY5YjBiYjA0NzU3OTg1ODkyMTQ5OGNmZjE1ZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ5Ljk2NTQxMTE1LDguMjU3Njk0NDMxMTc3MzVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuOTAxMjc5Nzg1OTEzNjM3NywKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kOTA1NzEwODkyZjM0NmUxOTg3Yzk1YjU0ZGNjZTI2YyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85YzAyMTJjMTE1MzY0MjU5ODdmY2ZjZTBmNWM1YTMwNiA9ICQoJzxkaXYgaWQ9Imh0bWxfOWMwMjEyYzExNTM2NDI1OTg3ZmNmY2UwZjVjNWEzMDYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1haW56LCBJbmhhYml0YW50cyAoMjAxNykgMjE3MTE4PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9kOTA1NzEwODkyZjM0NmUxOTg3Yzk1YjU0ZGNjZTI2Yy5zZXRDb250ZW50KGh0bWxfOWMwMjEyYzExNTM2NDI1OTg3ZmNmY2UwZjVjNWEzMDYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOTZhZDI2OWIwYmIwNDc1Nzk4NTg5MjE0OThjZmYxNWYuYmluZFBvcHVwKHBvcHVwX2Q5MDU3MTA4OTJmMzQ2ZTE5ODdjOTViNTRkY2NlMjZjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzkzZTY3YzE2NGZmMzRjYTFiYTFjMzg0ZjE4MTZkMzBkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTAuOTc3Nzk3NCwxMS4wMjg3MzY0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjg4NDEzNTcxOTAxOTk1MTYsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjFlYzM4NDUzNGIzNGJiMmE5YWE2NzNhYzhiODM2MWQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfODk3OGMxNDI0MTM3NDg3ZDgxNDJlMDM1ZGIzODUxNWMgPSAkKCc8ZGl2IGlkPSJodG1sXzg5NzhjMTQyNDEzNzQ4N2Q4MTQyZTAzNWRiMzg1MTVjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5FcmZ1cnQsIEluaGFiaXRhbnRzICgyMDE3KSAyMTI5ODg8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2YxZWMzODQ1MzRiMzRiYjJhOWFhNjczYWM4YjgzNjFkLnNldENvbnRlbnQoaHRtbF84OTc4YzE0MjQxMzc0ODdkODE0MmUwMzVkYjM4NTE1Yyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85M2U2N2MxNjRmZjM0Y2ExYmExYzM4NGYxODE2ZDMwZC5iaW5kUG9wdXAocG9wdXBfZjFlYzM4NDUzNGIzNGJiMmE5YWE2NzNhYzhiODM2MWQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfODQ1NDg4NGE4NzEzNDBhOWFhN2IyNTIyZWVjZjQ0OTEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs1MS41MTM5OTMyNSw2Ljg0OTMyMjc2MTI4MTkyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjg3NzYzNTA4NzM2MDAyMTMsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMDNlMTE3YmMzZmMyNDZjZGE5NmJhNGU1Nzk5MGE2YzAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNjNkZGJlYTU5NTc4NGE4OGI5OTMwZTcwMjZlODIyZjggPSAkKCc8ZGl2IGlkPSJodG1sXzYzZGRiZWE1OTU3ODRhODhiOTkzMGU3MDI2ZTgyMmY4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5PYmVyaGF1c2VuLCBJbmhhYml0YW50cyAoMjAxNykgMjExNDIyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wM2UxMTdiYzNmYzI0NmNkYTk2YmE0ZTU3OTkwYTZjMC5zZXRDb250ZW50KGh0bWxfNjNkZGJlYTU5NTc4NGE4OGI5OTMwZTcwMjZlODIyZjgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODQ1NDg4NGE4NzEzNDBhOWFhN2IyNTIyZWVjZjQ0OTEuYmluZFBvcHVwKHBvcHVwXzAzZTExN2JjM2ZjMjQ2Y2RhOTZiYTRlNTc5OTBhNmMwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzAzNzM1OGY4OTNlMDRhYzVhN2RkMzM1MDE3YmY5ZGUyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTQuMDkyNDQ0NSwxMi4xMjg2MTI3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjg2NTEyNzgwNTYyODYyMjcsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjYxODU1ZDFiZTAyNDE5N2ExNGQwMzJlNGZiODFkMjEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMzQ4NmE5NDc3MDk2NDE4NTgyYzczZWRjNWNhMGNmN2EgPSAkKCc8ZGl2IGlkPSJodG1sXzM0ODZhOTQ3NzA5NjQxODU4MmM3M2VkYzVjYTBjZjdhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Sb3N0b2NrLCBJbmhhYml0YW50cyAoMjAxNykgMjA4NDA5PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82NjE4NTVkMWJlMDI0MTk3YTE0ZDAzMmU0ZmI4MWQyMS5zZXRDb250ZW50KGh0bWxfMzQ4NmE5NDc3MDk2NDE4NTgyYzczZWRjNWNhMGNmN2EpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMDM3MzU4Zjg5M2UwNGFjNWE3ZGQzMzUwMTdiZjlkZTIuYmluZFBvcHVwKHBvcHVwXzY2MTg1NWQxYmUwMjQxOTdhMTRkMDMyZTRmYjgxZDIxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzgxODgzZTc4NDU1ZDQ2ZjNhMDljNWVlMmU3YzM0NGIyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTEuMzA3Njg2Nyw5LjQ2MjQ3MDVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuODMzMjc2MzcwOTM3Mjc4MSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wMzQyNTA4YWM3ZTY0MTNhYjk4NDI0NTRlZmI5ZTg5OSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80MjAwYjFlNWFiOWU0YTcyOWQ4ZjI2ZjFlYjQ4N2VmNCA9ICQoJzxkaXYgaWQ9Imh0bWxfNDIwMGIxZTVhYjllNGE3MjlkOGYyNmYxZWI0ODdlZjQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkthc3NlbCwgSW5oYWJpdGFudHMgKDIwMTcpIDIwMDczNjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDM0MjUwOGFjN2U2NDEzYWI5ODQyNDU0ZWZiOWU4OTkuc2V0Q29udGVudChodG1sXzQyMDBiMWU1YWI5ZTRhNzI5ZDhmMjZmMWViNDg3ZWY0KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzgxODgzZTc4NDU1ZDQ2ZjNhMDljNWVlMmU3YzM0NGIyLmJpbmRQb3B1cChwb3B1cF8wMzQyNTA4YWM3ZTY0MTNhYjk4NDI0NTRlZmI5ZTg5OSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yOTgyMTdkOTJhN2Y0NDhlYTM3NTkzNWFjZWUzZjU4OSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUxLjM1ODI5NDUsNy40NzMyOTZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNzc5Mjg3MDg5MDkyNDE2MSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jMzZjMzhkMzY0M2E0MzViODIwODI1ODMxZDliNGNjMyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lNGQzODNmZTU5Y2Q0Yzc3YTMwMTg2ZTVmMGI4NGJmMyA9ICQoJzxkaXYgaWQ9Imh0bWxfZTRkMzgzZmU1OWNkNGM3N2EzMDE4NmU1ZjBiODRiZjMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhhZ2VuLCBJbmhhYml0YW50cyAoMjAxNykgMTg3NzMwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jMzZjMzhkMzY0M2E0MzViODIwODI1ODMxZDliNGNjMy5zZXRDb250ZW50KGh0bWxfZTRkMzgzZmU1OWNkNGM3N2EzMDE4NmU1ZjBiODRiZjMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjk4MjE3ZDkyYTdmNDQ4ZWEzNzU5MzVhY2VlM2Y1ODkuYmluZFBvcHVwKHBvcHVwX2MzNmMzOGQzNjQzYTQzNWI4MjA4MjU4MzFkOWI0Y2MzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Q3N2IzODc3MmRlMjRkYTc5MzAxMjczYzVmMzExOTYxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDkuMjM0MzYyLDYuOTk2Mzc5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjc1MTIwOTAwOTU1OTk5NjYsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjkwYWJkZGZjZWY3NDQ3M2JlYWVjOTcwOTQ2Y2QzYzEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMTVjNzc3OTYzY2FmNDk3ZTk1Y2VlZjU1NGJmNGJjYmIgPSAkKCc8ZGl2IGlkPSJodG1sXzE1Yzc3Nzk2M2NhZjQ5N2U5NWNlZWY1NTRiZjRiY2JiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TYWFyYnLDvGNrZW4sIEluaGFiaXRhbnRzICgyMDE3KSAxODA5NjY8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzY5MGFiZGRmY2VmNzQ0NzNiZWFlYzk3MDk0NmNkM2MxLnNldENvbnRlbnQoaHRtbF8xNWM3Nzc5NjNjYWY0OTdlOTVjZWVmNTU0YmY0YmNiYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9kNzdiMzg3NzJkZTI0ZGE3OTMwMTI3M2M1ZjMxMTk2MS5iaW5kUG9wdXAocG9wdXBfNjkwYWJkZGZjZWY3NDQ3M2JlYWVjOTcwOTQ2Y2QzYzEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMDRiOWE0MGQ0MjcxNDlkMjlmNDhmMGU0YWIwYWM2MWUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs1MS42NjE2MjcxLDcuODIxNjgzMTI0ODQ2MzRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNzQzODE1ODkwMTU2MjA2MSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82ZGE0NGRjNjhjNmI0YjY2OGRhNDBhMDE0ZTczYjJmMyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xOWRkNzQyODg1NGY0YjAzYWRhMWNkMzQxNDY5NGJiNCA9ICQoJzxkaXYgaWQ9Imh0bWxfMTlkZDc0Mjg4NTRmNGIwM2FkYTFjZDM0MTQ2OTRiYjQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhhbW0sIEluaGFiaXRhbnRzICgyMDE3KSAxNzkxODU8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzZkYTQ0ZGM2OGM2YjRiNjY4ZGE0MGEwMTRlNzNiMmYzLnNldENvbnRlbnQoaHRtbF8xOWRkNzQyODg1NGY0YjAzYWRhMWNkMzQxNDY5NGJiNCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wNGI5YTQwZDQyNzE0OWQyOWY0OGYwZTRhYjBhYzYxZS5iaW5kUG9wdXAocG9wdXBfNmRhNDRkYzY4YzZiNGI2NjhkYTQwYTAxNGU3M2IyZjMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTQ1NmZmZDA1ZTU5NGEzYjg2MjljYWY3OTlmOWJhY2MgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs1Mi40MDA5MzA5LDEzLjA1OTEzOTddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNzI5MzkwNzk3NTUxOTU0NSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zNjdmOWM4M2RhMjc0YWNkOThhMjMwOTE3MGIxZDU4MyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81ZmM4ZWU1NWI0MjY0NzZhYjUyNDBiN2JkYmI0N2YwMiA9ICQoJzxkaXYgaWQ9Imh0bWxfNWZjOGVlNTViNDI2NDc2YWI1MjQwYjdiZGJiNDdmMDIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlBvdHNkYW0sIEluaGFiaXRhbnRzICgyMDE3KSAxNzU3MTA8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzM2N2Y5YzgzZGEyNzRhY2Q5OGEyMzA5MTcwYjFkNTgzLnNldENvbnRlbnQoaHRtbF81ZmM4ZWU1NWI0MjY0NzZhYjUyNDBiN2JkYmI0N2YwMik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl81NDU2ZmZkMDVlNTk0YTNiODYyOWNhZjc5OWY5YmFjYy5iaW5kUG9wdXAocG9wdXBfMzY3ZjljODNkYTI3NGFjZDk4YTIzMDkxNzBiMWQ1ODMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMWVlNThlNmUxZjI2NGYwOGExYWQ1ODM5YzhkNGEzMmIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs1MS40MjcyOTI1LDYuODgyOTE5Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMC43MTA5MzkxMzIzMzU4Njg3LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzcwMTk3ZTk5Y2MzNDQ0ODQ4NDZkZTk2OGQ2OTVjNjZmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzA5ZDBkMjFlNTRhZjQ4ZDZhMDlkY2M4ZWQ0OTY1OTk1ID0gJCgnPGRpdiBpZD0iaHRtbF8wOWQwZDIxZTU0YWY0OGQ2YTA5ZGNjOGVkNDk2NTk5NSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TcO8bGhlaW0gYW4gZGVywqBSdWhyLCBJbmhhYml0YW50cyAoMjAxNykgMTcxMjY1PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83MDE5N2U5OWNjMzQ0NDg0ODQ2ZGU5NjhkNjk1YzY2Zi5zZXRDb250ZW50KGh0bWxfMDlkMGQyMWU1NGFmNDhkNmEwOWRjYzhlZDQ5NjU5OTUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMWVlNThlNmUxZjI2NGYwOGExYWQ1ODM5YzhkNGEzMmIuYmluZFBvcHVwKHBvcHVwXzcwMTk3ZTk5Y2MzNDQ0ODQ4NDZkZTk2OGQ2OTVjNjZmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY3OTUwMzg0ZDAxZDRjZWRiOTgxNDJhYTYyOGVlM2RjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDkuNDg3Mjk3LDguMzkwMDY1NzcyNjgyNzRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNjk5NDQ4ODcxNTIxODkyMywKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xZDQwZGFmMTM2MWE0ZjBjOGNlNmM0YzZmZjZjZWRmYSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83M2VlYWM5NTYzMjQ0M2NiYTBjMGU5ZDRmYjhhNWUwMiA9ICQoJzxkaXYgaWQ9Imh0bWxfNzNlZWFjOTU2MzI0NDNjYmEwYzBlOWQ0ZmI4YTVlMDIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkx1ZHdpZ3NoYWZlbiBhbSBSaGVpbiwgSW5oYWJpdGFudHMgKDIwMTcpIDE2ODQ5NzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMWQ0MGRhZjEzNjFhNGYwYzhjZTZjNGM2ZmY2Y2VkZmEuc2V0Q29udGVudChodG1sXzczZWVhYzk1NjMyNDQzY2JhMGMwZTlkNGZiOGE1ZTAyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzY3OTUwMzg0ZDAxZDRjZWRiOTgxNDJhYTYyOGVlM2RjLmJpbmRQb3B1cChwb3B1cF8xZDQwZGFmMTM2MWE0ZjBjOGNlNmM0YzZmZjZjZWRmYSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wNmFjYjM2OWE1ZjU0NmVjYjNkYjQ0OWNkZTFhZWRmNiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUzLjEzODk3NTMsOC4yMTQ2MDE3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjY5MzU3MDkwNTcyOTc3MTMsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOWQzNzIzOTE4MDFjNDg2MGFlZjEyZmVmZjA5NTViZGYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMTJjYmIyYzZjOGYxNDU0MTg0M2YzZTYxNjlmZTQwMDUgPSAkKCc8ZGl2IGlkPSJodG1sXzEyY2JiMmM2YzhmMTQ1NDE4NDNmM2U2MTY5ZmU0MDA1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5PbGRlbmJ1cmcgKE9sZGIpLCBJbmhhYml0YW50cyAoMjAxNykgMTY3MDgxPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85ZDM3MjM5MTgwMWM0ODYwYWVmMTJmZWZmMDk1NWJkZi5zZXRDb250ZW50KGh0bWxfMTJjYmIyYzZjOGYxNDU0MTg0M2YzZTYxNjlmZTQwMDUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMDZhY2IzNjlhNWY1NDZlY2IzZGI0NDljZGUxYWVkZjYuYmluZFBvcHVwKHBvcHVwXzlkMzcyMzkxODAxYzQ4NjBhZWYxMmZlZmYwOTU1YmRmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2VlNTc0NDIxYjk5ODQ4NmM4OGVmZjMyODg5MzY2NDQ0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTIuMjY2ODM3LDguMDQ5NzQxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjY4MjMzMzg2MjM2ODcwNCwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lNjc5MWQ0NjQyMTg0ZWFhYTk4ODJlMjY3NjBkMWEzZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zNWYwOWVkNDc1N2E0YzNhODBkODYwMDdkZDQzOTUxYyA9ICQoJzxkaXYgaWQ9Imh0bWxfMzVmMDllZDQ3NTdhNGMzYTgwZDg2MDA3ZGQ0Mzk1MWMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk9zbmFicsO8Y2ssIEluaGFiaXRhbnRzICgyMDE3KSAxNjQzNzQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2U2NzkxZDQ2NDIxODRlYWFhOTg4MmUyNjc2MGQxYTNkLnNldENvbnRlbnQoaHRtbF8zNWYwOWVkNDc1N2E0YzNhODBkODYwMDdkZDQzOTUxYyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9lZTU3NDQyMWI5OTg0ODZjODhlZmYzMjg4OTM2NjQ0NC5iaW5kUG9wdXAocG9wdXBfZTY3OTFkNDY0MjE4NGVhYWE5ODgyZTI2NzYwZDFhM2QpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfN2I0NTI0MDQ2ZjA2NDViNWE1MTMzMDJjMzdiYTA1ODYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs1MS4wMzI0NzQzLDYuOTg4MTE5NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMC42NzkwMjU0MzEwNTc3NDMzLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2ZiN2Q4NDE0ZjZjOTQ0MTFhNjI1M2I1MzcxNDUxYmVhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2M2MjY5YjU4YmUzNjQyMjk5NWVhN2U3YjZlNGIwZjRmID0gJCgnPGRpdiBpZD0iaHRtbF9jNjI2OWI1OGJlMzY0MjI5OTVlYTdlN2I2ZTRiMGY0ZiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TGV2ZXJrdXNlbiwgSW5oYWJpdGFudHMgKDIwMTcpIDE2MzU3NzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZmI3ZDg0MTRmNmM5NDQxMWE2MjUzYjUzNzE0NTFiZWEuc2V0Q29udGVudChodG1sX2M2MjY5YjU4YmUzNjQyMjk5NWVhN2U3YjZlNGIwZjRmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzdiNDUyNDA0NmYwNjQ1YjVhNTEzMzAyYzM3YmEwNTg2LmJpbmRQb3B1cChwb3B1cF9mYjdkODQxNGY2Yzk0NDExYTYyNTNiNTM3MTQ1MWJlYSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81NGI0YTQzNGEzMDI0MGMxYTBjZWY1MzA3Njc0NjA0NiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ5LjQwOTM1ODIsOC42OTQ3MjRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNjY2NjcxNzQwMjQwNDA0NCwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84Zjc1ZDRiMjNmY2Y0M2JmOGQwZDc2MjA1N2MzOTA5YSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xZGJiNWQ0YjE1Y2Y0NWQ4ODM2M2E5MWUxMjBlZWY4NyA9ICQoJzxkaXYgaWQ9Imh0bWxfMWRiYjVkNGIxNWNmNDVkODgzNjNhOTFlMTIwZWVmODciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhlaWRlbGJlcmcsIEluaGFiaXRhbnRzICgyMDE3KSAxNjA2MDE8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzhmNzVkNGIyM2ZjZjQzYmY4ZDBkNzYyMDU3YzM5MDlhLnNldENvbnRlbnQoaHRtbF8xZGJiNWQ0YjE1Y2Y0NWQ4ODM2M2E5MWUxMjBlZWY4Nyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl81NGI0YTQzNGEzMDI0MGMxYTBjZWY1MzA3Njc0NjA0Ni5iaW5kUG9wdXAocG9wdXBfOGY3NWQ0YjIzZmNmNDNiZjhkMGQ3NjIwNTdjMzkwOWEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMjVjMDRkNTE1NWZhNDg0NDhjOGZiOTVhZjNiYTViMmQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs1MS4xNzEyNDY4LDcuMDgzODk5Nl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMC42NTkyMDgwNTIwMzgyNjIyLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzAwZGUwNzY5MDAzNTRhNDQ5MTEyYzU2OTBkNGYzYzlkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzUxNDAyYWVhYzhjNjRhNWQ4MDBlODk0NzMyZTZlYWQ4ID0gJCgnPGRpdiBpZD0iaHRtbF81MTQwMmFlYWM4YzY0YTVkODAwZTg5NDczMmU2ZWFkOCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U29saW5nZW4sIEluaGFiaXRhbnRzICgyMDE3KSAxNTg4MDM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzAwZGUwNzY5MDAzNTRhNDQ5MTEyYzU2OTBkNGYzYzlkLnNldENvbnRlbnQoaHRtbF81MTQwMmFlYWM4YzY0YTVkODAwZTg5NDczMmU2ZWFkOCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yNWMwNGQ1MTU1ZmE0ODQ0OGM4ZmI5NWFmM2JhNWIyZC5iaW5kUG9wdXAocG9wdXBfMDBkZTA3NjkwMDM1NGE0NDkxMTJjNTY5MGQ0ZjNjOWQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYzIxZjkzODRmOWU1NDI3OGI0NGVmOTIwZTQ3NTc1ZjcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OS44NzI3NzUsOC42NTExNzddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNjU2OTI5MDk0OTYyMDc5NiwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81N2Q5NDllMjZjMTE0NDc2YjEzNDk5ZWFhMjY1MjIxMCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jNTljYmJkZjBhN2E0ZGMxYjNjNzQwZTE5YWE3MWQ4ZSA9ICQoJzxkaXYgaWQ9Imh0bWxfYzU5Y2JiZGYwYTdhNGRjMWIzYzc0MGUxOWFhNzFkOGUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRhcm1zdGFkdCwgSW5oYWJpdGFudHMgKDIwMTcpIDE1ODI1NDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNTdkOTQ5ZTI2YzExNDQ3NmIxMzQ5OWVhYTI2NTIyMTAuc2V0Q29udGVudChodG1sX2M1OWNiYmRmMGE3YTRkYzFiM2M3NDBlMTlhYTcxZDhlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2MyMWY5Mzg0ZjllNTQyNzhiNDRlZjkyMGU0NzU3NWY3LmJpbmRQb3B1cChwb3B1cF81N2Q5NDllMjZjMTE0NDc2YjEzNDk5ZWFhMjY1MjIxMCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xNTljOWU3Yzc4MjY0ZGJmOWQ1ODFiMjI3NTA1NGUxOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUxLjUzODAzOTQsNy4yMTk5ODVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNjQ5NjA2NTQ0MzU2NjQwOSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yNjNkOGRlYWQ2YzQ0ZWJiOTZiZDBlZWJkMTQxMzhiMCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lZjFkMTdlMzM0M2Y0N2M0ODgzMzlmMDU4MGVhYmYxZCA9ICQoJzxkaXYgaWQ9Imh0bWxfZWYxZDE3ZTMzNDNmNDdjNDg4MzM5ZjA1ODBlYWJmMWQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhlcm5lLCBJbmhhYml0YW50cyAoMjAxNykgMTU2NDkwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yNjNkOGRlYWQ2YzQ0ZWJiOTZiZDBlZWJkMTQxMzhiMC5zZXRDb250ZW50KGh0bWxfZWYxZDE3ZTMzNDNmNDdjNDg4MzM5ZjA1ODBlYWJmMWQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMTU5YzllN2M3ODI2NGRiZjlkNTgxYjIyNzUwNTRlMTkuYmluZFBvcHVwKHBvcHVwXzI2M2Q4ZGVhZDZjNDRlYmI5NmJkMGVlYmQxNDEzOGIwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Q3MTI1ZjMzNzZlZjQ1NTVhNWM3NTY0OGNiYjhiMjU2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTEuMTk4MTc3OCw2LjY5MTY0NzZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNjM4NDgxNTgwODUxNzc5MiwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82NzBiYmFjZDUxYTk0OGMwYWIzN2RiYTFlODg4MzY5ZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80ZjU1MGRmNWE4YjM0NDk5ODM0ODgyZjkxOTFiNjRiMSA9ICQoJzxkaXYgaWQ9Imh0bWxfNGY1NTBkZjVhOGIzNDQ5OTgzNDg4MmY5MTkxYjY0YjEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5ldXNzLCBJbmhhYml0YW50cyAoMjAxNykgMTUzODEwPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82NzBiYmFjZDUxYTk0OGMwYWIzN2RiYTFlODg4MzY5ZC5zZXRDb250ZW50KGh0bWxfNGY1NTBkZjVhOGIzNDQ5OTgzNDg4MmY5MTkxYjY0YjEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZDcxMjVmMzM3NmVmNDU1NWE1Yzc1NjQ4Y2JiOGIyNTYuYmluZFBvcHVwKHBvcHVwXzY3MGJiYWNkNTFhOTQ4YzBhYjM3ZGJhMWU4ODgzNjlkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2EyN2JlZTlhZDQxNDRhZGZhODcwNTE4ZjRmNGM2Y2FlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDkuMDE5NTMzMywxMi4wOTc0ODY5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjYyNjM3Njk1NjM4MTU2NDEsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMGMwODQ5OTI3OGY3NGE2MDk3NWI1ZWYxNDUzODdiOGQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNDM2MzVkN2NiNjc5NGM2ZTlhYjMzZTljZWQxZDQxODcgPSAkKCc8ZGl2IGlkPSJodG1sXzQzNjM1ZDdjYjY3OTRjNmU5YWIzM2U5Y2VkMWQ0MTg3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5SZWdlbnNidXJnLCBJbmhhYml0YW50cyAoMjAxNykgMTUwODk0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8wYzA4NDk5Mjc4Zjc0YTYwOTc1YjVlZjE0NTM4N2I4ZC5zZXRDb250ZW50KGh0bWxfNDM2MzVkN2NiNjc5NGM2ZTlhYjMzZTljZWQxZDQxODcpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYTI3YmVlOWFkNDE0NGFkZmE4NzA1MThmNGY0YzZjYWUuYmluZFBvcHVwKHBvcHVwXzBjMDg0OTkyNzhmNzRhNjA5NzViNWVmMTQ1Mzg3YjhkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2VkMGMwMTIyYzA1ZTQ2MzdiMTBjNDU3ZDNiM2NkYzMzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTEuNzE4OTU5NTUsOC43NjQ4Njk3NzgxNzc1Nl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMC42MTg4MjYwOTQ5NTc5Mjg1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2NhZjk0ZjM4OTJkZjRjYjViYmU1NGNlOTkzMmE1MjQyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzA4NmM4NDBhMWY5NjQ5Y2ZhOGRhYjViMDNjMTFmMjJiID0gJCgnPGRpdiBpZD0iaHRtbF8wODZjODQwYTFmOTY0OWNmYThkYWI1YjAzYzExZjIyYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UGFkZXJib3JuLCBJbmhhYml0YW50cyAoMjAxNykgMTQ5MDc1PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jYWY5NGYzODkyZGY0Y2I1YmJlNTRjZTk5MzJhNTI0Mi5zZXRDb250ZW50KGh0bWxfMDg2Yzg0MGExZjk2NDljZmE4ZGFiNWIwM2MxMWYyMmIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZWQwYzAxMjJjMDVlNDYzN2IxMGM0NTdkM2IzY2RjMzMuYmluZFBvcHVwKHBvcHVwX2NhZjk0ZjM4OTJkZjRjYjViYmU1NGNlOTkzMmE1MjQyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzcyMTYwODVjM2JiODQxZmFhYzYzNjEwMjdiMjg2YWY2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguNzYzMDE2NSwxMS40MjUwMzk1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjU2MTQxMjE1MDg0MDExNDYsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZDM5ZTc4NzAxY2UyNDAzOThlNmZhNTEzNGI3NzA3MGQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNjhhNzg3NjNhM2Q2NGMyM2E5NGU4M2I3MTA1MDY1MzcgPSAkKCc8ZGl2IGlkPSJodG1sXzY4YTc4NzYzYTNkNjRjMjNhOTRlODNiNzEwNTA2NTM3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5JbmdvbHN0YWR0LCBJbmhhYml0YW50cyAoMjAxNykgMTM1MjQ0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9kMzllNzg3MDFjZTI0MDM5OGU2ZmE1MTM0Yjc3MDcwZC5zZXRDb250ZW50KGh0bWxfNjhhNzg3NjNhM2Q2NGMyM2E5NGU4M2I3MTA1MDY1MzcpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzIxNjA4NWMzYmI4NDFmYWFjNjM2MTAyN2IyODZhZjYuYmluZFBvcHVwKHBvcHVwX2QzOWU3ODcwMWNlMjQwMzk4ZTZmYTUxMzRiNzcwNzBkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2U3ODg0MGU4YTJlMjQwY2ZhYWY3MzBiODFmZDI4ZjU2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTAuMTA1NTAwMiw4Ljc2MTA2OThdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNTI1NzcwNzU2NTY2NzAzNCwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83ZTU2OTIwMzdkZDg0NjU3OWI3YWM0NDczZjNlODk1YSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lYTIyYjk2NjdiMjg0ZjZkYjExMjMxOWYzMGI3Y2ViMSA9ICQoJzxkaXYgaWQ9Imh0bWxfZWEyMmI5NjY3YjI4NGY2ZGIxMTIzMTlmMzBiN2NlYjEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk9mZmVuYmFjaCBhbSBNYWluLCBJbmhhYml0YW50cyAoMjAxNykgMTI2NjU4PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83ZTU2OTIwMzdkZDg0NjU3OWI3YWM0NDczZjNlODk1YS5zZXRDb250ZW50KGh0bWxfZWEyMmI5NjY3YjI4NGY2ZGIxMTIzMTlmMzBiN2NlYjEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZTc4ODQwZThhMmUyNDBjZmFhZjczMGI4MWZkMjhmNTYuYmluZFBvcHVwKHBvcHVwXzdlNTY5MjAzN2RkODQ2NTc5YjdhYzQ0NzNmM2U4OTVhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2VhYjVhMDgwNDY1ZjQzOGJhMjE0ZDlmM2ZlMDRlNjlmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDkuNzkyNDUsOS45MzI5NjZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNTI1Njc1MjgxMTMzNjM5MywKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9hZGUyN2E5MDI1MzA0YTIyOWY3MTFkMGU5ZDY4Y2ExOCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mMmIwYzRkMGI3NDA0YTE1YWRjMGZhZGRhOGJjOTE3MSA9ICQoJzxkaXYgaWQ9Imh0bWxfZjJiMGM0ZDBiNzQwNGExNWFkYzBmYWRkYThiYzkxNzEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlfDvHJ6YnVyZywgSW5oYWJpdGFudHMgKDIwMTcpIDEyNjYzNTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYWRlMjdhOTAyNTMwNGEyMjlmNzExZDBlOWQ2OGNhMTguc2V0Q29udGVudChodG1sX2YyYjBjNGQwYjc0MDRhMTVhZGMwZmFkZGE4YmM5MTcxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2VhYjVhMDgwNDY1ZjQzOGJhMjE0ZDlmM2ZlMDRlNjlmLmJpbmRQb3B1cChwb3B1cF9hZGUyN2E5MDI1MzA0YTIyOWY3MTFkMGU5ZDY4Y2ExOCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hOWYyOGVjMGVjNmM0YWM3Yjk5MzlhYjNjOGI1MzM2YiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ5LjQ3NzI2MywxMC45ODk2MTZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNTI1MjIyODEwNjAzMDMxMSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85OGQyNDZjZGFkZTI0MGM5YWE3Y2IxNjU0YTJiODU5NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF84YmIzNGJjNjAwZjY0NmVjOWYwYzBiYjVhZWMwYmQxZiA9ICQoJzxkaXYgaWQ9Imh0bWxfOGJiMzRiYzYwMGY2NDZlYzlmMGMwYmI1YWVjMGJkMWYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkbDvHJ0aCwgSW5oYWJpdGFudHMgKDIwMTcpIDEyNjUyNjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOThkMjQ2Y2RhZGUyNDBjOWFhN2NiMTY1NGEyYjg1OTQuc2V0Q29udGVudChodG1sXzhiYjM0YmM2MDBmNjQ2ZWM5ZjBjMGJiNWFlYzBiZDFmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2E5ZjI4ZWMwZWM2YzRhYzdiOTkzOWFiM2M4YjUzMzZiLmJpbmRQb3B1cChwb3B1cF85OGQyNDZjZGFkZTI0MGM5YWE3Y2IxNjU0YTJiODU5NCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83Yjg5MmE4NGQ2NjY0ZGE1OTQxYTg3YThhNzE3NmE3MSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ4LjM5NzQwMDMsOS45OTM0MzM2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjUyMTM2MjI4MjIyMjYxMjgsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzIyMTU4Njg4ZWM1NGRjOGIwZmQwMmZiMjlmNWQ0MjEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfODI2MDY5NDBhMzZkNDZhZDhiMmI1Nzg4ZWI5ZDYzOGYgPSAkKCc8ZGl2IGlkPSJodG1sXzgyNjA2OTQwYTM2ZDQ2YWQ4YjJiNTc4OGViOWQ2MzhmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5VbG0sIEluaGFiaXRhbnRzICgyMDE3KSAxMjU1OTY8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzMyMjE1ODY4OGVjNTRkYzhiMGZkMDJmYjI5ZjVkNDIxLnNldENvbnRlbnQoaHRtbF84MjYwNjk0MGEzNmQ0NmFkOGIyYjU3ODhlYjlkNjM4Zik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83Yjg5MmE4NGQ2NjY0ZGE1OTQxYTg3YThhNzE3NmE3MS5iaW5kUG9wdXAocG9wdXBfMzIyMTU4Njg4ZWM1NGRjOGIwZmQwMmZiMjlmNWQ0MjEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNWViMDNmODBjYTI1NGFlMmExZTE1MzY2MDQ2ZDU0YWUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OS4xNDIyOTEsOS4yMTg2NTVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNTE5MzU3Mjk4MTI4MjY2NCwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85NDY3NTg0ZTk3ODI0MjVjYjI3NTkwZDI3YmYyYzllZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF84NDkxNzFmZWMwNTA0MDhmYjEwZjY0OWRiNGE2ODE5MCA9ICQoJzxkaXYgaWQ9Imh0bWxfODQ5MTcxZmVjMDUwNDA4ZmIxMGY2NDlkYjRhNjgxOTAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhlaWxicm9ubiwgSW5oYWJpdGFudHMgKDIwMTcpIDEyNTExMzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOTQ2NzU4NGU5NzgyNDI1Y2IyNzU5MGQyN2JmMmM5ZWYuc2V0Q29udGVudChodG1sXzg0OTE3MWZlYzA1MDQwOGZiMTBmNjQ5ZGI0YTY4MTkwKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzVlYjAzZjgwY2EyNTRhZTJhMWUxNTM2NjA0NmQ1NGFlLmJpbmRQb3B1cChwb3B1cF85NDY3NTg0ZTk3ODI0MjVjYjI3NTkwZDI3YmYyYzllZik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83Nzk0NTEwYWNhYTc0NmIxOGRmZDQ1NTVlNTcwNTQ1NiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ4Ljg5MDg4NDYsOC43MDI5NTMyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjUxNTkzNjc4Njk2MTEsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZDAzY2ZlZTVjMThlNGNjODhlODdlMDQyYjM3MWIwMjcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfY2FkYTc3NDAyZDg5NDA2ZWJhYzYyZDdlZGU3NDlhNmYgPSAkKCc8ZGl2IGlkPSJodG1sX2NhZGE3NzQwMmQ4OTQwNmViYWM2MmQ3ZWRlNzQ5YTZmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5QZm9yemhlaW0sIEluaGFiaXRhbnRzICgyMDE3KSAxMjQyODk8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2QwM2NmZWU1YzE4ZTRjYzg4ZTg3ZTA0MmIzNzFiMDI3LnNldENvbnRlbnQoaHRtbF9jYWRhNzc0MDJkODk0MDZlYmFjNjJkN2VkZTc0OWE2Zik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83Nzk0NTEwYWNhYTc0NmIxOGRmZDQ1NTVlNTcwNTQ1Ni5iaW5kUG9wdXAocG9wdXBfZDAzY2ZlZTVjMThlNGNjODhlODdlMDQyYjM3MWIwMjcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTdjMjgzM2Y2MjQ2NDdmOGE0ZWEyM2JhOWY5YzNhYWUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs1Mi40MjA1NTg4LDEwLjc4NjE2ODJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNTE0MzgwMTIyMjkxNTc2NCwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iY2Y1NzJlMDhlZDg0Y2YwOWJjMGI0ZjcxNzZjYWFlOSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jZDg2MzYzYWI1ZDU0YWQ3OTlkYWIyZTNmMzkxZTNiNCA9ICQoJzxkaXYgaWQ9Imh0bWxfY2Q4NjM2M2FiNWQ1NGFkNzk5ZGFiMmUzZjM5MWUzYjQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldvbGZzYnVyZywgSW5oYWJpdGFudHMgKDIwMTcpIDEyMzkxNDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYmNmNTcyZTA4ZWQ4NGNmMDliYzBiNGY3MTc2Y2FhZTkuc2V0Q29udGVudChodG1sX2NkODYzNjNhYjVkNTRhZDc5OWRhYjJlM2YzOTFlM2I0KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU3YzI4MzNmNjI0NjQ3ZjhhNGVhMjNiYTlmOWMzYWFlLmJpbmRQb3B1cChwb3B1cF9iY2Y1NzJlMDhlZDg0Y2YwOWJjMGI0ZjcxNzZjYWFlOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84ZTAzM2JlYTNkODU0NGM3OGRhOGVjNWJlNzg1ZGE4MSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUxLjUzMjc2MDQsOS45MzUyMDUxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjQ5NjE3NzUyMzQyMjYxNDQ1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2FlMmMzNTJkNjA0MTRjNzk4OTg1MDExM2FjOTEyZTk1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzBhZWI1ODBlMGY0YzRhMmY5YmMzOGIzZDQ1ZWYwNWE5ID0gJCgnPGRpdiBpZD0iaHRtbF8wYWViNTgwZTBmNGM0YTJmOWJjMzhiM2Q0NWVmMDVhOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+R8O2dHRpbmdlbiwgSW5oYWJpdGFudHMgKDIwMTcpIDExOTUyOTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYWUyYzM1MmQ2MDQxNGM3OTg5ODUwMTEzYWM5MTJlOTUuc2V0Q29udGVudChodG1sXzBhZWI1ODBlMGY0YzRhMmY5YmMzOGIzZDQ1ZWYwNWE5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzhlMDMzYmVhM2Q4NTQ0Yzc4ZGE4ZWM1YmU3ODVkYTgxLmJpbmRQb3B1cChwb3B1cF9hZTJjMzUyZDYwNDE0Yzc5ODk4NTAxMTNhYzkxMmU5NSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kYjViY2M2MGI2ZjM0YTc2ODM3Njg5OTRiMDQ0ZWU3OSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUxLjUyMTU4MSw2LjkyOTIwNF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMC40ODcxOTAzNzkzOTcyMzE3NSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zODIwMzkxZmE3YjU0YjZjOGQzZjhjMWNhYTIwY2M1OSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lNThlYjE4MTFhNWE0ZjAyYjYyZjMxMTA1ZGYyOGU2YyA9ICQoJzxkaXYgaWQ9Imh0bWxfZTU4ZWIxODExYTVhNGYwMmI2MmYzMTEwNWRmMjhlNmMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJvdHRyb3AsIEluaGFiaXRhbnRzICgyMDE3KSAxMTczNjQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzM4MjAzOTFmYTdiNTRiNmM4ZDNmOGMxY2FhMjBjYzU5LnNldENvbnRlbnQoaHRtbF9lNThlYjE4MTFhNWE0ZjAyYjYyZjMxMTA1ZGYyOGU2Yyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9kYjViY2M2MGI2ZjM0YTc2ODM3Njg5OTRiMDQ0ZWU3OS5iaW5kUG9wdXAocG9wdXBfMzgyMDM5MWZhN2I1NGI2YzhkM2Y4YzFjYWEyMGNjNTkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNTgyZDViNDNkZjE1NDk2N2I4NmVjZWEyMDMyNGNiNjIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC40OTE5NTA4LDkuMjExNDE0NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMC40ODA1NDAzMDc5MjkwMjcyLAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RiZTFjNDYxOWFkYTQ5MDY5M2EwYjlmNDliZjZmMDk1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzkyMmZjNDhiNWYxMzQxMjc5Y2Y2MTZmNTEwMjM4N2RkID0gJCgnPGRpdiBpZD0iaHRtbF85MjJmYzQ4YjVmMTM0MTI3OWNmNjE2ZjUxMDIzODdkZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UmV1dGxpbmdlbiwgSW5oYWJpdGFudHMgKDIwMTcpIDExNTc2MjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZGJlMWM0NjE5YWRhNDkwNjkzYTBiOWY0OWJmNmYwOTUuc2V0Q29udGVudChodG1sXzkyMmZjNDhiNWYxMzQxMjc5Y2Y2MTZmNTEwMjM4N2RkKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU4MmQ1YjQzZGYxNTQ5NjdiODZlY2VhMjAzMjRjYjYyLmJpbmRQb3B1cChwb3B1cF9kYmUxYzQ2MTlhZGE0OTA2OTNhMGI5ZjQ5YmY2ZjA5NSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81NDMwNjBkMzM4NjA0MmU2OGJiYzNlZWRiZGRhZTBkNiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUwLjM1MzMyNzgsNy41OTQzOTUxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjQ3MjU3ODQ4NzAzMjYzNzQsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNTZhZWZhM2IxYzg2NGZmOTlmNWYyZDk1ZTJmMzk1YWMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOGE1ZTkyYTlmNDhkNDc2YWIxN2Y2ODg3OGJiMDMzMTggPSAkKCc8ZGl2IGlkPSJodG1sXzhhNWU5MmE5ZjQ4ZDQ3NmFiMTdmNjg4NzhiYjAzMzE4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Lb2JsZW56LCBJbmhhYml0YW50cyAoMjAxNykgMTEzODQ0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81NmFlZmEzYjFjODY0ZmY5OWY1ZjJkOTVlMmYzOTVhYy5zZXRDb250ZW50KGh0bWxfOGE1ZTkyYTlmNDhkNDc2YWIxN2Y2ODg3OGJiMDMzMTgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNTQzMDYwZDMzODYwNDJlNjhiYmMzZWVkYmRkYWUwZDYuYmluZFBvcHVwKHBvcHVwXzU2YWVmYTNiMWM4NjRmZjk5ZjVmMmQ5NWUyZjM5NWFjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzM4ZmY1OTgzMDI0ODRiN2ViNTZlNGQyZThkM2MyYzRiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTEuNjE0MzgxNSw3LjE5Nzg1NDZdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNDcwNTY5MzUxODMyNTA1NjQsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjMzYzA5ZTE1ODVkNGUxMTk1YjRhMDVkMmY4ZTM0ZTQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfN2JmMDcwZWMxMGRlNDQwYmJlN2Q1YmZhYTJkNGM5YjUgPSAkKCc8ZGl2IGlkPSJodG1sXzdiZjA3MGVjMTBkZTQ0MGJiZTdkNWJmYWEyZDRjOWI1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5SZWNrbGluZ2hhdXNlbiwgSW5oYWJpdGFudHMgKDIwMTcpIDExMzM2MDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNjMzYzA5ZTE1ODVkNGUxMTk1YjRhMDVkMmY4ZTM0ZTQuc2V0Q29udGVudChodG1sXzdiZjA3MGVjMTBkZTQ0MGJiZTdkNWJmYWEyZDRjOWI1KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzM4ZmY1OTgzMDI0ODRiN2ViNTZlNGQyZThkM2MyYzRiLmJpbmRQb3B1cChwb3B1cF82MzNjMDllMTU4NWQ0ZTExOTViNGEwNWQyZjhlMzRlNCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81MThiY2M3Mzc3NTM0MGE2OGRiMzFlZWU0M2Q1NWRjYiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUzLjU1MjIyNjQsOC41ODY1NTA5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjQ2OTE4Mjg4MjUwMDE4MzM2LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2EyZDZjODQyMDQ3MjQ3ZWY4MWE3ZWZhY2I3ZmI5NDc2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzZjMzdkYTUyNjEyMjQ3MjU5ZjE1NWMxZWM2OGUyY2ViID0gJCgnPGRpdiBpZD0iaHRtbF82YzM3ZGE1MjYxMjI0NzI1OWYxNTVjMWVjNjhlMmNlYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnJlbWVyaGF2ZW4gLCBJbmhhYml0YW50cyAoMjAxNykgMTEzMDI2PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hMmQ2Yzg0MjA0NzI0N2VmODFhN2VmYWNiN2ZiOTQ3Ni5zZXRDb250ZW50KGh0bWxfNmMzN2RhNTI2MTIyNDcyNTlmMTU1YzFlYzY4ZTJjZWIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNTE4YmNjNzM3NzUzNDBhNjhkYjMxZWVlNDNkNTVkY2IuYmluZFBvcHVwKHBvcHVwX2EyZDZjODQyMDQ3MjQ3ZWY4MWE3ZWZhY2I3ZmI5NDc2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzcxYTIyNzRkMTRlYTQ0MTNhZjE1ODU5NDk3MjFkZTAzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTAuOTkyOTMwMyw3LjEyNzczNzldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNDYzMzc1NDg1NTA2NDE0MTYsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOTExMjNkYmY0NDU4NDljNjkzZjVjYjRkNWUwMjI4MTIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYmZjMTQ4NjgxMmY1NDIyMWJjMTM0Mzk1NjdjNGZjYmUgPSAkKCc8ZGl2IGlkPSJodG1sX2JmYzE0ODY4MTJmNTQyMjFiYzEzNDM5NTY3YzRmY2JlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CZXJnaXNjaCBHbGFkYmFjaCwgSW5oYWJpdGFudHMgKDIwMTcpIDExMTYyNzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOTExMjNkYmY0NDU4NDljNjkzZjVjYjRkNWUwMjI4MTIuc2V0Q29udGVudChodG1sX2JmYzE0ODY4MTJmNTQyMjFiYzEzNDM5NTY3YzRmY2JlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzcxYTIyNzRkMTRlYTQ0MTNhZjE1ODU5NDk3MjFkZTAzLmJpbmRQb3B1cChwb3B1cF85MTEyM2RiZjQ0NTg0OWM2OTNmNWNiNGQ1ZTAyMjgxMik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hNmRhMzEzYmFkZDY0YzRmYWNkZWQwYjBhZGQ0NzVhNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUwLjkyODE3MTcsMTEuNTg3OTM1OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMC40NjExODM3MDE2NTE3MjQ5NSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mYzNjZjRlNWI2NTA0MWJjOTE3YTNmNDZlMTkxMGFiMyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zYWI1MTc1ZjMwM2E0MTlmYjIyYTAwM2M4NWY3M2I2MyA9ICQoJzxkaXYgaWQ9Imh0bWxfM2FiNTE3NWYzMDNhNDE5ZmIyMmEwMDNjODVmNzNiNjMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkplbmEsIEluaGFiaXRhbnRzICgyMDE3KSAxMTEwOTk8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2ZjM2NmNGU1YjY1MDQxYmM5MTdhM2Y0NmUxOTEwYWIzLnNldENvbnRlbnQoaHRtbF8zYWI1MTc1ZjMwM2E0MTlmYjIyYTAwM2M4NWY3M2I2Myk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hNmRhMzEzYmFkZDY0YzRmYWNkZWQwYjBhZGQ0NzVhNy5iaW5kUG9wdXAocG9wdXBfZmMzY2Y0ZTViNjUwNDFiYzkxN2EzZjQ2ZTE5MTBhYjMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOTBkYTBjZGRmZDcxNDMwOWFlMTQ3YTVkZmI4NWFhYWYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OS41OTgxMTg3LDExLjAwMzY0NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMC40NjA3NjQ0Mzk5NjczOTk5NiwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85MjZiMmNlNGJjOTQ0YzgxYjY3NDA0NGZlOTkxMzMxNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hMTVmYmIzZTE5NDY0MmFmODdlNzUyNTg2ZjE1NTFmNSA9ICQoJzxkaXYgaWQ9Imh0bWxfYTE1ZmJiM2UxOTQ2NDJhZjg3ZTc1MjU4NmYxNTUxZjUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkVybGFuZ2VuLCBJbmhhYml0YW50cyAoMjAxNykgMTEwOTk4PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85MjZiMmNlNGJjOTQ0YzgxYjY3NDA0NGZlOTkxMzMxNy5zZXRDb250ZW50KGh0bWxfYTE1ZmJiM2UxOTQ2NDJhZjg3ZTc1MjU4NmYxNTUxZjUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOTBkYTBjZGRmZDcxNDMwOWFlMTQ3YTVkZmI4NWFhYWYuYmluZFBvcHVwKHBvcHVwXzkyNmIyY2U0YmM5NDRjODFiNjc0MDQ0ZmU5OTEzMzE3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzkwNWRkM2Y3ZDM5MDQ1YTNhNWVjNDU0NWM5NTE0MGUzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTEuMTc5ODcwNiw3LjE5NDM1NDRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNDU5MDQ1ODgyMTcyMjQ2LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzlhM2FhZGIzNzE5NjQ3YWRhYzFlYjBjZTkxOGRmZWYyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2U2NGY4MDU0YTBiMjQ5NTdiZThhZTUzYWNmMDdkNzFiID0gJCgnPGRpdiBpZD0iaHRtbF9lNjRmODA1NGEwYjI0OTU3YmU4YWU1M2FjZjA3ZDcxYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UmVtc2NoZWlkLCBJbmhhYml0YW50cyAoMjAxNykgMTEwNTg0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85YTNhYWRiMzcxOTY0N2FkYWMxZWIwY2U5MThkZmVmMi5zZXRDb250ZW50KGh0bWxfZTY0ZjgwNTRhMGIyNDk1N2JlOGFlNTNhY2YwN2Q3MWIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOTA1ZGQzZjdkMzkwNDVhM2E1ZWM0NTQ1Yzk1MTQwZTMuYmluZFBvcHVwKHBvcHVwXzlhM2FhZGIzNzE5NjQ3YWRhYzFlYjBjZTkxOGRmZWYyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzYyNDMyMTQwNTA4MjQwMTI5ZDM4MjEyYWRmZmQzODVlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDkuNzU5NjIwOCw2LjY0NDE4NzhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNDU2Njc1NjAwNzY4Nzg0OCwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lMjQ2MTk5YzBhYzM0ZjNjODI5YjAzNmJmMDYwNTZkZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83MzQ2Mzc2YmZhY2Q0ODUyYmY0NDUxNThiOTQ5M2YwYiA9ICQoJzxkaXYgaWQ9Imh0bWxfNzM0NjM3NmJmYWNkNDg1MmJmNDQ1MTU4Yjk0OTNmMGIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlRyaWVyLCBJbmhhYml0YW50cyAoMjAxNykgMTEwMDEzPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9lMjQ2MTk5YzBhYzM0ZjNjODI5YjAzNmJmMDYwNTZkZC5zZXRDb250ZW50KGh0bWxfNzM0NjM3NmJmYWNkNDg1MmJmNDQ1MTU4Yjk0OTNmMGIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNjI0MzIxNDA1MDgyNDAxMjlkMzgyMTJhZGZmZDM4NWUuYmluZFBvcHVwKHBvcHVwX2UyNDYxOTljMGFjMzRmM2M4MjliMDM2YmYwNjA1NmRkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2M4ZGM1NTliYzNmZDRlYmU4NWI1ZmM0MzAxODcxYzdjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTIuMTUwMzcyMSwxMC4zNTkzMTQ3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjQzMzk4OTgwNzY1MTU5NDksCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZWM0NDUwNmQ4OTRlNDE2YmEwZmQwZjk3N2ViNmEzZGMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMGQ2YjM1MjA0N2Y1NDdhZmJhYjVlMzg1MmMxOTgyMTEgPSAkKCc8ZGl2IGlkPSJodG1sXzBkNmIzNTIwNDdmNTQ3YWZiYWI1ZTM4NTJjMTk4MjExIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TYWx6Z2l0dGVyICwgSW5oYWJpdGFudHMgKDIwMTcpIDEwNDU0ODwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZWM0NDUwNmQ4OTRlNDE2YmEwZmQwZjk3N2ViNmEzZGMuc2V0Q29udGVudChodG1sXzBkNmIzNTIwNDdmNTQ3YWZiYWI1ZTM4NTJjMTk4MjExKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2M4ZGM1NTliYzNmZDRlYmU4NWI1ZmM0MzAxODcxYzdjLmJpbmRQb3B1cChwb3B1cF9lYzQ0NTA2ZDg5NGU0MTZiYTBmZDBmOTc3ZWI2YTNkYyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kM2YxZDA2YTM1Nzk0OGUzYmQ4NjhhNzdjNWVkY2YyZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUxLjQ1MTI4Myw2LjYyODQzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjQzMTUwMzI5NTI4NjE0MjYsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOTI4ZmExYTNlNjUwNGI1ZjgwMjRjYzM1NTIwN2MyNGQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYjgxMGRkZThkZmI3NDA0ZTlmNDM2NDc4OWU0MTZmZjggPSAkKCc8ZGl2IGlkPSJodG1sX2I4MTBkZGU4ZGZiNzQwNGU5ZjQzNjQ3ODllNDE2ZmY4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Nb2VycywgSW5oYWJpdGFudHMgKDIwMTcpIDEwMzk0OTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOTI4ZmExYTNlNjUwNGI1ZjgwMjRjYzM1NTIwN2MyNGQuc2V0Q29udGVudChodG1sX2I4MTBkZGU4ZGZiNzQwNGU5ZjQzNjQ3ODllNDE2ZmY4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2QzZjFkMDZhMzU3OTQ4ZTNiZDg2OGE3N2M1ZWRjZjJmLmJpbmRQb3B1cChwb3B1cF85MjhmYTFhM2U2NTA0YjVmODAyNGNjMzU1MjA3YzI0ZCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9hZTg3ZGY5MmFhYmI0MGQ0YTQ5N2MxYzFjNGVkYTE1YiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzUwLjg3NDk4MDQsOC4wMjI3MjMzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiAwLjQyNDgxMTcxMjc2MDA4NDEsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfY2ZjMDc1MmMyOWFmNGE0MDk1MWRmZjcxYjc3M2FiNzYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZTQwMGY5ZGFjNjg1NDdhOWFhNTQ1NTllMTRhMmM4OGQgPSAkKCc8ZGl2IGlkPSJodG1sX2U0MDBmOWRhYzY4NTQ3YTlhYTU0NTU5ZTE0YTJjODhkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TaWVnZW4sIEluaGFiaXRhbnRzICgyMDE3KSAxMDIzMzc8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2NmYzA3NTJjMjlhZjRhNDA5NTFkZmY3MWI3NzNhYjc2LnNldENvbnRlbnQoaHRtbF9lNDAwZjlkYWM2ODU0N2E5YWE1NDU1OWUxNGEyYzg4ZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hZTg3ZGY5MmFhYmI0MGQ0YTQ5N2MxYzFjNGVkYTE1Yi5iaW5kUG9wdXAocG9wdXBfY2ZjMDc1MmMyOWFmNGE0MDk1MWRmZjcxYjc3M2FiNzYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYzUxOTNmMDU4NTBhNDM0NGEwNGUwNzkxMTQzY2U0MTYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs1Mi4xNTIxNjM2LDkuOTUxMzA0Nl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogMC40MjIzNTAxMDcwMjkzNDQxNywKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hNmQxOTg1NDU0MTg0NDAzYjc1MTIzMDZkYzIxOWJhYik7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xMjFmOGE3YzU2YWI0NzJhODU4OGE2YTIyZGNlMDA3MiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zYjVkODFkNWM5MGI0YmNjYjY4ODA0ODdmNTJmNzdkZSA9ICQoJzxkaXYgaWQ9Imh0bWxfM2I1ZDgxZDVjOTBiNGJjY2I2ODgwNDg3ZjUyZjc3ZGUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhpbGRlc2hlaW0sIEluaGFiaXRhbnRzICgyMDE3KSAxMDE3NDQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzEyMWY4YTdjNTZhYjQ3MmE4NTg4YTZhMjJkY2UwMDcyLnNldENvbnRlbnQoaHRtbF8zYjVkODFkNWM5MGI0YmNjYjY4ODA0ODdmNTJmNzdkZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jNTE5M2YwNTg1MGE0MzQ0YTA0ZTA3OTExNDNjZTQxNi5iaW5kUG9wdXAocG9wdXBfMTIxZjhhN2M1NmFiNDcyYTg1ODhhNmEyMmRjZTAwNzIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjQxOGZjOWM2NzhmNDQzZWFkYmEzMzJhNDc1OTc5YTcgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs1MS43NTY3NDQ3LDE0LjMzNTczMDddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDAuNDE5NDExMTI0MTMzMjgzNzQsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYTZkMTk4NTQ1NDE4NDQwM2I3NTEyMzA2ZGMyMTliYWIpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzBkNjQyZjAxNDJhNGM3YWE4ZTA2MDVjYmU1N2M2YzMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDc2N2U0MzQ1ZDNmNGFkNTk1NzU0MDYyZWVjNjE4YmQgPSAkKCc8ZGl2IGlkPSJodG1sX2Q3NjdlNDM0NWQzZjRhZDU5NTc1NDA2MmVlYzYxOGJkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Db3R0YnVzLCBJbmhhYml0YW50cyAoMjAxNykgMTAxMDM2PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jMGQ2NDJmMDE0MmE0YzdhYThlMDYwNWNiZTU3YzZjMy5zZXRDb250ZW50KGh0bWxfZDc2N2U0MzQ1ZDNmNGFkNTk1NzU0MDYyZWVjNjE4YmQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjQxOGZjOWM2NzhmNDQzZWFkYmEzMzJhNDc1OTc5YTcuYmluZFBvcHVwKHBvcHVwX2MwZDY0MmYwMTQyYTRjN2FhOGUwNjA1Y2JlNTdjNmMzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzAzNTc0ZDYxNzM5YjQzNmY5MzI5Y2NhMzc1MDkzNDczID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNTEuMTU5Mzk5MzAwMDAwMDA0LDYuOTA5MDQ4ODY5OTk5OTk5NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJ5ZWxsb3ciLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICJ5ZWxsb3ciLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDQ1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2E2ZDE5ODU0NTQxODQ0MDNiNzUxMjMwNmRjMjE5YmFiKTsKICAgICAgICAgICAgCjwvc2NyaXB0Pg==\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
],
"text/plain": [
"<folium.folium.Map at 0x7f173eee57b8>"
]
},
"execution_count": 156,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"TheMap"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Since the map will not render in the gist I made a screenshot which I am linking."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"![](https://raw.githubusercontent.com/PatrickRWright/Coursera_Capstone/master/mapDE_all.png)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finding the best match compared to your city of choice. Shape of the dataframe. As you can see we have 80 cities and five properties to classify them by. "
]
},
{
"cell_type": "code",
"execution_count": 157,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(80, 7)"
]
},
"execution_count": 157,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cities_df.shape"
]
},
{
"cell_type": "code",
"execution_count": 180,
"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>name</th>\n",
" <th>totalPop2017</th>\n",
" <th>area</th>\n",
" <th>popPerArea</th>\n",
" <th>popChange</th>\n",
" <th>province</th>\n",
" <th>cafeCount</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Berlin</td>\n",
" <td>3613495</td>\n",
" <td>89168</td>\n",
" <td>4009</td>\n",
" <td>1.08</td>\n",
" <td>Berlin</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Hamburg</td>\n",
" <td>1830584</td>\n",
" <td>75522</td>\n",
" <td>2397</td>\n",
" <td>1.11</td>\n",
" <td>Hamburg</td>\n",
" <td>8</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>München</td>\n",
" <td>1456039</td>\n",
" <td>31070</td>\n",
" <td>4713</td>\n",
" <td>-0.56</td>\n",
" <td>Bayern</td>\n",
" <td>14</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Köln</td>\n",
" <td>1080394</td>\n",
" <td>40502</td>\n",
" <td>2656</td>\n",
" <td>0.41</td>\n",
" <td>Nordrhein-Westfalen</td>\n",
" <td>2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Frankfurt am Main</td>\n",
" <td>746878</td>\n",
" <td>24831</td>\n",
" <td>2966</td>\n",
" <td>1.42</td>\n",
" <td>Hessen</td>\n",
" <td>10</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" name totalPop2017 area popPerArea popChange \\\n",
"0 Berlin 3613495 89168 4009 1.08 \n",
"1 Hamburg 1830584 75522 2397 1.11 \n",
"2 München 1456039 31070 4713 -0.56 \n",
"3 Köln 1080394 40502 2656 0.41 \n",
"4 Frankfurt am Main 746878 24831 2966 1.42 \n",
"\n",
" province cafeCount \n",
"0 Berlin 3 \n",
"1 Hamburg 8 \n",
"2 Bayern 14 \n",
"3 Nordrhein-Westfalen 2 \n",
"4 Hessen 10 "
]
},
"execution_count": 180,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cities_df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Distributions of scaled data"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(array([11., 8., 16., 10., 7., 15., 2., 7., 1., 3.]),\n",
" array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ]),\n",
" <a list of 10 Patch objects>)"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAXQAAAD8CAYAAABn919SAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAADtRJREFUeJzt3X+MZWddx/H3hy61ikBbdtpsWtYtyWK3gUDJpCkhQegiIWC6/aMlRdHVbNwUC8FgIqv8If5ILCaCGDeWDUUGw4+uVdwNIlq3bVBCC1Nb6I8tttRaNl26g7QVNAILX/+4B9y0M71nZu6PmWffr2Ryzzn3uft8n72zn3n2ueecSVUhSVr/njHtAiRJo2GgS1IjDHRJaoSBLkmNMNAlqREGuiQ1wkCXpEYY6JLUCANdkhqxYZKdbdy4sbZs2TLJLiVp3bv99tu/UVUzw9pNNNC3bNnC/Pz8JLuUpHUvyX/0aeeSiyQ1wkCXpEYY6JLUCANdkhphoEtSIwx0SWqEgS5JjTDQJakRBrokNWKiV4quxpY9fzeVfh+65g1T6VeSlssZuiQ1wkCXpEYY6JLUCANdkhphoEtSIwx0SWqEgS5JjTDQJakRBrokNcJAl6RGGOiS1IhegZ7k9CQ3JLkvyeEkL09yZpIbk9zfPZ4x7mIlSUvrO0N/P/CZqjofeAlwGNgDHKqqrcChbl+SNCVDAz3Jc4BXAtcBVNV3q+pxYAcw1zWbAy4bV5GSpOH6zNBfACwAf5HkjiQfTPIs4OyqOgrQPZ41xjolSUP0CfQNwMuAP6+qC4H/ZhnLK0l2J5lPMr+wsLDCMiVJw/QJ9CPAkaq6rdu/gUHAP5pkE0D3eGyxF1fVvqqararZmZmZUdQsSVrE0ECvqq8DX0vy092h7cC9wEFgZ3dsJ3BgLBVKknrp+yvo3gZ8NMmpwIPArzD4YbA/yS7gYeCK8ZQoSeqjV6BX1Z3A7CJPbR9tOZKklfJKUUlqhIEuSY0w0CWpEQa6JDXCQJekRhjoktQIA12SGmGgS1IjDHRJaoSBLkmNMNAlqREGuiQ1wkCXpEYY6JLUCANdkhphoEtSIwx0SWqEgS5JjTDQJakRBrokNcJAl6RGGOiS1AgDXZIasaFPoyQPAd8Cvg8cr6rZJGcC1wNbgIeAN1bVY+MpU5I0zHJm6K+uqpdW1Wy3vwc4VFVbgUPdviRpSlaz5LIDmOu254DLVl+OJGml+gZ6Af+Y5PYku7tjZ1fVUYDu8axxFChJ6qfXGjrwiqp6JMlZwI1J7uvbQfcDYDfA5s2bV1CiJKmPXjP0qnqkezwGfBK4CHg0ySaA7vHYEq/dV1WzVTU7MzMzmqolSU8xNNCTPCvJs3+4DbwWuBs4COzsmu0EDoyrSEnScH2WXM4GPpnkh+0/VlWfSfJFYH+SXcDDwBXjK1OSNMzQQK+qB4GXLHL8P4Ht4yhKkrR8XikqSY0w0CWpEQa6JDXCQJekRhjoktQIA12SGmGgS1IjDHRJaoSBLkmNMNAlqREGuiQ1wkCXpEYY6JLUCANdkhphoEtSIwx0SWqEgS5JjTDQJakRBrokNcJAl6RGGOiS1AgDXZIaYaBLUiN6B3qSU5LckeRT3f55SW5Lcn+S65OcOr4yJUnDLGeG/nbg8An77wHeV1VbgceAXaMsTJK0PL0CPcm5wBuAD3b7AS4BbuiazAGXjaNASVI/fWfofwL8JvCDbv95wONVdbzbPwKcs9gLk+xOMp9kfmFhYVXFSpKWNjTQk/wccKyqbj/x8CJNa7HXV9W+qpqtqtmZmZkVlilJGmZDjzavAC5N8nrgNOA5DGbspyfZ0M3SzwUeGV+ZkqRhhs7Qq+q3qurcqtoCXAncVFW/ANwMXN412wkcGFuVkqShVnMe+juBdyR5gMGa+nWjKUmStBJ9llx+pKpuAW7pth8ELhp9SZKklfBKUUlqhIEuSY0w0CWpEQa6JDXCQJekRhjoktQIA12SGrGs89Cn6aHTfn5KPT8xpX4laXmcoUtSIwx0SWqEgS5JjTDQJakRBrokNcJAl6RGGOiS1AgDXZIaYaBLUiMMdElqhIEuSY0w0CWpEQa6JDXCQJekRhjoktSIoYGe5LQkX0jypST3JPnd7vh5SW5Lcn+S65OcOv5yJUlL6TND/w5wSVW9BHgp8LokFwPvAd5XVVuBx4Bd4ytTkjTM0ECvgW93u8/svgq4BLihOz4HXDaWCiVJvfRaQ09ySpI7gWPAjcBXgcer6njX5AhwzhKv3Z1kPsn8wsLCKGqWJC2iV6BX1fer6qXAucBFwLbFmi3x2n1VNVtVszMzMyuvVJL0tJZ1lktVPQ7cAlwMnJ7kh79k+lzgkdGWJklajj5nucwkOb3b/nHgNcBh4Gbg8q7ZTuDAuIqUJA23YXgTNgFzSU5h8ANgf1V9Ksm9wCeS/AFwB3DdGOuUJA0xNNCr6svAhYscf5DBerokaQ3wSlFJaoSBLkmNMNAlqREGuiQ1os9ZLie3dz93in0/Mb2+Ja07ztAlqREGuiQ1wkCXpEYY6JLUCANdkhphoEtSIwx0SWqEgS5JjTDQJakRBrokNcJAl6RGGOiS1AhvzjXEi8/bPLW+75paz9Nz+PxtU+l3232Hp9KvNErO0CWpEQa6JDXCQJekRhjoktSIoYGe5PlJbk5yOMk9Sd7eHT8zyY1J7u8ezxh/uZKkpfSZoR8HfqOqtgEXA1cnuQDYAxyqqq3AoW5fkjQlQwO9qo5W1b92298CDgPnADuAua7ZHHDZuIqUJA23rDX0JFuAC4HbgLOr6igMQh84a9TFSZL66x3oSX4S+Gvg16vqv5bxut1J5pPMLywsrKRGSVIPvQI9yTMZhPlHq+pvusOPJtnUPb8JOLbYa6tqX1XNVtXszMzMKGqWJC2iz1kuAa4DDlfVe0946iCws9veCRwYfXmSpL763MvlFcAvAnclubM79tvANcD+JLuAh4ErxlOiJKmPoYFeVf8CZImnt4+2HEnSSnmlqCQ1wkCXpEYY6JLUCANdkhphoEtSI/wVdGvYi+dePO0SJm7/tAuQ1jFn6JLUCANdkhrhkssadtXn3z+Vfq99+dun0q+k1XGGLkmNMNAlqREuuUjA3qtumlrfV197ydT6VlucoUtSIwx0SWqESy56iv1/eHzaJUhaAWfoktQIA12SGmGgS1IjDHRJaoSBLkmNMNAlqREGuiQ1wkCXpEYMDfQkH0pyLMndJxw7M8mNSe7vHs8Yb5mSpGH6XCn6YeDPgI+ccGwPcKiqrkmyp9t/5+jL+397v/7Jcf7xSzvPe4NLWh+GztCr6rPAN590eAcw123PAZeNuC5J0jKtdA397Ko6CtA9njW6kiRJKzH2m3Ml2Q3sBti8efO4u9MI3PSqvVPr+5Jbrp5a39J6t9IZ+qNJNgF0j8eWalhV+6pqtqpmZ2ZmVtidJGmYlQb6QWBnt70TODCaciRJKzV0ySXJx4FXARuTHAF+B7gG2J9kF/AwcMU4i5Radvj8bVPpd9t9h6fSr8ZnaKBX1ZuWeGr7iGuRJK2CV4pKUiP8FXRDXPX590+7BEnqxRm6JDXCQJekRrjkojVlmhc1nWz2XnXT1Pq++tpLptZ3y5yhS1IjDHRJaoSBLkmNMNAlqREGuiQ1wkCXpEYY6JLUCANdkhphoEtSIwx0SWqEgS5JjTDQJakR3pxL0kljWjckm9TNyJyhS1IjDHRJaoRLLtKUnYz3gD98/rbpdNz437UzdElqhIEuSY1YVaAneV2SryR5IMmeURUlSVq+Fa+hJzkF2Av8LHAE+GKSg1V176iKk9Smk/Fzg0lYzQz9IuCBqnqwqr4LfALYMZqyJEnLtZpAPwf42gn7R7pjkqQpWM1pi1nkWD2lUbIb2N3tfjvJV1bY30bgGyt87XrlmE8Ojrlxb/3Aqsf7U30arSbQjwDPP2H/XOCRJzeqqn3AvlX0A0CS+aqaXe2fs5445pODY27fpMa7miWXLwJbk5yX5FTgSuDgaMqSJC3XimfoVXU8yVuBfwBOAT5UVfeMrDJJ0rKs6tL/qvo08OkR1TLMqpdt1iHHfHJwzO2byHhT9ZTPMSVJ65CX/ktSI9ZcoA+7nUCSH0tyfff8bUm2TL7K0eox5nckuTfJl5McStLrFKa1rO9tI5JcnqSSrOszIvqMN8kbu/f5niQfm3SNo9bj+3pzkpuT3NF9b79+GnWOUpIPJTmW5O4lnk+SP+3+Tr6c5GUjLaCq1swXgw9Xvwq8ADgV+BJwwZPa/Bpwbbd9JXD9tOuewJhfDfxEt/2Wk2HMXbtnA58FbgVmp133mN/jrcAdwBnd/lnTrnsCY94HvKXbvgB4aNp1j2DcrwReBty9xPOvB/6ewXU8FwO3jbL/tTZD73M7gR3AXLd9A7A9yWIXOa0XQ8dcVTdX1f90u7cyOOd/Pet724jfB/4I+N9JFjcGfcb7q8DeqnoMoKqOTbjGUesz5gKe020/l0WuY1lvquqzwDefpskO4CM1cCtwepJNo+p/rQV6n9sJ/KhNVR0HngCeN5HqxmO5t1DYxeAn/Ho2dMxJLgSeX1WfmmRhY9LnPX4h8MIkn0tya5LXTay68egz5ncDb05yhMHZcm+bTGlTNdZbpqy131jU53YCvW45sI70Hk+SNwOzwM+MtaLxe9oxJ3kG8D7glydV0Jj1eY83MFh2eRWD/4H9c5IXVdXjY65tXPqM+U3Ah6vqj5O8HPjLbsw/GH95UzPW/FprM/Q+txP4UZskGxj8V+3p/ouz1vW6hUKS1wDvAi6tqu9MqLZxGTbmZwMvAm5J8hCDtcaD6/iD0b7f1weq6ntV9e/AVxgE/HrVZ8y7gP0AVfV54DQG93hpWa9/7yu11gK9z+0EDgI7u+3LgZuq+7RhnRo65m754QMMwny9r63CkDFX1RNVtbGqtlTVFgafG1xaVfPTKXfV+nxf/y2DD79JspHBEsyDE61ytPqM+WFgO0CSbQwCfWGiVU7eQeCXurNdLgaeqKqjI/vTp/2p8BKfAv8bg0/I39Ud+z0G/6Bh8Kb/FfAA8AXgBdOueQJj/ifgUeDO7uvgtGse95if1PYW1vFZLj3f4wDvBe4F7gKunHbNExjzBcDnGJwBcyfw2mnXPIIxfxw4CnyPwWx8F3AVcNUJ7/Pe7u/krlF/X3ulqCQ1Yq0tuUiSVshAl6RGGOiS1AgDXZIaYaBLUiMMdElqhIEuSY0w0CWpEf8HKsPmhsNk/R8AAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.hist(df_scaled['totalPop2017'])\n",
"plt.hist(df_scaled['area'])\n",
"plt.hist(df_scaled['popPerArea'])\n",
"plt.hist(df_scaled['popChange'])\n",
"plt.hist(df_scaled['cafeCount'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The best match for Frankfurt am Main is Offenbach. Interestingly they are located exaclty next to each other and have a rivalry. Maybe they are more similar than they thought."
]
},
{
"cell_type": "code",
"execution_count": 158,
"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>name</th>\n",
" <th>totalPop2017</th>\n",
" <th>area</th>\n",
" <th>popPerArea</th>\n",
" <th>popChange</th>\n",
" <th>province</th>\n",
" <th>cafeCount</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>57</th>\n",
" <td>Offenbach am Main</td>\n",
" <td>126658</td>\n",
" <td>4489</td>\n",
" <td>2775</td>\n",
" <td>1.66</td>\n",
" <td>Hessen</td>\n",
" <td>9</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" name totalPop2017 area popPerArea popChange province \\\n",
"57 Offenbach am Main 126658 4489 2775 1.66 Hessen \n",
"\n",
" cafeCount \n",
"57 9 "
]
},
"execution_count": 158,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cities_df.iloc[[np.where(min(allDists) == allDists)[0][0]]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"![](https://raw.githubusercontent.com/PatrickRWright/Coursera_Capstone/master/mapHessen.png)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Discussion & Conclusion"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The above analysis shows how a comparatively small set of variables can serve to compare cities with each other. It also shows that if you are looking to move into an area which is densely populated you do not necessarily need to move to another big town with over 500.000 inhabitants but that you may also like the Ruhrgebiet."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.8"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment