About the Data
The data is from
Kenya
National Bureau of Statistics Data Tables.
It is about the Population Distribution of Households by County
according to the 2019 Kenya Population and Housing Census.
It contains the following fields;
-
County
-
Total_Population
-
Male_Population
-
Female_Population
-
Intersex_Population
-
Total_Household
-
Conventional_Household
-
Group_Quarters
-
Land_Area_SqKm
-
Density_Persons_per_SqKm
Steps Taken
-
Importing Necessary R Packages
-
Loading Data to R
-
Understanding the Data
-
Data Cleaning and Preparation - Missing Values
-
Exploratory Data Analysis - Visualizations
-
Findings
Importing necessary packages
library(readxl) # To read excel data into R
library(tidyverse) # To tidy data
library(plotly) # To create interactive visualizations
library(knitr) # For report generation
library(kableExtra) # To display table
library(dplyr) # For data analysis
Load and Preview the Data
# Load data to a dataFrame
pop_data <- read_excel("C:/Users/KNBS/Documents/PROJECTS/Education Loans R Shiny/Population-households-density-by-county.xlsx", skip = 4)
# Preview the Data
head(pop_data)
Understanding the structure of the Data
str(pop_data)
tibble [48 × 10] (S3: tbl_df/tbl/data.frame)
$ County : chr [1:48] "MOMBASA" "KWALE" "KILIFI" "TANA RIVER" ...
$ Total_Population : num [1:48] 1208333 866820 1453787 315943 143920 ...
$ Male_Population : num [1:48] 610257 425121 704089 158550 76103 ...
$ Female_Population : num [1:48] 598046 441681 749673 157391 67813 ...
$ Intersex_Population : num [1:48] 30 18 25 2 4 7 34 49 37 18 ...
$ Total_Household : num [1:48] 378422 173176 298472 68242 37963 ...
$ Conventional_Household : num [1:48] 376295 172802 297990 66984 34231 ...
$ Group_Quarters : num [1:48] 2127 374 482 1258 3732 ...
$ Land_Area_SqKm : num [1:48] 220 8254 12553 37904 6283 ...
$ Density_Persons_per_SqKm: num [1:48] 5495.01 105.02 115.81 8.34 22.91 ...
OBSERVATIONS:
-
There are 10 columns as listed, all in the correct Data Types.
-
The data has 48 records.
Missing Values
Checking for rows with any null/Missing Values and viewing them
# Check for NAs in the entire pop_data data frame
na_rows <- pop_data[apply(is.na(pop_data), 1, any), ]
# View the rows with NAs in any column
print(na_rows)
OBSERVATION: Only one of the rows has missing
values. It is the last row that isn’t related to the data, so will drop
it.
pop_data <- na.omit(pop_data)
Previewing nulls again to confirm removal of the row
# Check for nulls in the entire pop_data data frame
na_rows <- pop_data[apply(is.na(pop_data), 1, any), ]
# View the rows with nulls in any column
print(na_rows)
OBSERVATION: - There’s no missing values left.
Getting Summary statistics of the data fields
# Summary statistics of the Data's columns
summary(pop_data)
County Total_Population Male_Population Female_Population Intersex_Population Total_Household Conventional_Household Group_Quarters
Length:47 Min. : 143920 Min. : 76103 Min. : 67813 Min. : 2.00 Min. : 37963 Min. : 34231 Min. : 77.0
Class :character 1st Qu.: 609505 1st Qu.: 303110 1st Qu.: 311291 1st Qu.: 18.00 1st Qu.: 141956 1st Qu.: 140409 1st Qu.: 610.5
Mode :character Median : 893681 Median : 450741 Median : 448868 Median : 25.00 Median : 204188 Median : 203576 Median : 1258.0
Mean :1012006 Mean : 501023 Mean : 510951 Mean : 32.43 Mean : 258381 Mean : 256234 Mean : 2146.7
3rd Qu.:1156724 3rd Qu.: 569992 3rd Qu.: 589759 3rd Qu.: 34.00 3rd Qu.: 302844 3rd Qu.: 299550 3rd Qu.: 2681.0
Max. :4397073 Max. :2192452 Max. :2204376 Max. :245.00 Max. :1506888 Max. :1494676 Max. :17809.0
Land_Area_SqKm Density_Persons_per_SqKm
Min. : 219.9 Min. : 6.481
1st Qu.: 2526.2 1st Qu.: 52.826
Median : 3325.0 Median : 220.377
Mean :12359.5 Mean : 509.163
3rd Qu.:14852.6 3rd Qu.: 415.876
Max. :70944.3 Max. :6246.995
Adding an extra column called Regions for better analysis
# Create 'Region' column based on 'County'
pop_data$Region <- ifelse(pop_data$County %in% c("MOMBASA", "KWALE", "KILIFI", "TANA RIVER", "LAMU", "TAITA/TAVETA"), "Coast",
ifelse(pop_data$County %in% "NAIROBI CITY", "Nairobi",
ifelse(pop_data$County %in% c("KIAMBU", "MURANG'A", "NYERI", "NYANDARUA", "KIRINYAGA"), "Central",
ifelse(pop_data$County %in% c("MANDERA", "WAJIR", "GARISSA", "MARSABIT"), "North Eastern",
ifelse(pop_data$County %in% c("TURKANA", "UASIN GISHU", "ELGEYO/MARAKWET", "KERICHO", "WEST POKOT",
"SAMBURU", "TRANS NZOIA", "BARINGO", "NANDI", "LAIKIPIA", "NAKURU",
"NAROK", "KAJIADO"), "Rift Valley",
ifelse(pop_data$County %in% c("KAKAMEGA", "VIHIGA", "BUNGOMA", "BUSIA"), "Western",
ifelse(pop_data$County %in% c("KISII", "NYAMIRA", "HOMA BAY", "MIGORI", "KISUMU", "SIAYA"), "Nyanza",
ifelse(pop_data$County %in% c("THARAKA-NITHI", "EMBU", "KITUI", "MAKUENI", "MERU", "ISIOLO", "MACHAKOS"), "Eastern",
ifelse(pop_data$County %in% c("KAJIADO", "NAROK", "KERICHO", "BOMET", "NYERI"), "Rift Valley",
"Other")))))))))
# Reorder columns with 'Region' as the first column
pop_data <- pop_data %>%
select(Region, everything())
# Check the resulting data frame
head(pop_data)
# Check unique values in the 'Region' column
unique(pop_data$Region)
[1] "Coast" "North Eastern" "Eastern" "Central" "Rift Valley" "Western" "Nyanza" "Nairobi"
OBSERVATION
All records are represented in the 8 regions listed here
EXPLORATORY DATA ANALYSIS
VISUALIZATIONS
Total Population by Region
# Bar Plot of Total Population by Region
plot_ly(data = pop_data,
x = ~Region,
y = ~Total_Population,
type = 'bar',
name = 'Total Population',
marker = list(color = 'blue')) %>%
layout(title = 'Total Population by Region',
xaxis = list(title = 'Region'),
yaxis = list(title = 'Total Population'))
OBSERVATIONS:
-
Rift valley region has the Highest Population.
-
North Eastern region has the lowest Population.
Top 10 Highest County Populations
#Barplot of Top 10 Highest County Populations
# Order the data by Total_Population in descending order
Total_Population_desc <- pop_data[order(pop_data$Total_Population, decreasing = TRUE), ]
# Select the top N counties (e.g., top 10)
top_counties <- head(Total_Population_desc, n = 10)
plot_ly(data = top_counties,
x = ~reorder(County, -Total_Population),
y = ~Total_Population,
type = 'bar',
name = 'Total Population',
marker = list(color = 'blue')) %>%
layout(title = 'Top Highest County Populations',
xaxis = list(title = 'County'),
yaxis = list(title = 'Total Population'))
OBSERVATIONS=:
-
Nairobi County has the Highest Population compared to other counties,
followed by Kiambu then Nakuru.
Bottom 10 (Low) County Populations
# Barplot of Bottom 10 County Populations
# Order the data by Total_Population in ascending order
pop_data_sorted <- pop_data[order(pop_data$Total_Population), ]
# Select the top N counties (e.g., bottom 10)
bottom_counties <- head(pop_data_sorted, n = 10)
# Create the plot with ordered bars in ascending order
plot_ly(data = bottom_counties,
x = ~reorder(County, Total_Population),
y = ~Total_Population,
type = 'bar',
name = 'Total Population',
marker = list(color = 'blue')) %>%
layout(title = 'Bottom Least County Populations',
xaxis = list(title = 'County'),
yaxis = list(title = 'Total Population'))
OBSERVATION:
-
Lamu County has the Lowest Population compared to other counties,
followed by Isiolo then Samburu from the bottom.
Population by Gender
# Pie Chart of Male, Female and Intersex Population percentages
pop_data %>%
plot_ly(labels = ~c("Male", "Female", "Intersex"),
values = ~c(sum(pop_data$Male_Population), sum(pop_data$Female_Population), sum(pop_data$Intersex_Population)),
type = 'pie',
marker = list(colors = c("blue", "pink", "red"))) %>%
layout(title = "Population Distribution by Gender")
Total Households by Region
# Bar Plot of Total Population by Region
plot_ly(data = pop_data,
x = ~Region,
y = ~Total_Household,
type = 'bar',
name = 'Total Households by Region',
marker = list(color = 'blue')) %>%
layout(title = 'Total Households by Region',
xaxis = list(title = 'Region'),
yaxis = list(title = 'Total Households for Region'))
OBSERVATION:
-
Rift Valley has the Highest number of Households while North Eastern has
the least.
Comparison of Group Quarters and Conventional Household
# Pie Chart of Male, Female and Intersex Population percentages
pop_data %>%
plot_ly(labels = ~c("Conventional_Household", "Group_Quarters"),
values = ~c(sum(pop_data$Conventional_Household), sum(pop_data$Group_Quarters)),
type = 'pie',
marker = list(colors = c("blue", "red"))) %>%
layout(title = "Comparison of Group Quarters and Conventional Household")
OBSERVATION:
-
Conventional households are more common than Group Quarters.
Comparison of Group Quarters and Conventional Household by
Region
# Grouped Bar plot showing Comparison of Group Quarters and Conventional Household by Region
plot_ly(data = pop_data,
x = ~Region,
y = ~Group_Quarters,
type = 'bar',
name = 'Group Quarters',
marker = list(color = 'red')) %>%
add_trace(y = ~Conventional_Household,
name = 'Conventional Household',
marker = list(color = 'blue')) %>%
layout(title = 'Comparison of Group Quarters and Conventional Household by Region',
xaxis = list(title = 'Region'),
yaxis = list(title = 'Count'),
barmode = 'group')
OBSERVATIONS:
-
All Kenyan Regions have both Conventional Households and Group Quarters
-
Conventional Households are more common that Group Quarters
-
Rift Valley has the Highest Number of both Conventional Households and
Group Quarters
Household vs. Land Area
# Scatter Plot of Household vs. Land Area
plot_ly(
data = pop_data,
x = ~Total_Household,
y = ~Land_Area_SqKm,
color = ~Region, # Specify the variable for coloring
type = 'scatter',
mode = 'markers'
) %>%
layout(
title = 'Household vs. Land Area by Region',
xaxis = list(title = 'Total Household'),
yaxis = list(title = 'Land Area (Sq Km)')
)
OBSERVATION:
-
Most parts of Kenya have low Land area and low Household numbers.
Population Density Distribution
# Histogram of Population Density
# Calculate density values
density_values <- density(pop_data$Density_Persons_per_SqKm)
# Create the combined plot
combined_plot <- plot_ly() %>%
add_histogram(x = ~pop_data$Density_Persons_per_SqKm, nbinsx = 20, histnorm = 'probability density', marker = list(color = 'blue', line = list(color = 'black', width = 1))) %>%
add_lines(x = density_values$x, y = density_values$y, type = 'scatter', mode = 'lines', line = list(color = 'red', width = 2)) %>%
layout(title = 'Population Density Histogram with KDE',
xaxis = list(title = 'Density (Persons per Sq Km)'),
yaxis = list(title = 'Probability Density'))
# Display the combined plot
combined_plot
OBSERVATION:
-
Most Kenyan areas have relatively low population density with a few
exceptions where population density is significantly high.
Narrowing down to comparison in different regions will help gather
more insights.
Population Density by Region
# Box Plot
plot_ly(data = pop_data, x = ~Region, y = ~Density_Persons_per_SqKm, type = "box") %>%
layout(title = "Population Density by Region",
xaxis = list(title = "Region"),
yaxis = list(title = "Density (Persons per Sq Km)"))
OBSERVATION:
-
Most regions have relatively low density ranging from 0 to slightly
above 1000000 persons per square Km but the entire Nairobi Region has
very high density. Coast Region has an outlier that has very high
population density of 5495008 persons per Sq Km.
-
In most regions, the median is closer to the lower values. This means
that most values are in the lower range. This emphasizes the low
population density in most parts of Kenya.
A table showing density for each county in coast region will help
understand the outlier in the region better.
# filter coast data only
coast_data <- pop_data[pop_data$Region == "Coast", ]
# Assuming your data frame is named 'pop_data'
coast_data <- pop_data[pop_data$Region == "Coast", ]
# Create a table of density values
coast_density_table <- coast_data %>%
select(County, Density_Persons_per_SqKm) %>%
kable("html", caption = "Density Values for Counties in the Coast Region") %>%
kable_styling()
# Display the table
coast_density_table
Density Values for Counties in the Coast Region
| County |
Density_Persons_per_SqKm |
| MOMBASA |
5495.00838 |
| KWALE |
105.02256 |
| KILIFI |
115.80947 |
| TANA RIVER |
8.33543 |
| LAMU |
22.90616 |
| TAITA/TAVETA |
19.86188 |
OBSERVATION:
-
From the coast Region, Mombasa is the outlier with very high density
compared to the other areas.
FINDINGS
-
Rift valley region has the Highest Population and highest number of
Households.
-
North Eastern region has the lowest Population and lowest number of
Households.
-
Most Kenyans identify as male or female. With slightly more females than
males. A very small percentage(0.0032%) identify as intersex.
-
Nairobi County has the Highest Population compared to other counties,
followed by Kiambu then Nakuru.
-
Lamu County has the Lowest Population compared to other counties,
followed by Isiolo then Samburu from the bottom.
-
All Kenyan Regions have both Conventional Households and Group Quarters
but Conventional Households are more common that Group Quarters.
-
Most Kenyan counties have relatively low Population Density with an
exception of Mombasa and Nairobi which have very High Population
Density(Persons per Square Kilometer) compared to the other counties.
LS0tDQp0aXRsZTogIktlbnlhbiBQb3B1bGF0aW9uIERpc3RyaWJ1dGlvbiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMjIyBBYm91dCB0aGUgRGF0YQ0KVGhlIGRhdGEgaXMgZnJvbSBbS2VueWEgTmF0aW9uYWwgQnVyZWF1IG9mIFN0YXRpc3RpY3MgRGF0YSBUYWJsZXNdKGh0dHBzOi8vd3d3LmtuYnMub3Iua2UvZG93bmxvYWQvcG9wdWxhdGlvbi1ob3VzZWhvbGRzLWRlbnNpdHktYnktY291bnR5LykuDQo8cD5JdCBpcyBhYm91dCB0aGUgUG9wdWxhdGlvbiBEaXN0cmlidXRpb24gb2YgSG91c2Vob2xkcyBieSBDb3VudHkgYWNjb3JkaW5nIHRvIHRoZSAyMDE5IEtlbnlhIFBvcHVsYXRpb24gYW5kIEhvdXNpbmcgQ2Vuc3VzLjwvcD4NCkl0IGNvbnRhaW5zIHRoZSBmb2xsb3dpbmcgZmllbGRzOw0KPHVsPg0KICA8bGk+IENvdW50eQ0KICA8bGk+IFRvdGFsX1BvcHVsYXRpb24NCiAgPGxpPiBNYWxlX1BvcHVsYXRpb24NCiAgPGxpPiBGZW1hbGVfUG9wdWxhdGlvbg0KICA8bGk+IEludGVyc2V4X1BvcHVsYXRpb24NCiAgPGxpPiBUb3RhbF9Ib3VzZWhvbGQNCiAgPGxpPiBDb252ZW50aW9uYWxfSG91c2Vob2xkDQogIDxsaT4gR3JvdXBfUXVhcnRlcnMNCiAgPGxpPiBMYW5kX0FyZWFfU3FLbQ0KICA8bGk+IERlbnNpdHlfUGVyc29uc19wZXJfU3FLbQ0KPC91bD4NCg0KIyMjIFN0ZXBzIFRha2VuDQo8b2w+DQogIDxsaT4gSW1wb3J0aW5nIE5lY2Vzc2FyeSBSIFBhY2thZ2VzDQogIDxsaT4gTG9hZGluZyBEYXRhIHRvIFINCiAgPGxpPiBVbmRlcnN0YW5kaW5nIHRoZSBEYXRhDQogIDxsaT4gRGF0YSBDbGVhbmluZyBhbmQgUHJlcGFyYXRpb24gLSBNaXNzaW5nIFZhbHVlcw0KICA8bGk+IEV4cGxvcmF0b3J5IERhdGEgQW5hbHlzaXMgLSBWaXN1YWxpemF0aW9ucw0KICA8bGk+IEZpbmRpbmdzDQo8L29sPg0KDQojIyMgSW1wb3J0aW5nIG5lY2Vzc2FyeSBwYWNrYWdlcw0KYGBge3J9DQpsaWJyYXJ5KHJlYWR4bCkgIyBUbyByZWFkIGV4Y2VsIGRhdGEgaW50byBSDQpsaWJyYXJ5KHRpZHl2ZXJzZSkgIyBUbyB0aWR5IGRhdGENCmxpYnJhcnkocGxvdGx5KSAjIFRvIGNyZWF0ZSBpbnRlcmFjdGl2ZSB2aXN1YWxpemF0aW9ucw0KbGlicmFyeShrbml0cikgIyBGb3IgcmVwb3J0IGdlbmVyYXRpb24NCmxpYnJhcnkoa2FibGVFeHRyYSkgIyBUbyBkaXNwbGF5IHRhYmxlDQpsaWJyYXJ5KGRwbHlyKSAjIEZvciBkYXRhIGFuYWx5c2lzDQpgYGANCg0KIyMjIExvYWQgYW5kIFByZXZpZXcgdGhlIERhdGENCmBgYHtyfQ0KIyBMb2FkIGRhdGEgdG8gYSBkYXRhRnJhbWUNCnBvcF9kYXRhIDwtIHJlYWRfZXhjZWwoIkM6L1VzZXJzL0tOQlMvRG9jdW1lbnRzL1BST0pFQ1RTL0VkdWNhdGlvbiBMb2FucyBSIFNoaW55L1BvcHVsYXRpb24taG91c2Vob2xkcy1kZW5zaXR5LWJ5LWNvdW50eS54bHN4Iiwgc2tpcCA9IDQpDQoNCiMgUHJldmlldyB0aGUgRGF0YQ0KaGVhZChwb3BfZGF0YSkNCmBgYA0KDQojIyMgRm9ybWF0dGluZyBDb2x1bW5zDQpSZW5hbWluZyBjb2x1bW4gSGVhZGVycw0KYGBge3J9DQpjb2xuYW1lcyhwb3BfZGF0YSkgPC0gYygiQ291bnR5IiwgIlRvdGFsX1BvcHVsYXRpb24iLCAiTWFsZV9Qb3B1bGF0aW9uIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJGZW1hbGVfUG9wdWxhdGlvbiIsICJJbnRlcnNleF9Qb3B1bGF0aW9uIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJUb3RhbF9Ib3VzZWhvbGQiLCAiQ29udmVudGlvbmFsX0hvdXNlaG9sZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAiR3JvdXBfUXVhcnRlcnMiLCAiTGFuZF9BcmVhX1NxS20iLA0KICAgICAgICAgICAgICAgICAgICAgICAgIkRlbnNpdHlfUGVyc29uc19wZXJfU3FLbSIpDQojIFByZXZpZXdpbmcgdGhlIHJlc3VsdA0KaGVhZChwb3BfZGF0YSkNCmBgYA0KIyMjIFVuZGVyc3RhbmRpbmcgdGhlIHN0cnVjdHVyZSBvZiB0aGUgRGF0YQ0KYGBge3J9DQpzdHIocG9wX2RhdGEpDQpgYGANCioqT0JTRVJWQVRJT05TOioqDQo8dWw+DQo8bGk+VGhlcmUgYXJlIDEwIGNvbHVtbnMgYXMgbGlzdGVkLCBhbGwgaW4gdGhlIGNvcnJlY3QgRGF0YSBUeXBlcy4NCjxsaT5UaGUgZGF0YSBoYXMgNDggcmVjb3Jkcy4NCjx1bD4NCg0KIyMjIE1pc3NpbmcgVmFsdWVzDQpDaGVja2luZyBmb3Igcm93cyB3aXRoIGFueSBudWxsL01pc3NpbmcgVmFsdWVzIGFuZCB2aWV3aW5nIHRoZW0NCmBgYHtyfQ0KIyBDaGVjayBmb3IgTkFzIGluIHRoZSBlbnRpcmUgcG9wX2RhdGEgZGF0YSBmcmFtZQ0KbmFfcm93cyA8LSBwb3BfZGF0YVthcHBseShpcy5uYShwb3BfZGF0YSksIDEsIGFueSksIF0NCg0KIyBWaWV3IHRoZSByb3dzIHdpdGggTkFzIGluIGFueSBjb2x1bW4NCnByaW50KG5hX3Jvd3MpDQpgYGANCioqT0JTRVJWQVRJT046KioNCk9ubHkgb25lIG9mIHRoZSByb3dzIGhhcyBtaXNzaW5nIHZhbHVlcy4gSXQgaXMgdGhlIGxhc3Qgcm93IHRoYXQgaXNuJ3QgcmVsYXRlZCB0byB0aGUgZGF0YSwgc28gd2lsbCBkcm9wIGl0Lg0KYGBge3J9DQpwb3BfZGF0YSA8LSBuYS5vbWl0KHBvcF9kYXRhKQ0KYGBgDQoNClByZXZpZXdpbmcgbnVsbHMgYWdhaW4gdG8gY29uZmlybSByZW1vdmFsIG9mIHRoZSByb3cNCmBgYHtyfQ0KIyBDaGVjayBmb3IgbnVsbHMgaW4gdGhlIGVudGlyZSBwb3BfZGF0YSBkYXRhIGZyYW1lDQpuYV9yb3dzIDwtIHBvcF9kYXRhW2FwcGx5KGlzLm5hKHBvcF9kYXRhKSwgMSwgYW55KSwgXQ0KDQojIFZpZXcgdGhlIHJvd3Mgd2l0aCBudWxscyBpbiBhbnkgY29sdW1uDQpwcmludChuYV9yb3dzKQ0KYGBgDQoqKk9CU0VSVkFUSU9OOioqDQotIFRoZXJlJ3Mgbm8gbWlzc2luZyB2YWx1ZXMgbGVmdC4NCg0KIyMjIEdldHRpbmcgU3VtbWFyeSBzdGF0aXN0aWNzIG9mIHRoZSBkYXRhIGZpZWxkcw0KYGBge3J9DQojIFN1bW1hcnkgc3RhdGlzdGljcyBvZiB0aGUgRGF0YSdzIGNvbHVtbnMNCnN1bW1hcnkocG9wX2RhdGEpDQpgYGANCg0KIyMjIEFkZGluZyBhbiBleHRyYSBjb2x1bW4gY2FsbGVkIFJlZ2lvbnMgZm9yIGJldHRlciBhbmFseXNpcw0KYGBge3J9DQojIENyZWF0ZSAnUmVnaW9uJyBjb2x1bW4gYmFzZWQgb24gJ0NvdW50eScNCnBvcF9kYXRhJFJlZ2lvbiA8LSBpZmVsc2UocG9wX2RhdGEkQ291bnR5ICVpbiUgYygiTU9NQkFTQSIsICJLV0FMRSIsICJLSUxJRkkiLCAiVEFOQSBSSVZFUiIsICJMQU1VIiwgIlRBSVRBL1RBVkVUQSIpLCAiQ29hc3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocG9wX2RhdGEkQ291bnR5ICVpbiUgIk5BSVJPQkkgQ0lUWSIsICJOYWlyb2JpIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHBvcF9kYXRhJENvdW50eSAlaW4lIGMoIktJQU1CVSIsICJNVVJBTkcnQSIsICJOWUVSSSIsICJOWUFOREFSVUEiLCAiS0lSSU5ZQUdBIiksICJDZW50cmFsIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShwb3BfZGF0YSRDb3VudHkgJWluJSBjKCJNQU5ERVJBIiwgIldBSklSIiwgIkdBUklTU0EiLCAiTUFSU0FCSVQiKSwgIk5vcnRoIEVhc3Rlcm4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocG9wX2RhdGEkQ291bnR5ICVpbiUgYygiVFVSS0FOQSIsICJVQVNJTiBHSVNIVSIsICJFTEdFWU8vTUFSQUtXRVQiLCAiS0VSSUNITyIsICJXRVNUIFBPS09UIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNBTUJVUlUiLCAiVFJBTlMgTlpPSUEiLCAiQkFSSU5HTyIsICJOQU5ESSIsICJMQUlLSVBJQSIsICJOQUtVUlUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTkFST0siLCAiS0FKSUFETyIpLCAiUmlmdCBWYWxsZXkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocG9wX2RhdGEkQ291bnR5ICVpbiUgYygiS0FLQU1FR0EiLCAiVklISUdBIiwgIkJVTkdPTUEiLCAiQlVTSUEiKSwgIldlc3Rlcm4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocG9wX2RhdGEkQ291bnR5ICVpbiUgYygiS0lTSUkiLCAiTllBTUlSQSIsICJIT01BIEJBWSIsICJNSUdPUkkiLCAiS0lTVU1VIiwgIlNJQVlBIiksICJOeWFuemEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocG9wX2RhdGEkQ291bnR5ICVpbiUgYygiVEhBUkFLQS1OSVRISSIsICJFTUJVIiwgIktJVFVJIiwgIk1BS1VFTkkiLCAiTUVSVSIsICJJU0lPTE8iLCAiTUFDSEFLT1MiKSwgIkVhc3Rlcm4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UocG9wX2RhdGEkQ291bnR5ICVpbiUgYygiS0FKSUFETyIsICJOQVJPSyIsICJLRVJJQ0hPIiwgIkJPTUVUIiwgIk5ZRVJJIiksICJSaWZ0IFZhbGxleSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJPdGhlciIpKSkpKSkpKSkNCiMgUmVvcmRlciBjb2x1bW5zIHdpdGggJ1JlZ2lvbicgYXMgdGhlIGZpcnN0IGNvbHVtbg0KcG9wX2RhdGEgPC0gcG9wX2RhdGEgJT4lDQogIHNlbGVjdChSZWdpb24sIGV2ZXJ5dGhpbmcoKSkNCg0KIyBDaGVjayB0aGUgcmVzdWx0aW5nIGRhdGEgZnJhbWUNCmhlYWQocG9wX2RhdGEpDQpgYGANCg0KYGBge3J9DQojIENoZWNrIHVuaXF1ZSB2YWx1ZXMgaW4gdGhlICdSZWdpb24nIGNvbHVtbg0KdW5pcXVlKHBvcF9kYXRhJFJlZ2lvbikNCmBgYA0KKipPQlNFUlZBVElPTioqDQo8cD5BbGwgcmVjb3JkcyBhcmUgcmVwcmVzZW50ZWQgaW4gdGhlIDggcmVnaW9ucyBsaXN0ZWQgaGVyZTwvcD4NCg0KIyBFWFBMT1JBVE9SWSBEQVRBIEFOQUxZU0lTDQpWSVNVQUxJWkFUSU9OUw0KDQojIyMgVG90YWwgUG9wdWxhdGlvbiBieSBSZWdpb24NCmBgYHtyfQ0KIyBCYXIgUGxvdCBvZiBUb3RhbCBQb3B1bGF0aW9uIGJ5IFJlZ2lvbg0KcGxvdF9seShkYXRhID0gcG9wX2RhdGEsDQogICAgICAgIHggPSB+UmVnaW9uLA0KICAgICAgICB5ID0gflRvdGFsX1BvcHVsYXRpb24sDQogICAgICAgIHR5cGUgPSAnYmFyJywNCiAgICAgICAgbmFtZSA9ICdUb3RhbCBQb3B1bGF0aW9uJywNCiAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICdibHVlJykpICU+JQ0KICANCiAgbGF5b3V0KHRpdGxlID0gJ1RvdGFsIFBvcHVsYXRpb24gYnkgUmVnaW9uJywNCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICdSZWdpb24nKSwNCiAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICdUb3RhbCBQb3B1bGF0aW9uJykpDQpgYGANCioqT0JTRVJWQVRJT05TOioqDQo8dWw+DQo8bGk+IFJpZnQgdmFsbGV5IHJlZ2lvbiBoYXMgdGhlIEhpZ2hlc3QgUG9wdWxhdGlvbi4NCjxsaT4gTm9ydGggRWFzdGVybiByZWdpb24gaGFzIHRoZSBsb3dlc3QgUG9wdWxhdGlvbi4NCjwvdWw+DQoNCiMjIyBUb3AgMTAgSGlnaGVzdCBDb3VudHkgUG9wdWxhdGlvbnMNCmBgYHtyfQ0KI0JhcnBsb3Qgb2YgVG9wIDEwIEhpZ2hlc3QgQ291bnR5IFBvcHVsYXRpb25zDQoNCiMgT3JkZXIgdGhlIGRhdGEgYnkgVG90YWxfUG9wdWxhdGlvbiBpbiBkZXNjZW5kaW5nIG9yZGVyDQpUb3RhbF9Qb3B1bGF0aW9uX2Rlc2MgPC0gcG9wX2RhdGFbb3JkZXIocG9wX2RhdGEkVG90YWxfUG9wdWxhdGlvbiwgZGVjcmVhc2luZyA9IFRSVUUpLCBdDQoNCiMgU2VsZWN0IHRoZSB0b3AgTiBjb3VudGllcyAoZS5nLiwgdG9wIDEwKQ0KdG9wX2NvdW50aWVzIDwtIGhlYWQoVG90YWxfUG9wdWxhdGlvbl9kZXNjLCBuID0gMTApDQoNCnBsb3RfbHkoZGF0YSA9IHRvcF9jb3VudGllcywNCiAgICAgICAgeCA9IH5yZW9yZGVyKENvdW50eSwgLVRvdGFsX1BvcHVsYXRpb24pLA0KICAgICAgICB5ID0gflRvdGFsX1BvcHVsYXRpb24sDQogICAgICAgIHR5cGUgPSAnYmFyJywNCiAgICAgICAgbmFtZSA9ICdUb3RhbCBQb3B1bGF0aW9uJywNCiAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICdibHVlJykpICU+JQ0KICAgIGxheW91dCh0aXRsZSA9ICdUb3AgSGlnaGVzdCBDb3VudHkgUG9wdWxhdGlvbnMnLA0KICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0NvdW50eScpLA0KICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gJ1RvdGFsIFBvcHVsYXRpb24nKSkNCmBgYA0KKipPQlNFUlZBVElPTlM9OioqDQo8dWw+DQo8bGk+IE5haXJvYmkgQ291bnR5IGhhcyB0aGUgSGlnaGVzdCBQb3B1bGF0aW9uIGNvbXBhcmVkIHRvIG90aGVyIGNvdW50aWVzLCBmb2xsb3dlZCBieSBLaWFtYnUgdGhlbiBOYWt1cnUuDQo8L3VsPg0KDQojIyMgQm90dG9tIDEwIChMb3cpIENvdW50eSBQb3B1bGF0aW9ucw0KYGBge3J9DQojIEJhcnBsb3Qgb2YgQm90dG9tIDEwIENvdW50eSBQb3B1bGF0aW9ucw0KDQojIE9yZGVyIHRoZSBkYXRhIGJ5IFRvdGFsX1BvcHVsYXRpb24gaW4gYXNjZW5kaW5nIG9yZGVyDQpwb3BfZGF0YV9zb3J0ZWQgPC0gcG9wX2RhdGFbb3JkZXIocG9wX2RhdGEkVG90YWxfUG9wdWxhdGlvbiksIF0NCg0KIyBTZWxlY3QgdGhlIHRvcCBOIGNvdW50aWVzIChlLmcuLCBib3R0b20gMTApDQpib3R0b21fY291bnRpZXMgPC0gaGVhZChwb3BfZGF0YV9zb3J0ZWQsIG4gPSAxMCkNCg0KIyBDcmVhdGUgdGhlIHBsb3Qgd2l0aCBvcmRlcmVkIGJhcnMgaW4gYXNjZW5kaW5nIG9yZGVyDQpwbG90X2x5KGRhdGEgPSBib3R0b21fY291bnRpZXMsDQogICAgICAgIHggPSB+cmVvcmRlcihDb3VudHksIFRvdGFsX1BvcHVsYXRpb24pLA0KICAgICAgICB5ID0gflRvdGFsX1BvcHVsYXRpb24sDQogICAgICAgIHR5cGUgPSAnYmFyJywNCiAgICAgICAgbmFtZSA9ICdUb3RhbCBQb3B1bGF0aW9uJywNCiAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICdibHVlJykpICU+JQ0KICANCiAgbGF5b3V0KHRpdGxlID0gJ0JvdHRvbSBMZWFzdCBDb3VudHkgUG9wdWxhdGlvbnMnLA0KICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0NvdW50eScpLA0KICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gJ1RvdGFsIFBvcHVsYXRpb24nKSkNCmBgYA0KKipPQlNFUlZBVElPTjoqKg0KPHVsPg0KPGxpPiBMYW11IENvdW50eSBoYXMgdGhlIExvd2VzdCBQb3B1bGF0aW9uIGNvbXBhcmVkIHRvIG90aGVyIGNvdW50aWVzLCBmb2xsb3dlZCBieSBJc2lvbG8gdGhlbiBTYW1idXJ1IGZyb20gdGhlIGJvdHRvbS4NCjwvdWw+DQoNCiMjIyBQb3B1bGF0aW9uIGJ5IEdlbmRlcg0KYGBge3J9DQojIFBpZSBDaGFydCBvZiBNYWxlLCBGZW1hbGUgYW5kIEludGVyc2V4IFBvcHVsYXRpb24gcGVyY2VudGFnZXMNCnBvcF9kYXRhICU+JQ0KICBwbG90X2x5KGxhYmVscyA9IH5jKCJNYWxlIiwgIkZlbWFsZSIsICJJbnRlcnNleCIpLA0KICAgICAgICAgIHZhbHVlcyA9IH5jKHN1bShwb3BfZGF0YSRNYWxlX1BvcHVsYXRpb24pLCBzdW0ocG9wX2RhdGEkRmVtYWxlX1BvcHVsYXRpb24pLCBzdW0ocG9wX2RhdGEkSW50ZXJzZXhfUG9wdWxhdGlvbikpLA0KICAgICAgICAgIHR5cGUgPSAncGllJywNCiAgICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9ycyA9IGMoImJsdWUiLCAicGluayIsICJyZWQiKSkpICU+JQ0KICBsYXlvdXQodGl0bGUgPSAiUG9wdWxhdGlvbiBEaXN0cmlidXRpb24gYnkgR2VuZGVyIikNCmBgYA0KIyMjIyBUb3RhbCBIb3VzZWhvbGRzIGJ5IFJlZ2lvbg0KYGBge3J9DQojIEJhciBQbG90IG9mIFRvdGFsIFBvcHVsYXRpb24gYnkgUmVnaW9uDQoNCnBsb3RfbHkoZGF0YSA9IHBvcF9kYXRhLA0KICAgICAgICB4ID0gflJlZ2lvbiwNCiAgICAgICAgeSA9IH5Ub3RhbF9Ib3VzZWhvbGQsDQogICAgICAgIHR5cGUgPSAnYmFyJywNCiAgICAgICAgbmFtZSA9ICdUb3RhbCBIb3VzZWhvbGRzIGJ5IFJlZ2lvbicsDQogICAgICAgIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnYmx1ZScpKSAlPiUNCiAgICBsYXlvdXQodGl0bGUgPSAnVG90YWwgSG91c2Vob2xkcyBieSBSZWdpb24nLA0KICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gJ1JlZ2lvbicpLA0KICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gJ1RvdGFsIEhvdXNlaG9sZHMgZm9yIFJlZ2lvbicpKQ0KYGBgDQoqKk9CU0VSVkFUSU9OOioqDQo8dWw+DQo8bGk+IFJpZnQgVmFsbGV5IGhhcyB0aGUgSGlnaGVzdCBudW1iZXIgb2YgSG91c2Vob2xkcyB3aGlsZSBOb3J0aCBFYXN0ZXJuIGhhcyB0aGUgbGVhc3QuDQo8L3VsPg0KDQoNCiMjIyBDb21wYXJpc29uIG9mIEdyb3VwIFF1YXJ0ZXJzIGFuZCBDb252ZW50aW9uYWwgSG91c2Vob2xkDQpgYGB7cn0NCiMgUGllIENoYXJ0IG9mIE1hbGUsIEZlbWFsZSBhbmQgSW50ZXJzZXggUG9wdWxhdGlvbiBwZXJjZW50YWdlcw0KDQpwb3BfZGF0YSAlPiUNCiAgcGxvdF9seShsYWJlbHMgPSB+YygiQ29udmVudGlvbmFsX0hvdXNlaG9sZCIsICJHcm91cF9RdWFydGVycyIpLA0KICAgICAgICAgIHZhbHVlcyA9IH5jKHN1bShwb3BfZGF0YSRDb252ZW50aW9uYWxfSG91c2Vob2xkKSwgc3VtKHBvcF9kYXRhJEdyb3VwX1F1YXJ0ZXJzKSksDQogICAgICAgICAgdHlwZSA9ICdwaWUnLA0KICAgICAgICAgIG1hcmtlciA9IGxpc3QoY29sb3JzID0gYygiYmx1ZSIsICJyZWQiKSkpICU+JQ0KICBsYXlvdXQodGl0bGUgPSAiQ29tcGFyaXNvbiBvZiBHcm91cCBRdWFydGVycyBhbmQgQ29udmVudGlvbmFsIEhvdXNlaG9sZCIpDQpgYGANCioqT0JTRVJWQVRJT046KioNCjx1bD4NCjxsaT4gQ29udmVudGlvbmFsIGhvdXNlaG9sZHMgYXJlIG1vcmUgY29tbW9uIHRoYW4gR3JvdXAgUXVhcnRlcnMuDQo8L3VsPg0KDQojIyMgQ29tcGFyaXNvbiBvZiBHcm91cCBRdWFydGVycyBhbmQgQ29udmVudGlvbmFsIEhvdXNlaG9sZCBieSBSZWdpb24NCmBgYHtyfQ0KIyBHcm91cGVkIEJhciBwbG90IHNob3dpbmcgQ29tcGFyaXNvbiBvZiBHcm91cCBRdWFydGVycyBhbmQgQ29udmVudGlvbmFsIEhvdXNlaG9sZCBieSBSZWdpb24NCg0KcGxvdF9seShkYXRhID0gcG9wX2RhdGEsDQogICAgICAgIHggPSB+UmVnaW9uLA0KICAgICAgICB5ID0gfkdyb3VwX1F1YXJ0ZXJzLA0KICAgICAgICB0eXBlID0gJ2JhcicsDQogICAgICAgIG5hbWUgPSAnR3JvdXAgUXVhcnRlcnMnLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJ3JlZCcpKSAlPiUNCiAgDQogIGFkZF90cmFjZSh5ID0gfkNvbnZlbnRpb25hbF9Ib3VzZWhvbGQsDQogICAgICAgICAgICBuYW1lID0gJ0NvbnZlbnRpb25hbCBIb3VzZWhvbGQnLA0KICAgICAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICdibHVlJykpICU+JQ0KICANCiAgbGF5b3V0KHRpdGxlID0gJ0NvbXBhcmlzb24gb2YgR3JvdXAgUXVhcnRlcnMgYW5kIENvbnZlbnRpb25hbCBIb3VzZWhvbGQgYnkgUmVnaW9uJywNCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICdSZWdpb24nKSwNCiAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICdDb3VudCcpLA0KICAgICAgICAgYmFybW9kZSA9ICdncm91cCcpDQpgYGANCioqT0JTRVJWQVRJT05TOioqDQo8dWw+DQo8bGk+IEFsbCBLZW55YW4gUmVnaW9ucyBoYXZlIGJvdGggQ29udmVudGlvbmFsIEhvdXNlaG9sZHMgYW5kIEdyb3VwIFF1YXJ0ZXJzDQo8bGk+IENvbnZlbnRpb25hbCBIb3VzZWhvbGRzIGFyZSBtb3JlIGNvbW1vbiB0aGF0IEdyb3VwIFF1YXJ0ZXJzDQo8bGk+IFJpZnQgVmFsbGV5IGhhcyB0aGUgSGlnaGVzdCBOdW1iZXIgb2YgYm90aCBDb252ZW50aW9uYWwgSG91c2Vob2xkcyBhbmQgR3JvdXAgUXVhcnRlcnMNCjwvdWw+DQoNCiMjIyBIb3VzZWhvbGQgdnMuIExhbmQgQXJlYQ0KYGBge3J9DQojIFNjYXR0ZXIgUGxvdCBvZiBIb3VzZWhvbGQgdnMuIExhbmQgQXJlYQ0KDQpwbG90X2x5KA0KICBkYXRhID0gcG9wX2RhdGEsDQogIHggPSB+VG90YWxfSG91c2Vob2xkLA0KICB5ID0gfkxhbmRfQXJlYV9TcUttLA0KICBjb2xvciA9IH5SZWdpb24sICAjIFNwZWNpZnkgdGhlIHZhcmlhYmxlIGZvciBjb2xvcmluZw0KICB0eXBlID0gJ3NjYXR0ZXInLA0KICBtb2RlID0gJ21hcmtlcnMnDQopICU+JQ0KICBsYXlvdXQoDQogICAgdGl0bGUgPSAnSG91c2Vob2xkIHZzLiBMYW5kIEFyZWEgYnkgUmVnaW9uJywNCiAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAnVG90YWwgSG91c2Vob2xkJyksDQogICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gJ0xhbmQgQXJlYSAoU3EgS20pJykNCiAgKQ0KYGBgDQoqKk9CU0VSVkFUSU9OOioqDQo8dWw+DQo8bGk+IE1vc3QgcGFydHMgb2YgS2VueWEgaGF2ZSBsb3cgTGFuZCBhcmVhIGFuZCBsb3cgSG91c2Vob2xkIG51bWJlcnMuDQo8L3VsPg0KDQojIyMgUG9wdWxhdGlvbiBEZW5zaXR5IERpc3RyaWJ1dGlvbg0KYGBge3J9DQojIEhpc3RvZ3JhbSBvZiBQb3B1bGF0aW9uIERlbnNpdHkNCiMgQ2FsY3VsYXRlIGRlbnNpdHkgdmFsdWVzDQpkZW5zaXR5X3ZhbHVlcyA8LSBkZW5zaXR5KHBvcF9kYXRhJERlbnNpdHlfUGVyc29uc19wZXJfU3FLbSkNCg0KIyBDcmVhdGUgdGhlIGNvbWJpbmVkIHBsb3QNCmNvbWJpbmVkX3Bsb3QgPC0gcGxvdF9seSgpICU+JQ0KICBhZGRfaGlzdG9ncmFtKHggPSB+cG9wX2RhdGEkRGVuc2l0eV9QZXJzb25zX3Blcl9TcUttLCBuYmluc3ggPSAyMCwgaGlzdG5vcm0gPSAncHJvYmFiaWxpdHkgZGVuc2l0eScsIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnYmx1ZScsIGxpbmUgPSBsaXN0KGNvbG9yID0gJ2JsYWNrJywgd2lkdGggPSAxKSkpICU+JQ0KICBhZGRfbGluZXMoeCA9IGRlbnNpdHlfdmFsdWVzJHgsIHkgPSBkZW5zaXR5X3ZhbHVlcyR5LCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ2xpbmVzJywgbGluZSA9IGxpc3QoY29sb3IgPSAncmVkJywgd2lkdGggPSAyKSkgJT4lDQogIGxheW91dCh0aXRsZSA9ICdQb3B1bGF0aW9uIERlbnNpdHkgSGlzdG9ncmFtIHdpdGggS0RFJywNCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICdEZW5zaXR5IChQZXJzb25zIHBlciBTcSBLbSknKSwNCiAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICdQcm9iYWJpbGl0eSBEZW5zaXR5JykpDQoNCiMgRGlzcGxheSB0aGUgY29tYmluZWQgcGxvdA0KY29tYmluZWRfcGxvdA0KYGBgDQoqKk9CU0VSVkFUSU9OOioqDQo8dWw+DQo8bGk+TW9zdCBLZW55YW4gYXJlYXMgaGF2ZSByZWxhdGl2ZWx5IGxvdyBwb3B1bGF0aW9uIGRlbnNpdHkgd2l0aCBhIGZldyBleGNlcHRpb25zIHdoZXJlIHBvcHVsYXRpb24gZGVuc2l0eSBpcyBzaWduaWZpY2FudGx5IGhpZ2guDQo8L3VsPg0KDQo8cD48L3A+DQoNCk5hcnJvd2luZyBkb3duIHRvIGNvbXBhcmlzb24gaW4gZGlmZmVyZW50IHJlZ2lvbnMgd2lsbCBoZWxwIGdhdGhlciBtb3JlIGluc2lnaHRzLg0KDQojIyMgUG9wdWxhdGlvbiBEZW5zaXR5IGJ5IFJlZ2lvbg0KYGBge3J9DQojIEJveCBQbG90DQpwbG90X2x5KGRhdGEgPSBwb3BfZGF0YSwgeCA9IH5SZWdpb24sIHkgPSB+RGVuc2l0eV9QZXJzb25zX3Blcl9TcUttLCB0eXBlID0gImJveCIpICU+JQ0KICBsYXlvdXQodGl0bGUgPSAiUG9wdWxhdGlvbiBEZW5zaXR5IGJ5IFJlZ2lvbiIsDQogICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiUmVnaW9uIiksDQogICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiRGVuc2l0eSAoUGVyc29ucyBwZXIgU3EgS20pIikpDQpgYGANCioqT0JTRVJWQVRJT046KioNCjx1bD4NCjxsaT5Nb3N0IHJlZ2lvbnMgaGF2ZSByZWxhdGl2ZWx5IGxvdyBkZW5zaXR5IHJhbmdpbmcgZnJvbSAwIHRvIHNsaWdodGx5IGFib3ZlIDEwMDAwMDAgcGVyc29ucyBwZXIgc3F1YXJlIEttIGJ1dCB0aGUgZW50aXJlIE5haXJvYmkgUmVnaW9uIGhhcyB2ZXJ5IGhpZ2ggZGVuc2l0eS4gQ29hc3QgUmVnaW9uIGhhcyBhbiBvdXRsaWVyIHRoYXQgaGFzIHZlcnkgaGlnaCBwb3B1bGF0aW9uIGRlbnNpdHkgb2YgNTQ5NTAwOCBwZXJzb25zIHBlciBTcSBLbS4NCjxMST5JbiBtb3N0IHJlZ2lvbnMsIHRoZSBtZWRpYW4gaXMgY2xvc2VyIHRvIHRoZSBsb3dlciB2YWx1ZXMuIFRoaXMgbWVhbnMgdGhhdCBtb3N0IHZhbHVlcyBhcmUgaW4gdGhlIGxvd2VyIHJhbmdlLiBUaGlzIGVtcGhhc2l6ZXMgdGhlICpsb3cgcG9wdWxhdGlvbiBkZW5zaXR5IGluIG1vc3QgcGFydHMgb2YgS2VueWEuKg0KPC91bD4NCg0KQSB0YWJsZSBzaG93aW5nIGRlbnNpdHkgZm9yIGVhY2ggY291bnR5IGluIGNvYXN0IHJlZ2lvbiB3aWxsIGhlbHAgdW5kZXJzdGFuZCB0aGUgb3V0bGllciBpbiB0aGUgcmVnaW9uIGJldHRlci4NCmBgYHtyfQ0KIyBmaWx0ZXIgY29hc3QgZGF0YSBvbmx5DQpjb2FzdF9kYXRhIDwtIHBvcF9kYXRhW3BvcF9kYXRhJFJlZ2lvbiA9PSAiQ29hc3QiLCBdDQoNCiMgQXNzdW1pbmcgeW91ciBkYXRhIGZyYW1lIGlzIG5hbWVkICdwb3BfZGF0YScNCmNvYXN0X2RhdGEgPC0gcG9wX2RhdGFbcG9wX2RhdGEkUmVnaW9uID09ICJDb2FzdCIsIF0NCg0KIyBDcmVhdGUgYSB0YWJsZSBvZiBkZW5zaXR5IHZhbHVlcw0KY29hc3RfZGVuc2l0eV90YWJsZSA8LSBjb2FzdF9kYXRhICU+JQ0KICBzZWxlY3QoQ291bnR5LCBEZW5zaXR5X1BlcnNvbnNfcGVyX1NxS20pICU+JQ0KICBrYWJsZSgiaHRtbCIsIGNhcHRpb24gPSAiRGVuc2l0eSBWYWx1ZXMgZm9yIENvdW50aWVzIGluIHRoZSBDb2FzdCBSZWdpb24iKSAlPiUNCiAga2FibGVfc3R5bGluZygpDQoNCiMgRGlzcGxheSB0aGUgdGFibGUNCmNvYXN0X2RlbnNpdHlfdGFibGUNCmBgYA0KKipPQlNFUlZBVElPTjoqKg0KPHVsPg0KPGxpPiBGcm9tIHRoZSBjb2FzdCBSZWdpb24sIE1vbWJhc2EgaXMgdGhlIG91dGxpZXIgd2l0aCB2ZXJ5IGhpZ2ggZGVuc2l0eSBjb21wYXJlZCB0byB0aGUgb3RoZXIgYXJlYXMuDQo8L3VsPg0KDQojIEZJTkRJTkdTDQo8dWw+DQo8bGk+IFJpZnQgdmFsbGV5IHJlZ2lvbiBoYXMgdGhlIEhpZ2hlc3QgUG9wdWxhdGlvbiBhbmQgaGlnaGVzdCBudW1iZXIgb2YgSG91c2Vob2xkcy4NCjxwPjwvcD4NCjxsaT4gTm9ydGggRWFzdGVybiByZWdpb24gaGFzIHRoZSBsb3dlc3QgUG9wdWxhdGlvbiBhbmQgbG93ZXN0IG51bWJlciBvZiBIb3VzZWhvbGRzLg0KPHA+PC9wPg0KPGxpPiBNb3N0IEtlbnlhbnMgaWRlbnRpZnkgYXMgbWFsZSBvciBmZW1hbGUuIFdpdGggc2xpZ2h0bHkgbW9yZSBmZW1hbGVzIHRoYW4gbWFsZXMuIEEgdmVyeSBzbWFsbCBwZXJjZW50YWdlKDAuMDAzMiUpIGlkZW50aWZ5IGFzIGludGVyc2V4Lg0KPHA+PC9wPg0KPGxpPiBOYWlyb2JpIENvdW50eSBoYXMgdGhlIEhpZ2hlc3QgUG9wdWxhdGlvbiBjb21wYXJlZCB0byBvdGhlciBjb3VudGllcywgZm9sbG93ZWQgYnkgS2lhbWJ1IHRoZW4gTmFrdXJ1Lg0KPHA+PC9wPg0KPGxpPiBMYW11IENvdW50eSBoYXMgdGhlIExvd2VzdCBQb3B1bGF0aW9uIGNvbXBhcmVkIHRvIG90aGVyIGNvdW50aWVzLCBmb2xsb3dlZCBieSBJc2lvbG8gdGhlbiBTYW1idXJ1IGZyb20gdGhlIGJvdHRvbS4NCjxwPjwvcD4NCjxsaT4gQWxsIEtlbnlhbiBSZWdpb25zIGhhdmUgYm90aCBDb252ZW50aW9uYWwgSG91c2Vob2xkcyBhbmQgR3JvdXAgUXVhcnRlcnMgYnV0IENvbnZlbnRpb25hbCBIb3VzZWhvbGRzIGFyZSBtb3JlIGNvbW1vbiB0aGF0IEdyb3VwIFF1YXJ0ZXJzLg0KPHA+PC9wPg0KPGxpPiBNb3N0IEtlbnlhbiBjb3VudGllcyBoYXZlIHJlbGF0aXZlbHkgbG93IFBvcHVsYXRpb24gRGVuc2l0eSB3aXRoIGFuIGV4Y2VwdGlvbiBvZiBNb21iYXNhIGFuZCBOYWlyb2JpIHdoaWNoIGhhdmUgdmVyeSBIaWdoIFBvcHVsYXRpb24gRGVuc2l0eShQZXJzb25zIHBlciBTcXVhcmUgS2lsb21ldGVyKSBjb21wYXJlZCB0byB0aGUgb3RoZXIgY291bnRpZXMuDQo8L3VsPg0KDQoNCg==