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:
- Build an interpretable multiple linear regression model for sale
price.
- Diagnose violations of linear-model assumptions and apply a
Box–Cox transformation when appropriate.
- Compare several candidate models (full, Box–Cox, and stepwise AIC)
using goodness-of-fit criteria.
- Use bootstrap methods to construct confidence
intervals for regression coefficients and evaluate the robustness of
parametric inference.
Practical questions include:
- Which features (living area, quality, bathrooms, garages,
fireplaces, age) have the strongest impact on sale price?
- How large are those impacts in dollar terms?
- Are bootstrap confidence intervals consistent with the usual
parametric intervals?
Data Set and Practical
Questions
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).
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
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).
Practical
questions
- Which structural and amenity variables have the strongest impact on
sale price?
- Can a linear regression model explain a substantial portion of the
variation in sale price while meeting key assumptions?
- Are conclusions based on parametric inference stable under bootstrap
resampling?
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.
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:
- Fit the full model and check multicollinearity and
residual diagnostics.
- Fit a Box–Cox transformed model to improve
normality and variance stability.
- Use stepwise AIC to obtain a parsimonious
model.
- Compare models with \(R^2\),
adjusted \(R^2\), Mallows’ \(C_p\), and PRESS.
- Select a final model for interpretation and bootstrap
inference.
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.
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.
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.
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.
Model Selection and
Goodness-of-Fit
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.
Goodness-of-fit
comparison
Goodness-of-fit summary for candidate models.
| 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.
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)
| (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 |
| -65373 |
| 40.03 |
| 24.55 |
| 19692 |
| 5964 |
| -194 |
| -154.6 |
| 9611 |
| 45.34 |
| 10394 |
| 0.7727 |
| 46.59 |
| 17.15 |
| 6772 |
Key findings:
- Overall quality has one of the largest positive
effects; each one-unit increase in quality rating is associated with a
sizable increase in sale price, holding other variables fixed.
- Total bathrooms and garage
capacity/area have strong positive coefficients, indicating
that additional bathrooms and parking capacity yield meaningful price
premiums.
- Fireplaces add value, though on a smaller scale
than quality and size.
- House age and years since remodel
generally have negative coefficients, meaning older and less recently
updated homes sell for less.
8 Bootstrap
Regression
We use bootstrap methods to assess the robustness of parametric
inference for the final model.
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).
| (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 |
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).
| (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 |
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.
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:
- Higher overall quality and condition
- Greater living area and bathroom
counts
- Larger garages and additional amenities such as
fireplaces
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.
Limitations and Future
Work
- Important factors such as neighborhood school quality, proximity to
workplaces, and broader economic trends are not included.
- Nonlinearities and interaction effects were not fully
explored.
- The analysis is specific to Ames and may not generalize to other
housing markets.
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