Skip to content

Instantly share code, notes, and snippets.

@jdretz
Last active July 5, 2019 22:12
Show Gist options
  • Save jdretz/50ac7c5c7750c7c0955bbd283bd9f86e to your computer and use it in GitHub Desktop.
Save jdretz/50ac7c5c7750c7c0955bbd283bd9f86e 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": [
"# Potential Locations for Seattle Physical Therapy Clinic"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Introduction"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There has been a growing need for physical therapy clinics as the baby boomer generation has aged. With better medical technology this generation of people is also living longer, and the trend of increasing ages is not trivial. This report will analyze the Seattle area, and segment neighborhoods that can help identify a useful place for a new physical therapy clinic. \n",
"\n",
"Clinics tend to be in areas that are convenient for the potential clients. More factors will be listed in the Data section. \n",
"\n",
"This analysis will provide demographic information and segment neighborhoods based on common venues found in the area. It will not be a comprehensive analysis on many desired factors that are at play when choosing a business location.\n",
"\n",
"That being said, looking at the clusters of segments in our analysis will provide insight to recommend potentially suitable places for further investigation into a concrete location decision."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Data"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are many factors that could influence the location of a physical therapy clinic. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Availability of space\n",
"2. Cost per square foot for commercial real estate\n",
"3. Proximity to other clinics or pharmacies \n",
"4. Demographic information\n",
"5. Type of businesses in the neighborhood\n",
"6. Size of market "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This report will provide insight on factors 4 and 5. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The data for these factors will come from the Foursquare API that provides information on venues based on latitude and longitude coordinates. The latitude and longitude coordinates will come from a dataset at the NYU Geo Spatial Data Repository. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A description of that data follows;\n",
"\n",
"This polygon shapefile includes neighborhood boundaries supplied by Zillow.com, the Los Angeles Times and the City of Denver, and variables related to (A) parks, open space, greenness, and \"pavedness\" (impervious surface) together with (B) a number of demographic variables from the 2010 U.S. census. The project, titled City Nature (http://citynature.stanford.edu) was undertaken by researchers at Stanford University, led by Jon Christensen. This data was developed by Karl Grossner, assisted by Noemi Alvarez.This dataset is the product of a 2013 study seeking to explain the significant variation in areas of parks, open space and \"park-level greenness\" in 38 large U.S. cities, at the scale of neighborhoods."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It is important to note that the data is from the 2010 census. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It is a large data set, but we will only be using Seattle's city neighbhorhood coordinates, neighborhood names, population density, income, and median age. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Methodology"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Analyzing the data will be done using a k-Means clustering technique. Data will be wrangled from the geo-spatial dataset, cleaned, presented visually on maps, averaged, and then clustered. "
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# Import modules \n",
"\n",
"import pandas as pd # building dataframes for analysis\n",
"import numpy as np # mathmatical functions\n",
"import requests # pulling information off of the web\n",
"import json # handling JSON data\n",
"import matplotlib.cm as cm # plotting information on maps\n",
"import matplotlib.colors as colors \n",
"import folium # creating map\n",
"from sklearn.cluster import KMeans "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"After loading data into local environment, it can be opened into notebook as a variable."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"with open('stanford-xq082nw3443-geojson.json') as json_data:\n",
" json_data = json.load(json_data)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Length of all features list: 3155\n",
"Length after sorting by Washington: 78\n"
]
}
],
"source": [
"features = json_data[\"features\"]\n",
"print(\"Length of all features list:\", len(features))\n",
"washingtonFeatures = []\n",
"\n",
"for i, v in enumerate(features):\n",
" if features[i]['properties']['state'] == 'WA': # extract Seatte data from dataset\n",
" washingtonFeatures.append(v)\n",
" else:\n",
" continue\n",
" \n",
"print(\"Length after sorting by Washington:\", len(washingtonFeatures))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Make dataframe from JSON data"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>city</th>\n",
" <th>name</th>\n",
" <th>pc_income</th>\n",
" <th>median age_census</th>\n",
" <th>latitude</th>\n",
" <th>longitude</th>\n",
" <th>popdensity</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
"Empty DataFrame\n",
"Columns: [city, name, pc_income, median age_census, latitude, longitude, popdensity]\n",
"Index: []"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"columns = ['city', 'name', 'pc_income', 'median age_census', 'latitude', 'longitude', 'popdensity']\n",
"\n",
"areas = pd.DataFrame(columns=columns)\n",
"\n",
"areas"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>city</th>\n",
" <th>name</th>\n",
" <th>pc_income</th>\n",
" <th>median age_census</th>\n",
" <th>latitude</th>\n",
" <th>longitude</th>\n",
" <th>popdensity</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Seattle</td>\n",
" <td>Pinehurst</td>\n",
" <td>33705</td>\n",
" <td>40.640000</td>\n",
" <td>47.7229</td>\n",
" <td>-122.319553</td>\n",
" <td>7337.190000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Seattle</td>\n",
" <td>Brighton</td>\n",
" <td>23520</td>\n",
" <td>35.843750</td>\n",
" <td>47.5388</td>\n",
" <td>-122.275673</td>\n",
" <td>11462.300000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Seattle</td>\n",
" <td>Whittier Heights</td>\n",
" <td>41725</td>\n",
" <td>39.457143</td>\n",
" <td>47.6833</td>\n",
" <td>-122.371407</td>\n",
" <td>10478.685714</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Seattle</td>\n",
" <td>Windermere</td>\n",
" <td>56478</td>\n",
" <td>42.383333</td>\n",
" <td>47.6701</td>\n",
" <td>-122.262675</td>\n",
" <td>6346.766667</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Seattle</td>\n",
" <td>Loyal Heights</td>\n",
" <td>40157</td>\n",
" <td>40.529412</td>\n",
" <td>47.6832</td>\n",
" <td>-122.384869</td>\n",
" <td>10233.158824</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" city name pc_income median age_census latitude \\\n",
"0 Seattle Pinehurst 33705 40.640000 47.7229 \n",
"1 Seattle Brighton 23520 35.843750 47.5388 \n",
"2 Seattle Whittier Heights 41725 39.457143 47.6833 \n",
"3 Seattle Windermere 56478 42.383333 47.6701 \n",
"4 Seattle Loyal Heights 40157 40.529412 47.6832 \n",
"\n",
" longitude popdensity \n",
"0 -122.319553 7337.190000 \n",
"1 -122.275673 11462.300000 \n",
"2 -122.371407 10478.685714 \n",
"3 -122.262675 6346.766667 \n",
"4 -122.384869 10233.158824 "
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"for data in washingtonFeatures:\n",
" city = data['properties']['city'] \n",
" name = data['properties']['name']\n",
" pc_income = data['properties']['pc_income']\n",
" median_age_census = data['properties']['medage_cy']\n",
" latitude = data['properties']['y']\n",
" longitude = data['properties']['x']\n",
" popdensity = data['properties']['popdensity']\n",
" \n",
" areas = areas.append({'city': city,\n",
" 'name': name,\n",
" 'pc_income': pc_income,\n",
" 'median age_census': median_age_census,\n",
" 'latitude': latitude,\n",
" 'longitude': longitude,\n",
" 'popdensity': popdensity},\n",
" ignore_index=True)\n",
" \n",
"areas.head()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(78, 7)"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"areas.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can not create a map, using foium, that shows the areas we will be analyzing. "
]
},
{
"cell_type": "code",
"execution_count": 31,
"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+ICNtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogMTAwLjAlOwogICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgICAgICAgICAgdG9wOiAwLjAlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICA8L3N0eWxlPgogICAgICAgIAo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgICAgICAgICA8ZGl2IGNsYXNzPSJmb2xpdW0tbWFwIiBpZD0ibWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0IiA+PC9kaXY+CiAgICAgICAgCjwvYm9keT4KPHNjcmlwdD4gICAgCiAgICAKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGJvdW5kcyA9IG51bGw7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgdmFyIG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCA9IEwubWFwKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ21hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7Y2VudGVyOiBbNDcuNjA2MjA5LC0xMjIuMzMyMDY5XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHpvb206IDEwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4Qm91bmRzOiBib3VuZHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXllcnM6IFtdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ybGRDb3B5SnVtcDogZmFsc2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcnM6IEwuQ1JTLkVQU0czODU3CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgdGlsZV9sYXllcl85ZTczMjM3NjAyYzg0YjJlYWJmNmNkZDJhZmQ5OGQ3NiA9IEwudGlsZUxheWVyKAogICAgICAgICAgICAgICAgJ2h0dHBzOi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5vcmcve3p9L3t4fS97eX0ucG5nJywKICAgICAgICAgICAgICAgIHsKICAiYXR0cmlidXRpb24iOiBudWxsLAogICJkZXRlY3RSZXRpbmEiOiBmYWxzZSwKICAibWF4Wm9vbSI6IDE4LAogICJtaW5ab29tIjogMSwKICAibm9XcmFwIjogZmFsc2UsCiAgInN1YmRvbWFpbnMiOiAiYWJjIgp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYTNkZWY2MDBmNzVlNGIzMWIwZDk4YTE1ZmU4NmE3Y2IgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny43MjI5LC0xMjIuMzE5NTUzMDUxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzliMzZiZDkxYjFiYzRiYzM5ODVlMDQ0NjYwZTFlZjViID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzFkMmRiMWY4NTc5OTQ0OWFhNTI3NDJkMzM5NTNlZTkxID0gJCgnPGRpdiBpZD0iaHRtbF8xZDJkYjFmODU3OTk0NDlhYTUyNzQyZDMzOTUzZWU5MSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UGluZWh1cnN0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85YjM2YmQ5MWIxYmM0YmMzOTg1ZTA0NDY2MGUxZWY1Yi5zZXRDb250ZW50KGh0bWxfMWQyZGIxZjg1Nzk5NDQ5YWE1Mjc0MmQzMzk1M2VlOTEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYTNkZWY2MDBmNzVlNGIzMWIwZDk4YTE1ZmU4NmE3Y2IuYmluZFBvcHVwKHBvcHVwXzliMzZiZDkxYjFiYzRiYzM5ODVlMDQ0NjYwZTFlZjViKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2QwNmQ0ODBhYjQ3YjQyZGFiODAyMzI5MThkMmVhOWYzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTM4OCwtMTIyLjI3NTY3Mjk1MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83N2QwNGIwYmYwMmI0YTQwOGMyZDE4YzE5ZDVkZWM1NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iNmEzZWUxYTBlNWM0NjYxODBlMWYzMjc4ZmM2NDc1MCA9ICQoJzxkaXYgaWQ9Imh0bWxfYjZhM2VlMWEwZTVjNDY2MTgwZTFmMzI3OGZjNjQ3NTAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJyaWdodG9uPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83N2QwNGIwYmYwMmI0YTQwOGMyZDE4YzE5ZDVkZWM1NC5zZXRDb250ZW50KGh0bWxfYjZhM2VlMWEwZTVjNDY2MTgwZTFmMzI3OGZjNjQ3NTApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZDA2ZDQ4MGFiNDdiNDJkYWI4MDIzMjkxOGQyZWE5ZjMuYmluZFBvcHVwKHBvcHVwXzc3ZDA0YjBiZjAyYjRhNDA4YzJkMThjMTlkNWRlYzU0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2ZlNGVmZWYwNmZjNjQ2NmRiZGY1YmE4YjFiMzVlNDA0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjgzMywtMTIyLjM3MTQwNzAzN10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80YmEwOWY5Y2FjMDM0Njg5OWRlZjdiNDE1OGI1Y2EzMCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82M2QxYzQwOTgzMzM0OTY0OTY4OTY4MWE3ZmJkZTcwMSA9ICQoJzxkaXYgaWQ9Imh0bWxfNjNkMWM0MDk4MzMzNDk2NDk2ODk2ODFhN2ZiZGU3MDEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldoaXR0aWVyIEhlaWdodHM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzRiYTA5ZjljYWMwMzQ2ODk5ZGVmN2I0MTU4YjVjYTMwLnNldENvbnRlbnQoaHRtbF82M2QxYzQwOTgzMzM0OTY0OTY4OTY4MWE3ZmJkZTcwMSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mZTRlZmVmMDZmYzY0NjZkYmRmNWJhOGIxYjM1ZTQwNC5iaW5kUG9wdXAocG9wdXBfNGJhMDlmOWNhYzAzNDY4OTlkZWY3YjQxNThiNWNhMzApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMGE3ZWVhNzNjMGVlNGM3YjgzMjZmYzUyYWRiMTVlNjMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42NzAxLC0xMjIuMjYyNjc0ODY1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzU5YjZiNTYxY2EyNzQwYjdiYmMyNTQ3NTEyNWM4MDVlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2UxNmNlMjkwMzZlMjQxMjZiYTkzNjk5YWRlYWNmZTgwID0gJCgnPGRpdiBpZD0iaHRtbF9lMTZjZTI5MDM2ZTI0MTI2YmE5MzY5OWFkZWFjZmU4MCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2luZGVybWVyZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNTliNmI1NjFjYTI3NDBiN2JiYzI1NDc1MTI1YzgwNWUuc2V0Q29udGVudChodG1sX2UxNmNlMjkwMzZlMjQxMjZiYTkzNjk5YWRlYWNmZTgwKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzBhN2VlYTczYzBlZTRjN2I4MzI2ZmM1MmFkYjE1ZTYzLmJpbmRQb3B1cChwb3B1cF81OWI2YjU2MWNhMjc0MGI3YmJjMjU0NzUxMjVjODA1ZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82ZDFmOTg4MzZjMmE0NTdmOGE1ODMyM2MxYWE3ODAzNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjY4MzIsLTEyMi4zODQ4Njg2NzVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNmM5YmEyMjNmODAzNDQyZjliZGRiZDU3ZTdlNGExYWIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZmM0YWQ5ODkzNDhiNDdkZWI3MDhjMWU5YjU1ZWFjODggPSAkKCc8ZGl2IGlkPSJodG1sX2ZjNGFkOTg5MzQ4YjQ3ZGViNzA4YzFlOWI1NWVhYzg4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Mb3lhbCBIZWlnaHRzPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82YzliYTIyM2Y4MDM0NDJmOWJkZGJkNTdlN2U0YTFhYi5zZXRDb250ZW50KGh0bWxfZmM0YWQ5ODkzNDhiNDdkZWI3MDhjMWU5YjU1ZWFjODgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNmQxZjk4ODM2YzJhNDU3ZjhhNTgzMjNjMWFhNzgwMzUuYmluZFBvcHVwKHBvcHVwXzZjOWJhMjIzZjgwMzQ0MmY5YmRkYmQ1N2U3ZTRhMWFiKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzkwZDBmZTdhMmMzMTQ0ZDVhM2Y2MDdhODgzMjk3NGJlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjk2MSwtMTIyLjM5NjE1MzU1NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85Mzg2OTJhOThiMzg0YzYyOTczZWMyNjRhNWRlYjg5YiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9kNzAzNTQ4OGYxNTE0NmM2YTZmMGFhNzlhOWViYmM4OCA9ICQoJzxkaXYgaWQ9Imh0bWxfZDcwMzU0ODhmMTUxNDZjNmE2ZjBhYTc5YTllYmJjODgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5vcnRoIEJlYWNoPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85Mzg2OTJhOThiMzg0YzYyOTczZWMyNjRhNWRlYjg5Yi5zZXRDb250ZW50KGh0bWxfZDcwMzU0ODhmMTUxNDZjNmE2ZjBhYTc5YTllYmJjODgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOTBkMGZlN2EyYzMxNDRkNWEzZjYwN2E4ODMyOTc0YmUuYmluZFBvcHVwKHBvcHVwXzkzODY5MmE5OGIzODRjNjI5NzNlYzI2NGE1ZGViODliKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2E4YTBmYmU2NWQ5ODQ0ZmY5NmI1MjlkZTk0MmFiNmJlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjc3MiwtMTIyLjMxNjE5NjE4OF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zYWEwN2UxYzFmOWM0OTEyOTQ4OTE5NzRjMDc2YTAzMSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82NzI4OTdjMTE5NjY0YmY5OTBkYjAxMGUxYjIzZmE0NSA9ICQoJzxkaXYgaWQ9Imh0bWxfNjcyODk3YzExOTY2NGJmOTkwZGIwMTBlMWIyM2ZhNDUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJvb3NldmVsdDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfM2FhMDdlMWMxZjljNDkxMjk0ODkxOTc0YzA3NmEwMzEuc2V0Q29udGVudChodG1sXzY3Mjg5N2MxMTk2NjRiZjk5MGRiMDEwZTFiMjNmYTQ1KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2E4YTBmYmU2NWQ5ODQ0ZmY5NmI1MjlkZTk0MmFiNmJlLmJpbmRQb3B1cChwb3B1cF8zYWEwN2UxYzFmOWM0OTEyOTQ4OTE5NzRjMDc2YTAzMSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iZDgwYzEzZmViMzU0MDhmODQ2NWM0MDg0NTI1ODM5NCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjU5NzUsLTEyMi4zMzI3NzcwNzFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNzZjODJlZjZlNmE4NDgyOGIxN2M3ODhkYTJmOTMzYmQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfODNhYWE4NTc1NWVlNDU0NGEwNWQyMjg5NzIzZGZmNzcgPSAkKCc8ZGl2IGlkPSJodG1sXzgzYWFhODU3NTVlZTQ1NDRhMDVkMjI4OTcyM2RmZjc3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5QaW9uZWVyIFNxdWFyZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNzZjODJlZjZlNmE4NDgyOGIxN2M3ODhkYTJmOTMzYmQuc2V0Q29udGVudChodG1sXzgzYWFhODU3NTVlZTQ1NDRhMDVkMjI4OTcyM2RmZjc3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2JkODBjMTNmZWIzNTQwOGY4NDY1YzQwODQ1MjU4Mzk0LmJpbmRQb3B1cChwb3B1cF83NmM4MmVmNmU2YTg0ODI4YjE3Yzc4OGRhMmY5MzNiZCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl85YTAzZjIxZWI0OTU0YjcxOGI4YjlmZmMyZTBiMWVjZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjYzNDksLTEyMi4zNDE4MTIxMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mN2JhODczMmFiZTU0YWMyOWE5YWI2ZjA0OWRkNTFhZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81ZjUyYjdlZjRiMTA0NTA4YmMwYjNhYzQyMTJmZTk2YSA9ICQoJzxkaXYgaWQ9Imh0bWxfNWY1MmI3ZWY0YjEwNDUwOGJjMGIzYWM0MjEyZmU5NmEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldlc3RsYWtlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mN2JhODczMmFiZTU0YWMyOWE5YWI2ZjA0OWRkNTFhZi5zZXRDb250ZW50KGh0bWxfNWY1MmI3ZWY0YjEwNDUwOGJjMGIzYWM0MjEyZmU5NmEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOWEwM2YyMWViNDk1NGI3MThiOGI5ZmZjMmUwYjFlY2YuYmluZFBvcHVwKHBvcHVwX2Y3YmE4NzMyYWJlNTRhYzI5YTlhYjZmMDQ5ZGQ1MWFmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzE4MWY1Y2UyOGQxMjQ2ZGJhNDgzZjA1MDljZjU1YzExID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjgxNywtMTIyLjI1NTcxODI0M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jMWU1NTViMTY5Yzc0ZTk0ODgyODBlOGZhYjA2NzllYSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mYTVkOTY2ZjZmMWE0MjgwYmQ2OTlhODNjM2I3NWNlZCA9ICQoJzxkaXYgaWQ9Imh0bWxfZmE1ZDk2NmY2ZjFhNDI4MGJkNjk5YTgzYzNiNzVjZWQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlNhbmQgUG9pbnQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2MxZTU1NWIxNjljNzRlOTQ4ODI4MGU4ZmFiMDY3OWVhLnNldENvbnRlbnQoaHRtbF9mYTVkOTY2ZjZmMWE0MjgwYmQ2OTlhODNjM2I3NWNlZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xODFmNWNlMjhkMTI0NmRiYTQ4M2YwNTA5Y2Y1NWMxMS5iaW5kUG9wdXAocG9wdXBfYzFlNTU1YjE2OWM3NGU5NDg4MjgwZThmYWIwNjc5ZWEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZDg5MzdlNDlkNWYzNGUyMTljNzIwMGNmMDcxMTI3NDYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny41Mjg4LC0xMjIuMzIzMDE1NDYxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzM2YWJlOWI0OGExYTRjMGU5ZTUzOWM5NGNlMmVkMjljID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzVlZmI3OWRiNDkzZDRmMzRiNzI5N2MwZWM1NjRmYmU5ID0gJCgnPGRpdiBpZD0iaHRtbF81ZWZiNzlkYjQ5M2Q0ZjM0YjcyOTdjMGVjNTY0ZmJlOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U291dGggUGFyazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzZhYmU5YjQ4YTFhNGMwZTllNTM5Yzk0Y2UyZWQyOWMuc2V0Q29udGVudChodG1sXzVlZmI3OWRiNDkzZDRmMzRiNzI5N2MwZWM1NjRmYmU5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2Q4OTM3ZTQ5ZDVmMzRlMjE5YzcyMDBjZjA3MTEyNzQ2LmJpbmRQb3B1cChwb3B1cF8zNmFiZTliNDhhMWE0YzBlOWU1MzljOTRjZTJlZDI5Yyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83MGJiZTg3YWFjMzY0YmU1OTQ1MWQ5OWFjNzdhZjNiMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjY5NTIsLTEyMi4zMTc0MDAwMjhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzU4N2IxOTNmNmU2NGMwMWI4NTQxMjBjZmMwNDI1ODggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOTk1YTdkOWRhZjM4NDEzZjgwNTQwMDk0YTM1OTMxMTcgPSAkKCc8ZGl2IGlkPSJodG1sXzk5NWE3ZDlkYWYzODQxM2Y4MDU0MDA5NGEzNTkzMTE3IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5NYXBsZSBMZWFmPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zNTg3YjE5M2Y2ZTY0YzAxYjg1NDEyMGNmYzA0MjU4OC5zZXRDb250ZW50KGh0bWxfOTk1YTdkOWRhZjM4NDEzZjgwNTQwMDk0YTM1OTMxMTcpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzBiYmU4N2FhYzM2NGJlNTk0NTFkOTlhYzc3YWYzYjIuYmluZFBvcHVwKHBvcHVwXzM1ODdiMTkzZjZlNjRjMDFiODU0MTIwY2ZjMDQyNTg4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2IwOWE2Y2QwODNkZjRlM2ZiODNmNGM3OTY1YTBmZGQzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjc3OSwtMTIyLjQwMDk4NDgyMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80ZTM1NzFjODlmOWU0ZmRjYWY3MmQzNjRjYTY3MmIzNSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81ZGNkYmU2NmNhMWY0NDVjYWNhN2M4OTkxOTYzYzhmZSA9ICQoJzxkaXYgaWQ9Imh0bWxfNWRjZGJlNjZjYTFmNDQ1Y2FjYTdjODk5MTk2M2M4ZmUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlN1bnNldCBIaWxsPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80ZTM1NzFjODlmOWU0ZmRjYWY3MmQzNjRjYTY3MmIzNS5zZXRDb250ZW50KGh0bWxfNWRjZGJlNjZjYTFmNDQ1Y2FjYTdjODk5MTk2M2M4ZmUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjA5YTZjZDA4M2RmNGUzZmI4M2Y0Yzc5NjVhMGZkZDMuYmluZFBvcHVwKHBvcHVwXzRlMzU3MWM4OWY5ZTRmZGNhZjcyZDM2NGNhNjcyYjM1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2YwZGU0ZTNhMWNjMTQ4ZTZhYTM3MDQ5ZmY3NzIzZmQyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTU0MSwtMTIyLjMwMDg2MDUxNl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80NzMwMWY5MjBlZGM0NmIzOTQzNDQwYTdhZmY5ZGEzOSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF84MTNiZjg5ZGIyYTY0NmRjYTZkN2MyM2YxZjc5Yjc4ZiA9ICQoJzxkaXYgaWQ9Imh0bWxfODEzYmY4OWRiMmE2NDZkY2E2ZDdjMjNmMWY3OWI3OGYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJlYWNvbiBIaWxsPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80NzMwMWY5MjBlZGM0NmIzOTQzNDQwYTdhZmY5ZGEzOS5zZXRDb250ZW50KGh0bWxfODEzYmY4OWRiMmE2NDZkY2E2ZDdjMjNmMWY3OWI3OGYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjBkZTRlM2ExY2MxNDhlNmFhMzcwNDlmZjc3MjNmZDIuYmluZFBvcHVwKHBvcHVwXzQ3MzAxZjkyMGVkYzQ2YjM5NDM0NDBhN2FmZjlkYTM5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2NlMzkzZmJiOTliMDRkZmJiZDc5NWFhNTc3MTkxZTJkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTEzNSwtMTIyLjI2MTY0ODQ4Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lZjk0NTI5ZTM1Zjg0MzVlYTQzZWY2MmI2YmU0NjYyMCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83ZDI1YjczZmU3MjA0NTZlOWI3YmFlZWRlYjZlNTZjNCA9ICQoJzxkaXYgaWQ9Imh0bWxfN2QyNWI3M2ZlNzIwNDU2ZTliN2JhZWVkZWI2ZTU2YzQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJhaW5pZXIgQmVhY2g8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2VmOTQ1MjllMzVmODQzNWVhNDNlZjYyYjZiZTQ2NjIwLnNldENvbnRlbnQoaHRtbF83ZDI1YjczZmU3MjA0NTZlOWI3YmFlZWRlYjZlNTZjNCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jZTM5M2ZiYjk5YjA0ZGZiYmQ3OTVhYTU3NzE5MWUyZC5iaW5kUG9wdXAocG9wdXBfZWY5NDUyOWUzNWY4NDM1ZWE0M2VmNjJiNmJlNDY2MjApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZDgxYThjMmFjYWY3NGViMWFhNjNhMDEzMjJjOTFhNTAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42MzUxLC0xMjIuMjkxNTAwOTYzXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzFjZjAzMzc3NDcxMzRhOGI4ZWY4OWIzY2Q2Y2QzYTdlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzMxNWY3OGE0MDk0NTQzNzdiZDNkNTZiZTJkNjYxNWRkID0gJCgnPGRpdiBpZD0iaHRtbF8zMTVmNzhhNDA5NDU0Mzc3YmQzZDU2YmUyZDY2MTVkZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnJvYWRtb29yPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xY2YwMzM3NzQ3MTM0YThiOGVmODliM2NkNmNkM2E3ZS5zZXRDb250ZW50KGh0bWxfMzE1Zjc4YTQwOTQ1NDM3N2JkM2Q1NmJlMmQ2NjE1ZGQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZDgxYThjMmFjYWY3NGViMWFhNjNhMDEzMjJjOTFhNTAuYmluZFBvcHVwKHBvcHVwXzFjZjAzMzc3NDcxMzRhOGI4ZWY4OWIzY2Q2Y2QzYTdlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzMwMjUwMjgwODViMjRkYzE4ODcxM2ZhNDM0ZWNjYzUzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjMzMywtMTIyLjI4MzE4MjJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjJhYWZlNmNiNTMyNDNlYjllNDc1MGEwZWQ4ODlhMTEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjY0MzZmMmI1NGJlNGM3MmEyMTg5Yjg1MmJiZGQ5MTYgPSAkKCc8ZGl2IGlkPSJodG1sX2Y2NDM2ZjJiNTRiZTRjNzJhMjE4OWI4NTJiYmRkOTE2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5NYWRpc29uIFBhcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2YyYWFmZTZjYjUzMjQzZWI5ZTQ3NTBhMGVkODg5YTExLnNldENvbnRlbnQoaHRtbF9mNjQzNmYyYjU0YmU0YzcyYTIxODliODUyYmJkZDkxNik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zMDI1MDI4MDg1YjI0ZGMxODg3MTNmYTQzNGVjY2M1My5iaW5kUG9wdXAocG9wdXBfZjJhYWZlNmNiNTMyNDNlYjllNDc1MGEwZWQ4ODlhMTEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOGI5MDgyNDU3ZGI2NGYyNThmYTk4N2Y3MmQ3YzQ3ODMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny41NDQxLC0xMjIuMzY4NjMyODMyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzU5ODZmM2RkZGQ5YjRlYmU5ZWNjNGFiOGYzN2I1ZDMzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzA3NzNkMWE5NDY0ZjRlZDNiNDBlYzBlMWExMWE5MTUzID0gJCgnPGRpdiBpZD0iaHRtbF8wNzczZDFhOTQ2NGY0ZWQzYjQwZWMwZTFhMTFhOTE1MyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SGlnaCBQb2ludDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNTk4NmYzZGRkZDliNGViZTllY2M0YWI4ZjM3YjVkMzMuc2V0Q29udGVudChodG1sXzA3NzNkMWE5NDY0ZjRlZDNiNDBlYzBlMWExMWE5MTUzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzhiOTA4MjQ1N2RiNjRmMjU4ZmE5ODdmNzJkN2M0NzgzLmJpbmRQb3B1cChwb3B1cF81OTg2ZjNkZGRkOWI0ZWJlOWVjYzRhYjhmMzdiNWQzMyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mYTBiNGI2NGEyOTA0MGRkYTcyOWZiODg4ZTU0Yjc5YSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjY0MiwtMTIyLjM4MDM2MDQ2MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kNmM1NzAwODdmZDM0ODlmYmU5ZTQ3NTMyYmZkZTEzYyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lMzYyYzRhNTlmMzc0NmY3YmM4NGVjZWZkMWUzMTZkOSA9ICQoJzxkaXYgaWQ9Imh0bWxfZTM2MmM0YTU5ZjM3NDZmN2JjODRlY2VmZDFlMzE2ZDkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkludGVyYmF5PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9kNmM1NzAwODdmZDM0ODlmYmU5ZTQ3NTMyYmZkZTEzYy5zZXRDb250ZW50KGh0bWxfZTM2MmM0YTU5ZjM3NDZmN2JjODRlY2VmZDFlMzE2ZDkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZmEwYjRiNjRhMjkwNDBkZGE3MjlmYjg4OGU1NGI3OWEuYmluZFBvcHVwKHBvcHVwX2Q2YzU3MDA4N2ZkMzQ4OWZiZTllNDc1MzJiZmRlMTNjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzg4ZTRhZDFhOGNmMjRiNjhiZjc2NDQzZDI3NTBlMGQ3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjgzNCwtMTIyLjI3MzkzNDg3OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8zZTU0ZmI3NTI3YTk0Y2IwYTVlMDQ3YTBhNDEzMTFhYSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iODU4MzRlOGI5NWQ0NzI2YTViYzI0NTIwNGI2MTYwYSA9ICQoJzxkaXYgaWQ9Imh0bWxfYjg1ODM0ZThiOTVkNDcyNmE1YmMyNDUyMDRiNjE2MGEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlZpZXcgUmlkZ2U8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzNlNTRmYjc1MjdhOTRjYjBhNWUwNDdhMGE0MTMxMWFhLnNldENvbnRlbnQoaHRtbF9iODU4MzRlOGI5NWQ0NzI2YTViYzI0NTIwNGI2MTYwYSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84OGU0YWQxYThjZjI0YjY4YmY3NjQ0M2QyNzUwZTBkNy5iaW5kUG9wdXAocG9wdXBfM2U1NGZiNzUyN2E5NGNiMGE1ZTA0N2EwYTQxMzExYWEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDhlZWNhNzIwZTg1NDEwOTkzZThiOWUxYzM4MjY2MjQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny43MDQzLC0xMjIuMjgwMzY1MDY2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2JlMTY3YjM1YWQ4ZTQ1NjRiMWJmZWQwNDk4YjNmOWQ5ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzE1Y2IwOWI0M2I0OTRkYTRiNzBjZmViOTlmZDBiMTEyID0gJCgnPGRpdiBpZD0iaHRtbF8xNWNiMDliNDNiNDk0ZGE0YjcwY2ZlYjk5ZmQwYjExMiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TWF0dGhld3MgQmVhY2g8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2JlMTY3YjM1YWQ4ZTQ1NjRiMWJmZWQwNDk4YjNmOWQ5LnNldENvbnRlbnQoaHRtbF8xNWNiMDliNDNiNDk0ZGE0YjcwY2ZlYjk5ZmQwYjExMik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80OGVlY2E3MjBlODU0MTA5OTNlOGI5ZTFjMzgyNjYyNC5iaW5kUG9wdXAocG9wdXBfYmUxNjdiMzVhZDhlNDU2NGIxYmZlZDA0OThiM2Y5ZDkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZDY5Y2E4YzE5ZmRjNDhlY2EzYTNhYWRkZmFkYzQ0ZWQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42ODk5LC0xMjIuMjk2NDgzMTI4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2JjMDQ4NTRmYzM2NTQ3MDM5MzkyYzgxZTk4ODAwMDRhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzcyNDhhNjlhNTNjZDQ2YTRiNzdiNDIzMmIxMmY3YmM4ID0gJCgnPGRpdiBpZD0iaHRtbF83MjQ4YTY5YTUzY2Q0NmE0Yjc3YjQyMzJiMTJmN2JjOCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2VkZ3dvb2Q8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2JjMDQ4NTRmYzM2NTQ3MDM5MzkyYzgxZTk4ODAwMDRhLnNldENvbnRlbnQoaHRtbF83MjQ4YTY5YTUzY2Q0NmE0Yjc3YjQyMzJiMTJmN2JjOCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9kNjljYThjMTlmZGM0OGVjYTNhM2FhZGRmYWRjNDRlZC5iaW5kUG9wdXAocG9wdXBfYmMwNDg1NGZjMzY1NDcwMzkzOTJjODFlOTg4MDAwNGEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZGIwMWU5NjM5YWQ3NGY3Mzk3ODY3ZTAxZTBlNDI1ZWYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42MjE5LC0xMjIuMzM4Mzk0Mjc0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzlmZGU5YWZjNWUxNjQ2NDM5NTJlYTZjYjIxMzM3ZTFiID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzRmMjM1Zjk4N2E2OTQ5Mzc5ODQ4NzA5ZGQ2YzNmNzY3ID0gJCgnPGRpdiBpZD0iaHRtbF80ZjIzNWY5ODdhNjk0OTM3OTg0ODcwOWRkNmMzZjc2NyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+U291dGggTGFrZSBVbmlvbjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOWZkZTlhZmM1ZTE2NDY0Mzk1MmVhNmNiMjEzMzdlMWIuc2V0Q29udGVudChodG1sXzRmMjM1Zjk4N2E2OTQ5Mzc5ODQ4NzA5ZGQ2YzNmNzY3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2RiMDFlOTYzOWFkNzRmNzM5Nzg2N2UwMWUwZTQyNWVmLmJpbmRQb3B1cChwb3B1cF85ZmRlOWFmYzVlMTY0NjQzOTUyZWE2Y2IyMTMzN2UxYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82Y2IzYTBhMWRiNDc0MmEzYjhmZTU5YmI4OTJmMTliOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjUyMzIsLTEyMi4zODg5Nzg0NTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMTU1YzEwNDM2MjQyNDI2OThjYjRiNmMxNzhhYWE4MmMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNTYyMmZkODEyNjkyNDE5ZGEyNWNmMDhkOGE3ZGNmZTkgPSAkKCc8ZGl2IGlkPSJodG1sXzU2MjJmZDgxMjY5MjQxOWRhMjVjZjA4ZDhhN2RjZmU5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5GYXVudGxlcm95PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xNTVjMTA0MzYyNDI0MjY5OGNiNGI2YzE3OGFhYTgyYy5zZXRDb250ZW50KGh0bWxfNTYyMmZkODEyNjkyNDE5ZGEyNWNmMDhkOGE3ZGNmZTkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNmNiM2EwYTFkYjQ3NDJhM2I4ZmU1OWJiODkyZjE5YjkuYmluZFBvcHVwKHBvcHVwXzE1NWMxMDQzNjI0MjQyNjk4Y2I0YjZjMTc4YWFhODJjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2JjYzNlNmQ5NWRlMzQ5M2Y5MmZhZTQxZGU3M2RkZDYyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjI3MiwtMTIyLjMxMjQ1MTc1NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mYTU2N2ZlMTE3NTM0NTZiYmRjYWY1NmQxZTg4ZTA2ZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85MTVlMGIzYWNjMTc0N2FlODIxM2QxNjFlNzVmZmI3OCA9ICQoJzxkaXYgaWQ9Imh0bWxfOTE1ZTBiM2FjYzE3NDdhZTgyMTNkMTYxZTc1ZmZiNzgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNhcGl0b2wgSGlsbDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZmE1NjdmZTExNzUzNDU2YmJkY2FmNTZkMWU4OGUwNmYuc2V0Q29udGVudChodG1sXzkxNWUwYjNhY2MxNzQ3YWU4MjEzZDE2MWU3NWZmYjc4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2JjYzNlNmQ5NWRlMzQ5M2Y5MmZhZTQxZGU3M2RkZDYyLmJpbmRQb3B1cChwb3B1cF9mYTU2N2ZlMTE3NTM0NTZiYmRjYWY1NmQxZTg4ZTA2Zik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jZTM1NmEyYTEzMmI0Y2Y5ODFlZGM4ZTAzNDNkYzZkMSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjYwODUsLTEyMi4zMjM2ODkxOThdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjhjZTAxNDJkYTg3NDdlNzkwM2NlNzZkOGUxZjA5YjkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfODFjODc5MTZmNWE2NGNiZjkzMjFkMzQ4YzAyZWMyZTUgPSAkKCc8ZGl2IGlkPSJodG1sXzgxYzg3OTE2ZjVhNjRjYmY5MzIxZDM0OGMwMmVjMmU1IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5GaXJzdCBIaWxsPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82OGNlMDE0MmRhODc0N2U3OTAzY2U3NmQ4ZTFmMDliOS5zZXRDb250ZW50KGh0bWxfODFjODc5MTZmNWE2NGNiZjkzMjFkMzQ4YzAyZWMyZTUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfY2UzNTZhMmExMzJiNGNmOTgxZWRjOGUwMzQzZGM2ZDEuYmluZFBvcHVwKHBvcHVwXzY4Y2UwMTQyZGE4NzQ3ZTc5MDNjZTc2ZDhlMWYwOWI5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2EwMDM5MzQ3MWFhODQ4ZTI5ZTA1ZjljYjM0ZmRjZmE4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTA3OSwtMTIyLjM4MDg0OTI5NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wNzIxMThlNzE0YjA0MDE4YWZmYWQzY2Y3N2NkYzJlNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zOWYzOGMxNjhjN2U0NzVmOTA4ZjYxZGM2MzU4OWRkYSA9ICQoJzxkaXYgaWQ9Imh0bWxfMzlmMzhjMTY4YzdlNDc1ZjkwOGY2MWRjNjM1ODlkZGEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkFyYm9yIEhlaWdodHM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzA3MjExOGU3MTRiMDQwMThhZmZhZDNjZjc3Y2RjMmU0LnNldENvbnRlbnQoaHRtbF8zOWYzOGMxNjhjN2U0NzVmOTA4ZjYxZGM2MzU4OWRkYSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9hMDAzOTM0NzFhYTg0OGUyOWUwNWY5Y2IzNGZkY2ZhOC5iaW5kUG9wdXAocG9wdXBfMDcyMTE4ZTcxNGIwNDAxOGFmZmFkM2NmNzdjZGMyZTQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfY2RkZGUxYmRkNWVmNDgyZmI4NDIzZTc1NjRkNmJlMWIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny43MDgxLC0xMjIuMzIxODU2NTg1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzdlMmIzZjgzMGJkNTQwOGFhYzFhZTVhM2VlZWRkYTExID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2EzNzgyZTgxNGQ4NDQ0YWQ4MDBmNmEyZGM2ZGVmMTAwID0gJCgnPGRpdiBpZD0iaHRtbF9hMzc4MmU4MTRkODQ0NGFkODAwZjZhMmRjNmRlZjEwMCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Tm9ydGhnYXRlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83ZTJiM2Y4MzBiZDU0MDhhYWMxYWU1YTNlZWVkZGExMS5zZXRDb250ZW50KGh0bWxfYTM3ODJlODE0ZDg0NDRhZDgwMGY2YTJkYzZkZWYxMDApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfY2RkZGUxYmRkNWVmNDgyZmI4NDIzZTc1NjRkNmJlMWIuYmluZFBvcHVwKHBvcHVwXzdlMmIzZjgzMGJkNTQwOGFhYzFhZTVhM2VlZWRkYTExKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzE4NWI2MDVjODNlZTRhOTY5M2JlNzdiOTgxNjBhNzQ2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjI1MSwtMTIyLjM1NTY1MDA1N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lNjA3YWVhNDI1Yjc0ZTAyYThlZDM0YTg4MjllMmU0OSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80YWYzMTk5OTk1N2M0NDIwODcyYjA2NGM4NzNmOTQ1MCA9ICQoJzxkaXYgaWQ9Imh0bWxfNGFmMzE5OTk5NTdjNDQyMDg3MmIwNjRjODczZjk0NTAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxvd2VyIFF1ZWVuIEFubmU8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2U2MDdhZWE0MjViNzRlMDJhOGVkMzRhODgyOWUyZTQ5LnNldENvbnRlbnQoaHRtbF80YWYzMTk5OTk1N2M0NDIwODcyYjA2NGM4NzNmOTQ1MCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xODViNjA1YzgzZWU0YTk2OTNiZTc3Yjk4MTYwYTc0Ni5iaW5kUG9wdXAocG9wdXBfZTYwN2FlYTQyNWI3NGUwMmE4ZWQzNGE4ODI5ZTJlNDkpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDNjZmMwNDQ1Y2JhNGFmZmFlMTg1OTI3YzQyZmQ3OWMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42Mzc5LC0xMjIuMzI4MjI5MjM0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzE2OGY4NTQ1YjA4MjRhNmE4ODY5NmMxMzhmOWY2ZDA1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzg0NmIxMmI1MjJmYzQzMWFiMGVhYWIwNGQ3M2VlOWEzID0gJCgnPGRpdiBpZD0iaHRtbF84NDZiMTJiNTIyZmM0MzFhYjBlYWFiMDRkNzNlZTlhMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RWFzdGxha2U8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzE2OGY4NTQ1YjA4MjRhNmE4ODY5NmMxMzhmOWY2ZDA1LnNldENvbnRlbnQoaHRtbF84NDZiMTJiNTIyZmM0MzFhYjBlYWFiMDRkNzNlZTlhMyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80M2NmYzA0NDVjYmE0YWZmYWUxODU5MjdjNDJmZDc5Yy5iaW5kUG9wdXAocG9wdXBfMTY4Zjg1NDViMDgyNGE2YTg4Njk2YzEzOGY5ZjZkMDUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMmMzM2VkN2I5ZWU0NGUwZmEyYjQ5YTRlNWFjMjIxMjIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny41NzYsLTEyMi4yODY5NzUzOTVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNmJlNTA2MTM2NjJhNDAxMDk1MDM2NjFmNjIwZWNhNTIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMmE0MzUwOGNlNGFlNGRjN2EwZjljYjIwNjk4Nzg1MTEgPSAkKCc8ZGl2IGlkPSJodG1sXzJhNDM1MDhjZTRhZTRkYzdhMGY5Y2IyMDY5ODc4NTExIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Nb3VudCBCYWtlcjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNmJlNTA2MTM2NjJhNDAxMDk1MDM2NjFmNjIwZWNhNTIuc2V0Q29udGVudChodG1sXzJhNDM1MDhjZTRhZTRkYzdhMGY5Y2IyMDY5ODc4NTExKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzJjMzNlZDdiOWVlNDRlMGZhMmI0OWE0ZTVhYzIyMTIyLmJpbmRQb3B1cChwb3B1cF82YmU1MDYxMzY2MmE0MDEwOTUwMzY2MWY2MjBlY2E1Mik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iN2Y0ZTY4NDI1NWY0MTAwYWFiMDQyMTgzMTBjNmZkZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjcyMDMsLTEyMi4zMzUwOTk3NDFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNzBlMjdiMjAxMzM4NDQ0NGEwOWNlYWE1Y2VmM2E4ODMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZTQ0ODcyOTk4YTIxNGM3NTk0YjUyMzBjOTg1ZmZiNDQgPSAkKCc8ZGl2IGlkPSJodG1sX2U0NDg3Mjk5OGEyMTRjNzU5NGI1MjMwYzk4NWZmYjQ0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IYWxsZXIgTGFrZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNzBlMjdiMjAxMzM4NDQ0NGEwOWNlYWE1Y2VmM2E4ODMuc2V0Q29udGVudChodG1sX2U0NDg3Mjk5OGEyMTRjNzU5NGI1MjMwYzk4NWZmYjQ0KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2I3ZjRlNjg0MjU1ZjQxMDBhYWIwNDIxODMxMGM2ZmRkLmJpbmRQb3B1cChwb3B1cF83MGUyN2IyMDEzMzg0NDQ0YTA5Y2VhYTVjZWYzYTg4Myk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mY2E5ZjI2MDJkYmU0YzdmYmVkMjhkNTU3ZGI5OWU0NyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjcwNiwtMTIyLjI5NzEyODgyN10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80OTU5MzVlZjc5OTU0OTQ4YmE2NWQyYjU4YTEwZjFmOSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85MmM1YTQyNTIzNWI0N2QyYWQ2YWIxYTUyMWMyNjA5YiA9ICQoJzxkaXYgaWQ9Imh0bWxfOTJjNWE0MjUyMzViNDdkMmFkNmFiMWE1MjFjMjYwOWIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1lYWRvd2Jyb29rPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80OTU5MzVlZjc5OTU0OTQ4YmE2NWQyYjU4YTEwZjFmOS5zZXRDb250ZW50KGh0bWxfOTJjNWE0MjUyMzViNDdkMmFkNmFiMWE1MjFjMjYwOWIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZmNhOWYyNjAyZGJlNGM3ZmJlZDI4ZDU1N2RiOTllNDcuYmluZFBvcHVwKHBvcHVwXzQ5NTkzNWVmNzk5NTQ5NDhiYTY1ZDJiNThhMTBmMWY5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzQ1ZmI5N2FmN2M3MjRiYWFhYzM1YmM4MmY3MzExOWZjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjA2OCwtMTIyLjMzOTk4ODg5MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82ZTkxNjk5OWI1YmQ0MGFmYmI1MGFlYTM3NzRmZDkxNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83OWNkNTU0ODEwZTI0Yjg5YjhmNDdmOGYyYTFkNTZhNiA9ICQoJzxkaXYgaWQ9Imh0bWxfNzljZDU1NDgxMGUyNGI4OWI4ZjQ3ZjhmMmExZDU2YTYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkRvd250b3duPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82ZTkxNjk5OWI1YmQ0MGFmYmI1MGFlYTM3NzRmZDkxNy5zZXRDb250ZW50KGh0bWxfNzljZDU1NDgxMGUyNGI4OWI4ZjQ3ZjhmMmExZDU2YTYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDVmYjk3YWY3YzcyNGJhYWFjMzViYzgyZjczMTE5ZmMuYmluZFBvcHVwKHBvcHVwXzZlOTE2OTk5YjViZDQwYWZiYjUwYWVhMzc3NGZkOTE3KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzViNjExMzc5NDRjMTRmOWVhNWJkMDY3NmVlZWJkOTRhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTgwMywtMTIyLjM4NzExNzk2Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9hYjg5NzVmMzQ5ODk0M2FiOGY0NzI5ZTRjNWIyN2Y5NyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9lNGY4MGMzOTE1MDk0MmM3OWRjMGRhNGM3NzJkY2E2NCA9ICQoJzxkaXYgaWQ9Imh0bWxfZTRmODBjMzkxNTA5NDJjNzlkYzBkYTRjNzcyZGNhNjQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkFkbWlyYWw8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2FiODk3NWYzNDk4OTQzYWI4ZjQ3MjllNGM1YjI3Zjk3LnNldENvbnRlbnQoaHRtbF9lNGY4MGMzOTE1MDk0MmM3OWRjMGRhNGM3NzJkY2E2NCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl81YjYxMTM3OTQ0YzE0ZjllYTViZDA2NzZlZWViZDk0YS5iaW5kUG9wdXAocG9wdXBfYWI4OTc1ZjM0OTg5NDNhYjhmNDcyOWU0YzViMjdmOTcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNGUyODFkZGQ0MDIyNDg1YTk2MzZiNjdjOTIzOGRlNGUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42OTksLTEyMi4zMzY3NjYzODVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMmFiZDA2MGIwOGM3NGQwNTg2M2U0YjBiM2M5OTJkMGEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOTRjZjFkZjE1ZGVhNGM0MGJjN2E5MDM2MDUyNWQ5ZWYgPSAkKCc8ZGl2IGlkPSJodG1sXzk0Y2YxZGYxNWRlYTRjNDBiYzdhOTAzNjA1MjVkOWVmIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ob3J0aCBDb2xsZWdlIFBhcms8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzJhYmQwNjBiMDhjNzRkMDU4NjNlNGIwYjNjOTkyZDBhLnNldENvbnRlbnQoaHRtbF85NGNmMWRmMTVkZWE0YzQwYmM3YTkwMzYwNTI1ZDllZik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80ZTI4MWRkZDQwMjI0ODVhOTYzNmI2N2M5MjM4ZGU0ZS5iaW5kUG9wdXAocG9wdXBfMmFiZDA2MGIwOGM3NGQwNTg2M2U0YjBiM2M5OTJkMGEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOTRhOGQyMWZiNmVhNDlkNWE5OGVhN2UzNWI1NGExNDIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42NDE0LC0xMjIuMzYwOTU3NzI4XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzgwNTNmMjA5ZDU0ZjQ4N2ZhMWI3MTU2YWVjYWE0N2E4ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzJlZjU3NzI1MGI2NDRjM2RhOGQwZDNiOWJiZTVkY2RjID0gJCgnPGRpdiBpZD0iaHRtbF8yZWY1NzcyNTBiNjQ0YzNkYThkMGQzYjliYmU1ZGNkYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UXVlZW4gQW5uZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfODA1M2YyMDlkNTRmNDg3ZmExYjcxNTZhZWNhYTQ3YTguc2V0Q29udGVudChodG1sXzJlZjU3NzI1MGI2NDRjM2RhOGQwZDNiOWJiZTVkY2RjKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzk0YThkMjFmYjZlYTQ5ZDVhOThlYTdlMzViNTRhMTQyLmJpbmRQb3B1cChwb3B1cF84MDUzZjIwOWQ1NGY0ODdmYTFiNzE1NmFlY2FhNDdhOCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iZDRhM2EyOGE3ZTc0OGE0YjE1ODJhMWZhOTEwYjU1OCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjU5MDUsLTEyMi4zMDE1NjM4ODJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZGRmMmQ0NWM3ZWU2NGM1YjhiYTNjYzExODE1M2RjZWEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOGZiMDk5MmE3NGE5NDg0N2E2NjIyNzA3Yjc0ZjQzZmEgPSAkKCc8ZGl2IGlkPSJodG1sXzhmYjA5OTJhNzRhOTQ4NDdhNjYyMjcwN2I3NGY0M2ZhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5BdGxhbnRpYzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZGRmMmQ0NWM3ZWU2NGM1YjhiYTNjYzExODE1M2RjZWEuc2V0Q29udGVudChodG1sXzhmYjA5OTJhNzRhOTQ4NDdhNjYyMjcwN2I3NGY0M2ZhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2JkNGEzYTI4YTdlNzQ4YTRiMTU4MmExZmE5MTBiNTU4LmJpbmRQb3B1cChwb3B1cF9kZGYyZDQ1YzdlZTY0YzViOGJhM2NjMTE4MTUzZGNlYSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81MWViM2FhMWE0NTU0ZmYzYTBjOTUxYWFiYjg4NTZiNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjYyMTYsLTEyMi4yODQ5NDAwNTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMjQ3ZWUwZWYzMTg5NDI1ZWE4OGZjZWJlYzAzYTcyMGIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZmJjNzUxZjFlMjZhNGU5MDgzOGU3MGQ4ZDdkZTUxNDEgPSAkKCc8ZGl2IGlkPSJodG1sX2ZiYzc1MWYxZTI2YTRlOTA4MzhlNzBkOGQ3ZGU1MTQxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5EZW5ueS1CbGFpbmU8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzI0N2VlMGVmMzE4OTQyNWVhODhmY2ViZWMwM2E3MjBiLnNldENvbnRlbnQoaHRtbF9mYmM3NTFmMWUyNmE0ZTkwODM4ZTcwZDhkN2RlNTE0MSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl81MWViM2FhMWE0NTU0ZmYzYTBjOTUxYWFiYjg4NTZiNC5iaW5kUG9wdXAocG9wdXBfMjQ3ZWUwZWYzMTg5NDI1ZWE4OGZjZWJlYzAzYTcyMGIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMzE1OWJjOGZlNzMxNGVhNWJkYTc2M2ZlYjE0YmExMmEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42MjE5LC0xMjIuMjk2MTE4NjA3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2VjMTM1MGQyOTMyYTRhNDQ5NDRhYjAxNjQ2NDk2NGE0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2NiMTJiNWVlMjRkYTQ1YWQ4YWVjNWQ1MDI2MmVmMTE4ID0gJCgnPGRpdiBpZD0iaHRtbF9jYjEyYjVlZTI0ZGE0NWFkOGFlYzVkNTAyNjJlZjExOCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TWFkaXNvbiBWYWxsZXk8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2VjMTM1MGQyOTMyYTRhNDQ5NDRhYjAxNjQ2NDk2NGE0LnNldENvbnRlbnQoaHRtbF9jYjEyYjVlZTI0ZGE0NWFkOGFlYzVkNTAyNjJlZjExOCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zMTU5YmM4ZmU3MzE0ZWE1YmRhNzYzZmViMTRiYTEyYS5iaW5kUG9wdXAocG9wdXBfZWMxMzUwZDI5MzJhNGE0NDk0NGFiMDE2NDY0OTY0YTQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOTYwYjA0NGMwNDA1NGRiOTk0NzYwM2JhNDNmYzk2NzIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42MDYsLTEyMi4zMDY0ODA1NTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfODgwOGM3ZDhmMWRhNDZkMjkxZTA3MDUwYzE2MGFjZTQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOWMzMmM5NDM0N2FkNGVmZTkzM2NlY2VkOTM1MWFiMWUgPSAkKCc8ZGl2IGlkPSJodG1sXzljMzJjOTQzNDdhZDRlZmU5MzNjZWNlZDkzNTFhYjFlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DZW50cmFsIERpc3RyaWN0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84ODA4YzdkOGYxZGE0NmQyOTFlMDcwNTBjMTYwYWNlNC5zZXRDb250ZW50KGh0bWxfOWMzMmM5NDM0N2FkNGVmZTkzM2NlY2VkOTM1MWFiMWUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOTYwYjA0NGMwNDA1NGRiOTk0NzYwM2JhNDNmYzk2NzIuYmluZFBvcHVwKHBvcHVwXzg4MDhjN2Q4ZjFkYTQ2ZDI5MWUwNzA1MGMxNjBhY2U0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2ZkYWM0MWQxZjQ4ODQwYTlhNGQxM2JhNjUzMjczMjAyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTk3NSwtMTIyLjMxOTQ4MjUyMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xMDMwNDc0ZWZkMzI0ZmE0OTVlYzlkMzM0YjE4MmUwYyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mOGE2NTA3NGZhNmI0ZmFhOWM5MjIyODk2NTQyMjJkOSA9ICQoJzxkaXYgaWQ9Imh0bWxfZjhhNjUwNzRmYTZiNGZhYTljOTIyMjg5NjU0MjIyZDkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkludGVybmF0aW9uYWwgRGlzdHJpY3Q8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzEwMzA0NzRlZmQzMjRmYTQ5NWVjOWQzMzRiMTgyZTBjLnNldENvbnRlbnQoaHRtbF9mOGE2NTA3NGZhNmI0ZmFhOWM5MjIyODk2NTQyMjJkOSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mZGFjNDFkMWY0ODg0MGE5YTRkMTNiYTY1MzI3MzIwMi5iaW5kUG9wdXAocG9wdXBfMTAzMDQ3NGVmZDMyNGZhNDk1ZWM5ZDMzNGIxODJlMGMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZmY2NWIyNTY3NTcyNDJiMzk5NGNiOTg4NzMzZTUwZGMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny41Njk4LC0xMjIuMzQ1NzI5NzQ3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzA5MzkwZDU1ZDJlNDRkNGJiZDg3ZTFmN2U3MmRhYTk4ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2VkZDk3Yjg3OWZlNzRiNzBiNmFmM2YyZWJkZmYyODNjID0gJCgnPGRpdiBpZD0iaHRtbF9lZGQ5N2I4NzlmZTc0YjcwYjZhZjNmMmViZGZmMjgzYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SW5kdXN0cmlhbCBEaXN0cmljdDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDkzOTBkNTVkMmU0NGQ0YmJkODdlMWY3ZTcyZGFhOTguc2V0Q29udGVudChodG1sX2VkZDk3Yjg3OWZlNzRiNzBiNmFmM2YyZWJkZmYyODNjKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2ZmNjViMjU2NzU3MjQyYjM5OTRjYjk4ODczM2U1MGRjLmJpbmRQb3B1cChwb3B1cF8wOTM5MGQ1NWQyZTQ0ZDRiYmQ4N2UxZjdlNzJkYWE5OCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iNTAzZGM5MDAzOTY0MDZkYmIxOWRlZjZkYjgyYzQyZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjY2MDMsLTEyMi4zMDYzMTE0MThdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNGYzY2M0MWRkMWIyNDY2MTkyYTIwMzU3ZDRkZWU4MzAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzY4MTJhZDE5YzY4NDQyM2E2YWE2YjBlOWQxMDY4MGUgPSAkKCc8ZGl2IGlkPSJodG1sXzc2ODEyYWQxOWM2ODQ0MjNhNmFhNmIwZTlkMTA2ODBlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Vbml2ZXJzaXR5IERpc3RyaWN0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80ZjNjYzQxZGQxYjI0NjYxOTJhMjAzNTdkNGRlZTgzMC5zZXRDb250ZW50KGh0bWxfNzY4MTJhZDE5YzY4NDQyM2E2YWE2YjBlOWQxMDY4MGUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjUwM2RjOTAwMzk2NDA2ZGJiMTlkZWY2ZGI4MmM0MmUuYmluZFBvcHVwKHBvcHVwXzRmM2NjNDFkZDFiMjQ2NjE5MmEyMDM1N2Q0ZGVlODMwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzkyYmJmNmQ3N2RiNzQyNThiMjVjYTgzNjFhNDAzMmI3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNzA1MiwtMTIyLjM3NjMyNDI0MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iZDQyNTU0NDk5ZGI0ZjU0ODRjZjA3ODkzYjNiZTNiYyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wMDJhZWZhM2Y3Y2Q0ZTllYTY2Nzc5OGI3MmZkNDJkOCA9ICQoJzxkaXYgaWQ9Imh0bWxfMDAyYWVmYTNmN2NkNGU5ZWE2Njc3OThiNzJmZDQyZDgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJsdWUgUmlkZ2U8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2JkNDI1NTQ0OTlkYjRmNTQ4NGNmMDc4OTNiM2JlM2JjLnNldENvbnRlbnQoaHRtbF8wMDJhZWZhM2Y3Y2Q0ZTllYTY2Nzc5OGI3MmZkNDJkOCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85MmJiZjZkNzdkYjc0MjU4YjI1Y2E4MzYxYTQwMzJiNy5iaW5kUG9wdXAocG9wdXBfYmQ0MjU1NDQ5OWRiNGY1NDg0Y2YwNzg5M2IzYmUzYmMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZWFjYjVjODNmYjExNGZhOWFlZmVjM2U5MzM4MDYxOWEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42NjY1LC0xMjIuMzc2MDUxODc3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2Q5MjRmZjY3OThiODRkMzE5MmVjNDRhNDVjMWFhZjM4ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzdlYmNhMTBlOWI5ZTRjZDc5NDEyNGIwNTY2YTcyYmZhID0gJCgnPGRpdiBpZD0iaHRtbF83ZWJjYTEwZTliOWU0Y2Q3OTQxMjRiMDU2NmE3MmJmYSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmFsbGFyZDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZDkyNGZmNjc5OGI4NGQzMTkyZWM0NGE0NWMxYWFmMzguc2V0Q29udGVudChodG1sXzdlYmNhMTBlOWI5ZTRjZDc5NDEyNGIwNTY2YTcyYmZhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2VhY2I1YzgzZmIxMTRmYTlhZWZlYzNlOTMzODA2MTlhLmJpbmRQb3B1cChwb3B1cF9kOTI0ZmY2Nzk4Yjg0ZDMxOTJlYzQ0YTQ1YzFhYWYzOCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9kMjc2OGM3MzRjMWQ0NmQyYmJiMTIwY2YxZmQxMTIyYSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjY0NTQsLTEyMi4zMTcxNDI3ODldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMzE0MjU5MzAxMjhhNDg1ZGI3NzA3MGRiODI4MjEzNzcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjI1MmQ5NTE1YmZhNGUzZmE0NTRkMjRjYTZlNzMxNzIgPSAkKCc8ZGl2IGlkPSJodG1sX2YyNTJkOTUxNWJmYTRlM2ZhNDU0ZDI0Y2E2ZTczMTcyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Qb3J0YWdlIEJheTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMzE0MjU5MzAxMjhhNDg1ZGI3NzA3MGRiODI4MjEzNzcuc2V0Q29udGVudChodG1sX2YyNTJkOTUxNWJmYTRlM2ZhNDU0ZDI0Y2E2ZTczMTcyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2QyNzY4YzczNGMxZDQ2ZDJiYmIxMjBjZjFmZDExMjJhLmJpbmRQb3B1cChwb3B1cF8zMTQyNTkzMDEyOGE0ODVkYjc3MDcwZGI4MjgyMTM3Nyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83YThlNTA1ZGI4Yzg0OTZiYTI2NTBhOGE3ZWQxMjQxYyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjUyNzMsLTEyMi4zNzEwMDU2NjRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMmMxY2ViNjVmNjE5NDJjOGJlNjA1NjZjMWM5MTUxYzkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMGRiNTliMWZjNDY2NGY4YjhkN2U2MjQ0MWVhOTMyNWUgPSAkKCc8ZGl2IGlkPSJodG1sXzBkYjU5YjFmYzQ2NjRmOGI4ZDdlNjI0NDFlYTkzMjVlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Sb3hoaWxsPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yYzFjZWI2NWY2MTk0MmM4YmU2MDU2NmMxYzkxNTFjOS5zZXRDb250ZW50KGh0bWxfMGRiNTliMWZjNDY2NGY4YjhkN2U2MjQ0MWVhOTMyNWUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfN2E4ZTUwNWRiOGM4NDk2YmEyNjUwYThhN2VkMTI0MWMuYmluZFBvcHVwKHBvcHVwXzJjMWNlYjY1ZjYxOTQyYzhiZTYwNTY2YzFjOTE1MWM5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y1YWY2OGI4ZmE4NjRkZWFiN2M4MjE0YjEzYzM3M2EyID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTYyNywtMTIyLjM2NDU5MTY4N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81MGRlY2Q2MTg2YWQ0YmE5YWQ1OWM5OGQxNjJjYWUwMCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81YjZhZmFmNWMwZTE0MDMxYWJlMDZjOWYwODU1ZDMyYiA9ICQoJzxkaXYgaWQ9Imh0bWxfNWI2YWZhZjVjMGUxNDAzMWFiZTA2YzlmMDg1NWQzMmIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5vcnRoIERlbHJpZGdlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81MGRlY2Q2MTg2YWQ0YmE5YWQ1OWM5OGQxNjJjYWUwMC5zZXRDb250ZW50KGh0bWxfNWI2YWZhZjVjMGUxNDAzMWFiZTA2YzlmMDg1NWQzMmIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjVhZjY4YjhmYTg2NGRlYWI3YzgyMTRiMTNjMzczYTIuYmluZFBvcHVwKHBvcHVwXzUwZGVjZDYxODZhZDRiYTlhZDU5Yzk4ZDE2MmNhZTAwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzVjNmFkYWZmY2UyYjQ2Mzk5M2JmZWU3Y2UxY2ViMDY0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTI4LC0xMjIuMzQzMDY0MDgyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzkzZjkwN2EzYWNjMDRmMTNiY2ZjNGYyNjNkOTg3YTgxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2ZjNGRiMTFhYzkzMTQwZmRhNzJlZjVhNDFkOGI5NmZjID0gJCgnPGRpdiBpZD0iaHRtbF9mYzRkYjExYWM5MzE0MGZkYTcyZWY1YTQxZDhiOTZmYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SGlnaGxhbmQgUGFyazwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOTNmOTA3YTNhY2MwNGYxM2JjZmM0ZjI2M2Q5ODdhODEuc2V0Q29udGVudChodG1sX2ZjNGRiMTFhYzkzMTQwZmRhNzJlZjVhNDFkOGI5NmZjKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzVjNmFkYWZmY2UyYjQ2Mzk5M2JmZWU3Y2UxY2ViMDY0LmJpbmRQb3B1cChwb3B1cF85M2Y5MDdhM2FjYzA0ZjEzYmNmYzRmMjYzZDk4N2E4MSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jMmEzYmZlMWE0MzI0ODNjOTViZjk0MmI0MmE0MDlmYSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjY1NywtMTIyLjM1MzI5NDA4OF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81NDgzMDg4ZDU3NzE0ZjkzODdmYjJlNzk4YzQ5NGE1NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zMDhkOTRiM2Q1ZjQ0NjUxYTFlMGJmMDhkZmEyMGQyOCA9ICQoJzxkaXYgaWQ9Imh0bWxfMzA4ZDk0YjNkNWY0NDY1MWExZTBiZjA4ZGZhMjBkMjgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZyZW1vbnQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzU0ODMwODhkNTc3MTRmOTM4N2ZiMmU3OThjNDk0YTU0LnNldENvbnRlbnQoaHRtbF8zMDhkOTRiM2Q1ZjQ0NjUxYTFlMGJmMDhkZmEyMGQyOCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jMmEzYmZlMWE0MzI0ODNjOTViZjk0MmI0MmE0MDlmYS5iaW5kUG9wdXAocG9wdXBfNTQ4MzA4OGQ1NzcxNGY5Mzg3ZmIyZTc5OGM0OTRhNTQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNzRiYzJjODlkYzYyNGQ5YWExNzljNjc2NzM0YzkzMTkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42NTkzLC0xMjIuMzMzNzQ5Mzc3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzMzZjIyMWNkZmE2MTRlMWQ5NDgwN2E5MjgwZjViZDliID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2VjZThiN2EwOGM0ZjQxZDk5NmMzZjM5YzlmNmM5NWQyID0gJCgnPGRpdiBpZD0iaHRtbF9lY2U4YjdhMDhjNGY0MWQ5OTZjM2YzOWM5ZjZjOTVkMiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+V2FsbGluZ2ZvcmQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzMzZjIyMWNkZmE2MTRlMWQ5NDgwN2E5MjgwZjViZDliLnNldENvbnRlbnQoaHRtbF9lY2U4YjdhMDhjNGY0MWQ5OTZjM2YzOWM5ZjZjOTVkMik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83NGJjMmM4OWRjNjI0ZDlhYTE3OWM2NzY3MzRjOTMxOS5iaW5kUG9wdXAocG9wdXBfMzNmMjIxY2RmYTYxNGUxZDk0ODA3YTkyODBmNWJkOWIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDZjYmQ2MDcyNDBiNDMxY2FjZmY2OWEyNWU0ZWZkY2YgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42NzIyLC0xMjIuMjcyNTI3MDddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNzc4YTliNTM1MGVlNDYyYmEzYTQwY2M1ZmUzN2UyN2UgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfODVmZGY0NzY5OWZhNGRkYjlkN2E3OTYyNzAzOTIwYWEgPSAkKCc8ZGl2IGlkPSJodG1sXzg1ZmRmNDc2OTlmYTRkZGI5ZDdhNzk2MjcwMzkyMGFhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IYXd0aG9ybmUgSGlsbHM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzc3OGE5YjUzNTBlZTQ2MmJhM2E0MGNjNWZlMzdlMjdlLnNldENvbnRlbnQoaHRtbF84NWZkZjQ3Njk5ZmE0ZGRiOWQ3YTc5NjI3MDM5MjBhYSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80NmNiZDYwNzI0MGI0MzFjYWNmZjY5YTI1ZTRlZmRjZi5iaW5kUG9wdXAocG9wdXBfNzc4YTliNTM1MGVlNDYyYmEzYTQwY2M1ZmUzN2UyN2UpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMGZmMTRmZWUxYWE1NDE1N2EzMDc4MGY0MzQ5NzNiYTAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42OTQyLC0xMjIuMzU1MjQ3NTFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZmZiYzc3MjRkZWVjNDIxY2IxN2QxODUxN2NiNmM3MjQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMWJiN2JiZjdlZmEwNGU5ZWIyYWFhODg5MmVmOTc3Y2IgPSAkKCc8ZGl2IGlkPSJodG1sXzFiYjdiYmY3ZWZhMDRlOWViMmFhYTg4OTJlZjk3N2NiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5HcmVlbndvb2Q8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2ZmYmM3NzI0ZGVlYzQyMWNiMTdkMTg1MTdjYjZjNzI0LnNldENvbnRlbnQoaHRtbF8xYmI3YmJmN2VmYTA0ZTllYjJhYWE4ODkyZWY5NzdjYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wZmYxNGZlZTFhYTU0MTU3YTMwNzgwZjQzNDk3M2JhMC5iaW5kUG9wdXAocG9wdXBfZmZiYzc3MjRkZWVjNDIxY2IxN2QxODUxN2NiNmM3MjQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOTAxMGEwN2IyMDcwNDA4ZWJjMWQxOTYxMmMzYjVjM2YgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny41OTk2LC0xMjIuMjkwNjY1NDc1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzg3MGUxM2ZkYzI2MjQzYmJhZTk4Y2U1YzQzNDE3ZGM1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzFiMmI4MTI1NTVkMjQ0NTM4MGRjNDA2MDEzMDAyZWFjID0gJCgnPGRpdiBpZD0iaHRtbF8xYjJiODEyNTU1ZDI0NDUzODBkYzQwNjAxMzAwMmVhYyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TGVzY2hpPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84NzBlMTNmZGMyNjI0M2JiYWU5OGNlNWM0MzQxN2RjNS5zZXRDb250ZW50KGh0bWxfMWIyYjgxMjU1NWQyNDQ1MzgwZGM0MDYwMTMwMDJlYWMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOTAxMGEwN2IyMDcwNDA4ZWJjMWQxOTYxMmMzYjVjM2YuYmluZFBvcHVwKHBvcHVwXzg3MGUxM2ZkYzI2MjQzYmJhZTk4Y2U1YzQzNDE3ZGM1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzYyYjE1NzI4YTllNTRjMmI5ZGQwMzNiMTA0MTFjMjA2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTU1NiwtMTIyLjI4NDI4MTMwN10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80NmRlOTkyNjgxNWU0NzExYWFmMDMxY2U0YjQ4ZTdiNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9kYzkyZmU1YzJmOTk0YTI3OGI1ZDlkYzJiNTdkZTIwNyA9ICQoJzxkaXYgaWQ9Imh0bWxfZGM5MmZlNWMyZjk5NGEyNzhiNWQ5ZGMyYjU3ZGUyMDciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNvbHVtYmlhIENpdHk8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzQ2ZGU5OTI2ODE1ZTQ3MTFhYWYwMzFjZTRiNDhlN2I0LnNldENvbnRlbnQoaHRtbF9kYzkyZmU1YzJmOTk0YTI3OGI1ZDlkYzJiNTdkZTIwNyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82MmIxNTcyOGE5ZTU0YzJiOWRkMDMzYjEwNDExYzIwNi5iaW5kUG9wdXAocG9wdXBfNDZkZTk5MjY4MTVlNDcxMWFhZjAzMWNlNGI0OGU3YjQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDc1ZGU4ZjRlZjI3NDkxM2EzOWEyN2I3MjNmNzc0MDEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny41NDYzLC0xMjIuMzUzMzUxNTA1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2ZjOTVmYzYwYTVkODQ3MThiMGQwZjAzNzI0YjQ3N2YwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2NhZDk2NzZlYjY1ZjQwMTE5MTBiNzI3NmY0ZDZmYjcxID0gJCgnPGRpdiBpZD0iaHRtbF9jYWQ5Njc2ZWI2NWY0MDExOTEwYjcyNzZmNGQ2ZmI3MSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Uml2ZXJ2aWV3PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mYzk1ZmM2MGE1ZDg0NzE4YjBkMGYwMzcyNGI0NzdmMC5zZXRDb250ZW50KGh0bWxfY2FkOTY3NmViNjVmNDAxMTkxMGI3Mjc2ZjRkNmZiNzEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDc1ZGU4ZjRlZjI3NDkxM2EzOWEyN2I3MjNmNzc0MDEuYmluZFBvcHVwKHBvcHVwX2ZjOTVmYzYwYTVkODQ3MThiMGQwZjAzNzI0YjQ3N2YwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzc3NjA4ZDUxM2JjNTRiMzc5Y2VmMTI0MDJlZTI5ZjI0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjQwNywtMTIyLjMwMzgxNTcyMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80ODEzZTc5ZWRlN2M0NzZkOTI2YWE0NzI5YWRiOWUwMCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83YjdiOWQzOTExNWI0YjU5YjNiNGUzMDRjN2FkNWJlNiA9ICQoJzxkaXYgaWQ9Imh0bWxfN2I3YjlkMzkxMTViNGI1OWIzYjRlMzA0YzdhZDViZTYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1vbnRsYWtlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80ODEzZTc5ZWRlN2M0NzZkOTI2YWE0NzI5YWRiOWUwMC5zZXRDb250ZW50KGh0bWxfN2I3YjlkMzkxMTViNGI1OWIzYjRlMzA0YzdhZDViZTYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzc2MDhkNTEzYmM1NGIzNzljZWYxMjQwMmVlMjlmMjQuYmluZFBvcHVwKHBvcHVwXzQ4MTNlNzllZGU3YzQ3NmQ5MjZhYTQ3MjlhZGI5ZTAwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzBiMzRhMzEzYTQ3YzRiNjc4Y2YwMGQ1NGI5YjM2YzRlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjgwMiwtMTIyLjMzMzg2OTk1OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83MTgxZTEzNWE1Zjk0NzNmODg0ZGJlYjNhYzlmNDkwMyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81YWUyMWNkNjY1OTg0MmY3YmUzOWFlOGFlMjU4ZTEzYiA9ICQoJzxkaXYgaWQ9Imh0bWxfNWFlMjFjZDY2NTk4NDJmN2JlMzlhZThhZTI1OGUxM2IiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkdyZWVuIExha2U8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzcxODFlMTM1YTVmOTQ3M2Y4ODRkYmViM2FjOWY0OTAzLnNldENvbnRlbnQoaHRtbF81YWUyMWNkNjY1OTg0MmY3YmUzOWFlOGFlMjU4ZTEzYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wYjM0YTMxM2E0N2M0YjY3OGNmMDBkNTRiOWIzNmM0ZS5iaW5kUG9wdXAocG9wdXBfNzE4MWUxMzVhNWY5NDczZjg4NGRiZWIzYWM5ZjQ5MDMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYTZiMzkwM2MyZmFiNDRjZTk2YTA3NjZiZjJjMmE4NzQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny43MjY2LC0xMjIuMzAyNTg4NzUxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2RlNDg2YjliMjMyNjQ4NjE4NGEwMzAzZDgxMzUzMzhmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzJiM2UxNDc3NTgxYjRkNTFhOTliYWIxMjA0ZTJjNWYzID0gJCgnPGRpdiBpZD0iaHRtbF8yYjNlMTQ3NzU4MWI0ZDUxYTk5YmFiMTIwNGUyYzVmMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+T2x5bXBpYyBIaWxsczwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZGU0ODZiOWIyMzI2NDg2MTg0YTAzMDNkODEzNTMzOGYuc2V0Q29udGVudChodG1sXzJiM2UxNDc3NTgxYjRkNTFhOTliYWIxMjA0ZTJjNWYzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2E2YjM5MDNjMmZhYjQ0Y2U5NmEwNzY2YmYyYzJhODc0LmJpbmRQb3B1cChwb3B1cF9kZTQ4NmI5YjIzMjY0ODYxODRhMDMwM2Q4MTM1MzM4Zik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84YWY3NDhkZmUwZGM0Nzk5ODEzNzIyOWY2MTFkODkwMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjY3MzUsLTEyMi4zMDAzODkyNzldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZjY2MzFjNjNmMjU5NGU2NjgwNmRlMGUwNWM1YWY0MTggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOWI1NjA0ZWY5YTRkNDE4NmIwYzRlMDA0M2Y1MzlmNTkgPSAkKCc8ZGl2IGlkPSJodG1sXzliNTYwNGVmOWE0ZDQxODZiMGM0ZTAwNDNmNTM5ZjU5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5SYXZlbm5hPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mNjYzMWM2M2YyNTk0ZTY2ODA2ZGUwZTA1YzVhZjQxOC5zZXRDb250ZW50KGh0bWxfOWI1NjA0ZWY5YTRkNDE4NmIwYzRlMDA0M2Y1MzlmNTkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOGFmNzQ4ZGZlMGRjNDc5OTgxMzcyMjlmNjExZDg5MDIuYmluZFBvcHVwKHBvcHVwX2Y2NjMxYzYzZjI1OTRlNjY4MDZkZTBlMDVjNWFmNDE4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzBmNWE5NTE0NjhiZjRiNGViNThhYmZlZDQ1OTA0NjllID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjU4OCwtMTIyLjI3ODEzMTkzMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9hMWQ3ZmU1ZjQ1M2I0MDc5OTczMWM1M2I5NjZmODI1MiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81N2QzNDk5YmRjMTQ0NjgzYTVkNWJmYjNhNGJjMmE0YSA9ICQoJzxkaXYgaWQ9Imh0bWxfNTdkMzQ5OWJkYzE0NDY4M2E1ZDViZmIzYTRiYzJhNGEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxhdXJlbGh1cnN0PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hMWQ3ZmU1ZjQ1M2I0MDc5OTczMWM1M2I5NjZmODI1Mi5zZXRDb250ZW50KGh0bWxfNTdkMzQ5OWJkYzE0NDY4M2E1ZDViZmIzYTRiYzJhNGEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMGY1YTk1MTQ2OGJmNGI0ZWI1OGFiZmVkNDU5MDQ2OWUuYmluZFBvcHVwKHBvcHVwX2ExZDdmZTVmNDUzYjQwNzk5NzMxYzUzYjk2NmY4MjUyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzAyYmNlMDM0Y2M3YjQxMDhiYWY3NDhhMDA0NDBmMzA0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjk2MSwtMTIyLjM3MTM5OTI2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzdhNzY1ZGRjYTJkMDQwZjM4MmIxOTVmMjE5YTczZTdmID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzk1NWVjMGZkNjMyZTQ1ODNiZGU1NGNhZGQ2NzgzOTU3ID0gJCgnPGRpdiBpZD0iaHRtbF85NTVlYzBmZDYzMmU0NTgzYmRlNTRjYWRkNjc4Mzk1NyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q3Jvd24gSGlsbDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfN2E3NjVkZGNhMmQwNDBmMzgyYjE5NWYyMTlhNzNlN2Yuc2V0Q29udGVudChodG1sXzk1NWVjMGZkNjMyZTQ1ODNiZGU1NGNhZGQ2NzgzOTU3KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzAyYmNlMDM0Y2M3YjQxMDhiYWY3NDhhMDA0NDBmMzA0LmJpbmRQb3B1cChwb3B1cF83YTc2NWRkY2EyZDA0MGYzODJiMTk1ZjIxOWE3M2U3Zik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl85NjRlMjczNWFmZWY0OTY3YWEyZmU5ZjQ2MjE0NjAzMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjYxMjksLTEyMi4yODg3NzI2M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wMmFkY2MwNThiMWE0NTU4YjIxNmQxODg4MDhhYzA1MiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wYjk4ZDAzZmQxY2M0ZjBkOWNkM2Q0MjNkODY5ODVjYiA9ICQoJzxkaXYgaWQ9Imh0bWxfMGI5OGQwM2ZkMWNjNGYwZDljZDNkNDIzZDg2OTg1Y2IiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1hZHJvbmE8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzAyYWRjYzA1OGIxYTQ1NThiMjE2ZDE4ODgwOGFjMDUyLnNldENvbnRlbnQoaHRtbF8wYjk4ZDAzZmQxY2M0ZjBkOWNkM2Q0MjNkODY5ODVjYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85NjRlMjczNWFmZWY0OTY3YWEyZmU5ZjQ2MjE0NjAzMi5iaW5kUG9wdXAocG9wdXBfMDJhZGNjMDU4YjFhNDU1OGIyMTZkMTg4ODA4YWMwNTIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNDNjNzM4OGZhNzdlNDg2ZDhlNDk0ZjhlZjZiYzVjNDIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny43MTk3LC0xMjIuMzY2NzQyOTIyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2I3NmJjZWJmZDIyNzQxM2ViOTJjYjZhYjY0NGEwYmVlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2JkZTEyYTMyYjJiNjRiMWJhZGFjMGFkMWQwNTA3ZmRhID0gJCgnPGRpdiBpZD0iaHRtbF9iZGUxMmEzMmIyYjY0YjFiYWRhYzBhZDFkMDUwN2ZkYSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnJvYWR2aWV3PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iNzZiY2ViZmQyMjc0MTNlYjkyY2I2YWI2NDRhMGJlZS5zZXRDb250ZW50KGh0bWxfYmRlMTJhMzJiMmI2NGIxYmFkYWMwYWQxZDA1MDdmZGEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDNjNzM4OGZhNzdlNDg2ZDhlNDk0ZjhlZjZiYzVjNDIuYmluZFBvcHVwKHBvcHVwX2I3NmJjZWJmZDIyNzQxM2ViOTJjYjZhYjY0NGEwYmVlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzY3ODkwNzYwMTQ2ZDRhY2JhMjdlYjgwNDFlYzFkYTNhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNzE5NSwtMTIyLjM1MDE2MTcxNl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85YmU1OTMzNTQ3ODI0NDU3ODRmMDNhOTVlZjNiMzZlYyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jNzAzODgxMGM2OTQ0ZDkwYTQ4OWM2ZmZmNzU4YTkzZSA9ICQoJzxkaXYgaWQ9Imh0bWxfYzcwMzg4MTBjNjk0NGQ5MGE0ODljNmZmZjc1OGE5M2UiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJpdHRlciBMYWtlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85YmU1OTMzNTQ3ODI0NDU3ODRmMDNhOTVlZjNiMzZlYy5zZXRDb250ZW50KGh0bWxfYzcwMzg4MTBjNjk0NGQ5MGE0ODljNmZmZjc1OGE5M2UpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNjc4OTA3NjAxNDZkNGFjYmEyN2ViODA0MWVjMWRhM2EuYmluZFBvcHVwKHBvcHVwXzliZTU5MzM1NDc4MjQ0NTc4NGYwM2E5NWVmM2IzNmVjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzUwYWYzY2IyNmRhNjQyZTQ5Y2Y0ZWNjOGE3NjdmNTg3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTUwNiwtMTIyLjI2MTUyMzAwOF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81NDc1ODU0ZDFhZDA0YTE3ODI2ZDg4NTNiZGQ0MGFiNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iNjFlZjZkZGIxZGI0OTQ0Yjg1OWU5MGY5MWY0NTQwMCA9ICQoJzxkaXYgaWQ9Imh0bWxfYjYxZWY2ZGRiMWRiNDk0NGI4NTllOTBmOTFmNDU0MDAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlNld2FyZCBQYXJrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81NDc1ODU0ZDFhZDA0YTE3ODI2ZDg4NTNiZGQ0MGFiNC5zZXRDb250ZW50KGh0bWxfYjYxZWY2ZGRiMWRiNDk0NGI4NTllOTBmOTFmNDU0MDApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNTBhZjNjYjI2ZGE2NDJlNDljZjRlY2M4YTc2N2Y1ODcuYmluZFBvcHVwKHBvcHVwXzU0NzU4NTRkMWFkMDRhMTc4MjZkODg1M2JkZDQwYWI0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y5NWU4Mjk0ZjJlYjRlMjQ4N2FkZTQwYWYzMDI0ODc4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjk2MSwtMTIyLjM4MjE4MTg3Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xODBmODhkODEzNDc0YzBkYjhiMDZhMTdkNGM3NTg5MCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iNWRhMjFmOGJjMmM0OWFjYTJiMTY2OTI5NzVmYWM0NyA9ICQoJzxkaXYgaWQ9Imh0bWxfYjVkYTIxZjhiYzJjNDlhY2EyYjE2NjkyOTc1ZmFjNDciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk9seW1waWMgTWFub3I8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzE4MGY4OGQ4MTM0NzRjMGRiOGIwNmExN2Q0Yzc1ODkwLnNldENvbnRlbnQoaHRtbF9iNWRhMjFmOGJjMmM0OWFjYTJiMTY2OTI5NzVmYWM0Nyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9mOTVlODI5NGYyZWI0ZTI0ODdhZGU0MGFmMzAyNDg3OC5iaW5kUG9wdXAocG9wdXBfMTgwZjg4ZDgxMzQ3NGMwZGI4YjA2YTE3ZDRjNzU4OTApOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOGQyNmFhNmU3ZmUzNDJlOGE0Y2JjM2ZkYWI1N2IxZjIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42NzE4LC0xMjIuMjg2MDY5MTk3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogImJsdWUiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMzE4NmNjIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2VhYzBhYzI5NWZhYjRiN2RiODkwNzdjZTRlYmM0MDc0KTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzZjODIxZWQ4ZjEwNDQ0ZjhiYmFiNzcyZmYzZjcyZTgwID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzE4YTFiZWVjMDNlOTRiYmI4ZWE3YmZlOWY3ODA1OWMzID0gJCgnPGRpdiBpZD0iaHRtbF8xOGExYmVlYzAzZTk0YmJiOGVhN2JmZTlmNzgwNTljMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnJ5YW50PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82YzgyMWVkOGYxMDQ0NGY4YmJhYjc3MmZmM2Y3MmU4MC5zZXRDb250ZW50KGh0bWxfMThhMWJlZWMwM2U5NGJiYjhlYTdiZmU5Zjc4MDU5YzMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOGQyNmFhNmU3ZmUzNDJlOGE0Y2JjM2ZkYWI1N2IxZjIuYmluZFBvcHVwKHBvcHVwXzZjODIxZWQ4ZjEwNDQ0ZjhiYmFiNzcyZmYzZjcyZTgwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzcyNmVlYWM4YTMwYzQ4Zjg5NWYwYjEzZTNkZGYzYTNhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTI2NSwtMTIyLjM2MDgwMzUwM10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9hMjE1MmRkZTljYTk0NjE0OTQyZmZlNTQ4NzQwYmM5YyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mYjYzOTE0ZjNiZDg0NmQ4YTgwODUwYTc2YTkwNjdhNCA9ICQoJzxkaXYgaWQ9Imh0bWxfZmI2MzkxNGYzYmQ4NDZkOGE4MDg1MGE3NmE5MDY3YTQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlNvdXRoIERlbHJpZGdlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hMjE1MmRkZTljYTk0NjE0OTQyZmZlNTQ4NzQwYmM5Yy5zZXRDb250ZW50KGh0bWxfZmI2MzkxNGYzYmQ4NDZkOGE4MDg1MGE3NmE5MDY3YTQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzI2ZWVhYzhhMzBjNDhmODk1ZjBiMTNlM2RkZjNhM2EuYmluZFBvcHVwKHBvcHVwX2EyMTUyZGRlOWNhOTQ2MTQ5NDJmZmU1NDg3NDBiYzljKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2UwMDZjYmFmNjcyNTRkODBhY2VhOWRjNGFhZjBmZGQ0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNzI0MiwtMTIyLjI4NzI5MjhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfY2IyMmZkOWJjNjM1NGYwMjlmN2EzZTZhM2RmYjQ4YjYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMzhkMjQ0ZWYyNjFjNDU3M2FhZjViY2M0NzNjMjIwNTAgPSAkKCc8ZGl2IGlkPSJodG1sXzM4ZDI0NGVmMjYxYzQ1NzNhYWY1YmNjNDczYzIyMDUwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DZWRhciBQYXJrPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jYjIyZmQ5YmM2MzU0ZjAyOWY3YTNlNmEzZGZiNDhiNi5zZXRDb250ZW50KGh0bWxfMzhkMjQ0ZWYyNjFjNDU3M2FhZjViY2M0NzNjMjIwNTApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZTAwNmNiYWY2NzI1NGQ4MGFjZWE5ZGM0YWFmMGZkZDQuYmluZFBvcHVwKHBvcHVwX2NiMjJmZDliYzYzNTRmMDI5ZjdhM2U2YTNkZmI0OGI2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzU2MWU0NjcyY2VlNDQzMGI5ODkxMWQyN2Y2MDg0MDQ0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNzEwMywtMTIyLjMwNDkzNjUwNl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF84MjRiYTU4YWZkMDQ0ZWU5YTM4NTc3MGRhYTU4YWM2ZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8yZjkxMTdmYTNkZmM0ZjgyYWZjN2JjNGEyOGFmOTUxNSA9ICQoJzxkaXYgaWQ9Imh0bWxfMmY5MTE3ZmEzZGZjNGY4MmFmYzdiYzRhMjhhZjk1MTUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlZpY3RvcnkgSGVpZ2h0czwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfODI0YmE1OGFmZDA0NGVlOWEzODU3NzBkYWE1OGFjNmYuc2V0Q29udGVudChodG1sXzJmOTExN2ZhM2RmYzRmODJhZmM3YmM0YTI4YWY5NTE1KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzU2MWU0NjcyY2VlNDQzMGI5ODkxMWQyN2Y2MDg0MDQ0LmJpbmRQb3B1cChwb3B1cF84MjRiYTU4YWZkMDQ0ZWU5YTM4NTc3MGRhYTU4YWM2Zik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mNzg2Zjc2NDVlM2Q0YzQ2ODY0NDZjYmU0YThmZGYyNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjY1MTMsLTEyMi40MDY5NDQwOTJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYTU0MDg3MzA5MjcxNGU2NjkyNzQwOTFmNDY2MWYxNTggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZGQ1YmY2M2Y0ZDg5NGNkYjlmZmMyYzIwOGU5ZmRiOWQgPSAkKCc8ZGl2IGlkPSJodG1sX2RkNWJmNjNmNGQ4OTRjZGI5ZmZjMmMyMDhlOWZkYjlkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5NYWdub2xpYTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYTU0MDg3MzA5MjcxNGU2NjkyNzQwOTFmNDY2MWYxNTguc2V0Q29udGVudChodG1sX2RkNWJmNjNmNGQ4OTRjZGI5ZmZjMmMyMDhlOWZkYjlkKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2Y3ODZmNzY0NWUzZDRjNDY4NjQ0NmNiZTRhOGZkZjI3LmJpbmRQb3B1cChwb3B1cF9hNTQwODczMDkyNzE0ZTY2OTI3NDA5MWY0NjYxZjE1OCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mODg1NDZjMjVhMjg0YWZmOTZjNWI2ODY3OWNmZWI5YyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjY3MzMsLTEyMi4zNTMxODc1NThdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMTY0M2NhYTA4MzE3NGY2ZjkzYzk2MmZlYzg1YjBiOTUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfODgzM2MyM2YyMzk5NDFlNGIzNzNiZjQzZDExMDkzNTAgPSAkKCc8ZGl2IGlkPSJodG1sXzg4MzNjMjNmMjM5OTQxZTRiMzczYmY0M2QxMTA5MzUwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5QaGlubmV5IFJpZGdlPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xNjQzY2FhMDgzMTc0ZjZmOTNjOTYyZmVjODViMGI5NS5zZXRDb250ZW50KGh0bWxfODgzM2MyM2YyMzk5NDFlNGIzNzNiZjQzZDExMDkzNTApOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjg4NTQ2YzI1YTI4NGFmZjk2YzViNjg2NzljZmViOWMuYmluZFBvcHVwKHBvcHVwXzE2NDNjYWEwODMxNzRmNmY5M2M5NjJmZWM4NWIwYjk1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y3ZGY3NDUzYzI3ZjQ3MDU4OTYwNjllOWNjZDllNDZmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTUzNiwtMTIyLjM5MTg5MDcwNl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9lMTZmYjFjNDdkMjI0OTlmYWNjYjEwNDkxODRmMGEwNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81MTY2NDgyMjYxMWY0MWY3YTQ5NDQ0ZmM5NmQ5YWRkNiA9ICQoJzxkaXYgaWQ9Imh0bWxfNTE2NjQ4MjI2MTFmNDFmN2E0OTQ0NGZjOTZkOWFkZDYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldlc3QgU2VhdHRsZTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZTE2ZmIxYzQ3ZDIyNDk5ZmFjY2IxMDQ5MTg0ZjBhMDQuc2V0Q29udGVudChodG1sXzUxNjY0ODIyNjExZjQxZjdhNDk0NDRmYzk2ZDlhZGQ2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2Y3ZGY3NDUzYzI3ZjQ3MDU4OTYwNjllOWNjZDllNDZmLmJpbmRQb3B1cChwb3B1cF9lMTZmYjFjNDdkMjI0OTlmYWNjYjEwNDkxODRmMGEwNCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80MTVkYjZlNTQ3NDQ0M2M2ODUxM2E5YWE1MWIxZDM1YiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjYxNDgsLTEyMi4zNDgzMDMwMTJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNGE4YzQxYWFjNzk0NGM0ZGEzOWE3N2M1Mjk1MTRiMzkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjdiNDY5NmNjMTcxNGVlODk5NzU2MDVlMmQ0ODBiMDYgPSAkKCc8ZGl2IGlkPSJodG1sX2Y3YjQ2OTZjYzE3MTRlZTg5OTc1NjA1ZTJkNDgwYjA2IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5CZWxsdG93bjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNGE4YzQxYWFjNzk0NGM0ZGEzOWE3N2M1Mjk1MTRiMzkuc2V0Q29udGVudChodG1sX2Y3YjQ2OTZjYzE3MTRlZTg5OTc1NjA1ZTJkNDgwYjA2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzQxNWRiNmU1NDc0NDQzYzY4NTEzYTlhYTUxYjFkMzViLmJpbmRQb3B1cChwb3B1cF80YThjNDFhYWM3OTQ0YzRkYTM5YTc3YzUyOTUxNGIzOSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl81OWNlMzExNzUzM2Q0OGZjOWQ3ZmIwYjJkM2VmMTNhMiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjU4MzgsLTEyMi40MDIwMzUzNzddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiYmx1ZSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMzMTg2Y2MiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfZWFjMGFjMjk1ZmFiNGI3ZGI4OTA3N2NlNGViYzQwNzQpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjQzZWEzZDUzYzVhNDc2NDkxMTQ2YmU2YzQ0NWE2ZmMgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZTAwYzIxYThjN2M1NGNkZmFlZTNiZTc2ZmI3YjZiZmEgPSAkKCc8ZGl2IGlkPSJodG1sX2UwMGMyMWE4YzdjNTRjZGZhZWUzYmU3NmZiN2I2YmZhIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5BbGtpPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82NDNlYTNkNTNjNWE0NzY0OTExNDZiZTZjNDQ1YTZmYy5zZXRDb250ZW50KGh0bWxfZTAwYzIxYThjN2M1NGNkZmFlZTNiZTc2ZmI3YjZiZmEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNTljZTMxMTc1MzNkNDhmYzlkN2ZiMGIyZDNlZjEzYTIuYmluZFBvcHVwKHBvcHVwXzY0M2VhM2Q1M2M1YTQ3NjQ5MTE0NmJlNmM0NDVhNmZjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzM5YTM1ZjM4YzZjMDQyMTdhZDcxNzQzNmQyMjZlNTBlID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTQwMywtMTIyLjMxNjM3MDg1NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICJibHVlIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzMxODZjYyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9lYWMwYWMyOTVmYWI0YjdkYjg5MDc3Y2U0ZWJjNDA3NCk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83MDI2NmFiNGYxYTM0YmExYTQ5NWZiMzFhYjczM2JhOCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jNWVlOTViMGJmYWU0MzE3YWFmODQ0MmQwYjAwOTFmNyA9ICQoJzxkaXYgaWQ9Imh0bWxfYzVlZTk1YjBiZmFlNDMxN2FhZjg0NDJkMGIwMDkxZjciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkdlb3JnZXRvd248L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzcwMjY2YWI0ZjFhMzRiYTFhNDk1ZmIzMWFiNzMzYmE4LnNldENvbnRlbnQoaHRtbF9jNWVlOTViMGJmYWU0MzE3YWFmODQ0MmQwYjAwOTFmNyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zOWEzNWYzOGM2YzA0MjE3YWQ3MTc0MzZkMjI2ZTUwZS5iaW5kUG9wdXAocG9wdXBfNzAyNjZhYjRmMWEzNGJhMWE0OTVmYjMxYWI3MzNiYTgpOwoKICAgICAgICAgICAgCiAgICAgICAgCjwvc2NyaXB0Pg==\" 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 0x7ff5740c6b00>"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"seattlex = 47.606209\n",
"seattley = -122.332069\n",
"\n",
"seattle_map = folium.Map(location=[seattlex, seattley], zoom_start=10)\n",
"\n",
"for lat, lng, label in zip(areas['latitude'], areas['longitude'], areas['name']):\n",
" label = folium.Popup(label, parse_html=True)\n",
" folium.CircleMarker([lat, lng],\n",
" radius=5,\n",
" popup=label,\n",
" color='blue',\n",
" fill=True,\n",
" fill_color='#3186cc',\n",
" fill_opacity=0.7,\n",
" parse_html=False).add_to(seattle_map)\n",
"\n",
"seattle_map"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Pull Venue Information from Foursquare"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"# @hidden_cell\n",
"CLIENT_ID = 'my_id'\n",
"CLIENT_SECRET = 'my_secret'\n",
"VERSION = '20180604'\n",
"radius = 500\n",
"LIMIT = 30"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"def getNearbyVenues(names, latitudes, longitudes, radius=500):\n",
" \n",
" venues_list=[]\n",
" for name, lat, lng in zip(names, latitudes, longitudes):\n",
" print(name)\n",
" \n",
" # create the API request URL\n",
" url = 'https://api.foursquare.com/v2/venues/explore?&client_id={}&client_secret={}&v={}&ll={},{}&radius={}&limit={}'.format(\n",
" CLIENT_ID, \n",
" CLIENT_SECRET, \n",
" VERSION, \n",
" lat, \n",
" lng, \n",
" radius, \n",
" LIMIT)\n",
" \n",
" # make the GET request\n",
" results = requests.get(url).json()[\"response\"][\"groups\"][0][\"items\"]\n",
" \n",
" # return only relevant information for each nearby venue\n",
" venues_list.append([(\n",
" name, \n",
" lat, \n",
" lng, \n",
" v['venue']['name'], \n",
" v['venue']['location']['lat'], \n",
" v['venue']['location']['lng'], \n",
" v['venue']['categories'][0]['name']) for v in results])\n",
"\n",
" nearby_venues = pd.DataFrame([item for venue_list in venues_list for item in venue_list])\n",
" nearby_venues.columns = ['Name', \n",
" 'Name Latitude', \n",
" 'Name Longitude', \n",
" 'Venue', \n",
" 'Venue Latitude', \n",
" 'Venue Longitude', \n",
" 'Venue Category']\n",
" \n",
" return(nearby_venues)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Pinehurst\n",
"Brighton\n",
"Whittier Heights\n",
"Windermere\n",
"Loyal Heights\n",
"North Beach\n",
"Roosevelt\n",
"Pioneer Square\n",
"Westlake\n",
"Sand Point\n",
"South Park\n",
"Maple Leaf\n",
"Sunset Hill\n",
"Beacon Hill\n",
"Rainier Beach\n",
"Broadmoor\n",
"Madison Park\n",
"High Point\n",
"Interbay\n",
"View Ridge\n",
"Matthews Beach\n",
"Wedgwood\n",
"South Lake Union\n",
"Fauntleroy\n",
"Capitol Hill\n",
"First Hill\n",
"Arbor Heights\n",
"Northgate\n",
"Lower Queen Anne\n",
"Eastlake\n",
"Mount Baker\n",
"Haller Lake\n",
"Meadowbrook\n",
"Downtown\n",
"Admiral\n",
"North College Park\n",
"Queen Anne\n",
"Atlantic\n",
"Denny-Blaine\n",
"Madison Valley\n",
"Central District\n",
"International District\n",
"Industrial District\n",
"University District\n",
"Blue Ridge\n",
"Ballard\n",
"Portage Bay\n",
"Roxhill\n",
"North Delridge\n",
"Highland Park\n",
"Fremont\n",
"Wallingford\n",
"Hawthorne Hills\n",
"Greenwood\n",
"Leschi\n",
"Columbia City\n",
"Riverview\n",
"Montlake\n",
"Green Lake\n",
"Olympic Hills\n",
"Ravenna\n",
"Laurelhurst\n",
"Crown Hill\n",
"Madrona\n",
"Broadview\n",
"Bitter Lake\n",
"Seward Park\n",
"Olympic Manor\n",
"Bryant\n",
"South Delridge\n",
"Cedar Park\n",
"Victory Heights\n",
"Magnolia\n",
"Phinney Ridge\n",
"West Seattle\n",
"Belltown\n",
"Alki\n",
"Georgetown\n"
]
}
],
"source": [
"seattle_venus = getNearbyVenues(names=areas['name'],\n",
" latitudes=areas['latitude'],\n",
" longitudes=areas['longitude']\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>name</th>\n",
" <th>ATM</th>\n",
" <th>African Restaurant</th>\n",
" <th>American Restaurant</th>\n",
" <th>Amphitheater</th>\n",
" <th>Antique Shop</th>\n",
" <th>Arcade</th>\n",
" <th>Art Gallery</th>\n",
" <th>Art Museum</th>\n",
" <th>Arts &amp; Crafts Store</th>\n",
" <th>...</th>\n",
" <th>Turkish Restaurant</th>\n",
" <th>Vegetarian / Vegan Restaurant</th>\n",
" <th>Video Store</th>\n",
" <th>Vietnamese Restaurant</th>\n",
" <th>Waterfront</th>\n",
" <th>Wine Bar</th>\n",
" <th>Wine Shop</th>\n",
" <th>Winery</th>\n",
" <th>Yoga Studio</th>\n",
" <th>Zoo Exhibit</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Pinehurst</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Pinehurst</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Pinehurst</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Pinehurst</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Pinehurst</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5 rows × 226 columns</p>\n",
"</div>"
],
"text/plain": [
" name ATM African Restaurant American Restaurant Amphitheater \\\n",
"0 Pinehurst 0 0 0 0 \n",
"1 Pinehurst 0 0 0 0 \n",
"2 Pinehurst 0 0 0 0 \n",
"3 Pinehurst 0 0 0 0 \n",
"4 Pinehurst 0 0 0 0 \n",
"\n",
" Antique Shop Arcade Art Gallery Art Museum Arts & Crafts Store ... \\\n",
"0 0 0 0 0 0 ... \n",
"1 0 0 0 0 0 ... \n",
"2 0 0 0 0 0 ... \n",
"3 0 0 0 0 0 ... \n",
"4 0 0 0 0 0 ... \n",
"\n",
" Turkish Restaurant Vegetarian / Vegan Restaurant Video Store \\\n",
"0 0 0 0 \n",
"1 0 0 0 \n",
"2 0 0 0 \n",
"3 0 0 0 \n",
"4 0 0 0 \n",
"\n",
" Vietnamese Restaurant Waterfront Wine Bar Wine Shop Winery \\\n",
"0 0 0 0 0 0 \n",
"1 0 0 0 0 0 \n",
"2 0 0 0 0 0 \n",
"3 0 0 0 0 0 \n",
"4 0 0 0 0 0 \n",
"\n",
" Yoga Studio Zoo Exhibit \n",
"0 0 0 \n",
"1 0 0 \n",
"2 0 0 \n",
"3 0 0 \n",
"4 0 0 \n",
"\n",
"[5 rows x 226 columns]"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Create dummy variables to represent presence of venues by category\n",
"\n",
"onehot = pd.get_dummies(seattle_venus[['Venue Category']], prefix=\"\", prefix_sep=\"\")\n",
"\n",
"onehot['name'] = seattle_venus['Name']\n",
"\n",
"fixed_columns = [onehot.columns[-1]] + list(onehot.columns[:-1])\n",
"onehot = onehot[fixed_columns]\n",
"\n",
"onehot.head()"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>name</th>\n",
" <th>ATM</th>\n",
" <th>African Restaurant</th>\n",
" <th>American Restaurant</th>\n",
" <th>Amphitheater</th>\n",
" <th>Antique Shop</th>\n",
" <th>Arcade</th>\n",
" <th>Art Gallery</th>\n",
" <th>Art Museum</th>\n",
" <th>Arts &amp; Crafts Store</th>\n",
" <th>...</th>\n",
" <th>Turkish Restaurant</th>\n",
" <th>Vegetarian / Vegan Restaurant</th>\n",
" <th>Video Store</th>\n",
" <th>Vietnamese Restaurant</th>\n",
" <th>Waterfront</th>\n",
" <th>Wine Bar</th>\n",
" <th>Wine Shop</th>\n",
" <th>Winery</th>\n",
" <th>Yoga Studio</th>\n",
" <th>Zoo Exhibit</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Admiral</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.033333</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.033333</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.033333</td>\n",
" <td>0.033333</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Alki</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Arbor Heights</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Atlantic</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Ballard</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.033333</td>\n",
" <td>0.000000</td>\n",
" <td>0.033333</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.033333</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5 rows × 226 columns</p>\n",
"</div>"
],
"text/plain": [
" name ATM African Restaurant American Restaurant Amphitheater \\\n",
"0 Admiral 0.0 0.0 0.033333 0.0 \n",
"1 Alki 0.0 0.0 0.000000 0.0 \n",
"2 Arbor Heights 0.0 0.0 0.000000 0.0 \n",
"3 Atlantic 0.0 0.0 0.000000 0.0 \n",
"4 Ballard 0.0 0.0 0.000000 0.0 \n",
"\n",
" Antique Shop Arcade Art Gallery Art Museum Arts & Crafts Store ... \\\n",
"0 0.0 0.0 0.033333 0.0 0.0 ... \n",
"1 0.0 0.0 0.000000 0.0 0.0 ... \n",
"2 0.0 0.0 0.000000 0.0 0.0 ... \n",
"3 0.0 0.0 0.000000 0.0 0.0 ... \n",
"4 0.0 0.0 0.000000 0.0 0.0 ... \n",
"\n",
" Turkish Restaurant Vegetarian / Vegan Restaurant Video Store \\\n",
"0 0.0 0.000000 0.033333 \n",
"1 0.0 0.000000 0.000000 \n",
"2 0.0 0.000000 0.000000 \n",
"3 0.0 0.000000 0.000000 \n",
"4 0.0 0.033333 0.000000 \n",
"\n",
" Vietnamese Restaurant Waterfront Wine Bar Wine Shop Winery \\\n",
"0 0.033333 0.0 0.0 0.0 0.0 \n",
"1 0.000000 0.0 0.0 0.0 0.0 \n",
"2 0.000000 0.0 0.0 0.0 0.0 \n",
"3 0.000000 0.0 0.0 0.0 0.0 \n",
"4 0.033333 0.0 0.0 0.0 0.0 \n",
"\n",
" Yoga Studio Zoo Exhibit \n",
"0 0.000000 0.0 \n",
"1 0.000000 0.0 \n",
"2 0.000000 0.0 \n",
"3 0.000000 0.0 \n",
"4 0.033333 0.0 \n",
"\n",
"[5 rows x 226 columns]"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"meanAnalysis = onehot.groupby('name').mean().reset_index()\n",
"meanAnalysis.head()"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"def return_most_common_venues(row, num_top_venues):\n",
" row_categories = row.iloc[1:]\n",
" row_categories_sorted = row_categories.sort_values(ascending=False)\n",
" \n",
" return row_categories_sorted.index.values[0:num_top_venues]"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"num_top_venues = 10\n",
"\n",
"indicators = ['st', 'nd', 'rd']\n",
"\n",
"# create columns according to number of top venues\n",
"columns = ['name']\n",
"for ind in np.arange(num_top_venues):\n",
" try:\n",
" columns.append('{}{} Most Common Venue'.format(ind+1, indicators[ind]))\n",
" except:\n",
" columns.append('{}th Most Common Venue'.format(ind+1))\n",
"\n",
"# create a new dataframe\n",
"name_venues_sorted = pd.DataFrame(columns=columns)\n",
"name_venues_sorted['name'] = meanAnalysis['name']\n",
"\n",
"for ind in np.arange(meanAnalysis.shape[0]):\n",
" name_venues_sorted.iloc[ind, 1:] = return_most_common_venues(meanAnalysis.iloc[ind, :], num_top_venues)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>name</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Admiral</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Grocery Store</td>\n",
" <td>Italian Restaurant</td>\n",
" <td>Theater</td>\n",
" <td>Salon / Barbershop</td>\n",
" <td>Mexican Restaurant</td>\n",
" <td>Middle Eastern Restaurant</td>\n",
" <td>Spa</td>\n",
" <td>Frozen Yogurt Shop</td>\n",
" <td>Pub</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Alki</td>\n",
" <td>Food Truck</td>\n",
" <td>Trail</td>\n",
" <td>Beach</td>\n",
" <td>Seafood Restaurant</td>\n",
" <td>Cosmetics Shop</td>\n",
" <td>Greek Restaurant</td>\n",
" <td>Burger Joint</td>\n",
" <td>Field</td>\n",
" <td>Farmers Market</td>\n",
" <td>Fast Food Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Arbor Heights</td>\n",
" <td>BBQ Joint</td>\n",
" <td>Park</td>\n",
" <td>Scenic Lookout</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" <td>Field</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Atlantic</td>\n",
" <td>Park</td>\n",
" <td>Bus Stop</td>\n",
" <td>Bus Station</td>\n",
" <td>Tunnel</td>\n",
" <td>Trail</td>\n",
" <td>Ethiopian Restaurant</td>\n",
" <td>Museum</td>\n",
" <td>Japanese Restaurant</td>\n",
" <td>Scenic Lookout</td>\n",
" <td>Dog Run</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Ballard</td>\n",
" <td>Brewery</td>\n",
" <td>Seafood Restaurant</td>\n",
" <td>Mexican Restaurant</td>\n",
" <td>Gaming Cafe</td>\n",
" <td>Pizza Place</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Marijuana Dispensary</td>\n",
" <td>Food Truck</td>\n",
" <td>Beer Bar</td>\n",
" <td>Supermarket</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" name 1st Most Common Venue 2nd Most Common Venue \\\n",
"0 Admiral Coffee Shop Grocery Store \n",
"1 Alki Food Truck Trail \n",
"2 Arbor Heights BBQ Joint Park \n",
"3 Atlantic Park Bus Stop \n",
"4 Ballard Brewery Seafood Restaurant \n",
"\n",
" 3rd Most Common Venue 4th Most Common Venue 5th Most Common Venue \\\n",
"0 Italian Restaurant Theater Salon / Barbershop \n",
"1 Beach Seafood Restaurant Cosmetics Shop \n",
"2 Scenic Lookout Zoo Exhibit Food Court \n",
"3 Bus Station Tunnel Trail \n",
"4 Mexican Restaurant Gaming Cafe Pizza Place \n",
"\n",
" 6th Most Common Venue 7th Most Common Venue 8th Most Common Venue \\\n",
"0 Mexican Restaurant Middle Eastern Restaurant Spa \n",
"1 Greek Restaurant Burger Joint Field \n",
"2 Food & Drink Shop Food Fondue Restaurant \n",
"3 Ethiopian Restaurant Museum Japanese Restaurant \n",
"4 Sandwich Place Marijuana Dispensary Food Truck \n",
"\n",
" 9th Most Common Venue 10th Most Common Venue \n",
"0 Frozen Yogurt Shop Pub \n",
"1 Farmers Market Fast Food Restaurant \n",
"2 Fish Market Field \n",
"3 Scenic Lookout Dog Run \n",
"4 Beer Bar Supermarket "
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"name_venues_sorted.head()"
]
},
{
"cell_type": "code",
"execution_count": 19,
"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>ATM</th>\n",
" <th>African Restaurant</th>\n",
" <th>American Restaurant</th>\n",
" <th>Amphitheater</th>\n",
" <th>Antique Shop</th>\n",
" <th>Arcade</th>\n",
" <th>Art Gallery</th>\n",
" <th>Art Museum</th>\n",
" <th>Arts &amp; Crafts Store</th>\n",
" <th>Asian Restaurant</th>\n",
" <th>...</th>\n",
" <th>Turkish Restaurant</th>\n",
" <th>Vegetarian / Vegan Restaurant</th>\n",
" <th>Video Store</th>\n",
" <th>Vietnamese Restaurant</th>\n",
" <th>Waterfront</th>\n",
" <th>Wine Bar</th>\n",
" <th>Wine Shop</th>\n",
" <th>Winery</th>\n",
" <th>Yoga Studio</th>\n",
" <th>Zoo Exhibit</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.033333</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.033333</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.033333</td>\n",
" <td>0.033333</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.000000</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.033333</td>\n",
" <td>0.000000</td>\n",
" <td>0.033333</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.033333</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5 rows × 225 columns</p>\n",
"</div>"
],
"text/plain": [
" ATM African Restaurant American Restaurant Amphitheater Antique Shop \\\n",
"0 0.0 0.0 0.033333 0.0 0.0 \n",
"1 0.0 0.0 0.000000 0.0 0.0 \n",
"2 0.0 0.0 0.000000 0.0 0.0 \n",
"3 0.0 0.0 0.000000 0.0 0.0 \n",
"4 0.0 0.0 0.000000 0.0 0.0 \n",
"\n",
" Arcade Art Gallery Art Museum Arts & Crafts Store Asian Restaurant \\\n",
"0 0.0 0.033333 0.0 0.0 0.0 \n",
"1 0.0 0.000000 0.0 0.0 0.0 \n",
"2 0.0 0.000000 0.0 0.0 0.0 \n",
"3 0.0 0.000000 0.0 0.0 0.0 \n",
"4 0.0 0.000000 0.0 0.0 0.0 \n",
"\n",
" ... Turkish Restaurant Vegetarian / Vegan Restaurant Video Store \\\n",
"0 ... 0.0 0.000000 0.033333 \n",
"1 ... 0.0 0.000000 0.000000 \n",
"2 ... 0.0 0.000000 0.000000 \n",
"3 ... 0.0 0.000000 0.000000 \n",
"4 ... 0.0 0.033333 0.000000 \n",
"\n",
" Vietnamese Restaurant Waterfront Wine Bar Wine Shop Winery \\\n",
"0 0.033333 0.0 0.0 0.0 0.0 \n",
"1 0.000000 0.0 0.0 0.0 0.0 \n",
"2 0.000000 0.0 0.0 0.0 0.0 \n",
"3 0.000000 0.0 0.0 0.0 0.0 \n",
"4 0.033333 0.0 0.0 0.0 0.0 \n",
"\n",
" Yoga Studio Zoo Exhibit \n",
"0 0.000000 0.0 \n",
"1 0.000000 0.0 \n",
"2 0.000000 0.0 \n",
"3 0.000000 0.0 \n",
"4 0.033333 0.0 \n",
"\n",
"[5 rows x 225 columns]"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Prepare dataframe for clustering analysis\n",
"\n",
"meanAnalysis_clustering = meanAnalysis.drop(columns=['name'])\n",
"meanAnalysis_clustering.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Create model"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([2, 1, 6, 2, 2], dtype=int32)"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"k = 7 # set number of clusters\n",
"\n",
"kMeans = KMeans(init=\"k-means++\", n_clusters= k, random_state=0).fit(meanAnalysis_clustering)\n",
"\n",
"kMeans.labels_[0:5]"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"# Add cluster labels to dataframe\n",
"\n",
"name_venues_sorted.insert(0, 'Cluster Labels', kMeans.labels_)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"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>city</th>\n",
" <th>name</th>\n",
" <th>pc_income</th>\n",
" <th>median age_census</th>\n",
" <th>latitude</th>\n",
" <th>longitude</th>\n",
" <th>popdensity</th>\n",
" <th>Cluster Labels</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Seattle</td>\n",
" <td>Pinehurst</td>\n",
" <td>33705</td>\n",
" <td>40.640000</td>\n",
" <td>47.7229</td>\n",
" <td>-122.319553</td>\n",
" <td>7337.190000</td>\n",
" <td>6</td>\n",
" <td>Park</td>\n",
" <td>Moving Target</td>\n",
" <td>Garden</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Dog Run</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Event Space</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Seattle</td>\n",
" <td>Brighton</td>\n",
" <td>23520</td>\n",
" <td>35.843750</td>\n",
" <td>47.5388</td>\n",
" <td>-122.275673</td>\n",
" <td>11462.300000</td>\n",
" <td>2</td>\n",
" <td>Mexican Restaurant</td>\n",
" <td>Vietnamese Restaurant</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Breakfast Spot</td>\n",
" <td>Seafood Restaurant</td>\n",
" <td>Café</td>\n",
" <td>Fast Food Restaurant</td>\n",
" <td>Gas Station</td>\n",
" <td>Bank</td>\n",
" <td>Mobile Phone Shop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Seattle</td>\n",
" <td>Whittier Heights</td>\n",
" <td>41725</td>\n",
" <td>39.457143</td>\n",
" <td>47.6833</td>\n",
" <td>-122.371407</td>\n",
" <td>10478.685714</td>\n",
" <td>2</td>\n",
" <td>Bar</td>\n",
" <td>Dance Studio</td>\n",
" <td>Trail</td>\n",
" <td>Caribbean Restaurant</td>\n",
" <td>Rental Car Location</td>\n",
" <td>Bakery</td>\n",
" <td>Karaoke Bar</td>\n",
" <td>Theme Park Ride / Attraction</td>\n",
" <td>Cocktail Bar</td>\n",
" <td>Breakfast Spot</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Seattle</td>\n",
" <td>Windermere</td>\n",
" <td>56478</td>\n",
" <td>42.383333</td>\n",
" <td>47.6701</td>\n",
" <td>-122.262675</td>\n",
" <td>6346.766667</td>\n",
" <td>6</td>\n",
" <td>Park</td>\n",
" <td>Pizza Place</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Ethiopian Restaurant</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" <td>Field</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Seattle</td>\n",
" <td>Loyal Heights</td>\n",
" <td>40157</td>\n",
" <td>40.529412</td>\n",
" <td>47.6832</td>\n",
" <td>-122.384869</td>\n",
" <td>10233.158824</td>\n",
" <td>3</td>\n",
" <td>Pizza Place</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Athletics &amp; Sports</td>\n",
" <td>Food Truck</td>\n",
" <td>Fish Market</td>\n",
" <td>Café</td>\n",
" <td>Music Store</td>\n",
" <td>General College &amp; University</td>\n",
" <td>Bakery</td>\n",
" <td>Middle Eastern Restaurant</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" city name pc_income median age_census latitude \\\n",
"0 Seattle Pinehurst 33705 40.640000 47.7229 \n",
"1 Seattle Brighton 23520 35.843750 47.5388 \n",
"2 Seattle Whittier Heights 41725 39.457143 47.6833 \n",
"3 Seattle Windermere 56478 42.383333 47.6701 \n",
"4 Seattle Loyal Heights 40157 40.529412 47.6832 \n",
"\n",
" longitude popdensity Cluster Labels 1st Most Common Venue \\\n",
"0 -122.319553 7337.190000 6 Park \n",
"1 -122.275673 11462.300000 2 Mexican Restaurant \n",
"2 -122.371407 10478.685714 2 Bar \n",
"3 -122.262675 6346.766667 6 Park \n",
"4 -122.384869 10233.158824 3 Pizza Place \n",
"\n",
" 2nd Most Common Venue 3rd Most Common Venue 4th Most Common Venue \\\n",
"0 Moving Target Garden Coffee Shop \n",
"1 Vietnamese Restaurant Coffee Shop Breakfast Spot \n",
"2 Dance Studio Trail Caribbean Restaurant \n",
"3 Pizza Place Zoo Exhibit Ethiopian Restaurant \n",
"4 Coffee Shop Athletics & Sports Food Truck \n",
"\n",
" 5th Most Common Venue 6th Most Common Venue 7th Most Common Venue \\\n",
"0 Dog Run Zoo Exhibit Event Space \n",
"1 Seafood Restaurant Café Fast Food Restaurant \n",
"2 Rental Car Location Bakery Karaoke Bar \n",
"3 Food Court Food & Drink Shop Food \n",
"4 Fish Market Café Music Store \n",
"\n",
" 8th Most Common Venue 9th Most Common Venue \\\n",
"0 Food & Drink Shop Food \n",
"1 Gas Station Bank \n",
"2 Theme Park Ride / Attraction Cocktail Bar \n",
"3 Fondue Restaurant Fish Market \n",
"4 General College & University Bakery \n",
"\n",
" 10th Most Common Venue \n",
"0 Fondue Restaurant \n",
"1 Mobile Phone Shop \n",
"2 Breakfast Spot \n",
"3 Field \n",
"4 Middle Eastern Restaurant "
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Merge demographic data frame and common venues dataframe\n",
"\n",
"seattle_merged = areas\n",
"\n",
"seattle_merged = seattle_merged.join(name_venues_sorted.set_index(\"name\"), on=\"name\")\n",
"seattle_merged.head()"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVMgPSBmYWxzZTsgTF9OT19UT1VDSCA9IGZhbHNlOyBMX0RJU0FCTEVfM0QgPSBmYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdnaXQuY29tL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9tYXN0ZXIvZm9saXVtL3RlbXBsYXRlcy9sZWFmbGV0LmF3ZXNvbWUucm90YXRlLmNzcyIvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogMTAwLjAlOwogICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgICAgICAgICAgdG9wOiAwLjAlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICA8L3N0eWxlPgogICAgICAgIAo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgICAgICAgICA8ZGl2IGNsYXNzPSJmb2xpdW0tbWFwIiBpZD0ibWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlIiA+PC9kaXY+CiAgICAgICAgCjwvYm9keT4KPHNjcmlwdD4gICAgCiAgICAKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGJvdW5kcyA9IG51bGw7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgdmFyIG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSA9IEwubWFwKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ21hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7Y2VudGVyOiBbNDcuNTQwMywtMTIyLjMxNjM3MDg1NV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB6b29tOiAxMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heEJvdW5kczogYm91bmRzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF5ZXJzOiBbXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmxkQ29weUp1bXA6IGZhbHNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JzOiBMLkNSUy5FUFNHMzg1NwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHRpbGVfbGF5ZXJfY2I0MmZhYzk3MWNhNGVlMDk1MWMzYTY0YTJiZjg1ZWQgPSBMLnRpbGVMYXllcigKICAgICAgICAgICAgICAgICdodHRwczovL3tzfS50aWxlLm9wZW5zdHJlZXRtYXAub3JnL3t6fS97eH0ve3l9LnBuZycsCiAgICAgICAgICAgICAgICB7CiAgImF0dHJpYnV0aW9uIjogbnVsbCwKICAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsCiAgIm1heFpvb20iOiAxOCwKICAibWluWm9vbSI6IDEsCiAgIm5vV3JhcCI6IGZhbHNlLAogICJzdWJkb21haW5zIjogImFiYyIKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzkwNjRjZWRiMDg2YjRjZjE4YjhiZTc4YWU5MmE1MWZhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNzIyOSwtMTIyLjMxOTU1MzA1MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmY3ZTQxIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmN2U0MSIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81OTkxMzY4ZmM5YWI0ZDY3YjQyNTIxZWEzOTdjNzg5YyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9kY2JiYmYyODA2YWE0ODJiYTkyMGNjMTA4M2RlMTUwMyA9ICQoJzxkaXYgaWQ9Imh0bWxfZGNiYmJmMjgwNmFhNDgyYmE5MjBjYzEwODNkZTE1MDMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlBpbmVodXJzdCBDbHVzdGVyIDY8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzU5OTEzNjhmYzlhYjRkNjdiNDI1MjFlYTM5N2M3ODljLnNldENvbnRlbnQoaHRtbF9kY2JiYmYyODA2YWE0ODJiYTkyMGNjMTA4M2RlMTUwMyk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85MDY0Y2VkYjA4NmI0Y2YxOGI4YmU3OGFlOTJhNTFmYS5iaW5kUG9wdXAocG9wdXBfNTk5MTM2OGZjOWFiNGQ2N2I0MjUyMWVhMzk3Yzc4OWMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMGNhYjM3MTVhNjkzNGExZDk5YWNmOTFjNGVmZjQzMTUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny41Mzg4LC0xMjIuMjc1NjcyOTUxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMyYzdlZjciLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMmM3ZWY3IiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzljOThkODA2OTc1ZDQzYzdhYTA0ZWQ4MGViZGFhOTFjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2E0ZWJlMGE3OGVmMDQ4OTU4NjlmZDk4N2RkZGFmYWFiID0gJCgnPGRpdiBpZD0iaHRtbF9hNGViZTBhNzhlZjA0ODk1ODY5ZmQ5ODdkZGRhZmFhYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnJpZ2h0b24gQ2x1c3RlciAyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85Yzk4ZDgwNjk3NWQ0M2M3YWEwNGVkODBlYmRhYTkxYy5zZXRDb250ZW50KGh0bWxfYTRlYmUwYTc4ZWYwNDg5NTg2OWZkOTg3ZGRkYWZhYWIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMGNhYjM3MTVhNjkzNGExZDk5YWNmOTFjNGVmZjQzMTUuYmluZFBvcHVwKHBvcHVwXzljOThkODA2OTc1ZDQzYzdhYTA0ZWQ4MGViZGFhOTFjKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Q1OTNiMWUxYzUzYjRlMjNiMTllMjhlZTI3MTQ3NmViID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjgzMywtMTIyLjM3MTQwNzAzN10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mODZlMGQzMjk4ZDQ0NTljYThiNTE5ZDE4ZGNjZDZmYSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83ZTE1MmQ0NjNlOTg0NzU5Yjg0MDgwMTUwZjNkNzdmZSA9ICQoJzxkaXYgaWQ9Imh0bWxfN2UxNTJkNDYzZTk4NDc1OWI4NDA4MDE1MGYzZDc3ZmUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldoaXR0aWVyIEhlaWdodHMgQ2x1c3RlciAyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mODZlMGQzMjk4ZDQ0NTljYThiNTE5ZDE4ZGNjZDZmYS5zZXRDb250ZW50KGh0bWxfN2UxNTJkNDYzZTk4NDc1OWI4NDA4MDE1MGYzZDc3ZmUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZDU5M2IxZTFjNTNiNGUyM2IxOWUyOGVlMjcxNDc2ZWIuYmluZFBvcHVwKHBvcHVwX2Y4NmUwZDMyOThkNDQ1OWNhOGI1MTlkMThkY2NkNmZhKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzJkYWNjOTIwOTUzODQxZDQ5YTgyMTE1Zjg4OTMxOTI3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjcwMSwtMTIyLjI2MjY3NDg2NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmY3ZTQxIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmN2U0MSIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jYjM2Y2M3Yjg5YTg0ODAyOGY3ZWY5NDc0ZGUwYTFhMyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jOTgxNTMyZDZhZWI0MDUwOWE5ZTk4NTVjM2JjMzkzNiA9ICQoJzxkaXYgaWQ9Imh0bWxfYzk4MTUzMmQ2YWViNDA1MDlhOWU5ODU1YzNiYzM5MzYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldpbmRlcm1lcmUgQ2x1c3RlciA2PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jYjM2Y2M3Yjg5YTg0ODAyOGY3ZWY5NDc0ZGUwYTFhMy5zZXRDb250ZW50KGh0bWxfYzk4MTUzMmQ2YWViNDA1MDlhOWU5ODU1YzNiYzM5MzYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMmRhY2M5MjA5NTM4NDFkNDlhODIxMTVmODg5MzE5MjcuYmluZFBvcHVwKHBvcHVwX2NiMzZjYzdiODlhODQ4MDI4ZjdlZjk0NzRkZTBhMWEzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I1ZjcyNTBjZTVmYzQ5MGE4YWRkOWI2NTdjZmY4MDNiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjgzMiwtMTIyLjM4NDg2ODY3NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmFkZGRkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJhZGRkZCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jMjFhZWIzYjEzZjY0NmQ3YWQyNzA2OTkwOTc4MWExMyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zMzRjNDQ1YmMwNGE0NDQ3OTMwOTc3NTBmZTMxZDI5ZiA9ICQoJzxkaXYgaWQ9Imh0bWxfMzM0YzQ0NWJjMDRhNDQ0NzkzMDk3NzUwZmUzMWQyOWYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxveWFsIEhlaWdodHMgQ2x1c3RlciAzPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jMjFhZWIzYjEzZjY0NmQ3YWQyNzA2OTkwOTc4MWExMy5zZXRDb250ZW50KGh0bWxfMzM0YzQ0NWJjMDRhNDQ0NzkzMDk3NzUwZmUzMWQyOWYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjVmNzI1MGNlNWZjNDkwYThhZGQ5YjY1N2NmZjgwM2IuYmluZFBvcHVwKHBvcHVwX2MyMWFlYjNiMTNmNjQ2ZDdhZDI3MDY5OTA5NzgxYTEzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2I1OWQ5YWUwZGU5NTRkYzJiMDc5MzM3MzcyMjdlNjcxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjk2MSwtMTIyLjM5NjE1MzU1NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjODAwMGZmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80MjA3NjU5NjJkMmU0MTNmOTlhMDk4MDM5Yjg1ZTM1ZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wMDk2MjU5OTA4M2Q0ZDVkYjQ5NDZjMGRjOWVjOGMxMyA9ICQoJzxkaXYgaWQ9Imh0bWxfMDA5NjI1OTkwODNkNGQ1ZGI0OTQ2YzBkYzllYzhjMTMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5vcnRoIEJlYWNoIENsdXN0ZXIgMTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNDIwNzY1OTYyZDJlNDEzZjk5YTA5ODAzOWI4NWUzNWQuc2V0Q29udGVudChodG1sXzAwOTYyNTk5MDgzZDRkNWRiNDk0NmMwZGM5ZWM4YzEzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2I1OWQ5YWUwZGU5NTRkYzJiMDc5MzM3MzcyMjdlNjcxLmJpbmRQb3B1cChwb3B1cF80MjA3NjU5NjJkMmU0MTNmOTlhMDk4MDM5Yjg1ZTM1ZCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mYjQ3NjFlMGY0ZjI0MDI4OTYwMjQyN2ExZjJlZWUyYSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjY3NzIsLTEyMi4zMTYxOTYxODhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzJjN2VmNyIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMyYzdlZjciLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZDhhMjVlZTc5ZTZlNGI3M2E2ZjZjZGMwNDIzMWYzZDEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfN2FkODM4MDNlZjI1NGVjNzg2YjQ4MjBiNWYwZDgyY2MgPSAkKCc8ZGl2IGlkPSJodG1sXzdhZDgzODAzZWYyNTRlYzc4NmI0ODIwYjVmMGQ4MmNjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Sb29zZXZlbHQgQ2x1c3RlciAyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9kOGEyNWVlNzllNmU0YjczYTZmNmNkYzA0MjMxZjNkMS5zZXRDb250ZW50KGh0bWxfN2FkODM4MDNlZjI1NGVjNzg2YjQ4MjBiNWYwZDgyY2MpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZmI0NzYxZTBmNGYyNDAyODk2MDI0MjdhMWYyZWVlMmEuYmluZFBvcHVwKHBvcHVwX2Q4YTI1ZWU3OWU2ZTRiNzNhNmY2Y2RjMDQyMzFmM2QxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzcwZDg3YzE5MzkxYjRmYzc4MzE4YmIzODNjZmNlN2I5ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTk3NSwtMTIyLjMzMjc3NzA3MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmFkZGRkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJhZGRkZCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83Yjc5MjI1Zjk5YzA0NTI5YWM5NDg4MWVmOTdjZDZlMyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9mMDYzZTE4N2FhYzU0OTI5YTk0MDNmOGFiMGQ3MDc1ZSA9ICQoJzxkaXYgaWQ9Imh0bWxfZjA2M2UxODdhYWM1NDkyOWE5NDAzZjhhYjBkNzA3NWUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlBpb25lZXIgU3F1YXJlIENsdXN0ZXIgMzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfN2I3OTIyNWY5OWMwNDUyOWFjOTQ4ODFlZjk3Y2Q2ZTMuc2V0Q29udGVudChodG1sX2YwNjNlMTg3YWFjNTQ5MjlhOTQwM2Y4YWIwZDcwNzVlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzcwZDg3YzE5MzkxYjRmYzc4MzE4YmIzODNjZmNlN2I5LmJpbmRQb3B1cChwb3B1cF83Yjc5MjI1Zjk5YzA0NTI5YWM5NDg4MWVmOTdjZDZlMyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mYmVlZDBhYTVhMmE0OGZlYTA2ZjRmNzVmN2IxNTZjNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjYzNDksLTEyMi4zNDE4MTIxMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iMWMxNmFiMzU2MTU0NDY3YWVjYmUzY2NmOTlkYzMxNSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83NTg2ZDc1OGI1ZTU0ZGQ2YmQ1Zjk5ZTEyNTIzMzNmNCA9ICQoJzxkaXYgaWQ9Imh0bWxfNzU4NmQ3NThiNWU1NGRkNmJkNWY5OWUxMjUyMzMzZjQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldlc3RsYWtlIENsdXN0ZXIgMjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYjFjMTZhYjM1NjE1NDQ2N2FlY2JlM2NjZjk5ZGMzMTUuc2V0Q29udGVudChodG1sXzc1ODZkNzU4YjVlNTRkZDZiZDVmOTllMTI1MjMzM2Y0KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2ZiZWVkMGFhNWEyYTQ4ZmVhMDZmNGY3NWY3YjE1NmM1LmJpbmRQb3B1cChwb3B1cF9iMWMxNmFiMzU2MTU0NDY3YWVjYmUzY2NmOTlkYzMxNSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wNmUwMDI3N2Y4YWM0MGE3YTBmZGI4Mjc4YTBiZDg2YSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjY4MTcsLTEyMi4yNTU3MTgyNDNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzJjN2VmNyIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMyYzdlZjciLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYWNmZTEwODhmMmU0NGQ2YWIzODNmMzMwNzAyYzBmOTcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfYmFkNDNlODczMWNkNDc5OGIxMzI5MGI2YWU3NWYzZmIgPSAkKCc8ZGl2IGlkPSJodG1sX2JhZDQzZTg3MzFjZDQ3OThiMTMyOTBiNmFlNzVmM2ZiIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TYW5kIFBvaW50IENsdXN0ZXIgMjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYWNmZTEwODhmMmU0NGQ2YWIzODNmMzMwNzAyYzBmOTcuc2V0Q29udGVudChodG1sX2JhZDQzZTg3MzFjZDQ3OThiMTMyOTBiNmFlNzVmM2ZiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzA2ZTAwMjc3ZjhhYzQwYTdhMGZkYjgyNzhhMGJkODZhLmJpbmRQb3B1cChwb3B1cF9hY2ZlMTA4OGYyZTQ0ZDZhYjM4M2YzMzA3MDJjMGY5Nyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xMTVlYWM2MmNhZjE0ZmIzOTQwNGJmM2JkYTQxMDNhNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjUyODgsLTEyMi4zMjMwMTU0NjFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmN2U0MSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjdlNDEiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNDg5ZGYzMDNkMTdhNDlkY2EyYjk3NWM3M2YwYjQ0Y2UgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjM2ZjFmODM2ZWM4NGY2Y2E4ZTNkZGI4NDY5ODdlMGMgPSAkKCc8ZGl2IGlkPSJodG1sX2YzNmYxZjgzNmVjODRmNmNhOGUzZGRiODQ2OTg3ZTBjIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Tb3V0aCBQYXJrIENsdXN0ZXIgNjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNDg5ZGYzMDNkMTdhNDlkY2EyYjk3NWM3M2YwYjQ0Y2Uuc2V0Q29udGVudChodG1sX2YzNmYxZjgzNmVjODRmNmNhOGUzZGRiODQ2OTg3ZTBjKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzExNWVhYzYyY2FmMTRmYjM5NDA0YmYzYmRhNDEwM2E3LmJpbmRQb3B1cChwb3B1cF80ODlkZjMwM2QxN2E0OWRjYTJiOTc1YzczZjBiNDRjZSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zYzQ5ODA5MWJhZWI0ZmEzYjY3MWM1MGI1YTdkNDhkYSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjY5NTIsLTEyMi4zMTc0MDAwMjhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzJhZGRkZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMyYWRkZGQiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOTRmNjY0OGQ2YzQwNDRiM2JjYmZkMWNhOWNmY2ZiMWIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNjQ2M2VhYTc2ODE5NGMyZDk4NDE3N2Q2OTUyMWY2OTIgPSAkKCc8ZGl2IGlkPSJodG1sXzY0NjNlYWE3NjgxOTRjMmQ5ODQxNzdkNjk1MjFmNjkyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5NYXBsZSBMZWFmIENsdXN0ZXIgMzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfOTRmNjY0OGQ2YzQwNDRiM2JjYmZkMWNhOWNmY2ZiMWIuc2V0Q29udGVudChodG1sXzY0NjNlYWE3NjgxOTRjMmQ5ODQxNzdkNjk1MjFmNjkyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzNjNDk4MDkxYmFlYjRmYTNiNjcxYzUwYjVhN2Q0OGRhLmJpbmRQb3B1cChwb3B1cF85NGY2NjQ4ZDZjNDA0NGIzYmNiZmQxY2E5Y2ZjZmIxYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jNGE0OGZkZTYwMTY0NjI3ODUwYWUxNDQwZDRkYjVhNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjY3NzksLTEyMi40MDA5ODQ4MjJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzJhZGRkZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMyYWRkZGQiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNGYyYmYzNzg2OWI5NDMyOGFhMzkxYWViOWZkMzM3NDYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzEwOWRhMWFmMmNlNDY5YTgwODYwYzRmM2I4MmU5NjEgPSAkKCc8ZGl2IGlkPSJodG1sXzcxMDlkYTFhZjJjZTQ2OWE4MDg2MGM0ZjNiODJlOTYxIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TdW5zZXQgSGlsbCBDbHVzdGVyIDM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzRmMmJmMzc4NjliOTQzMjhhYTM5MWFlYjlmZDMzNzQ2LnNldENvbnRlbnQoaHRtbF83MTA5ZGExYWYyY2U0NjlhODA4NjBjNGYzYjgyZTk2MSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jNGE0OGZkZTYwMTY0NjI3ODUwYWUxNDQwZDRkYjVhNC5iaW5kUG9wdXAocG9wdXBfNGYyYmYzNzg2OWI5NDMyOGFhMzkxYWViOWZkMzM3NDYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZmMzZDc5YzI2OGRiNDkyN2IyZGJjMjU0ZjQ5NzhmZjAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny41NTQxLC0xMjIuMzAwODYwNTE2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMyYzdlZjciLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMmM3ZWY3IiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzQ1NmRhZWMyOGY0MzQ5ZmVhZDM1NWQwMGVmNjgzNmIyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzJjZGFmNzMwNjFhOTQ4NmRiYzAwZWFhNGNmOTQ5NmM2ID0gJCgnPGRpdiBpZD0iaHRtbF8yY2RhZjczMDYxYTk0ODZkYmMwMGVhYTRjZjk0OTZjNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmVhY29uIEhpbGwgQ2x1c3RlciAyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF80NTZkYWVjMjhmNDM0OWZlYWQzNTVkMDBlZjY4MzZiMi5zZXRDb250ZW50KGh0bWxfMmNkYWY3MzA2MWE5NDg2ZGJjMDBlYWE0Y2Y5NDk2YzYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZmMzZDc5YzI2OGRiNDkyN2IyZGJjMjU0ZjQ5NzhmZjAuYmluZFBvcHVwKHBvcHVwXzQ1NmRhZWMyOGY0MzQ5ZmVhZDM1NWQwMGVmNjgzNmIyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzgyN2NkZjcyZjg0ZDQxNDdiMzUwYzM0MjY0N2Q3NDlkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTEzNSwtMTIyLjI2MTY0ODQ4Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF85ZmY3YTJkOWRiYTQ0YzllYmIxOTdjYmMzMzdjYzgxZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81OTIxMzlhOGJjMTk0MzVhOTg3ZGZmNjlhY2EyMzQyYiA9ICQoJzxkaXYgaWQ9Imh0bWxfNTkyMTM5YThiYzE5NDM1YTk4N2RmZjY5YWNhMjM0MmIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlJhaW5pZXIgQmVhY2ggQ2x1c3RlciAyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85ZmY3YTJkOWRiYTQ0YzllYmIxOTdjYmMzMzdjYzgxZi5zZXRDb250ZW50KGh0bWxfNTkyMTM5YThiYzE5NDM1YTk4N2RmZjY5YWNhMjM0MmIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODI3Y2RmNzJmODRkNDE0N2IzNTBjMzQyNjQ3ZDc0OWQuYmluZFBvcHVwKHBvcHVwXzlmZjdhMmQ5ZGJhNDRjOWViYjE5N2NiYzMzN2NjODFmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzc0MGRhYWQ1MTA0MDQwMTM5ODg2OTlhMjlmNjY2OTZiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjM1MSwtMTIyLjI5MTUwMDk2M10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjODAwMGZmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xNDM4ZWU3MGJiOGU0ZWE5YWQ4MzlhYWEyYWQ2Y2YyNSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85NjkzYjk2ZjBhZWU0ZmU5YWY4NWQ0NDNmZDFlOGQwZCA9ICQoJzxkaXYgaWQ9Imh0bWxfOTY5M2I5NmYwYWVlNGZlOWFmODVkNDQzZmQxZThkMGQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJyb2FkbW9vciBDbHVzdGVyIDE8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzE0MzhlZTcwYmI4ZTRlYTlhZDgzOWFhYTJhZDZjZjI1LnNldENvbnRlbnQoaHRtbF85NjkzYjk2ZjBhZWU0ZmU5YWY4NWQ0NDNmZDFlOGQwZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83NDBkYWFkNTEwNDA0MDEzOTg4Njk5YTI5ZjY2Njk2Yi5iaW5kUG9wdXAocG9wdXBfMTQzOGVlNzBiYjhlNGVhOWFkODM5YWFhMmFkNmNmMjUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfY2ZjMDg2MzBhMDg0NDg2NDhhNzVhZWMxMmI2YzhmNzYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42MzMzLC0xMjIuMjgzMTgyMl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9iNjA3NzVmODVjNGY0ODFjYjg1NDgwMGI0NDI1NmFhMSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jNWZmN2FiYjk1ZTQ0MjU3YmE3MjJmYTdmNDAyZGRhMCA9ICQoJzxkaXYgaWQ9Imh0bWxfYzVmZjdhYmI5NWU0NDI1N2JhNzIyZmE3ZjQwMmRkYTAiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1hZGlzb24gUGFyayBDbHVzdGVyIDI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2I2MDc3NWY4NWM0ZjQ4MWNiODU0ODAwYjQ0MjU2YWExLnNldENvbnRlbnQoaHRtbF9jNWZmN2FiYjk1ZTQ0MjU3YmE3MjJmYTdmNDAyZGRhMCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jZmMwODYzMGEwODQ0ODY0OGE3NWFlYzEyYjZjOGY3Ni5iaW5kUG9wdXAocG9wdXBfYjYwNzc1Zjg1YzRmNDgxY2I4NTQ4MDBiNDQyNTZhYTEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMWUyMTE3ZDdhMTM4NDBiMzk4MzMxMmJkOTkyMmI4YTYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny41NDQxLC0xMjIuMzY4NjMyODMyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMyYzdlZjciLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMmM3ZWY3IiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzUwZDEyMWM2OGFiZTQ2M2NiYjkwYzE0OTE4MTY1NjVkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzcyODVlMzJhNzYxNDQ3NmE5ZDUxYjQ0OGFhM2ZkYmY5ID0gJCgnPGRpdiBpZD0iaHRtbF83Mjg1ZTMyYTc2MTQ0NzZhOWQ1MWI0NDhhYTNmZGJmOSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+SGlnaCBQb2ludCBDbHVzdGVyIDI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzUwZDEyMWM2OGFiZTQ2M2NiYjkwYzE0OTE4MTY1NjVkLnNldENvbnRlbnQoaHRtbF83Mjg1ZTMyYTc2MTQ0NzZhOWQ1MWI0NDhhYTNmZGJmOSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xZTIxMTdkN2ExMzg0MGIzOTgzMzEyYmQ5OTIyYjhhNi5iaW5kUG9wdXAocG9wdXBfNTBkMTIxYzY4YWJlNDYzY2JiOTBjMTQ5MTgxNjU2NWQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNGEyMzE4YmJlN2M3NDgwNTlmNjExMGUyZTAwZGRhZGMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42NDIsLTEyMi4zODAzNjA0NjFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzJjN2VmNyIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMyYzdlZjciLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNWI0MWY4ODQ0MjgxNGE3MDg1ZGVkNGM5ODc0YTQwYzcgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZDJhZmE2MWFlMjFhNDY5NDlkMGQ4M2E2NWEyYzEyNjMgPSAkKCc8ZGl2IGlkPSJodG1sX2QyYWZhNjFhZTIxYTQ2OTQ5ZDBkODNhNjVhMmMxMjYzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5JbnRlcmJheSBDbHVzdGVyIDI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzViNDFmODg0NDI4MTRhNzA4NWRlZDRjOTg3NGE0MGM3LnNldENvbnRlbnQoaHRtbF9kMmFmYTYxYWUyMWE0Njk0OWQwZDgzYTY1YTJjMTI2Myk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl80YTIzMThiYmU3Yzc0ODA1OWY2MTEwZTJlMDBkZGFkYy5iaW5kUG9wdXAocG9wdXBfNWI0MWY4ODQ0MjgxNGE3MDg1ZGVkNGM5ODc0YTQwYzcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMTZmZTRkMjhmOThlNDRiYWIzOTk5M2ZmNmZhNjVlZjUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42ODM0LC0xMjIuMjczOTM0ODc5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjdlNDEiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmY3ZTQxIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzY3NGJlMmE1ODZjMzRjM2JiYTQ3MzZlN2JjNjZiMjUxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2IzOTNjZTI3NGExMzQ1NGE5ODQ0MmRkMGRlMzZlY2JkID0gJCgnPGRpdiBpZD0iaHRtbF9iMzkzY2UyNzRhMTM0NTRhOTg0NDJkZDBkZTM2ZWNiZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+VmlldyBSaWRnZSBDbHVzdGVyIDY8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzY3NGJlMmE1ODZjMzRjM2JiYTQ3MzZlN2JjNjZiMjUxLnNldENvbnRlbnQoaHRtbF9iMzkzY2UyNzRhMTM0NTRhOTg0NDJkZDBkZTM2ZWNiZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xNmZlNGQyOGY5OGU0NGJhYjM5OTkzZmY2ZmE2NWVmNS5iaW5kUG9wdXAocG9wdXBfNjc0YmUyYTU4NmMzNGMzYmJhNDczNmU3YmM2NmIyNTEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZWZhMGJhNGE3OGVlNDYzYzk2MzI1MjA5ZTMyMzU0NTIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny43MDQzLC0xMjIuMjgwMzY1MDY2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiM4MDAwZmYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjODAwMGZmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzUwOTJmOTUzOGQyNzRiYmU5YTFkMDcwZDFiZWI5ODUzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzczZDdkMWU4NmJlMzRmNDFiYWJmYWVhYTJkNzVkOWY0ID0gJCgnPGRpdiBpZD0iaHRtbF83M2Q3ZDFlODZiZTM0ZjQxYmFiZmFlYWEyZDc1ZDlmNCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TWF0dGhld3MgQmVhY2ggQ2x1c3RlciAxPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81MDkyZjk1MzhkMjc0YmJlOWExZDA3MGQxYmViOTg1My5zZXRDb250ZW50KGh0bWxfNzNkN2QxZTg2YmUzNGY0MWJhYmZhZWFhMmQ3NWQ5ZjQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZWZhMGJhNGE3OGVlNDYzYzk2MzI1MjA5ZTMyMzU0NTIuYmluZFBvcHVwKHBvcHVwXzUwOTJmOTUzOGQyNzRiYmU5YTFkMDcwZDFiZWI5ODUzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Q3ZDEwYjI3MDI2MDQwMGFiYzdmYjNhN2ZhNzhjYTEwID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjg5OSwtMTIyLjI5NjQ4MzEyOF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmFkZGRkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJhZGRkZCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF80NTZkYjYyNzRlZjU0ODVkYWRmN2M1MzQyNjMzMGU1MiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8yOTllOTk4YjQ3YWY0ZTU2OGQyMmZlNTk2MmQ0YTJjNiA9ICQoJzxkaXYgaWQ9Imh0bWxfMjk5ZTk5OGI0N2FmNGU1NjhkMjJmZTU5NjJkNGEyYzYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldlZGd3b29kIENsdXN0ZXIgMzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNDU2ZGI2Mjc0ZWY1NDg1ZGFkZjdjNTM0MjYzMzBlNTIuc2V0Q29udGVudChodG1sXzI5OWU5OThiNDdhZjRlNTY4ZDIyZmU1OTYyZDRhMmM2KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2Q3ZDEwYjI3MDI2MDQwMGFiYzdmYjNhN2ZhNzhjYTEwLmJpbmRQb3B1cChwb3B1cF80NTZkYjYyNzRlZjU0ODVkYWRmN2M1MzQyNjMzMGU1Mik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84N2UwODE4N2M4MWQ0ZjRiOWYzYmIwZWNhMzY1YTE3NCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjYyMTksLTEyMi4zMzgzOTQyNzRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzJhZGRkZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMyYWRkZGQiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfZGMyNjUxMDc1ZWM5NDVlMDk1YzAzZDE3ZDk1ZDI2MWEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjQzZDBkNjJiODkxNGY3OTg5ZGE4NzBjZDQyYWI2MTIgPSAkKCc8ZGl2IGlkPSJodG1sX2Y0M2QwZDYyYjg5MTRmNzk4OWRhODcwY2Q0MmFiNjEyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Tb3V0aCBMYWtlIFVuaW9uIENsdXN0ZXIgMzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZGMyNjUxMDc1ZWM5NDVlMDk1YzAzZDE3ZDk1ZDI2MWEuc2V0Q29udGVudChodG1sX2Y0M2QwZDYyYjg5MTRmNzk4OWRhODcwY2Q0MmFiNjEyKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzg3ZTA4MTg3YzgxZDRmNGI5ZjNiYjBlY2EzNjVhMTc0LmJpbmRQb3B1cChwb3B1cF9kYzI2NTEwNzVlYzk0NWUwOTVjMDNkMTdkOTVkMjYxYSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zNWMxYWRiOTU5Mzg0YTVkYTVkMmE5ZTQwNzI2ZGFjZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjUyMzIsLTEyMi4zODg5Nzg0NTldLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmN2U0MSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjdlNDEiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNjc5MmUxYjJiZDUwNDgzY2FkN2JhMWFiMmYwOGFhZDEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzE4ZDExZmE4NjVkNDg5ZGFkNjczZTMzNDZhNGJmMjkgPSAkKCc8ZGl2IGlkPSJodG1sXzcxOGQxMWZhODY1ZDQ4OWRhZDY3M2UzMzQ2YTRiZjI5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5GYXVudGxlcm95IENsdXN0ZXIgNjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNjc5MmUxYjJiZDUwNDgzY2FkN2JhMWFiMmYwOGFhZDEuc2V0Q29udGVudChodG1sXzcxOGQxMWZhODY1ZDQ4OWRhZDY3M2UzMzQ2YTRiZjI5KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzM1YzFhZGI5NTkzODRhNWRhNWQyYTllNDA3MjZkYWNkLmJpbmRQb3B1cChwb3B1cF82NzkyZTFiMmJkNTA0ODNjYWQ3YmExYWIyZjA4YWFkMSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80OThiNzllMjZjNWI0MjI4YWJiMGFhMDE5ZGUzMmRlOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjYyNzIsLTEyMi4zMTI0NTE3NTRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzJhZGRkZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMyYWRkZGQiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYWZmYTMyYTgxOWI3NGViMmE5ZGVlZGFmOTNjMDlmNDkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZjNkMTc0ZmVhYjJiNDY1ZDlhNzNlZjEwNDMzYzU5YzQgPSAkKCc8ZGl2IGlkPSJodG1sX2YzZDE3NGZlYWIyYjQ2NWQ5YTczZWYxMDQzM2M1OWM0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5DYXBpdG9sIEhpbGwgQ2x1c3RlciAzPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hZmZhMzJhODE5Yjc0ZWIyYTlkZWVkYWY5M2MwOWY0OS5zZXRDb250ZW50KGh0bWxfZjNkMTc0ZmVhYjJiNDY1ZDlhNzNlZjEwNDMzYzU5YzQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNDk4Yjc5ZTI2YzViNDIyOGFiYjBhYTAxOWRlMzJkZTkuYmluZFBvcHVwKHBvcHVwX2FmZmEzMmE4MTliNzRlYjJhOWRlZWRhZjkzYzA5ZjQ5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzc0ZGJiNDVjMzdiODQ3MmZhMDE0NzRkZTljNzJmZTI0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjA4NSwtMTIyLjMyMzY4OTE5OF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81YTk3Zjk0N2NlZTE0YTFhYmYzZDAxZmQ1MjY1ZGZhZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF83MDkzZjI1ZDBjNzM0NTk4YTYwNmQ5NGJkNWQyYThiNiA9ICQoJzxkaXYgaWQ9Imh0bWxfNzA5M2YyNWQwYzczNDU5OGE2MDZkOTRiZDVkMmE4YjYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZpcnN0IEhpbGwgQ2x1c3RlciAyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81YTk3Zjk0N2NlZTE0YTFhYmYzZDAxZmQ1MjY1ZGZhZC5zZXRDb250ZW50KGh0bWxfNzA5M2YyNWQwYzczNDU5OGE2MDZkOTRiZDVkMmE4YjYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzRkYmI0NWMzN2I4NDcyZmEwMTQ3NGRlOWM3MmZlMjQuYmluZFBvcHVwKHBvcHVwXzVhOTdmOTQ3Y2VlMTRhMWFiZjNkMDFmZDUyNjVkZmFkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzc3ZmQ4NzI5N2ExMTQ3NmFiMTBlMWZlZTYzMWI0NTljID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTA3OSwtMTIyLjM4MDg0OTI5NF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmY3ZTQxIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmN2U0MSIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82MTQwMjc4OTYzOTM0YjlmYTdjMWVmNzNhZjBkMTZlOSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8zMjhlNjRjNjY5ZTU0NTMwYTdhMWVjYmVlZDUwYjAwYSA9ICQoJzxkaXYgaWQ9Imh0bWxfMzI4ZTY0YzY2OWU1NDUzMGE3YTFlY2JlZWQ1MGIwMGEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkFyYm9yIEhlaWdodHMgQ2x1c3RlciA2PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82MTQwMjc4OTYzOTM0YjlmYTdjMWVmNzNhZjBkMTZlOS5zZXRDb250ZW50KGh0bWxfMzI4ZTY0YzY2OWU1NDUzMGE3YTFlY2JlZWQ1MGIwMGEpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNzdmZDg3Mjk3YTExNDc2YWIxMGUxZmVlNjMxYjQ1OWMuYmluZFBvcHVwKHBvcHVwXzYxNDAyNzg5NjM5MzRiOWZhN2MxZWY3M2FmMGQxNmU5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzkwNDFhZjM2NTMxNDQwMDRiZTRiNzIyMTlkNGJmN2Q4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNzA4MSwtMTIyLjMyMTg1NjU4NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xZWJhNjM0Njg4ZDc0MWQ3YmEzYTc1M2UyZmZjYWMwZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wMmQ3MzMwMGZjOTU0MDNkYTYwOTBkMWZkZmJkYTg3MSA9ICQoJzxkaXYgaWQ9Imh0bWxfMDJkNzMzMDBmYzk1NDAzZGE2MDkwZDFmZGZiZGE4NzEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk5vcnRoZ2F0ZSBDbHVzdGVyIDI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzFlYmE2MzQ2ODhkNzQxZDdiYTNhNzUzZTJmZmNhYzBkLnNldENvbnRlbnQoaHRtbF8wMmQ3MzMwMGZjOTU0MDNkYTYwOTBkMWZkZmJkYTg3MSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85MDQxYWYzNjUzMTQ0MDA0YmU0YjcyMjE5ZDRiZjdkOC5iaW5kUG9wdXAocG9wdXBfMWViYTYzNDY4OGQ3NDFkN2JhM2E3NTNlMmZmY2FjMGQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYzcwMGQ3MWU4ZjJlNGQ5NGE5YjQxNjQ3NmEwMjhmZDAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42MjUxLC0xMjIuMzU1NjUwMDU3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMyYzdlZjciLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMmM3ZWY3IiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzQ5NzZkOThjZDg4NTRhNTg4NmRjMGY4N2RmZDhmMWI1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzVkYjM5Nzg2Y2U4NDRjZDc5NjA0YTg0NmQ1YTYwNjFiID0gJCgnPGRpdiBpZD0iaHRtbF81ZGIzOTc4NmNlODQ0Y2Q3OTYwNGE4NDZkNWE2MDYxYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TG93ZXIgUXVlZW4gQW5uZSBDbHVzdGVyIDI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzQ5NzZkOThjZDg4NTRhNTg4NmRjMGY4N2RmZDhmMWI1LnNldENvbnRlbnQoaHRtbF81ZGIzOTc4NmNlODQ0Y2Q3OTYwNGE4NDZkNWE2MDYxYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jNzAwZDcxZThmMmU0ZDk0YTliNDE2NDc2YTAyOGZkMC5iaW5kUG9wdXAocG9wdXBfNDk3NmQ5OGNkODg1NGE1ODg2ZGMwZjg3ZGZkOGYxYjUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZmZlMWMzOTJmZmU0NDEyODgxNmFjNmM5Yzg1ZDc0MDQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42Mzc5LC0xMjIuMzI4MjI5MjM0XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMyYzdlZjciLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMmM3ZWY3IiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2JmZmQ1YzZlN2ZlMjRlYzg5OGYyNjQ4ODAzZGJhNTY0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzFhNDAyYTA3M2RiMzRiMjdiY2FjNTA1MjczZjhkYTEzID0gJCgnPGRpdiBpZD0iaHRtbF8xYTQwMmEwNzNkYjM0YjI3YmNhYzUwNTI3M2Y4ZGExMyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+RWFzdGxha2UgQ2x1c3RlciAyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9iZmZkNWM2ZTdmZTI0ZWM4OThmMjY0ODgwM2RiYTU2NC5zZXRDb250ZW50KGh0bWxfMWE0MDJhMDczZGIzNGIyN2JjYWM1MDUyNzNmOGRhMTMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZmZlMWMzOTJmZmU0NDEyODgxNmFjNmM5Yzg1ZDc0MDQuYmluZFBvcHVwKHBvcHVwX2JmZmQ1YzZlN2ZlMjRlYzg5OGYyNjQ4ODAzZGJhNTY0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzBjMDMzOWM3ZDI5ZTQ3Y2JhZGNmYzg5ZjBkYjgyNDFiID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTc2LC0xMjIuMjg2OTc1Mzk1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjdlNDEiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmY3ZTQxIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzgzY2FiZTk2MWE5ODQ0OGRhYWYyMGQzYTg4NmY2ZGEzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzllYWE0MDFkMDFmNTQ5NjViOTk4YThhMTViMzliYjBkID0gJCgnPGRpdiBpZD0iaHRtbF85ZWFhNDAxZDAxZjU0OTY1Yjk5OGE4YTE1YjM5YmIwZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TW91bnQgQmFrZXIgQ2x1c3RlciA2PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF84M2NhYmU5NjFhOTg0NDhkYWFmMjBkM2E4ODZmNmRhMy5zZXRDb250ZW50KGh0bWxfOWVhYTQwMWQwMWY1NDk2NWI5OThhOGExNWIzOWJiMGQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMGMwMzM5YzdkMjllNDdjYmFkY2ZjODlmMGRiODI0MWIuYmluZFBvcHVwKHBvcHVwXzgzY2FiZTk2MWE5ODQ0OGRhYWYyMGQzYTg4NmY2ZGEzKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzZlZTRlNDdkNDFjNjQxMjdiYWZkYTFkYWU0NGRhMzVhID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNzIwMywtMTIyLjMzNTA5OTc0MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmFkZGRkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJhZGRkZCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jNTAzZmIyMTEyYzA0ZWRiOTViMGIwZTVlNWEyM2M0YyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80NmM1MmZjMTAzYzU0N2Q2YjNkNTFhMjlmYmU3MjU2ZSA9ICQoJzxkaXYgaWQ9Imh0bWxfNDZjNTJmYzEwM2M1NDdkNmIzZDUxYTI5ZmJlNzI1NmUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhhbGxlciBMYWtlIENsdXN0ZXIgMzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYzUwM2ZiMjExMmMwNGVkYjk1YjBiMGU1ZTVhMjNjNGMuc2V0Q29udGVudChodG1sXzQ2YzUyZmMxMDNjNTQ3ZDZiM2Q1MWEyOWZiZTcyNTZlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzZlZTRlNDdkNDFjNjQxMjdiYWZkYTFkYWU0NGRhMzVhLmJpbmRQb3B1cChwb3B1cF9jNTAzZmIyMTEyYzA0ZWRiOTViMGIwZTVlNWEyM2M0Yyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl83NGVhZDNjYTA2Y2Y0NzZhYjliM2YwMzU3NzBmNjI2YiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjcwNiwtMTIyLjI5NzEyODgyN10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmYwMDAwIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmMDAwMCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wMjM2OTZhZmNhNDQ0YjFkOGZmMzgyZjY4MjAxMmQwNyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xNzIzMDVhZmUyZTc0ZGRkYTY5MDJkMmU5MmY4M2FiZiA9ICQoJzxkaXYgaWQ9Imh0bWxfMTcyMzA1YWZlMmU3NGRkZGE2OTAyZDJlOTJmODNhYmYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1lYWRvd2Jyb29rIENsdXN0ZXIgMDwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMDIzNjk2YWZjYTQ0NGIxZDhmZjM4MmY2ODIwMTJkMDcuc2V0Q29udGVudChodG1sXzE3MjMwNWFmZTJlNzRkZGRhNjkwMmQyZTkyZjgzYWJmKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzc0ZWFkM2NhMDZjZjQ3NmFiOWIzZjAzNTc3MGY2MjZiLmJpbmRQb3B1cChwb3B1cF8wMjM2OTZhZmNhNDQ0YjFkOGZmMzgyZjY4MjAxMmQwNyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8wOTc1NjNkYWFjY2Y0ZTgxODJkNzM0YmI3NzcxMDY4ZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjYwNjgsLTEyMi4zMzk5ODg4OTFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzJjN2VmNyIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMyYzdlZjciLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYTNmZmNiMTFhYTE4NGM4YWE3OWFmNmU2NTQzODM3MDUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNTgzYWRiOTAyZWZjNGU4YWE3MzRmYWRiNjZmMWExZjkgPSAkKCc8ZGl2IGlkPSJodG1sXzU4M2FkYjkwMmVmYzRlOGFhNzM0ZmFkYjY2ZjFhMWY5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Eb3dudG93biBDbHVzdGVyIDI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2EzZmZjYjExYWExODRjOGFhNzlhZjZlNjU0MzgzNzA1LnNldENvbnRlbnQoaHRtbF81ODNhZGI5MDJlZmM0ZThhYTczNGZhZGI2NmYxYTFmOSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wOTc1NjNkYWFjY2Y0ZTgxODJkNzM0YmI3NzcxMDY4ZC5iaW5kUG9wdXAocG9wdXBfYTNmZmNiMTFhYTE4NGM4YWE3OWFmNmU2NTQzODM3MDUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMTQ5ZDRiMzNjNjdiNDQyYjgxYTQ2Yzg0MDhmMWIxOTkgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny41ODAzLC0xMjIuMzg3MTE3OTYyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMyYzdlZjciLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMmM3ZWY3IiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzUzYjUyMjgyMGQ1YTQ2MzM5MTRiNmNkY2I4OTJjMzNlID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzQwY2ZmOGFkYmE1ZjQ4YzI4OWI4N2E5OTdkZTY4MWYxID0gJCgnPGRpdiBpZD0iaHRtbF80MGNmZjhhZGJhNWY0OGMyODliODdhOTk3ZGU2ODFmMSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QWRtaXJhbCBDbHVzdGVyIDI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzUzYjUyMjgyMGQ1YTQ2MzM5MTRiNmNkY2I4OTJjMzNlLnNldENvbnRlbnQoaHRtbF80MGNmZjhhZGJhNWY0OGMyODliODdhOTk3ZGU2ODFmMSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xNDlkNGIzM2M2N2I0NDJiODFhNDZjODQwOGYxYjE5OS5iaW5kUG9wdXAocG9wdXBfNTNiNTIyODIwZDVhNDYzMzkxNGI2Y2RjYjg5MmMzM2UpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMWEzNzljYTA2OTgxNDFmZDlhNmIxZTJjMjgzYmE1NmMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42OTksLTEyMi4zMzY3NjYzODVdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmN2U0MSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjdlNDEiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNWU2ODk0ZGY4Y2Y4NDkyYTg2ZWNjYzZmYmYzOWU1NGQgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMjgzNGZiODE5NzcxNDc0YjlhODdhYTk2ZGE4ZjFiZWQgPSAkKCc8ZGl2IGlkPSJodG1sXzI4MzRmYjgxOTc3MTQ3NGI5YTg3YWE5NmRhOGYxYmVkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ob3J0aCBDb2xsZWdlIFBhcmsgQ2x1c3RlciA2PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81ZTY4OTRkZjhjZjg0OTJhODZlY2NjNmZiZjM5ZTU0ZC5zZXRDb250ZW50KGh0bWxfMjgzNGZiODE5NzcxNDc0YjlhODdhYTk2ZGE4ZjFiZWQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMWEzNzljYTA2OTgxNDFmZDlhNmIxZTJjMjgzYmE1NmMuYmluZFBvcHVwKHBvcHVwXzVlNjg5NGRmOGNmODQ5MmE4NmVjY2M2ZmJmMzllNTRkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzRjYjM3N2Q4YTYzYTQwY2Q5NGNjZGFkYjQyMDE0ZWRmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjQxNCwtMTIyLjM2MDk1NzcyOF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83ZDkyMmNjNDIwNzQ0MjBkODcxMTgxMWZlZWI1Yzc4ZSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wYWQyZmFkMGQ5M2U0Y2Y0YmJjZmJlN2U5MTVjOTM4MiA9ICQoJzxkaXYgaWQ9Imh0bWxfMGFkMmZhZDBkOTNlNGNmNGJiY2ZiZTdlOTE1YzkzODIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlF1ZWVuIEFubmUgQ2x1c3RlciAyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83ZDkyMmNjNDIwNzQ0MjBkODcxMTgxMWZlZWI1Yzc4ZS5zZXRDb250ZW50KGh0bWxfMGFkMmZhZDBkOTNlNGNmNGJiY2ZiZTdlOTE1YzkzODIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNGNiMzc3ZDhhNjNhNDBjZDk0Y2NkYWRiNDIwMTRlZGYuYmluZFBvcHVwKHBvcHVwXzdkOTIyY2M0MjA3NDQyMGQ4NzExODExZmVlYjVjNzhlKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzgyZDc3NmY4OWFkMDQ4NjQ5NDhiOGFjY2RlYmNhM2ViID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTkwNSwtMTIyLjMwMTU2Mzg4Ml0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82ZjNhNDhjNjFhNWM0YmRlOGEzZjA5Yjk4MjMyMGU5NyA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF84YmRlNDk4MGJlNDU0MWRiOTljZTRlODNjMjc3NTM2MyA9ICQoJzxkaXYgaWQ9Imh0bWxfOGJkZTQ5ODBiZTQ1NDFkYjk5Y2U0ZTgzYzI3NzUzNjMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkF0bGFudGljIENsdXN0ZXIgMjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNmYzYTQ4YzYxYTVjNGJkZThhM2YwOWI5ODIzMjBlOTcuc2V0Q29udGVudChodG1sXzhiZGU0OTgwYmU0NTQxZGI5OWNlNGU4M2MyNzc1MzYzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzgyZDc3NmY4OWFkMDQ4NjQ5NDhiOGFjY2RlYmNhM2ViLmJpbmRQb3B1cChwb3B1cF82ZjNhNDhjNjFhNWM0YmRlOGEzZjA5Yjk4MjMyMGU5Nyk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mNTM4NzY1OTY4NmE0YzM3OWFhZTVhNjdiZTllODgxZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjYyMTYsLTEyMi4yODQ5NDAwNTNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmN2U0MSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjdlNDEiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYzc0ZGZmZThlNTc4NDA1ZGJkOTk0OGJjYzZmMTNmODggPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzk5MGE1NmM1MGIxNDBiZGE4YjI2MDE4NzhkMzM1ODMgPSAkKCc8ZGl2IGlkPSJodG1sXzc5OTBhNTZjNTBiMTQwYmRhOGIyNjAxODc4ZDMzNTgzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5EZW5ueS1CbGFpbmUgQ2x1c3RlciA2PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jNzRkZmZlOGU1Nzg0MDVkYmQ5OTQ4YmNjNmYxM2Y4OC5zZXRDb250ZW50KGh0bWxfNzk5MGE1NmM1MGIxNDBiZGE4YjI2MDE4NzhkMzM1ODMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjUzODc2NTk2ODZhNGMzNzlhYWU1YTY3YmU5ZTg4MWUuYmluZFBvcHVwKHBvcHVwX2M3NGRmZmU4ZTU3ODQwNWRiZDk5NDhiY2M2ZjEzZjg4KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzIzYzc5Y2YwNGRjYjQyNWRhOTU2MWFiZmQxMjE4ZWEzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjIxOSwtMTIyLjI5NjExODYwN10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9kODdiNWI1MTEwMTY0YzhkYjJlM2M2ZDMyY2Y2ZDNiZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wNjJlODdhMjgyMzk0MmE4ODI0NDJiZjAzNmQ0ZDc2NCA9ICQoJzxkaXYgaWQ9Imh0bWxfMDYyZTg3YTI4MjM5NDJhODgyNDQyYmYwMzZkNGQ3NjQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPk1hZGlzb24gVmFsbGV5IENsdXN0ZXIgMjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZDg3YjViNTExMDE2NGM4ZGIyZTNjNmQzMmNmNmQzYmQuc2V0Q29udGVudChodG1sXzA2MmU4N2EyODIzOTQyYTg4MjQ0MmJmMDM2ZDRkNzY0KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzIzYzc5Y2YwNGRjYjQyNWRhOTU2MWFiZmQxMjE4ZWEzLmJpbmRQb3B1cChwb3B1cF9kODdiNWI1MTEwMTY0YzhkYjJlM2M2ZDMyY2Y2ZDNiZCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lNjUwYTZlYjlhYWU0OThlYWEwNDY5NzdmYTQxYjkzNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjYwNiwtMTIyLjMwNjQ4MDU1OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmFkZGRkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJhZGRkZCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mYTRiMjJmN2QwZjM0YzkwYWNiY2Y4MmJhNGRhNzZjMiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82NGY3N2U4NGQ2NDY0NDg0ODc4NWYwNDUzNjUxNzVlMiA9ICQoJzxkaXYgaWQ9Imh0bWxfNjRmNzdlODRkNjQ2NDQ4NDg3ODVmMDQ1MzY1MTc1ZTIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNlbnRyYWwgRGlzdHJpY3QgQ2x1c3RlciAzPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mYTRiMjJmN2QwZjM0YzkwYWNiY2Y4MmJhNGRhNzZjMi5zZXRDb250ZW50KGh0bWxfNjRmNzdlODRkNjQ2NDQ4NDg3ODVmMDQ1MzY1MTc1ZTIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZTY1MGE2ZWI5YWFlNDk4ZWFhMDQ2OTc3ZmE0MWI5MzQuYmluZFBvcHVwKHBvcHVwX2ZhNGIyMmY3ZDBmMzRjOTBhY2JjZjgyYmE0ZGE3NmMyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2NjNDRiMmVhMjIxNDQxMmI4MDFlMzRjYjI5MmIwZTM5ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTk3NSwtMTIyLjMxOTQ4MjUyMV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82ZTVkOTg1MDQyM2M0NGM2OWY2NDUxOGVkN2MxMTAyOSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iNDg0NjlhMTljMDI0MjUxOTcyOWY2YzlkMGEwYzJhOCA9ICQoJzxkaXYgaWQ9Imh0bWxfYjQ4NDY5YTE5YzAyNDI1MTk3MjlmNmM5ZDBhMGMyYTgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkludGVybmF0aW9uYWwgRGlzdHJpY3QgQ2x1c3RlciAyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82ZTVkOTg1MDQyM2M0NGM2OWY2NDUxOGVkN2MxMTAyOS5zZXRDb250ZW50KGh0bWxfYjQ4NDY5YTE5YzAyNDI1MTk3MjlmNmM5ZDBhMGMyYTgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfY2M0NGIyZWEyMjE0NDEyYjgwMWUzNGNiMjkyYjBlMzkuYmluZFBvcHVwKHBvcHVwXzZlNWQ5ODUwNDIzYzQ0YzY5ZjY0NTE4ZWQ3YzExMDI5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y2ZTU5MmZiNmM0MTRiZGY4NTQ3MmE4ZTc1ZTgyN2YzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTY5OCwtMTIyLjM0NTcyOTc0N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmFkZGRkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJhZGRkZCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yMjg1NWZiOTgwMjQ0OTllYmU1ZDczMWZiNjAxYWEwNCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9hZmVmNTdkMTIxYjY0MjkyYTYyMTk2NDRiYTIxYzFlMyA9ICQoJzxkaXYgaWQ9Imh0bWxfYWZlZjU3ZDEyMWI2NDI5MmE2MjE5NjQ0YmEyMWMxZTMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkluZHVzdHJpYWwgRGlzdHJpY3QgQ2x1c3RlciAzPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yMjg1NWZiOTgwMjQ0OTllYmU1ZDczMWZiNjAxYWEwNC5zZXRDb250ZW50KGh0bWxfYWZlZjU3ZDEyMWI2NDI5MmE2MjE5NjQ0YmEyMWMxZTMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZjZlNTkyZmI2YzQxNGJkZjg1NDcyYThlNzVlODI3ZjMuYmluZFBvcHVwKHBvcHVwXzIyODU1ZmI5ODAyNDQ5OWViZTVkNzMxZmI2MDFhYTA0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzNmZGZkZDc4NzQ3MDQ0ZWI4M2QxNTEwOGRkOWMzNDY2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjYwMywtMTIyLjMwNjMxMTQxOF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF82M2U5NjAyMDhmZjk0NGQ3ODQ3ZjFjNjI3MDIwZTgyMSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82Y2Q2OGVjNDUxNzA0YmVkYTc5NmNmNzgwMGFmZTk1ZiA9ICQoJzxkaXYgaWQ9Imh0bWxfNmNkNjhlYzQ1MTcwNGJlZGE3OTZjZjc4MDBhZmU5NWYiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlVuaXZlcnNpdHkgRGlzdHJpY3QgQ2x1c3RlciAyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF82M2U5NjAyMDhmZjk0NGQ3ODQ3ZjFjNjI3MDIwZTgyMS5zZXRDb250ZW50KGh0bWxfNmNkNjhlYzQ1MTcwNGJlZGE3OTZjZjc4MDBhZmU5NWYpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfM2ZkZmRkNzg3NDcwNDRlYjgzZDE1MTA4ZGQ5YzM0NjYuYmluZFBvcHVwKHBvcHVwXzYzZTk2MDIwOGZmOTQ0ZDc4NDdmMWM2MjcwMjBlODIxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzIxNTg5YjA4YzY1NDQ5OGFiYTQ2YzhlNDI5MGQ4MmUxID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNzA1MiwtMTIyLjM3NjMyNDI0MV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmY3ZTQxIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmN2U0MSIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF81NzFjNGFhNmMwMTQ0YzAxODM5NTZhMzk2MTMwOTM1ZCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81MGVjYTNkOWYzMGU0NTdlYmE3YzAzNTg2YTZmNzA2OSA9ICQoJzxkaXYgaWQ9Imh0bWxfNTBlY2EzZDlmMzBlNDU3ZWJhN2MwMzU4NmE2ZjcwNjkiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJsdWUgUmlkZ2UgQ2x1c3RlciA2PC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81NzFjNGFhNmMwMTQ0YzAxODM5NTZhMzk2MTMwOTM1ZC5zZXRDb250ZW50KGh0bWxfNTBlY2EzZDlmMzBlNDU3ZWJhN2MwMzU4NmE2ZjcwNjkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMjE1ODliMDhjNjU0NDk4YWJhNDZjOGU0MjkwZDgyZTEuYmluZFBvcHVwKHBvcHVwXzU3MWM0YWE2YzAxNDRjMDE4Mzk1NmEzOTYxMzA5MzVkKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzA5NmFhNTI4ZTE3NzQ4ZDZiZTUxNDgwYjA1YTQwNTE5ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjY2NSwtMTIyLjM3NjA1MTg3N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83MDAwZTM4YWQ5YmQ0N2YzYmRmZTlkYmMyMGEyOWMwNiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF82NDMyYjk5MzEyYjA0MThhYTIxN2ViNzdiNjAwOWJiNSA9ICQoJzxkaXYgaWQ9Imh0bWxfNjQzMmI5OTMxMmIwNDE4YWEyMTdlYjc3YjYwMDliYjUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJhbGxhcmQgQ2x1c3RlciAyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF83MDAwZTM4YWQ5YmQ0N2YzYmRmZTlkYmMyMGEyOWMwNi5zZXRDb250ZW50KGh0bWxfNjQzMmI5OTMxMmIwNDE4YWEyMTdlYjc3YjYwMDliYjUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMDk2YWE1MjhlMTc3NDhkNmJlNTE0ODBiMDVhNDA1MTkuYmluZFBvcHVwKHBvcHVwXzcwMDBlMzhhZDliZDQ3ZjNiZGZlOWRiYzIwYTI5YzA2KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2UwZjQ3NzA3NzZhODQwNTc5OGQyMzlkOTFmMTg0OWQ0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjQ1NCwtMTIyLjMxNzE0Mjc4OV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yNWM0OTBjMjE4NWM0NjFkYWU3NTgzNmFhYjY0N2E2MCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF80YTM2NTBjYzNiYWU0YTlmODg4OWYwN2UxMDBmYzNhZSA9ICQoJzxkaXYgaWQ9Imh0bWxfNGEzNjUwY2MzYmFlNGE5Zjg4ODlmMDdlMTAwZmMzYWUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlBvcnRhZ2UgQmF5IENsdXN0ZXIgMjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMjVjNDkwYzIxODVjNDYxZGFlNzU4MzZhYWI2NDdhNjAuc2V0Q29udGVudChodG1sXzRhMzY1MGNjM2JhZTRhOWY4ODg5ZjA3ZTEwMGZjM2FlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2UwZjQ3NzA3NzZhODQwNTc5OGQyMzlkOTFmMTg0OWQ0LmJpbmRQb3B1cChwb3B1cF8yNWM0OTBjMjE4NWM0NjFkYWU3NTgzNmFhYjY0N2E2MCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zMmU1OGZiNjMyZjM0MTZjYjg2ZjIyYzgyZDllZjMzNSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjUyNzMsLTEyMi4zNzEwMDU2NjRdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiI2ZmN2U0MSIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiNmZjdlNDEiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNDQxMTJkNDMyOTE1NDg2NGIwZmYyZGViMWI5NDg0MWIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfZmNhMzg1ZmM4YmI0NGQ0YWE3NzRhMzlmOThkZTM5MmQgPSAkKCc8ZGl2IGlkPSJodG1sX2ZjYTM4NWZjOGJiNDRkNGFhNzc0YTM5Zjk4ZGUzOTJkIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Sb3hoaWxsIENsdXN0ZXIgNjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNDQxMTJkNDMyOTE1NDg2NGIwZmYyZGViMWI5NDg0MWIuc2V0Q29udGVudChodG1sX2ZjYTM4NWZjOGJiNDRkNGFhNzc0YTM5Zjk4ZGUzOTJkKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzMyZTU4ZmI2MzJmMzQxNmNiODZmMjJjODJkOWVmMzM1LmJpbmRQb3B1cChwb3B1cF80NDExMmQ0MzI5MTU0ODY0YjBmZjJkZWIxYjk0ODQxYik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82ZjI2YmFmZmVkMjg0ZDZmYjkwMWExNmM0Njg2MDI3ZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjU2MjcsLTEyMi4zNjQ1OTE2ODddLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzJhZGRkZCIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMyYWRkZGQiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfY2Q5ZGQzYmNlM2YxNGUxY2JkMWI0ODdhY2UyMWQ5ZGUgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMzZkNjIwZjY5YjQ3NGYzZDljYTNjNmYwYzNjZWFiYTIgPSAkKCc8ZGl2IGlkPSJodG1sXzM2ZDYyMGY2OWI0NzRmM2Q5Y2EzYzZmMGMzY2VhYmEyIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ob3J0aCBEZWxyaWRnZSBDbHVzdGVyIDM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2NkOWRkM2JjZTNmMTRlMWNiZDFiNDg3YWNlMjFkOWRlLnNldENvbnRlbnQoaHRtbF8zNmQ2MjBmNjliNDc0ZjNkOWNhM2M2ZjBjM2NlYWJhMik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82ZjI2YmFmZmVkMjg0ZDZmYjkwMWExNmM0Njg2MDI3ZC5iaW5kUG9wdXAocG9wdXBfY2Q5ZGQzYmNlM2YxNGUxY2JkMWI0ODdhY2UyMWQ5ZGUpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMDdjMTViNmI3MWU1NDY5NTk0N2ZmZGFiZmVmYjk3ODYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny41MjgsLTEyMi4zNDMwNjQwODJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzJjN2VmNyIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMyYzdlZjciLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfYmYyMWY4Njk3ZjZkNDUxMmIyZTY1Y2VlMTQwMTQ3OWEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMzEwOGM5MTAwNzM5NDE2OTg4ZmQwNWU3Y2NmYTA3ZGUgPSAkKCc8ZGl2IGlkPSJodG1sXzMxMDhjOTEwMDczOTQxNjk4OGZkMDVlN2NjZmEwN2RlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5IaWdobGFuZCBQYXJrIENsdXN0ZXIgMjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfYmYyMWY4Njk3ZjZkNDUxMmIyZTY1Y2VlMTQwMTQ3OWEuc2V0Q29udGVudChodG1sXzMxMDhjOTEwMDczOTQxNjk4OGZkMDVlN2NjZmEwN2RlKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzA3YzE1YjZiNzFlNTQ2OTU5NDdmZmRhYmZlZmI5Nzg2LmJpbmRQb3B1cChwb3B1cF9iZjIxZjg2OTdmNmQ0NTEyYjJlNjVjZWUxNDAxNDc5YSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mYjI1MjdhNWQ1ZTI0OWIyYTNhODlkMjQ0NDUyYzYzMCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjY1NywtMTIyLjM1MzI5NDA4OF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmFkZGRkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJhZGRkZCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xZDdiNWQ3ZjkzMWU0YmExYjQxNjMzNWJlZTBhMDFjMiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9jZmViOWNiODBkNmU0MzZlYjNlMjY0NTEwODE5YzBjOCA9ICQoJzxkaXYgaWQ9Imh0bWxfY2ZlYjljYjgwZDZlNDM2ZWIzZTI2NDUxMDgxOWMwYzgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkZyZW1vbnQgQ2x1c3RlciAzPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8xZDdiNWQ3ZjkzMWU0YmExYjQxNjMzNWJlZTBhMDFjMi5zZXRDb250ZW50KGh0bWxfY2ZlYjljYjgwZDZlNDM2ZWIzZTI2NDUxMDgxOWMwYzgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfZmIyNTI3YTVkNWUyNDliMmEzYTg5ZDI0NDQ1MmM2MzAuYmluZFBvcHVwKHBvcHVwXzFkN2I1ZDdmOTMxZTRiYTFiNDE2MzM1YmVlMGEwMWMyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzM1ODUyNTQwMjlmODQ3OGU5OGU3YjNlMGNmYjc5MmU3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjU5MywtMTIyLjMzMzc0OTM3N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF83YzI3NWYzODUyZDE0MTA0YThiODE5YTVhZTQwZmU3ZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iZDFkMTQxNTRmM2E0ZjQwOGZlNjcwMzVjZjZkOWJmYSA9ICQoJzxkaXYgaWQ9Imh0bWxfYmQxZDE0MTU0ZjNhNGY0MDhmZTY3MDM1Y2Y2ZDliZmEiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldhbGxpbmdmb3JkIENsdXN0ZXIgMjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfN2MyNzVmMzg1MmQxNDEwNGE4YjgxOWE1YWU0MGZlN2Yuc2V0Q29udGVudChodG1sX2JkMWQxNDE1NGYzYTRmNDA4ZmU2NzAzNWNmNmQ5YmZhKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzM1ODUyNTQwMjlmODQ3OGU5OGU3YjNlMGNmYjc5MmU3LmJpbmRQb3B1cChwb3B1cF83YzI3NWYzODUyZDE0MTA0YThiODE5YTVhZTQwZmU3Zik7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jNjlkZGE0Zjc3Zjc0ZTEwYmE3NmU2YjlhMmE4YzdmMyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjY3MjIsLTEyMi4yNzI1MjcwN10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmY3ZTQxIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmN2U0MSIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xYWQ2MWIwODNkOTY0OGVmYmM0NjBjZjE3MGZlYjliMiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9kMzc0YTc2YmNkODQ0ZTYyYmY4OGViNWIzZGRiYTQ4MiA9ICQoJzxkaXYgaWQ9Imh0bWxfZDM3NGE3NmJjZDg0NGU2MmJmODhlYjViM2RkYmE0ODIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkhhd3Rob3JuZSBIaWxscyBDbHVzdGVyIDY8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzFhZDYxYjA4M2Q5NjQ4ZWZiYzQ2MGNmMTcwZmViOWIyLnNldENvbnRlbnQoaHRtbF9kMzc0YTc2YmNkODQ0ZTYyYmY4OGViNWIzZGRiYTQ4Mik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9jNjlkZGE0Zjc3Zjc0ZTEwYmE3NmU2YjlhMmE4YzdmMy5iaW5kUG9wdXAocG9wdXBfMWFkNjFiMDgzZDk2NDhlZmJjNDYwY2YxNzBmZWI5YjIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOTRmMGM3MmU5M2UzNDNhMGI2YjUxMGU2NGU0YTA3ZjUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42OTQyLC0xMjIuMzU1MjQ3NTFdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzJjN2VmNyIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMyYzdlZjciLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMjUzOTM1N2U0YmNlNDk5NmExZWFiZGQyNDBhMDMzNzAgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNDZlNmQ4NWE4ODllNGQ1ZWI2Mzc2ZWJjYzA2N2Q3YzkgPSAkKCc8ZGl2IGlkPSJodG1sXzQ2ZTZkODVhODg5ZTRkNWViNjM3NmViY2MwNjdkN2M5IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5HcmVlbndvb2QgQ2x1c3RlciAyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8yNTM5MzU3ZTRiY2U0OTk2YTFlYWJkZDI0MGEwMzM3MC5zZXRDb250ZW50KGh0bWxfNDZlNmQ4NWE4ODllNGQ1ZWI2Mzc2ZWJjYzA2N2Q3YzkpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOTRmMGM3MmU5M2UzNDNhMGI2YjUxMGU2NGU0YTA3ZjUuYmluZFBvcHVwKHBvcHVwXzI1MzkzNTdlNGJjZTQ5OTZhMWVhYmRkMjQwYTAzMzcwKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2U1MmY3ZDVmNGUyZTQ2MTY4NWY1YjBhMDY4NGJjZDRjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTk5NiwtMTIyLjI5MDY2NTQ3NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjZmY3ZTQxIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiI2ZmN2U0MSIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8xMTQ2ZWM0N2E4MjM0YzQ5OTJhMzgxZTg1YzlmNWY4ZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF81MjI4NjFiMTUzNDM0OGUxODRiYjQwMTU4OTNjNjk2MiA9ICQoJzxkaXYgaWQ9Imh0bWxfNTIyODYxYjE1MzQzNDhlMTg0YmI0MDE1ODkzYzY5NjIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkxlc2NoaSBDbHVzdGVyIDY8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzExNDZlYzQ3YTgyMzRjNDk5MmEzODFlODVjOWY1ZjhmLnNldENvbnRlbnQoaHRtbF81MjI4NjFiMTUzNDM0OGUxODRiYjQwMTU4OTNjNjk2Mik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9lNTJmN2Q1ZjRlMmU0NjE2ODVmNWIwYTA2ODRiY2Q0Yy5iaW5kUG9wdXAocG9wdXBfMTE0NmVjNDdhODIzNGM0OTkyYTM4MWU4NWM5ZjVmOGYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMGI2NmU3OTI5NjU5NGQwM2I5MjU3MWVlMzZkNzk1MjMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny41NTU2LC0xMjIuMjg0MjgxMzA3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMyYzdlZjciLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMmM3ZWY3IiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzU3NzdmMDExOGRlNzQyNDlhOTAwMTQwOGQ1ZDNlYzY0ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzk4NzkwODA4OTU5NTQ4NGVhMjY3ZGI2MTBkYjc3MWJlID0gJCgnPGRpdiBpZD0iaHRtbF85ODc5MDgwODk1OTU0ODRlYTI2N2RiNjEwZGI3NzFiZSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q29sdW1iaWEgQ2l0eSBDbHVzdGVyIDI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzU3NzdmMDExOGRlNzQyNDlhOTAwMTQwOGQ1ZDNlYzY0LnNldENvbnRlbnQoaHRtbF85ODc5MDgwODk1OTU0ODRlYTI2N2RiNjEwZGI3NzFiZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8wYjY2ZTc5Mjk2NTk0ZDAzYjkyNTcxZWUzNmQ3OTUyMy5iaW5kUG9wdXAocG9wdXBfNTc3N2YwMTE4ZGU3NDI0OWE5MDAxNDA4ZDVkM2VjNjQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNWViMGM2NTlkZGE0NGE2NmIzOGM5OGYwNDFhYWQxMzUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny41NDYzLC0xMjIuMzUzMzUxNTA1XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNkNGRkODAiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZDRkZDgwIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzZjZmZhMmVjMjU2ZDRiMmFiMmU0OGY4MDNjZGRiNGFkID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzFhMDVlNmMzODIyZTQ5OGFiNDg5OWM3MDYzMmIxM2JiID0gJCgnPGRpdiBpZD0iaHRtbF8xYTA1ZTZjMzgyMmU0OThhYjQ4OTljNzA2MzJiMTNiYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Uml2ZXJ2aWV3IENsdXN0ZXIgNTwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfNmNmZmEyZWMyNTZkNGIyYWIyZTQ4ZjgwM2NkZGI0YWQuc2V0Q29udGVudChodG1sXzFhMDVlNmMzODIyZTQ5OGFiNDg5OWM3MDYzMmIxM2JiKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzVlYjBjNjU5ZGRhNDRhNjZiMzhjOThmMDQxYWFkMTM1LmJpbmRQb3B1cChwb3B1cF82Y2ZmYTJlYzI1NmQ0YjJhYjJlNDhmODAzY2RkYjRhZCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl82Yzk2NGFhZjVjNTM0NmFhYmIxNGI4ZmUyNDkxNWU3ZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjY0MDcsLTEyMi4zMDM4MTU3MjJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzJjN2VmNyIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMyYzdlZjciLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNDkzZjQ2OTE5Y2VjNDcwZmEzZjYyNmU5NDkzNmM3MzYgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzQ5NjgzMWJiNThmNDRjM2FkY2Y0ZTY5YTRkMzFjZWUgPSAkKCc8ZGl2IGlkPSJodG1sXzc0OTY4MzFiYjU4ZjQ0YzNhZGNmNGU2OWE0ZDMxY2VlIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Nb250bGFrZSBDbHVzdGVyIDI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzQ5M2Y0NjkxOWNlYzQ3MGZhM2Y2MjZlOTQ5MzZjNzM2LnNldENvbnRlbnQoaHRtbF83NDk2ODMxYmI1OGY0NGMzYWRjZjRlNjlhNGQzMWNlZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82Yzk2NGFhZjVjNTM0NmFhYmIxNGI4ZmUyNDkxNWU3ZS5iaW5kUG9wdXAocG9wdXBfNDkzZjQ2OTE5Y2VjNDcwZmEzZjYyNmU5NDkzNmM3MzYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNmY1YWQ5NzEyZWE3NGRiMDlhOTAyMjg0YWNhMDg1ZTUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42ODAyLC0xMjIuMzMzODY5OTU5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjdlNDEiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmY3ZTQxIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2JhNzg1NWM2MWVmZDRjNjI5MGU0ZTViZTUyNDQzYWU3ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2MxODI0Zjg2OTAzMDQ0Y2I5OTg3OWRmMzU1ZDliOGNiID0gJCgnPGRpdiBpZD0iaHRtbF9jMTgyNGY4NjkwMzA0NGNiOTk4NzlkZjM1NWQ5YjhjYiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+R3JlZW4gTGFrZSBDbHVzdGVyIDY8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2JhNzg1NWM2MWVmZDRjNjI5MGU0ZTViZTUyNDQzYWU3LnNldENvbnRlbnQoaHRtbF9jMTgyNGY4NjkwMzA0NGNiOTk4NzlkZjM1NWQ5YjhjYik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl82ZjVhZDk3MTJlYTc0ZGIwOWE5MDIyODRhY2EwODVlNS5iaW5kUG9wdXAocG9wdXBfYmE3ODU1YzYxZWZkNGM2MjkwZTRlNWJlNTI0NDNhZTcpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfN2MzNTZkMDRlYTIyNDg1OTk3MTI1NjdiNzgzNGE5NDMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny43MjY2LC0xMjIuMzAyNTg4NzUxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiM4MGZmYjQiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjODBmZmI0IiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzMyMGI2MjQwZmIyMjRhOWI5MjYwMWExMDUwNDgwMTZjID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzNiOGJjNzMyYzM3NDRjZDhhZDljNDg3MmQ2ZTVlY2Y1ID0gJCgnPGRpdiBpZD0iaHRtbF8zYjhiYzczMmMzNzQ0Y2Q4YWQ5YzQ4NzJkNmU1ZWNmNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+T2x5bXBpYyBIaWxscyBDbHVzdGVyIDQ8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzMyMGI2MjQwZmIyMjRhOWI5MjYwMWExMDUwNDgwMTZjLnNldENvbnRlbnQoaHRtbF8zYjhiYzczMmMzNzQ0Y2Q4YWQ5YzQ4NzJkNmU1ZWNmNSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl83YzM1NmQwNGVhMjI0ODU5OTcxMjU2N2I3ODM0YTk0My5iaW5kUG9wdXAocG9wdXBfMzIwYjYyNDBmYjIyNGE5YjkyNjAxYTEwNTA0ODAxNmMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMzc5ZTA4OTE0OTRlNDgzNzhmMDA5NzZmNjg4YzYzZGMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42NzM1LC0xMjIuMzAwMzg5Mjc5XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMyYzdlZjciLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMmM3ZWY3IiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2M0MGU2ZDBkZWY1ZTRiZDdhZjY1Y2E3NjY1N2E3NzRhID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2VlNzhkYzgxZjhlNDQ3MmU4OWNlNDUyZmI0NWI3NTVhID0gJCgnPGRpdiBpZD0iaHRtbF9lZTc4ZGM4MWY4ZTQ0NzJlODljZTQ1MmZiNDViNzU1YSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+UmF2ZW5uYSBDbHVzdGVyIDI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2M0MGU2ZDBkZWY1ZTRiZDdhZjY1Y2E3NjY1N2E3NzRhLnNldENvbnRlbnQoaHRtbF9lZTc4ZGM4MWY4ZTQ0NzJlODljZTQ1MmZiNDViNzU1YSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8zNzllMDg5MTQ5NGU0ODM3OGYwMDk3NmY2ODhjNjNkYy5iaW5kUG9wdXAocG9wdXBfYzQwZTZkMGRlZjVlNGJkN2FmNjVjYTc2NjU3YTc3NGEpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNGJlYzVjOGRlZmYwNDhlNzhhMTZjNjEyMjUzMThkZmMgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42NTg4LC0xMjIuMjc4MTMxOTMxXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMyYWRkZGQiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMmFkZGRkIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzU5NDRhOTAxNGQxMjQ2MjlhNmY4MzJiMjg1OWVlZjUxID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzJjZjliZjRlMDNiMjQyZTViNjJiYjdjZTExOWNhYjI1ID0gJCgnPGRpdiBpZD0iaHRtbF8yY2Y5YmY0ZTAzYjI0MmU1YjYyYmI3Y2UxMTljYWIyNSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TGF1cmVsaHVyc3QgQ2x1c3RlciAzPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81OTQ0YTkwMTRkMTI0NjI5YTZmODMyYjI4NTllZWY1MS5zZXRDb250ZW50KGh0bWxfMmNmOWJmNGUwM2IyNDJlNWI2MmJiN2NlMTE5Y2FiMjUpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfNGJlYzVjOGRlZmYwNDhlNzhhMTZjNjEyMjUzMThkZmMuYmluZFBvcHVwKHBvcHVwXzU5NDRhOTAxNGQxMjQ2MjlhNmY4MzJiMjg1OWVlZjUxKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzFiODUyMzgzMzZlYTQyZTU4MDI4ZjY5ODdjODY2MTBmID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjk2MSwtMTIyLjM3MTM5OTI2XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMyYWRkZGQiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMmFkZGRkIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2ZiMDY1MDZjNDJmMjQzMWU5YjkxNDIyZmIxNmU2YmEzID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2JkYTNkYzhjZmRiZTQxMzFiODMwZTdlYjYyNThjZTM2ID0gJCgnPGRpdiBpZD0iaHRtbF9iZGEzZGM4Y2ZkYmU0MTMxYjgzMGU3ZWI2MjU4Y2UzNiIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+Q3Jvd24gSGlsbCBDbHVzdGVyIDM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwX2ZiMDY1MDZjNDJmMjQzMWU5YjkxNDIyZmIxNmU2YmEzLnNldENvbnRlbnQoaHRtbF9iZGEzZGM4Y2ZkYmU0MTMxYjgzMGU3ZWI2MjU4Y2UzNik7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8xYjg1MjM4MzM2ZWE0MmU1ODAyOGY2OTg3Yzg2NjEwZi5iaW5kUG9wdXAocG9wdXBfZmIwNjUwNmM0MmYyNDMxZTliOTE0MjJmYjE2ZTZiYTMpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNGZlNzlmYTY2ZTZlNGM5YmFhOWE1MjkyYmEzNzZiNjIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42MTI5LC0xMjIuMjg4NzcyNjNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzJjN2VmNyIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMyYzdlZjciLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMGJjMjZhZjM2NWUwNGY3NmI4YTM2NDJmMmE2NGZmYTEgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNzc0NGQ0Y2Y3NWU4NDRlZGJmZmFkZDA4NTc5M2UxYTMgPSAkKCc8ZGl2IGlkPSJodG1sXzc3NDRkNGNmNzVlODQ0ZWRiZmZhZGQwODU3OTNlMWEzIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5NYWRyb25hIENsdXN0ZXIgMjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfMGJjMjZhZjM2NWUwNGY3NmI4YTM2NDJmMmE2NGZmYTEuc2V0Q29udGVudChodG1sXzc3NDRkNGNmNzVlODQ0ZWRiZmZhZGQwODU3OTNlMWEzKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyXzRmZTc5ZmE2NmU2ZTRjOWJhYTlhNTI5MmJhMzc2YjYyLmJpbmRQb3B1cChwb3B1cF8wYmMyNmFmMzY1ZTA0Zjc2YjhhMzY0MmYyYTY0ZmZhMSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84Mzk2OWEyOTIyYjc0YmJlOTY0NWRmMWIyOGZiZTZmNiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjcxOTcsLTEyMi4zNjY3NDI5MjJdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzgwMDBmZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiM4MDAwZmYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfOTcyMDQ0ODhjODRkNDU1Yzg0MzA4ZTc0NmFjYWJiNTkgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfMmExODg2MTExM2M4NGNmMmExYmE3MDhjOWM5YTgwZjggPSAkKCc8ZGl2IGlkPSJodG1sXzJhMTg4NjExMTNjODRjZjJhMWJhNzA4YzljOWE4MGY4IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Ccm9hZHZpZXcgQ2x1c3RlciAxPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF85NzIwNDQ4OGM4NGQ0NTVjODQzMDhlNzQ2YWNhYmI1OS5zZXRDb250ZW50KGh0bWxfMmExODg2MTExM2M4NGNmMmExYmE3MDhjOWM5YTgwZjgpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfODM5NjlhMjkyMmI3NGJiZTk2NDVkZjFiMjhmYmU2ZjYuYmluZFBvcHVwKHBvcHVwXzk3MjA0NDg4Yzg0ZDQ1NWM4NDMwOGU3NDZhY2FiYjU5KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y3MDk3NDZkNGEwMjQ3YWU5MDRlMjNiNDA1M2I0OTQ2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNzE5NSwtMTIyLjM1MDE2MTcxNl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mZDU0OWFiOWIzOWY0OWNjYjJiMmY1YTE2NjcxODRjMSA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9kNWRjNDZmYTJjOGI0MGNkOGQ1NTcwN2Q2NGE3NGIyOCA9ICQoJzxkaXYgaWQ9Imh0bWxfZDVkYzQ2ZmEyYzhiNDBjZDhkNTU3MDdkNjRhNzRiMjgiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkJpdHRlciBMYWtlIENsdXN0ZXIgMjwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfZmQ1NDlhYjliMzlmNDljY2IyYjJmNWExNjY3MTg0YzEuc2V0Q29udGVudChodG1sX2Q1ZGM0NmZhMmM4YjQwY2Q4ZDU1NzA3ZDY0YTc0YjI4KTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2Y3MDk3NDZkNGEwMjQ3YWU5MDRlMjNiNDA1M2I0OTQ2LmJpbmRQb3B1cChwb3B1cF9mZDU0OWFiOWIzOWY0OWNjYjJiMmY1YTE2NjcxODRjMSk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8yOWJhZDBmYmEzY2I0YWU2YWFkOWE0ZDMwNDkyODMyZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjU1MDYsLTEyMi4yNjE1MjMwMDhdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzgwMDBmZiIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiM4MDAwZmYiLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfNDcwNjA0YWM5YTg5NDg0NWJlOTAwYmJlY2EzYzdlN2MgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfOGRlOTkzNDc1MjA3NDdkZmI4MTFkNjdjZDMxMDQyNDAgPSAkKCc8ZGl2IGlkPSJodG1sXzhkZTk5MzQ3NTIwNzQ3ZGZiODExZDY3Y2QzMTA0MjQwIiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5TZXdhcmQgUGFyayBDbHVzdGVyIDE8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzQ3MDYwNGFjOWE4OTQ4NDViZTkwMGJiZWNhM2M3ZTdjLnNldENvbnRlbnQoaHRtbF84ZGU5OTM0NzUyMDc0N2RmYjgxMWQ2N2NkMzEwNDI0MCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl8yOWJhZDBmYmEzY2I0YWU2YWFkOWE0ZDMwNDkyODMyZC5iaW5kUG9wdXAocG9wdXBfNDcwNjA0YWM5YTg5NDg0NWJlOTAwYmJlY2EzYzdlN2MpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYmNlNTQ2YjQzYzYyNDEzYTgyYjRlODc2ZTdhYzYwNmUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42OTYxLC0xMjIuMzgyMTgxODcyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiNmZjdlNDEiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjZmY3ZTQxIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzE1N2ViZDdkY2IwMjRjNmQ4YTE3YjVkZTg0NDViNjc2ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2VjYzVmOWQ3Y2NlNDQwZWRhNzRiYjhiNjdiNTA5NWY0ID0gJCgnPGRpdiBpZD0iaHRtbF9lY2M1ZjlkN2NjZTQ0MGVkYTc0YmI4YjY3YjUwOTVmNCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+T2x5bXBpYyBNYW5vciBDbHVzdGVyIDY8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzE1N2ViZDdkY2IwMjRjNmQ4YTE3YjVkZTg0NDViNjc2LnNldENvbnRlbnQoaHRtbF9lY2M1ZjlkN2NjZTQ0MGVkYTc0YmI4YjY3YjUwOTVmNCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl9iY2U1NDZiNDNjNjI0MTNhODJiNGU4NzZlN2FjNjA2ZS5iaW5kUG9wdXAocG9wdXBfMTU3ZWJkN2RjYjAyNGM2ZDhhMTdiNWRlODQ0NWI2NzYpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZTIyY2Y2NDU4NmIwNDgyYzliNWRiMjBlYjU5NzUzMDAgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42NzE4LC0xMjIuMjg2MDY5MTk3XSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMyYWRkZGQiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMmFkZGRkIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwX2NmZGE5OTQ2YjJlMjQ5NDNhYThkZTFkYzNmYWZmMDY4ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2EwMDA0ODlmMWQ3ZDQyN2Q5OTBiNjQwZGRhN2JkOTMxID0gJCgnPGRpdiBpZD0iaHRtbF9hMDAwNDg5ZjFkN2Q0MjdkOTkwYjY0MGRkYTdiZDkzMSIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QnJ5YW50IENsdXN0ZXIgMzwvZGl2PicpWzBdOwogICAgICAgICAgICAgICAgcG9wdXBfY2ZkYTk5NDZiMmUyNDk0M2FhOGRlMWRjM2ZhZmYwNjguc2V0Q29udGVudChodG1sX2EwMDA0ODlmMWQ3ZDQyN2Q5OTBiNjQwZGRhN2JkOTMxKTsKICAgICAgICAgICAgCgogICAgICAgICAgICBjaXJjbGVfbWFya2VyX2UyMmNmNjQ1ODZiMDQ4MmM5YjVkYjIwZWI1OTc1MzAwLmJpbmRQb3B1cChwb3B1cF9jZmRhOTk0NmIyZTI0OTQzYWE4ZGUxZGMzZmFmZjA2OCk7CgogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84MDU2NzljYjQzZWY0ZmM0OTQ3MzYxODYyMjQ3MGMzZCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ3LjUyNjUsLTEyMi4zNjA4MDM1MDNdLAogICAgICAgICAgICAgICAgewogICJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwKICAiY29sb3IiOiAiIzJjN2VmNyIsCiAgImRhc2hBcnJheSI6IG51bGwsCiAgImRhc2hPZmZzZXQiOiBudWxsLAogICJmaWxsIjogdHJ1ZSwKICAiZmlsbENvbG9yIjogIiMyYzdlZjciLAogICJmaWxsT3BhY2l0eSI6IDAuNywKICAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsCiAgImxpbmVDYXAiOiAicm91bmQiLAogICJsaW5lSm9pbiI6ICJyb3VuZCIsCiAgIm9wYWNpdHkiOiAxLjAsCiAgInJhZGl1cyI6IDUsCiAgInN0cm9rZSI6IHRydWUsCiAgIndlaWdodCI6IDMKfQogICAgICAgICAgICAgICAgKS5hZGRUbyhtYXBfYWMxMmI1MjNmODM1NDU3YTk4M2QwMzFjMjQ1YzUxN2UpOwogICAgICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9wdXBfMTViMjlkN2RmOGY2NDVhMDhhODY4Y2ZmYjc5ZmMzZTIgPSBMLnBvcHVwKHttYXhXaWR0aDogJzMwMCd9KTsKCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgdmFyIGh0bWxfNjQyYmZkMDkxMTE2NDhmZWE4MDZjNmYzNjlkZjk2MjQgPSAkKCc8ZGl2IGlkPSJodG1sXzY0MmJmZDA5MTExNjQ4ZmVhODA2YzZmMzY5ZGY5NjI0IiBzdHlsZT0id2lkdGg6IDEwMC4wJTsgaGVpZ2h0OiAxMDAuMCU7Ij5Tb3V0aCBEZWxyaWRnZSBDbHVzdGVyIDI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzE1YjI5ZDdkZjhmNjQ1YTA4YTg2OGNmZmI3OWZjM2UyLnNldENvbnRlbnQoaHRtbF82NDJiZmQwOTExMTY0OGZlYTgwNmM2ZjM2OWRmOTYyNCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84MDU2NzljYjQzZWY0ZmM0OTQ3MzYxODYyMjQ3MGMzZC5iaW5kUG9wdXAocG9wdXBfMTViMjlkN2RmOGY2NDVhMDhhODY4Y2ZmYjc5ZmMzZTIpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfOGNhZjU1MWQ4ZjEwNDJiNDllOTQ4ZmY2NTc0ZDZkY2QgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny43MjQyLC0xMjIuMjg3MjkyOF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jNWY5NTlkNWJhZTE0ZWQwYTAwYWMzMzkzNTQyZDAxZiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8wYThmZTIwYmViYjc0NzRmODI1YTIwNjg4ODBiODY2YiA9ICQoJzxkaXYgaWQ9Imh0bWxfMGE4ZmUyMGJlYmI3NDc0ZjgyNWEyMDY4ODgwYjg2NmIiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkNlZGFyIFBhcmsgQ2x1c3RlciAyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jNWY5NTlkNWJhZTE0ZWQwYTAwYWMzMzkzNTQyZDAxZi5zZXRDb250ZW50KGh0bWxfMGE4ZmUyMGJlYmI3NDc0ZjgyNWEyMDY4ODgwYjg2NmIpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfOGNhZjU1MWQ4ZjEwNDJiNDllOTQ4ZmY2NTc0ZDZkY2QuYmluZFBvcHVwKHBvcHVwX2M1Zjk1OWQ1YmFlMTRlZDBhMDBhYzMzOTM1NDJkMDFmKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzk1MzU1N2ZkODRmNzQzZmY5ODJmNDQ4MDIxYzhkMjYzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNzEwMywtMTIyLjMwNDkzNjUwNl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmFkZGRkIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJhZGRkZCIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8yYTE2NmU1NzkzYzg0ODJhYmFlNTNjZmMzYzdlMWE2NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85YTFjZjc4NGRjZDU0MThiODdlNGE5NzA1MjcxMGQxZSA9ICQoJzxkaXYgaWQ9Imh0bWxfOWExY2Y3ODRkY2Q1NDE4Yjg3ZTRhOTcwNTI3MTBkMWUiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlZpY3RvcnkgSGVpZ2h0cyBDbHVzdGVyIDM8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzJhMTY2ZTU3OTNjODQ4MmFiYWU1M2NmYzNjN2UxYTY0LnNldENvbnRlbnQoaHRtbF85YTFjZjc4NGRjZDU0MThiODdlNGE5NzA1MjcxMGQxZSk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl85NTM1NTdmZDg0Zjc0M2ZmOTgyZjQ0ODAyMWM4ZDI2My5iaW5kUG9wdXAocG9wdXBfMmExNjZlNTc5M2M4NDgyYWJhZTUzY2ZjM2M3ZTFhNjQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfM2Q1NWEzZDU4M2M3NDVmMmEzYzNiYzU4MWNlYTM1ZjUgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42NTEzLC0xMjIuNDA2OTQ0MDkyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiM4MDAwZmYiLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjODAwMGZmIiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzMwZTM5NTI3NDQwODQ5MmM5YjY0MTcxNzQyMGE5MDY1ID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sX2QxZjJjN2E5MjAyYTRmNzVhNzQ5ZjA1Njg4NzM5YzU3ID0gJCgnPGRpdiBpZD0iaHRtbF9kMWYyYzdhOTIwMmE0Zjc1YTc0OWYwNTY4ODczOWM1NyIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+TWFnbm9saWEgQ2x1c3RlciAxPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF8zMGUzOTUyNzQ0MDg0OTJjOWI2NDE3MTc0MjBhOTA2NS5zZXRDb250ZW50KGh0bWxfZDFmMmM3YTkyMDJhNGY3NWE3NDlmMDU2ODg3MzljNTcpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfM2Q1NWEzZDU4M2M3NDVmMmEzYzNiYzU4MWNlYTM1ZjUuYmluZFBvcHVwKHBvcHVwXzMwZTM5NTI3NDQwODQ5MmM5YjY0MTcxNzQyMGE5MDY1KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzBhOTI2Y2EzMDY3NTQ4ODM5NTI5NDY1YmEwY2Y3M2I1ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNjczMywtMTIyLjM1MzE4NzU1OF0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9hNWRiNDEwY2I3Zjg0ZWY3YTlhMmFmYWM4Y2ZkZWQ1NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF85ZGY1MDg1MjRhNDQ0NWMwODcwYjVjMjUxZjIxZGY1YyA9ICQoJzxkaXYgaWQ9Imh0bWxfOWRmNTA4NTI0YTQ0NDVjMDg3MGI1YzI1MWYyMWRmNWMiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPlBoaW5uZXkgUmlkZ2UgQ2x1c3RlciAyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9hNWRiNDEwY2I3Zjg0ZWY3YTlhMmFmYWM4Y2ZkZWQ1NC5zZXRDb250ZW50KGh0bWxfOWRmNTA4NTI0YTQ0NDVjMDg3MGI1YzI1MWYyMWRmNWMpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMGE5MjZjYTMwNjc1NDg4Mzk1Mjk0NjViYTBjZjczYjUuYmluZFBvcHVwKHBvcHVwX2E1ZGI0MTBjYjdmODRlZjdhOWEyYWZhYzhjZmRlZDU0KTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzhkMzcyNjVmMWY5ODRkMjJiOGMwYjMwOTFjOGYwMmUzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTUzNiwtMTIyLjM5MTg5MDcwNl0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF8wYWFiZTVhZWVhY2Y0ZmUwYjBjMDA0NjE4YmU2YjA1NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9kNmY2NDhiOTNhNzQ0ODM0OGQ0YmExMWE1YjRmMzk0ZCA9ICQoJzxkaXYgaWQ9Imh0bWxfZDZmNjQ4YjkzYTc0NDgzNDhkNGJhMTFhNWI0ZjM5NGQiIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPldlc3QgU2VhdHRsZSBDbHVzdGVyIDI8L2Rpdj4nKVswXTsKICAgICAgICAgICAgICAgIHBvcHVwXzBhYWJlNWFlZWFjZjRmZTBiMGMwMDQ2MThiZTZiMDU0LnNldENvbnRlbnQoaHRtbF9kNmY2NDhiOTNhNzQ0ODM0OGQ0YmExMWE1YjRmMzk0ZCk7CiAgICAgICAgICAgIAoKICAgICAgICAgICAgY2lyY2xlX21hcmtlcl84ZDM3MjY1ZjFmOTg0ZDIyYjhjMGIzMDkxYzhmMDJlMy5iaW5kUG9wdXAocG9wdXBfMGFhYmU1YWVlYWNmNGZlMGIwYzAwNDYxOGJlNmIwNTQpOwoKICAgICAgICAgICAgCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMzViZDNiNjAxZjZlNGYzOGFkODdhOWJkOTEzZWU0YTYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0Ny42MTQ4LC0xMjIuMzQ4MzAzMDEyXSwKICAgICAgICAgICAgICAgIHsKICAiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsCiAgImNvbG9yIjogIiMyYzdlZjciLAogICJkYXNoQXJyYXkiOiBudWxsLAogICJkYXNoT2Zmc2V0IjogbnVsbCwKICAiZmlsbCI6IHRydWUsCiAgImZpbGxDb2xvciI6ICIjMmM3ZWY3IiwKICAiZmlsbE9wYWNpdHkiOiAwLjcsCiAgImZpbGxSdWxlIjogImV2ZW5vZGQiLAogICJsaW5lQ2FwIjogInJvdW5kIiwKICAibGluZUpvaW4iOiAicm91bmQiLAogICJvcGFjaXR5IjogMS4wLAogICJyYWRpdXMiOiA1LAogICJzdHJva2UiOiB0cnVlLAogICJ3ZWlnaHQiOiAzCn0KICAgICAgICAgICAgICAgICkuYWRkVG8obWFwX2FjMTJiNTIzZjgzNTQ1N2E5ODNkMDMxYzI0NWM1MTdlKTsKICAgICAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvcHVwXzVkZDYzY2JmZjYzYTQ1OTBhNGNkYzIzNGM2OWFkMzkyID0gTC5wb3B1cCh7bWF4V2lkdGg6ICczMDAnfSk7CgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBodG1sXzk0YjVkODgxOWRlNjQzMzU4NTgzMjVjYjVlZTc4ZmFkID0gJCgnPGRpdiBpZD0iaHRtbF85NGI1ZDg4MTlkZTY0MzM1ODU4MzI1Y2I1ZWU3OGZhZCIgc3R5bGU9IndpZHRoOiAxMDAuMCU7IGhlaWdodDogMTAwLjAlOyI+QmVsbHRvd24gQ2x1c3RlciAyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF81ZGQ2M2NiZmY2M2E0NTkwYTRjZGMyMzRjNjlhZDM5Mi5zZXRDb250ZW50KGh0bWxfOTRiNWQ4ODE5ZGU2NDMzNTg1ODMyNWNiNWVlNzhmYWQpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMzViZDNiNjAxZjZlNGYzOGFkODdhOWJkOTEzZWU0YTYuYmluZFBvcHVwKHBvcHVwXzVkZDYzY2JmZjYzYTQ1OTBhNGNkYzIzNGM2OWFkMzkyKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzBmNzJhOGJhNDAwYjQ0NTc5YWZhMTI5NWVmZWVlMjMzID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTgzOCwtMTIyLjQwMjAzNTM3N10sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjODAwMGZmIiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzgwMDBmZiIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9mOTFlZWNhYzIxZGQ0ZjgwODUyODE2ODFmMDA4M2I0YiA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF9iNTlhODk0MDg1NDQ0M2I1YWYyM2YzMThjMmQwMjhmNyA9ICQoJzxkaXYgaWQ9Imh0bWxfYjU5YTg5NDA4NTQ0NDNiNWFmMjNmMzE4YzJkMDI4ZjciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkFsa2kgQ2x1c3RlciAxPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9mOTFlZWNhYzIxZGQ0ZjgwODUyODE2ODFmMDA4M2I0Yi5zZXRDb250ZW50KGh0bWxfYjU5YTg5NDA4NTQ0NDNiNWFmMjNmMzE4YzJkMDI4ZjcpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfMGY3MmE4YmE0MDBiNDQ1NzlhZmExMjk1ZWZlZWUyMzMuYmluZFBvcHVwKHBvcHVwX2Y5MWVlY2FjMjFkZDRmODA4NTI4MTY4MWYwMDgzYjRiKTsKCiAgICAgICAgICAgIAogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2IwODI0OTY4YjczMDRiZTNhOWQ1NGVhYTlkYzIyYmVjID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDcuNTQwMywtMTIyLjMxNjM3MDg1NV0sCiAgICAgICAgICAgICAgICB7CiAgImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLAogICJjb2xvciI6ICIjMmM3ZWY3IiwKICAiZGFzaEFycmF5IjogbnVsbCwKICAiZGFzaE9mZnNldCI6IG51bGwsCiAgImZpbGwiOiB0cnVlLAogICJmaWxsQ29sb3IiOiAiIzJjN2VmNyIsCiAgImZpbGxPcGFjaXR5IjogMC43LAogICJmaWxsUnVsZSI6ICJldmVub2RkIiwKICAibGluZUNhcCI6ICJyb3VuZCIsCiAgImxpbmVKb2luIjogInJvdW5kIiwKICAib3BhY2l0eSI6IDEuMCwKICAicmFkaXVzIjogNSwKICAic3Ryb2tlIjogdHJ1ZSwKICAid2VpZ2h0IjogMwp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF9hYzEyYjUyM2Y4MzU0NTdhOTgzZDAzMWMyNDVjNTE3ZSk7CiAgICAgICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb3B1cF9jYzdlYTVkZWE0ZmY0ZDg1YjRiNzI4MjQ4NmJjNTE2NCA9IEwucG9wdXAoe21heFdpZHRoOiAnMzAwJ30pOwoKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB2YXIgaHRtbF8xYzE4NzZmYWEyNzE0YzUzODM5M2YwODAzZDUzN2UzNyA9ICQoJzxkaXYgaWQ9Imh0bWxfMWMxODc2ZmFhMjcxNGM1MzgzOTNmMDgwM2Q1MzdlMzciIHN0eWxlPSJ3aWR0aDogMTAwLjAlOyBoZWlnaHQ6IDEwMC4wJTsiPkdlb3JnZXRvd24gQ2x1c3RlciAyPC9kaXY+JylbMF07CiAgICAgICAgICAgICAgICBwb3B1cF9jYzdlYTVkZWE0ZmY0ZDg1YjRiNzI4MjQ4NmJjNTE2NC5zZXRDb250ZW50KGh0bWxfMWMxODc2ZmFhMjcxNGM1MzgzOTNmMDgwM2Q1MzdlMzcpOwogICAgICAgICAgICAKCiAgICAgICAgICAgIGNpcmNsZV9tYXJrZXJfYjA4MjQ5NjhiNzMwNGJlM2E5ZDU0ZWFhOWRjMjJiZWMuYmluZFBvcHVwKHBvcHVwX2NjN2VhNWRlYTRmZjRkODViNGI3MjgyNDg2YmM1MTY0KTsKCiAgICAgICAgICAgIAogICAgICAgIAo8L3NjcmlwdD4=\" 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 0x7ff57762a668>"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# create map\n",
"map_clusters = folium.Map(location=[latitude, longitude], zoom_start=11)\n",
"\n",
"# set color scheme for the clusters\n",
"x = np.arange(k)\n",
"ys = [i + x + (i*x)**2 for i in range(k)]\n",
"colors_array = cm.rainbow(np.linspace(0, 1, len(ys)))\n",
"rainbow = [colors.rgb2hex(i) for i in colors_array]\n",
"\n",
"# add markers to the map\n",
"markers_colors = []\n",
"for lat, lon, poi, cluster in zip(seattle_merged['latitude'], seattle_merged['longitude'], seattle_merged['name'], seattle_merged['Cluster Labels']):\n",
" label = folium.Popup(str(poi) + ' Cluster ' + str(cluster), parse_html=True)\n",
" folium.CircleMarker(\n",
" [lat, lon],\n",
" radius=5,\n",
" popup=label,\n",
" color=rainbow[cluster-1],\n",
" fill=True,\n",
" fill_color=rainbow[cluster-1],\n",
" fill_opacity=0.7).add_to(map_clusters)\n",
" \n",
"map_clusters"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Results"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"After mapping the data we can begin to examine the results of the analysis, and the finer details of the clusters. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Cluster 1"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>name</th>\n",
" <th>pc_income</th>\n",
" <th>median age_census</th>\n",
" <th>latitude</th>\n",
" <th>longitude</th>\n",
" <th>popdensity</th>\n",
" <th>Cluster Labels</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>32</th>\n",
" <td>Meadowbrook</td>\n",
" <td>36252</td>\n",
" <td>39.441667</td>\n",
" <td>47.706</td>\n",
" <td>-122.297129</td>\n",
" <td>8600.141667</td>\n",
" <td>0</td>\n",
" <td>Marijuana Dispensary</td>\n",
" <td>Furniture / Home Store</td>\n",
" <td>Tennis Court</td>\n",
" <td>Pet Store</td>\n",
" <td>Soccer Field</td>\n",
" <td>Pool</td>\n",
" <td>Park</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Eye Doctor</td>\n",
" <td>Farm</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" name pc_income median age_census latitude longitude \\\n",
"32 Meadowbrook 36252 39.441667 47.706 -122.297129 \n",
"\n",
" popdensity Cluster Labels 1st Most Common Venue 2nd Most Common Venue \\\n",
"32 8600.141667 0 Marijuana Dispensary Furniture / Home Store \n",
"\n",
" 3rd Most Common Venue 4th Most Common Venue 5th Most Common Venue \\\n",
"32 Tennis Court Pet Store Soccer Field \n",
"\n",
" 6th Most Common Venue 7th Most Common Venue 8th Most Common Venue \\\n",
"32 Pool Park Zoo Exhibit \n",
"\n",
" 9th Most Common Venue 10th Most Common Venue \n",
"32 Eye Doctor Farm "
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"seattle_merged.loc[seattle_merged['Cluster Labels'] == 0, seattle_merged.columns[[1] + list(range(2, seattle_merged.shape[1]))]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Cluster 2"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>name</th>\n",
" <th>pc_income</th>\n",
" <th>median age_census</th>\n",
" <th>latitude</th>\n",
" <th>longitude</th>\n",
" <th>popdensity</th>\n",
" <th>Cluster Labels</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>North Beach</td>\n",
" <td>51777</td>\n",
" <td>47.080000</td>\n",
" <td>47.6961</td>\n",
" <td>-122.396154</td>\n",
" <td>5890.960000</td>\n",
" <td>1</td>\n",
" <td>Beach</td>\n",
" <td>Trail</td>\n",
" <td>Scenic Lookout</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Event Space</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" </tr>\n",
" <tr>\n",
" <th>15</th>\n",
" <td>Broadmoor</td>\n",
" <td>72144</td>\n",
" <td>43.675000</td>\n",
" <td>47.6351</td>\n",
" <td>-122.291501</td>\n",
" <td>5517.750000</td>\n",
" <td>1</td>\n",
" <td>Park</td>\n",
" <td>Trail</td>\n",
" <td>Golf Course</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Electronics Store</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" <td>Field</td>\n",
" </tr>\n",
" <tr>\n",
" <th>20</th>\n",
" <td>Matthews Beach</td>\n",
" <td>43419</td>\n",
" <td>42.573333</td>\n",
" <td>47.7043</td>\n",
" <td>-122.280365</td>\n",
" <td>7068.626667</td>\n",
" <td>1</td>\n",
" <td>Construction &amp; Landscaping</td>\n",
" <td>Trail</td>\n",
" <td>Gym</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Ethiopian Restaurant</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" </tr>\n",
" <tr>\n",
" <th>64</th>\n",
" <td>Broadview</td>\n",
" <td>39048</td>\n",
" <td>47.542857</td>\n",
" <td>47.7197</td>\n",
" <td>-122.366743</td>\n",
" <td>7622.800000</td>\n",
" <td>1</td>\n",
" <td>Concert Hall</td>\n",
" <td>Art Gallery</td>\n",
" <td>Trail</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Event Space</td>\n",
" <td>Food Truck</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>66</th>\n",
" <td>Seward Park</td>\n",
" <td>35407</td>\n",
" <td>42.800000</td>\n",
" <td>47.5506</td>\n",
" <td>-122.261523</td>\n",
" <td>7176.923077</td>\n",
" <td>1</td>\n",
" <td>Trail</td>\n",
" <td>Nature Preserve</td>\n",
" <td>Playground</td>\n",
" <td>Beach</td>\n",
" <td>Park</td>\n",
" <td>Arts &amp; Crafts Store</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Fast Food Restaurant</td>\n",
" <td>Farm</td>\n",
" <td>Farmers Market</td>\n",
" </tr>\n",
" <tr>\n",
" <th>72</th>\n",
" <td>Magnolia</td>\n",
" <td>49171</td>\n",
" <td>43.295652</td>\n",
" <td>47.6513</td>\n",
" <td>-122.406944</td>\n",
" <td>6871.173913</td>\n",
" <td>1</td>\n",
" <td>Trail</td>\n",
" <td>Park</td>\n",
" <td>Bus Stop</td>\n",
" <td>Athletics &amp; Sports</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Event Space</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>76</th>\n",
" <td>Alki</td>\n",
" <td>56337</td>\n",
" <td>45.528571</td>\n",
" <td>47.5838</td>\n",
" <td>-122.402035</td>\n",
" <td>7179.071429</td>\n",
" <td>1</td>\n",
" <td>Food Truck</td>\n",
" <td>Trail</td>\n",
" <td>Beach</td>\n",
" <td>Seafood Restaurant</td>\n",
" <td>Cosmetics Shop</td>\n",
" <td>Greek Restaurant</td>\n",
" <td>Burger Joint</td>\n",
" <td>Field</td>\n",
" <td>Farmers Market</td>\n",
" <td>Fast Food Restaurant</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" name pc_income median age_census latitude longitude \\\n",
"5 North Beach 51777 47.080000 47.6961 -122.396154 \n",
"15 Broadmoor 72144 43.675000 47.6351 -122.291501 \n",
"20 Matthews Beach 43419 42.573333 47.7043 -122.280365 \n",
"64 Broadview 39048 47.542857 47.7197 -122.366743 \n",
"66 Seward Park 35407 42.800000 47.5506 -122.261523 \n",
"72 Magnolia 49171 43.295652 47.6513 -122.406944 \n",
"76 Alki 56337 45.528571 47.5838 -122.402035 \n",
"\n",
" popdensity Cluster Labels 1st Most Common Venue \\\n",
"5 5890.960000 1 Beach \n",
"15 5517.750000 1 Park \n",
"20 7068.626667 1 Construction & Landscaping \n",
"64 7622.800000 1 Concert Hall \n",
"66 7176.923077 1 Trail \n",
"72 6871.173913 1 Trail \n",
"76 7179.071429 1 Food Truck \n",
"\n",
" 2nd Most Common Venue 3rd Most Common Venue 4th Most Common Venue \\\n",
"5 Trail Scenic Lookout Zoo Exhibit \n",
"15 Trail Golf Course Zoo Exhibit \n",
"20 Trail Gym Zoo Exhibit \n",
"64 Art Gallery Trail Zoo Exhibit \n",
"66 Nature Preserve Playground Beach \n",
"72 Park Bus Stop Athletics & Sports \n",
"76 Trail Beach Seafood Restaurant \n",
"\n",
" 5th Most Common Venue 6th Most Common Venue 7th Most Common Venue \\\n",
"5 Event Space Food Court Food & Drink Shop \n",
"15 Electronics Store Food & Drink Shop Food \n",
"20 Ethiopian Restaurant Food Court Food & Drink Shop \n",
"64 Event Space Food Truck Food Court \n",
"66 Park Arts & Crafts Store Zoo Exhibit \n",
"72 Zoo Exhibit Event Space Food Court \n",
"76 Cosmetics Shop Greek Restaurant Burger Joint \n",
"\n",
" 8th Most Common Venue 9th Most Common Venue 10th Most Common Venue \n",
"5 Food Fondue Restaurant Fish Market \n",
"15 Fondue Restaurant Fish Market Field \n",
"20 Food Fondue Restaurant Fish Market \n",
"64 Food & Drink Shop Food Fondue Restaurant \n",
"66 Fast Food Restaurant Farm Farmers Market \n",
"72 Food & Drink Shop Food Fondue Restaurant \n",
"76 Field Farmers Market Fast Food Restaurant "
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"seattle_merged.loc[seattle_merged['Cluster Labels'] == 1, seattle_merged.columns[[1] + list(range(2, seattle_merged.shape[1]))]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Cluster 3"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>name</th>\n",
" <th>pc_income</th>\n",
" <th>median age_census</th>\n",
" <th>latitude</th>\n",
" <th>longitude</th>\n",
" <th>popdensity</th>\n",
" <th>Cluster Labels</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Brighton</td>\n",
" <td>23520</td>\n",
" <td>35.843750</td>\n",
" <td>47.5388</td>\n",
" <td>-122.275673</td>\n",
" <td>11462.300000</td>\n",
" <td>2</td>\n",
" <td>Mexican Restaurant</td>\n",
" <td>Vietnamese Restaurant</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Breakfast Spot</td>\n",
" <td>Seafood Restaurant</td>\n",
" <td>Café</td>\n",
" <td>Fast Food Restaurant</td>\n",
" <td>Gas Station</td>\n",
" <td>Bank</td>\n",
" <td>Mobile Phone Shop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Whittier Heights</td>\n",
" <td>41725</td>\n",
" <td>39.457143</td>\n",
" <td>47.6833</td>\n",
" <td>-122.371407</td>\n",
" <td>10478.685714</td>\n",
" <td>2</td>\n",
" <td>Bar</td>\n",
" <td>Dance Studio</td>\n",
" <td>Trail</td>\n",
" <td>Caribbean Restaurant</td>\n",
" <td>Rental Car Location</td>\n",
" <td>Bakery</td>\n",
" <td>Karaoke Bar</td>\n",
" <td>Theme Park Ride / Attraction</td>\n",
" <td>Cocktail Bar</td>\n",
" <td>Breakfast Spot</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>Roosevelt</td>\n",
" <td>40906</td>\n",
" <td>34.614286</td>\n",
" <td>47.6772</td>\n",
" <td>-122.316196</td>\n",
" <td>10132.100000</td>\n",
" <td>2</td>\n",
" <td>Vegetarian / Vegan Restaurant</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Spa</td>\n",
" <td>Gym / Fitness Center</td>\n",
" <td>Burger Joint</td>\n",
" <td>Salon / Barbershop</td>\n",
" <td>Indian Restaurant</td>\n",
" <td>Breakfast Spot</td>\n",
" <td>Bookstore</td>\n",
" <td>Mexican Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>Westlake</td>\n",
" <td>54865</td>\n",
" <td>39.500000</td>\n",
" <td>47.6349</td>\n",
" <td>-122.341812</td>\n",
" <td>9201.244444</td>\n",
" <td>2</td>\n",
" <td>Harbor / Marina</td>\n",
" <td>Bus Stop</td>\n",
" <td>Deli / Bodega</td>\n",
" <td>Boat or Ferry</td>\n",
" <td>Pool</td>\n",
" <td>Track</td>\n",
" <td>Chinese Restaurant</td>\n",
" <td>Café</td>\n",
" <td>Cocktail Bar</td>\n",
" <td>Sandwich Place</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>Sand Point</td>\n",
" <td>55299</td>\n",
" <td>43.500000</td>\n",
" <td>47.6817</td>\n",
" <td>-122.255718</td>\n",
" <td>5598.020000</td>\n",
" <td>2</td>\n",
" <td>Dog Run</td>\n",
" <td>Tennis Court</td>\n",
" <td>Theater</td>\n",
" <td>Food Truck</td>\n",
" <td>Snack Place</td>\n",
" <td>Playground</td>\n",
" <td>Night Market</td>\n",
" <td>Garden</td>\n",
" <td>Indie Movie Theater</td>\n",
" <td>Sculpture Garden</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13</th>\n",
" <td>Beacon Hill</td>\n",
" <td>25174</td>\n",
" <td>37.592308</td>\n",
" <td>47.5541</td>\n",
" <td>-122.300861</td>\n",
" <td>8630.397436</td>\n",
" <td>2</td>\n",
" <td>Bus Station</td>\n",
" <td>Light Rail Station</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Eye Doctor</td>\n",
" <td>Food Truck</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14</th>\n",
" <td>Rainier Beach</td>\n",
" <td>26397</td>\n",
" <td>39.600000</td>\n",
" <td>47.5135</td>\n",
" <td>-122.261648</td>\n",
" <td>7352.230435</td>\n",
" <td>2</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Garden</td>\n",
" <td>Baseball Field</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Eye Doctor</td>\n",
" <td>Food Truck</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>16</th>\n",
" <td>Madison Park</td>\n",
" <td>76309</td>\n",
" <td>46.900000</td>\n",
" <td>47.6333</td>\n",
" <td>-122.283182</td>\n",
" <td>6296.500000</td>\n",
" <td>2</td>\n",
" <td>Bank</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Playground</td>\n",
" <td>Soccer Field</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Café</td>\n",
" <td>Bar</td>\n",
" <td>Bakery</td>\n",
" <td>Dry Cleaner</td>\n",
" <td>Coffee Shop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>17</th>\n",
" <td>High Point</td>\n",
" <td>29334</td>\n",
" <td>34.233333</td>\n",
" <td>47.5441</td>\n",
" <td>-122.368633</td>\n",
" <td>8380.480000</td>\n",
" <td>2</td>\n",
" <td>Playground</td>\n",
" <td>Vietnamese Restaurant</td>\n",
" <td>Garden</td>\n",
" <td>Electronics Store</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" <td>Field</td>\n",
" <td>Fast Food Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>18</th>\n",
" <td>Interbay</td>\n",
" <td>48811</td>\n",
" <td>40.200000</td>\n",
" <td>47.6420</td>\n",
" <td>-122.380360</td>\n",
" <td>7233.818750</td>\n",
" <td>2</td>\n",
" <td>Bus Stop</td>\n",
" <td>Golf Course</td>\n",
" <td>Bike Shop</td>\n",
" <td>Garden</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Electronics Store</td>\n",
" <td>Grocery Store</td>\n",
" <td>Gym</td>\n",
" <td>Asian Restaurant</td>\n",
" <td>Basketball Court</td>\n",
" </tr>\n",
" <tr>\n",
" <th>25</th>\n",
" <td>First Hill</td>\n",
" <td>32941</td>\n",
" <td>36.257143</td>\n",
" <td>47.6085</td>\n",
" <td>-122.323689</td>\n",
" <td>28164.214286</td>\n",
" <td>2</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Bakery</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Hotel</td>\n",
" <td>Restaurant</td>\n",
" <td>Sushi Restaurant</td>\n",
" <td>Supplement Shop</td>\n",
" <td>Speakeasy</td>\n",
" <td>Snack Place</td>\n",
" <td>Café</td>\n",
" </tr>\n",
" <tr>\n",
" <th>27</th>\n",
" <td>Northgate</td>\n",
" <td>35382</td>\n",
" <td>40.772727</td>\n",
" <td>47.7081</td>\n",
" <td>-122.321857</td>\n",
" <td>9248.927273</td>\n",
" <td>2</td>\n",
" <td>Mexican Restaurant</td>\n",
" <td>Arts &amp; Crafts Store</td>\n",
" <td>Dance Studio</td>\n",
" <td>Department Store</td>\n",
" <td>Big Box Store</td>\n",
" <td>Sporting Goods Shop</td>\n",
" <td>Library</td>\n",
" <td>Spa</td>\n",
" <td>Lingerie Store</td>\n",
" <td>Snack Place</td>\n",
" </tr>\n",
" <tr>\n",
" <th>28</th>\n",
" <td>Lower Queen Anne</td>\n",
" <td>59411</td>\n",
" <td>37.250000</td>\n",
" <td>47.6251</td>\n",
" <td>-122.355650</td>\n",
" <td>18774.038889</td>\n",
" <td>2</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Performing Arts Venue</td>\n",
" <td>Theater</td>\n",
" <td>Indie Movie Theater</td>\n",
" <td>Seafood Restaurant</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Lounge</td>\n",
" <td>Cajun / Creole Restaurant</td>\n",
" <td>Music Venue</td>\n",
" <td>Radio Station</td>\n",
" </tr>\n",
" <tr>\n",
" <th>29</th>\n",
" <td>Eastlake</td>\n",
" <td>59684</td>\n",
" <td>36.877778</td>\n",
" <td>47.6379</td>\n",
" <td>-122.328229</td>\n",
" <td>9791.577778</td>\n",
" <td>2</td>\n",
" <td>Mexican Restaurant</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Bus Stop</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Italian Restaurant</td>\n",
" <td>Burger Joint</td>\n",
" <td>Boat or Ferry</td>\n",
" <td>Park</td>\n",
" <td>Sporting Goods Shop</td>\n",
" <td>Furniture / Home Store</td>\n",
" </tr>\n",
" <tr>\n",
" <th>33</th>\n",
" <td>Downtown</td>\n",
" <td>38300</td>\n",
" <td>41.160000</td>\n",
" <td>47.6068</td>\n",
" <td>-122.339989</td>\n",
" <td>23976.375000</td>\n",
" <td>2</td>\n",
" <td>Seafood Restaurant</td>\n",
" <td>Cocktail Bar</td>\n",
" <td>Coffee Shop</td>\n",
" <td>New American Restaurant</td>\n",
" <td>Theme Park Ride / Attraction</td>\n",
" <td>Other Nightlife</td>\n",
" <td>Ice Cream Shop</td>\n",
" <td>Rock Club</td>\n",
" <td>Lounge</td>\n",
" <td>Spa</td>\n",
" </tr>\n",
" <tr>\n",
" <th>34</th>\n",
" <td>Admiral</td>\n",
" <td>51458</td>\n",
" <td>43.736842</td>\n",
" <td>47.5803</td>\n",
" <td>-122.387118</td>\n",
" <td>7051.247368</td>\n",
" <td>2</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Grocery Store</td>\n",
" <td>Italian Restaurant</td>\n",
" <td>Theater</td>\n",
" <td>Salon / Barbershop</td>\n",
" <td>Mexican Restaurant</td>\n",
" <td>Middle Eastern Restaurant</td>\n",
" <td>Spa</td>\n",
" <td>Frozen Yogurt Shop</td>\n",
" <td>Pub</td>\n",
" </tr>\n",
" <tr>\n",
" <th>36</th>\n",
" <td>Queen Anne</td>\n",
" <td>55596</td>\n",
" <td>38.040625</td>\n",
" <td>47.6414</td>\n",
" <td>-122.360958</td>\n",
" <td>12571.496875</td>\n",
" <td>2</td>\n",
" <td>Bakery</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Restaurant</td>\n",
" <td>Yoga Studio</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Mexican Restaurant</td>\n",
" <td>Seafood Restaurant</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Market</td>\n",
" <td>Café</td>\n",
" </tr>\n",
" <tr>\n",
" <th>37</th>\n",
" <td>Atlantic</td>\n",
" <td>25814</td>\n",
" <td>38.060000</td>\n",
" <td>47.5905</td>\n",
" <td>-122.301564</td>\n",
" <td>10343.806667</td>\n",
" <td>2</td>\n",
" <td>Park</td>\n",
" <td>Bus Stop</td>\n",
" <td>Bus Station</td>\n",
" <td>Tunnel</td>\n",
" <td>Trail</td>\n",
" <td>Ethiopian Restaurant</td>\n",
" <td>Museum</td>\n",
" <td>Japanese Restaurant</td>\n",
" <td>Scenic Lookout</td>\n",
" <td>Dog Run</td>\n",
" </tr>\n",
" <tr>\n",
" <th>39</th>\n",
" <td>Madison Valley</td>\n",
" <td>49039</td>\n",
" <td>40.585714</td>\n",
" <td>47.6219</td>\n",
" <td>-122.296119</td>\n",
" <td>9170.942857</td>\n",
" <td>2</td>\n",
" <td>French Restaurant</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Italian Restaurant</td>\n",
" <td>Hardware Store</td>\n",
" <td>Sushi Restaurant</td>\n",
" <td>Kids Store</td>\n",
" <td>Bar</td>\n",
" <td>Salad Place</td>\n",
" <td>Japanese Restaurant</td>\n",
" <td>Bus Stop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>41</th>\n",
" <td>International District</td>\n",
" <td>23795</td>\n",
" <td>42.620000</td>\n",
" <td>47.5975</td>\n",
" <td>-122.319483</td>\n",
" <td>17579.306667</td>\n",
" <td>2</td>\n",
" <td>Vietnamese Restaurant</td>\n",
" <td>Chinese Restaurant</td>\n",
" <td>Pizza Place</td>\n",
" <td>Hotpot Restaurant</td>\n",
" <td>Thrift / Vintage Store</td>\n",
" <td>Massage Studio</td>\n",
" <td>Noodle House</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Dance Studio</td>\n",
" <td>Performing Arts Venue</td>\n",
" </tr>\n",
" <tr>\n",
" <th>43</th>\n",
" <td>University District</td>\n",
" <td>31344</td>\n",
" <td>28.924000</td>\n",
" <td>47.6603</td>\n",
" <td>-122.306311</td>\n",
" <td>19281.440000</td>\n",
" <td>2</td>\n",
" <td>Pet Store</td>\n",
" <td>Tanning Salon</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Ethiopian Restaurant</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" <td>Field</td>\n",
" </tr>\n",
" <tr>\n",
" <th>45</th>\n",
" <td>Ballard</td>\n",
" <td>40963</td>\n",
" <td>39.100000</td>\n",
" <td>47.6665</td>\n",
" <td>-122.376052</td>\n",
" <td>11085.669565</td>\n",
" <td>2</td>\n",
" <td>Brewery</td>\n",
" <td>Seafood Restaurant</td>\n",
" <td>Mexican Restaurant</td>\n",
" <td>Gaming Cafe</td>\n",
" <td>Pizza Place</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Marijuana Dispensary</td>\n",
" <td>Food Truck</td>\n",
" <td>Beer Bar</td>\n",
" <td>Supermarket</td>\n",
" </tr>\n",
" <tr>\n",
" <th>46</th>\n",
" <td>Portage Bay</td>\n",
" <td>68608</td>\n",
" <td>42.200000</td>\n",
" <td>47.6454</td>\n",
" <td>-122.317143</td>\n",
" <td>6909.850000</td>\n",
" <td>2</td>\n",
" <td>Playground</td>\n",
" <td>Deli / Bodega</td>\n",
" <td>Bar</td>\n",
" <td>Pizza Place</td>\n",
" <td>Dance Studio</td>\n",
" <td>Eye Doctor</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>49</th>\n",
" <td>Highland Park</td>\n",
" <td>23273</td>\n",
" <td>33.640000</td>\n",
" <td>47.5280</td>\n",
" <td>-122.343064</td>\n",
" <td>6513.213333</td>\n",
" <td>2</td>\n",
" <td>Dog Run</td>\n",
" <td>Baseball Field</td>\n",
" <td>Gym</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Eye Doctor</td>\n",
" <td>Food Truck</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>51</th>\n",
" <td>Wallingford</td>\n",
" <td>44655</td>\n",
" <td>33.855556</td>\n",
" <td>47.6593</td>\n",
" <td>-122.333749</td>\n",
" <td>12177.762963</td>\n",
" <td>2</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Ice Cream Shop</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Japanese Restaurant</td>\n",
" <td>Café</td>\n",
" <td>Restaurant</td>\n",
" <td>Beer Store</td>\n",
" <td>Clothing Store</td>\n",
" <td>Pub</td>\n",
" <td>Poke Place</td>\n",
" </tr>\n",
" <tr>\n",
" <th>53</th>\n",
" <td>Greenwood</td>\n",
" <td>37837</td>\n",
" <td>37.225000</td>\n",
" <td>47.6942</td>\n",
" <td>-122.355248</td>\n",
" <td>10170.633333</td>\n",
" <td>2</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Mexican Restaurant</td>\n",
" <td>Bar</td>\n",
" <td>Playground</td>\n",
" <td>Lounge</td>\n",
" <td>Bookstore</td>\n",
" <td>Middle Eastern Restaurant</td>\n",
" <td>Spa</td>\n",
" <td>Café</td>\n",
" <td>French Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>55</th>\n",
" <td>Columbia City</td>\n",
" <td>28851</td>\n",
" <td>37.988235</td>\n",
" <td>47.5556</td>\n",
" <td>-122.284281</td>\n",
" <td>8669.729412</td>\n",
" <td>2</td>\n",
" <td>Bar</td>\n",
" <td>African Restaurant</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Ice Cream Shop</td>\n",
" <td>Mexican Restaurant</td>\n",
" <td>Pizza Place</td>\n",
" <td>Poke Place</td>\n",
" <td>Music Venue</td>\n",
" <td>Ethiopian Restaurant</td>\n",
" <td>Pub</td>\n",
" </tr>\n",
" <tr>\n",
" <th>57</th>\n",
" <td>Montlake</td>\n",
" <td>65157</td>\n",
" <td>42.820000</td>\n",
" <td>47.6407</td>\n",
" <td>-122.303816</td>\n",
" <td>4397.260000</td>\n",
" <td>2</td>\n",
" <td>Bus Stop</td>\n",
" <td>Salon / Barbershop</td>\n",
" <td>Bike Shop</td>\n",
" <td>Farm</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Grocery Store</td>\n",
" <td>Italian Restaurant</td>\n",
" <td>Library</td>\n",
" <td>Park</td>\n",
" <td>Playground</td>\n",
" </tr>\n",
" <tr>\n",
" <th>60</th>\n",
" <td>Ravenna</td>\n",
" <td>40785</td>\n",
" <td>36.815000</td>\n",
" <td>47.6735</td>\n",
" <td>-122.300389</td>\n",
" <td>10964.250000</td>\n",
" <td>2</td>\n",
" <td>Bakery</td>\n",
" <td>Mediterranean Restaurant</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Bus Station</td>\n",
" <td>Bus Stop</td>\n",
" <td>Sushi Restaurant</td>\n",
" <td>Bagel Shop</td>\n",
" <td>New American Restaurant</td>\n",
" <td>Park</td>\n",
" <td>Southern / Soul Food Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>63</th>\n",
" <td>Madrona</td>\n",
" <td>53030</td>\n",
" <td>43.136364</td>\n",
" <td>47.6129</td>\n",
" <td>-122.288773</td>\n",
" <td>8126.663636</td>\n",
" <td>2</td>\n",
" <td>Gift Shop</td>\n",
" <td>French Restaurant</td>\n",
" <td>Asian Restaurant</td>\n",
" <td>Spa</td>\n",
" <td>Cupcake Shop</td>\n",
" <td>Furniture / Home Store</td>\n",
" <td>Ethiopian Restaurant</td>\n",
" <td>Bar</td>\n",
" <td>Italian Restaurant</td>\n",
" <td>Coffee Shop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>65</th>\n",
" <td>Bitter Lake</td>\n",
" <td>34450</td>\n",
" <td>43.981818</td>\n",
" <td>47.7195</td>\n",
" <td>-122.350162</td>\n",
" <td>9008.872727</td>\n",
" <td>2</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Marijuana Dispensary</td>\n",
" <td>Automotive Shop</td>\n",
" <td>Convenience Store</td>\n",
" <td>Sushi Restaurant</td>\n",
" <td>Steakhouse</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Restaurant</td>\n",
" <td>Pizza Place</td>\n",
" <td>ATM</td>\n",
" </tr>\n",
" <tr>\n",
" <th>69</th>\n",
" <td>South Delridge</td>\n",
" <td>25586</td>\n",
" <td>35.842857</td>\n",
" <td>47.5265</td>\n",
" <td>-122.360804</td>\n",
" <td>7293.821429</td>\n",
" <td>2</td>\n",
" <td>Spa</td>\n",
" <td>Eye Doctor</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Fountain</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" <td>Field</td>\n",
" </tr>\n",
" <tr>\n",
" <th>70</th>\n",
" <td>Cedar Park</td>\n",
" <td>37780</td>\n",
" <td>39.725000</td>\n",
" <td>47.7242</td>\n",
" <td>-122.287293</td>\n",
" <td>11275.083333</td>\n",
" <td>2</td>\n",
" <td>Dog Run</td>\n",
" <td>Gas Station</td>\n",
" <td>Brewery</td>\n",
" <td>Vietnamese Restaurant</td>\n",
" <td>Supermarket</td>\n",
" <td>Recreation Center</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Farm</td>\n",
" <td>Farmers Market</td>\n",
" <td>Fast Food Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>73</th>\n",
" <td>Phinney Ridge</td>\n",
" <td>47937</td>\n",
" <td>37.970833</td>\n",
" <td>47.6733</td>\n",
" <td>-122.353188</td>\n",
" <td>11101.016667</td>\n",
" <td>2</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Pizza Place</td>\n",
" <td>Pub</td>\n",
" <td>Dessert Shop</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Salon / Barbershop</td>\n",
" <td>Café</td>\n",
" <td>Music Venue</td>\n",
" <td>Bar</td>\n",
" <td>Chinese Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>74</th>\n",
" <td>West Seattle</td>\n",
" <td>45851</td>\n",
" <td>43.758824</td>\n",
" <td>47.5536</td>\n",
" <td>-122.391891</td>\n",
" <td>7484.032353</td>\n",
" <td>2</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Speakeasy</td>\n",
" <td>Bar</td>\n",
" <td>Garden Center</td>\n",
" <td>Salon / Barbershop</td>\n",
" <td>Night Market</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Marijuana Dispensary</td>\n",
" <td>Knitting Store</td>\n",
" <td>Pizza Place</td>\n",
" </tr>\n",
" <tr>\n",
" <th>75</th>\n",
" <td>Belltown</td>\n",
" <td>55230</td>\n",
" <td>40.755556</td>\n",
" <td>47.6148</td>\n",
" <td>-122.348303</td>\n",
" <td>25429.055556</td>\n",
" <td>2</td>\n",
" <td>Cocktail Bar</td>\n",
" <td>Steakhouse</td>\n",
" <td>Sushi Restaurant</td>\n",
" <td>Bar</td>\n",
" <td>Korean Restaurant</td>\n",
" <td>Bakery</td>\n",
" <td>Gastropub</td>\n",
" <td>Beer Bar</td>\n",
" <td>Garden</td>\n",
" <td>Thai Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>77</th>\n",
" <td>Georgetown</td>\n",
" <td>27613</td>\n",
" <td>39.325000</td>\n",
" <td>47.5403</td>\n",
" <td>-122.316371</td>\n",
" <td>1763.362500</td>\n",
" <td>2</td>\n",
" <td>Museum</td>\n",
" <td>Indie Theater</td>\n",
" <td>Gas Station</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Event Space</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" name pc_income median age_census latitude longitude \\\n",
"1 Brighton 23520 35.843750 47.5388 -122.275673 \n",
"2 Whittier Heights 41725 39.457143 47.6833 -122.371407 \n",
"6 Roosevelt 40906 34.614286 47.6772 -122.316196 \n",
"8 Westlake 54865 39.500000 47.6349 -122.341812 \n",
"9 Sand Point 55299 43.500000 47.6817 -122.255718 \n",
"13 Beacon Hill 25174 37.592308 47.5541 -122.300861 \n",
"14 Rainier Beach 26397 39.600000 47.5135 -122.261648 \n",
"16 Madison Park 76309 46.900000 47.6333 -122.283182 \n",
"17 High Point 29334 34.233333 47.5441 -122.368633 \n",
"18 Interbay 48811 40.200000 47.6420 -122.380360 \n",
"25 First Hill 32941 36.257143 47.6085 -122.323689 \n",
"27 Northgate 35382 40.772727 47.7081 -122.321857 \n",
"28 Lower Queen Anne 59411 37.250000 47.6251 -122.355650 \n",
"29 Eastlake 59684 36.877778 47.6379 -122.328229 \n",
"33 Downtown 38300 41.160000 47.6068 -122.339989 \n",
"34 Admiral 51458 43.736842 47.5803 -122.387118 \n",
"36 Queen Anne 55596 38.040625 47.6414 -122.360958 \n",
"37 Atlantic 25814 38.060000 47.5905 -122.301564 \n",
"39 Madison Valley 49039 40.585714 47.6219 -122.296119 \n",
"41 International District 23795 42.620000 47.5975 -122.319483 \n",
"43 University District 31344 28.924000 47.6603 -122.306311 \n",
"45 Ballard 40963 39.100000 47.6665 -122.376052 \n",
"46 Portage Bay 68608 42.200000 47.6454 -122.317143 \n",
"49 Highland Park 23273 33.640000 47.5280 -122.343064 \n",
"51 Wallingford 44655 33.855556 47.6593 -122.333749 \n",
"53 Greenwood 37837 37.225000 47.6942 -122.355248 \n",
"55 Columbia City 28851 37.988235 47.5556 -122.284281 \n",
"57 Montlake 65157 42.820000 47.6407 -122.303816 \n",
"60 Ravenna 40785 36.815000 47.6735 -122.300389 \n",
"63 Madrona 53030 43.136364 47.6129 -122.288773 \n",
"65 Bitter Lake 34450 43.981818 47.7195 -122.350162 \n",
"69 South Delridge 25586 35.842857 47.5265 -122.360804 \n",
"70 Cedar Park 37780 39.725000 47.7242 -122.287293 \n",
"73 Phinney Ridge 47937 37.970833 47.6733 -122.353188 \n",
"74 West Seattle 45851 43.758824 47.5536 -122.391891 \n",
"75 Belltown 55230 40.755556 47.6148 -122.348303 \n",
"77 Georgetown 27613 39.325000 47.5403 -122.316371 \n",
"\n",
" popdensity Cluster Labels 1st Most Common Venue \\\n",
"1 11462.300000 2 Mexican Restaurant \n",
"2 10478.685714 2 Bar \n",
"6 10132.100000 2 Vegetarian / Vegan Restaurant \n",
"8 9201.244444 2 Harbor / Marina \n",
"9 5598.020000 2 Dog Run \n",
"13 8630.397436 2 Bus Station \n",
"14 7352.230435 2 Dessert Shop \n",
"16 6296.500000 2 Bank \n",
"17 8380.480000 2 Playground \n",
"18 7233.818750 2 Bus Stop \n",
"25 28164.214286 2 Sandwich Place \n",
"27 9248.927273 2 Mexican Restaurant \n",
"28 18774.038889 2 Coffee Shop \n",
"29 9791.577778 2 Mexican Restaurant \n",
"33 23976.375000 2 Seafood Restaurant \n",
"34 7051.247368 2 Coffee Shop \n",
"36 12571.496875 2 Bakery \n",
"37 10343.806667 2 Park \n",
"39 9170.942857 2 French Restaurant \n",
"41 17579.306667 2 Vietnamese Restaurant \n",
"43 19281.440000 2 Pet Store \n",
"45 11085.669565 2 Brewery \n",
"46 6909.850000 2 Playground \n",
"49 6513.213333 2 Dog Run \n",
"51 12177.762963 2 Coffee Shop \n",
"53 10170.633333 2 Coffee Shop \n",
"55 8669.729412 2 Bar \n",
"57 4397.260000 2 Bus Stop \n",
"60 10964.250000 2 Bakery \n",
"63 8126.663636 2 Gift Shop \n",
"65 9008.872727 2 Thai Restaurant \n",
"69 7293.821429 2 Spa \n",
"70 11275.083333 2 Dog Run \n",
"73 11101.016667 2 Zoo Exhibit \n",
"74 7484.032353 2 Thai Restaurant \n",
"75 25429.055556 2 Cocktail Bar \n",
"77 1763.362500 2 Museum \n",
"\n",
" 2nd Most Common Venue 3rd Most Common Venue 4th Most Common Venue \\\n",
"1 Vietnamese Restaurant Coffee Shop Breakfast Spot \n",
"2 Dance Studio Trail Caribbean Restaurant \n",
"6 Coffee Shop Spa Gym / Fitness Center \n",
"8 Bus Stop Deli / Bodega Boat or Ferry \n",
"9 Tennis Court Theater Food Truck \n",
"13 Light Rail Station Zoo Exhibit Eye Doctor \n",
"14 Garden Baseball Field Zoo Exhibit \n",
"16 Thai Restaurant Playground Soccer Field \n",
"17 Vietnamese Restaurant Garden Electronics Store \n",
"18 Golf Course Bike Shop Garden \n",
"25 Bakery Coffee Shop Hotel \n",
"27 Arts & Crafts Store Dance Studio Department Store \n",
"28 Performing Arts Venue Theater Indie Movie Theater \n",
"29 Coffee Shop Bus Stop Sandwich Place \n",
"33 Cocktail Bar Coffee Shop New American Restaurant \n",
"34 Grocery Store Italian Restaurant Theater \n",
"36 Thai Restaurant Restaurant Yoga Studio \n",
"37 Bus Stop Bus Station Tunnel \n",
"39 Dessert Shop Italian Restaurant Hardware Store \n",
"41 Chinese Restaurant Pizza Place Hotpot Restaurant \n",
"43 Tanning Salon Zoo Exhibit Ethiopian Restaurant \n",
"45 Seafood Restaurant Mexican Restaurant Gaming Cafe \n",
"46 Deli / Bodega Bar Pizza Place \n",
"49 Baseball Field Gym Zoo Exhibit \n",
"51 Ice Cream Shop Thai Restaurant Japanese Restaurant \n",
"53 Mexican Restaurant Bar Playground \n",
"55 African Restaurant Coffee Shop Ice Cream Shop \n",
"57 Salon / Barbershop Bike Shop Farm \n",
"60 Mediterranean Restaurant Coffee Shop Bus Station \n",
"63 French Restaurant Asian Restaurant Spa \n",
"65 Marijuana Dispensary Automotive Shop Convenience Store \n",
"69 Eye Doctor Zoo Exhibit Fountain \n",
"70 Gas Station Brewery Vietnamese Restaurant \n",
"73 Pizza Place Pub Dessert Shop \n",
"74 Speakeasy Bar Garden Center \n",
"75 Steakhouse Sushi Restaurant Bar \n",
"77 Indie Theater Gas Station Sandwich Place \n",
"\n",
" 5th Most Common Venue 6th Most Common Venue \\\n",
"1 Seafood Restaurant Café \n",
"2 Rental Car Location Bakery \n",
"6 Burger Joint Salon / Barbershop \n",
"8 Pool Track \n",
"9 Snack Place Playground \n",
"13 Food Truck Food Court \n",
"14 Eye Doctor Food Truck \n",
"16 Food & Drink Shop Café \n",
"17 Food & Drink Shop Food \n",
"18 Coffee Shop Electronics Store \n",
"25 Restaurant Sushi Restaurant \n",
"27 Big Box Store Sporting Goods Shop \n",
"28 Seafood Restaurant Fondue Restaurant \n",
"29 Italian Restaurant Burger Joint \n",
"33 Theme Park Ride / Attraction Other Nightlife \n",
"34 Salon / Barbershop Mexican Restaurant \n",
"36 Coffee Shop Mexican Restaurant \n",
"37 Trail Ethiopian Restaurant \n",
"39 Sushi Restaurant Kids Store \n",
"41 Thrift / Vintage Store Massage Studio \n",
"43 Food Court Food & Drink Shop \n",
"45 Pizza Place Sandwich Place \n",
"46 Dance Studio Eye Doctor \n",
"49 Eye Doctor Food Truck \n",
"51 Café Restaurant \n",
"53 Lounge Bookstore \n",
"55 Mexican Restaurant Pizza Place \n",
"57 Coffee Shop Grocery Store \n",
"60 Bus Stop Sushi Restaurant \n",
"63 Cupcake Shop Furniture / Home Store \n",
"65 Sushi Restaurant Steakhouse \n",
"69 Food Court Food & Drink Shop \n",
"70 Supermarket Recreation Center \n",
"73 Sandwich Place Salon / Barbershop \n",
"74 Salon / Barbershop Night Market \n",
"75 Korean Restaurant Bakery \n",
"77 Zoo Exhibit Event Space \n",
"\n",
" 7th Most Common Venue 8th Most Common Venue \\\n",
"1 Fast Food Restaurant Gas Station \n",
"2 Karaoke Bar Theme Park Ride / Attraction \n",
"6 Indian Restaurant Breakfast Spot \n",
"8 Chinese Restaurant Café \n",
"9 Night Market Garden \n",
"13 Food & Drink Shop Food \n",
"14 Food Court Food & Drink Shop \n",
"16 Bar Bakery \n",
"17 Fondue Restaurant Fish Market \n",
"18 Grocery Store Gym \n",
"25 Supplement Shop Speakeasy \n",
"27 Library Spa \n",
"28 Lounge Cajun / Creole Restaurant \n",
"29 Boat or Ferry Park \n",
"33 Ice Cream Shop Rock Club \n",
"34 Middle Eastern Restaurant Spa \n",
"36 Seafood Restaurant Sandwich Place \n",
"37 Museum Japanese Restaurant \n",
"39 Bar Salad Place \n",
"41 Noodle House Dessert Shop \n",
"43 Food Fondue Restaurant \n",
"45 Marijuana Dispensary Food Truck \n",
"46 Food Court Food & Drink Shop \n",
"49 Food Court Food & Drink Shop \n",
"51 Beer Store Clothing Store \n",
"53 Middle Eastern Restaurant Spa \n",
"55 Poke Place Music Venue \n",
"57 Italian Restaurant Library \n",
"60 Bagel Shop New American Restaurant \n",
"63 Ethiopian Restaurant Bar \n",
"65 Sandwich Place Restaurant \n",
"69 Food Fondue Restaurant \n",
"70 Zoo Exhibit Farm \n",
"73 Café Music Venue \n",
"74 Coffee Shop Marijuana Dispensary \n",
"75 Gastropub Beer Bar \n",
"77 Food & Drink Shop Food \n",
"\n",
" 9th Most Common Venue 10th Most Common Venue \n",
"1 Bank Mobile Phone Shop \n",
"2 Cocktail Bar Breakfast Spot \n",
"6 Bookstore Mexican Restaurant \n",
"8 Cocktail Bar Sandwich Place \n",
"9 Indie Movie Theater Sculpture Garden \n",
"13 Fondue Restaurant Fish Market \n",
"14 Food Fondue Restaurant \n",
"16 Dry Cleaner Coffee Shop \n",
"17 Field Fast Food Restaurant \n",
"18 Asian Restaurant Basketball Court \n",
"25 Snack Place Café \n",
"27 Lingerie Store Snack Place \n",
"28 Music Venue Radio Station \n",
"29 Sporting Goods Shop Furniture / Home Store \n",
"33 Lounge Spa \n",
"34 Frozen Yogurt Shop Pub \n",
"36 Market Café \n",
"37 Scenic Lookout Dog Run \n",
"39 Japanese Restaurant Bus Stop \n",
"41 Dance Studio Performing Arts Venue \n",
"43 Fish Market Field \n",
"45 Beer Bar Supermarket \n",
"46 Food Fondue Restaurant \n",
"49 Food Fondue Restaurant \n",
"51 Pub Poke Place \n",
"53 Café French Restaurant \n",
"55 Ethiopian Restaurant Pub \n",
"57 Park Playground \n",
"60 Park Southern / Soul Food Restaurant \n",
"63 Italian Restaurant Coffee Shop \n",
"65 Pizza Place ATM \n",
"69 Fish Market Field \n",
"70 Farmers Market Fast Food Restaurant \n",
"73 Bar Chinese Restaurant \n",
"74 Knitting Store Pizza Place \n",
"75 Garden Thai Restaurant \n",
"77 Fondue Restaurant Fish Market "
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"seattle_merged.loc[seattle_merged['Cluster Labels'] == 2, seattle_merged.columns[[1] + list(range(2, seattle_merged.shape[1]))]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Cluster 4"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>name</th>\n",
" <th>pc_income</th>\n",
" <th>median age_census</th>\n",
" <th>latitude</th>\n",
" <th>longitude</th>\n",
" <th>popdensity</th>\n",
" <th>Cluster Labels</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Loyal Heights</td>\n",
" <td>40157</td>\n",
" <td>40.529412</td>\n",
" <td>47.6832</td>\n",
" <td>-122.384869</td>\n",
" <td>10233.158824</td>\n",
" <td>3</td>\n",
" <td>Pizza Place</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Athletics &amp; Sports</td>\n",
" <td>Food Truck</td>\n",
" <td>Fish Market</td>\n",
" <td>Café</td>\n",
" <td>Music Store</td>\n",
" <td>General College &amp; University</td>\n",
" <td>Bakery</td>\n",
" <td>Middle Eastern Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>Pioneer Square</td>\n",
" <td>41304</td>\n",
" <td>45.725000</td>\n",
" <td>47.5975</td>\n",
" <td>-122.332777</td>\n",
" <td>10274.175000</td>\n",
" <td>3</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Cocktail Bar</td>\n",
" <td>Wine Bar</td>\n",
" <td>Sporting Goods Shop</td>\n",
" <td>Italian Restaurant</td>\n",
" <td>German Restaurant</td>\n",
" <td>Mexican Restaurant</td>\n",
" <td>Food Truck</td>\n",
" <td>Café</td>\n",
" <td>Candy Store</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11</th>\n",
" <td>Maple Leaf</td>\n",
" <td>38895</td>\n",
" <td>39.850000</td>\n",
" <td>47.6952</td>\n",
" <td>-122.317400</td>\n",
" <td>8168.300000</td>\n",
" <td>3</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Arts &amp; Crafts Store</td>\n",
" <td>Toy / Game Store</td>\n",
" <td>Video Store</td>\n",
" <td>Theater</td>\n",
" <td>Chinese Restaurant</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Gourmet Shop</td>\n",
" <td>Cocktail Bar</td>\n",
" <td>Bus Stop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>12</th>\n",
" <td>Sunset Hill</td>\n",
" <td>44096</td>\n",
" <td>42.942857</td>\n",
" <td>47.6779</td>\n",
" <td>-122.400985</td>\n",
" <td>8570.428571</td>\n",
" <td>3</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Boat or Ferry</td>\n",
" <td>Board Shop</td>\n",
" <td>Bakery</td>\n",
" <td>Post Office</td>\n",
" <td>Outdoor Sculpture</td>\n",
" <td>Italian Restaurant</td>\n",
" <td>Harbor / Marina</td>\n",
" <td>Ice Cream Shop</td>\n",
" <td>Playground</td>\n",
" </tr>\n",
" <tr>\n",
" <th>21</th>\n",
" <td>Wedgwood</td>\n",
" <td>43218</td>\n",
" <td>41.047826</td>\n",
" <td>47.6899</td>\n",
" <td>-122.296483</td>\n",
" <td>7453.430435</td>\n",
" <td>3</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Park</td>\n",
" <td>Pharmacy</td>\n",
" <td>Supermarket</td>\n",
" <td>Steakhouse</td>\n",
" <td>Lounge</td>\n",
" <td>Pub</td>\n",
" <td>ATM</td>\n",
" <td>Video Store</td>\n",
" <td>Dance Studio</td>\n",
" </tr>\n",
" <tr>\n",
" <th>22</th>\n",
" <td>South Lake Union</td>\n",
" <td>49155</td>\n",
" <td>35.990909</td>\n",
" <td>47.6219</td>\n",
" <td>-122.338394</td>\n",
" <td>14765.927273</td>\n",
" <td>3</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Mexican Restaurant</td>\n",
" <td>Bar</td>\n",
" <td>Pizza Place</td>\n",
" <td>Breakfast Spot</td>\n",
" <td>Food Truck</td>\n",
" <td>Martial Arts Dojo</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Café</td>\n",
" <td>Camera Store</td>\n",
" </tr>\n",
" <tr>\n",
" <th>24</th>\n",
" <td>Capitol Hill</td>\n",
" <td>50184</td>\n",
" <td>37.360976</td>\n",
" <td>47.6272</td>\n",
" <td>-122.312452</td>\n",
" <td>20721.204878</td>\n",
" <td>3</td>\n",
" <td>Park</td>\n",
" <td>Bakery</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Performing Arts Venue</td>\n",
" <td>Marijuana Dispensary</td>\n",
" <td>Thai Restaurant</td>\n",
" <td>Scenic Lookout</td>\n",
" <td>Lounge</td>\n",
" <td>Gift Shop</td>\n",
" <td>Sporting Goods Shop</td>\n",
" </tr>\n",
" <tr>\n",
" <th>31</th>\n",
" <td>Haller Lake</td>\n",
" <td>31972</td>\n",
" <td>38.700000</td>\n",
" <td>47.7203</td>\n",
" <td>-122.335100</td>\n",
" <td>6936.507692</td>\n",
" <td>3</td>\n",
" <td>Dance Studio</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Track</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Event Space</td>\n",
" <td>Food Truck</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>40</th>\n",
" <td>Central District</td>\n",
" <td>30653</td>\n",
" <td>37.012500</td>\n",
" <td>47.6060</td>\n",
" <td>-122.306481</td>\n",
" <td>12971.179167</td>\n",
" <td>3</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Baseball Field</td>\n",
" <td>Fried Chicken Joint</td>\n",
" <td>Bus Stop</td>\n",
" <td>BBQ Joint</td>\n",
" <td>Café</td>\n",
" <td>Gym Pool</td>\n",
" <td>Convenience Store</td>\n",
" <td>Tennis Court</td>\n",
" <td>Fish Market</td>\n",
" </tr>\n",
" <tr>\n",
" <th>42</th>\n",
" <td>Industrial District</td>\n",
" <td>40111</td>\n",
" <td>41.718182</td>\n",
" <td>47.5698</td>\n",
" <td>-122.345730</td>\n",
" <td>2559.227273</td>\n",
" <td>3</td>\n",
" <td>Deli / Bodega</td>\n",
" <td>Harbor / Marina</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Event Space</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" </tr>\n",
" <tr>\n",
" <th>48</th>\n",
" <td>North Delridge</td>\n",
" <td>34876</td>\n",
" <td>40.450000</td>\n",
" <td>47.5627</td>\n",
" <td>-122.364592</td>\n",
" <td>5430.820000</td>\n",
" <td>3</td>\n",
" <td>Bus Station</td>\n",
" <td>Soccer Field</td>\n",
" <td>Park</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Skate Park</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Event Space</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" </tr>\n",
" <tr>\n",
" <th>50</th>\n",
" <td>Fremont</td>\n",
" <td>45672</td>\n",
" <td>35.184211</td>\n",
" <td>47.6570</td>\n",
" <td>-122.353294</td>\n",
" <td>11167.542105</td>\n",
" <td>3</td>\n",
" <td>Park</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Japanese Restaurant</td>\n",
" <td>Performing Arts Venue</td>\n",
" <td>Optical Shop</td>\n",
" <td>Pizza Place</td>\n",
" <td>Comic Shop</td>\n",
" <td>Cocktail Bar</td>\n",
" <td>Record Shop</td>\n",
" <td>Caribbean Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>61</th>\n",
" <td>Laurelhurst</td>\n",
" <td>53868</td>\n",
" <td>39.033333</td>\n",
" <td>47.6588</td>\n",
" <td>-122.278132</td>\n",
" <td>6649.411111</td>\n",
" <td>3</td>\n",
" <td>Pharmacy</td>\n",
" <td>Park</td>\n",
" <td>Music Venue</td>\n",
" <td>Juice Bar</td>\n",
" <td>Café</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Event Space</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>62</th>\n",
" <td>Crown Hill</td>\n",
" <td>41844</td>\n",
" <td>41.233333</td>\n",
" <td>47.6961</td>\n",
" <td>-122.371399</td>\n",
" <td>7402.866667</td>\n",
" <td>3</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Burger Joint</td>\n",
" <td>Mexican Restaurant</td>\n",
" <td>Taco Place</td>\n",
" <td>Pizza Place</td>\n",
" <td>Sports Bar</td>\n",
" <td>Pet Store</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" </tr>\n",
" <tr>\n",
" <th>68</th>\n",
" <td>Bryant</td>\n",
" <td>43710</td>\n",
" <td>39.592308</td>\n",
" <td>47.6718</td>\n",
" <td>-122.286069</td>\n",
" <td>7839.515385</td>\n",
" <td>3</td>\n",
" <td>Chinese Restaurant</td>\n",
" <td>Organic Grocery</td>\n",
" <td>Bus Station</td>\n",
" <td>Seafood Restaurant</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Trail</td>\n",
" <td>Italian Restaurant</td>\n",
" <td>Grocery Store</td>\n",
" <td>Martial Arts Dojo</td>\n",
" <td>Park</td>\n",
" </tr>\n",
" <tr>\n",
" <th>71</th>\n",
" <td>Victory Heights</td>\n",
" <td>35463</td>\n",
" <td>39.012500</td>\n",
" <td>47.7103</td>\n",
" <td>-122.304937</td>\n",
" <td>9331.293750</td>\n",
" <td>3</td>\n",
" <td>Pizza Place</td>\n",
" <td>Music Store</td>\n",
" <td>Gas Station</td>\n",
" <td>Asian Restaurant</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Marijuana Dispensary</td>\n",
" <td>Pharmacy</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Field</td>\n",
" <td>Fish Market</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" name pc_income median age_census latitude longitude \\\n",
"4 Loyal Heights 40157 40.529412 47.6832 -122.384869 \n",
"7 Pioneer Square 41304 45.725000 47.5975 -122.332777 \n",
"11 Maple Leaf 38895 39.850000 47.6952 -122.317400 \n",
"12 Sunset Hill 44096 42.942857 47.6779 -122.400985 \n",
"21 Wedgwood 43218 41.047826 47.6899 -122.296483 \n",
"22 South Lake Union 49155 35.990909 47.6219 -122.338394 \n",
"24 Capitol Hill 50184 37.360976 47.6272 -122.312452 \n",
"31 Haller Lake 31972 38.700000 47.7203 -122.335100 \n",
"40 Central District 30653 37.012500 47.6060 -122.306481 \n",
"42 Industrial District 40111 41.718182 47.5698 -122.345730 \n",
"48 North Delridge 34876 40.450000 47.5627 -122.364592 \n",
"50 Fremont 45672 35.184211 47.6570 -122.353294 \n",
"61 Laurelhurst 53868 39.033333 47.6588 -122.278132 \n",
"62 Crown Hill 41844 41.233333 47.6961 -122.371399 \n",
"68 Bryant 43710 39.592308 47.6718 -122.286069 \n",
"71 Victory Heights 35463 39.012500 47.7103 -122.304937 \n",
"\n",
" popdensity Cluster Labels 1st Most Common Venue 2nd Most Common Venue \\\n",
"4 10233.158824 3 Pizza Place Coffee Shop \n",
"7 10274.175000 3 Coffee Shop Cocktail Bar \n",
"11 8168.300000 3 Coffee Shop Arts & Crafts Store \n",
"12 8570.428571 3 Coffee Shop Boat or Ferry \n",
"21 7453.430435 3 Coffee Shop Park \n",
"22 14765.927273 3 Coffee Shop Mexican Restaurant \n",
"24 20721.204878 3 Park Bakery \n",
"31 6936.507692 3 Dance Studio Coffee Shop \n",
"40 12971.179167 3 Coffee Shop Baseball Field \n",
"42 2559.227273 3 Deli / Bodega Harbor / Marina \n",
"48 5430.820000 3 Bus Station Soccer Field \n",
"50 11167.542105 3 Park Coffee Shop \n",
"61 6649.411111 3 Pharmacy Park \n",
"62 7402.866667 3 Coffee Shop Burger Joint \n",
"68 7839.515385 3 Chinese Restaurant Organic Grocery \n",
"71 9331.293750 3 Pizza Place Music Store \n",
"\n",
" 3rd Most Common Venue 4th Most Common Venue 5th Most Common Venue \\\n",
"4 Athletics & Sports Food Truck Fish Market \n",
"7 Wine Bar Sporting Goods Shop Italian Restaurant \n",
"11 Toy / Game Store Video Store Theater \n",
"12 Board Shop Bakery Post Office \n",
"21 Pharmacy Supermarket Steakhouse \n",
"22 Bar Pizza Place Breakfast Spot \n",
"24 Coffee Shop Performing Arts Venue Marijuana Dispensary \n",
"31 Track Zoo Exhibit Event Space \n",
"40 Fried Chicken Joint Bus Stop BBQ Joint \n",
"42 Coffee Shop Zoo Exhibit Event Space \n",
"48 Park Coffee Shop Skate Park \n",
"50 Japanese Restaurant Performing Arts Venue Optical Shop \n",
"61 Music Venue Juice Bar Café \n",
"62 Mexican Restaurant Taco Place Pizza Place \n",
"68 Bus Station Seafood Restaurant Coffee Shop \n",
"71 Gas Station Asian Restaurant Coffee Shop \n",
"\n",
" 6th Most Common Venue 7th Most Common Venue 8th Most Common Venue \\\n",
"4 Café Music Store General College & University \n",
"7 German Restaurant Mexican Restaurant Food Truck \n",
"11 Chinese Restaurant Thai Restaurant Gourmet Shop \n",
"12 Outdoor Sculpture Italian Restaurant Harbor / Marina \n",
"21 Lounge Pub ATM \n",
"22 Food Truck Martial Arts Dojo Sandwich Place \n",
"24 Thai Restaurant Scenic Lookout Lounge \n",
"31 Food Truck Food Court Food & Drink Shop \n",
"40 Café Gym Pool Convenience Store \n",
"42 Food Court Food & Drink Shop Food \n",
"48 Zoo Exhibit Event Space Food \n",
"50 Pizza Place Comic Shop Cocktail Bar \n",
"61 Zoo Exhibit Event Space Food & Drink Shop \n",
"62 Sports Bar Pet Store Sandwich Place \n",
"68 Trail Italian Restaurant Grocery Store \n",
"71 Marijuana Dispensary Pharmacy Sandwich Place \n",
"\n",
" 9th Most Common Venue 10th Most Common Venue \n",
"4 Bakery Middle Eastern Restaurant \n",
"7 Café Candy Store \n",
"11 Cocktail Bar Bus Stop \n",
"12 Ice Cream Shop Playground \n",
"21 Video Store Dance Studio \n",
"22 Café Camera Store \n",
"24 Gift Shop Sporting Goods Shop \n",
"31 Food Fondue Restaurant \n",
"40 Tennis Court Fish Market \n",
"42 Fondue Restaurant Fish Market \n",
"48 Fondue Restaurant Fish Market \n",
"50 Record Shop Caribbean Restaurant \n",
"61 Food Fondue Restaurant \n",
"62 Fondue Restaurant Fish Market \n",
"68 Martial Arts Dojo Park \n",
"71 Field Fish Market "
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"seattle_merged.loc[seattle_merged['Cluster Labels'] == 3, seattle_merged.columns[[1] + list(range(2, seattle_merged.shape[1]))]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Cluster 5"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>name</th>\n",
" <th>pc_income</th>\n",
" <th>median age_census</th>\n",
" <th>latitude</th>\n",
" <th>longitude</th>\n",
" <th>popdensity</th>\n",
" <th>Cluster Labels</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>59</th>\n",
" <td>Olympic Hills</td>\n",
" <td>29614</td>\n",
" <td>37.992308</td>\n",
" <td>47.7266</td>\n",
" <td>-122.302589</td>\n",
" <td>11859.538462</td>\n",
" <td>4</td>\n",
" <td>Pool</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Ethiopian Restaurant</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" <td>Field</td>\n",
" <td>Fast Food Restaurant</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" name pc_income median age_census latitude longitude \\\n",
"59 Olympic Hills 29614 37.992308 47.7266 -122.302589 \n",
"\n",
" popdensity Cluster Labels 1st Most Common Venue 2nd Most Common Venue \\\n",
"59 11859.538462 4 Pool Zoo Exhibit \n",
"\n",
" 3rd Most Common Venue 4th Most Common Venue 5th Most Common Venue \\\n",
"59 Ethiopian Restaurant Food Court Food & Drink Shop \n",
"\n",
" 6th Most Common Venue 7th Most Common Venue 8th Most Common Venue \\\n",
"59 Food Fondue Restaurant Fish Market \n",
"\n",
" 9th Most Common Venue 10th Most Common Venue \n",
"59 Field Fast Food Restaurant "
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"seattle_merged.loc[seattle_merged['Cluster Labels'] == 4, seattle_merged.columns[[1] + list(range(2, seattle_merged.shape[1]))]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Cluster 6"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>name</th>\n",
" <th>pc_income</th>\n",
" <th>median age_census</th>\n",
" <th>latitude</th>\n",
" <th>longitude</th>\n",
" <th>popdensity</th>\n",
" <th>Cluster Labels</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>56</th>\n",
" <td>Riverview</td>\n",
" <td>27081</td>\n",
" <td>34.825</td>\n",
" <td>47.5463</td>\n",
" <td>-122.353352</td>\n",
" <td>6269.5125</td>\n",
" <td>5</td>\n",
" <td>Bakery</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>French Restaurant</td>\n",
" <td>Food Truck</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" <td>Field</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" name pc_income median age_census latitude longitude popdensity \\\n",
"56 Riverview 27081 34.825 47.5463 -122.353352 6269.5125 \n",
"\n",
" Cluster Labels 1st Most Common Venue 2nd Most Common Venue \\\n",
"56 5 Bakery Zoo Exhibit \n",
"\n",
" 3rd Most Common Venue 4th Most Common Venue 5th Most Common Venue \\\n",
"56 French Restaurant Food Truck Food Court \n",
"\n",
" 6th Most Common Venue 7th Most Common Venue 8th Most Common Venue \\\n",
"56 Food & Drink Shop Food Fondue Restaurant \n",
"\n",
" 9th Most Common Venue 10th Most Common Venue \n",
"56 Fish Market Field "
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"seattle_merged.loc[seattle_merged['Cluster Labels'] == 5, seattle_merged.columns[[1] + list(range(2, seattle_merged.shape[1]))]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Cluster 7"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>name</th>\n",
" <th>pc_income</th>\n",
" <th>median age_census</th>\n",
" <th>latitude</th>\n",
" <th>longitude</th>\n",
" <th>popdensity</th>\n",
" <th>Cluster Labels</th>\n",
" <th>1st Most Common Venue</th>\n",
" <th>2nd Most Common Venue</th>\n",
" <th>3rd Most Common Venue</th>\n",
" <th>4th Most Common Venue</th>\n",
" <th>5th Most Common Venue</th>\n",
" <th>6th Most Common Venue</th>\n",
" <th>7th Most Common Venue</th>\n",
" <th>8th Most Common Venue</th>\n",
" <th>9th Most Common Venue</th>\n",
" <th>10th Most Common Venue</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Pinehurst</td>\n",
" <td>33705</td>\n",
" <td>40.640000</td>\n",
" <td>47.7229</td>\n",
" <td>-122.319553</td>\n",
" <td>7337.190000</td>\n",
" <td>6</td>\n",
" <td>Park</td>\n",
" <td>Moving Target</td>\n",
" <td>Garden</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Dog Run</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Event Space</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Windermere</td>\n",
" <td>56478</td>\n",
" <td>42.383333</td>\n",
" <td>47.6701</td>\n",
" <td>-122.262675</td>\n",
" <td>6346.766667</td>\n",
" <td>6</td>\n",
" <td>Park</td>\n",
" <td>Pizza Place</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Ethiopian Restaurant</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" <td>Field</td>\n",
" </tr>\n",
" <tr>\n",
" <th>10</th>\n",
" <td>South Park</td>\n",
" <td>23577</td>\n",
" <td>32.366667</td>\n",
" <td>47.5288</td>\n",
" <td>-122.323015</td>\n",
" <td>3663.933333</td>\n",
" <td>6</td>\n",
" <td>Park</td>\n",
" <td>Brewery</td>\n",
" <td>Library</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Event Space</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" </tr>\n",
" <tr>\n",
" <th>19</th>\n",
" <td>View Ridge</td>\n",
" <td>51864</td>\n",
" <td>44.509091</td>\n",
" <td>47.6834</td>\n",
" <td>-122.273935</td>\n",
" <td>6056.290909</td>\n",
" <td>6</td>\n",
" <td>Park</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Event Space</td>\n",
" <td>Food Truck</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" <td>Field</td>\n",
" </tr>\n",
" <tr>\n",
" <th>23</th>\n",
" <td>Fauntleroy</td>\n",
" <td>44606</td>\n",
" <td>45.366667</td>\n",
" <td>47.5232</td>\n",
" <td>-122.388978</td>\n",
" <td>6106.541667</td>\n",
" <td>6</td>\n",
" <td>Park</td>\n",
" <td>Pizza Place</td>\n",
" <td>Bakery</td>\n",
" <td>Dance Studio</td>\n",
" <td>Pier</td>\n",
" <td>Market</td>\n",
" <td>Pilates Studio</td>\n",
" <td>American Restaurant</td>\n",
" <td>Gymnastics Gym</td>\n",
" <td>Dumpling Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>26</th>\n",
" <td>Arbor Heights</td>\n",
" <td>38305</td>\n",
" <td>44.683333</td>\n",
" <td>47.5079</td>\n",
" <td>-122.380849</td>\n",
" <td>5354.600000</td>\n",
" <td>6</td>\n",
" <td>BBQ Joint</td>\n",
" <td>Park</td>\n",
" <td>Scenic Lookout</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" <td>Field</td>\n",
" </tr>\n",
" <tr>\n",
" <th>30</th>\n",
" <td>Mount Baker</td>\n",
" <td>37183</td>\n",
" <td>39.973333</td>\n",
" <td>47.5760</td>\n",
" <td>-122.286975</td>\n",
" <td>7071.486667</td>\n",
" <td>6</td>\n",
" <td>Park</td>\n",
" <td>Pizza Place</td>\n",
" <td>Harbor / Marina</td>\n",
" <td>Café</td>\n",
" <td>Scenic Lookout</td>\n",
" <td>Food</td>\n",
" <td>Convenience Store</td>\n",
" <td>Pet Store</td>\n",
" <td>Deli / Bodega</td>\n",
" <td>Fondue Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>35</th>\n",
" <td>North College Park</td>\n",
" <td>34197</td>\n",
" <td>35.000000</td>\n",
" <td>47.6990</td>\n",
" <td>-122.336766</td>\n",
" <td>8823.460000</td>\n",
" <td>6</td>\n",
" <td>Food Court</td>\n",
" <td>Concert Hall</td>\n",
" <td>Community College</td>\n",
" <td>Park</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Event Space</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" </tr>\n",
" <tr>\n",
" <th>38</th>\n",
" <td>Denny-Blaine</td>\n",
" <td>74598</td>\n",
" <td>47.785714</td>\n",
" <td>47.6216</td>\n",
" <td>-122.284940</td>\n",
" <td>5947.228571</td>\n",
" <td>6</td>\n",
" <td>Park</td>\n",
" <td>Monument / Landmark</td>\n",
" <td>Surf Spot</td>\n",
" <td>Beach</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Eye Doctor</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>44</th>\n",
" <td>Blue Ridge</td>\n",
" <td>42336</td>\n",
" <td>43.620000</td>\n",
" <td>47.7052</td>\n",
" <td>-122.376324</td>\n",
" <td>5369.420000</td>\n",
" <td>6</td>\n",
" <td>Wine Bar</td>\n",
" <td>Pool</td>\n",
" <td>Park</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Electronics Store</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" <td>Field</td>\n",
" </tr>\n",
" <tr>\n",
" <th>47</th>\n",
" <td>Roxhill</td>\n",
" <td>32584</td>\n",
" <td>38.538462</td>\n",
" <td>47.5273</td>\n",
" <td>-122.371006</td>\n",
" <td>7482.946154</td>\n",
" <td>6</td>\n",
" <td>Pool</td>\n",
" <td>Soccer Field</td>\n",
" <td>Intersection</td>\n",
" <td>Park</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Electronics Store</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" <td>Field</td>\n",
" </tr>\n",
" <tr>\n",
" <th>52</th>\n",
" <td>Hawthorne Hills</td>\n",
" <td>52864</td>\n",
" <td>42.310000</td>\n",
" <td>47.6722</td>\n",
" <td>-122.272527</td>\n",
" <td>6894.980000</td>\n",
" <td>6</td>\n",
" <td>Park</td>\n",
" <td>Bank</td>\n",
" <td>Auto Workshop</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Eye Doctor</td>\n",
" <td>Food Truck</td>\n",
" <td>Food Court</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>54</th>\n",
" <td>Leschi</td>\n",
" <td>47840</td>\n",
" <td>39.921429</td>\n",
" <td>47.5996</td>\n",
" <td>-122.290665</td>\n",
" <td>8942.235714</td>\n",
" <td>6</td>\n",
" <td>Park</td>\n",
" <td>Pizza Place</td>\n",
" <td>Playground</td>\n",
" <td>American Restaurant</td>\n",
" <td>Pet Store</td>\n",
" <td>Coffee Shop</td>\n",
" <td>Grocery Store</td>\n",
" <td>Fast Food Restaurant</td>\n",
" <td>Event Space</td>\n",
" <td>Eye Doctor</td>\n",
" </tr>\n",
" <tr>\n",
" <th>58</th>\n",
" <td>Green Lake</td>\n",
" <td>46646</td>\n",
" <td>34.765000</td>\n",
" <td>47.6802</td>\n",
" <td>-122.333870</td>\n",
" <td>9909.300000</td>\n",
" <td>6</td>\n",
" <td>Park</td>\n",
" <td>Beach</td>\n",
" <td>New American Restaurant</td>\n",
" <td>Trail</td>\n",
" <td>Theater</td>\n",
" <td>Lake</td>\n",
" <td>Bed &amp; Breakfast</td>\n",
" <td>Neighborhood</td>\n",
" <td>Pool</td>\n",
" <td>Playground</td>\n",
" </tr>\n",
" <tr>\n",
" <th>67</th>\n",
" <td>Olympic Manor</td>\n",
" <td>51299</td>\n",
" <td>45.012500</td>\n",
" <td>47.6961</td>\n",
" <td>-122.382182</td>\n",
" <td>6952.787500</td>\n",
" <td>6</td>\n",
" <td>Sandwich Place</td>\n",
" <td>Playground</td>\n",
" <td>Park</td>\n",
" <td>Baseball Field</td>\n",
" <td>Zoo Exhibit</td>\n",
" <td>Food &amp; Drink Shop</td>\n",
" <td>Food</td>\n",
" <td>Fondue Restaurant</td>\n",
" <td>Fish Market</td>\n",
" <td>Field</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" name pc_income median age_census latitude longitude \\\n",
"0 Pinehurst 33705 40.640000 47.7229 -122.319553 \n",
"3 Windermere 56478 42.383333 47.6701 -122.262675 \n",
"10 South Park 23577 32.366667 47.5288 -122.323015 \n",
"19 View Ridge 51864 44.509091 47.6834 -122.273935 \n",
"23 Fauntleroy 44606 45.366667 47.5232 -122.388978 \n",
"26 Arbor Heights 38305 44.683333 47.5079 -122.380849 \n",
"30 Mount Baker 37183 39.973333 47.5760 -122.286975 \n",
"35 North College Park 34197 35.000000 47.6990 -122.336766 \n",
"38 Denny-Blaine 74598 47.785714 47.6216 -122.284940 \n",
"44 Blue Ridge 42336 43.620000 47.7052 -122.376324 \n",
"47 Roxhill 32584 38.538462 47.5273 -122.371006 \n",
"52 Hawthorne Hills 52864 42.310000 47.6722 -122.272527 \n",
"54 Leschi 47840 39.921429 47.5996 -122.290665 \n",
"58 Green Lake 46646 34.765000 47.6802 -122.333870 \n",
"67 Olympic Manor 51299 45.012500 47.6961 -122.382182 \n",
"\n",
" popdensity Cluster Labels 1st Most Common Venue 2nd Most Common Venue \\\n",
"0 7337.190000 6 Park Moving Target \n",
"3 6346.766667 6 Park Pizza Place \n",
"10 3663.933333 6 Park Brewery \n",
"19 6056.290909 6 Park Zoo Exhibit \n",
"23 6106.541667 6 Park Pizza Place \n",
"26 5354.600000 6 BBQ Joint Park \n",
"30 7071.486667 6 Park Pizza Place \n",
"35 8823.460000 6 Food Court Concert Hall \n",
"38 5947.228571 6 Park Monument / Landmark \n",
"44 5369.420000 6 Wine Bar Pool \n",
"47 7482.946154 6 Pool Soccer Field \n",
"52 6894.980000 6 Park Bank \n",
"54 8942.235714 6 Park Pizza Place \n",
"58 9909.300000 6 Park Beach \n",
"67 6952.787500 6 Sandwich Place Playground \n",
"\n",
" 3rd Most Common Venue 4th Most Common Venue 5th Most Common Venue \\\n",
"0 Garden Coffee Shop Dog Run \n",
"3 Zoo Exhibit Ethiopian Restaurant Food Court \n",
"10 Library Zoo Exhibit Event Space \n",
"19 Event Space Food Truck Food Court \n",
"23 Bakery Dance Studio Pier \n",
"26 Scenic Lookout Zoo Exhibit Food Court \n",
"30 Harbor / Marina Café Scenic Lookout \n",
"35 Community College Park Zoo Exhibit \n",
"38 Surf Spot Beach Zoo Exhibit \n",
"44 Park Zoo Exhibit Electronics Store \n",
"47 Intersection Park Zoo Exhibit \n",
"52 Auto Workshop Zoo Exhibit Eye Doctor \n",
"54 Playground American Restaurant Pet Store \n",
"58 New American Restaurant Trail Theater \n",
"67 Park Baseball Field Zoo Exhibit \n",
"\n",
" 6th Most Common Venue 7th Most Common Venue 8th Most Common Venue \\\n",
"0 Zoo Exhibit Event Space Food & Drink Shop \n",
"3 Food & Drink Shop Food Fondue Restaurant \n",
"10 Food Court Food & Drink Shop Food \n",
"19 Food & Drink Shop Food Fondue Restaurant \n",
"23 Market Pilates Studio American Restaurant \n",
"26 Food & Drink Shop Food Fondue Restaurant \n",
"30 Food Convenience Store Pet Store \n",
"35 Event Space Food & Drink Shop Food \n",
"38 Eye Doctor Food Court Food & Drink Shop \n",
"44 Food & Drink Shop Food Fondue Restaurant \n",
"47 Electronics Store Food Fondue Restaurant \n",
"52 Food Truck Food Court Food & Drink Shop \n",
"54 Coffee Shop Grocery Store Fast Food Restaurant \n",
"58 Lake Bed & Breakfast Neighborhood \n",
"67 Food & Drink Shop Food Fondue Restaurant \n",
"\n",
" 9th Most Common Venue 10th Most Common Venue \n",
"0 Food Fondue Restaurant \n",
"3 Fish Market Field \n",
"10 Fondue Restaurant Fish Market \n",
"19 Fish Market Field \n",
"23 Gymnastics Gym Dumpling Restaurant \n",
"26 Fish Market Field \n",
"30 Deli / Bodega Fondue Restaurant \n",
"35 Fondue Restaurant Fish Market \n",
"38 Food Fondue Restaurant \n",
"44 Fish Market Field \n",
"47 Fish Market Field \n",
"52 Food Fondue Restaurant \n",
"54 Event Space Eye Doctor \n",
"58 Pool Playground \n",
"67 Fish Market Field "
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"seattle_merged.loc[seattle_merged['Cluster Labels'] == 6, seattle_merged.columns[[1] + list(range(2, seattle_merged.shape[1]))]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Discussion"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As mentioned previously, accurate data on the commercial rent in each area, as well as, the availability of space would be important to a final decision. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"My personal choice would be to dive further into potential locations in Cluster 7. Looking at some of the top venues in these neighborhoods gives the impression that these areas have a healthy & active atmosphere. It could be a place where a physical therapy clinic makes sense in relation to the other activities that are going on around it. It ranks lower on popdensity, but has a slightly higher median age (positive factor given the potential customer demographic). "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Conclusion"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Cluster 7 would be my recommendation, as far as neighborhoods go, to investigate real estate options for potential locations. \n",
"\n",
"There is not enough data on other important factors (i.e commercial real estate available, cost of real estate, market size) to make a definitive move. However, this research has focused the attention to a few specific areas that would complement the goals of small physical therapy clinic, and has promising demographic information. "
]
}
],
"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