1. Import the dataset Apartments.xlsx
# Load dataset
apartments <- read_xlsx("Apartments.xlsx")
head(apartments)
NA
Description:
- Age: Age of an apartment in years
- Distance: The distance from city center in km
- Price: Price per m2
- Parking: 0-No, 1-Yes
- Balcony: 0-No, 1-Yes
2. Change categorical variables into factors. (0.5 p)
# Convert character columns to factors
apartments$Parking <- factor(apartments$Parking,
levels = c(0, 1),
labels = c("no", "yes"))
apartments$Balcony <- factor(apartments$Balcony,
levels = c(0, 1),
labels = c("no", "yes"))
head(apartments)
NA
3. Test the hypothesis H0: Mu_Price = 1900 eur. What can you
conclude? (1 p)
# Explore the dataset
summary(apartments)
Age Distance Price Parking Balcony
Min. : 1.00 Min. : 1.00 Min. :1400 no :42 no :48
1st Qu.:12.00 1st Qu.: 4.00 1st Qu.:1710 yes:43 yes:37
Median :18.00 Median :12.00 Median :1950
Mean :18.55 Mean :14.22 Mean :2019
3rd Qu.:24.00 3rd Qu.:20.00 3rd Qu.:2290
Max. :45.00 Max. :45.00 Max. :2820
describe(apartments)
apartments
5 Variables 85 Observations
---------------------------------------------------------------------------------------------------------------------------------
Age
n missing distinct Info Mean Gmd .05 .10 .25 .50 .75 .90 .95
85 0 29 0.99 18.55 10.86 6.2 7.0 12.0 18.0 24.0 32.0 37.8
lowest : 1 2 5 6 7, highest: 37 38 40 43 45
---------------------------------------------------------------------------------------------------------------------------------
Distance
n missing distinct Info Mean Gmd .05 .10 .25 .50 .75 .90 .95
85 0 30 0.997 14.22 12.62 1.0 2.0 4.0 12.0 20.0 29.0 38.6
lowest : 1 2 3 4 5, highest: 33 37 39 40 45
---------------------------------------------------------------------------------------------------------------------------------
Price
n missing distinct Info Mean Gmd .05 .10 .25 .50 .75 .90 .95
85 0 50 0.999 2019 427.5 1570 1620 1710 1950 2290 2570 2782
lowest : 1400 1510 1560 1610 1620, highest: 2750 2790 2800 2810 2820
---------------------------------------------------------------------------------------------------------------------------------
Parking
n missing distinct
85 0 2
Value no yes
Frequency 42 43
Proportion 0.494 0.506
---------------------------------------------------------------------------------------------------------------------------------
Balcony
n missing distinct
85 0 2
Value no yes
Frequency 48 37
Proportion 0.565 0.435
---------------------------------------------------------------------------------------------------------------------------------
# Plot distribution of price
hist(apartments$Price,
main = "Distribution of the variable Price",
ylab = "Frequency",
xlab = "Price",
breaks = seq(1000, 3000, 200),
right = FALSE)

# Test for normality
shapiro.test(apartments$Price)
Shapiro-Wilk normality test
data: apartments$Price
W = 0.94017, p-value = 0.0006513
wilcox.test(apartments$Price,
mu = 1900,
correct = FALSE)
Wilcoxon signed rank test
data: apartments$Price
V = 2328, p-value = 0.02828
alternative hypothesis: true location is not equal to 1900
effectsize(wilcox.test(apartments$Price,
mu = 1900,
correct = FALSE))
r (rank biserial) | 95% CI
--------------------------------
0.27 | [0.04, 0.48]
- Deviation from a difference of 1900.
interpret_rank_biserial(0.27, rules = "funder2019")
[1] "medium"
(Rules: funder2019)
The descriptive and graphical analysis would lead me to the
conclusion that Mu_Price is NOT equal to 1900 eur and Price is NOT
normally distributed, but let’s see what the statistical tests show.
First I used the Shapiro-Wilk test to check if Price is normally
distributed, which it is not because I can reject H_0 of the
Shapiro-Wilk test at p < 0.001 and accept H_1 that Price is NOT
normally distributed.
Thus, I won’t use the t-test but its alternative, the Wilcoxon Signed
Rank Test with H_0 being Median_Price = 1900 and H_1 being Median_Price
=/= 1900 and cannot reject H_0 at p = 0.028 and conclude that
Median_Price = 1900, which according to funder2019 is a medium effect
size.
4. Estimate the simple regression function: Price = f(Age). Save
results in object fit1 and explain the estimate of regression
coefficient, coefficient of correlation and coefficient of
determination. (2 p)
# Scatterplot
scatterplot(Price ~ Age,
ylab = "Price per m2",
xlab = "Age of aparment in years",
smooth = FALSE,
data = apartments)

# Regression with Age as a predictor for price
fit1 <- lm(Price ~ Age,
data = apartments)
summary(fit1)
Call:
lm(formula = Price ~ Age, data = apartments)
Residuals:
Min 1Q Median 3Q Max
-623.9 -278.0 -69.8 243.5 776.1
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2185.455 87.043 25.108 <2e-16 ***
Age -8.975 4.164 -2.156 0.034 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 369.9 on 83 degrees of freedom
Multiple R-squared: 0.05302, Adjusted R-squared: 0.04161
F-statistic: 4.647 on 1 and 83 DF, p-value: 0.03401
# Correlation coefficient
cor_coef1 <- sqrt(summary(fit1)$r.squared)
cor_coef1
[1] 0.230255
Regression Coefficient:
- Age: Reject H_0 at p = 0.034 and accept H_1 that beta is NOT equal
to 0 and that we have a significant negative correlation between Age and
Price and each additional year that an apartment ages leads to an
average decrease of its price per m² of 8.975 eur.
Correlation Coefficient:
A correlation coefficient of only 0.230 indicates a weak negative
linear relationship between the age of an apartment and its price per
m².
Determination Coefficient:
Judging by the R-squared, approximately 5.302% of the variation in
the price per m² can be explained by knowing the age of the apartment.
This very low R-squared value suggests that other factors besides age
play significant roles in determining the price per m² of
apartments.
5. Show the scatterplot matrix between Price, Age and Distance.
Based on the matrix determine if there is a potential problem with
multicolinearity. (0.5 p)
# Scatterplot
scatterplotMatrix(~ Price + Age + Distance, data = apartments)

Looking at the scatterplot matrix for Price, Age and Distance, we can
see that:
Price vs. Age: This scatterplot suggests a slight negative trend
where Price decreases as Age increases. While there is some variation,
the pattern does suggest a possible relationship.
Price vs. Distance: This plot shows a clear negative trend where
Price decreases as Distance increases, suggesting that apartments closer
to the city center should be priced higher. This relationship appears to
be moderately strong and could be significant.
Age vs. Distance: This scatterplot does not show a clear trend
and I would argue that there should not be a correlation between Age and
Distance and no problems with multicollinearity when predicting
Price.
6. Estimate the multiple regression function: Price = f(Age,
Distance). Save it in object named fit2.
# Regression with Age and Distance as a predictors for Price
fit2 <- lm(Price ~ Age + Distance,
data = apartments)
summary(fit2)
Call:
lm(formula = Price ~ Age + Distance, data = apartments)
Residuals:
Min 1Q Median 3Q Max
-603.23 -219.94 -85.68 211.31 689.58
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2460.101 76.632 32.10 < 2e-16 ***
Age -7.934 3.225 -2.46 0.016 *
Distance -20.667 2.748 -7.52 6.18e-11 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 286.3 on 82 degrees of freedom
Multiple R-squared: 0.4396, Adjusted R-squared: 0.4259
F-statistic: 32.16 on 2 and 82 DF, p-value: 4.896e-11
# Correlation coefficient
cor_coef2 <- sqrt(summary(fit2)$r.squared)
cor_coef2
[1] 0.6629887
Regression Coefficients:
Age: Like with the previous regression, reject H_0 but this time
at a more significant p = 0.016 and accept H_1 that beta is NOT equal to
0 and that we have a significant negative correlation between Age and
Price and each additional year that an apartment ages leads to an
average decrease of its price per m² of 7.934 eur.
Distance: Reject H_0 at p < 0.001 and accept H_1 that beta is
NOT equal to 0 and that we have a significant negative correlation
between Distance and Price and each additional km that an apartment is
further away from the city center leads to an average decrease of its
price per m² of 20.667 eur.
Correlation Coefficient:
A correlation coefficient of only 0.662 indicates a semi-strong
negative linear relationship between the age of an apartment, its
distance from the city center and its price per m².
Determination Coefficient:
Judging by the R-squared, approximately 43.96% of the variation in
the price per m² can be explained by knowing the age and distance from
the city center of the apartment. This good R-squared value suggests
that age and distance explain the price to a decent degree but still
less than half, so other factors besides them play a bigger role in
determining the price per m² of apartments.
7. Check the multicolinearity with VIF statistics. Explain the
findings. (1 p)
# VIF statisctic
vif(fit2)
Age Distance
1.001845 1.001845
mean(vif(fit2))
[1] 1.001845
Both VIF’s are way below 5 and the average VIF is close to 1, so
there is no issue with multicoliniearity.
8. Calculate standardized residuals and Cooks Distances for model
fit2. Remove any potentially problematic units (outliers or units with
high influence). (2 p)
# Standardiued residuals and cooks distance
apartments$StdResid <- round(rstandard(fit2), 3)
apartments$StdFitted <- scale(fit2$fitted.values)
apartments$CooksD <- round(cooks.distance(fit2), 3)
hist(apartments$StdResid,
xlab = "Standardized Residuals",
ylab = "Frequency",
main = "Histogram of standardized residuals")

# Check if standardized residuals are normally distributed
shapiro.test(apartments$StdResid)
Shapiro-Wilk normality test
data: apartments$StdResid
W = 0.95303, p-value = 0.003645
hist(apartments$CooksD,
xlab = "Cooks distance",
ylab = "Frequency",
main = "Histogram of Cooks distances")

