1 Introduction

The goal of this project is to model home sale prices in Ames, Iowa using structural, size, and amenity characteristics from the Ames Housing dataset.

We aim to:

Practical questions include:

2 Data Set and Practical Questions

2.1 Data source

We use the make_ames() function from the AmesHousing package. Each observation corresponds to a single residential home sale.

housing <- AmesHousing::make_ames()
dim(housing)

[1] 2930 81

head(housing[, 1:6])

The response variable is

  • Sale_Price: sale price of the home (USD).

2.2 Variables used in the analysis

We select predictors related to size, quality, condition, age, and amenities, and construct a few engineered variables.

dat0 <- housing %>%
  dplyr::select(
    Sale_Price,
    Gr_Liv_Area, Total_Bsmt_SF, First_Flr_SF, Second_Flr_SF,
    Overall_Qual, Overall_Cond,
    Year_Built, Year_Remod_Add,
    Full_Bath, Half_Bath, Bsmt_Full_Bath, Bsmt_Half_Bath,
    Garage_Cars, Garage_Area,
    Fireplaces,
    Lot_Area, Mas_Vnr_Area
  ) %>%
  tidyr::drop_na(Sale_Price)

dat <- dat0 %>%
  dplyr::mutate(
    Total_Baths = Full_Bath + 0.5 * Half_Bath +
      Bsmt_Full_Bath + 0.5 * Bsmt_Half_Bath,
    House_Age         = max(Year_Built, na.rm = TRUE) - Year_Built,
    Years_Since_Remod = max(Year_Remod_Add, na.rm = TRUE) - Year_Remod_Add,
    Overall_Qual_S    = as.numeric(Overall_Qual),
    Overall_Cond_S    = as.numeric(Overall_Cond)
  ) %>%
  dplyr::select(
    Sale_Price,
    Gr_Liv_Area, Total_Bsmt_SF, First_Flr_SF, Second_Flr_SF,
    Overall_Qual_S, Overall_Cond_S,
    House_Age, Years_Since_Remod,
    Total_Baths, Garage_Cars, Garage_Area, Fireplaces,
    Lot_Area, Mas_Vnr_Area
  )

dim(dat)

[1] 2930 15

2.2.1 Variable descriptions

  • Sale_Price (numeric): sale price of the home (USD).
  • Gr_Liv_Area (numeric): above-ground living area (sq ft).
  • Total_Bsmt_SF (numeric): total basement area (sq ft).
  • First_Flr_SF, Second_Flr_SF (numeric): first- and second-floor areas.
  • Overall_Qual_S (integer): overall material and finish quality (higher = better).
  • Overall_Cond_S (integer): overall condition rating.
  • House_Age (numeric): age of the house at time of sale.
  • Years_Since_Remod (numeric): years since last remodeling.
  • Total_Baths (numeric): effective number of bathrooms
    (full = 1, half = 0.5, summed across basement and basement baths).
  • Garage_Cars (integer): garage car capacity.
  • Garage_Area (numeric): garage size in sq ft.
  • Fireplaces (integer): number of fireplaces.
  • Lot_Area (numeric): lot size in sq ft.
  • Mas_Vnr_Area (numeric): masonry veneer area (sq ft).

2.2.2 Practical questions

  1. Which structural and amenity variables have the strongest impact on sale price?
  2. Can a linear regression model explain a substantial portion of the variation in sale price while meeting key assumptions?
  3. Are conclusions based on parametric inference stable under bootstrap resampling?

3 Exploratory Data Analysis

Min. 1st Qu. Median Mean 3rd Qu. Max. 12789 129500 160000 180796 213500 755000

The median home sells for around the mid $160,000s, with substantial variation across the market.

We examine relationships among sale price and several key predictors using a manageable subsample.

set.seed(321)
small <- dat %>% dplyr::sample_n(min(1000, nrow(dat)))

GGally::ggpairs(
  dplyr::select(small,
                Sale_Price, Gr_Liv_Area, Total_Bsmt_SF,
                Overall_Qual_S, Total_Baths, Garage_Cars)
)

Interpretation.
Sale price is strongly and positively associated with living area, basement size, overall quality, and total bathrooms. The relationships appear roughly linear, with increasing spread for larger, more expensive homes, suggesting mild heteroscedasticity.

4 Modeling Strategy

We start with the following full multiple linear regression model:

full_formula <- Sale_Price ~ Gr_Liv_Area + Total_Bsmt_SF +
  First_Flr_SF + Second_Flr_SF +
  Overall_Qual_S + Overall_Cond_S +
  House_Age + Years_Since_Remod +
  Total_Baths + Garage_Cars + Garage_Area +
  Fireplaces + Lot_Area + Mas_Vnr_Area

Plan:

  1. Fit the full model and check multicollinearity and residual diagnostics.
  2. Fit a Box–Cox transformed model to improve normality and variance stability.
  3. Use stepwise AIC to obtain a parsimonious model.
  4. Compare models with \(R^2\), adjusted \(R^2\), Mallows’ \(C_p\), and PRESS.
  5. Select a final model for interpretation and bootstrap inference.

4.1 Full multiple regression model

m_full <- lm(full_formula, data = dat)
summary(m_full)

Call: lm(formula = full_formula, data = dat)

Residuals: Min 1Q Median 3Q Max -518019 -17759 -2451 14208 296657

Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) -7.770e+04 6.299e+03 -12.335 < 2e-16 Gr_Liv_Area 2.189e+01 1.403e+01 1.560 0.1189
Total_Bsmt_SF 1.949e+01 2.639e+00 7.385 1.97e-13
First_Flr_SF 2.543e+01 1.440e+01 1.767 0.0774 .
Second_Flr_SF 1.443e+01 1.420e+01 1.016 0.3097
Overall_Qual_S 1.817e+04 7.712e+02 23.559 < 2e-16 Overall_Cond_S 4.595e+03 6.830e+02 6.728 2.06e-11 House_Age -2.637e+02 3.736e+01 -7.059 2.08e-12 Years_Since_Remod -2.433e+02 4.472e+01 -5.442 5.72e-08 Total_Baths 7.264e+03 1.168e+03 6.220 5.67e-10 Garage_Cars 2.841e+03 1.982e+03 1.434 0.1518
Garage_Area 3.202e+01 6.810e+00 4.702 2.70e-06
Fireplaces 8.071e+03 1.174e+03 6.874 7.63e-12 Lot_Area 5.961e-01 8.903e-02 6.696 2.56e-11 Mas_Vnr_Area 3.817e+01 4.181e+00 9.128 < 2e-16 *** — Signif. codes: 0 ‘’ 0.001 ’’ 0.01 ’’ 0.05 ‘.’ 0.1 ’ ’ 1

Residual standard error: 34630 on 2915 degrees of freedom Multiple R-squared: 0.813, Adjusted R-squared: 0.8121 F-statistic: 905.3 on 14 and 2915 DF, p-value: < 2.2e-16

The full model explains over 80% of the variation in sale price, with many predictors (especially quality, baths, and fireplaces) highly significant.

4.1.1 Multicollinearity

vif_vals <- car::vif(m_full)
sort(round(vif_vals, 2), decreasing = TRUE)
  Gr_Liv_Area     Second_Flr_SF      First_Flr_SF       Garage_Cars 
       122.87             90.44             77.75              5.56 
  Garage_Area     Total_Bsmt_SF         House_Age    Overall_Qual_S 
         5.25              3.31              3.12              2.89 
  Total_Baths Years_Since_Remod    Overall_Cond_S        Fireplaces 
         2.17              2.13              1.41              1.41 
 Mas_Vnr_Area          Lot_Area 
         1.36              1.20 

Several size-related variables (Gr_Liv_Area, First_Flr_SF, Second_Flr_SF) have large VIFs, indicating notable multicollinearity.

4.1.2 Residual diagnostics

op <- par(mfrow = c(2, 2))
plot(m_full)

par(op)

Residual plots show mild skewness and hints of non-constant variance; Q–Q plots indicate slightly heavy upper tails.

5 Box–Cox Transformation

y <- dat$Sale_Price
eps <- ifelse(any(y <= 0), 1, 0)

bc <- MASS::boxcox(m_full, lambda = seq(-1, 1, by = 0.1), plotit = TRUE)

(lambda_hat <- bc$x[which.max(bc$y)])

[1] 0.1515152

The estimated lambda is around 0.15, suggesting a mild power transformation.

# Recompute Box–Cox inside this chunk so lambda_hat always exists
y <- dat$Sale_Price
eps <- ifelse(any(y <= 0), 1, 0)

# Box–Cox profile based on full model
bc <- MASS::boxcox(m_full, lambda = seq(-1, 1, by = 0.1))

lambda_hat <- bc$x[which.max(bc$y)]
lambda_hat

[1] 0.1515152

