1. Import the dataset Apartments.xlsx

# Load dataset
apartments <- read_xlsx("Apartments.xlsx")

head(apartments)
NA

Description:

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:

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.

10. Are standardized residuals ditributed normally? Show the graph and formally test it. Explain the findings. (1 p)

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

As stated before in 8., there is NO normal distribution of the standardized residuals since “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,…”

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

-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.

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=