Judging by the histogram of the standardized residuals, all residuals
are between +-3 where they should be so we technically do not have any
outliers but there seem to be entries with values both at the lower and
upper end that do not belong to the majority. However, they do NOT seem
to be normally distributed which is confirmed by the Shapiro-Wilk Test
on them where I have to reject H_0 at p = 0.004 that they are normally
distributed and accept H_1 that the are NOT normally distributed.
Furthermore, by taking a look at the histogram of the Cooks
distances, it becomes obvious that there is a large gap between 0.15 and
0.30 and I need to remove the high impact outliers above that gap.
# Check for highg impact outliers with the highest Cooks distances
head(apartments[order(-apartments$CooksD),], 10)
# Remove identified high impact outliers
apartments <- apartments %>%
filter(!CooksD == 0.320)
hist(apartments$StdResid,
xlab = "Standardized Residuals",
ylab = "Frequency",
main = "Histogram of standardized residuals")

# Check if standardized residuals are normally distributed
shapiro.test(apartments$StdResid)
Shapiro-Wilk normality test
data: apartments$StdResid
W = 0.94879, p-value = 0.002187
hist(apartments$CooksD,
xlab = "Cooks distance",
ylab = "Frequency",
main = "Histogram of Cooks distances")

Still some gaps remain in the Cooks distance plot that were not
obvious before and we need to exclude even more entries where the Cooks
disances are above 0.04.
# Check for highg impact outliers with the highest Cooks distances
head(apartments[order(-apartments$CooksD),], 10)
# Remove identified high impact outliers
apartments <- apartments %>%
filter(!CooksD > 0.04)
hist(apartments$StdResid,
xlab = "Standardized Residuals",
ylab = "Frequency",
main = "Histogram of standardized residuals")

# Check if standardized residuals are normally distributed
shapiro.test(apartments$StdResid)
Shapiro-Wilk normality test
data: apartments$StdResid
W = 0.93418, p-value = 0.0004761
hist(apartments$CooksD,
xlab = "Cooks distance",
ylab = "Frequency",
main = "Histogram of Cooks distances")

After removing all high impact outliers, all standardized residuals
now fall in a narrower band, albeit still NOT normally distributed
according to the Shapiro-Wilk Test where I need to reject H_0 at p <
0.001 and accept H_1, and more importantly there are no more gaps in the
Cooks distances histogram.
9. Check for potential heteroskedasticity with scatterplot between
standarized residuals and standardized fitted values. Explain the
findings. (1 p)
# Check for potential heteroskedasticity
scatterplot(y = apartments$StdResid, x = apartments$StdFitted,
ylab = "Standardized Residuals",
xlab = "Standardized fitted values",
boxplots = FALSE,
regLine = FALSE,
smooth = FALSE)