# Transform the response using lambda_hat
y_bc <- if (abs(lambda_hat) < 1e-8) {
  log(y + eps)
} else {
  ((y + eps)^lambda_hat - 1) / lambda_hat
}

# Fit Box–Cox transformed model
m_bc <- lm(
  y_bc ~ Gr_Liv_Area + Total_Bsmt_SF + First_Flr_SF + Second_Flr_SF +
    Overall_Qual_S + Overall_Cond_S + House_Age + Years_Since_Remod +
    Total_Baths + Garage_Cars + Garage_Area + Fireplaces +
    Lot_Area + Mas_Vnr_Area,
  data = dat
)

summary(m_bc)

Call: lm(formula = y_bc ~ Gr_Liv_Area + Total_Bsmt_SF + First_Flr_SF + Second_Flr_SF + Overall_Qual_S + Overall_Cond_S + House_Age + Years_Since_Remod + Total_Baths + Garage_Cars + Garage_Area + Fireplaces + Lot_Area + Mas_Vnr_Area, data = dat)

Residuals: Min 1Q Median 3Q Max -15.1262 -0.4469 0.0052 0.4908 3.2168

Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) 2.549e+01 1.681e-01 151.637 < 2e-16 Gr_Liv_Area 8.797e-04 3.744e-04 2.349 0.018874
Total_Bsmt_SF 6.307e-04 7.044e-05 8.954 < 2e-16
First_Flr_SF 5.040e-04 3.842e-04 1.312 0.189683
Second_Flr_SF 2.632e-04 3.791e-04 0.694 0.487479
Overall_Qual_S 5.684e-01 2.058e-02 27.614 < 2e-16
Overall_Cond_S 3.081e-01 1.823e-02 16.904 < 2e-16 House_Age -1.622e-02 9.971e-04 -16.267 < 2e-16 Years_Since_Remod -6.867e-03 1.193e-03 -5.754 9.62e-09 Total_Baths 2.759e-01 3.117e-02 8.854 < 2e-16 Garage_Cars 2.375e-01 5.289e-02 4.490 7.40e-06 Garage_Area 6.377e-04 1.817e-04 3.509 0.000457 Fireplaces 3.425e-01 3.134e-02 10.929 < 2e-16 Lot_Area 1.835e-05 2.376e-06 7.722 1.56e-14 ** Mas_Vnr_Area 1.986e-04 1.116e-04 1.779 0.075309 .
— Signif. codes: 0 ‘’ 0.001 ’’ 0.01 ’’ 0.05 ‘.’ 0.1 ’ ’ 1

Residual standard error: 0.9242 on 2915 degrees of freedom Multiple R-squared: 0.8671, Adjusted R-squared: 0.8664 F-statistic: 1358 on 14 and 2915 DF, p-value: < 2.2e-16

op <- par(mfrow = c(2, 2))
plot(m_bc)

par(op)

The Box–Cox model improves residual normality and slightly increases adjusted \(R^2\), although interpretation becomes less direct due to the transformed response.

6 Model Selection and Goodness-of-Fit

6.1 Stepwise AIC model

m_step <- MASS::stepAIC(m_full, trace = FALSE)
summary(m_step)

Call: lm(formula = Sale_Price ~ Gr_Liv_Area + Total_Bsmt_SF + First_Flr_SF + Overall_Qual_S + Overall_Cond_S + House_Age + Years_Since_Remod + Total_Baths + Garage_Cars + Garage_Area + Fireplaces + Lot_Area + Mas_Vnr_Area, data = dat)

Residuals: Min 1Q Median 3Q Max -517086 -17863 -2425 14259 297387

Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) -7.772e+04 6.299e+03 -12.338 < 2e-16 Gr_Liv_Area 3.599e+01 2.063e+00 17.443 < 2e-16 Total_Bsmt_SF 1.938e+01 2.637e+00 7.350 2.56e-13 First_Flr_SF 1.114e+01 3.063e+00 3.639 0.000279 Overall_Qual_S 1.818e+04 7.711e+02 23.576 < 2e-16 Overall_Cond_S 4.626e+03 6.823e+02 6.781 1.44e-11 House_Age -2.670e+02 3.723e+01 -7.172 9.34e-13 Years_Since_Remod -2.423e+02 4.471e+01 -5.420 6.46e-08 Total_Baths 7.324e+03 1.166e+03 6.280 3.89e-10 Garage_Cars 2.887e+03 1.981e+03 1.457 0.145096
Garage_Area 3.199e+01 6.810e+00 4.698 2.75e-06
Fireplaces 8.092e+03 1.174e+03 6.893 6.67e-12 Lot_Area 5.982e-01 8.900e-02 6.721 2.16e-11 Mas_Vnr_Area 3.841e+01 4.175e+00 9.200 < 2e-16 *** — Signif. codes: 0 ‘’ 0.001 ’’ 0.01 ’’ 0.05 ‘.’ 0.1 ’ ’ 1

Residual standard error: 34630 on 2916 degrees of freedom Multiple R-squared: 0.8129, Adjusted R-squared: 0.8121 F-statistic: 974.8 on 13 and 2916 DF, p-value: < 2.2e-16

round(car::vif(m_step), 2)
  Gr_Liv_Area     Total_Bsmt_SF      First_Flr_SF    Overall_Qual_S 
         2.66              3.30              3.52              2.89 

Overall_Cond_S House_Age Years_Since_Remod Total_Baths 1.40 3.10 2.12 2.17 Garage_Cars Garage_Area Fireplaces Lot_Area 5.55 5.25 1.41 1.20 Mas_Vnr_Area 1.36

The stepwise procedure removes some collinear or weak predictors while maintaining strong fit and reducing VIF values.

6.2 Goodness-of-fit comparison

Goodness-of-fit summary for candidate models.
Name SSE R2 R2_Adj Cp PRESS p
Box–Cox 2490 0.867 0.866 -2900 2589 15
Stepwise (orig) 3.497e+12 0.813 0.812 29.04 3.626e+12 14
Full 3.495e+12 0.813 0.812 30 3.629e+12 15

Interpretation.

  • The Box–Cox model has the best raw \(R^2\), but uses a transformed response.
  • The stepwise model achieves similar adjusted \(R^2\) and PRESS with fewer predictors and lower multicollinearity.

We select the stepwise original model as the final model due to its balance of fit and interpretability.

7 Final Model and Interpretation

m_final <- m_step
summary(m_final)

Call: lm(formula = Sale_Price ~ Gr_Liv_Area + Total_Bsmt_SF + First_Flr_SF + Overall_Qual_S + Overall_Cond_S + House_Age + Years_Since_Remod + Total_Baths + Garage_Cars + Garage_Area + Fireplaces + Lot_Area + Mas_Vnr_Area, data = dat)

Residuals: Min 1Q Median 3Q Max -517086 -17863 -2425 14259 297387

Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) -7.772e+04 6.299e+03 -12.338 < 2e-16 Gr_Liv_Area 3.599e+01 2.063e+00 17.443 < 2e-16 Total_Bsmt_SF 1.938e+01 2.637e+00 7.350 2.56e-13 First_Flr_SF 1.114e+01 3.063e+00 3.639 0.000279 Overall_Qual_S 1.818e+04 7.711e+02 23.576 < 2e-16 Overall_Cond_S 4.626e+03 6.823e+02 6.781 1.44e-11 House_Age -2.670e+02 3.723e+01 -7.172 9.34e-13 Years_Since_Remod -2.423e+02 4.471e+01 -5.420 6.46e-08 Total_Baths 7.324e+03 1.166e+03 6.280 3.89e-10 Garage_Cars 2.887e+03 1.981e+03 1.457 0.145096
Garage_Area 3.199e+01 6.810e+00 4.698 2.75e-06
Fireplaces 8.092e+03 1.174e+03 6.893 6.67e-12 Lot_Area 5.982e-01 8.900e-02 6.721 2.16e-11 Mas_Vnr_Area 3.841e+01 4.175e+00 9.200 < 2e-16 *** — Signif. codes: 0 ‘’ 0.001 ’’ 0.01 ’’ 0.05 ‘.’ 0.1 ’ ’ 1

Residual standard error: 34630 on 2916 degrees of freedom Multiple R-squared: 0.8129, Adjusted R-squared: 0.8121 F-statistic: 974.8 on 13 and 2916 DF, p-value: < 2.2e-16

confint(m_final)
                      2.5 %        97.5 %

