Introduction
This is our first lab when we are considering 2 dimensions and
instead of calculating univariate statistics by groups (or factors) of
other variable - we will measure their common relationships based on
co-variance and correlation coefficients.
*Please be very careful when choosing the measure of correlation! In
case of different measurument scales we have to recode one of the
variables into weaker scale.
It would be nice to add some additional plots in the background. Feel
free to add your own sections and use external packages.
Data
This time we are going to use a typical credit scoring data with
predefined “default” variables and personal demografic and income data.
Please take a look closer at headers and descriptions of each
variable.
Scatterplots
First let’s visualize our quantitative relationships using
scatterplots.

You can also normalize the skewed distribution of incomes using
log:

We can add an estimated linear regression line:
## `geom_smooth()` using formula = 'y ~ x'

Scatterplots by groups
We can finally see if there any differences between risk status:
## `geom_smooth()` using formula = 'y ~ x'

We can also see more closely if there any differences between those
two distributions adding their estimated density plots:
## Instalowanie pakietu w 'C:/Users/magda/AppData/Local/R/win-library/4.3'
## (ponieważ 'lib' nie jest określony)
## pakiet 'ggExtra' został pomyślnie rozpakowany oraz sumy MD5 zostały sprawdzone
##
## Pobrane pakiety binarne są w
## C:\Users\magda\AppData\Local\Temp\Rtmp23SdA1\downloaded_packages
## Warning: pakiet 'ggExtra' został zbudowany w wersji R 4.3.3

We can also put those plots together:

Scatterplots with density curves
We can also see more closely if there any differences between those
two distributions adding their estimated density plots:

Correlation coefficients - Pearson’s linear correlation
Ok, let’s move to some calculations. In R, we can use the cor()
function. It takes three arguments and the method: cor(x, y, method) For
2 quantitative data, with all assumptions met, we can calculate simple
Pearson’s coefficient of linear correlation:
## [1] "Pearson's linear correlation: 0.574346033083121"
Ok, what about the percentage of the explained variability?
## [1] "Percentage of the explained variability: 32.9873365718318 %"
So as we can see almost 32,99% of total log of incomes’ variability
is explained by differences in age. The rest (67,1%) is probably
explained by other factors.
Partial and semipartial correlation
The partial and semi-partial (also known as part) correlations are
used to express the specific portion of variance explained by
eliminating the effect of other variables when assessing the correlation
between two variables.
Partial correlation holds constant one variable when computing the
relations to others. Suppose we want to know the correlation between X
and Y holding Z constant for both X and Y. That would be the partial
correlation between X and Y controlling for Z.
Semipartial correlation holds Z constant for either X or Y, but not
both, so if we wanted to control X for Z, we could compute the
semipartial correlation between X and Y holding Z constant for X.
Suppose we want to know the correlation between the log of income and
age controlling for years of employment. How highly correlated are these
after controlling for tenure?
**There can be more than one control variable.
## [1] "Partial correlation: 0.319426338025541"
How can we interpret the obtained partial correlation coefficient?
What is the difference between that one and the semi-partial
coefficient:
## [1] "Semi-partial correlation: 0.22037110188406"
Partial correlation coefficient calculated for the log of income and
age controlling for years of employment equals 0,319. It means that
after including influence of years of employment there exist positive
and moderate relationship between age and logarithm of income. So after
removing the effects of years of employment, these two are still
moderately correlated.
On the other hand, the semi-partial correlation between log income
and age, controlling for years of employment for log income equals
0,220. Therefore after taking into account the effect of years of
employment on the logarithm of income, there is a weaker but still
positive relationship between age and the logarithm of income. In other
words, age is moderately correlated with log income, after removing the
effect of years of employment on log income only.
Finally, comparing these two coefficients we can see that controlling
for years of employment has a greater impact on logarithm of income than
on age, which is visible in the lower value of the semi-partial
correlation coefficient compared to the partial correlation.
Rank correlation
For 2 different scales - like for example this pair of variables:
income vs. education levels - we cannot use Pearson’s coefficient. The
only possibility is to rank also incomes… and lose some more detailed
information about them.
First, let’s see boxplots of income by education levels.


In these box-plots we see that people with the highest education
generally earn the most. In case of lower education levels the
difference between them isn’t as significant.
Now, let’s see Kendal’s coefficient of rank correlation (robust for
ties).
## [1] "Kendall's rank correlation coefficient: 0.158"
Kendall’s rank correlation coefficient is in range -1 to 1, where 1
inform us about perfect positive correlation, -1 about perfect negative
correlation and 0 about no correlation. Value 0,158 suggest weak
correlation between income and age.
Point-biserial correlation
Let’s try to verify if there is a significant relationship between
incomes and risk status. First, let’s take a look at the boxplot:


If you would like to compare 1 quantitative variable (income) and 1
dychotomous variable (default status - binary), then you can use
point-biserial coefficient:
## [1] "Point-biserial correlation coefficient (income): 0.071"
## [1] "Point-biserial correlation coefficient (log income): 0.135"
We can see that this correlation is positive and weak, since the
absolute value is below 0,2.
Nonlinear correlation - eta coefficient
If you would like to check if there are any nonlinearities between 2
variables, the only possibility (beside transformations and linear
analysis) is to calculate “eta” coefficient and compare it with the
Pearson’s linear coefficient.
## [1] "Eta coefficient (income ~ default): 0.0709696566192232"
## [1] "Eta coefficient (log income ~ default): 0.135225798931301"
The values of eta coefficient and Pearsons coefficient are the same,
so there is no nonlinear correlation.
Correlation matrix
We can also prepare the correlation matrix for all quantitative
variables stored in our data frame.
We can use ggcorr() function:
## Warning in ggcorr(bank, method = c("everything", "pearson"), label = TRUE):
## data in column(s) 'ed', 'default', 'def', 'educ' are not numeric and were
## ignored

As you can see - the default correlation matrix is not the best idea
for all measurement scales (including binary variable “default”).
That’s why now we can perform our bivariate analysis with ggpair with
grouping.
Correlation matrix with scatterplots
Here is what we are about to calculate: - The correlation matrix
between age, log_income, employ, address, debtinc, creddebt, and othdebt
variable grouped by whether the person has a default status or not. -
Plot the distribution of each variable by group - Display the scatter
plot with the trend by group
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Qualitative data
In case of two variables measured on nominal or ordinal&nominal
scale - we are forced to organize so called “contingency” table with
frequencies and calculate some kind of the correlation coefficient based
on them. This is so called “contingency analysis”.
Let’s consider one example based on our data: verify, if there is any
significant correlation between education level and credit risk.
bank$ed <- as.factor(bank$ed)
bank$default <- as.factor(bank$default)
contingency_table <- table(bank$ed, bank$default)
print(contingency_table)
##
## 0 1
## 1 293 79
## 2 139 59
## 3 57 30
## 4 24 14
## 5 4 1
chisq.test(contingency_table)
## Warning in chisq.test(contingency_table): Aproksymacja chi-kwadrat może być
## niepoprawna
##
## Pearson's Chi-squared test
##
## data: contingency_table
## X-squared = 11.492, df = 4, p-value = 0.02155
prop.table(contingency_table)
##
## 0 1
## 1 0.418571429 0.112857143
## 2 0.198571429 0.084285714
## 3 0.081428571 0.042857143
## 4 0.034285714 0.020000000
## 5 0.005714286 0.001428571
cramers_v <- CramerV(contingency_table)
print(paste("Cramer's V:", round(cramers_v, 3)))
## [1] "Cramer's V: 0.128"
The results suggest that there is a relationship between education
level and credit risk, although it is weak (the value of Cramer’s V is
low). However, due to the low p-value, we can consider this relationship
to be statistically significant.
Exercise 1. Contingency analysis.
Do you believe in the Afterlife? https://nationalpost.com/news/canada/millennials-do-you-believe-in-life-after-life
A survey was conducted and a random sample of 1091 questionnaires is
given in the form of the following contingency table:
## Believe
## Gender Yes No
## Female 435 375
## Male 147 134