Judging by the scatterplot of the standarized residuals and
standardized fitted values, there is no linearity issue and likely no
heteroskedasticity issue a well.
11. Estimate the fit2 again without potentially excluded units and
show the summary of the model. Explain all coefficients. (2 p)
# Regression with Age and Distance as a predictors for Price
fit2b <- lm(Price ~ Age + Distance,
data = apartments)
summary(fit2b)
Call:
lm(formula = Price ~ Age + Distance, data = apartments)
Residuals:
Min 1Q Median 3Q Max
-411.50 -203.69 -45.24 191.11 492.56
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2502.467 75.024 33.356 < 2e-16 ***
Age -8.674 3.221 -2.693 0.00869 **
Distance -24.063 2.692 -8.939 1.57e-13 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 256.8 on 77 degrees of freedom
Multiple R-squared: 0.5361, Adjusted R-squared: 0.524
F-statistic: 44.49 on 2 and 77 DF, p-value: 1.437e-13
# Correlation coefficient
cor_coef2b <- sqrt(summary(fit2b)$r.squared)
cor_coef2b
[1] 0.732187
# VIF statisctic
vif(fit2b)
Age Distance
1.001257 1.001257
mean(vif(fit2b))
[1] 1.001257
Regression Coefficients:
-Age: Like with the previous regression, reject H_0 but this time at
a even more significant p = 0.009 and accept H_1 that beta is NOT equal
to 0 and that we have a significant negative correlation between Age and
Price and each additional year that an apartment ages leads to an
average decrease of its price per m² of 8.674 eur.
-Distance: Reject H_0 at p < 0.001 and accept H_1 that beta is NOT
equal to 0 and that we have a significant negative correlation between
Distance and Price and each additional km that an apartment is further
away from the city center leads to an average decrease of its price per
m² of 24.063 eur.
Correlation Coefficient:
A correlation coefficient of 0.732 indicates a strong negative linear
relationship between the age of an apartment, its distance from the city
center and its price per m².
Determination Coefficient:
Judging by the R-squared, approximately 53.61% of the variation in
the price per m² can be explained by knowing the age and distance from
the city center of the apartment. This good R-squared value suggests
that age and distance explain the price well with more than half, so
other factors besides them play a role too in determining the price per
m² of apartments but a smaller one.
Compared to the previous regression with outliers: Removing the
outliers made both predictors more significant, especially Age, led to
an increase in the correlation coefficient and nudged the determination
coefficient over 50%.
12. Estimate the linear regression function Price = f(Age, Distance,
Parking and Balcony). Be careful to correctly include categorical
variables. Save the object named fit3.
# Regression with Age and Distance as a predictors for Price
fit3 <- lm(Price ~ Age + Distance + Parking + Balcony,
data = apartments)
summary(fit3)
Call:
lm(formula = Price ~ Age + Distance + Parking + Balcony, data = apartments)
Residuals:
Min 1Q Median 3Q Max
-390.93 -198.19 -53.64 186.73 518.34
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2393.316 93.930 25.480 < 2e-16 ***
Age -7.970 3.191 -2.498 0.0147 *
Distance -21.961 2.830 -7.762 3.39e-11 ***
Parkingyes 128.700 60.801 2.117 0.0376 *
Balconyyes 6.032 57.307 0.105 0.9165
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 252.7 on 75 degrees of freedom
Multiple R-squared: 0.5623, Adjusted R-squared: 0.5389
F-statistic: 24.08 on 4 and 75 DF, p-value: 7.764e-13
# Correlation coefficient
cor_coef3 <- sqrt(summary(fit3)$r.squared)
cor_coef3
[1] 0.7498334
# VIF statisctic
vif(fit3)
Age Distance Parking Balcony
1.014239 1.141993 1.157384 1.005037
mean(vif(fit3))
[1] 1.079664
Regression Coefficients:
Age: Like with the previous regression using only two predictors,
reject H_0 but this time at a less significant p = 0.015 and accept H_1
that beta is NOT equal to 0 and that we have a significant negative
correlation between Age and Price and each additional year that an
apartment ages leads to an average decrease of its price per m² of 7.970
eur assuming all other variables remain unchanged.
Distance: Reject H_0 at p < 0.001 and accept H_1 that beta is
NOT equal to 0 and that we have a significant negative correlation
between Distance and Price and each additional km that an apartment is
further away from the city center leads to an average decrease of its
price per m² of 21.961 eur assuming all other variables remain
unchanged.
Parking: Reject H_0 at p = 0.038 and accept H_1 that beta is NOT
equal to 0 and that we have a significant positive correlation between
Parking and Price and having parking space leads to an average increase
of its price per m² of 128.700 eur assuming all other variables remain
unchanged.
Correlation Coefficient: A correlation coefficient of 0.75 indicates
a strong linear relationship between the age of an apartment, its
distance from the city center, the availability of parking space and its
price per m².
Determination Coefficient:
Judging by the R-squared, approximately 53.89% of the variation in
the price per m² can be explained by knowing the age, distance from the
city center of the apartment and the availability of parking spaces.
This good R-squared value suggests that age, distance and parking
explain the price well with more than half, so other factors besides
them play a role too in determining the price per m² of apartments but a
smaller one.
13. With function anova check if model fit3 fits data better than
model fit2. (1 p)
# Compare regression models
anova(fit2b, fit3)
Analysis of Variance Table
Model 1: Price ~ Age + Distance
Model 2: Price ~ Age + Distance + Parking + Balcony
Res.Df RSS Df Sum of Sq F Pr(>F)
1 77 5077362
2 75 4791128 2 286234 2.2403 0.1135
Residual Degrees of Freedom: Model 1, this is 77, and for Model
2, it is 75. The difference in degrees of freedom corresponds to the
number of additional predictors Parking and Balcony included in Model 2
compared to Model 1.
Residual Sum of Squares: Model 1, the RSS is 5,077,362, and for
Model 2, it is 4,791,128. A lower RSS indicates a better model fit as it
suggests smaller deviations of the observed values from the model’s
predicted values.
-Degrees of Freedom: This is the difference in the number of
parameters between the two models. Here, 2 additional parameters are
estimated in Model 2 with the inclusion of Parking and Balcony.
Sum of Squares: This shows the difference in RSS between the two
models, which is 286,234. This value represents the improvement in model
fit that can be attributed to the addition of the new
parameters.
F-statistic: With a value is 2.2403. It tests whether the extra
parameters added in Model 2 significantly improve the model’s
fit.
Since the p-value is 0.114, we can NOT reject H_0 that the addition
of Parking and Balcony does provide a significant improvement in
predicting Price over just using Age and Distance and Model 1 (Price ~
Age + Distance) is sufficient for modeling the relationship and I would
only include Parking and/or Balcony if required by similar past research
for example.
14. Show the results of fit3 and explain regression coefficient for
both categorical variables. Can you write down the hypothesis which is
being tested with F-statistics, shown at the bottom of the output? (2
p)
summary(fit3)
Call:
lm(formula = Price ~ Age + Distance + Parking + Balcony, data = apartments)
Residuals:
Min 1Q Median 3Q Max
-390.93 -198.19 -53.64 186.73 518.34
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2393.316 93.930 25.480 < 2e-16 ***
Age -7.970 3.191 -2.498 0.0147 *
Distance -21.961 2.830 -7.762 3.39e-11 ***
Parkingyes 128.700 60.801 2.117 0.0376 *
Balconyyes 6.032 57.307 0.105 0.9165
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 252.7 on 75 degrees of freedom
Multiple R-squared: 0.5623, Adjusted R-squared: 0.5389
F-statistic: 24.08 on 4 and 75 DF, p-value: 7.764e-13
Categorical Regression Coefficients:
As stated in 12. for Parking: “Reject H_0 at p = 0.038 and accept
H_1 that beta is NOT equal to 0 and that we have a significant positive
correlation between Parking and Price and having parking space leads to
an average increase of its price per m² of 128.700 eur assuming all
other variables remain unchanged.”
Balcony: I can NOT reject H_0 with a high p = 0.917 and assume
that beta is equal to 0 and that we have NO significant correlation
between Balcony and Price and having a balcony does NOT lead to an
average increase of its price per m² assuming all other variables remain
unchanged.
F-statistic:
The F-statistic is used to test the overall significance of the
regression model. With H_O that the independent variables Age.,
Distance, Parking and Balcony have NO significant effect on Price and
H_1 that the independent variables do have a significant effect on
Price. I reject H_0 at p < 0.001 and accept H_1 that there is a
significant effect of the dependent variables on Price.
15. Save fitted values and calculate the residual for apartment ID2.
(1 p)
# Standardiued residuals
apartments$StdResid3 <- round(rstandard(fit3), 3)
apartments$StdResid3[2]
2
1.794
Since the Appartments.xlsx file does not contain an ID column, I will
assume that the apartment in row 2 has the ID = 2 and thus a
standardized residual of 1.794.
LS0tDQp0aXRsZTogIjU5NDNfQXBwbGllZERhdGFBbmFseXNpc0luQnVzaW5lc3NXaXRoUl9IVzMiDQphdXRob3I6ICJNYXJrdXMgV2Vpc3MiDQpkYXRlOiAiMjAyNC0wNS0wMyINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KIyAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KYGBge3IgZWNobyA9IEYsIG1lc3NhZ2UgPSBGLCBpbmNsdWRlID0gRn0NCm9wdGlvbnModGlueXRleC52ZXJib3NlID0gVFJVRSkNCmlmICghcmVxdWlyZSgia25pdHIiKSkgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKTsgbGlicmFyeSgia25pdHIiKQ0KaWYgKCFyZXF1aXJlKCJzdGFyZ2F6ZXIiKSkgaW5zdGFsbC5wYWNrYWdlcygic3RhcmdhemVyIik7IGxpYnJhcnkoInN0YXJnYXplciIpDQppZiAoIXJlcXVpcmUoInN0cmluZ3IiKSkgaW5zdGFsbC5wYWNrYWdlcygic3RyaW5nciIpOyBsaWJyYXJ5KCJzdHJpbmdyIikNCmlmICghcmVxdWlyZSgiZHBseXIiKSkgaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKTsgbGlicmFyeSgiZHBseXIiKQ0KaWYgKCFyZXF1aXJlKCJyZWFkeGwiKSkgaW5zdGFsbC5wYWNrYWdlcygicmVhZHhsIik7IGxpYnJhcnkoInJlYWR4bCIpDQppZiAoIXJlcXVpcmUoImx1YnJpZGF0ZSIpKSBpbnN0YWxsLnBhY2thZ2VzKCJsdWJyaWRhdGUiKTsgbGlicmFyeSgibHVicmlkYXRlIikNCmlmICghcmVxdWlyZSgicGxvdGx5IikpIGluc3RhbGwucGFja2FnZXMoInBsb3RseSIpOyBsaWJyYXJ5KCJwbG90bHkiKQ0KaWYgKCFyZXF1aXJlKCJnZ3Bsb3QyIikpIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKTsgbGlicmFyeSgiZ2dwbG90MiIpDQppZiAoIXJlcXVpcmUoImdncHViciIpKSBpbnN0YWxsLnBhY2thZ2VzKCJnZ3B1YnIiKTsgbGlicmFyeSgiZ2dwdWJyIikNCmlmICghcmVxdWlyZSgicnN0YXRpeCIpKSBpbnN0YWxsLnBhY2thZ2VzKCJyc3RhdGl4Iik7IGxpYnJhcnkoInJzdGF0aXgiKQ0KaWYgKCFyZXF1aXJlKCJwc3ljaCIpKSBpbnN0YWxsLnBhY2thZ2VzKCJwc3ljaCIpOyBsaWJyYXJ5KCJwc3ljaCIpDQppZiAoIXJlcXVpcmUoInBhc3RlY3MiKSkgaW5zdGFsbC5wYWNrYWdlcygicGFzdGVjcyIpOyBsaWJyYXJ5KCJwYXN0ZWNzIikNCmlmICghcmVxdWlyZSgiZWZmZWN0c2l6ZSIpKSBpbnN0YWxsLnBhY2thZ2VzKCJlZmZlY3RzaXplIik7IGxpYnJhcnkoImVmZmVjdHNpemUiKQ0KaWYgKCFyZXF1aXJlKCJjYXIiKSkgaW5zdGFsbC5wYWNrYWdlcygiY2FyIik7IGxpYnJhcnkoImNhciIpDQppZiAoIXJlcXVpcmUoIkhtaXNjIikpIGluc3RhbGwucGFja2FnZXMoImNhciIpOyBsaWJyYXJ5KCJjYXIiKQ0KDQojIGNsZWFuaW5nIHRoZSB3b3JraW5nIGVudmlyb25tZW50DQpybShsaXN0ID0gbHMoKSkNCiMgc2V0dGluZyBzZWVkIGZvciByZXByb2R1Y2liaWxpdHkNCnNldC5zZWVkKDY5KQ0KDQprbml0cjo6b3B0c19jaHVuayRzZXQobWVzc2FnZSA9IEYsIGZpZy53aWR0aCA9IDgsIGZpZy5oZWlnaHQgPSA0KQ0Kb3B0aW9ucyh3aWR0aCA9IDEyMCkNCg0KYGBgDQoNCg0KIyAgMS4gSW1wb3J0IHRoZSBkYXRhc2V0IEFwYXJ0bWVudHMueGxzeA0KDQpgYGB7cn0NCiMgTG9hZCBkYXRhc2V0DQphcGFydG1lbnRzIDwtIHJlYWRfeGxzeCgiQXBhcnRtZW50cy54bHN4IikNCg0KaGVhZChhcGFydG1lbnRzKQ0KDQpgYGANCg0KRGVzY3JpcHRpb246DQoNCi0gQWdlOiBBZ2Ugb2YgYW4gYXBhcnRtZW50IGluIHllYXJzDQotIERpc3RhbmNlOiBUaGUgZGlzdGFuY2UgZnJvbSBjaXR5IGNlbnRlciBpbiBrbQ0KLSBQcmljZTogUHJpY2UgcGVyIG0yDQotIFBhcmtpbmc6IDAtTm8sIDEtWWVzDQotIEJhbGNvbnk6IDAtTm8sIDEtWWVzDQoNCg0KIyAyLiBDaGFuZ2UgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGludG8gZmFjdG9ycy4gKDAuNSBwKQ0KDQpgYGB7cn0NCiMgQ29udmVydCBjaGFyYWN0ZXIgY29sdW1ucyB0byBmYWN0b3JzDQphcGFydG1lbnRzJFBhcmtpbmcgPC0gZmFjdG9yKGFwYXJ0bWVudHMkUGFya2luZywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoMCwgMSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJubyIsICJ5ZXMiKSkNCmFwYXJ0bWVudHMkQmFsY29ueSA8LSBmYWN0b3IoYXBhcnRtZW50cyRCYWxjb255LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygwLCAxKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIm5vIiwgInllcyIpKQ0KDQpoZWFkKGFwYXJ0bWVudHMpDQoNCmBgYA0KDQoNCiMgMy4gVGVzdCB0aGUgaHlwb3RoZXNpcyBIMDogTXVfUHJpY2UgPSAxOTAwIGV1ci4gV2hhdCBjYW4geW91IGNvbmNsdWRlPyAoMSBwKQ0KDQpgYGB7cn0NCiMgRXhwbG9yZSB0aGUgZGF0YXNldA0Kc3VtbWFyeShhcGFydG1lbnRzKQ0KZGVzY3JpYmUoYXBhcnRtZW50cykNCg0KIyBQbG90IGRpc3RyaWJ1dGlvbiBvZiBwcmljZQ0KaGlzdChhcGFydG1lbnRzJFByaWNlLA0KICAgICBtYWluID0gIkRpc3RyaWJ1dGlvbiBvZiB0aGUgdmFyaWFibGUgUHJpY2UiLA0KICAgICB5bGFiID0gIkZyZXF1ZW5jeSIsDQogICAgIHhsYWIgPSAiUHJpY2UiLA0KICAgICBicmVha3MgPSBzZXEoMTAwMCwgMzAwMCwgMjAwKSwNCiAgICAgcmlnaHQgPSBGQUxTRSkNCg0KIyBUZXN0IGZvciBub3JtYWxpdHkNCnNoYXBpcm8udGVzdChhcGFydG1lbnRzJFByaWNlKQ0KDQp3aWxjb3gudGVzdChhcGFydG1lbnRzJFByaWNlLA0KICAgICAgICAgICAgbXUgPSAxOTAwLA0KICAgICAgICAgICAgY29ycmVjdCA9IEZBTFNFKQ0KDQplZmZlY3RzaXplKHdpbGNveC50ZXN0KGFwYXJ0bWVudHMkUHJpY2UsDQogICAgICAgICAgICBtdSA9IDE5MDAsDQogICAgICAgICAgICBjb3JyZWN0ID0gRkFMU0UpKQ0KDQppbnRlcnByZXRfcmFua19iaXNlcmlhbCgwLjI3LCBydWxlcyA9ICJmdW5kZXIyMDE5IikNCg0KYGBgDQoNClRoZSBkZXNjcmlwdGl2ZSBhbmQgZ3JhcGhpY2FsIGFuYWx5c2lzIHdvdWxkIGxlYWQgbWUgdG8gdGhlIGNvbmNsdXNpb24gdGhhdCBNdV9QcmljZSBpcyBOT1QgZXF1YWwgdG8gMTkwMCBldXIgYW5kIFByaWNlIGlzIE5PVCBub3JtYWxseSBkaXN0cmlidXRlZCwgYnV0IGxldCdzIHNlZSB3aGF0IHRoZSBzdGF0aXN0aWNhbCB0ZXN0cyBzaG93Lg0KDQpGaXJzdCBJIHVzZWQgdGhlIFNoYXBpcm8tV2lsayB0ZXN0IHRvIGNoZWNrIGlmIFByaWNlIGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLCB3aGljaCBpdCBpcyBub3QgYmVjYXVzZSBJIGNhbiByZWplY3QgSF8wIG9mIHRoZSBTaGFwaXJvLVdpbGsgdGVzdCBhdCBwIDwgMC4wMDEgYW5kIGFjY2VwdCBIXzEgdGhhdCBQcmljZSBpcyBOT1Qgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuDQoNClRodXMsIEkgd29uJ3QgdXNlIHRoZSB0LXRlc3QgYnV0IGl0cyBhbHRlcm5hdGl2ZSwgdGhlIFdpbGNveG9uIFNpZ25lZCBSYW5rIFRlc3Qgd2l0aCBIXzAgYmVpbmcgTWVkaWFuX1ByaWNlID0gMTkwMCBhbmQgSF8xIGJlaW5nIE1lZGlhbl9QcmljZSA9Lz0gMTkwMCBhbmQgY2Fubm90IHJlamVjdCBIXzAgYXQgcCA9IDAuMDI4IGFuZCBjb25jbHVkZSB0aGF0IE1lZGlhbl9QcmljZSA9IDE5MDAsIHdoaWNoIGFjY29yZGluZyB0byBmdW5kZXIyMDE5IGlzIGEgbWVkaXVtIGVmZmVjdCBzaXplLg0KDQoNCiMgNC4gRXN0aW1hdGUgdGhlIHNpbXBsZSByZWdyZXNzaW9uIGZ1bmN0aW9uOiBQcmljZSA9IGYoQWdlKS4gU2F2ZSByZXN1bHRzIGluIG9iamVjdCBmaXQxIGFuZCBleHBsYWluIHRoZSBlc3RpbWF0ZSBvZiByZWdyZXNzaW9uIGNvZWZmaWNpZW50LCBjb2VmZmljaWVudCBvZiBjb3JyZWxhdGlvbiBhbmQgY29lZmZpY2llbnQgb2YgZGV0ZXJtaW5hdGlvbi4gKDIgcCkNCmBgYHtyfQ0KIyBTY2F0dGVycGxvdA0Kc2NhdHRlcnBsb3QoUHJpY2UgfiBBZ2UsDQogICAgICAgICAgICB5bGFiID0gIlByaWNlIHBlciBtMiIsDQogICAgICAgICAgICB4bGFiID0gIkFnZSBvZiBhcGFybWVudCBpbiB5ZWFycyIsDQogICAgICAgICAgICBzbW9vdGggPSBGQUxTRSwNCiAgICAgICAgICAgIGRhdGEgPSBhcGFydG1lbnRzKQ0KDQojIFJlZ3Jlc3Npb24gd2l0aCBBZ2UgYXMgYSBwcmVkaWN0b3IgZm9yIHByaWNlDQpmaXQxIDwtIGxtKFByaWNlIH4gQWdlLA0KICAgICAgICAgIGRhdGEgPSBhcGFydG1lbnRzKQ0KDQpzdW1tYXJ5KGZpdDEpDQoNCiMgQ29ycmVsYXRpb24gY29lZmZpY2llbnQNCmNvcl9jb2VmMSA8LSBzcXJ0KHN1bW1hcnkoZml0MSkkci5zcXVhcmVkKQ0KY29yX2NvZWYxDQoNCmBgYA0KDQojIyBSZWdyZXNzaW9uIENvZWZmaWNpZW50Og0KDQotIEFnZTogUmVqZWN0IEhfMCBhdCBwID0gMC4wMzQgYW5kIGFjY2VwdCBIXzEgdGhhdCBiZXRhIGlzIE5PVCBlcXVhbCB0byAwIGFuZCB0aGF0IHdlIGhhdmUgYSBzaWduaWZpY2FudCBuZWdhdGl2ZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIEFnZSBhbmQgUHJpY2UgYW5kIGVhY2ggYWRkaXRpb25hbCB5ZWFyIHRoYXQgYW4gYXBhcnRtZW50IGFnZXMgbGVhZHMgdG8gYW4gYXZlcmFnZSBkZWNyZWFzZSBvZiBpdHMgcHJpY2UgcGVyIG3CsiBvZiA4Ljk3NSBldXIuDQoNCiMjIENvcnJlbGF0aW9uIENvZWZmaWNpZW50Og0KDQpBIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IG9mIG9ubHkgMC4yMzAgaW5kaWNhdGVzIGEgd2VhayBuZWdhdGl2ZSBsaW5lYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIGFnZSBvZiBhbiBhcGFydG1lbnQgYW5kIGl0cyBwcmljZSBwZXIgbcKyLg0KDQojIyBEZXRlcm1pbmF0aW9uIENvZWZmaWNpZW50Og0KDQpKdWRnaW5nIGJ5IHRoZSBSLXNxdWFyZWQsIGFwcHJveGltYXRlbHkgNS4zMDIlIG9mIHRoZSB2YXJpYXRpb24gaW4gdGhlIHByaWNlIHBlciBtwrIgY2FuIGJlIGV4cGxhaW5lZCBieSBrbm93aW5nIHRoZSBhZ2Ugb2YgdGhlIGFwYXJ0bWVudC4gVGhpcyB2ZXJ5IGxvdyBSLXNxdWFyZWQgdmFsdWUgc3VnZ2VzdHMgdGhhdCBvdGhlciBmYWN0b3JzIGJlc2lkZXMgYWdlIHBsYXkgc2lnbmlmaWNhbnQgcm9sZXMgaW4gZGV0ZXJtaW5pbmcgdGhlIHByaWNlIHBlciBtwrIgb2YgYXBhcnRtZW50cy4NCg0KDQojIDUuIFNob3cgdGhlIHNjYXR0ZXJwbG90IG1hdHJpeCBiZXR3ZWVuIFByaWNlLCBBZ2UgYW5kIERpc3RhbmNlLiBCYXNlZCBvbiB0aGUgbWF0cml4IGRldGVybWluZSBpZiB0aGVyZSBpcyBhIHBvdGVudGlhbCBwcm9ibGVtIHdpdGggbXVsdGljb2xpbmVhcml0eS4gKDAuNSBwKQ0KYGBge3J9DQojIFNjYXR0ZXJwbG90DQpzY2F0dGVycGxvdE1hdHJpeCh+IFByaWNlICsgQWdlICsgRGlzdGFuY2UsIGRhdGEgPSBhcGFydG1lbnRzKQ0KDQpgYGANCg0KTG9va2luZyBhdCB0aGUgc2NhdHRlcnBsb3QgbWF0cml4IGZvciBQcmljZSwgQWdlIGFuZCBEaXN0YW5jZSwgd2UgY2FuIHNlZSB0aGF0Og0KDQotIFByaWNlIHZzLiBBZ2U6IFRoaXMgc2NhdHRlcnBsb3Qgc3VnZ2VzdHMgYSBzbGlnaHQgbmVnYXRpdmUgdHJlbmQgd2hlcmUgUHJpY2UgZGVjcmVhc2VzIGFzIEFnZSBpbmNyZWFzZXMuIFdoaWxlIHRoZXJlIGlzIHNvbWUgdmFyaWF0aW9uLCB0aGUgcGF0dGVybiBkb2VzIHN1Z2dlc3QgYSBwb3NzaWJsZSByZWxhdGlvbnNoaXAuDQoNCi0gUHJpY2UgdnMuIERpc3RhbmNlOiBUaGlzIHBsb3Qgc2hvd3MgYSBjbGVhciBuZWdhdGl2ZSB0cmVuZCB3aGVyZSBQcmljZSBkZWNyZWFzZXMgYXMgRGlzdGFuY2UgaW5jcmVhc2VzLCBzdWdnZXN0aW5nIHRoYXQgYXBhcnRtZW50cyBjbG9zZXIgdG8gdGhlIGNpdHkgY2VudGVyIHNob3VsZCBiZSBwcmljZWQgaGlnaGVyLiBUaGlzIHJlbGF0aW9uc2hpcCBhcHBlYXJzIHRvIGJlIG1vZGVyYXRlbHkgc3Ryb25nIGFuZCBjb3VsZCBiZSBzaWduaWZpY2FudC4NCg0KLSBBZ2UgdnMuIERpc3RhbmNlOiBUaGlzIHNjYXR0ZXJwbG90IGRvZXMgbm90IHNob3cgYSBjbGVhciB0cmVuZCBhbmQgSSB3b3VsZCBhcmd1ZSB0aGF0IHRoZXJlIHNob3VsZCBub3QgYmUgYSBjb3JyZWxhdGlvbiBiZXR3ZWVuIEFnZSBhbmQgRGlzdGFuY2UgYW5kIG5vIHByb2JsZW1zIHdpdGggbXVsdGljb2xsaW5lYXJpdHkgd2hlbiBwcmVkaWN0aW5nIFByaWNlLg0KDQoNCiMgNi4gRXN0aW1hdGUgdGhlIG11bHRpcGxlIHJlZ3Jlc3Npb24gZnVuY3Rpb246IFByaWNlID0gZihBZ2UsIERpc3RhbmNlKS4gU2F2ZSBpdCBpbiBvYmplY3QgbmFtZWQgZml0Mi4NCg0KYGBge3J9DQojIFJlZ3Jlc3Npb24gd2l0aCBBZ2UgYW5kIERpc3RhbmNlIGFzIGEgcHJlZGljdG9ycyBmb3IgUHJpY2UNCmZpdDIgPC0gbG0oUHJpY2UgfiBBZ2UgKyBEaXN0YW5jZSwNCiAgICAgICAgICBkYXRhID0gYXBhcnRtZW50cykNCg0Kc3VtbWFyeShmaXQyKQ0KDQojIENvcnJlbGF0aW9uIGNvZWZmaWNpZW50DQpjb3JfY29lZjIgPC0gc3FydChzdW1tYXJ5KGZpdDIpJHIuc3F1YXJlZCkNCmNvcl9jb2VmMg0KDQpgYGANCg0KIyMgUmVncmVzc2lvbiBDb2VmZmljaWVudHM6DQoNCi0gQWdlOiBMaWtlIHdpdGggdGhlIHByZXZpb3VzIHJlZ3Jlc3Npb24sIHJlamVjdCBIXzAgYnV0IHRoaXMgdGltZSBhdCBhIG1vcmUgc2lnbmlmaWNhbnQgcCA9IDAuMDE2IGFuZCBhY2NlcHQgSF8xIHRoYXQgYmV0YSBpcyBOT1QgZXF1YWwgdG8gMCBhbmQgdGhhdCB3ZSBoYXZlIGEgc2lnbmlmaWNhbnQgbmVnYXRpdmUgY29ycmVsYXRpb24gYmV0d2VlbiBBZ2UgYW5kIFByaWNlIGFuZCBlYWNoIGFkZGl0aW9uYWwgeWVhciB0aGF0IGFuIGFwYXJ0bWVudCBhZ2VzIGxlYWRzIHRvIGFuIGF2ZXJhZ2UgZGVjcmVhc2Ugb2YgaXRzIHByaWNlIHBlciBtwrIgb2YgNy45MzQgZXVyLg0KDQotIERpc3RhbmNlOiBSZWplY3QgSF8wIGF0IHAgPCAwLjAwMSBhbmQgYWNjZXB0IEhfMSB0aGF0IGJldGEgaXMgTk9UIGVxdWFsIHRvIDAgYW5kIHRoYXQgd2UgaGF2ZSBhIHNpZ25pZmljYW50IG5lZ2F0aXZlIGNvcnJlbGF0aW9uIGJldHdlZW4gRGlzdGFuY2UgYW5kIFByaWNlIGFuZCBlYWNoIGFkZGl0aW9uYWwga20gdGhhdCBhbiBhcGFydG1lbnQgaXMgZnVydGhlciBhd2F5IGZyb20gdGhlIGNpdHkgY2VudGVyIGxlYWRzIHRvIGFuIGF2ZXJhZ2UgZGVjcmVhc2Ugb2YgaXRzIHByaWNlIHBlciBtwrIgb2YgMjAuNjY3IGV1ci4NCg0KIyMgQ29ycmVsYXRpb24gQ29lZmZpY2llbnQ6DQoNCkEgY29ycmVsYXRpb24gY29lZmZpY2llbnQgb2Ygb25seSAwLjY2MiBpbmRpY2F0ZXMgYSBzZW1pLXN0cm9uZyBuZWdhdGl2ZSBsaW5lYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIGFnZSBvZiBhbiBhcGFydG1lbnQsIGl0cyBkaXN0YW5jZSBmcm9tIHRoZSBjaXR5IGNlbnRlciBhbmQgaXRzIHByaWNlIHBlciBtwrIuDQoNCiMjIERldGVybWluYXRpb24gQ29lZmZpY2llbnQ6DQoNCkp1ZGdpbmcgYnkgdGhlIFItc3F1YXJlZCwgYXBwcm94aW1hdGVseSA0My45NiUgb2YgdGhlIHZhcmlhdGlvbiBpbiB0aGUgcHJpY2UgcGVyIG3CsiBjYW4gYmUgZXhwbGFpbmVkIGJ5IGtub3dpbmcgdGhlIGFnZSBhbmQgZGlzdGFuY2UgZnJvbSB0aGUgY2l0eSBjZW50ZXIgb2YgdGhlIGFwYXJ0bWVudC4gVGhpcyBnb29kIFItc3F1YXJlZCB2YWx1ZSBzdWdnZXN0cyB0aGF0IGFnZSBhbmQgZGlzdGFuY2UgZXhwbGFpbiB0aGUgcHJpY2UgdG8gYSBkZWNlbnQgZGVncmVlIGJ1dCBzdGlsbCBsZXNzIHRoYW4gaGFsZiwgc28gb3RoZXIgZmFjdG9ycyBiZXNpZGVzIHRoZW0gcGxheSBhIGJpZ2dlciByb2xlIGluIGRldGVybWluaW5nIHRoZSBwcmljZSBwZXIgbcKyIG9mIGFwYXJ0bWVudHMuDQoNCg0KIyA3LiBDaGVjayB0aGUgbXVsdGljb2xpbmVhcml0eSB3aXRoIFZJRiBzdGF0aXN0aWNzLiBFeHBsYWluIHRoZSBmaW5kaW5ncy4gKDEgcCkNCg0KYGBge3J9DQojIFZJRiBzdGF0aXNjdGljDQp2aWYoZml0MikNCm1lYW4odmlmKGZpdDIpKQ0KDQpgYGANCg0KQm90aCBWSUYncyBhcmUgd2F5IGJlbG93IDUgYW5kIHRoZSBhdmVyYWdlIFZJRiBpcyBjbG9zZSB0byAxLCBzbyB0aGVyZSBpcyBubyBpc3N1ZSB3aXRoIG11bHRpY29saW5pZWFyaXR5Lg0KDQoNCiMgOC4gQ2FsY3VsYXRlIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgYW5kIENvb2tzIERpc3RhbmNlcyBmb3IgbW9kZWwgZml0Mi4gUmVtb3ZlIGFueSBwb3RlbnRpYWxseSBwcm9ibGVtYXRpYyB1bml0cyAob3V0bGllcnMgb3IgdW5pdHMgd2l0aCBoaWdoIGluZmx1ZW5jZSkuICgyIHApDQoNCmBgYHtyfQ0KIyBTdGFuZGFyZGl1ZWQgcmVzaWR1YWxzIGFuZCBjb29rcyBkaXN0YW5jZQ0KYXBhcnRtZW50cyRTdGRSZXNpZCA8LSByb3VuZChyc3RhbmRhcmQoZml0MiksIDMpDQphcGFydG1lbnRzJFN0ZEZpdHRlZCA8LSBzY2FsZShmaXQyJGZpdHRlZC52YWx1ZXMpDQphcGFydG1lbnRzJENvb2tzRCA8LSByb3VuZChjb29rcy5kaXN0YW5jZShmaXQyKSwgMykNCg0KaGlzdChhcGFydG1lbnRzJFN0ZFJlc2lkLA0KICAgICB4bGFiID0gIlN0YW5kYXJkaXplZCBSZXNpZHVhbHMiLA0KICAgICB5bGFiID0gIkZyZXF1ZW5jeSIsDQogICAgIG1haW4gPSAiSGlzdG9ncmFtIG9mIHN0YW5kYXJkaXplZCByZXNpZHVhbHMiKQ0KDQojIENoZWNrIGlmIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgYXJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkDQpzaGFwaXJvLnRlc3QoYXBhcnRtZW50cyRTdGRSZXNpZCkNCg0KaGlzdChhcGFydG1lbnRzJENvb2tzRCwNCiAgICAgeGxhYiA9ICJDb29rcyBkaXN0YW5jZSIsDQogICAgIHlsYWIgPSAiRnJlcXVlbmN5IiwNCiAgICAgbWFpbiA9ICJIaXN0b2dyYW0gb2YgQ29va3MgZGlzdGFuY2VzIikNCg0KYGBgDQoNCkp1ZGdpbmcgYnkgdGhlIGhpc3RvZ3JhbSBvZiB0aGUgc3RhbmRhcmRpemVkIHJlc2lkdWFscywgYWxsIHJlc2lkdWFscyBhcmUgYmV0d2VlbiArLTMgd2hlcmUgdGhleSBzaG91bGQgYmUgc28gd2UgdGVjaG5pY2FsbHkgZG8gbm90IGhhdmUgYW55IG91dGxpZXJzIGJ1dCB0aGVyZSBzZWVtIHRvIGJlIGVudHJpZXMgd2l0aCB2YWx1ZXMgYm90aCBhdCB0aGUgbG93ZXIgYW5kIHVwcGVyIGVuZCB0aGF0IGRvIG5vdCBiZWxvbmcgdG8gdGhlIG1ham9yaXR5LiBIb3dldmVyLCB0aGV5IGRvIE5PVCBzZWVtIHRvIGJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIHdoaWNoIGlzIGNvbmZpcm1lZCBieSB0aGUgU2hhcGlyby1XaWxrIFRlc3Qgb24gdGhlbSB3aGVyZSBJIGhhdmUgdG8gcmVqZWN0IEhfMCBhdCBwID0gMC4wMDQgdGhhdCB0aGV5IGFyZSBub3JtYWxseSBkaXN0cmlidXRlZCBhbmQgYWNjZXB0IEhfMSB0aGF0IHRoZSBhcmUgTk9UIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLg0KDQpGdXJ0aGVybW9yZSwgYnkgdGFraW5nIGEgbG9vayBhdCB0aGUgaGlzdG9ncmFtIG9mIHRoZSBDb29rcyBkaXN0YW5jZXMsIGl0IGJlY29tZXMgb2J2aW91cyB0aGF0IHRoZXJlIGlzIGEgbGFyZ2UgZ2FwIGJldHdlZW4gMC4xNSBhbmQgMC4zMCBhbmQgSSBuZWVkIHRvIHJlbW92ZSB0aGUgaGlnaCBpbXBhY3Qgb3V0bGllcnMgYWJvdmUgdGhhdCBnYXAuDQoNCmBgYHtyfQ0KIyBDaGVjayBmb3IgaGlnaGcgaW1wYWN0IG91dGxpZXJzIHdpdGggdGhlIGhpZ2hlc3QgQ29va3MgZGlzdGFuY2VzDQpoZWFkKGFwYXJ0bWVudHNbb3JkZXIoLWFwYXJ0bWVudHMkQ29va3NEKSxdLCAxMCkNCg0KIyBSZW1vdmUgaWRlbnRpZmllZCBoaWdoIGltcGFjdCBvdXRsaWVycw0KYXBhcnRtZW50cyA8LSBhcGFydG1lbnRzICU+JQ0KICBmaWx0ZXIoIUNvb2tzRCA9PSAwLjMyMCkNCg0KaGlzdChhcGFydG1lbnRzJFN0ZFJlc2lkLA0KICAgICB4bGFiID0gIlN0YW5kYXJkaXplZCBSZXNpZHVhbHMiLA0KICAgICB5bGFiID0gIkZyZXF1ZW5jeSIsDQogICAgIG1haW4gPSAiSGlzdG9ncmFtIG9mIHN0YW5kYXJkaXplZCByZXNpZHVhbHMiKQ0KDQojIENoZWNrIGlmIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgYXJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkDQpzaGFwaXJvLnRlc3QoYXBhcnRtZW50cyRTdGRSZXNpZCkNCg0KaGlzdChhcGFydG1lbnRzJENvb2tzRCwNCiAgICAgeGxhYiA9ICJDb29rcyBkaXN0YW5jZSIsDQogICAgIHlsYWIgPSAiRnJlcXVlbmN5IiwNCiAgICAgbWFpbiA9ICJIaXN0b2dyYW0gb2YgQ29va3MgZGlzdGFuY2VzIikNCg0KYGBgDQoNClN0aWxsIHNvbWUgZ2FwcyByZW1haW4gaW4gdGhlIENvb2tzIGRpc3RhbmNlIHBsb3QgdGhhdCB3ZXJlIG5vdCBvYnZpb3VzIGJlZm9yZSBhbmQgd2UgbmVlZCB0byBleGNsdWRlIGV2ZW4gbW9yZSBlbnRyaWVzIHdoZXJlIHRoZSBDb29rcyBkaXNhbmNlcyBhcmUgYWJvdmUgMC4wNC4NCg0KYGBge3J9DQojIENoZWNrIGZvciBoaWdoZyBpbXBhY3Qgb3V0bGllcnMgd2l0aCB0aGUgaGlnaGVzdCBDb29rcyBkaXN0YW5jZXMNCmhlYWQoYXBhcnRtZW50c1tvcmRlcigtYXBhcnRtZW50cyRDb29rc0QpLF0sIDEwKQ0KDQojIFJlbW92ZSBpZGVudGlmaWVkIGhpZ2ggaW1wYWN0IG91dGxpZXJzDQphcGFydG1lbnRzIDwtIGFwYXJ0bWVudHMgJT4lDQogIGZpbHRlcighQ29va3NEID4gMC4wNCkNCg0KaGlzdChhcGFydG1lbnRzJFN0ZFJlc2lkLA0KICAgICB4bGFiID0gIlN0YW5kYXJkaXplZCBSZXNpZHVhbHMiLA0KICAgICB5bGFiID0gIkZyZXF1ZW5jeSIsDQogICAgIG1haW4gPSAiSGlzdG9ncmFtIG9mIHN0YW5kYXJkaXplZCByZXNpZHVhbHMiKQ0KDQojIENoZWNrIGlmIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgYXJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkDQpzaGFwaXJvLnRlc3QoYXBhcnRtZW50cyRTdGRSZXNpZCkNCg0KaGlzdChhcGFydG1lbnRzJENvb2tzRCwNCiAgICAgeGxhYiA9ICJDb29rcyBkaXN0YW5jZSIsDQogICAgIHlsYWIgPSAiRnJlcXVlbmN5IiwNCiAgICAgbWFpbiA9ICJIaXN0b2dyYW0gb2YgQ29va3MgZGlzdGFuY2VzIikNCg0KYGBgDQoNCkFmdGVyIHJlbW92aW5nIGFsbCBoaWdoIGltcGFjdCBvdXRsaWVycywgYWxsIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgbm93IGZhbGwgaW4gYSBuYXJyb3dlciBiYW5kLCBhbGJlaXQgc3RpbGwgTk9UIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIGFjY29yZGluZyB0byB0aGUgU2hhcGlyby1XaWxrIFRlc3Qgd2hlcmUgSSBuZWVkIHRvIHJlamVjdCBIXzAgYXQgcCA8IDAuMDAxIGFuZCBhY2NlcHQgSF8xLCBhbmQgbW9yZSBpbXBvcnRhbnRseSB0aGVyZSBhcmUgbm8gbW9yZSBnYXBzIGluIHRoZSBDb29rcyBkaXN0YW5jZXMgaGlzdG9ncmFtLg0KDQoNCiMgOS4gQ2hlY2sgZm9yIHBvdGVudGlhbCBoZXRlcm9za2VkYXN0aWNpdHkgd2l0aCBzY2F0dGVycGxvdCBiZXR3ZWVuIHN0YW5kYXJpemVkIHJlc2lkdWFscyBhbmQgc3RhbmRhcmRpemVkIGZpdHRlZCB2YWx1ZXMuIEV4cGxhaW4gdGhlIGZpbmRpbmdzLiAoMSBwKQ0KDQpgYGB7cn0NCiMgQ2hlY2sgZm9yIHBvdGVudGlhbCBoZXRlcm9za2VkYXN0aWNpdHkNCnNjYXR0ZXJwbG90KHkgPSBhcGFydG1lbnRzJFN0ZFJlc2lkLCB4ID0gYXBhcnRtZW50cyRTdGRGaXR0ZWQsDQogICAgICAgICAgICB5bGFiID0gIlN0YW5kYXJkaXplZCBSZXNpZHVhbHMiLA0KICAgICAgICAgICAgeGxhYiA9ICJTdGFuZGFyZGl6ZWQgZml0dGVkIHZhbHVlcyIsDQogICAgICAgICAgICBib3hwbG90cyA9IEZBTFNFLA0KICAgICAgICAgICAgcmVnTGluZSA9IEZBTFNFLA0KICAgICAgICAgICAgc21vb3RoID0gRkFMU0UpDQoNCmBgYA0KDQpKdWRnaW5nIGJ5IHRoZSBzY2F0dGVycGxvdCBvZiB0aGUgc3RhbmRhcml6ZWQgcmVzaWR1YWxzIGFuZCBzdGFuZGFyZGl6ZWQgZml0dGVkIHZhbHVlcywgdGhlcmUgaXMgbm8gbGluZWFyaXR5IGlzc3VlIGFuZCBsaWtlbHkgbm8gaGV0ZXJvc2tlZGFzdGljaXR5IGlzc3VlIGEgd2VsbC4NCg0KDQojIDEwLiBBcmUgc3RhbmRhcmRpemVkIHJlc2lkdWFscyBkaXRyaWJ1dGVkIG5vcm1hbGx5PyBTaG93IHRoZSBncmFwaCBhbmQgZm9ybWFsbHkgdGVzdCBpdC4gRXhwbGFpbiB0aGUgZmluZGluZ3MuICgxIHApDQoNCmBgYHtyfQ0KaGlzdChhcGFydG1lbnRzJFN0ZFJlc2lkLA0KICAgICB4bGFiID0gIlN0YW5kYXJkaXplZCBSZXNpZHVhbHMiLA0KICAgICB5bGFiID0gIkZyZXF1ZW5jeSIsDQogICAgIG1haW4gPSAiSGlzdG9ncmFtIG9mIHN0YW5kYXJkaXplZCByZXNpZHVhbHMiKQ0KDQojIENoZWNrIGlmIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgYXJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkDQpzaGFwaXJvLnRlc3QoYXBhcnRtZW50cyRTdGRSZXNpZCkNCg0KYGBgDQoNCkFzIHN0YXRlZCBiZWZvcmUgaW4gOC4sIHRoZXJlIGlzIE5PIG5vcm1hbCBkaXN0cmlidXRpb24gb2YgdGhlIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgc2luY2UgImFmdGVyIHJlbW92aW5nIGFsbCBoaWdoIGltcGFjdCBvdXRsaWVycywgYWxsIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgbm93IGZhbGwgaW4gYSBuYXJyb3dlciBiYW5kLCBhbGJlaXQgc3RpbGwgTk9UIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIGFjY29yZGluZyB0byB0aGUgU2hhcGlyby1XaWxrIFRlc3Qgd2hlcmUgSSBuZWVkIHRvIHJlamVjdCBIXzAgYXQgcCA8IDAuMDAxIGFuZCBhY2NlcHQgSF8xLC4uLiINCg0KDQojIDExLiBFc3RpbWF0ZSB0aGUgZml0MiBhZ2FpbiB3aXRob3V0IHBvdGVudGlhbGx5IGV4Y2x1ZGVkIHVuaXRzIGFuZCBzaG93IHRoZSBzdW1tYXJ5IG9mIHRoZSBtb2RlbC4gRXhwbGFpbiBhbGwgY29lZmZpY2llbnRzLiAoMiBwKQ0KDQpgYGB7cn0NCiMgUmVncmVzc2lvbiB3aXRoIEFnZSBhbmQgRGlzdGFuY2UgYXMgYSBwcmVkaWN0b3JzIGZvciBQcmljZQ0KZml0MmIgPC0gbG0oUHJpY2UgfiBBZ2UgKyBEaXN0YW5jZSwNCiAgICAgICAgICBkYXRhID0gYXBhcnRtZW50cykNCg0Kc3VtbWFyeShmaXQyYikNCg0KIyBDb3JyZWxhdGlvbiBjb2VmZmljaWVudA0KY29yX2NvZWYyYiA8LSBzcXJ0KHN1bW1hcnkoZml0MmIpJHIuc3F1YXJlZCkNCmNvcl9jb2VmMmINCg0KIyBWSUYgc3RhdGlzY3RpYw0KdmlmKGZpdDJiKQ0KbWVhbih2aWYoZml0MmIpKQ0KDQpgYGANCg0KIyMgUmVncmVzc2lvbiBDb2VmZmljaWVudHM6DQoNCi1BZ2U6IExpa2Ugd2l0aCB0aGUgcHJldmlvdXMgcmVncmVzc2lvbiwgcmVqZWN0IEhfMCBidXQgdGhpcyB0aW1lIGF0IGEgZXZlbiBtb3JlIHNpZ25pZmljYW50IHAgPSAwLjAwOSBhbmQgYWNjZXB0IEhfMSB0aGF0IGJldGEgaXMgTk9UIGVxdWFsIHRvIDAgYW5kIHRoYXQgd2UgaGF2ZSBhIHNpZ25pZmljYW50IG5lZ2F0aXZlIGNvcnJlbGF0aW9uIGJldHdlZW4gQWdlIGFuZCBQcmljZSBhbmQgZWFjaCBhZGRpdGlvbmFsIHllYXIgdGhhdCBhbiBhcGFydG1lbnQgYWdlcyBsZWFkcyB0byBhbiBhdmVyYWdlIGRlY3JlYXNlIG9mIGl0cyBwcmljZSBwZXIgbcKyIG9mIDguNjc0IGV1ci4NCg0KLURpc3RhbmNlOiBSZWplY3QgSF8wIGF0IHAgPCAwLjAwMSBhbmQgYWNjZXB0IEhfMSB0aGF0IGJldGEgaXMgTk9UIGVxdWFsIHRvIDAgYW5kIHRoYXQgd2UgaGF2ZSBhIHNpZ25pZmljYW50IG5lZ2F0aXZlIGNvcnJlbGF0aW9uIGJldHdlZW4gRGlzdGFuY2UgYW5kIFByaWNlIGFuZCBlYWNoIGFkZGl0aW9uYWwga20gdGhhdCBhbiBhcGFydG1lbnQgaXMgZnVydGhlciBhd2F5IGZyb20gdGhlIGNpdHkgY2VudGVyIGxlYWRzIHRvIGFuIGF2ZXJhZ2UgZGVjcmVhc2Ugb2YgaXRzIHByaWNlIHBlciBtwrIgb2YgMjQuMDYzIGV1ci4NCg0KIyMgQ29ycmVsYXRpb24gQ29lZmZpY2llbnQ6DQoNCkEgY29ycmVsYXRpb24gY29lZmZpY2llbnQgb2YgMC43MzIgaW5kaWNhdGVzIGEgc3Ryb25nIG5lZ2F0aXZlIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgYWdlIG9mIGFuIGFwYXJ0bWVudCwgaXRzIGRpc3RhbmNlIGZyb20gdGhlIGNpdHkgY2VudGVyIGFuZCBpdHMgcHJpY2UgcGVyIG3Csi4NCg0KIyMgRGV0ZXJtaW5hdGlvbiBDb2VmZmljaWVudDoNCg0KSnVkZ2luZyBieSB0aGUgUi1zcXVhcmVkLCBhcHByb3hpbWF0ZWx5IDUzLjYxJSBvZiB0aGUgdmFyaWF0aW9uIGluIHRoZSBwcmljZSBwZXIgbcKyIGNhbiBiZSBleHBsYWluZWQgYnkga25vd2luZyB0aGUgYWdlIGFuZCBkaXN0YW5jZSBmcm9tIHRoZSBjaXR5IGNlbnRlciBvZiB0aGUgYXBhcnRtZW50LiBUaGlzIGdvb2QgUi1zcXVhcmVkIHZhbHVlIHN1Z2dlc3RzIHRoYXQgYWdlIGFuZCBkaXN0YW5jZSBleHBsYWluIHRoZSBwcmljZSB3ZWxsIHdpdGggbW9yZSB0aGFuIGhhbGYsIHNvIG90aGVyIGZhY3RvcnMgYmVzaWRlcyB0aGVtIHBsYXkgYSByb2xlIHRvbyBpbiBkZXRlcm1pbmluZyB0aGUgcHJpY2UgcGVyIG3CsiBvZiBhcGFydG1lbnRzIGJ1dCBhIHNtYWxsZXIgb25lLg0KDQpDb21wYXJlZCB0byB0aGUgcHJldmlvdXMgcmVncmVzc2lvbiB3aXRoIG91dGxpZXJzOiBSZW1vdmluZyB0aGUgb3V0bGllcnMgbWFkZSBib3RoIHByZWRpY3RvcnMgbW9yZSBzaWduaWZpY2FudCwgZXNwZWNpYWxseSBBZ2UsIGxlZCB0byBhbiBpbmNyZWFzZSBpbiB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgYW5kIG51ZGdlZCB0aGUgZGV0ZXJtaW5hdGlvbiBjb2VmZmljaWVudCBvdmVyIDUwJS4NCg0KDQojIDEyLiBFc3RpbWF0ZSB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gZnVuY3Rpb24gUHJpY2UgPSBmKEFnZSwgRGlzdGFuY2UsIFBhcmtpbmcgYW5kIEJhbGNvbnkpLiBCZSBjYXJlZnVsIHRvIGNvcnJlY3RseSBpbmNsdWRlIGNhdGVnb3JpY2FsIHZhcmlhYmxlcy4gU2F2ZSB0aGUgb2JqZWN0IG5hbWVkIGZpdDMuDQoNCmBgYHtyfQ0KIyBSZWdyZXNzaW9uIHdpdGggQWdlIGFuZCBEaXN0YW5jZSBhcyBhIHByZWRpY3RvcnMgZm9yIFByaWNlDQpmaXQzIDwtIGxtKFByaWNlIH4gQWdlICsgRGlzdGFuY2UgKyBQYXJraW5nICsgQmFsY29ueSwNCiAgICAgICAgICBkYXRhID0gYXBhcnRtZW50cykNCg0Kc3VtbWFyeShmaXQzKQ0KDQojIENvcnJlbGF0aW9uIGNvZWZmaWNpZW50DQpjb3JfY29lZjMgPC0gc3FydChzdW1tYXJ5KGZpdDMpJHIuc3F1YXJlZCkNCmNvcl9jb2VmMw0KDQojIFZJRiBzdGF0aXNjdGljDQp2aWYoZml0MykNCm1lYW4odmlmKGZpdDMpKQ0KDQpgYGANCg0KIyMgUmVncmVzc2lvbiBDb2VmZmljaWVudHM6DQoNCi0gQWdlOiBMaWtlIHdpdGggdGhlIHByZXZpb3VzIHJlZ3Jlc3Npb24gdXNpbmcgb25seSB0d28gcHJlZGljdG9ycywgcmVqZWN0IEhfMCBidXQgdGhpcyB0aW1lIGF0IGEgbGVzcyBzaWduaWZpY2FudCBwID0gMC4wMTUgYW5kIGFjY2VwdCBIXzEgdGhhdCBiZXRhIGlzIE5PVCBlcXVhbCB0byAwIGFuZCB0aGF0IHdlIGhhdmUgYSBzaWduaWZpY2FudCBuZWdhdGl2ZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIEFnZSBhbmQgUHJpY2UgYW5kIGVhY2ggYWRkaXRpb25hbCB5ZWFyIHRoYXQgYW4gYXBhcnRtZW50IGFnZXMgbGVhZHMgdG8gYW4gYXZlcmFnZSBkZWNyZWFzZSBvZiBpdHMgcHJpY2UgcGVyIG3CsiBvZiA3Ljk3MCBldXIgYXNzdW1pbmcgYWxsIG90aGVyIHZhcmlhYmxlcyByZW1haW4gdW5jaGFuZ2VkLg0KDQotIERpc3RhbmNlOiBSZWplY3QgSF8wIGF0IHAgPCAwLjAwMSBhbmQgYWNjZXB0IEhfMSB0aGF0IGJldGEgaXMgTk9UIGVxdWFsIHRvIDAgYW5kIHRoYXQgd2UgaGF2ZSBhIHNpZ25pZmljYW50IG5lZ2F0aXZlIGNvcnJlbGF0aW9uIGJldHdlZW4gRGlzdGFuY2UgYW5kIFByaWNlIGFuZCBlYWNoIGFkZGl0aW9uYWwga20gdGhhdCBhbiBhcGFydG1lbnQgaXMgZnVydGhlciBhd2F5IGZyb20gdGhlIGNpdHkgY2VudGVyIGxlYWRzIHRvIGFuIGF2ZXJhZ2UgZGVjcmVhc2Ugb2YgaXRzIHByaWNlIHBlciBtwrIgb2YgMjEuOTYxIGV1ciBhc3N1bWluZyBhbGwgb3RoZXIgdmFyaWFibGVzIHJlbWFpbiB1bmNoYW5nZWQuDQoNCi0gUGFya2luZzogUmVqZWN0IEhfMCBhdCBwID0gMC4wMzggYW5kIGFjY2VwdCBIXzEgdGhhdCBiZXRhIGlzIE5PVCBlcXVhbCB0byAwIGFuZCB0aGF0IHdlIGhhdmUgYSBzaWduaWZpY2FudCBwb3NpdGl2ZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIFBhcmtpbmcgYW5kIFByaWNlIGFuZCBoYXZpbmcgcGFya2luZyBzcGFjZSBsZWFkcyB0byBhbiBhdmVyYWdlIGluY3JlYXNlIG9mIGl0cyBwcmljZSBwZXIgbcKyIG9mIDEyOC43MDAgZXVyIGFzc3VtaW5nIGFsbCBvdGhlciB2YXJpYWJsZXMgcmVtYWluIHVuY2hhbmdlZC4NCg0KIyMgQ29ycmVsYXRpb24gQ29lZmZpY2llbnQ6IEEgY29ycmVsYXRpb24gY29lZmZpY2llbnQgb2YgMC43NSBpbmRpY2F0ZXMgYSBzdHJvbmcgbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBhZ2Ugb2YgYW4gYXBhcnRtZW50LCBpdHMgZGlzdGFuY2UgZnJvbSB0aGUgY2l0eSBjZW50ZXIsIHRoZSBhdmFpbGFiaWxpdHkgb2YgcGFya2luZyBzcGFjZSBhbmQgaXRzIHByaWNlIHBlciBtwrIuDQoNCiMjIERldGVybWluYXRpb24gQ29lZmZpY2llbnQ6DQoNCkp1ZGdpbmcgYnkgdGhlIFItc3F1YXJlZCwgYXBwcm94aW1hdGVseSA1My44OSUgb2YgdGhlIHZhcmlhdGlvbiBpbiB0aGUgcHJpY2UgcGVyIG3CsiBjYW4gYmUgZXhwbGFpbmVkIGJ5IGtub3dpbmcgdGhlIGFnZSwgZGlzdGFuY2UgZnJvbSB0aGUgY2l0eSBjZW50ZXIgb2YgdGhlIGFwYXJ0bWVudCBhbmQgdGhlIGF2YWlsYWJpbGl0eSBvZiBwYXJraW5nIHNwYWNlcy4gVGhpcyBnb29kIFItc3F1YXJlZCB2YWx1ZSBzdWdnZXN0cyB0aGF0IGFnZSwgZGlzdGFuY2UgYW5kIHBhcmtpbmcgZXhwbGFpbiB0aGUgcHJpY2Ugd2VsbCB3aXRoIG1vcmUgdGhhbiBoYWxmLCBzbyBvdGhlciBmYWN0b3JzIGJlc2lkZXMgdGhlbSBwbGF5IGEgcm9sZSB0b28gaW4gZGV0ZXJtaW5pbmcgdGhlIHByaWNlIHBlciBtwrIgb2YgYXBhcnRtZW50cyBidXQgYSBzbWFsbGVyIG9uZS4NCg0KDQojIDEzLiBXaXRoIGZ1bmN0aW9uIGFub3ZhIGNoZWNrIGlmIG1vZGVsIGZpdDMgZml0cyBkYXRhIGJldHRlciB0aGFuIG1vZGVsIGZpdDIuICgxIHApDQoNCmBgYHtyfQ0KIyBDb21wYXJlIHJlZ3Jlc3Npb24gbW9kZWxzDQphbm92YShmaXQyYiwgZml0MykNCg0KYGBgDQoNCi0gUmVzaWR1YWwgRGVncmVlcyBvZiBGcmVlZG9tOiAgTW9kZWwgMSwgdGhpcyBpcyA3NywgYW5kIGZvciBNb2RlbCAyLCBpdCBpcyA3NS4gVGhlIGRpZmZlcmVuY2UgaW4gZGVncmVlcyBvZiBmcmVlZG9tIGNvcnJlc3BvbmRzIHRvIHRoZSBudW1iZXIgb2YgYWRkaXRpb25hbCBwcmVkaWN0b3JzIFBhcmtpbmcgYW5kIEJhbGNvbnkgaW5jbHVkZWQgaW4gTW9kZWwgMiBjb21wYXJlZCB0byBNb2RlbCAxLg0KDQotIFJlc2lkdWFsIFN1bSBvZiBTcXVhcmVzOiAgTW9kZWwgMSwgdGhlIFJTUyBpcyA1LDA3NywzNjIsIGFuZCBmb3IgTW9kZWwgMiwgaXQgaXMgNCw3OTEsMTI4LiBBIGxvd2VyIFJTUyBpbmRpY2F0ZXMgYSBiZXR0ZXIgbW9kZWwgZml0IGFzIGl0IHN1Z2dlc3RzIHNtYWxsZXIgZGV2aWF0aW9ucyBvZiB0aGUgb2JzZXJ2ZWQgdmFsdWVzIGZyb20gdGhlIG1vZGVsJ3MgcHJlZGljdGVkIHZhbHVlcy4NCg0KLURlZ3JlZXMgb2YgRnJlZWRvbTogVGhpcyBpcyB0aGUgZGlmZmVyZW5jZSBpbiB0aGUgbnVtYmVyIG9mIHBhcmFtZXRlcnMgYmV0d2VlbiB0aGUgdHdvIG1vZGVscy4gSGVyZSwgMiBhZGRpdGlvbmFsIHBhcmFtZXRlcnMgYXJlIGVzdGltYXRlZCBpbiBNb2RlbCAyIHdpdGggdGhlIGluY2x1c2lvbiBvZiBQYXJraW5nIGFuZCBCYWxjb255Lg0KDQotIFN1bSBvZiBTcXVhcmVzOiBUaGlzIHNob3dzIHRoZSBkaWZmZXJlbmNlIGluIFJTUyBiZXR3ZWVuIHRoZSB0d28gbW9kZWxzLCB3aGljaCBpcyAyODYsMjM0LiBUaGlzIHZhbHVlIHJlcHJlc2VudHMgdGhlIGltcHJvdmVtZW50IGluIG1vZGVsIGZpdCB0aGF0IGNhbiBiZSBhdHRyaWJ1dGVkIHRvIHRoZSBhZGRpdGlvbiBvZiB0aGUgbmV3IHBhcmFtZXRlcnMuDQoNCi0gRi1zdGF0aXN0aWM6IFdpdGggYSB2YWx1ZSBpcyAyLjI0MDMuIEl0IHRlc3RzIHdoZXRoZXIgdGhlIGV4dHJhIHBhcmFtZXRlcnMgYWRkZWQgaW4gTW9kZWwgMiBzaWduaWZpY2FudGx5IGltcHJvdmUgdGhlIG1vZGVsJ3MgZml0Lg0KDQpTaW5jZSB0aGUgcC12YWx1ZSBpcyAwLjExNCwgd2UgY2FuIE5PVCByZWplY3QgSF8wIHRoYXQgdGhlIGFkZGl0aW9uIG9mIFBhcmtpbmcgYW5kIEJhbGNvbnkgZG9lcyBwcm92aWRlIGEgc2lnbmlmaWNhbnQgaW1wcm92ZW1lbnQgaW4gcHJlZGljdGluZyBQcmljZSBvdmVyIGp1c3QgdXNpbmcgQWdlIGFuZCBEaXN0YW5jZSBhbmQgTW9kZWwgMSAoUHJpY2UgfiBBZ2UgKyBEaXN0YW5jZSkgaXMgc3VmZmljaWVudCBmb3IgbW9kZWxpbmcgdGhlIHJlbGF0aW9uc2hpcCBhbmQgSSB3b3VsZCBvbmx5IGluY2x1ZGUgUGFya2luZyBhbmQvb3IgQmFsY29ueSBpZiByZXF1aXJlZCBieSBzaW1pbGFyIHBhc3QgcmVzZWFyY2ggZm9yIGV4YW1wbGUuDQoNCg0KIyAxNC4gU2hvdyB0aGUgcmVzdWx0cyBvZiBmaXQzIGFuZCBleHBsYWluIHJlZ3Jlc3Npb24gY29lZmZpY2llbnQgZm9yIGJvdGggY2F0ZWdvcmljYWwgdmFyaWFibGVzLiBDYW4geW91IHdyaXRlIGRvd24gdGhlIGh5cG90aGVzaXMgd2hpY2ggaXMgYmVpbmcgdGVzdGVkIHdpdGggRi1zdGF0aXN0aWNzLCBzaG93biBhdCB0aGUgYm90dG9tIG9mIHRoZSBvdXRwdXQ/ICgyIHApDQoNCmBgYHtyfQ0Kc3VtbWFyeShmaXQzKQ0KDQpgYGANCg0KIyMgQ2F0ZWdvcmljYWwgUmVncmVzc2lvbiBDb2VmZmljaWVudHM6DQoNCi0gQXMgc3RhdGVkIGluIDEyLiBmb3IgUGFya2luZzogIlJlamVjdCBIXzAgYXQgcCA9IDAuMDM4IGFuZCBhY2NlcHQgSF8xIHRoYXQgYmV0YSBpcyBOT1QgZXF1YWwgdG8gMCBhbmQgdGhhdCB3ZSBoYXZlIGEgc2lnbmlmaWNhbnQgcG9zaXRpdmUgY29ycmVsYXRpb24gYmV0d2VlbiBQYXJraW5nIGFuZCBQcmljZSBhbmQgaGF2aW5nIHBhcmtpbmcgc3BhY2UgbGVhZHMgdG8gYW4gYXZlcmFnZSBpbmNyZWFzZSBvZiBpdHMgcHJpY2UgcGVyIG3CsiBvZiAxMjguNzAwIGV1ciBhc3N1bWluZyBhbGwgb3RoZXIgdmFyaWFibGVzIHJlbWFpbiB1bmNoYW5nZWQuIg0KDQotICBCYWxjb255OiBJIGNhbiBOT1QgcmVqZWN0IEhfMCB3aXRoIGEgaGlnaCBwID0gMC45MTcgYW5kIGFzc3VtZSB0aGF0IGJldGEgaXMgZXF1YWwgdG8gMCBhbmQgdGhhdCB3ZSBoYXZlIE5PIHNpZ25pZmljYW50IGNvcnJlbGF0aW9uIGJldHdlZW4gQmFsY29ueSBhbmQgUHJpY2UgYW5kIGhhdmluZyBhIGJhbGNvbnkgZG9lcyBOT1QgbGVhZCB0byBhbiBhdmVyYWdlIGluY3JlYXNlIG9mIGl0cyBwcmljZSBwZXIgbcKyIGFzc3VtaW5nIGFsbCBvdGhlciB2YXJpYWJsZXMgcmVtYWluIHVuY2hhbmdlZC4NCg0KIyMgRi1zdGF0aXN0aWM6DQoNClRoZSBGLXN0YXRpc3RpYyBpcyB1c2VkIHRvIHRlc3QgdGhlIG92ZXJhbGwgc2lnbmlmaWNhbmNlIG9mIHRoZSByZWdyZXNzaW9uIG1vZGVsLiBXaXRoIEhfTyB0aGF0IHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZXMgQWdlLiwgRGlzdGFuY2UsIFBhcmtpbmcgYW5kIEJhbGNvbnkgaGF2ZSBOTyBzaWduaWZpY2FudCBlZmZlY3Qgb24gUHJpY2UgYW5kIEhfMSB0aGF0IHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZXMgZG8gaGF2ZSBhIHNpZ25pZmljYW50IGVmZmVjdCBvbiBQcmljZS4gSSByZWplY3QgSF8wIGF0IHAgPCAwLjAwMSBhbmQgYWNjZXB0IEhfMSB0aGF0IHRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgZWZmZWN0IG9mIHRoZSBkZXBlbmRlbnQgdmFyaWFibGVzIG9uIFByaWNlLg0KDQoNCiMgMTUuIFNhdmUgZml0dGVkIHZhbHVlcyBhbmQgY2FsY3VsYXRlIHRoZSByZXNpZHVhbCBmb3IgYXBhcnRtZW50IElEMi4gKDEgcCkNCg0KYGBge3J9DQojIFN0YW5kYXJkaXVlZCByZXNpZHVhbHMNCmFwYXJ0bWVudHMkU3RkUmVzaWQzIDwtIHJvdW5kKHJzdGFuZGFyZChmaXQzKSwgMykNCmFwYXJ0bWVudHMkU3RkUmVzaWQzWzJdDQoNCmBgYA0KDQpTaW5jZSB0aGUgQXBwYXJ0bWVudHMueGxzeCBmaWxlIGRvZXMgbm90IGNvbnRhaW4gYW4gSUQgY29sdW1uLCBJIHdpbGwgYXNzdW1lIHRoYXQgdGhlIGFwYXJ0bWVudCBpbiByb3cgMiBoYXMgdGhlIElEID0gMiBhbmQgdGh1cyBhIHN0YW5kYXJkaXplZCByZXNpZHVhbCBvZiAxLjc5NC4NCg0KDQo=