(Intercept) -9.007652e+04 -6.537308e+04 Gr_Liv_Area 3.194066e+01 4.003102e+01 Total_Bsmt_SF 1.421075e+01 2.455175e+01 First_Flr_SF 5.138295e+00 1.714841e+01 Overall_Qual_S 1.666798e+04 1.969192e+04 Overall_Cond_S 3.288468e+03 5.964038e+03 House_Age -3.399672e+02 -1.939860e+02 Years_Since_Remod -3.299438e+02 -1.546299e+02 Total_Baths 5.037435e+03 9.610963e+03 Garage_Cars -9.971247e+02 6.771933e+03 Garage_Area 1.863786e+01 4.534281e+01 Fireplaces 5.790373e+03 1.039430e+04 Lot_Area 4.236867e-01 7.727211e-01 Mas_Vnr_Area 3.022111e+01 4.659273e+01

Parametric estimates and confidence intervals for the final model. (continued below)
term estimate std.error statistic p.value conf.low
(Intercept) -77725 6299 -12.34 0 -90077
Gr_Liv_Area 35.99 2.063 17.44 0 31.94
Total_Bsmt_SF 19.38 2.637 7.35 0 14.21
Overall_Qual_S 18180 771.1 23.58 0 16668
Overall_Cond_S 4626 682.3 6.781 0 3288
House_Age -267 37.23 -7.172 0 -340
Years_Since_Remod -242.3 44.71 -5.42 0 -329.9
Total_Baths 7324 1166 6.28 0 5037
Garage_Area 31.99 6.81 4.698 0 18.64
Fireplaces 8092 1174 6.893 0 5790
Lot_Area 0.5982 0.089 6.721 0 0.4237
Mas_Vnr_Area 38.41 4.175 9.2 0 30.22
First_Flr_SF 11.14 3.063 3.639 3e-04 5.138
Garage_Cars 2887 1981 1.458 0.1451 -997.1
conf.high
-65373
40.03
24.55
19692
5964
-194
-154.6
9611
45.34
10394
0.7727
46.59
17.15
6772

Key findings:

8 8 Bootstrap Regression

We use bootstrap methods to assess the robustness of parametric inference for the final model.

8.1 Bootstrapping cases

set.seed(321)

X <- model.matrix(m_final)
y_final <- model.response(model.frame(m_final))
p <- length(coef(m_final))
coef_names <- names(coef(m_final))
B <- 1000

boot_beta_case <- matrix(NA_real_, nrow = B, ncol = p)
colnames(boot_beta_case) <- coef_names

for (b in 1:B) {
  idx <- sample.int(nrow(X), replace = TRUE)
  fit_b <- lm(y_final[idx] ~ X[idx, -1])
  boot_beta_case[b, ] <- coef(fit_b)
}

ci_case_mat <- apply(boot_beta_case, 2,
                     quantile, probs = c(0.025, 0.975), na.rm = TRUE)

ci_case_tbl <- tibble::tibble(
  term  = colnames(ci_case_mat),
  `2.5%` = as.numeric(ci_case_mat[1, ]),
  `97.5%`= as.numeric(ci_case_mat[2, ])
)

pander::pander(ci_case_tbl,
               caption = "95% bootstrap confidence intervals (case resampling).")
95% bootstrap confidence intervals (case resampling).
term 2.5% 97.5%
(Intercept) -93979 -62811
Gr_Liv_Area 25.08 46.42
Total_Bsmt_SF 4.742 31.93
First_Flr_SF 2.983 19.83
Overall_Qual_S 15904 20600
Overall_Cond_S 3282 6082
House_Age -340.4 -186.2
Years_Since_Remod -309 -176.6
Total_Baths 4413 10224
Garage_Cars -4657 11975
Garage_Area 5.562 54.25
Fireplaces 5292 10937
Lot_Area 0.363 1.063
Mas_Vnr_Area 23.79 53.63

8.2 Bootstrapping residuals

fit_hat   <- fitted(m_final)
resid_hat <- resid(m_final)

boot_beta_res <- matrix(NA_real_, nrow = B, ncol = p)
colnames(boot_beta_res) <- coef_names

for (b in 1:B) {
  y_star <- fit_hat + sample(resid_hat, replace = TRUE)
  fit_b  <- lm(y_star ~ X[, -1])
  boot_beta_res[b, ] <- coef(fit_b)
}

ci_resid_mat <- apply(boot_beta_res, 2,
                      quantile, probs = c(0.025, 0.975), na.rm = TRUE)

ci_resid_tbl <- tibble::tibble(
  term  = colnames(ci_resid_mat),
  `2.5%` = as.numeric(ci_resid_mat[1, ]),
  `97.5%`= as.numeric(ci_resid_mat[2, ])
)

pander::pander(ci_resid_tbl,
               caption = "95% bootstrap confidence intervals (residual resampling).")
95% bootstrap confidence intervals (residual resampling).
term 2.5% 97.5%
(Intercept) -90205 -65312
Gr_Liv_Area 32.02 40
Total_Bsmt_SF 14.1 24.98
First_Flr_SF 4.273 17.05
Overall_Qual_S 16719 19599
Overall_Cond_S 3271 5969
House_Age -336 -199.7
Years_Since_Remod -330.9 -149.2
Total_Baths 5015 9557
Garage_Cars -1096 6664
Garage_Area 18.6 45.32
Fireplaces 5949 10589
Lot_Area 0.4408 0.7659
Mas_Vnr_Area 29.71 46.29

8.3 Comparison with parametric intervals

Across major predictors, the bootstrap intervals from both methods are very similar to the parametric confidence intervals, and all three procedures agree on which coefficients are significantly different from zero. This indicates that the sample size is large enough for classical linear-model inference to be reliable, even in the presence of mild deviations from ideal assumptions.

9 Conclusions

The final stepwise regression model explains a large portion of the variation in Ames home sale prices and highlights that buyers pay the highest premiums for:

Older homes and those with long intervals since the last remodel tend to sell for lower prices, holding other factors constant.

Bootstrap inference corroborates the parametric results, suggesting that the key conclusions about drivers of sale price are robust.

10 Limitations and Future Work

Future work could incorporate additional location-based variables, explore flexible nonlinear models (splines, tree-based methods), and validate model performance using out-of-sample predictions or time-based cross-validation.

