Read in Bank Loan
Default Dataset
Read in dataset.
bank <- read.csv("BankLoanDefaultDataset.csv")
Below looks at each variable and see what type they all are.
str(bank)
'data.frame': 1000 obs. of 16 variables:
$ Default : int 0 0 0 1 1 0 0 0 0 1 ...
$ Checking_amount : int 988 458 158 300 63 1071 -192 172 585 189 ...
$ Term : int 15 15 14 25 24 20 13 16 20 19 ...
$ Credit_score : int 796 813 756 737 662 828 856 763 778 649 ...
$ Gender : chr "Female" "Female" "Female" "Female" ...
$ Marital_status : chr "Single" "Single" "Single" "Single" ...
$ Car_loan : int 1 1 0 0 0 1 1 1 1 1 ...
$ Personal_loan : int 0 0 1 0 0 0 0 0 0 0 ...
$ Home_loan : int 0 0 0 0 0 0 0 0 0 0 ...
$ Education_loan : int 0 0 0 1 1 0 0 0 0 0 ...
$ Emp_status : chr "employed" "employed" "employed" "employed" ...
$ Amount : int 1536 947 1678 1804 1184 475 626 1224 1162 786 ...
$ Saving_amount : int 3455 3600 3093 2449 2867 3282 3398 3022 3475 2711 ...
$ Emp_duration : int 12 25 43 0 4 12 11 12 12 0 ...
$ Age : int 38 36 34 29 30 32 38 36 36 29 ...
$ No_of_credit_acc: int 1 1 1 1 1 2 1 1 1 1 ...
Below looks at the top few rows of dataset.
head(bank)
Default Checking_amount Term Credit_score Gender Marital_status Car_loan
1 0 988 15 796 Female Single 1
2 0 458 15 813 Female Single 1
3 0 158 14 756 Female Single 0
4 1 300 25 737 Female Single 0
5 1 63 24 662 Female Single 0
6 0 1071 20 828 Male Married 1
Personal_loan Home_loan Education_loan Emp_status Amount Saving_amount
1 0 0 0 employed 1536 3455
2 0 0 0 employed 947 3600
3 1 0 0 employed 1678 3093
4 0 0 1 employed 1804 2449
5 0 0 1 unemployed 1184 2867
6 0 0 0 employed 475 3282
Emp_duration Age No_of_credit_acc
1 12 38 1
2 25 36 1
3 43 34 1
4 0 29 1
5 4 30 1
6 12 32 2
Create Missing
Values
The original dataset does not have any missing values so I needed to
manually create them.
gender.missing.id <- sample(1:1000, 20 , replace = FALSE)
Marital.missing.id <- sample(1:1000, 20, replace = FALSE)
emp.status.missing.id <- sample(1:1000, 20, replace = FALSE)
credit.missing.id <- sample(1:1000, 20, replace = FALSE)
amount.missing.id <- sample(1:1000, 20, replace = FALSE)
emp.duration.missing.id <- sample(1:1000, 20, replace = FALSE)
check.amt.missing.id <- sample(1:1000, 20, replace = FALSE)
age.missing.id <- sample(1:1000, 20, replace = FALSE)
bank$Gender[gender.missing.id] <- NA
bank$Marital_status[Marital.missing.id] <- NA
bank$Emp_status[emp.status.missing.id] <- NA
bank$Credit_score[credit.missing.id] <- NA
bank$Amount[amount.missing.id] <- NA
bank$Emp_duration[emp.duration.missing.id] <- NA
bank$Checking_amount[check.amt.missing.id] <- NA
bank$Age[age.missing.id] <- NA
Description and Purpose
of Dataset and Analytic Tasks
This dataset is titled “Bank Loan Default Dataset” and shows various
explanatory variables and one target/response variable (Default). The
purpose of collecting this dataset is to see what factors may cause
peoples loans to be in default or not. This dataset was collected from
your Course Project Data Repository. This dataset contains 1000
observations and 16 variables (15 feature variables and 1 target
variable). The Checking_amount is a numerical variable that shows the
amount of money in ones checking account. The Saving_amount is a
numerical variable that shows the amount of money in ones saving
account. The term (numerical) is the duration of the loan term. The
credit_score (numerical) shows ones credit score. The gender
(categorical) consists of male and female. The marital_status
(categorical) consists of married or single. The car_loan,
personal_loan, home_loan, and education_loan (all categorical/binary)
shows if people have loans in any of those areas. The emp_status
(categorical) consists of unemployed or employed. The amount (numerical)
shows the amount of the loan. The emp_duration (num) shows length of
employment in months. Age (num) shows age and no_of_credit_account (num)
shows number of credit accounts. The overall goal of this project is to
see how significant the feature variables are in predicting if ones loan
will be in default (1 if default, 0 if not). The first part of the
project is doing EDA.
The original dataset did not have any missing values so I needed to
manually create them. For this dataset, the variables Gender,
Marital_status, Emp_status, credit_score, amount, emp_duration,
checking_amount, and age have missing values. Missing numerical values
can be resolved by imputing the mean. Missing categorical values can be
resolved by imputing the mode.
Distribution of
Individual Features
This section will show the distribution of each individual feature.
Some features will have missing values and can be resolved by imputing
the mean or mode.
The below figure shows the distribution of the Gender variable. There
are significantly more males than females.
ggplot(bank, aes(x = Gender)) +
geom_bar() +
labs(title = "Gender")

The below figure shows the distribution of the Marital_status
variable. Married and single people have similar counts.
ggplot(bank, aes(x = Marital_status)) +
geom_bar() +
labs(title = "Marital_status")

The below figure shows the distribution of the Emp_status variable.
There are significantly more unemployed than employed.
ggplot(bank, aes(x = Emp_status)) +
geom_bar() +
labs(title = "Emp_status")

The below figure shows the distribution of the car loan variable.
There are significantly more that do not have a car loan than those that
do.
ggplot(bank, aes(x = Car_loan)) +
geom_bar() +
labs(title = "Car_loan")

The below figure shows the distribution of the personal loan
variable. Those that have a personal loan and those that do not have
similar counts.
ggplot(bank, aes(x = Personal_loan)) +
geom_bar() +
labs(title = "Personal_loan")

The below figure shows the distribution of the education loan
variable. There are significantly more that do not have an education
loan than those that do.
ggplot(bank, aes(x = Education_loan)) +
geom_bar() +
labs(title = "Education_loan")

The below figure shows the distribution of the home loan variable.
There are significantly more that do not have a home loan than those
that do.
ggplot(bank, aes(x = Home_loan)) +
geom_bar() +
labs(title = "Home_loan")

The below figure shows the distribution of the credit score variable.
There are no alarming trends outside of a couple anomalies.
ggplot(data = bank, aes(x = Credit_score)) +
geom_boxplot() +
labs(title = "Credit_score")

The below figure shows the distribution of the checking amount
variable. There are no alarming trends.
ggplot(data = bank, aes(x = Checking_amount)) +
geom_boxplot() +
labs(title = "Checking_amount")

The below figure shows the distribution of the term variable. There
are no alarming trends.
ggplot(data = bank, aes(x = Term)) +
geom_boxplot() +
labs(title = "Term")

The below figure shows the distribution of the amount variable. There
are no alarming trends.
ggplot(data = bank, aes(x = Amount)) +
geom_boxplot() +
labs(title = "Amount")

The below figure shows the distribution of the Saving amount
variable. There are no alarming trends.
ggplot(data = bank, aes(x = Saving_amount)) +
geom_boxplot() +
labs(title = "Saving amount")

The below figure shows the distribution of the Emp_duration variable.
There are no alarming trends.
ggplot(data = bank, aes(x = Emp_duration)) +
geom_boxplot() +
labs(title = "Emp duration")

The below figure shows the distribution of the age variable. There
are no alarming trends.
ggplot(data = bank, aes(x = Age)) +
geom_boxplot() +
labs(title = "Age")

The below figure shows the distribution of the No_of_credit_acc
variable. This variable seems to be heavily skewed.
ggplot(data = bank, aes(x = No_of_credit_acc)) +
geom_boxplot() +
labs(title = "No_of_credit_acc")

One Categorical Feature
and One Numerical feature Graphs
In this section, we will show the relationship between one
categorical feature and one numerical feature.
The below figure shows the relationship between credit score and
gender. Based on the graph, the credit score ranges look to be similar
across both genders. There are some anomalies but I do not believe that
they will have a significant effect on the analysis. There are missing
values but they can be resolved using imputation.
ggplot(bank, aes(x=Credit_score, y=Gender, fill=Gender)) +
geom_boxplot() + theme(legend.position="none")+
ggtitle("Credit Score by Gender")

The below figure shows the relationship between loan amount and
gender. Based on the graph, the loan amount ranges look to be similar
across both genders. There are some anomalies but I do not believe that
they will have a significant effect on the analysis. There are missing
values but they can be resolved using imputation.
ggplot(bank, aes(x=Amount, y=Gender, fill=Gender)) +
geom_boxplot() + theme(legend.position="none")+
ggtitle("Amount by Gender")

The below figure shows the relationship between Employment duration
and gender. Based on the graph, it seems like males have a longer
employment duration than females. There are missing values but they can
be resolved using imputation.
ggplot(bank, aes(x=Emp_duration, y=Gender, fill=Gender)) +
geom_boxplot() + theme(legend.position="none")+
ggtitle("Employment duration by Gender")

The below figure shows the relationship between Age and gender. Based
on the graph, the Age ranges look to be similar across both genders.
There are some anomalies but I do not believe that they will have a
significant effect on the analysis. There are missing values but they
can be resolved using imputation.
ggplot(bank, aes(x=Age, y=Gender, fill=Gender)) +
geom_boxplot() + theme(legend.position="none")+
ggtitle("Age by Gender")