Our task is to check if there is a significant relationship between
the belief in the afterlife and gender. We can perform this procedure
with the simple chi-square statistics and chosen qualitative correlation
coefficient (two-way 2x2 table).
## Call: cohen.kappa1(x = x, w = w, n.obs = n.obs, alpha = alpha, levels = levels,
## w.exp = w.exp)
##
## Cohen Kappa and Weighted Kappa correlation coefficients and confidence boundaries
## lower estimate upper
## unweighted kappa -0.043 0.011 0.065
## weighted kappa -0.043 0.011 0.065
##
## Number of subjects = 1091
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: dane
## X-squared = 0.11103, df = 1, p-value = 0.739
## Believe
## Gender Yes No
## Female 0.3987168 0.3437214
## Male 0.1347388 0.1228231
As you can see we can calculate our chi-square statistic really
quickly for two-way tables or larger. Now we can standardize this
contingency measure to see if the relationship is significant.
## [1] 0.01218871
## [1] 0.0121878
## [1] 0.01218871
## [1] 0.01218871


The unweighted Cohen Kappa value ranges from -0.043 to 0.065,
suggesting that there is only minimal above-random agreement between
belief in an afterlife and gender. Similarly the Chi-square test
indicates that there is no statistically significant relationship
between belief in the afterlife and gender (p > 0.05). Furthermore,
all from coefficients Phi, Cont, Cramer’s V and Tschuprow’s T are around
0,012, which suggest very weak relationship between this belief and
gender.
Exercise 2. Contingency analysis for the ‘Titanic’ data.
Let’s consider the titanic dataset which contains a complete list of
passengers and crew members on the RMS Titanic. It includes a variable
indicating whether a person did survive the sinking of the RMS Titanic
on April 15, 1912. A data frame contains 2456 observations on 14
variables.
The website http://www.encyclopedia-titanica.org/ offers detailed
information about passengers and crew members on the RMS Titanic.
According to the website 1317 passengers and 890 crew member were
aboard.
8 musicians and 9 employees of the shipyard company are listed as
passengers, but travelled with a free ticket, which is why they have NA
values in fare. In addition to that, fare is truely missing for a few
regular passengers.
# your answer here
titanic <- titanic[complete.cases(titanic$Fare.Price), ]
contingency_table_titanic <- table(titanic$Status, titanic$Crew.or.Passenger.)
print(contingency_table_titanic)
##
## Crew Passenger
## 214 35
## Survivor 211 500
## Victim 679 817
prop.table(contingency_table_titanic)
##
## Crew Passenger
## 0.08713355 0.01425081
## Survivor 0.08591205 0.20358306
## Victim 0.27646580 0.33265472
chisq.test(contingency_table_titanic)
##
## Pearson's Chi-squared test
##
## data: contingency_table_titanic
## X-squared = 236.24, df = 2, p-value < 2.2e-16
Phi(contingency_table_titanic)
## [1] 0.3101466
ContCoef(contingency_table_titanic)
## [1] 0.2962265
CramerV(contingency_table_titanic)
## [1] 0.3101466
TschuprowT(contingency_table_titanic)
## [1] 0.2608012
mosaicplot(contingency_table_titanic)

barplot(contingency_table_titanic)