LS0tDQp0aXRsZTogIk1vZGVsaW5nIEFtZXMgSG9tZSBTYWxlIFByaWNlczogQSBNdWx0aXBsZSBSZWdyZXNzaW9uICYgQm9vdHN0cmFwIEFuYWx5c2lzIg0KYXV0aG9yOiAiUnlhbiBHb3JtYW4iDQpkYXRlOiAiMjAyNS0xMi0xMSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZGVwdGg6IDMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgd29yZF9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZGVwdGg6IDMNCi0tLQ0KDQpgYGB7PWh0bWx9DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KDQovKiAtLS0tLS0tLS0tIFRpdGxlIGFyZWEgLS0tLS0tLS0tLSAqLw0KDQpoMS50aXRsZSB7DQogIGZvbnQtc2l6ZTogMjRweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQogIGZvbnQtZmFtaWx5OiAiR2lsbCBTYW5zIiwgc2Fucy1zZXJpZjsNCn0NCmg0LmF1dGhvciB7DQogIGZvbnQtc2l6ZTogMjBweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiBzeXN0ZW0tdWk7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoNC5kYXRlIHsNCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6IHN5c3RlbS11aTsNCiAgY29sb3I6IERhcmtCbHVlOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCi8qIC0tLS0tLS0tLS0gU2VjdGlvbiBoZWFkZXJzIC0tLS0tLS0tLS0gKi8NCg0KaDEgew0KICBmb250LXNpemU6IDIycHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogc3lzdGVtLXVpOw0KICBjb2xvcjogbmF2eTsNCiAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCmgyIHsNCiAgZm9udC1zaXplOiAyMHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBuYXZ5Ow0KICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KaDMgew0KICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgY29sb3I6IG5hdnk7DQogIHRleHQtYWxpZ246IGxlZnQ7DQp9DQpoNCB7DQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBjb2xvcjogZGFya3JlZDsNCiAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KLyogLS0tLS0tLS0tLSBCb2R5ICYgaGlnaGxpZ2h0cyAtLS0tLS0tLS0tICovDQoNCmJvZHkgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9DQpwICAgIHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KLmhpZ2hsaWdodG1lIHsgYmFja2dyb3VuZC1jb2xvcjp5ZWxsb3c7IH0NCg0KPC9zdHlsZT4NCmBgYA0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMgRGV0ZWN0LCBpbnN0YWxsLCBhbmQgbG9hZCBwYWNrYWdlcyBpZiBuZWVkZWQgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KbmVlZGVkIDwtIGMoImtuaXRyIiwgInRpZHl2ZXJzZSIsICJBbWVzSG91c2luZyIsICJHR2FsbHkiLA0KICAgICAgICAgICAgIk1BU1MiLCAiY2FyIiwgImJyb29tIiwgInBhbmRlciIpDQoNCmZvciAocCBpbiBuZWVkZWQpIHsNCiAgaWYgKCFyZXF1aXJlKHAsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKHAsIHJlcG9zID0gImh0dHBzOi8vY2xvdWQuci1wcm9qZWN0Lm9yZyIpDQogICAgbGlicmFyeShwLCBjaGFyYWN0ZXIub25seSA9IFRSVUUpDQogIH0NCn0NCg0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICBlY2hvICAgID0gVFJVRSwNCiAgbWVzc2FnZSA9IEZBTFNFLA0KICB3YXJuaW5nID0gRkFMU0UsDQogIHJlc3VsdHMgPSAiYXNpcyIsDQogIGZpZy5hbGlnbiA9ICJjZW50ZXIiDQopDQoNCnNldC5zZWVkKDMyMSkNCmBgYA0KDQojIEludHJvZHVjdGlvbg0KDQpUaGUgZ29hbCBvZiB0aGlzIHByb2plY3QgaXMgdG8gbW9kZWwgKipob21lIHNhbGUgcHJpY2VzIGluIEFtZXMsIElvd2EqKiB1c2luZyBzdHJ1Y3R1cmFsLCBzaXplLCBhbmQgYW1lbml0eSBjaGFyYWN0ZXJpc3RpY3MgZnJvbSB0aGUgKkFtZXMgSG91c2luZyogZGF0YXNldC4NCg0KV2UgYWltIHRvOg0KDQotIEJ1aWxkIGFuIGludGVycHJldGFibGUgbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgZm9yIHNhbGUgcHJpY2UuICANCi0gRGlhZ25vc2UgdmlvbGF0aW9ucyBvZiBsaW5lYXItbW9kZWwgYXNzdW1wdGlvbnMgYW5kIGFwcGx5IGEgKipCb3jigJNDb3ggdHJhbnNmb3JtYXRpb24qKiB3aGVuIGFwcHJvcHJpYXRlLiAgDQotIENvbXBhcmUgc2V2ZXJhbCBjYW5kaWRhdGUgbW9kZWxzIChmdWxsLCBCb3jigJNDb3gsIGFuZCBzdGVwd2lzZSBBSUMpIHVzaW5nIGdvb2RuZXNzLW9mLWZpdCBjcml0ZXJpYS4gIA0KLSBVc2UgKipib290c3RyYXAgbWV0aG9kcyoqIHRvIGNvbnN0cnVjdCBjb25maWRlbmNlIGludGVydmFscyBmb3IgcmVncmVzc2lvbiBjb2VmZmljaWVudHMgYW5kIGV2YWx1YXRlIHRoZSByb2J1c3RuZXNzIG9mIHBhcmFtZXRyaWMgaW5mZXJlbmNlLg0KDQpQcmFjdGljYWwgcXVlc3Rpb25zIGluY2x1ZGU6DQoNCi0gV2hpY2ggZmVhdHVyZXMgKGxpdmluZyBhcmVhLCBxdWFsaXR5LCBiYXRocm9vbXMsIGdhcmFnZXMsIGZpcmVwbGFjZXMsIGFnZSkgaGF2ZSB0aGUgc3Ryb25nZXN0IGltcGFjdCBvbiBzYWxlIHByaWNlPyAgDQotIEhvdyBsYXJnZSBhcmUgdGhvc2UgaW1wYWN0cyBpbiBkb2xsYXIgdGVybXM/ICANCi0gQXJlIGJvb3RzdHJhcCBjb25maWRlbmNlIGludGVydmFscyBjb25zaXN0ZW50IHdpdGggdGhlIHVzdWFsIHBhcmFtZXRyaWMgaW50ZXJ2YWxzPw0KDQojIERhdGEgU2V0IGFuZCBQcmFjdGljYWwgUXVlc3Rpb25zDQoNCiMjIERhdGEgc291cmNlDQoNCldlIHVzZSB0aGUgYG1ha2VfYW1lcygpYCBmdW5jdGlvbiBmcm9tIHRoZSBgQW1lc0hvdXNpbmdgIHBhY2thZ2UuIEVhY2ggb2JzZXJ2YXRpb24gY29ycmVzcG9uZHMgdG8gYSBzaW5nbGUgcmVzaWRlbnRpYWwgaG9tZSBzYWxlLg0KDQpgYGB7ciBsb2FkLWRhdGF9DQpob3VzaW5nIDwtIEFtZXNIb3VzaW5nOjptYWtlX2FtZXMoKQ0KZGltKGhvdXNpbmcpDQpoZWFkKGhvdXNpbmdbLCAxOjZdKQ0KYGBgDQoNClRoZSByZXNwb25zZSB2YXJpYWJsZSBpcw0KDQotICoqU2FsZV9QcmljZSoqOiBzYWxlIHByaWNlIG9mIHRoZSBob21lIChVU0QpLg0KDQojIyBWYXJpYWJsZXMgdXNlZCBpbiB0aGUgYW5hbHlzaXMNCg0KV2Ugc2VsZWN0IHByZWRpY3RvcnMgcmVsYXRlZCB0byBzaXplLCBxdWFsaXR5LCBjb25kaXRpb24sIGFnZSwgYW5kIGFtZW5pdGllcywgYW5kIGNvbnN0cnVjdCBhIGZldyBlbmdpbmVlcmVkIHZhcmlhYmxlcy4NCg0KYGBge3IgZGF0YS1wcmVwfQ0KZGF0MCA8LSBob3VzaW5nICU+JQ0KICBkcGx5cjo6c2VsZWN0KA0KICAgIFNhbGVfUHJpY2UsDQogICAgR3JfTGl2X0FyZWEsIFRvdGFsX0JzbXRfU0YsIEZpcnN0X0Zscl9TRiwgU2Vjb25kX0Zscl9TRiwNCiAgICBPdmVyYWxsX1F1YWwsIE92ZXJhbGxfQ29uZCwNCiAgICBZZWFyX0J1aWx0LCBZZWFyX1JlbW9kX0FkZCwNCiAgICBGdWxsX0JhdGgsIEhhbGZfQmF0aCwgQnNtdF9GdWxsX0JhdGgsIEJzbXRfSGFsZl9CYXRoLA0KICAgIEdhcmFnZV9DYXJzLCBHYXJhZ2VfQXJlYSwNCiAgICBGaXJlcGxhY2VzLA0KICAgIExvdF9BcmVhLCBNYXNfVm5yX0FyZWENCiAgKSAlPiUNCiAgdGlkeXI6OmRyb3BfbmEoU2FsZV9QcmljZSkNCg0KZGF0IDwtIGRhdDAgJT4lDQogIGRwbHlyOjptdXRhdGUoDQogICAgVG90YWxfQmF0aHMgPSBGdWxsX0JhdGggKyAwLjUgKiBIYWxmX0JhdGggKw0KICAgICAgQnNtdF9GdWxsX0JhdGggKyAwLjUgKiBCc210X0hhbGZfQmF0aCwNCiAgICBIb3VzZV9BZ2UgICAgICAgICA9IG1heChZZWFyX0J1aWx0LCBuYS5ybSA9IFRSVUUpIC0gWWVhcl9CdWlsdCwNCiAgICBZZWFyc19TaW5jZV9SZW1vZCA9IG1heChZZWFyX1JlbW9kX0FkZCwgbmEucm0gPSBUUlVFKSAtIFllYXJfUmVtb2RfQWRkLA0KICAgIE92ZXJhbGxfUXVhbF9TICAgID0gYXMubnVtZXJpYyhPdmVyYWxsX1F1YWwpLA0KICAgIE92ZXJhbGxfQ29uZF9TICAgID0gYXMubnVtZXJpYyhPdmVyYWxsX0NvbmQpDQogICkgJT4lDQogIGRwbHlyOjpzZWxlY3QoDQogICAgU2FsZV9QcmljZSwNCiAgICBHcl9MaXZfQXJlYSwgVG90YWxfQnNtdF9TRiwgRmlyc3RfRmxyX1NGLCBTZWNvbmRfRmxyX1NGLA0KICAgIE92ZXJhbGxfUXVhbF9TLCBPdmVyYWxsX0NvbmRfUywNCiAgICBIb3VzZV9BZ2UsIFllYXJzX1NpbmNlX1JlbW9kLA0KICAgIFRvdGFsX0JhdGhzLCBHYXJhZ2VfQ2FycywgR2FyYWdlX0FyZWEsIEZpcmVwbGFjZXMsDQogICAgTG90X0FyZWEsIE1hc19WbnJfQXJlYQ0KICApDQoNCmRpbShkYXQpDQpgYGANCg0KIyMjIFZhcmlhYmxlIGRlc2NyaXB0aW9ucw0KDQotICoqU2FsZV9QcmljZSoqIChudW1lcmljKTogc2FsZSBwcmljZSBvZiB0aGUgaG9tZSAoVVNEKS4gIA0KLSAqKkdyX0xpdl9BcmVhKiogKG51bWVyaWMpOiBhYm92ZS1ncm91bmQgbGl2aW5nIGFyZWEgKHNxIGZ0KS4gIA0KLSAqKlRvdGFsX0JzbXRfU0YqKiAobnVtZXJpYyk6IHRvdGFsIGJhc2VtZW50IGFyZWEgKHNxIGZ0KS4gIA0KLSAqKkZpcnN0X0Zscl9TRioqLCAqKlNlY29uZF9GbHJfU0YqKiAobnVtZXJpYyk6IGZpcnN0LSBhbmQgc2Vjb25kLWZsb29yIGFyZWFzLiAgDQotICoqT3ZlcmFsbF9RdWFsX1MqKiAoaW50ZWdlcik6IG92ZXJhbGwgbWF0ZXJpYWwgYW5kIGZpbmlzaCBxdWFsaXR5IChoaWdoZXIgPSBiZXR0ZXIpLiAgDQotICoqT3ZlcmFsbF9Db25kX1MqKiAoaW50ZWdlcik6IG92ZXJhbGwgY29uZGl0aW9uIHJhdGluZy4gIA0KLSAqKkhvdXNlX0FnZSoqIChudW1lcmljKTogYWdlIG9mIHRoZSBob3VzZSBhdCB0aW1lIG9mIHNhbGUuICANCi0gKipZZWFyc19TaW5jZV9SZW1vZCoqIChudW1lcmljKTogeWVhcnMgc2luY2UgbGFzdCByZW1vZGVsaW5nLiAgDQotICoqVG90YWxfQmF0aHMqKiAobnVtZXJpYyk6IGVmZmVjdGl2ZSBudW1iZXIgb2YgYmF0aHJvb21zICANCiAgKGZ1bGwgPSAxLCBoYWxmID0gMC41LCBzdW1tZWQgYWNyb3NzIGJhc2VtZW50IGFuZCBiYXNlbWVudCBiYXRocykuICANCi0gKipHYXJhZ2VfQ2FycyoqIChpbnRlZ2VyKTogZ2FyYWdlIGNhciBjYXBhY2l0eS4gIA0KLSAqKkdhcmFnZV9BcmVhKiogKG51bWVyaWMpOiBnYXJhZ2Ugc2l6ZSBpbiBzcSBmdC4gIA0KLSAqKkZpcmVwbGFjZXMqKiAoaW50ZWdlcik6IG51bWJlciBvZiBmaXJlcGxhY2VzLiAgDQotICoqTG90X0FyZWEqKiAobnVtZXJpYyk6IGxvdCBzaXplIGluIHNxIGZ0LiAgDQotICoqTWFzX1Zucl9BcmVhKiogKG51bWVyaWMpOiBtYXNvbnJ5IHZlbmVlciBhcmVhIChzcSBmdCkuDQoNCiMjIyBQcmFjdGljYWwgcXVlc3Rpb25zDQoNCjEuIFdoaWNoIHN0cnVjdHVyYWwgYW5kIGFtZW5pdHkgdmFyaWFibGVzIGhhdmUgdGhlIHN0cm9uZ2VzdCBpbXBhY3Qgb24gc2FsZSBwcmljZT8gIA0KMi4gQ2FuIGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgZXhwbGFpbiBhIHN1YnN0YW50aWFsIHBvcnRpb24gb2YgdGhlIHZhcmlhdGlvbiBpbiBzYWxlIHByaWNlIHdoaWxlIG1lZXRpbmcga2V5IGFzc3VtcHRpb25zPyAgDQozLiBBcmUgY29uY2x1c2lvbnMgYmFzZWQgb24gcGFyYW1ldHJpYyBpbmZlcmVuY2Ugc3RhYmxlIHVuZGVyIGJvb3RzdHJhcCByZXNhbXBsaW5nPw0KDQojIEV4cGxvcmF0b3J5IERhdGEgQW5hbHlzaXMNCg0KYGBge3Igc3VtbWFyeS1zYWxlcHJpY2UsIGVjaG89RkFMU0V9DQpzdW1tYXJ5KGRhdCRTYWxlX1ByaWNlKQ0KYGBgDQoNClRoZSBtZWRpYW4gaG9tZSBzZWxscyBmb3IgYXJvdW5kIHRoZSBtaWQgXCQxNjAsMDAwcywgd2l0aCBzdWJzdGFudGlhbCB2YXJpYXRpb24gYWNyb3NzIHRoZSBtYXJrZXQuDQoNCldlIGV4YW1pbmUgcmVsYXRpb25zaGlwcyBhbW9uZyBzYWxlIHByaWNlIGFuZCBzZXZlcmFsIGtleSBwcmVkaWN0b3JzIHVzaW5nIGEgbWFuYWdlYWJsZSBzdWJzYW1wbGUuDQoNCmBgYHtyIGdncGFpcnN9DQpzZXQuc2VlZCgzMjEpDQpzbWFsbCA8LSBkYXQgJT4lIGRwbHlyOjpzYW1wbGVfbihtaW4oMTAwMCwgbnJvdyhkYXQpKSkNCg0KR0dhbGx5OjpnZ3BhaXJzKA0KICBkcGx5cjo6c2VsZWN0KHNtYWxsLA0KICAgICAgICAgICAgICAgIFNhbGVfUHJpY2UsIEdyX0xpdl9BcmVhLCBUb3RhbF9Cc210X1NGLA0KICAgICAgICAgICAgICAgIE92ZXJhbGxfUXVhbF9TLCBUb3RhbF9CYXRocywgR2FyYWdlX0NhcnMpDQopDQpgYGANCg0KKipJbnRlcnByZXRhdGlvbi4qKiAgDQpTYWxlIHByaWNlIGlzIHN0cm9uZ2x5IGFuZCBwb3NpdGl2ZWx5IGFzc29jaWF0ZWQgd2l0aCAqKmxpdmluZyBhcmVhKiosICoqYmFzZW1lbnQgc2l6ZSoqLCAqKm92ZXJhbGwgcXVhbGl0eSoqLCBhbmQgKip0b3RhbCBiYXRocm9vbXMqKi4gVGhlIHJlbGF0aW9uc2hpcHMgYXBwZWFyIHJvdWdobHkgbGluZWFyLCB3aXRoIGluY3JlYXNpbmcgc3ByZWFkIGZvciBsYXJnZXIsIG1vcmUgZXhwZW5zaXZlIGhvbWVzLCBzdWdnZXN0aW5nIG1pbGQgaGV0ZXJvc2NlZGFzdGljaXR5Lg0KDQojIE1vZGVsaW5nIFN0cmF0ZWd5DQoNCldlIHN0YXJ0IHdpdGggdGhlIGZvbGxvd2luZyBmdWxsIG11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsOg0KDQpgYGB7ciBmdWxsLWZvcm11bGF9DQpmdWxsX2Zvcm11bGEgPC0gU2FsZV9QcmljZSB+IEdyX0xpdl9BcmVhICsgVG90YWxfQnNtdF9TRiArDQogIEZpcnN0X0Zscl9TRiArIFNlY29uZF9GbHJfU0YgKw0KICBPdmVyYWxsX1F1YWxfUyArIE92ZXJhbGxfQ29uZF9TICsNCiAgSG91c2VfQWdlICsgWWVhcnNfU2luY2VfUmVtb2QgKw0KICBUb3RhbF9CYXRocyArIEdhcmFnZV9DYXJzICsgR2FyYWdlX0FyZWEgKw0KICBGaXJlcGxhY2VzICsgTG90X0FyZWEgKyBNYXNfVm5yX0FyZWENCmBgYA0KDQpQbGFuOg0KDQoxLiBGaXQgdGhlICoqZnVsbCBtb2RlbCoqIGFuZCBjaGVjayBtdWx0aWNvbGxpbmVhcml0eSBhbmQgcmVzaWR1YWwgZGlhZ25vc3RpY3MuICANCjIuIEZpdCBhICoqQm944oCTQ294IHRyYW5zZm9ybWVkIG1vZGVsKiogdG8gaW1wcm92ZSBub3JtYWxpdHkgYW5kIHZhcmlhbmNlIHN0YWJpbGl0eS4gIA0KMy4gVXNlICoqc3RlcHdpc2UgQUlDKiogdG8gb2J0YWluIGEgcGFyc2ltb25pb3VzIG1vZGVsLiAgDQo0LiBDb21wYXJlIG1vZGVscyB3aXRoIFwoUl4yXCksIGFkanVzdGVkIFwoUl4yXCksIE1hbGxvd3PigJkgXChDX3BcKSwgYW5kIFBSRVNTLiAgDQo1LiBTZWxlY3QgYSBmaW5hbCBtb2RlbCBmb3IgaW50ZXJwcmV0YXRpb24gYW5kIGJvb3RzdHJhcCBpbmZlcmVuY2UuDQoNCiMjIEZ1bGwgbXVsdGlwbGUgcmVncmVzc2lvbiBtb2RlbA0KDQpgYGB7ciBmdWxsLW1vZGVsfQ0KbV9mdWxsIDwtIGxtKGZ1bGxfZm9ybXVsYSwgZGF0YSA9IGRhdCkNCnN1bW1hcnkobV9mdWxsKQ0KYGBgDQoNClRoZSBmdWxsIG1vZGVsIGV4cGxhaW5zIG92ZXIgODAlIG9mIHRoZSB2YXJpYXRpb24gaW4gc2FsZSBwcmljZSwgd2l0aCBtYW55IHByZWRpY3RvcnMgKGVzcGVjaWFsbHkgcXVhbGl0eSwgYmF0aHMsIGFuZCBmaXJlcGxhY2VzKSBoaWdobHkgc2lnbmlmaWNhbnQuDQoNCiMjIyBNdWx0aWNvbGxpbmVhcml0eQ0KDQpgYGB7ciB2aWYtZnVsbH0NCnZpZl92YWxzIDwtIGNhcjo6dmlmKG1fZnVsbCkNCnNvcnQocm91bmQodmlmX3ZhbHMsIDIpLCBkZWNyZWFzaW5nID0gVFJVRSkNCmBgYA0KDQpTZXZlcmFsIHNpemUtcmVsYXRlZCB2YXJpYWJsZXMgKCoqR3JfTGl2X0FyZWEqKiwgKipGaXJzdF9GbHJfU0YqKiwgKipTZWNvbmRfRmxyX1NGKiopIGhhdmUgbGFyZ2UgVklGcywgaW5kaWNhdGluZyBub3RhYmxlIG11bHRpY29sbGluZWFyaXR5Lg0KDQojIyMgUmVzaWR1YWwgZGlhZ25vc3RpY3MNCg0KYGBge3IgZnVsbC1kaWFnbm9zdGljc30NCm9wIDwtIHBhcihtZnJvdyA9IGMoMiwgMikpDQpwbG90KG1fZnVsbCkNCnBhcihvcCkNCmBgYA0KDQpSZXNpZHVhbCBwbG90cyBzaG93IG1pbGQgc2tld25lc3MgYW5kIGhpbnRzIG9mIG5vbi1jb25zdGFudCB2YXJpYW5jZTsgUeKAk1EgcGxvdHMgaW5kaWNhdGUgc2xpZ2h0bHkgaGVhdnkgdXBwZXIgdGFpbHMuDQoNCiMgQm944oCTQ294IFRyYW5zZm9ybWF0aW9uDQoNCg0KDQpgYGB7ciBib3hjb3gtcGxvdCx9DQp5IDwtIGRhdCRTYWxlX1ByaWNlDQplcHMgPC0gaWZlbHNlKGFueSh5IDw9IDApLCAxLCAwKQ0KDQpiYyA8LSBNQVNTOjpib3hjb3gobV9mdWxsLCBsYW1iZGEgPSBzZXEoLTEsIDEsIGJ5ID0gMC4xKSwgcGxvdGl0ID0gVFJVRSkNCihsYW1iZGFfaGF0IDwtIGJjJHhbd2hpY2gubWF4KGJjJHkpXSkNCmBgYA0KDQpUaGUgZXN0aW1hdGVkIGxhbWJkYSBpcyBhcm91bmQgMC4xNSwgc3VnZ2VzdGluZyBhIG1pbGQgcG93ZXIgdHJhbnNmb3JtYXRpb24uDQoNCmBgYHtyfQ0KIyBSZWNvbXB1dGUgQm944oCTQ294IGluc2lkZSB0aGlzIGNodW5rIHNvIGxhbWJkYV9oYXQgYWx3YXlzIGV4aXN0cw0KeSA8LSBkYXQkU2FsZV9QcmljZQ0KZXBzIDwtIGlmZWxzZShhbnkoeSA8PSAwKSwgMSwgMCkNCg0KIyBCb3jigJNDb3ggcHJvZmlsZSBiYXNlZCBvbiBmdWxsIG1vZGVsDQpiYyA8LSBNQVNTOjpib3hjb3gobV9mdWxsLCBsYW1iZGEgPSBzZXEoLTEsIDEsIGJ5ID0gMC4xKSkNCg0KbGFtYmRhX2hhdCA8LSBiYyR4W3doaWNoLm1heChiYyR5KV0NCmxhbWJkYV9oYXQNCg0KIyBUcmFuc2Zvcm0gdGhlIHJlc3BvbnNlIHVzaW5nIGxhbWJkYV9oYXQNCnlfYmMgPC0gaWYgKGFicyhsYW1iZGFfaGF0KSA8IDFlLTgpIHsNCiAgbG9nKHkgKyBlcHMpDQp9IGVsc2Ugew0KICAoKHkgKyBlcHMpXmxhbWJkYV9oYXQgLSAxKSAvIGxhbWJkYV9oYXQNCn0NCg0KIyBGaXQgQm944oCTQ294IHRyYW5zZm9ybWVkIG1vZGVsDQptX2JjIDwtIGxtKA0KICB5X2JjIH4gR3JfTGl2X0FyZWEgKyBUb3RhbF9Cc210X1NGICsgRmlyc3RfRmxyX1NGICsgU2Vjb25kX0Zscl9TRiArDQogICAgT3ZlcmFsbF9RdWFsX1MgKyBPdmVyYWxsX0NvbmRfUyArIEhvdXNlX0FnZSArIFllYXJzX1NpbmNlX1JlbW9kICsNCiAgICBUb3RhbF9CYXRocyArIEdhcmFnZV9DYXJzICsgR2FyYWdlX0FyZWEgKyBGaXJlcGxhY2VzICsNCiAgICBMb3RfQXJlYSArIE1hc19WbnJfQXJlYSwNCiAgZGF0YSA9IGRhdA0KKQ0KDQpzdW1tYXJ5KG1fYmMpDQoNCmBgYA0KDQpgYGB7ciBiYy1kaWFnbm9zdGljc30NCm9wIDwtIHBhcihtZnJvdyA9IGMoMiwgMikpDQpwbG90KG1fYmMpDQpwYXIob3ApDQpgYGANCg0KVGhlIEJveOKAk0NveCBtb2RlbCBpbXByb3ZlcyByZXNpZHVhbCBub3JtYWxpdHkgYW5kIHNsaWdodGx5IGluY3JlYXNlcyBhZGp1c3RlZCBcKFJeMlwpLCBhbHRob3VnaCBpbnRlcnByZXRhdGlvbiBiZWNvbWVzIGxlc3MgZGlyZWN0IGR1ZSB0byB0aGUgdHJhbnNmb3JtZWQgcmVzcG9uc2UuDQoNCiMgTW9kZWwgU2VsZWN0aW9uIGFuZCBHb29kbmVzcy1vZi1GaXQNCg0KIyMgU3RlcHdpc2UgQUlDIG1vZGVsDQoNCmBgYHtyIHN0ZXB3aXNlLW1vZGVsfQ0KbV9zdGVwIDwtIE1BU1M6OnN0ZXBBSUMobV9mdWxsLCB0cmFjZSA9IEZBTFNFKQ0Kc3VtbWFyeShtX3N0ZXApDQpyb3VuZChjYXI6OnZpZihtX3N0ZXApLCAyKQ0KYGBgDQoNClRoZSBzdGVwd2lzZSBwcm9jZWR1cmUgcmVtb3ZlcyBzb21lIGNvbGxpbmVhciBvciB3ZWFrIHByZWRpY3RvcnMgd2hpbGUgbWFpbnRhaW5pbmcgc3Ryb25nIGZpdCBhbmQgcmVkdWNpbmcgVklGIHZhbHVlcy4NCg0KIyMgR29vZG5lc3Mtb2YtZml0IGNvbXBhcmlzb24NCg0KYGBge3IgZ29mLWZ1bmN0aW9uLCBlY2hvPUZBTFNFfQ0KZ29mX3RhYmxlIDwtIGZ1bmN0aW9uKG0sIG1zZV9mdWxsLCBuKXsNCiAgZSAgIDwtIHJlc2lkKG0pDQogIFNTRSA8LSBzdW0oZV4yKQ0KICBSMiAgICA8LSBzdW1tYXJ5KG0pJHIuc3F1YXJlZA0KICBSMmFkaiA8LSBzdW1tYXJ5KG0pJGFkai5yLnNxdWFyZWQNCiAgcCAgICAgPC0gbGVuZ3RoKGNvZWYobSkpDQogIENwICAgIDwtIFNTRS9tc2VfZnVsbCAtIChuIC0gMipwKQ0KICBYIDwtIG1vZGVsLm1hdHJpeChtKQ0KICBIIDwtIFggJSolIHNvbHZlKHQoWCkgJSolIFgpICUqJSB0KFgpDQogIGQgPC0gZS8oMSAtIGRpYWcoSCkpDQogIFBSRVNTIDwtIHN1bShkXjIpDQogIHRpYmJsZTo6dGliYmxlKE1vZGVsID0gZGVwYXJzZShmb3JtdWxhKG0pKVsyXSwNCiAgICAgICAgICAgICAgICAgU1NFID0gU1NFLCBSMiA9IFIyLCBSMl9BZGogPSBSMmFkaiwNCiAgICAgICAgICAgICAgICAgQ3AgPSBDcCwgUFJFU1MgPSBQUkVTUywgcCA9IHApDQp9DQoNCm4gPC0gc3RhdHM6Om5vYnMobV9mdWxsKQ0KbXNlX2Z1bGwgPC0gbWVhbihyZXNpZChtX2Z1bGwpXjIpDQoNCmdvZiA8LSBkcGx5cjo6YmluZF9yb3dzKA0KICBGdWxsX01vZGVsICAgPSBnb2ZfdGFibGUobV9mdWxsLCBtc2VfZnVsbCwgbikgJT4lIGRwbHlyOjptdXRhdGUoTmFtZSA9ICJGdWxsIiksDQogIEJveENveF9Nb2RlbCA9IGdvZl90YWJsZShtX2JjLCAgIG1zZV9mdWxsLCBuKSAlPiUgZHBseXI6Om11dGF0ZShOYW1lID0gIkJveOKAk0NveCIpLA0KICBTdGVwX0FJQyAgICAgPSBnb2ZfdGFibGUobV9zdGVwLCBtc2VfZnVsbCwgbikgJT4lIGRwbHlyOjptdXRhdGUoTmFtZSA9ICJTdGVwd2lzZSAob3JpZykiKQ0KKSAlPiUNCiAgZHBseXI6OnNlbGVjdChOYW1lLCBkcGx5cjo6ZXZlcnl0aGluZygpLCAtTW9kZWwpICU+JQ0KICBkcGx5cjo6bXV0YXRlKGRwbHlyOjphY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLngsIDMpKSkgJT4lDQogIGRwbHlyOjphcnJhbmdlKENwKQ0KDQpnb2YNCmBgYA0KDQpgYGB7ciBnb2YtdGFibGUtbmljZSwgZWNobz1GQUxTRX0NCnBhbmRlcjo6cGFuZGVyKGdvZiwgY2FwdGlvbiA9ICJHb29kbmVzcy1vZi1maXQgc3VtbWFyeSBmb3IgY2FuZGlkYXRlIG1vZGVscy4iKQ0KYGBgDQoNCioqSW50ZXJwcmV0YXRpb24uKioNCg0KLSBUaGUgQm944oCTQ294IG1vZGVsIGhhcyB0aGUgYmVzdCByYXcgXChSXjJcKSwgYnV0IHVzZXMgYSB0cmFuc2Zvcm1lZCByZXNwb25zZS4gIA0KLSBUaGUgc3RlcHdpc2UgbW9kZWwgYWNoaWV2ZXMgc2ltaWxhciBhZGp1c3RlZCBcKFJeMlwpIGFuZCBQUkVTUyB3aXRoIGZld2VyIHByZWRpY3RvcnMgYW5kIGxvd2VyIG11bHRpY29sbGluZWFyaXR5LiAgDQoNCldlIHNlbGVjdCB0aGUgKipzdGVwd2lzZSBvcmlnaW5hbCBtb2RlbCoqIGFzIHRoZSBmaW5hbCBtb2RlbCBkdWUgdG8gaXRzIGJhbGFuY2Ugb2YgZml0IGFuZCBpbnRlcnByZXRhYmlsaXR5Lg0KDQojIEZpbmFsIE1vZGVsIGFuZCBJbnRlcnByZXRhdGlvbg0KDQpgYGB7ciBmaW5hbC1tb2RlbH0NCm1fZmluYWwgPC0gbV9zdGVwDQpzdW1tYXJ5KG1fZmluYWwpDQpjb25maW50KG1fZmluYWwpDQpgYGANCg0KYGBge3IgZmluYWwtdGlkeSwgZWNobz1GQUxTRX0NCmZpbmFsX3RibCA8LSBicm9vbTo6dGlkeShtX2ZpbmFsLCBjb25mLmludCA9IFRSVUUpICU+JQ0KICBkcGx5cjo6bXV0YXRlKGRwbHlyOjphY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLngsIDQpKSkgJT4lDQogIGRwbHlyOjphcnJhbmdlKHAudmFsdWUpDQoNCnBhbmRlcjo6cGFuZGVyKGZpbmFsX3RibCwNCiAgICAgICAgICAgICAgIGNhcHRpb24gPSAiUGFyYW1ldHJpYyBlc3RpbWF0ZXMgYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGZvciB0aGUgZmluYWwgbW9kZWwuIikNCmBgYA0KDQpLZXkgZmluZGluZ3M6DQoNCi0gKipPdmVyYWxsIHF1YWxpdHkqKiBoYXMgb25lIG9mIHRoZSBsYXJnZXN0IHBvc2l0aXZlIGVmZmVjdHM7IGVhY2ggb25lLXVuaXQgaW5jcmVhc2UgaW4gcXVhbGl0eSByYXRpbmcgaXMgYXNzb2NpYXRlZCB3aXRoIGEgc2l6YWJsZSBpbmNyZWFzZSBpbiBzYWxlIHByaWNlLCBob2xkaW5nIG90aGVyIHZhcmlhYmxlcyBmaXhlZC4gIA0KLSAqKlRvdGFsIGJhdGhyb29tcyoqIGFuZCAqKmdhcmFnZSBjYXBhY2l0eS9hcmVhKiogaGF2ZSBzdHJvbmcgcG9zaXRpdmUgY29lZmZpY2llbnRzLCBpbmRpY2F0aW5nIHRoYXQgYWRkaXRpb25hbCBiYXRocm9vbXMgYW5kIHBhcmtpbmcgY2FwYWNpdHkgeWllbGQgbWVhbmluZ2Z1bCBwcmljZSBwcmVtaXVtcy4gIA0KLSAqKkZpcmVwbGFjZXMqKiBhZGQgdmFsdWUsIHRob3VnaCBvbiBhIHNtYWxsZXIgc2NhbGUgdGhhbiBxdWFsaXR5IGFuZCBzaXplLiAgDQotICoqSG91c2UgYWdlKiogYW5kICoqeWVhcnMgc2luY2UgcmVtb2RlbCoqIGdlbmVyYWxseSBoYXZlIG5lZ2F0aXZlIGNvZWZmaWNpZW50cywgbWVhbmluZyBvbGRlciBhbmQgbGVzcyByZWNlbnRseSB1cGRhdGVkIGhvbWVzIHNlbGwgZm9yIGxlc3MuDQoNCiMgOCBCb290c3RyYXAgUmVncmVzc2lvbg0KDQpXZSB1c2UgYm9vdHN0cmFwIG1ldGhvZHMgdG8gYXNzZXNzIHRoZSByb2J1c3RuZXNzIG9mIHBhcmFtZXRyaWMgaW5mZXJlbmNlIGZvciB0aGUgZmluYWwgbW9kZWwuDQoNCiMjIEJvb3RzdHJhcHBpbmcgY2FzZXMNCg0KYGBge3IgYm9vdHN0cmFwLWNhc2VzfQ0Kc2V0LnNlZWQoMzIxKQ0KDQpYIDwtIG1vZGVsLm1hdHJpeChtX2ZpbmFsKQ0KeV9maW5hbCA8LSBtb2RlbC5yZXNwb25zZShtb2RlbC5mcmFtZShtX2ZpbmFsKSkNCnAgPC0gbGVuZ3RoKGNvZWYobV9maW5hbCkpDQpjb2VmX25hbWVzIDwtIG5hbWVzKGNvZWYobV9maW5hbCkpDQpCIDwtIDEwMDANCg0KYm9vdF9iZXRhX2Nhc2UgPC0gbWF0cml4KE5BX3JlYWxfLCBucm93ID0gQiwgbmNvbCA9IHApDQpjb2xuYW1lcyhib290X2JldGFfY2FzZSkgPC0gY29lZl9uYW1lcw0KDQpmb3IgKGIgaW4gMTpCKSB7DQogIGlkeCA8LSBzYW1wbGUuaW50KG5yb3coWCksIHJlcGxhY2UgPSBUUlVFKQ0KICBmaXRfYiA8LSBsbSh5X2ZpbmFsW2lkeF0gfiBYW2lkeCwgLTFdKQ0KICBib290X2JldGFfY2FzZVtiLCBdIDwtIGNvZWYoZml0X2IpDQp9DQoNCmNpX2Nhc2VfbWF0IDwtIGFwcGx5KGJvb3RfYmV0YV9jYXNlLCAyLA0KICAgICAgICAgICAgICAgICAgICAgcXVhbnRpbGUsIHByb2JzID0gYygwLjAyNSwgMC45NzUpLCBuYS5ybSA9IFRSVUUpDQoNCmNpX2Nhc2VfdGJsIDwtIHRpYmJsZTo6dGliYmxlKA0KICB0ZXJtICA9IGNvbG5hbWVzKGNpX2Nhc2VfbWF0KSwNCiAgYDIuNSVgID0gYXMubnVtZXJpYyhjaV9jYXNlX21hdFsxLCBdKSwNCiAgYDk3LjUlYD0gYXMubnVtZXJpYyhjaV9jYXNlX21hdFsyLCBdKQ0KKQ0KDQpwYW5kZXI6OnBhbmRlcihjaV9jYXNlX3RibCwNCiAgICAgICAgICAgICAgIGNhcHRpb24gPSAiOTUlIGJvb3RzdHJhcCBjb25maWRlbmNlIGludGVydmFscyAoY2FzZSByZXNhbXBsaW5nKS4iKQ0KYGBgDQoNCiMjIEJvb3RzdHJhcHBpbmcgcmVzaWR1YWxzDQoNCmBgYHtyIGJvb3RzdHJhcC1yZXNpZHVhbHN9DQpmaXRfaGF0ICAgPC0gZml0dGVkKG1fZmluYWwpDQpyZXNpZF9oYXQgPC0gcmVzaWQobV9maW5hbCkNCg0KYm9vdF9iZXRhX3JlcyA8LSBtYXRyaXgoTkFfcmVhbF8sIG5yb3cgPSBCLCBuY29sID0gcCkNCmNvbG5hbWVzKGJvb3RfYmV0YV9yZXMpIDwtIGNvZWZfbmFtZXMNCg0KZm9yIChiIGluIDE6Qikgew0KICB5X3N0YXIgPC0gZml0X2hhdCArIHNhbXBsZShyZXNpZF9oYXQsIHJlcGxhY2UgPSBUUlVFKQ0KICBmaXRfYiAgPC0gbG0oeV9zdGFyIH4gWFssIC0xXSkNCiAgYm9vdF9iZXRhX3Jlc1tiLCBdIDwtIGNvZWYoZml0X2IpDQp9DQoNCmNpX3Jlc2lkX21hdCA8LSBhcHBseShib290X2JldGFfcmVzLCAyLA0KICAgICAgICAgICAgICAgICAgICAgIHF1YW50aWxlLCBwcm9icyA9IGMoMC4wMjUsIDAuOTc1KSwgbmEucm0gPSBUUlVFKQ0KDQpjaV9yZXNpZF90YmwgPC0gdGliYmxlOjp0aWJibGUoDQogIHRlcm0gID0gY29sbmFtZXMoY2lfcmVzaWRfbWF0KSwNCiAgYDIuNSVgID0gYXMubnVtZXJpYyhjaV9yZXNpZF9tYXRbMSwgXSksDQogIGA5Ny41JWA9IGFzLm51bWVyaWMoY2lfcmVzaWRfbWF0WzIsIF0pDQopDQoNCnBhbmRlcjo6cGFuZGVyKGNpX3Jlc2lkX3RibCwNCiAgICAgICAgICAgICAgIGNhcHRpb24gPSAiOTUlIGJvb3RzdHJhcCBjb25maWRlbmNlIGludGVydmFscyAocmVzaWR1YWwgcmVzYW1wbGluZykuIikNCmBgYA0KDQojIyBDb21wYXJpc29uIHdpdGggcGFyYW1ldHJpYyBpbnRlcnZhbHMNCg0KQWNyb3NzIG1ham9yIHByZWRpY3RvcnMsIHRoZSBib290c3RyYXAgaW50ZXJ2YWxzIGZyb20gYm90aCBtZXRob2RzIGFyZSAqKnZlcnkgc2ltaWxhcioqIHRvIHRoZSBwYXJhbWV0cmljIGNvbmZpZGVuY2UgaW50ZXJ2YWxzLCBhbmQgYWxsIHRocmVlIHByb2NlZHVyZXMgYWdyZWUgb24gd2hpY2ggY29lZmZpY2llbnRzIGFyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIHplcm8uIFRoaXMgaW5kaWNhdGVzIHRoYXQgdGhlIHNhbXBsZSBzaXplIGlzIGxhcmdlIGVub3VnaCBmb3IgY2xhc3NpY2FsIGxpbmVhci1tb2RlbCBpbmZlcmVuY2UgdG8gYmUgcmVsaWFibGUsIGV2ZW4gaW4gdGhlIHByZXNlbmNlIG9mIG1pbGQgZGV2aWF0aW9ucyBmcm9tIGlkZWFsIGFzc3VtcHRpb25zLg0KDQojIENvbmNsdXNpb25zDQoNClRoZSBmaW5hbCBzdGVwd2lzZSByZWdyZXNzaW9uIG1vZGVsIGV4cGxhaW5zIGEgbGFyZ2UgcG9ydGlvbiBvZiB0aGUgdmFyaWF0aW9uIGluIEFtZXMgaG9tZSBzYWxlIHByaWNlcyBhbmQgaGlnaGxpZ2h0cyB0aGF0IGJ1eWVycyBwYXkgdGhlIGhpZ2hlc3QgcHJlbWl1bXMgZm9yOg0KDQotIEhpZ2hlciAqKm92ZXJhbGwgcXVhbGl0eSBhbmQgY29uZGl0aW9uKiogIA0KLSBHcmVhdGVyICoqbGl2aW5nIGFyZWEqKiBhbmQgKipiYXRocm9vbSBjb3VudHMqKiAgDQotIExhcmdlciAqKmdhcmFnZXMqKiBhbmQgYWRkaXRpb25hbCBhbWVuaXRpZXMgc3VjaCBhcyAqKmZpcmVwbGFjZXMqKiAgDQoNCk9sZGVyIGhvbWVzIGFuZCB0aG9zZSB3aXRoIGxvbmcgaW50ZXJ2YWxzIHNpbmNlIHRoZSBsYXN0IHJlbW9kZWwgdGVuZCB0byBzZWxsIGZvciBsb3dlciBwcmljZXMsIGhvbGRpbmcgb3RoZXIgZmFjdG9ycyBjb25zdGFudC4NCg0KQm9vdHN0cmFwIGluZmVyZW5jZSBjb3Jyb2JvcmF0ZXMgdGhlIHBhcmFtZXRyaWMgcmVzdWx0cywgc3VnZ2VzdGluZyB0aGF0IHRoZSBrZXkgY29uY2x1c2lvbnMgYWJvdXQgZHJpdmVycyBvZiBzYWxlIHByaWNlIGFyZSByb2J1c3QuDQoNCiMgTGltaXRhdGlvbnMgYW5kIEZ1dHVyZSBXb3JrDQoNCi0gSW1wb3J0YW50IGZhY3RvcnMgc3VjaCBhcyBuZWlnaGJvcmhvb2Qgc2Nob29sIHF1YWxpdHksIHByb3hpbWl0eSB0byB3b3JrcGxhY2VzLCBhbmQgYnJvYWRlciBlY29ub21pYyB0cmVuZHMgYXJlIG5vdCBpbmNsdWRlZC4gIA0KLSBOb25saW5lYXJpdGllcyBhbmQgaW50ZXJhY3Rpb24gZWZmZWN0cyB3ZXJlIG5vdCBmdWxseSBleHBsb3JlZC4gIA0KLSBUaGUgYW5hbHlzaXMgaXMgc3BlY2lmaWMgdG8gQW1lcyBhbmQgbWF5IG5vdCBnZW5lcmFsaXplIHRvIG90aGVyIGhvdXNpbmcgbWFya2V0cy4NCg0KRnV0dXJlIHdvcmsgY291bGQgaW5jb3Jwb3JhdGUgYWRkaXRpb25hbCBsb2NhdGlvbi1iYXNlZCB2YXJpYWJsZXMsIGV4cGxvcmUgZmxleGlibGUgbm9ubGluZWFyIG1vZGVscyAoc3BsaW5lcywgdHJlZS1iYXNlZCBtZXRob2RzKSwgYW5kIHZhbGlkYXRlIG1vZGVsIHBlcmZvcm1hbmNlIHVzaW5nIG91dC1vZi1zYW1wbGUgcHJlZGljdGlvbnMgb3IgdGltZS1iYXNlZCBjcm9zcy12YWxpZGF0aW9uLg0K