The below figure shows the relationship between marital status and
credit score. Based on the graph, the credit score ranges look to be
similar across both single and married people. There are some anomalies
but I do not believe that they will have a significant effect on the
analysis. There are missing values but they can be resolved using
imputation.
ggplot(bank, aes(x=Credit_score, y=Marital_status, fill=Marital_status)) +
geom_boxplot() + theme(legend.position="none")+
ggtitle("Credit Score by Marital status")

The below figure shows the relationship between loan amount and
marital status. Based on the graph, the loan amount ranges look to be
similar across both marital statuses. There are some anomalies but I do
not believe that they will have a significant effect on the analysis.
There are missing values but they can be resolved using imputation.
ggplot(bank, aes(x=Amount, y=Marital_status, fill=Marital_status)) +
geom_boxplot() + theme(legend.position="none")+
ggtitle("Amount by Marital status")

The below figure shows the relationship between marital status and
employment duration. Based on the graph, it seems like married people
have longer employment duration than single people. There are missing
values but they can be resolved using imputation.
ggplot(bank, aes(x=Emp_duration, y=Marital_status, fill=Marital_status)) +
geom_boxplot() + theme(legend.position="none")+
ggtitle("Employment duration by Marital status")

The below figure shows the relationship between Age and marital
status. Based on the graph, the Age ranges look to be similar across
both marital statuses. There are some anomalies but I do not believe
that they will have a significant effect on the analysis. There are
missing values but they can be resolved using imputation.
ggplot(bank, aes(x=Age, y=Marital_status, fill=Marital_status)) +
geom_boxplot() + theme(legend.position="none")+
ggtitle("age by Marital status")

The below figure shows the relationship between credit score and
employment status. Based on the graph, the credit score ranges look to
be similar across both employed and unemployed people. There seems to be
more anomalies for unemployed people but I do not believe that they will
have a significant effect on the analysis. There are missing values but
they can be resolved using imputation.
ggplot(bank, aes(x=Credit_score, y=Emp_status, fill=Emp_status)) +
geom_boxplot() + theme(legend.position="none")+
ggtitle("Credit Score by Employment status")

The below figure shows the relationship between loan amount and
employment status. Based on the graph, the loan amount ranges look to be
similar across both employed/unemployed. Again there seems to be more
anomalies for unemployed people than employed. There are missing values
but they can be resolved using imputation.
ggplot(bank, aes(x=Amount, y=Emp_status, fill=Emp_status)) +
geom_boxplot() + theme(legend.position="none")+
ggtitle("Amount by Employment status")

The below figure shows the relationship between employment duration
and employment status. Based on the graph, it seems like unemployed
people have longer and more varied employment duration than employed
people. There are missing values but they can be resolved using
imputation.
ggplot(bank, aes(x=Emp_duration, y=Emp_status, fill=Emp_status)) +
geom_boxplot() + theme(legend.position="none")+
ggtitle("Employment duration by employment status")

The below figure shows the relationship between Age and employment
status. Based on the graph, the Age ranges look to be similar across
both statuses. There are some anomalies but I do not believe that they
will have a significant effect on the analysis. There are missing values
but they can be resolved using imputation.
ggplot(bank, aes(x=Age, y=Emp_status, fill=Emp_status)) +
geom_boxplot() + theme(legend.position="none")+
ggtitle("age by employment status")

The below figure shows the relationship between Age and car loan.
Based on the graph, the Age ranges look to be similar across both those
who own a car loan and those who do not.
# convert car, home, personal, and education loans into categorical to use for EDA purposes
bank$Car_loan <- as.factor(bank$Car_loan)
bank$Personal_loan <- as.factor(bank$Personal_loan)
bank$Home_loan <- as.factor(bank$Home_loan)
bank$Education_loan <- as.factor(bank$Education_loan)
ggplot(bank, aes(x=Age, y=Car_loan, fill=Car_loan)) +
geom_boxplot() + theme(legend.position="none")+
ggtitle("age by car loan")

The below figure shows the relationship between Age and personal
loan. Based on the graph, the Age ranges look to be similar across all
those that have a personal loan or not.
ggplot(bank, aes(x=Age, y=Personal_loan, fill=Personal_loan)) +
geom_boxplot() + theme(legend.position="none")+
ggtitle("age by personal_loan")

The below figure shows the relationship between Age and home loan.
Based on the graph, the Age ranges look to be similar across all those
that have a home loan or not.
ggplot(bank, aes(x=Age, y=Home_loan, fill=Home_loan)) +
geom_boxplot() + theme(legend.position="none")+
ggtitle("age by home_loan")

The below figure shows the relationship between Age and education
loan. Based on the graph, it seems like younger people have an education
loan and older people do not.
ggplot(bank, aes(x=Age, y=Education_loan, fill=Education_loan)) +
geom_boxplot() + theme(legend.position="none")+
ggtitle("age by education loan")

Two numerical feature
variables graphs
Next, we will examine the relationship between two numerical
features.
The below graph shows employment duration and credit score. Based on
the graph, it seems like regardless of the employment duration, the
majority of the credit scores seem to fall in the 700-900 range.
ggplot(data = bank, aes(x = Credit_score, y = Emp_duration)) +
geom_point() +
ggtitle("Employment Duration vs Credit Score")

The below graph shows employment duration and loan amount. There does
not seem to be any patterns based on this graph.
ggplot(data = bank, aes(x = Amount, y = Emp_duration)) +
geom_point() +
ggtitle("Employment Duration vs Loan Amount")

The below graph shows employment duration and age. There does not
seem to be any patterns based on this graph.
ggplot(data = bank, aes(x = Age, y = Emp_duration)) +
geom_point() +
ggtitle("Employment Duration vs Age")

The below graph shows age and Credit score. Again, it seems like
regardless of age, most of the credit scores seem to fall in that
700-900 range.
ggplot(data = bank, aes(x = Age, y = Credit_score)) +
geom_point() +
ggtitle("Age vs credit score")

The below graph shows checking amount and saving amount. There does
not seem to be any correlation between these two variables.
ggplot(data = bank, aes(x = Checking_amount, y = Saving_amount)) +
geom_point() +
ggtitle("Checking amount vs savings Amount")

The below graph shows age and loan amount. It seems like regardless
of age, most of the loan amounts seem to fall in a certain range.
ggplot(data = bank, aes(x = Age, y = Amount)) +
geom_point() +
ggtitle("age vs Loan Amount")

The below graph shows credit score and loan amount. It seems like
most of the points are clumped together.
ggplot(data = bank, aes(x = Credit_score, y = Amount)) +
geom_point() +
ggtitle("credit score vs Loan Amount")

Two categorical feature
variables graphs
This section shows the relationships between two categorical
features.
The below graph shows Gender and Employment status. It seems like the
amount of employed and unemployed females are similar but there are
significantly more unemployed males than employed.
ggplot(bank, aes(Gender, ..count..)) + geom_bar(aes(fill = Emp_status), position = "dodge")+ggtitle("gender vs employment status")

The below graph shows Gender and marital status. It seems like all
females are single and there are significantly more married males than
single.
ggplot(bank, aes(Gender, ..count..)) + geom_bar(aes(fill = Marital_status), position = "dodge")+ggtitle("gender vs marital status")

The below graph shows employment status and marital status. It seems
like the amount of employed and unemployed people are relatively similar
but for married people, there are significantly more who are
unemployed.
ggplot(bank, aes(Marital_status, ..count..)) + geom_bar(aes(fill = Emp_status), position = "dodge")+ggtitle("marital status vs enployment status")

The below graph shows gender and car loan. It seems like for both
males and females, there are significantly more that do not have car
loans than those that do.
ggplot(bank, aes(Gender, ..count..)) + geom_bar(aes(fill = Car_loan), position = "dodge")+ggtitle("gender vs car loan")

The below graph shows gender and education loan. It seems like for
both males and females, there are significantly more that do not have
education loans than those that do.
ggplot(bank, aes(Gender, ..count..)) + geom_bar(aes(fill = Education_loan), position = "dodge")+ggtitle("Gender vs education Loan")

The below graph shows gender and personal loan. It seems like for
both males and females, the amounts that who have personal loans and
those that do not are relatively similar.
ggplot(bank, aes(Gender, ..count..)) + geom_bar(aes(fill = Personal_loan), position = "dodge")+ggtitle("Gender vs personal Loan")

The below graph shows gender and home loan. It seems like for both
males and females, there are significantly more that do not have home
loans than those that do.
ggplot(bank, aes(Gender, ..count..)) + geom_bar(aes(fill = Home_loan), position = "dodge")+ggtitle("Gender vs home Loan")