The result of the chi-square test indicates that there is a
statistically significant relationship between status (survival or
death) and crew or passenger affiliation (p < 0.05).
Coefficients values estimates around 0,3, which means that there exist
moderate correlation between these two variables. Based on this analysis
we can say that belonging to the crew or passengers had a significant
impact on survival during the Titanic disaster. Passengers had higher
chance of surviving than the crew members.
LS0tDQp0aXRsZTogJ0Rlc2NyaXB0aXZlIFN0YXRpc3RpY3MnDQpzdWJ0aXRsZTogJ0JpdmFyaWF0ZSBBbmFseXNpcycNCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCmF1dGhvcjogIk1hZ2RhbGVuYSBTaWVsYWZmIDE5NDM0OSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgdGhlbWU6IGNlcnVsZWFuDQogICAgaGlnaGxpZ2h0OiB0ZXh0bWF0ZQ0KICAgIGZvbnRzaXplOiAxMHB0DQogICAgdG9jOiB5ZXMNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IG5vDQogICAgZGZfcHJpbnQ6IGRlZmF1bHQNCiAgICB0b2NfZGVwdGg6IDUNCmVkaXRvcl9vcHRpb25zOiANCiAgbWFya2Rvd246IA0KICAgIHdyYXA6IDcyDQotLS0NCg0KYGBge3Igc2V0dXAsCW1lc3NhZ2UgPSBGQUxTRSwJd2FybmluZyA9IEZBTFNFLAlpbmNsdWRlID0gRkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpvcHRpb25zKHJlcG9zID0gYyhDUkFOID0gImh0dHBzOi8vY2xvdWQuci1wcm9qZWN0Lm9yZyIpKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShIU0FVUjMpDQpsaWJyYXJ5KGhhdmVuKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShncmlkRXh0cmEpDQpsaWJyYXJ5KHBwY29yKSAjIHRoaXMgcGFja2FnZSBjb21wdXRlcyBwYXJ0aWFsIGFuZCBzZW1pcGFydGlhbCBjb3JyZWxhdGlvbnMuDQpsaWJyYXJ5KGx0bSkgIyB0aGlzIHBhY2thZ2UgY29tcHV0ZXMgcG9pbnQtYmlzZXJpYWwgY29ycmVsYXRpb25zLg0KbGlicmFyeShkZXZ0b29scykgDQojaW5zdGFsbF9naXRodWIoIm1hcmtoZWNrbWFubi9yeW91cmVhZHkiKSAjIHBsZWFzZSBpbnN0YWxsIHBhY2thZ2UgInJ5b3VyZWFkeSIgZnJvbSBnaXRodWIhICh0aGVuICMgaXQpDQpsaWJyYXJ5KHJ5b3VyZWFkeSkgIyB0aGlzIHBhY2thZ2UgY29tcHV0ZXMgbm9ubGluZWFyICJldGEiIGNvcnJlbGF0aW9ucy4NCmxpYnJhcnkoR0dhbGx5KSAjIHRoaXMgcGFja2FnZSBjb21wdXRlcyBjb3JyZWxhdGlvbiBtYXRyaXguDQpsaWJyYXJ5KHBzeWNoKSAjIHRoaXMgcGFja2FnZSBjb21wdXRlcyBxdWFsaXRhdGl2ZSBjb3JyZWxhdGlvbnMuDQpsaWJyYXJ5KERlc2NUb29scykgIyB0aGlzIHBhY2thZ2UgY29tcHV0ZXMgcXVhbGl0YXRpdmUgY29ycmVsYXRpb25zLg0KYGBgDQoNCiMjIEludHJvZHVjdGlvbg0KDQpUaGlzIGlzIG91ciBmaXJzdCBsYWIgd2hlbiB3ZSBhcmUgY29uc2lkZXJpbmcgMiBkaW1lbnNpb25zIGFuZCBpbnN0ZWFkDQpvZiBjYWxjdWxhdGluZyB1bml2YXJpYXRlIHN0YXRpc3RpY3MgYnkgZ3JvdXBzIChvciBmYWN0b3JzKSBvZiBvdGhlcg0KdmFyaWFibGUgLSB3ZSB3aWxsIG1lYXN1cmUgdGhlaXIgY29tbW9uIHJlbGF0aW9uc2hpcHMgYmFzZWQgb24NCmNvLXZhcmlhbmNlIGFuZCBjb3JyZWxhdGlvbiBjb2VmZmljaWVudHMuDQoNClwqUGxlYXNlIGJlIHZlcnkgY2FyZWZ1bCB3aGVuIGNob29zaW5nIHRoZSBtZWFzdXJlIG9mIGNvcnJlbGF0aW9uISBJbg0KY2FzZSBvZiBkaWZmZXJlbnQgbWVhc3VydW1lbnQgc2NhbGVzIHdlIGhhdmUgdG8gcmVjb2RlIG9uZSBvZiB0aGUNCnZhcmlhYmxlcyBpbnRvIHdlYWtlciBzY2FsZS4NCg0KSXQgd291bGQgYmUgbmljZSB0byBhZGQgc29tZSBhZGRpdGlvbmFsIHBsb3RzIGluIHRoZSBiYWNrZ3JvdW5kLiBGZWVsDQpmcmVlIHRvIGFkZCB5b3VyIG93biBzZWN0aW9ucyBhbmQgdXNlIGV4dGVybmFsIHBhY2thZ2VzLg0KDQojIyBEYXRhDQoNClRoaXMgdGltZSB3ZSBhcmUgZ29pbmcgdG8gdXNlIGEgdHlwaWNhbCBjcmVkaXQgc2NvcmluZyBkYXRhIHdpdGgNCnByZWRlZmluZWQgImRlZmF1bHQiIHZhcmlhYmxlcyBhbmQgcGVyc29uYWwgZGVtb2dyYWZpYyBhbmQgaW5jb21lIGRhdGEuDQpQbGVhc2UgdGFrZSBhIGxvb2sgY2xvc2VyIGF0IGhlYWRlcnMgYW5kIGRlc2NyaXB0aW9ucyBvZiBlYWNoIHZhcmlhYmxlLg0KDQpgYGB7ciBsb2FkLWRhdGEsIHdhcm5pbmc9VFJVRSwgaW5jbHVkZT1GQUxTRX0NCmRvd25sb2FkLmZpbGUoImh0dHBzOi8vZ2l0aHViLmNvbS9rZmxpc2lrb3dza2kvZHMvYmxvYi9tYXN0ZXIvYmFua19kZWZhdWx0cy5zYXY/cmF3PXRydWUiLCBkZXN0ZmlsZSA9ImJhbmtfZGVmYXVsdHMuc2F2Iixtb2RlPSJ3YiIpDQpiYW5rX2RlZmF1bHRzIDwtIHJlYWRfc2F2KCJiYW5rX2RlZmF1bHRzLnNhdiIpDQpiYW5rPC1uYS5vbWl0KGJhbmtfZGVmYXVsdHMpDQpiYW5rJGRlZjwtYXMuZmFjdG9yKGJhbmskZGVmYXVsdCkNCmJhbmskZWR1YzwtYXMuZmFjdG9yKGJhbmskZWQpDQpgYGANCg0KIyMgU2NhdHRlcnBsb3RzDQoNCkZpcnN0IGxldCdzIHZpc3VhbGl6ZSBvdXIgcXVhbnRpdGF0aXZlIHJlbGF0aW9uc2hpcHMgdXNpbmcgc2NhdHRlcnBsb3RzLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nPVRSVUV9DQojIEJhc2ljIHNjYXR0ZXIgcGxvdA0KDQpnZ3Bsb3QoYmFuaywgYWVzKGFnZSxpbmNvbWUpKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIHNoYXBlID0gMTgsIGNvbG9yID0gInJlZCIpICsNCiAgbGFicyh4ID0gIkFnZSIsDQogICAgICAgeSA9ICJJbmNvbWUiKQ0KDQojIENoYW5nZSB0aGUgcG9pbnQgc2l6ZSwgYW5kIHNoYXBlDQoNCg0KYGBgDQoNCllvdSBjYW4gYWxzbyBub3JtYWxpemUgdGhlIHNrZXdlZCBkaXN0cmlidXRpb24gb2YgaW5jb21lcyB1c2luZyBsb2c6DQoNCmBgYHtyIGVjaG89RkFMU0UsIHdhcm5pbmc9VFJVRX0NCiMgQmFzaWMgc2NhdHRlciBwbG90IHdpdGggdGhlIGxvZyBvZiBpbmNvbWUNCmJhbmskbG9naW5jb21lIDwtIGxvZyhiYW5rJGluY29tZSkNCmdncGxvdChiYW5rLCBhZXMoYWdlLGxvZ2luY29tZSkpICsNCiAgZ2VvbV9wb2ludCgpDQoNCmBgYA0KDQpXZSBjYW4gYWRkIGFuIGVzdGltYXRlZCBsaW5lYXIgcmVncmVzc2lvbiBsaW5lOg0KDQpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nPVRSVUV9DQpnZ3Bsb3QoYmFuaywgYWVzKHggPSBhZ2UsIHkgPSBsb2dpbmNvbWUpKSArDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gImJsdWUiKSArDQogIGxhYnMoeCA9ICJBZ2UiLA0KICAgICAgIHkgPSAiTG9nIG9mIGluY29tZSIpIA0KDQoNCg0KYGBgDQoNCiMjIFNjYXR0ZXJwbG90cyBieSBncm91cHMNCg0KV2UgY2FuIGZpbmFsbHkgc2VlIGlmIHRoZXJlIGFueSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHJpc2sgc3RhdHVzOg0KDQpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nPVRSVUV9DQpnZ3Bsb3QoYmFuaywgYWVzKHggPSBhZ2UsIHkgPSBsb2dpbmNvbWUpKSArDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gImJsdWUiKSArDQogIGZhY2V0X3dyYXAofiBkZWZhdWx0KSArDQogIGxhYnMoeCA9ICJBZ2UiLA0KICAgICAgIHkgPSAiTG9nIG9mIGluY29tZSIpDQpgYGANCg0KV2UgY2FuIGFsc28gc2VlIG1vcmUgY2xvc2VseSBpZiB0aGVyZSBhbnkgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aG9zZSB0d28NCmRpc3RyaWJ1dGlvbnMgYWRkaW5nIHRoZWlyIGVzdGltYXRlZCBkZW5zaXR5IHBsb3RzOg0KDQpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nPVRSVUV9DQppbnN0YWxsLnBhY2thZ2VzKCJnZ0V4dHJhIikNCg0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShnZ0V4dHJhKQ0KDQoNCmJhbmskYWdlIDwtIGFzLm51bWVyaWMoYmFuayRhZ2UpDQpiYW5rJGluY29tZSA8LSBhcy5udW1lcmljKGJhbmskaW5jb21lKQ0KYmFuayRkZWZhdWx0IDwtIGFzLmZhY3RvcihiYW5rJGRlZmF1bHQpDQpiYW5rJGVkIDwtIGFzLmZhY3RvcihiYW5rJGVkKQ0KDQojIE5vcm1hbGl6YWNqYSByb3prxYJhZHUgZG9jaG9kw7N3IHphIHBvbW9jxIUgbG9nYXJ5dG11DQpiYW5rJGxvZ2luY29tZSA8LSBsb2coYmFuayRpbmNvbWUpDQojIHNjYXR0ZXIgcGxvdCBvZiB4IGFuZCB5IHZhcmlhYmxlcw0KIyBjb2xvdXIgYnkgZ3JvdXBzDQpzY2F0dGVyX3Bsb3QgPC0gZ2dwbG90KGJhbmssIGFlcyh4ID0gYWdlLCB5ID0gbG9naW5jb21lLCBjb2xvciA9IGRlZmF1bHQpKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsNCiAgbGFicyh4ID0gIkFnZSIsDQogICAgICAgeSA9ICJMb2cgb2YgaW5jb21lIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KDQojIE1hcmdpbmFsIGRlbnNpdHkgcGxvdCBvZiBhZ2UgKHRvcCBwYW5lbCkNCnNjYXR0ZXJfcGxvdF93aXRoX2FnZV9kZW5zaXR5X2J5X2dyb3VwIDwtIGdnTWFyZ2luYWwoc2NhdHRlcl9wbG90LCBtYXJnaW5zID0gIngiLCB0eXBlID0gImRlbnNpdHkiLCBncm91cENvbG91ciA9IFRSVUUsIGdyb3VwRmlsbCA9IFRSVUUpDQpwcmludChzY2F0dGVyX3Bsb3Rfd2l0aF9hZ2VfZGVuc2l0eV9ieV9ncm91cCkNCg0Kc2NhdHRlcl9wbG90X3dpdGhfYWdlX2RlbnNpdHkgPC0gZ2dNYXJnaW5hbChzY2F0dGVyX3Bsb3QsIG1hcmdpbnMgPSAieCIsIHR5cGUgPSAiZGVuc2l0eSIpDQpwcmludChzY2F0dGVyX3Bsb3Rfd2l0aF9hZ2VfZGVuc2l0eSkNCg0KIyBNYXJnaW5hbCBkZW5zaXR5IHBsb3Qgb2YgeSAocmlnaHQgcGFuZWwpDQpzY2F0dGVyX3Bsb3Rfd2l0aF9pbmNvbWVfZGVuc2l0eV9ieV9ncm91cCA8LSBnZ01hcmdpbmFsKHNjYXR0ZXJfcGxvdCwgbWFyZ2lucyA9ICJ5IiwgdHlwZSA9ICJkZW5zaXR5IiwgZ3JvdXBDb2xvdXIgPSBUUlVFLCBncm91cEZpbGwgPSBUUlVFKQ0KcHJpbnQoc2NhdHRlcl9wbG90X3dpdGhfaW5jb21lX2RlbnNpdHlfYnlfZ3JvdXApDQoNCnNjYXR0ZXJfcGxvdF93aXRoX2luY29tZV9kZW5zaXR5IDwtIGdnTWFyZ2luYWwoc2NhdHRlcl9wbG90LCBtYXJnaW5zID0gInkiLCB0eXBlID0gImRlbnNpdHkiKQ0KcHJpbnQoc2NhdHRlcl9wbG90X3dpdGhfaW5jb21lX2RlbnNpdHkpDQpgYGANCg0KV2UgY2FuIGFsc28gcHV0IHRob3NlIHBsb3RzIHRvZ2V0aGVyOg0KDQpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nPVRSVUV9DQoNCnNjYXR0ZXJfcGxvdF93aXRoX21hcmdpbmFsX2J5X2dyb3VwIDwtIGdnTWFyZ2luYWwoc2NhdHRlcl9wbG90LCB0eXBlID0gImRlbnNpdHkiLCBncm91cENvbG91ciA9IFRSVUUsIGdyb3VwRmlsbCA9IFRSVUUpDQpwcmludChzY2F0dGVyX3Bsb3Rfd2l0aF9tYXJnaW5hbF9ieV9ncm91cCkNCg0Kc2NhdHRlcl9wbG90X3dpdGhfbWFyZ2luYWwgPC0gZ2dNYXJnaW5hbChzY2F0dGVyX3Bsb3QsIHR5cGUgPSAiZGVuc2l0eSIpDQpwcmludChzY2F0dGVyX3Bsb3Rfd2l0aF9tYXJnaW5hbCkNCg0KYGBgDQoNCiMjIFNjYXR0ZXJwbG90cyB3aXRoIGRlbnNpdHkgY3VydmVzDQoNCldlIGNhbiBhbHNvIHNlZSBtb3JlIGNsb3NlbHkgaWYgdGhlcmUgYW55IGRpZmZlcmVuY2VzIGJldHdlZW4gdGhvc2UgdHdvDQpkaXN0cmlidXRpb25zIGFkZGluZyB0aGVpciBlc3RpbWF0ZWQgZGVuc2l0eSBwbG90czoNCg0KYGBge3IgZWNobz1GQUxTRSwgd2FybmluZz1UUlVFfQ0KZ2dwbG90KGJhbmssIGFlcyh4ID0gYWdlLCB5ID0gbG9naW5jb21lLCBjb2xvciA9IGRlZmF1bHQpKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsNCiAgZ2VvbV9kZW5zaXR5XzJkKCkgKw0KICBsYWJzKHggPSAiQWdlIiwNCiAgICAgICB5ID0gIkxvZyBvZiBpbmNvbWUiKQ0KDQpgYGANCg0KIyMgQ29ycmVsYXRpb24gY29lZmZpY2llbnRzIC0gUGVhcnNvbidzIGxpbmVhciBjb3JyZWxhdGlvbg0KDQpPaywgbGV0J3MgbW92ZSB0byBzb21lIGNhbGN1bGF0aW9ucy4gSW4gUiwgd2UgY2FuIHVzZSB0aGUgY29yKCkNCmZ1bmN0aW9uLiBJdCB0YWtlcyB0aHJlZSBhcmd1bWVudHMgYW5kIHRoZSBtZXRob2Q6IGNvcih4LCB5LCBtZXRob2QpIEZvcg0KMiBxdWFudGl0YXRpdmUgZGF0YSwgd2l0aCBhbGwgYXNzdW1wdGlvbnMgbWV0LCB3ZSBjYW4gY2FsY3VsYXRlIHNpbXBsZQ0KUGVhcnNvbidzIGNvZWZmaWNpZW50IG9mIGxpbmVhciBjb3JyZWxhdGlvbjoNCg0KYGBge3IgZWNobz1GQUxTRSwgd2FybmluZz1UUlVFfQ0KcGVhcnNvbl9jb3JyIDwtIGNvcihiYW5rJGFnZSwgYmFuayRsb2dpbmNvbWUsIG1ldGhvZCA9ICJwZWFyc29uIikNCg0KcHJpbnQocGFzdGUoIlBlYXJzb24ncyBsaW5lYXIgY29ycmVsYXRpb246ICIsIHBlYXJzb25fY29ycikpDQoNCg0KDQpgYGANCg0KT2ssIHdoYXQgYWJvdXQgdGhlIHBlcmNlbnRhZ2Ugb2YgdGhlIGV4cGxhaW5lZCB2YXJpYWJpbGl0eT8NCg0KYGBge3IgZWNobz1GQUxTRSwgd2FybmluZz1UUlVFfQ0Kcl9zcXVhcmVkIDwtIHBlYXJzb25fY29ycl4yDQoNCnBlcmNlbnRfZXhwbGFpbmVkX3ZhcmlhYmlsaXR5IDwtIHJfc3F1YXJlZCAqIDEwMA0KDQpwcmludChwYXN0ZSgiUGVyY2VudGFnZSBvZiB0aGUgZXhwbGFpbmVkIHZhcmlhYmlsaXR5OiAiLCBwZXJjZW50X2V4cGxhaW5lZF92YXJpYWJpbGl0eSwgIiUiKSkNCg0KDQoNCmBgYA0KDQpTbyBhcyB3ZSBjYW4gc2VlIGFsbW9zdCAzMiw5OSUgb2YgdG90YWwgbG9nIG9mIGluY29tZXMnIHZhcmlhYmlsaXR5IGlzDQpleHBsYWluZWQgYnkgZGlmZmVyZW5jZXMgaW4gYWdlLiBUaGUgcmVzdCAoNjcsMSUpIGlzIHByb2JhYmx5IGV4cGxhaW5lZA0KYnkgb3RoZXIgZmFjdG9ycy4NCg0KIyMgUGFydGlhbCBhbmQgc2VtaXBhcnRpYWwgY29ycmVsYXRpb24NCg0KVGhlIHBhcnRpYWwgYW5kIHNlbWktcGFydGlhbCAoYWxzbyBrbm93biBhcyBwYXJ0KSBjb3JyZWxhdGlvbnMgYXJlIHVzZWQNCnRvIGV4cHJlc3MgdGhlIHNwZWNpZmljIHBvcnRpb24gb2YgdmFyaWFuY2UgZXhwbGFpbmVkIGJ5IGVsaW1pbmF0aW5nIHRoZQ0KZWZmZWN0IG9mIG90aGVyIHZhcmlhYmxlcyB3aGVuIGFzc2Vzc2luZyB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiB0d28NCnZhcmlhYmxlcy4NCg0KUGFydGlhbCBjb3JyZWxhdGlvbiBob2xkcyBjb25zdGFudCBvbmUgdmFyaWFibGUgd2hlbiBjb21wdXRpbmcgdGhlDQpyZWxhdGlvbnMgdG8gb3RoZXJzLiBTdXBwb3NlIHdlIHdhbnQgdG8ga25vdyB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBYDQphbmQgWSBob2xkaW5nIFogY29uc3RhbnQgZm9yIGJvdGggWCBhbmQgWS4gVGhhdCB3b3VsZCBiZSB0aGUgcGFydGlhbA0KY29ycmVsYXRpb24gYmV0d2VlbiBYIGFuZCBZIGNvbnRyb2xsaW5nIGZvciBaLg0KDQpTZW1pcGFydGlhbCBjb3JyZWxhdGlvbiBob2xkcyBaIGNvbnN0YW50IGZvciBlaXRoZXIgWCBvciBZLCBidXQgbm90DQpib3RoLCBzbyBpZiB3ZSB3YW50ZWQgdG8gY29udHJvbCBYIGZvciBaLCB3ZSBjb3VsZCBjb21wdXRlIHRoZQ0Kc2VtaXBhcnRpYWwgY29ycmVsYXRpb24gYmV0d2VlbiBYIGFuZCBZIGhvbGRpbmcgWiBjb25zdGFudCBmb3IgWC4NCg0KU3VwcG9zZSB3ZSB3YW50IHRvIGtub3cgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIGxvZyBvZiBpbmNvbWUgYW5kDQphZ2UgY29udHJvbGxpbmcgZm9yIHllYXJzIG9mIGVtcGxveW1lbnQuIEhvdyBoaWdobHkgY29ycmVsYXRlZCBhcmUgdGhlc2UNCmFmdGVyIGNvbnRyb2xsaW5nIGZvciB0ZW51cmU/DQoNClwqXCpUaGVyZSBjYW4gYmUgbW9yZSB0aGFuIG9uZSBjb250cm9sIHZhcmlhYmxlLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQpwYXJ0aWFsX2NvcnIgPC0gcGNvci50ZXN0KGJhbmskbG9naW5jb21lLCBiYW5rJGFnZSwgYmFuayRlbXBsb3kpDQoNCnByaW50KHBhc3RlKCJQYXJ0aWFsIGNvcnJlbGF0aW9uOiAiLCBwYXJ0aWFsX2NvcnIkZXN0aW1hdGUpKQ0KDQpgYGANCg0KSG93IGNhbiB3ZSBpbnRlcnByZXQgdGhlIG9idGFpbmVkIHBhcnRpYWwgY29ycmVsYXRpb24gY29lZmZpY2llbnQ/IFdoYXQNCmlzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhhdCBvbmUgYW5kIHRoZSBzZW1pLXBhcnRpYWwgY29lZmZpY2llbnQ6DQoNCmBgYHtyIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCnNlbWlfcGFydGlhbF9jb3JyIDwtIHNwY29yLnRlc3QoYmFuayRsb2dpbmNvbWUsIGJhbmskYWdlLCBiYW5rJGVtcGxveSkNCg0KcHJpbnQocGFzdGUoIlNlbWktcGFydGlhbCBjb3JyZWxhdGlvbjogIiwgc2VtaV9wYXJ0aWFsX2NvcnIkZXN0aW1hdGUpKQ0KDQpgYGANCg0KUGFydGlhbCBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBjYWxjdWxhdGVkIGZvciB0aGUgbG9nIG9mIGluY29tZSBhbmQgYWdlDQpjb250cm9sbGluZyBmb3IgeWVhcnMgb2YgZW1wbG95bWVudCBlcXVhbHMgMCwzMTkuIEl0IG1lYW5zIHRoYXQgYWZ0ZXINCmluY2x1ZGluZyBpbmZsdWVuY2Ugb2YgeWVhcnMgb2YgZW1wbG95bWVudCB0aGVyZSBleGlzdCBwb3NpdGl2ZSBhbmQNCm1vZGVyYXRlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGFnZSBhbmQgbG9nYXJpdGhtIG9mIGluY29tZS4gU28gYWZ0ZXINCnJlbW92aW5nIHRoZSBlZmZlY3RzIG9mIHllYXJzIG9mIGVtcGxveW1lbnQsIHRoZXNlIHR3byBhcmUgc3RpbGwNCm1vZGVyYXRlbHkgY29ycmVsYXRlZC4NCg0KT24gdGhlIG90aGVyIGhhbmQsIHRoZSBzZW1pLXBhcnRpYWwgY29ycmVsYXRpb24gYmV0d2VlbiBsb2cgaW5jb21lIGFuZA0KYWdlLCBjb250cm9sbGluZyBmb3IgeWVhcnMgb2YgZW1wbG95bWVudCBmb3IgbG9nIGluY29tZSBlcXVhbHMgMCwyMjAuDQpUaGVyZWZvcmUgYWZ0ZXIgdGFraW5nIGludG8gYWNjb3VudCB0aGUgZWZmZWN0IG9mIHllYXJzIG9mIGVtcGxveW1lbnQgb24NCnRoZSBsb2dhcml0aG0gb2YgaW5jb21lLCB0aGVyZSBpcyBhIHdlYWtlciBidXQgc3RpbGwgcG9zaXRpdmUNCnJlbGF0aW9uc2hpcCBiZXR3ZWVuIGFnZSBhbmQgdGhlIGxvZ2FyaXRobSBvZiBpbmNvbWUuIEluIG90aGVyIHdvcmRzLA0KYWdlIGlzIG1vZGVyYXRlbHkgY29ycmVsYXRlZCB3aXRoIGxvZyBpbmNvbWUsIGFmdGVyIHJlbW92aW5nIHRoZSBlZmZlY3QNCm9mIHllYXJzIG9mIGVtcGxveW1lbnQgb24gbG9nIGluY29tZSBvbmx5Lg0KDQpGaW5hbGx5LCBjb21wYXJpbmcgdGhlc2UgdHdvIGNvZWZmaWNpZW50cyB3ZSBjYW4gc2VlIHRoYXQgY29udHJvbGxpbmcNCmZvciB5ZWFycyBvZiBlbXBsb3ltZW50IGhhcyBhIGdyZWF0ZXIgaW1wYWN0IG9uIGxvZ2FyaXRobSBvZiBpbmNvbWUgdGhhbg0Kb24gYWdlLCB3aGljaCBpcyB2aXNpYmxlIGluIHRoZSBsb3dlciB2YWx1ZSBvZiB0aGUgc2VtaS1wYXJ0aWFsDQpjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBjb21wYXJlZCB0byB0aGUgcGFydGlhbCBjb3JyZWxhdGlvbi4NCg0KIyMgUmFuayBjb3JyZWxhdGlvbg0KDQpGb3IgMiBkaWZmZXJlbnQgc2NhbGVzIC0gbGlrZSBmb3IgZXhhbXBsZSB0aGlzIHBhaXIgb2YgdmFyaWFibGVzOiBpbmNvbWUNCnZzLiBlZHVjYXRpb24gbGV2ZWxzIC0gd2UgY2Fubm90IHVzZSBQZWFyc29uJ3MgY29lZmZpY2llbnQuIFRoZSBvbmx5DQpwb3NzaWJpbGl0eSBpcyB0byByYW5rIGFsc28gaW5jb21lcy4uLiBhbmQgbG9zZSBzb21lIG1vcmUgZGV0YWlsZWQNCmluZm9ybWF0aW9uIGFib3V0IHRoZW0uDQoNCkZpcnN0LCBsZXQncyBzZWUgYm94cGxvdHMgb2YgaW5jb21lIGJ5IGVkdWNhdGlvbiBsZXZlbHMuDQoNCmBgYHtyIGVjaG89RkFMU0UsIHdhcm5pbmc9VFJVRX0NCmdncGxvdChiYW5rLCBhZXMoeCA9IGVkLCB5ID0gaW5jb21lKSkgKw0KICBnZW9tX2JveHBsb3QoKSArDQogIGxhYnModGl0bGUgPSAiQm94cGxvdCBvZiBJbmNvbWUgYnkgRWR1Y2F0aW9uIExldmVscyIsDQogICAgICAgeCA9ICJFZHVjYXRpb24gTGV2ZWxzIiwNCiAgICAgICB5ID0gIkluY29tZSIpDQoNCmdncGxvdChiYW5rLCBhZXMoeCA9IGVkLCB5ID0gbG9naW5jb21lKSkgKw0KICBnZW9tX2JveHBsb3QoKSArDQogIGxhYnModGl0bGUgPSAiQm94cGxvdCBvZiBMb2dhcml0aG0gb2YgaW5jb21lIGJ5IEVkdWNhdGlvbiBMZXZlbHMiLA0KICAgICAgIHggPSAiRWR1Y2F0aW9uIExldmVscyIsDQogICAgICAgeSA9ICJMb2dhcml0aG0gb2YgaW5jb21lIikNCmBgYA0KDQpJbiB0aGVzZSBib3gtcGxvdHMgd2Ugc2VlIHRoYXQgcGVvcGxlIHdpdGggdGhlIGhpZ2hlc3QgZWR1Y2F0aW9uDQpnZW5lcmFsbHkgZWFybiB0aGUgbW9zdC4gSW4gY2FzZSBvZiBsb3dlciBlZHVjYXRpb24gbGV2ZWxzIHRoZQ0KZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZW0gaXNuJ3QgYXMgc2lnbmlmaWNhbnQuDQoNCk5vdywgbGV0J3Mgc2VlIEtlbmRhbCdzIGNvZWZmaWNpZW50IG9mIHJhbmsgY29ycmVsYXRpb24gKHJvYnVzdCBmb3INCnRpZXMpLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nPVRSVUV9DQprZW5kYWxsX2NvcnIgPC0gY29yKGJhbmskbG9naW5jb21lLGFzLm51bWVyaWMoYmFuayRlZCksbWV0aG9kPSJrZW5kYWxsIikNCmF0dGFjaChiYW5rKQ0KDQpwcmludChwYXN0ZSgiS2VuZGFsbCdzIHJhbmsgY29ycmVsYXRpb24gY29lZmZpY2llbnQ6ICIsIHJvdW5kKGtlbmRhbGxfY29yciwgMykpKQ0KDQoNCmBgYA0KDQpLZW5kYWxsJ3MgcmFuayBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBpcyBpbiByYW5nZSAtMSB0byAxLCB3aGVyZSAxDQppbmZvcm0gdXMgYWJvdXQgcGVyZmVjdCBwb3NpdGl2ZSBjb3JyZWxhdGlvbiwgLTEgYWJvdXQgcGVyZmVjdCBuZWdhdGl2ZQ0KY29ycmVsYXRpb24gYW5kIDAgYWJvdXQgbm8gY29ycmVsYXRpb24uIFZhbHVlIDAsMTU4IHN1Z2dlc3Qgd2Vhaw0KY29ycmVsYXRpb24gYmV0d2VlbiBpbmNvbWUgYW5kIGFnZS4NCg0KIyMgUG9pbnQtYmlzZXJpYWwgY29ycmVsYXRpb24NCg0KTGV0J3MgdHJ5IHRvIHZlcmlmeSBpZiB0aGVyZSBpcyBhIHNpZ25pZmljYW50IHJlbGF0aW9uc2hpcCBiZXR3ZWVuDQppbmNvbWVzIGFuZCByaXNrIHN0YXR1cy4gRmlyc3QsIGxldCdzIHRha2UgYSBsb29rIGF0IHRoZSBib3hwbG90Og0KDQpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nPVRSVUV9DQpnZ3Bsb3QoYmFuaywgYWVzKHggPSBkZWZhdWx0LCB5ID0gaW5jb21lKSkgKw0KICBnZW9tX2JveHBsb3QoKSArDQogIGxhYnModGl0bGUgPSAiQm94cGxvdCBvZiBJbmNvbWUgYnkgUmlzayBzdGF0dXMiLA0KICAgICAgIHggPSAiUmlzayBzdGF0dXMiLA0KICAgICAgIHkgPSAiSW5jb21lIikNCg0KZ2dwbG90KGJhbmssIGFlcyh4ID0gZGVmYXVsdCwgeSA9IGxvZ2luY29tZSkpICsNCiAgZ2VvbV9ib3hwbG90KCkgKw0KICBsYWJzKHRpdGxlID0gIkJveHBsb3Qgb2YgTG9nYXJpdGhtIG9mIGluY29tZSBieSBSaXNrIHN0YXR1cyIsDQogICAgICAgeCA9ICJSaXNrIHN0YXR1cyIsDQogICAgICAgeSA9ICJMb2dhcml0aG0gb2YgaW5jb21lIikNCg0KYGBgDQoNCklmIHlvdSB3b3VsZCBsaWtlIHRvIGNvbXBhcmUgMSBxdWFudGl0YXRpdmUgdmFyaWFibGUgKGluY29tZSkgYW5kIDENCmR5Y2hvdG9tb3VzIHZhcmlhYmxlIChkZWZhdWx0IHN0YXR1cyAtIGJpbmFyeSksIHRoZW4geW91IGNhbiB1c2UNCnBvaW50LWJpc2VyaWFsIGNvZWZmaWNpZW50Og0KDQpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KYmFuayA8LSBiYW5rICU+JQ0KICBtdXRhdGUoZGVmYXVsdF9udW1lcmljID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoZGVmYXVsdCkpKQ0KDQpwb2ludF9iaXNlcmlhbF9jb3JyX2luY29tZSA8LSBiaXNlcmlhbC5jb3IoYmFuayRpbmNvbWUsIGJhbmskZGVmYXVsdF9udW1lcmljKQ0KDQpwb2ludF9iaXNlcmlhbF9jb3JyX2xvZ2luY29tZSA8LSBiaXNlcmlhbC5jb3IoYmFuayRsb2dpbmNvbWUsIGJhbmskZGVmYXVsdF9udW1lcmljKQ0KDQpwcmludChwYXN0ZSgiUG9pbnQtYmlzZXJpYWwgY29ycmVsYXRpb24gY29lZmZpY2llbnQgKGluY29tZSk6Iiwgcm91bmQocG9pbnRfYmlzZXJpYWxfY29ycl9pbmNvbWUsIDMpKSkNCnByaW50KHBhc3RlKCJQb2ludC1iaXNlcmlhbCBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCAobG9nIGluY29tZSk6Iiwgcm91bmQocG9pbnRfYmlzZXJpYWxfY29ycl9sb2dpbmNvbWUsIDMpKSkNCg0KYGBgDQoNCldlIGNhbiBzZWUgdGhhdCB0aGlzIGNvcnJlbGF0aW9uIGlzIHBvc2l0aXZlIGFuZCB3ZWFrLCBzaW5jZSB0aGUNCmFic29sdXRlIHZhbHVlIGlzIGJlbG93IDAsMi4NCg0KIyMgTm9ubGluZWFyIGNvcnJlbGF0aW9uIC0gZXRhIGNvZWZmaWNpZW50DQoNCklmIHlvdSB3b3VsZCBsaWtlIHRvIGNoZWNrIGlmIHRoZXJlIGFyZSBhbnkgbm9ubGluZWFyaXRpZXMgYmV0d2VlbiAyDQp2YXJpYWJsZXMsIHRoZSBvbmx5IHBvc3NpYmlsaXR5IChiZXNpZGUgdHJhbnNmb3JtYXRpb25zIGFuZCBsaW5lYXINCmFuYWx5c2lzKSBpcyB0byBjYWxjdWxhdGUgImV0YSIgY29lZmZpY2llbnQgYW5kIGNvbXBhcmUgaXQgd2l0aCB0aGUNClBlYXJzb24ncyBsaW5lYXIgY29lZmZpY2llbnQuDQoNCmBgYHtyIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCmV0YV9pbmNvbWUgPC0gZXRhKGJhbmskZGVmYXVsdCwgYmFuayRpbmNvbWUpDQoNCmV0YV9sb2dpbmNvbWUgPC0gZXRhKGJhbmskZGVmYXVsdCwgYmFuayRsb2dpbmNvbWUpDQoNCnByaW50KHBhc3RlKCJFdGEgY29lZmZpY2llbnQgKGluY29tZSB+IGRlZmF1bHQpOiIsIGV0YV9pbmNvbWUpKQ0KcHJpbnQocGFzdGUoIkV0YSBjb2VmZmljaWVudCAobG9nIGluY29tZSB+IGRlZmF1bHQpOiIsIGV0YV9sb2dpbmNvbWUpKQ0KDQpgYGANCg0KVGhlIHZhbHVlcyBvZiBldGEgY29lZmZpY2llbnQgYW5kIFBlYXJzb25zIGNvZWZmaWNpZW50IGFyZSB0aGUgc2FtZSwgc28NCnRoZXJlIGlzIG5vIG5vbmxpbmVhciBjb3JyZWxhdGlvbi4NCg0KIyMgQ29ycmVsYXRpb24gbWF0cml4DQoNCldlIGNhbiBhbHNvIHByZXBhcmUgdGhlIGNvcnJlbGF0aW9uIG1hdHJpeCBmb3IgYWxsIHF1YW50aXRhdGl2ZQ0KdmFyaWFibGVzIHN0b3JlZCBpbiBvdXIgZGF0YSBmcmFtZS4NCg0KV2UgY2FuIHVzZSBnZ2NvcnIoKSBmdW5jdGlvbjoNCg0KYGBge3IgZWNobz1GQUxTRSwgd2FybmluZz1UUlVFfQ0KDQpnZ2NvcnIoYmFuaywgbWV0aG9kID0gYygiZXZlcnl0aGluZyIsICJwZWFyc29uIiksIGxhYmVsID0gVFJVRSkNCg0KYGBgDQoNCkFzIHlvdSBjYW4gc2VlIC0gdGhlIGRlZmF1bHQgY29ycmVsYXRpb24gbWF0cml4IGlzIG5vdCB0aGUgYmVzdCBpZGVhIGZvcg0KYWxsIG1lYXN1cmVtZW50IHNjYWxlcyAoaW5jbHVkaW5nIGJpbmFyeSB2YXJpYWJsZSAiZGVmYXVsdCIpLg0KDQpUaGF0J3Mgd2h5IG5vdyB3ZSBjYW4gcGVyZm9ybSBvdXIgYml2YXJpYXRlIGFuYWx5c2lzIHdpdGggZ2dwYWlyIHdpdGgNCmdyb3VwaW5nLg0KDQojIyBDb3JyZWxhdGlvbiBtYXRyaXggd2l0aCBzY2F0dGVycGxvdHMNCg0KSGVyZSBpcyB3aGF0IHdlIGFyZSBhYm91dCB0byBjYWxjdWxhdGU6IC0gVGhlIGNvcnJlbGF0aW9uIG1hdHJpeCBiZXR3ZWVuDQphZ2UsIGxvZ19pbmNvbWUsIGVtcGxveSwgYWRkcmVzcywgZGVidGluYywgY3JlZGRlYnQsIGFuZCBvdGhkZWJ0DQp2YXJpYWJsZSBncm91cGVkIGJ5IHdoZXRoZXIgdGhlIHBlcnNvbiBoYXMgYSBkZWZhdWx0IHN0YXR1cyBvciBub3QuIC0NClBsb3QgdGhlIGRpc3RyaWJ1dGlvbiBvZiBlYWNoIHZhcmlhYmxlIGJ5IGdyb3VwIC0gRGlzcGxheSB0aGUgc2NhdHRlcg0KcGxvdCB3aXRoIHRoZSB0cmVuZCBieSBncm91cA0KDQpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nPVRSVUV9DQoNCnNlbGVjdGVkX3ZhcnMgPC0gYmFua1ssIGMoImFnZSIsICJsb2dpbmNvbWUiLCAiZW1wbG95IiwgImFkZHJlc3MiLCAiZGVidGluYyIsICJjcmVkZGVidCIsICJvdGhkZWJ0IiwgImRlZmF1bHQiKV0NCg0Kc2VsZWN0ZWRfdmFycyRkZWZhdWx0IDwtIGFzLmZhY3RvcihzZWxlY3RlZF92YXJzJGRlZmF1bHQpDQoNCmdncGFpcnMoc2VsZWN0ZWRfdmFycywgDQogICAgICAgIG1hcHBpbmcgPSBhZXMoY29sb3IgPSBkZWZhdWx0LCBhbHBoYSA9IDAuNSksIA0KICAgICAgICB1cHBlciA9IGxpc3QoY29udGludW91cyA9ICJjb3IiKSwgDQogICAgICAgIGxvd2VyID0gbGlzdChjb250aW51b3VzID0gInNtb290aCIpLA0KICAgICAgICBkaWFnID0gbGlzdChjb250aW51b3VzID0gImRlbnNpdHlEaWFnIikpDQoNCmBgYA0KDQojIyBRdWFsaXRhdGl2ZSBkYXRhDQoNCkluIGNhc2Ugb2YgdHdvIHZhcmlhYmxlcyBtZWFzdXJlZCBvbiBub21pbmFsIG9yIG9yZGluYWwmbm9taW5hbCBzY2FsZSAtDQp3ZSBhcmUgZm9yY2VkIHRvIG9yZ2FuaXplIHNvIGNhbGxlZCAiY29udGluZ2VuY3kiIHRhYmxlIHdpdGggZnJlcXVlbmNpZXMNCmFuZCBjYWxjdWxhdGUgc29tZSBraW5kIG9mIHRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBiYXNlZCBvbiB0aGVtLg0KVGhpcyBpcyBzbyBjYWxsZWQgImNvbnRpbmdlbmN5IGFuYWx5c2lzIi4NCg0KTGV0J3MgY29uc2lkZXIgb25lIGV4YW1wbGUgYmFzZWQgb24gb3VyIGRhdGE6IHZlcmlmeSwgaWYgdGhlcmUgaXMgYW55DQpzaWduaWZpY2FudCBjb3JyZWxhdGlvbiBiZXR3ZWVuIGVkdWNhdGlvbiBsZXZlbCBhbmQgY3JlZGl0IHJpc2suDQoNCmBgYHtyfQ0KYmFuayRlZCA8LSBhcy5mYWN0b3IoYmFuayRlZCkNCmJhbmskZGVmYXVsdCA8LSBhcy5mYWN0b3IoYmFuayRkZWZhdWx0KQ0KDQpjb250aW5nZW5jeV90YWJsZSA8LSB0YWJsZShiYW5rJGVkLCBiYW5rJGRlZmF1bHQpDQpwcmludChjb250aW5nZW5jeV90YWJsZSkNCg0KY2hpc3EudGVzdChjb250aW5nZW5jeV90YWJsZSkNCnByb3AudGFibGUoY29udGluZ2VuY3lfdGFibGUpDQoNCg0KY3JhbWVyc192IDwtIENyYW1lclYoY29udGluZ2VuY3lfdGFibGUpDQpwcmludChwYXN0ZSgiQ3JhbWVyJ3MgVjoiLCByb3VuZChjcmFtZXJzX3YsIDMpKSkNCg0KYGBgDQoNClRoZSByZXN1bHRzIHN1Z2dlc3QgdGhhdCB0aGVyZSBpcyBhIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGVkdWNhdGlvbiBsZXZlbA0KYW5kIGNyZWRpdCByaXNrLCBhbHRob3VnaCBpdCBpcyB3ZWFrICh0aGUgdmFsdWUgb2YgQ3JhbWVyJ3MgViBpcyBsb3cpLg0KSG93ZXZlciwgZHVlIHRvIHRoZSBsb3cgcC12YWx1ZSwgd2UgY2FuIGNvbnNpZGVyIHRoaXMgcmVsYXRpb25zaGlwIHRvIGJlDQpzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50Lg0KDQojIyBFeGVyY2lzZSAxLiBDb250aW5nZW5jeSBhbmFseXNpcy4NCg0KRG8geW91IGJlbGlldmUgaW4gdGhlIEFmdGVybGlmZT8NCjxodHRwczovL25hdGlvbmFscG9zdC5jb20vbmV3cy9jYW5hZGEvbWlsbGVubmlhbHMtZG8teW91LWJlbGlldmUtaW4tbGlmZS1hZnRlci1saWZlPg0KQSBzdXJ2ZXkgd2FzIGNvbmR1Y3RlZCBhbmQgYSByYW5kb20gc2FtcGxlIG9mIDEwOTEgcXVlc3Rpb25uYWlyZXMgaXMNCmdpdmVuIGluIHRoZSBmb3JtIG9mIHRoZSBmb2xsb3dpbmcgY29udGluZ2VuY3kgdGFibGU6DQoNCmBgYHtyIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQp4PWMoNDM1LDE0NywzNzUsMTM0KQ0KZGltKHgpPWMoMiwyKQ0KZGFuZTwtYXMudGFibGUoeCkNCmRpbW5hbWVzKGRhbmUpPWxpc3QoR2VuZGVyPWMoJ0ZlbWFsZScsJ01hbGUnKSxCZWxpZXZlPWMoJ1llcycsJ05vJykpDQpkYW5lDQpmb3VyZm9sZHBsb3QoZGFuZSkNCmBgYA0KDQpPdXIgdGFzayBpcyB0byBjaGVjayBpZiB0aGVyZSBpcyBhIHNpZ25pZmljYW50IHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZQ0KYmVsaWVmIGluIHRoZSBhZnRlcmxpZmUgYW5kIGdlbmRlci4gV2UgY2FuIHBlcmZvcm0gdGhpcyBwcm9jZWR1cmUgd2l0aA0KdGhlIHNpbXBsZSBjaGktc3F1YXJlIHN0YXRpc3RpY3MgYW5kIGNob3NlbiBxdWFsaXRhdGl2ZSBjb3JyZWxhdGlvbg0KY29lZmZpY2llbnQgKHR3by13YXkgMngyIHRhYmxlKS4NCg0KYGBge3IgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnllczwtYyg0MzUsMTQ3KQ0Kbm88LWMoMzc1LDEzNCkNCmNvaGVuLmthcHBhKGNiaW5kKHllcyxubykpDQpjaGlzcS50ZXN0KGRhbmUpDQpwcm9wLnRhYmxlKGRhbmUpDQpgYGANCg0KQXMgeW91IGNhbiBzZWUgd2UgY2FuIGNhbGN1bGF0ZSBvdXIgY2hpLXNxdWFyZSBzdGF0aXN0aWMgcmVhbGx5IHF1aWNrbHkNCmZvciB0d28td2F5IHRhYmxlcyBvciBsYXJnZXIuIE5vdyB3ZSBjYW4gc3RhbmRhcmRpemUgdGhpcyBjb250aW5nZW5jeQ0KbWVhc3VyZSB0byBzZWUgaWYgdGhlIHJlbGF0aW9uc2hpcCBpcyBzaWduaWZpY2FudC4NCg0KYGBge3IgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0NClBoaShkYW5lKQ0KQ29udENvZWYoZGFuZSkNCkNyYW1lclYoZGFuZSkNClRzY2h1cHJvd1QoZGFuZSkNCm1vc2FpY3Bsb3QoZGFuZSkNCmJhcnBsb3QoZGFuZSkNCmBgYA0KDQpUaGUgdW53ZWlnaHRlZCBDb2hlbiBLYXBwYSB2YWx1ZSByYW5nZXMgZnJvbSAtMC4wNDMgdG8gMC4wNjUsIHN1Z2dlc3RpbmcNCnRoYXQgdGhlcmUgaXMgb25seSBtaW5pbWFsIGFib3ZlLXJhbmRvbSBhZ3JlZW1lbnQgYmV0d2VlbiBiZWxpZWYgaW4gYW4NCmFmdGVybGlmZSBhbmQgZ2VuZGVyLiBTaW1pbGFybHkgdGhlIENoaS1zcXVhcmUgdGVzdCBpbmRpY2F0ZXMgdGhhdCB0aGVyZQ0KaXMgbm8gc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCByZWxhdGlvbnNoaXAgYmV0d2VlbiBiZWxpZWYgaW4gdGhlDQphZnRlcmxpZmUgYW5kIGdlbmRlciAocCBcPiAwLjA1KS4gRnVydGhlcm1vcmUsIGFsbCBmcm9tIGNvZWZmaWNpZW50cw0KUGhpLCBDb250LCBDcmFtZXIncyBWIGFuZCBUc2NodXByb3cncyBUIGFyZSBhcm91bmQgMCwwMTIsIHdoaWNoIHN1Z2dlc3QNCnZlcnkgd2VhayByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGlzIGJlbGllZiBhbmQgZ2VuZGVyLg0KDQojIyBFeGVyY2lzZSAyLiBDb250aW5nZW5jeSBhbmFseXNpcyBmb3IgdGhlICdUaXRhbmljJyBkYXRhLg0KDQpMZXQncyBjb25zaWRlciB0aGUgdGl0YW5pYyBkYXRhc2V0IHdoaWNoIGNvbnRhaW5zIGEgY29tcGxldGUgbGlzdCBvZg0KcGFzc2VuZ2VycyBhbmQgY3JldyBtZW1iZXJzIG9uIHRoZSBSTVMgVGl0YW5pYy4gSXQgaW5jbHVkZXMgYSB2YXJpYWJsZQ0KaW5kaWNhdGluZyB3aGV0aGVyIGEgcGVyc29uIGRpZCBzdXJ2aXZlIHRoZSBzaW5raW5nIG9mIHRoZSBSTVMgVGl0YW5pYw0Kb24gQXByaWwgMTUsIDE5MTIuIEEgZGF0YSBmcmFtZSBjb250YWlucyAyNDU2IG9ic2VydmF0aW9ucyBvbiAxNA0KdmFyaWFibGVzLg0KDQpgYGB7ciBsb2FkLWRhdGEyLCB3YXJuaW5nPVRSVUUsIGluY2x1ZGU9RkFMU0V9DQpkb3dubG9hZC5maWxlKCJodHRwczovL2dpdGh1Yi5jb20va2ZsaXNpa293c2tpL2RzL2Jsb2IvbWFzdGVyL3RpdGFuaWMuY3N2P3Jhdz10cnVlIiwgZGVzdGZpbGUgPSJ0aXRhbmljLmNzdiIsbW9kZT0id2IiKQ0KdGl0YW5pYyA8LSByZWFkLmNzdigidGl0YW5pYy5jc3YiLHJvdy5uYW1lcz0xLHNlcD0iOyIpDQoNCmBgYA0KDQpUaGUgd2Vic2l0ZSA8aHR0cDovL3d3dy5lbmN5Y2xvcGVkaWEtdGl0YW5pY2Eub3JnLz4gb2ZmZXJzIGRldGFpbGVkDQppbmZvcm1hdGlvbiBhYm91dCBwYXNzZW5nZXJzIGFuZCBjcmV3IG1lbWJlcnMgb24gdGhlIFJNUyBUaXRhbmljLg0KQWNjb3JkaW5nIHRvIHRoZSB3ZWJzaXRlIDEzMTcgcGFzc2VuZ2VycyBhbmQgODkwIGNyZXcgbWVtYmVyIHdlcmUNCmFib2FyZC4NCg0KOCBtdXNpY2lhbnMgYW5kIDkgZW1wbG95ZWVzIG9mIHRoZSBzaGlweWFyZCBjb21wYW55IGFyZSBsaXN0ZWQgYXMNCnBhc3NlbmdlcnMsIGJ1dCB0cmF2ZWxsZWQgd2l0aCBhIGZyZWUgdGlja2V0LCB3aGljaCBpcyB3aHkgdGhleSBoYXZlIE5BDQp2YWx1ZXMgaW4gZmFyZS4gSW4gYWRkaXRpb24gdG8gdGhhdCwgZmFyZSBpcyB0cnVlbHkgbWlzc2luZyBmb3IgYSBmZXcNCnJlZ3VsYXIgcGFzc2VuZ2Vycy4NCg0KYGBge3J9DQojIHlvdXIgYW5zd2VyIGhlcmUNCg0KdGl0YW5pYyA8LSB0aXRhbmljW2NvbXBsZXRlLmNhc2VzKHRpdGFuaWMkRmFyZS5QcmljZSksIF0NCg0KY29udGluZ2VuY3lfdGFibGVfdGl0YW5pYyA8LSB0YWJsZSh0aXRhbmljJFN0YXR1cywgdGl0YW5pYyRDcmV3Lm9yLlBhc3Nlbmdlci4pDQoNCg0KcHJpbnQoY29udGluZ2VuY3lfdGFibGVfdGl0YW5pYykNCg0KcHJvcC50YWJsZShjb250aW5nZW5jeV90YWJsZV90aXRhbmljKQ0KDQpjaGlzcS50ZXN0KGNvbnRpbmdlbmN5X3RhYmxlX3RpdGFuaWMpDQoNClBoaShjb250aW5nZW5jeV90YWJsZV90aXRhbmljKQ0KQ29udENvZWYoY29udGluZ2VuY3lfdGFibGVfdGl0YW5pYykNCkNyYW1lclYoY29udGluZ2VuY3lfdGFibGVfdGl0YW5pYykNClRzY2h1cHJvd1QoY29udGluZ2VuY3lfdGFibGVfdGl0YW5pYykNCm1vc2FpY3Bsb3QoY29udGluZ2VuY3lfdGFibGVfdGl0YW5pYykNCmJhcnBsb3QoY29udGluZ2VuY3lfdGFibGVfdGl0YW5pYykNCg0KYGBgDQoNClRoZSByZXN1bHQgb2YgdGhlIGNoaS1zcXVhcmUgdGVzdCBpbmRpY2F0ZXMgdGhhdCB0aGVyZSBpcyBhDQpzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHN0YXR1cyAoc3Vydml2YWwgb3INCmRlYXRoKSBhbmQgY3JldyBvciBwYXNzZW5nZXIgYWZmaWxpYXRpb24gKHAgXDwgMC4wNSkuXA0KQ29lZmZpY2llbnRzIHZhbHVlcyBlc3RpbWF0ZXMgYXJvdW5kIDAsMywgd2hpY2ggbWVhbnMgdGhhdCB0aGVyZSBleGlzdA0KbW9kZXJhdGUgY29ycmVsYXRpb24gYmV0d2VlbiB0aGVzZSB0d28gdmFyaWFibGVzLiBCYXNlZCBvbiB0aGlzIGFuYWx5c2lzDQp3ZSBjYW4gc2F5IHRoYXQgYmVsb25naW5nIHRvIHRoZSBjcmV3IG9yIHBhc3NlbmdlcnMgaGFkIGEgc2lnbmlmaWNhbnQNCmltcGFjdCBvbiBzdXJ2aXZhbCBkdXJpbmcgdGhlIFRpdGFuaWMgZGlzYXN0ZXIuIFBhc3NlbmdlcnMgaGFkIGhpZ2hlcg0KY2hhbmNlIG9mIHN1cnZpdmluZyB0aGFuIHRoZSBjcmV3IG1lbWJlcnMuDQo=