LS0tDQp0aXRsZTogIkJhbmsgTG9hbiBEZWZhdWx0IERhdGFzZXQiDQphdXRob3I6ICJFcmljIFpodSINCmRhdGU6ICIyMDI1LTAyLTA1Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICB0aGVtZTogbHVtZW4NCiAgcGRmX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IG5vDQogICAgZmlnX3dpZHRoOiAzDQogICAgZmlnX2hlaWdodDogMw0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lDQotLS0NCg0KDQpgYGB7PWh0bWx9DQoNCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoNCi8qIENhc2NhZGluZyBTdHlsZSBTaGVldHMgKENTUykgaXMgYSBzdHlsZXNoZWV0IGxhbmd1YWdlIHVzZWQgdG8gZGVzY3JpYmUgdGhlIHByZXNlbnRhdGlvbiBvZiBhIGRvY3VtZW50IHdyaXR0ZW4gaW4gSFRNTCBvciBYTUwuIGl0IGlzIGEgc2ltcGxlIG1lY2hhbmlzbSBmb3IgYWRkaW5nIHN0eWxlIChlLmcuLCBmb250cywgY29sb3JzLCBzcGFjaW5nKSB0byBXZWIgZG9jdW1lbnRzLiAqLw0KDQpoMS50aXRsZSB7ICAvKiBUaXRsZSAtIGZvbnQgc3BlY2lmaWNhdGlvbnMgb2YgdGhlIHJlcG9ydCB0aXRsZSAqLw0KICBmb250LXNpemU6IDI0cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBjb2xvcjogbmF2eTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7DQp9DQpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGZvbnQgc3BlY2lmaWNhdGlvbnMgZm9yIGF1dGhvcnMgICovDQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC1mYW1pbHk6IHN5c3RlbS11aTsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGNvbG9yOiBuYXZ5Ow0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBmb250IHNwZWNpZmljYXRpb25zIGZvciB0aGUgZGF0ZSAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LWZhbWlseTogc3lzdGVtLXVpOw0KICBjb2xvcjogRGFya0JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQp9DQpoMSB7IC8qIEhlYWRlciAxIC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgbGV2ZWwgMSBzZWN0aW9uIHRpdGxlICAqLw0KICAgIGZvbnQtc2l6ZTogMjBweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQp9DQpoMiB7IC8qIEhlYWRlciAyIC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgbGV2ZWwgMiBzZWN0aW9uIHRpdGxlICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQp9DQoNCmgzIHsgLyogSGVhZGVyIDMgLSBmb250IHNwZWNpZmljYXRpb25zIG9mIGxldmVsIDMgc2VjdGlvbiB0aXRsZSAgKi8NCiAgICBmb250LXNpemU6IDE2cHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDQgeyAvKiBIZWFkZXIgNCAtIGZvbnQgc3BlY2lmaWNhdGlvbnMgb2YgbGV2ZWwgNCBzZWN0aW9uIHRpdGxlICAqLw0KICAgIGZvbnQtc2l6ZTogMTRweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpib2R5IHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQouaGlnaGxpZ2h0bWUgeyBiYWNrZ3JvdW5kLWNvbG9yOnllbGxvdzsgfQ0KDQpwIHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQo8L3N0eWxlPg0KYGBgDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IA0KIyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZSBvdXRwdXQgZmlsZXMuDQppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCiAgIGxpYnJhcnkoa25pdHIpDQp9DQppZiAoIXJlcXVpcmUoInRpZHl2ZXJzZSIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQp9DQppZiAoIXJlcXVpcmUoInJlYWR4bCIpKSB7ICMgU1ZNIG1ldGhvZG9sb2d5DQogICBpbnN0YWxsLnBhY2thZ2VzKCJyZWFkeGwiKQ0KbGlicmFyeShyZWFkeGwpDQp9DQppZiAoIXJlcXVpcmUoImdncGxvdDIiKSkgeyAjIFNWTSBtZXRob2RvbG9neQ0KICAgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpDQpsaWJyYXJ5KGdncGxvdDIpDQp9DQppZiAoIXJlcXVpcmUoIklTTFIiKSkgeyAjIGNvbnRhaW5zIGV4YW1wbGUgZGF0YSBzZXQgIktoYW4iDQogICBpbnN0YWxsLnBhY2thZ2VzKCJJU0xSIikNCmxpYnJhcnkoSVNMUikNCn0NCmlmICghcmVxdWlyZSgiUkNvbG9yQnJld2VyIikpIHsgIyBjdXN0b21pemVkIGNvbG9yaW5nIG9mIHBsb3RzDQogICBpbnN0YWxsLnBhY2thZ2VzKCJSQ29sb3JCcmV3ZXIiKQ0KbGlicmFyeShSQ29sb3JCcmV3ZXIpDQp9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsICAgICAgICMgaW5jbHVkZSBjb2RlIGNodW5rIGluIHRoZSBvdXRwdXQgZmlsZQ0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgICAjIHNvbWV0aW1lcywgeW91IGNvZGUgbWF5IHByb2R1Y2Ugd2FybmluZyBtZXNzYWdlcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB5b3UgY2FuIGNob29zZSB0byBpbmNsdWRlIHRoZSB3YXJuaW5nIG1lc3NhZ2VzIGluDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdGhlIG91dHB1dCBmaWxlLiANCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzID0gVFJVRSwgICAgIyB5b3UgY2FuIGFsc28gZGVjaWRlIHdoZXRoZXIgdG8gaW5jbHVkZSB0aGUgb3V0cHV0DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgaW4gdGhlIG91dHB1dCBmaWxlLg0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICBjb21tZW50ID0gTkENCiAgICAgICAgICAgICAgICAgICAgICApICANCmBgYA0KDQoNCg0KDQojIFJlYWQgaW4gQmFuayBMb2FuIERlZmF1bHQgRGF0YXNldA0KDQpSZWFkIGluIGRhdGFzZXQuDQoNCmBgYHtyfQ0KYmFuayA8LSByZWFkLmNzdigiQmFua0xvYW5EZWZhdWx0RGF0YXNldC5jc3YiKQ0KYGBgDQoNCkJlbG93IGxvb2tzIGF0IGVhY2ggdmFyaWFibGUgYW5kIHNlZSB3aGF0IHR5cGUgdGhleSBhbGwgYXJlLg0KDQpgYGB7cn0NCnN0cihiYW5rKQ0KYGBgDQoNCkJlbG93IGxvb2tzIGF0IHRoZSB0b3AgZmV3IHJvd3Mgb2YgZGF0YXNldC4NCg0KYGBge3J9DQpoZWFkKGJhbmspDQpgYGANCg0KDQojIyBDcmVhdGUgTWlzc2luZyBWYWx1ZXMNCg0KVGhlIG9yaWdpbmFsIGRhdGFzZXQgZG9lcyBub3QgaGF2ZSBhbnkgbWlzc2luZyB2YWx1ZXMgc28gSSBuZWVkZWQgdG8gbWFudWFsbHkgY3JlYXRlIHRoZW0uDQoNCmBgYHtyfQ0KZ2VuZGVyLm1pc3NpbmcuaWQgPC0gc2FtcGxlKDE6MTAwMCwgMjAgLCByZXBsYWNlID0gRkFMU0UpDQpNYXJpdGFsLm1pc3NpbmcuaWQgPC0gc2FtcGxlKDE6MTAwMCwgMjAsIHJlcGxhY2UgPSBGQUxTRSkNCmVtcC5zdGF0dXMubWlzc2luZy5pZCA8LSBzYW1wbGUoMToxMDAwLCAyMCwgcmVwbGFjZSA9IEZBTFNFKQ0KY3JlZGl0Lm1pc3NpbmcuaWQgPC0gc2FtcGxlKDE6MTAwMCwgMjAsIHJlcGxhY2UgPSBGQUxTRSkNCmFtb3VudC5taXNzaW5nLmlkIDwtIHNhbXBsZSgxOjEwMDAsIDIwLCByZXBsYWNlID0gRkFMU0UpDQplbXAuZHVyYXRpb24ubWlzc2luZy5pZCA8LSBzYW1wbGUoMToxMDAwLCAyMCwgcmVwbGFjZSA9IEZBTFNFKQ0KY2hlY2suYW10Lm1pc3NpbmcuaWQgPC0gc2FtcGxlKDE6MTAwMCwgMjAsIHJlcGxhY2UgPSBGQUxTRSkNCmFnZS5taXNzaW5nLmlkIDwtIHNhbXBsZSgxOjEwMDAsIDIwLCByZXBsYWNlID0gRkFMU0UpDQoNCmJhbmskR2VuZGVyW2dlbmRlci5taXNzaW5nLmlkXSA8LSBOQQ0KYmFuayRNYXJpdGFsX3N0YXR1c1tNYXJpdGFsLm1pc3NpbmcuaWRdIDwtIE5BDQpiYW5rJEVtcF9zdGF0dXNbZW1wLnN0YXR1cy5taXNzaW5nLmlkXSA8LSBOQQ0KYmFuayRDcmVkaXRfc2NvcmVbY3JlZGl0Lm1pc3NpbmcuaWRdIDwtIE5BDQpiYW5rJEFtb3VudFthbW91bnQubWlzc2luZy5pZF0gPC0gTkENCmJhbmskRW1wX2R1cmF0aW9uW2VtcC5kdXJhdGlvbi5taXNzaW5nLmlkXSA8LSBOQQ0KYmFuayRDaGVja2luZ19hbW91bnRbY2hlY2suYW10Lm1pc3NpbmcuaWRdIDwtIE5BDQpiYW5rJEFnZVthZ2UubWlzc2luZy5pZF0gPC0gTkENCg0KDQoNCmBgYA0KDQojIERlc2NyaXB0aW9uIGFuZCBQdXJwb3NlIG9mIERhdGFzZXQgYW5kIEFuYWx5dGljIFRhc2tzDQoNClRoaXMgZGF0YXNldCBpcyB0aXRsZWQgIkJhbmsgTG9hbiBEZWZhdWx0IERhdGFzZXQiIGFuZCBzaG93cyB2YXJpb3VzIGV4cGxhbmF0b3J5IHZhcmlhYmxlcyBhbmQgb25lIHRhcmdldC9yZXNwb25zZSB2YXJpYWJsZSAoRGVmYXVsdCkuIFRoZSBwdXJwb3NlIG9mIGNvbGxlY3RpbmcgdGhpcyBkYXRhc2V0IGlzIHRvIHNlZSB3aGF0IGZhY3RvcnMgbWF5IGNhdXNlIHBlb3BsZXMgbG9hbnMgdG8gYmUgaW4gZGVmYXVsdCBvciBub3QuIFRoaXMgZGF0YXNldCB3YXMgY29sbGVjdGVkIGZyb20geW91ciBDb3Vyc2UgUHJvamVjdCBEYXRhIFJlcG9zaXRvcnkuIFRoaXMgZGF0YXNldCBjb250YWlucyAxMDAwIG9ic2VydmF0aW9ucyBhbmQgMTYgdmFyaWFibGVzICgxNSBmZWF0dXJlIHZhcmlhYmxlcyBhbmQgMSB0YXJnZXQgdmFyaWFibGUpLiBUaGUgQ2hlY2tpbmdfYW1vdW50IGlzIGEgbnVtZXJpY2FsIHZhcmlhYmxlIHRoYXQgc2hvd3MgdGhlIGFtb3VudCBvZiBtb25leSBpbiBvbmVzIGNoZWNraW5nIGFjY291bnQuIFRoZSBTYXZpbmdfYW1vdW50IGlzIGEgbnVtZXJpY2FsIHZhcmlhYmxlIHRoYXQgc2hvd3MgdGhlIGFtb3VudCBvZiBtb25leSBpbiBvbmVzIHNhdmluZyBhY2NvdW50LiBUaGUgdGVybSAobnVtZXJpY2FsKSBpcyB0aGUgZHVyYXRpb24gb2YgdGhlIGxvYW4gdGVybS4gVGhlIGNyZWRpdF9zY29yZSAobnVtZXJpY2FsKSBzaG93cyBvbmVzIGNyZWRpdCBzY29yZS4gVGhlIGdlbmRlciAoY2F0ZWdvcmljYWwpIGNvbnNpc3RzIG9mIG1hbGUgYW5kIGZlbWFsZS4gVGhlIG1hcml0YWxfc3RhdHVzIChjYXRlZ29yaWNhbCkgY29uc2lzdHMgb2YgbWFycmllZCBvciBzaW5nbGUuIFRoZSBjYXJfbG9hbiwgcGVyc29uYWxfbG9hbiwgaG9tZV9sb2FuLCBhbmQgZWR1Y2F0aW9uX2xvYW4gKGFsbCBjYXRlZ29yaWNhbC9iaW5hcnkpIHNob3dzIGlmIHBlb3BsZSBoYXZlIGxvYW5zIGluIGFueSBvZiB0aG9zZSBhcmVhcy4gVGhlIGVtcF9zdGF0dXMgKGNhdGVnb3JpY2FsKSBjb25zaXN0cyBvZiB1bmVtcGxveWVkIG9yIGVtcGxveWVkLiBUaGUgYW1vdW50IChudW1lcmljYWwpIHNob3dzIHRoZSBhbW91bnQgb2YgdGhlIGxvYW4uIFRoZSBlbXBfZHVyYXRpb24gKG51bSkgc2hvd3MgbGVuZ3RoIG9mIGVtcGxveW1lbnQgaW4gbW9udGhzLiBBZ2UgKG51bSkgc2hvd3MgYWdlIGFuZCBub19vZl9jcmVkaXRfYWNjb3VudCAobnVtKSBzaG93cyBudW1iZXIgb2YgY3JlZGl0IGFjY291bnRzLiBUaGUgb3ZlcmFsbCBnb2FsIG9mIHRoaXMgcHJvamVjdCBpcyB0byBzZWUgaG93IHNpZ25pZmljYW50IHRoZSBmZWF0dXJlIHZhcmlhYmxlcyBhcmUgaW4gcHJlZGljdGluZyBpZiBvbmVzIGxvYW4gd2lsbCBiZSBpbiBkZWZhdWx0ICgxIGlmIGRlZmF1bHQsIDAgaWYgbm90KS4gVGhlIGZpcnN0IHBhcnQgb2YgdGhlIHByb2plY3QgaXMgZG9pbmcgRURBLg0KDQpUaGUgb3JpZ2luYWwgZGF0YXNldCBkaWQgbm90IGhhdmUgYW55IG1pc3NpbmcgdmFsdWVzIHNvIEkgbmVlZGVkIHRvIG1hbnVhbGx5IGNyZWF0ZSB0aGVtLiBGb3IgdGhpcyBkYXRhc2V0LCB0aGUgdmFyaWFibGVzIEdlbmRlciwgTWFyaXRhbF9zdGF0dXMsIEVtcF9zdGF0dXMsIGNyZWRpdF9zY29yZSwgYW1vdW50LCBlbXBfZHVyYXRpb24sIGNoZWNraW5nX2Ftb3VudCwgYW5kIGFnZSBoYXZlIG1pc3NpbmcgdmFsdWVzLiBNaXNzaW5nIG51bWVyaWNhbCB2YWx1ZXMgY2FuIGJlIHJlc29sdmVkIGJ5IGltcHV0aW5nIHRoZSBtZWFuLiBNaXNzaW5nIGNhdGVnb3JpY2FsIHZhbHVlcyBjYW4gYmUgcmVzb2x2ZWQgYnkgaW1wdXRpbmcgdGhlIG1vZGUuDQoNCiMgRGlzdHJpYnV0aW9uIG9mIEluZGl2aWR1YWwgRmVhdHVyZXMNCg0KVGhpcyBzZWN0aW9uIHdpbGwgc2hvdyB0aGUgZGlzdHJpYnV0aW9uIG9mIGVhY2ggaW5kaXZpZHVhbCBmZWF0dXJlLiBTb21lIGZlYXR1cmVzIHdpbGwgaGF2ZSBtaXNzaW5nIHZhbHVlcyBhbmQgY2FuIGJlIHJlc29sdmVkIGJ5IGltcHV0aW5nIHRoZSBtZWFuIG9yIG1vZGUuDQoNClRoZSBiZWxvdyBmaWd1cmUgc2hvd3MgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgR2VuZGVyIHZhcmlhYmxlLiBUaGVyZSBhcmUgc2lnbmlmaWNhbnRseSBtb3JlIG1hbGVzIHRoYW4gZmVtYWxlcy4NCg0KYGBge3J9DQpnZ3Bsb3QoYmFuaywgYWVzKHggPSBHZW5kZXIpKSArIA0KICANCiAgZ2VvbV9iYXIoKSArDQogIGxhYnModGl0bGUgPSAiR2VuZGVyIikNCmBgYA0KDQpUaGUgYmVsb3cgZmlndXJlIHNob3dzIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIE1hcml0YWxfc3RhdHVzIHZhcmlhYmxlLiBNYXJyaWVkIGFuZCBzaW5nbGUgcGVvcGxlIGhhdmUgc2ltaWxhciBjb3VudHMuDQoNCmBgYHtyfQ0KZ2dwbG90KGJhbmssIGFlcyh4ID0gTWFyaXRhbF9zdGF0dXMpKSArIA0KICANCiAgZ2VvbV9iYXIoKSArDQogIGxhYnModGl0bGUgPSAiTWFyaXRhbF9zdGF0dXMiKQ0KYGBgDQoNClRoZSBiZWxvdyBmaWd1cmUgc2hvd3MgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgRW1wX3N0YXR1cyB2YXJpYWJsZS4gVGhlcmUgYXJlIHNpZ25pZmljYW50bHkgbW9yZSB1bmVtcGxveWVkIHRoYW4gZW1wbG95ZWQuDQoNCmBgYHtyfQ0KZ2dwbG90KGJhbmssIGFlcyh4ID0gRW1wX3N0YXR1cykpICsgDQogIA0KICBnZW9tX2JhcigpICsNCiAgbGFicyh0aXRsZSA9ICJFbXBfc3RhdHVzIikNCmBgYA0KDQoNClRoZSBiZWxvdyBmaWd1cmUgc2hvd3MgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgY2FyIGxvYW4gdmFyaWFibGUuIFRoZXJlIGFyZSBzaWduaWZpY2FudGx5IG1vcmUgdGhhdCBkbyBub3QgaGF2ZSBhIGNhciBsb2FuIHRoYW4gdGhvc2UgdGhhdCBkby4NCg0KYGBge3J9DQpnZ3Bsb3QoYmFuaywgYWVzKHggPSBDYXJfbG9hbikpICsgDQogIA0KICBnZW9tX2JhcigpICsNCiAgbGFicyh0aXRsZSA9ICJDYXJfbG9hbiIpDQpgYGANCg0KVGhlIGJlbG93IGZpZ3VyZSBzaG93cyB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBwZXJzb25hbCBsb2FuIHZhcmlhYmxlLiBUaG9zZSB0aGF0IGhhdmUgYSBwZXJzb25hbCBsb2FuIGFuZCB0aG9zZSB0aGF0IGRvIG5vdCBoYXZlIHNpbWlsYXIgY291bnRzLg0KDQpgYGB7cn0NCmdncGxvdChiYW5rLCBhZXMoeCA9IFBlcnNvbmFsX2xvYW4pKSArIA0KICANCiAgZ2VvbV9iYXIoKSArDQogIGxhYnModGl0bGUgPSAiUGVyc29uYWxfbG9hbiIpDQpgYGANCg0KVGhlIGJlbG93IGZpZ3VyZSBzaG93cyB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBlZHVjYXRpb24gbG9hbiB2YXJpYWJsZS4gVGhlcmUgYXJlIHNpZ25pZmljYW50bHkgbW9yZSB0aGF0IGRvIG5vdCBoYXZlIGFuIGVkdWNhdGlvbiBsb2FuIHRoYW4gdGhvc2UgdGhhdCBkby4NCg0KYGBge3J9DQpnZ3Bsb3QoYmFuaywgYWVzKHggPSBFZHVjYXRpb25fbG9hbikpICsgDQogIA0KICBnZW9tX2JhcigpICsNCiAgbGFicyh0aXRsZSA9ICJFZHVjYXRpb25fbG9hbiIpDQpgYGANCg0KVGhlIGJlbG93IGZpZ3VyZSBzaG93cyB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBob21lIGxvYW4gdmFyaWFibGUuIFRoZXJlIGFyZSBzaWduaWZpY2FudGx5IG1vcmUgdGhhdCBkbyBub3QgaGF2ZSBhIGhvbWUgbG9hbiB0aGFuIHRob3NlIHRoYXQgZG8uDQoNCmBgYHtyfQ0KZ2dwbG90KGJhbmssIGFlcyh4ID0gSG9tZV9sb2FuKSkgKyANCiAgDQogIGdlb21fYmFyKCkgKw0KICBsYWJzKHRpdGxlID0gIkhvbWVfbG9hbiIpDQpgYGANCg0KVGhlIGJlbG93IGZpZ3VyZSBzaG93cyB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBjcmVkaXQgc2NvcmUgdmFyaWFibGUuIFRoZXJlIGFyZSBubyBhbGFybWluZyB0cmVuZHMgb3V0c2lkZSBvZiBhIGNvdXBsZSBhbm9tYWxpZXMuDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBiYW5rLCBhZXMoeCA9IENyZWRpdF9zY29yZSkpICsgDQogIGdlb21fYm94cGxvdCgpICsgDQogIA0KICBsYWJzKHRpdGxlID0gIkNyZWRpdF9zY29yZSIpDQpgYGANCg0KVGhlIGJlbG93IGZpZ3VyZSBzaG93cyB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBjaGVja2luZyBhbW91bnQgdmFyaWFibGUuIFRoZXJlIGFyZSBubyBhbGFybWluZyB0cmVuZHMuDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBiYW5rLCBhZXMoeCA9IENoZWNraW5nX2Ftb3VudCkpICsgDQogIGdlb21fYm94cGxvdCgpICsgDQogIA0KICBsYWJzKHRpdGxlID0gIkNoZWNraW5nX2Ftb3VudCIpDQpgYGANCg0KVGhlIGJlbG93IGZpZ3VyZSBzaG93cyB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSB0ZXJtIHZhcmlhYmxlLiBUaGVyZSBhcmUgbm8gYWxhcm1pbmcgdHJlbmRzLg0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gYmFuaywgYWVzKHggPSBUZXJtKSkgKyANCiAgZ2VvbV9ib3hwbG90KCkgKyANCiAgDQogIGxhYnModGl0bGUgPSAiVGVybSIpDQoNCmBgYA0KDQpUaGUgYmVsb3cgZmlndXJlIHNob3dzIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIGFtb3VudCB2YXJpYWJsZS4gVGhlcmUgYXJlIG5vIGFsYXJtaW5nIHRyZW5kcy4NCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGJhbmssIGFlcyh4ID0gQW1vdW50KSkgKyANCiAgZ2VvbV9ib3hwbG90KCkgKyANCiAgDQogIGxhYnModGl0bGUgPSAiQW1vdW50IikNCmBgYA0KDQpUaGUgYmVsb3cgZmlndXJlIHNob3dzIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIFNhdmluZyBhbW91bnQgdmFyaWFibGUuIFRoZXJlIGFyZSBubyBhbGFybWluZyB0cmVuZHMuDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBiYW5rLCBhZXMoeCA9IFNhdmluZ19hbW91bnQpKSArIA0KICBnZW9tX2JveHBsb3QoKSArIA0KICANCiAgbGFicyh0aXRsZSA9ICJTYXZpbmcgYW1vdW50IikNCmBgYA0KDQpUaGUgYmVsb3cgZmlndXJlIHNob3dzIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIEVtcF9kdXJhdGlvbiB2YXJpYWJsZS4gVGhlcmUgYXJlIG5vIGFsYXJtaW5nIHRyZW5kcy4NCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGJhbmssIGFlcyh4ID0gRW1wX2R1cmF0aW9uKSkgKyANCiAgZ2VvbV9ib3hwbG90KCkgKyANCiAgDQogIGxhYnModGl0bGUgPSAiRW1wIGR1cmF0aW9uIikNCmBgYA0KDQpUaGUgYmVsb3cgZmlndXJlIHNob3dzIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIGFnZSB2YXJpYWJsZS4gVGhlcmUgYXJlIG5vIGFsYXJtaW5nIHRyZW5kcy4NCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGJhbmssIGFlcyh4ID0gQWdlKSkgKyANCiAgZ2VvbV9ib3hwbG90KCkgKyANCiAgDQogIGxhYnModGl0bGUgPSAiQWdlIikNCmBgYA0KDQpUaGUgYmVsb3cgZmlndXJlIHNob3dzIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIE5vX29mX2NyZWRpdF9hY2MgdmFyaWFibGUuIFRoaXMgdmFyaWFibGUgc2VlbXMgdG8gYmUgaGVhdmlseSBza2V3ZWQuDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBiYW5rLCBhZXMoeCA9IE5vX29mX2NyZWRpdF9hY2MpKSArIA0KICBnZW9tX2JveHBsb3QoKSArIA0KICANCiAgbGFicyh0aXRsZSA9ICJOb19vZl9jcmVkaXRfYWNjIikNCmBgYA0KDQojIE9uZSBDYXRlZ29yaWNhbCBGZWF0dXJlIGFuZCBPbmUgTnVtZXJpY2FsIGZlYXR1cmUgR3JhcGhzDQoNCkluIHRoaXMgc2VjdGlvbiwgd2Ugd2lsbCBzaG93IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBvbmUgY2F0ZWdvcmljYWwgZmVhdHVyZSBhbmQgb25lIG51bWVyaWNhbCBmZWF0dXJlLg0KDQpUaGUgYmVsb3cgZmlndXJlIHNob3dzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBjcmVkaXQgc2NvcmUgYW5kIGdlbmRlci4gQmFzZWQgb24gdGhlIGdyYXBoLCB0aGUgY3JlZGl0IHNjb3JlIHJhbmdlcyBsb29rIHRvIGJlIHNpbWlsYXIgYWNyb3NzIGJvdGggZ2VuZGVycy4gVGhlcmUgYXJlIHNvbWUgYW5vbWFsaWVzIGJ1dCBJIGRvIG5vdCBiZWxpZXZlIHRoYXQgdGhleSB3aWxsIGhhdmUgYSBzaWduaWZpY2FudCBlZmZlY3Qgb24gdGhlIGFuYWx5c2lzLiBUaGVyZSBhcmUgbWlzc2luZyB2YWx1ZXMgYnV0IHRoZXkgY2FuIGJlIHJlc29sdmVkIHVzaW5nIGltcHV0YXRpb24uDQoNCmBgYHtyfQ0KZ2dwbG90KGJhbmssIGFlcyh4PUNyZWRpdF9zY29yZSwgeT1HZW5kZXIsIGZpbGw9R2VuZGVyKSkgKw0KICBnZW9tX2JveHBsb3QoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpKw0KZ2d0aXRsZSgiQ3JlZGl0IFNjb3JlIGJ5IEdlbmRlciIpDQpgYGANCg0KVGhlIGJlbG93IGZpZ3VyZSBzaG93cyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gbG9hbiBhbW91bnQgYW5kIGdlbmRlci4gQmFzZWQgb24gdGhlIGdyYXBoLCB0aGUgbG9hbiBhbW91bnQgcmFuZ2VzIGxvb2sgdG8gYmUgc2ltaWxhciBhY3Jvc3MgYm90aCBnZW5kZXJzLiBUaGVyZSBhcmUgc29tZSBhbm9tYWxpZXMgYnV0IEkgZG8gbm90IGJlbGlldmUgdGhhdCB0aGV5IHdpbGwgaGF2ZSBhIHNpZ25pZmljYW50IGVmZmVjdCBvbiB0aGUgYW5hbHlzaXMuIFRoZXJlIGFyZSBtaXNzaW5nIHZhbHVlcyBidXQgdGhleSBjYW4gYmUgcmVzb2x2ZWQgdXNpbmcgaW1wdXRhdGlvbi4NCg0KYGBge3J9DQpnZ3Bsb3QoYmFuaywgYWVzKHg9QW1vdW50LCB5PUdlbmRlciwgZmlsbD1HZW5kZXIpKSArDQogIGdlb21fYm94cGxvdCgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikrDQpnZ3RpdGxlKCJBbW91bnQgYnkgR2VuZGVyIikNCmBgYA0KDQpUaGUgYmVsb3cgZmlndXJlIHNob3dzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBFbXBsb3ltZW50IGR1cmF0aW9uIGFuZCBnZW5kZXIuIEJhc2VkIG9uIHRoZSBncmFwaCwgaXQgc2VlbXMgbGlrZSBtYWxlcyBoYXZlIGEgbG9uZ2VyIGVtcGxveW1lbnQgZHVyYXRpb24gdGhhbiBmZW1hbGVzLiBUaGVyZSBhcmUgbWlzc2luZyB2YWx1ZXMgYnV0IHRoZXkgY2FuIGJlIHJlc29sdmVkIHVzaW5nIGltcHV0YXRpb24uDQoNCmBgYHtyfQ0KZ2dwbG90KGJhbmssIGFlcyh4PUVtcF9kdXJhdGlvbiwgeT1HZW5kZXIsIGZpbGw9R2VuZGVyKSkgKw0KICBnZW9tX2JveHBsb3QoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpKw0KZ2d0aXRsZSgiRW1wbG95bWVudCBkdXJhdGlvbiBieSBHZW5kZXIiKQ0KYGBgDQoNClRoZSBiZWxvdyBmaWd1cmUgc2hvd3MgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIEFnZSBhbmQgZ2VuZGVyLiBCYXNlZCBvbiB0aGUgZ3JhcGgsIHRoZSBBZ2UgcmFuZ2VzIGxvb2sgdG8gYmUgc2ltaWxhciBhY3Jvc3MgYm90aCBnZW5kZXJzLiBUaGVyZSBhcmUgc29tZSBhbm9tYWxpZXMgYnV0IEkgZG8gbm90IGJlbGlldmUgdGhhdCB0aGV5IHdpbGwgaGF2ZSBhIHNpZ25pZmljYW50IGVmZmVjdCBvbiB0aGUgYW5hbHlzaXMuIFRoZXJlIGFyZSBtaXNzaW5nIHZhbHVlcyBidXQgdGhleSBjYW4gYmUgcmVzb2x2ZWQgdXNpbmcgaW1wdXRhdGlvbi4NCg0KYGBge3J9DQpnZ3Bsb3QoYmFuaywgYWVzKHg9QWdlLCB5PUdlbmRlciwgZmlsbD1HZW5kZXIpKSArDQogIGdlb21fYm94cGxvdCgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikrDQpnZ3RpdGxlKCJBZ2UgYnkgR2VuZGVyIikNCmBgYA0KDQpUaGUgYmVsb3cgZmlndXJlIHNob3dzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBtYXJpdGFsIHN0YXR1cyBhbmQgY3JlZGl0IHNjb3JlLiBCYXNlZCBvbiB0aGUgZ3JhcGgsIHRoZSBjcmVkaXQgc2NvcmUgcmFuZ2VzIGxvb2sgdG8gYmUgc2ltaWxhciBhY3Jvc3MgYm90aCBzaW5nbGUgYW5kIG1hcnJpZWQgcGVvcGxlLiBUaGVyZSBhcmUgc29tZSBhbm9tYWxpZXMgYnV0IEkgZG8gbm90IGJlbGlldmUgdGhhdCB0aGV5IHdpbGwgaGF2ZSBhIHNpZ25pZmljYW50IGVmZmVjdCBvbiB0aGUgYW5hbHlzaXMuIFRoZXJlIGFyZSBtaXNzaW5nIHZhbHVlcyBidXQgdGhleSBjYW4gYmUgcmVzb2x2ZWQgdXNpbmcgaW1wdXRhdGlvbi4NCg0KYGBge3J9DQpnZ3Bsb3QoYmFuaywgYWVzKHg9Q3JlZGl0X3Njb3JlLCB5PU1hcml0YWxfc3RhdHVzLCBmaWxsPU1hcml0YWxfc3RhdHVzKSkgKw0KICBnZW9tX2JveHBsb3QoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpKw0KZ2d0aXRsZSgiQ3JlZGl0IFNjb3JlIGJ5IE1hcml0YWwgc3RhdHVzIikNCmBgYA0KDQpUaGUgYmVsb3cgZmlndXJlIHNob3dzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBsb2FuIGFtb3VudCBhbmQgbWFyaXRhbCBzdGF0dXMuIEJhc2VkIG9uIHRoZSBncmFwaCwgdGhlIGxvYW4gYW1vdW50IHJhbmdlcyBsb29rIHRvIGJlIHNpbWlsYXIgYWNyb3NzIGJvdGggbWFyaXRhbCBzdGF0dXNlcy4gVGhlcmUgYXJlIHNvbWUgYW5vbWFsaWVzIGJ1dCBJIGRvIG5vdCBiZWxpZXZlIHRoYXQgdGhleSB3aWxsIGhhdmUgYSBzaWduaWZpY2FudCBlZmZlY3Qgb24gdGhlIGFuYWx5c2lzLiBUaGVyZSBhcmUgbWlzc2luZyB2YWx1ZXMgYnV0IHRoZXkgY2FuIGJlIHJlc29sdmVkIHVzaW5nIGltcHV0YXRpb24uDQoNCmBgYHtyfQ0KZ2dwbG90KGJhbmssIGFlcyh4PUFtb3VudCwgeT1NYXJpdGFsX3N0YXR1cywgZmlsbD1NYXJpdGFsX3N0YXR1cykpICsNCiAgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSsNCmdndGl0bGUoIkFtb3VudCBieSBNYXJpdGFsIHN0YXR1cyIpDQpgYGANCg0KVGhlIGJlbG93IGZpZ3VyZSBzaG93cyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gbWFyaXRhbCBzdGF0dXMgYW5kIGVtcGxveW1lbnQgZHVyYXRpb24uIEJhc2VkIG9uIHRoZSBncmFwaCwgaXQgc2VlbXMgbGlrZSBtYXJyaWVkIHBlb3BsZSBoYXZlIGxvbmdlciBlbXBsb3ltZW50IGR1cmF0aW9uIHRoYW4gc2luZ2xlIHBlb3BsZS4gVGhlcmUgYXJlIG1pc3NpbmcgdmFsdWVzIGJ1dCB0aGV5IGNhbiBiZSByZXNvbHZlZCB1c2luZyBpbXB1dGF0aW9uLg0KDQpgYGB7cn0NCmdncGxvdChiYW5rLCBhZXMoeD1FbXBfZHVyYXRpb24sIHk9TWFyaXRhbF9zdGF0dXMsIGZpbGw9TWFyaXRhbF9zdGF0dXMpKSArDQogIGdlb21fYm94cGxvdCgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikrDQpnZ3RpdGxlKCJFbXBsb3ltZW50IGR1cmF0aW9uIGJ5IE1hcml0YWwgc3RhdHVzIikNCmBgYA0KDQpUaGUgYmVsb3cgZmlndXJlIHNob3dzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBBZ2UgYW5kIG1hcml0YWwgc3RhdHVzLiBCYXNlZCBvbiB0aGUgZ3JhcGgsIHRoZSBBZ2UgcmFuZ2VzIGxvb2sgdG8gYmUgc2ltaWxhciBhY3Jvc3MgYm90aCBtYXJpdGFsIHN0YXR1c2VzLiBUaGVyZSBhcmUgc29tZSBhbm9tYWxpZXMgYnV0IEkgZG8gbm90IGJlbGlldmUgdGhhdCB0aGV5IHdpbGwgaGF2ZSBhIHNpZ25pZmljYW50IGVmZmVjdCBvbiB0aGUgYW5hbHlzaXMuIFRoZXJlIGFyZSBtaXNzaW5nIHZhbHVlcyBidXQgdGhleSBjYW4gYmUgcmVzb2x2ZWQgdXNpbmcgaW1wdXRhdGlvbi4NCg0KYGBge3J9DQpnZ3Bsb3QoYmFuaywgYWVzKHg9QWdlLCB5PU1hcml0YWxfc3RhdHVzLCBmaWxsPU1hcml0YWxfc3RhdHVzKSkgKw0KICBnZW9tX2JveHBsb3QoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpKw0KZ2d0aXRsZSgiYWdlIGJ5IE1hcml0YWwgc3RhdHVzIikNCmBgYA0KDQpUaGUgYmVsb3cgZmlndXJlIHNob3dzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBjcmVkaXQgc2NvcmUgYW5kIGVtcGxveW1lbnQgc3RhdHVzLiBCYXNlZCBvbiB0aGUgZ3JhcGgsIHRoZSBjcmVkaXQgc2NvcmUgcmFuZ2VzIGxvb2sgdG8gYmUgc2ltaWxhciBhY3Jvc3MgYm90aCBlbXBsb3llZCBhbmQgdW5lbXBsb3llZCBwZW9wbGUuIFRoZXJlIHNlZW1zIHRvIGJlIG1vcmUgYW5vbWFsaWVzIGZvciB1bmVtcGxveWVkIHBlb3BsZSBidXQgSSBkbyBub3QgYmVsaWV2ZSB0aGF0IHRoZXkgd2lsbCBoYXZlIGEgc2lnbmlmaWNhbnQgZWZmZWN0IG9uIHRoZSBhbmFseXNpcy4gVGhlcmUgYXJlIG1pc3NpbmcgdmFsdWVzIGJ1dCB0aGV5IGNhbiBiZSByZXNvbHZlZCB1c2luZyBpbXB1dGF0aW9uLg0KDQpgYGB7cn0NCmdncGxvdChiYW5rLCBhZXMoeD1DcmVkaXRfc2NvcmUsIHk9RW1wX3N0YXR1cywgZmlsbD1FbXBfc3RhdHVzKSkgKw0KICBnZW9tX2JveHBsb3QoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpKw0KZ2d0aXRsZSgiQ3JlZGl0IFNjb3JlIGJ5IEVtcGxveW1lbnQgc3RhdHVzIikNCmBgYA0KDQpUaGUgYmVsb3cgZmlndXJlIHNob3dzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBsb2FuIGFtb3VudCBhbmQgZW1wbG95bWVudCBzdGF0dXMuIEJhc2VkIG9uIHRoZSBncmFwaCwgdGhlIGxvYW4gYW1vdW50IHJhbmdlcyBsb29rIHRvIGJlIHNpbWlsYXIgYWNyb3NzIGJvdGggZW1wbG95ZWQvdW5lbXBsb3llZC4gQWdhaW4gdGhlcmUgc2VlbXMgdG8gYmUgbW9yZSBhbm9tYWxpZXMgZm9yIHVuZW1wbG95ZWQgcGVvcGxlIHRoYW4gZW1wbG95ZWQuIFRoZXJlIGFyZSBtaXNzaW5nIHZhbHVlcyBidXQgdGhleSBjYW4gYmUgcmVzb2x2ZWQgdXNpbmcgaW1wdXRhdGlvbi4NCg0KYGBge3J9DQpnZ3Bsb3QoYmFuaywgYWVzKHg9QW1vdW50LCB5PUVtcF9zdGF0dXMsIGZpbGw9RW1wX3N0YXR1cykpICsNCiAgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSsNCmdndGl0bGUoIkFtb3VudCBieSBFbXBsb3ltZW50IHN0YXR1cyIpDQpgYGANCg0KVGhlIGJlbG93IGZpZ3VyZSBzaG93cyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gZW1wbG95bWVudCBkdXJhdGlvbiBhbmQgZW1wbG95bWVudCBzdGF0dXMuIEJhc2VkIG9uIHRoZSBncmFwaCwgaXQgc2VlbXMgbGlrZSB1bmVtcGxveWVkIHBlb3BsZSBoYXZlIGxvbmdlciBhbmQgbW9yZSB2YXJpZWQgZW1wbG95bWVudCBkdXJhdGlvbiB0aGFuIGVtcGxveWVkIHBlb3BsZS4gVGhlcmUgYXJlIG1pc3NpbmcgdmFsdWVzIGJ1dCB0aGV5IGNhbiBiZSByZXNvbHZlZCB1c2luZyBpbXB1dGF0aW9uLg0KDQpgYGB7cn0NCmdncGxvdChiYW5rLCBhZXMoeD1FbXBfZHVyYXRpb24sIHk9RW1wX3N0YXR1cywgZmlsbD1FbXBfc3RhdHVzKSkgKw0KICBnZW9tX2JveHBsb3QoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpKw0KZ2d0aXRsZSgiRW1wbG95bWVudCBkdXJhdGlvbiBieSBlbXBsb3ltZW50IHN0YXR1cyIpDQpgYGANCg0KVGhlIGJlbG93IGZpZ3VyZSBzaG93cyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gQWdlIGFuZCBlbXBsb3ltZW50IHN0YXR1cy4gQmFzZWQgb24gdGhlIGdyYXBoLCB0aGUgQWdlIHJhbmdlcyBsb29rIHRvIGJlIHNpbWlsYXIgYWNyb3NzIGJvdGggc3RhdHVzZXMuIFRoZXJlIGFyZSBzb21lIGFub21hbGllcyBidXQgSSBkbyBub3QgYmVsaWV2ZSB0aGF0IHRoZXkgd2lsbCBoYXZlIGEgc2lnbmlmaWNhbnQgZWZmZWN0IG9uIHRoZSBhbmFseXNpcy4gVGhlcmUgYXJlIG1pc3NpbmcgdmFsdWVzIGJ1dCB0aGV5IGNhbiBiZSByZXNvbHZlZCB1c2luZyBpbXB1dGF0aW9uLg0KDQpgYGB7cn0NCmdncGxvdChiYW5rLCBhZXMoeD1BZ2UsIHk9RW1wX3N0YXR1cywgZmlsbD1FbXBfc3RhdHVzKSkgKw0KICBnZW9tX2JveHBsb3QoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpKw0KZ2d0aXRsZSgiYWdlIGJ5IGVtcGxveW1lbnQgc3RhdHVzIikNCmBgYA0KDQpUaGUgYmVsb3cgZmlndXJlIHNob3dzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBBZ2UgYW5kIGNhciBsb2FuLiBCYXNlZCBvbiB0aGUgZ3JhcGgsIHRoZSBBZ2UgcmFuZ2VzIGxvb2sgdG8gYmUgc2ltaWxhciBhY3Jvc3MgYm90aCB0aG9zZSB3aG8gb3duIGEgY2FyIGxvYW4gYW5kIHRob3NlIHdobyBkbyBub3QuDQoNCmBgYHtyfQ0KIyBjb252ZXJ0IGNhciwgaG9tZSwgcGVyc29uYWwsIGFuZCBlZHVjYXRpb24gbG9hbnMgaW50byBjYXRlZ29yaWNhbCB0byB1c2UgZm9yIEVEQSBwdXJwb3Nlcw0KIGJhbmskQ2FyX2xvYW4gPC0gYXMuZmFjdG9yKGJhbmskQ2FyX2xvYW4pDQogYmFuayRQZXJzb25hbF9sb2FuIDwtIGFzLmZhY3RvcihiYW5rJFBlcnNvbmFsX2xvYW4pDQogYmFuayRIb21lX2xvYW4gPC0gYXMuZmFjdG9yKGJhbmskSG9tZV9sb2FuKQ0KIGJhbmskRWR1Y2F0aW9uX2xvYW4gPC0gYXMuZmFjdG9yKGJhbmskRWR1Y2F0aW9uX2xvYW4pDQogDQpnZ3Bsb3QoYmFuaywgYWVzKHg9QWdlLCB5PUNhcl9sb2FuLCBmaWxsPUNhcl9sb2FuKSkgKw0KICBnZW9tX2JveHBsb3QoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpKw0KZ2d0aXRsZSgiYWdlIGJ5IGNhciBsb2FuIikNCmBgYA0KDQpUaGUgYmVsb3cgZmlndXJlIHNob3dzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBBZ2UgYW5kIHBlcnNvbmFsIGxvYW4uIEJhc2VkIG9uIHRoZSBncmFwaCwgdGhlIEFnZSByYW5nZXMgbG9vayB0byBiZSBzaW1pbGFyIGFjcm9zcyBhbGwgdGhvc2UgdGhhdCBoYXZlIGEgcGVyc29uYWwgbG9hbiBvciBub3QuDQoNCmBgYHtyfQ0KZ2dwbG90KGJhbmssIGFlcyh4PUFnZSwgeT1QZXJzb25hbF9sb2FuLCBmaWxsPVBlcnNvbmFsX2xvYW4pKSArDQogIGdlb21fYm94cGxvdCgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikrDQpnZ3RpdGxlKCJhZ2UgYnkgcGVyc29uYWxfbG9hbiIpDQpgYGANCg0KVGhlIGJlbG93IGZpZ3VyZSBzaG93cyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gQWdlIGFuZCBob21lIGxvYW4uIEJhc2VkIG9uIHRoZSBncmFwaCwgdGhlIEFnZSByYW5nZXMgbG9vayB0byBiZSBzaW1pbGFyIGFjcm9zcyBhbGwgdGhvc2UgdGhhdCBoYXZlIGEgaG9tZSBsb2FuIG9yIG5vdC4NCg0KYGBge3J9DQpnZ3Bsb3QoYmFuaywgYWVzKHg9QWdlLCB5PUhvbWVfbG9hbiwgZmlsbD1Ib21lX2xvYW4pKSArDQogIGdlb21fYm94cGxvdCgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikrDQpnZ3RpdGxlKCJhZ2UgYnkgaG9tZV9sb2FuIikNCmBgYA0KDQpUaGUgYmVsb3cgZmlndXJlIHNob3dzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBBZ2UgYW5kIGVkdWNhdGlvbiBsb2FuLiBCYXNlZCBvbiB0aGUgZ3JhcGgsIGl0IHNlZW1zIGxpa2UgeW91bmdlciBwZW9wbGUgaGF2ZSBhbiBlZHVjYXRpb24gbG9hbiBhbmQgb2xkZXIgcGVvcGxlIGRvIG5vdC4NCmBgYHtyfQ0KZ2dwbG90KGJhbmssIGFlcyh4PUFnZSwgeT1FZHVjYXRpb25fbG9hbiwgZmlsbD1FZHVjYXRpb25fbG9hbikpICsNCiAgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSsNCmdndGl0bGUoImFnZSBieSBlZHVjYXRpb24gbG9hbiIpDQpgYGANCg0KIyBUd28gbnVtZXJpY2FsIGZlYXR1cmUgdmFyaWFibGVzIGdyYXBocw0KDQpOZXh0LCB3ZSB3aWxsIGV4YW1pbmUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHR3byBudW1lcmljYWwgZmVhdHVyZXMuDQoNClRoZSBiZWxvdyBncmFwaCBzaG93cyBlbXBsb3ltZW50IGR1cmF0aW9uIGFuZCBjcmVkaXQgc2NvcmUuIEJhc2VkIG9uIHRoZSBncmFwaCwgaXQgc2VlbXMgbGlrZSByZWdhcmRsZXNzIG9mIHRoZSBlbXBsb3ltZW50IGR1cmF0aW9uLCB0aGUgbWFqb3JpdHkgb2YgdGhlIGNyZWRpdCBzY29yZXMgc2VlbSB0byBmYWxsIGluIHRoZSA3MDAtOTAwIHJhbmdlLg0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gYmFuaywgYWVzKHggPSBDcmVkaXRfc2NvcmUsIHkgPSBFbXBfZHVyYXRpb24pKSArDQogIGdlb21fcG9pbnQoKSArIA0KICBnZ3RpdGxlKCJFbXBsb3ltZW50IER1cmF0aW9uIHZzIENyZWRpdCBTY29yZSIpDQpgYGANCg0KVGhlIGJlbG93IGdyYXBoIHNob3dzIGVtcGxveW1lbnQgZHVyYXRpb24gYW5kIGxvYW4gYW1vdW50LiBUaGVyZSBkb2VzIG5vdCBzZWVtIHRvIGJlIGFueSBwYXR0ZXJucyBiYXNlZCBvbiB0aGlzIGdyYXBoLg0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gYmFuaywgYWVzKHggPSBBbW91bnQsIHkgPSBFbXBfZHVyYXRpb24pKSArDQogIGdlb21fcG9pbnQoKSArIA0KICBnZ3RpdGxlKCJFbXBsb3ltZW50IER1cmF0aW9uIHZzIExvYW4gQW1vdW50IikNCmBgYA0KDQpUaGUgYmVsb3cgZ3JhcGggc2hvd3MgZW1wbG95bWVudCBkdXJhdGlvbiBhbmQgYWdlLiBUaGVyZSBkb2VzIG5vdCBzZWVtIHRvIGJlIGFueSBwYXR0ZXJucyBiYXNlZCBvbiB0aGlzIGdyYXBoLg0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gYmFuaywgYWVzKHggPSBBZ2UsIHkgPSBFbXBfZHVyYXRpb24pKSArDQogIGdlb21fcG9pbnQoKSArIA0KICBnZ3RpdGxlKCJFbXBsb3ltZW50IER1cmF0aW9uIHZzIEFnZSIpDQpgYGANCg0KVGhlIGJlbG93IGdyYXBoIHNob3dzIGFnZSBhbmQgQ3JlZGl0IHNjb3JlLiBBZ2FpbiwgaXQgc2VlbXMgbGlrZSByZWdhcmRsZXNzIG9mIGFnZSwgbW9zdCBvZiB0aGUgY3JlZGl0IHNjb3JlcyBzZWVtIHRvIGZhbGwgaW4gdGhhdCA3MDAtOTAwIHJhbmdlLg0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gYmFuaywgYWVzKHggPSBBZ2UsIHkgPSBDcmVkaXRfc2NvcmUpKSArDQogIGdlb21fcG9pbnQoKSArIA0KICBnZ3RpdGxlKCJBZ2UgdnMgY3JlZGl0IHNjb3JlIikNCmBgYA0KDQpUaGUgYmVsb3cgZ3JhcGggc2hvd3MgY2hlY2tpbmcgYW1vdW50IGFuZCBzYXZpbmcgYW1vdW50LiBUaGVyZSBkb2VzIG5vdCBzZWVtIHRvIGJlIGFueSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZXNlIHR3byB2YXJpYWJsZXMuDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBiYW5rLCBhZXMoeCA9IENoZWNraW5nX2Ftb3VudCwgeSA9IFNhdmluZ19hbW91bnQpKSArDQogIGdlb21fcG9pbnQoKSArIA0KICBnZ3RpdGxlKCJDaGVja2luZyBhbW91bnQgdnMgc2F2aW5ncyBBbW91bnQiKQ0KYGBgDQoNClRoZSBiZWxvdyBncmFwaCBzaG93cyBhZ2UgYW5kIGxvYW4gYW1vdW50LiBJdCBzZWVtcyBsaWtlIHJlZ2FyZGxlc3Mgb2YgYWdlLCBtb3N0IG9mIHRoZSBsb2FuIGFtb3VudHMgc2VlbSB0byBmYWxsIGluIGEgY2VydGFpbiByYW5nZS4NCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGJhbmssIGFlcyh4ID0gQWdlLCB5ID0gQW1vdW50KSkgKw0KICBnZW9tX3BvaW50KCkgKyANCiAgZ2d0aXRsZSgiYWdlIHZzIExvYW4gQW1vdW50IikNCmBgYA0KDQpUaGUgYmVsb3cgZ3JhcGggc2hvd3MgY3JlZGl0IHNjb3JlIGFuZCBsb2FuIGFtb3VudC4gSXQgc2VlbXMgbGlrZSBtb3N0IG9mIHRoZSBwb2ludHMgYXJlIGNsdW1wZWQgdG9nZXRoZXIuDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBiYW5rLCBhZXMoeCA9IENyZWRpdF9zY29yZSwgeSA9IEFtb3VudCkpICsNCiAgZ2VvbV9wb2ludCgpICsgDQogIGdndGl0bGUoImNyZWRpdCBzY29yZSB2cyBMb2FuIEFtb3VudCIpDQpgYGANCg0KDQojIFR3byBjYXRlZ29yaWNhbCBmZWF0dXJlIHZhcmlhYmxlcyBncmFwaHMNCg0KVGhpcyBzZWN0aW9uIHNob3dzIHRoZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gdHdvIGNhdGVnb3JpY2FsIGZlYXR1cmVzLg0KDQpUaGUgYmVsb3cgZ3JhcGggc2hvd3MgR2VuZGVyIGFuZCBFbXBsb3ltZW50IHN0YXR1cy4gSXQgc2VlbXMgbGlrZSB0aGUgYW1vdW50IG9mIGVtcGxveWVkIGFuZCB1bmVtcGxveWVkIGZlbWFsZXMgYXJlIHNpbWlsYXIgYnV0IHRoZXJlIGFyZSBzaWduaWZpY2FudGx5IG1vcmUgdW5lbXBsb3llZCBtYWxlcyB0aGFuIGVtcGxveWVkLg0KDQpgYGB7cn0NCmdncGxvdChiYW5rLCBhZXMoR2VuZGVyLCAuLmNvdW50Li4pKSArIGdlb21fYmFyKGFlcyhmaWxsID0gRW1wX3N0YXR1cyksIHBvc2l0aW9uID0gImRvZGdlIikrZ2d0aXRsZSgiZ2VuZGVyIHZzIGVtcGxveW1lbnQgc3RhdHVzIikNCmBgYA0KDQpUaGUgYmVsb3cgZ3JhcGggc2hvd3MgR2VuZGVyIGFuZCBtYXJpdGFsIHN0YXR1cy4gSXQgc2VlbXMgbGlrZSBhbGwgZmVtYWxlcyBhcmUgc2luZ2xlIGFuZCB0aGVyZSBhcmUgc2lnbmlmaWNhbnRseSBtb3JlIG1hcnJpZWQgbWFsZXMgdGhhbiBzaW5nbGUuDQoNCmBgYHtyfQ0KZ2dwbG90KGJhbmssIGFlcyhHZW5kZXIsIC4uY291bnQuLikpICsgZ2VvbV9iYXIoYWVzKGZpbGwgPSBNYXJpdGFsX3N0YXR1cyksIHBvc2l0aW9uID0gImRvZGdlIikrZ2d0aXRsZSgiZ2VuZGVyIHZzIG1hcml0YWwgc3RhdHVzIikNCmBgYA0KDQpUaGUgYmVsb3cgZ3JhcGggc2hvd3MgZW1wbG95bWVudCBzdGF0dXMgYW5kIG1hcml0YWwgc3RhdHVzLiBJdCBzZWVtcyBsaWtlIHRoZSBhbW91bnQgb2YgZW1wbG95ZWQgYW5kIHVuZW1wbG95ZWQgcGVvcGxlIGFyZSByZWxhdGl2ZWx5IHNpbWlsYXIgYnV0IGZvciBtYXJyaWVkIHBlb3BsZSwgdGhlcmUgYXJlIHNpZ25pZmljYW50bHkgbW9yZSB3aG8gYXJlIHVuZW1wbG95ZWQuDQoNCmBgYHtyfQ0KZ2dwbG90KGJhbmssIGFlcyhNYXJpdGFsX3N0YXR1cywgLi5jb3VudC4uKSkgKyBnZW9tX2JhcihhZXMoZmlsbCA9IEVtcF9zdGF0dXMpLCBwb3NpdGlvbiA9ICJkb2RnZSIpK2dndGl0bGUoIm1hcml0YWwgc3RhdHVzIHZzIGVucGxveW1lbnQgc3RhdHVzIikNCmBgYA0KDQpUaGUgYmVsb3cgZ3JhcGggc2hvd3MgZ2VuZGVyIGFuZCBjYXIgbG9hbi4gSXQgc2VlbXMgbGlrZSBmb3IgYm90aCBtYWxlcyBhbmQgZmVtYWxlcywgdGhlcmUgYXJlIHNpZ25pZmljYW50bHkgbW9yZSB0aGF0IGRvIG5vdCBoYXZlIGNhciBsb2FucyB0aGFuIHRob3NlIHRoYXQgZG8uDQoNCmBgYHtyfQ0KZ2dwbG90KGJhbmssIGFlcyhHZW5kZXIsIC4uY291bnQuLikpICsgZ2VvbV9iYXIoYWVzKGZpbGwgPSBDYXJfbG9hbiksIHBvc2l0aW9uID0gImRvZGdlIikrZ2d0aXRsZSgiZ2VuZGVyIHZzIGNhciBsb2FuIikNCmBgYA0KDQpUaGUgYmVsb3cgZ3JhcGggc2hvd3MgZ2VuZGVyIGFuZCBlZHVjYXRpb24gbG9hbi4gSXQgc2VlbXMgbGlrZSBmb3IgYm90aCBtYWxlcyBhbmQgZmVtYWxlcywgdGhlcmUgYXJlIHNpZ25pZmljYW50bHkgbW9yZSB0aGF0IGRvIG5vdCBoYXZlIGVkdWNhdGlvbiBsb2FucyB0aGFuIHRob3NlIHRoYXQgZG8uDQoNCmBgYHtyfQ0KZ2dwbG90KGJhbmssIGFlcyhHZW5kZXIsIC4uY291bnQuLikpICsgZ2VvbV9iYXIoYWVzKGZpbGwgPSBFZHVjYXRpb25fbG9hbiksIHBvc2l0aW9uID0gImRvZGdlIikrZ2d0aXRsZSgiR2VuZGVyIHZzIGVkdWNhdGlvbiBMb2FuIikNCmBgYA0KDQpUaGUgYmVsb3cgZ3JhcGggc2hvd3MgZ2VuZGVyIGFuZCBwZXJzb25hbCBsb2FuLiBJdCBzZWVtcyBsaWtlIGZvciBib3RoIG1hbGVzIGFuZCBmZW1hbGVzLCB0aGUgYW1vdW50cyB0aGF0IHdobyBoYXZlIHBlcnNvbmFsIGxvYW5zIGFuZCB0aG9zZSB0aGF0IGRvIG5vdCBhcmUgcmVsYXRpdmVseSBzaW1pbGFyLg0KDQpgYGB7cn0NCmdncGxvdChiYW5rLCBhZXMoR2VuZGVyLCAuLmNvdW50Li4pKSArIGdlb21fYmFyKGFlcyhmaWxsID0gUGVyc29uYWxfbG9hbiksIHBvc2l0aW9uID0gImRvZGdlIikrZ2d0aXRsZSgiR2VuZGVyIHZzIHBlcnNvbmFsIExvYW4iKQ0KYGBgDQoNClRoZSBiZWxvdyBncmFwaCBzaG93cyBnZW5kZXIgYW5kIGhvbWUgbG9hbi4gSXQgc2VlbXMgbGlrZSBmb3IgYm90aCBtYWxlcyBhbmQgZmVtYWxlcywgdGhlcmUgYXJlIHNpZ25pZmljYW50bHkgbW9yZSB0aGF0IGRvIG5vdCBoYXZlIGhvbWUgbG9hbnMgdGhhbiB0aG9zZSB0aGF0IGRvLg0KDQpgYGB7cn0NCmdncGxvdChiYW5rLCBhZXMoR2VuZGVyLCAuLmNvdW50Li4pKSArIGdlb21fYmFyKGFlcyhmaWxsID0gSG9tZV9sb2FuKSwgcG9zaXRpb24gPSAiZG9kZ2UiKStnZ3RpdGxlKCJHZW5kZXIgdnMgaG9tZSBMb2FuIikNCg0KYGBgDQo=