Keywords: Ordinary Least Square Regression, K-fold Cross Validation,
Sum of Square Errors, Root Mean Squared Error, Stepwise AIC
Methods
Data Cleaning
The original dataset used in this study consisted of 1816 census
block groups in Philadelphia according to the 2000 Census, but to ensure
the dataset was suitable for regression analysis, several data cleaning
procedures were performed. First, every block group in the dataset with
a population of less than 40 was removed. These block groups represent
sparsely populated or unusually housed areas that may introduce noise
into the analysis. Secondly, block groups without any housing units were
also excluded due to their lack of significance in a study centered on
housing attributes. Thirdly, block groups with a median housing value of
less than $10,000 were not included. These block groups do not
accurately reflect the reality of the typical housing market, and the
unusually low home values in these block groups may bias the results of
the study. Finally, a unique combination of values - median property
values over $800,000 and typical household incomes less than $8,000 -
led to the exclusion of one block group in North Philadelphia. As a
clear outlier, it was excluded to avoid biasing the results. The final
dataset includes 1,720 observations, each corresponding to a different
Philadelphia block group, and has the following attributes:
- POLY_ID: Census block group ID
- MEDHVAL: Median value of all owner occupied housing
units
- PCTBACHMOR: Proportion of residents in Block Group
with at least a Bachelor’s degree
- PCTVACANT: Proportion of housing units that are
vacant
- PCTSINGLES: Percent of housing units that are
detached single family houses
- NBELPOV100: Number of households with incomes below
100% poverty level (i.e., number of households living in poverty)
- MEDHHINC: Median household income
Exploratory Data Analysis
We begin by examining the summary statistics and distributions of the
dependent and independent variables. This will provide a better
understanding of the data and help identify any potential outliers or
unusual patterns that may need to be addressed before proceeding with
regression analysis. In our case, the median home value (MEDHVAL) is the
dependent variable. The independent variables are the proportion of the
population with a bachelor’s degree or higher (PCBACHMORE), the number
of households in poverty (NBELPOV100), the proportion of vacant homes
(PCTVACANT), and the proportion of single family homes (PCTSINGLES). We
computed the mean and standard deviation for each variable to understand
the central tendency and variability of the data. If results show that
the variable is non-normally distributed, we apply a log transformation
to normalize the data.
This is followed by investigating the correlations between the
predictor variables to avoid multicollinearity. Correlation is a
statistical measure that describes the strength and direction of a
relationship between variables. The correlation coefficient \(r\) quantifies the degree to which two
variables are linearly related. The formula for the sample correlation
coefficient \(r\) is as follows:
\[
r = \frac{\sum_{i=1}^{n} (x_i - \bar{x})(y_i -
\bar{y})}{\sqrt{\sum_{i=1}^{n} (x_i - \bar{x})^2 \sum_{i=1}^{n} (y_i -
\bar{y})^2}}
\] In a more concise way, this above formula is also equivalent
to the following:
\[
r = \frac{1}{n-1} \sum_{i=1}^{n} \left( \frac{x_i - \bar{x}}{S_x}
\right) \left( \frac{y_i - \bar{y}}{S_y} \right)
\] where \(x_i\) and \(y_i\) are individual data points, \(\bar{x}\) and \(\bar{y}\) are the means of the variables
\(x\) and \(y\), \(S_x\) and \(S_y\) are the standard deviations of the
variables \(x\) and \(y\) respectively.
For each observation \(i\), the
formula calculates the difference between the data point \(x_i\), \(y_i\) and the mean of the variables and
then divides them by their standard deviation. Then, these standardized
values are multiplied together to assess the extent to which the two
variables deviate from their respective means in the same direction. The
result of this multiplication is summed across all observations, which
aggregates the individual contributions to the correlation. Finally,
dividing this sum by \(n-1\) where
\(n\) is the number of observations
yields the sample correlation coefficient \(r\).
The correlation coefficient \(r\) can range from -1 to +1. A
value of +1 indicates a perfect positive linear relationship, where
increases in one variable correspond with increases in the other, while
a value of -1 indicates a perfect negative linear relationship. A value
of 0 suggests no linear relationship between the variables, meaning
changes in one do not predict changes in the other. Understanding the
correlations between the predictors is critical to identify whether any
variables are highly correlated, which would suggest multicollinearity.
Multicollinearity can distort the regression results by inflating the
standard errors of the coefficients, which lead to less reliable
interpretations.
Multiple Regression Analysis
After exploring the data, we conduct a multiple regression analysis
to examine the relationship between the dependent variable (median house
value) and the independent variables (educational attainment, poverty
levels, vacancy rates, and single-family housing). Regression analysis
is a statistical method used to examine the relationship between a
dependent variable and one or more independent variables. It allows
researchers to understand how the dependent variable changes as the
independent variables vary and make inferences about the relationships
among the variables. The model estimates coefficients for each
independent variable, which quantify the expected change in the
dependent variable for a one-unit increase in the independent variable,
holding all other variables constant. For our problem, the equation for
the multiple regression model is as follows:
\[
\text{LNMEDHVAL} = \beta_0 + \beta_1 \text{PCTVACANT} + \beta_2
\text{PCTSINGLES} + \beta_3 \text{PCTBACHMOR} + \beta_4
\text{LN(LNNBELPOV100)} + \epsilon
\]
where \(\text{LNMEDHVAL}\) is the
log-transformed median house value, \(\text{PCTVACANT}\) is the proportion of
vacant housing units, \(\text{PCTSINGLES}\) is the proportion of
single-family detached homes, \(\text{PCTBACHMOR}\) is the percentage of
residents with a bachelor’s degree or higher, \(\text{LN(LNNBELPOV100)}\) is the
log-transformed number of households living below the poverty line.
\(\beta_0\) is the intercept, \(\beta_1, \beta_2, \beta_3, \beta_4\) are
the coefficients for each independent variable, and \(\epsilon\) is the residual error term. The
coefficients \(\beta_1, \beta_2, \beta_3,
\beta_4\) represent the expected change in \(\text{LNMEDHVAL}\) for a one-unit increase
in the corresponding independent variable, holding all other variables
constant. The error term \(\epsilon\)
accounts for the variability in \(\text{LNMEDHVAL}\) that is not explained by
the independent variables.
Regression Assumptions
There are several assumptions associated with regression analysis
that needs to be checked before we further proceed. First,
linearity asserts that there should be a linear
relationship between the dependent variables and independent variable.
To verify this assumption, we made scatterplots to visualize the
relationship between the relationship between \(y\) and each of the predictor.
Second the assumption of independence of
observations requires that the observations within the dataset
be independent of one another, without any spatial, temporal, or other
dependencies. In spatial contexts, we made choropleth maps to assess the
presence of spatial autocorrelation in the residuals or dependent
variable.
Third, the normality of residuals assumption states
that the residuals should follow a normal distribution. While this
assumption is less critical in large samples due to the Central Limit
Theorem, it remains desirable for inference purposes. To evaluate this
assumption, we made a histogram of the residuals - a bell-shaped curve
would suggest that the residuals are normally distributed.
Another important assumption is homoscedasticity,
which states that the variance of the residuals should remain constant
across all levels of the independent variables. We assessed
homoscedasticity by examining scatterplot of standardized residuals
against predicted values. Ideally, these residuals should be evenly
distributed around zero; any patterns may indicate the presence of
heteroscedasticity.
The assumption of no multicollinearity asserts that
the predictor variables should not be highly correlated with each other,
as this can inflate the variance of the coefficient estimates and make
them unstable. To check for multicollinearity, we created a correlation
matrixfor the predictors to look for any correlations greater than 0.8
(or less than -0.8).
Finally, it is important to consider the ratio of
observations to predictors in the model. A general guideline
suggests having at least 10 to 15 observations for each predictor to
ensure robust estimates. Since we have over 1700 observations in our
dataset, this assumption is met.
Parameter Estimations
After verifying these assumptions, we proceed with the regression
analysis. There are several parameters that we need to estimate here:
\(\beta_0\), which is the intercept,
\(\beta_1, \dots, \beta_k\), which are
coefficients of the independent variables, as well as \(\sigma^2\), the variance of the error
terms, which represents the variability in the dependent variable \(Y\) that is not explained by the predictors
\(X_1, \dots, X_k\).
The least squares method estimates the coefficients by minimizing
the sum of squared residuals. Given \(n\) observations on \(y\), and \(k\) predictors \(X_1, \dots, X_k\), the estimates \(\beta_1, \dots, \beta_k\) are chosen
simultaneously to minimize the expression for the Error Sum of Squares
(SSE), given by:
\[
\text{SSE} = \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 = \sum_{i=1}^{n} (y_i -
\hat{\beta}_0 - \hat{\beta}_1 x_{i1} - \dots - \hat{\beta}_k x_{ik})^2
\]
where \(y_i\) represents the actual
values, \(\hat{\beta}_0\) is the
estimated intercept, \(\beta_1\) is the
coefficient for the predictor \(x_{1i}\), and \(x_{1i}\) is the predictor value for the
\(i\)-th observation.
With the Error Sum of Squares (SSE), the equation of the estimated
variance of the error term \(\sigma^2\)
is given by:
\[
\sigma^2 = \frac{\text{SSE}}{n - (k+1)}
\]
where \(n\) is the number of
observations and \(k\) is the number of
predictors in the model.
We evaluated the model’s goodness of fit using the coefficient of
determination \(R^2\), which quantifies
the proportion of variance in the dependent variable explained by the
independent variables. The adjusted \(R^2\), which adjusts the \(R^2\) value based on the number of
predictors in the model to provide a more accurate measure of model fit
for multiple regression. In simple regression:
\[
SST = \sum_{i=1}^{n} (y_i - \bar{y})^2
\] where \(y_i\) is the observed
value, \(\bar{y}\) is the mean of the
observed values, and \(n\) is the
number of observations. Then, \(R^2\)
can be simply obtained by:
\[
R^2 = 1 - \frac{SSE}{SST}
\] \(R^2\) is then typically
adjusted as follows based on \(n\), the
number of observations and \(k\), the
number of predictors in the model.
\[
R^2_{\text{adj}} = 1 - \frac{(1 - R^2)(n - 1)}{n - k - 1}
\]
Hypothesis Testing
In this analysis, we test several hypotheses to evaluate the
significance of the model and its predictors. The overall significance
of the regression model is assessed using the F-ratio. It compares the
variance explained by the regression model to the variance that is not
explained by the model, assessing whether the independent variables as a
whole have a statistically significant effect on the dependent variable.
A higher F-ratio indicates that the regression model explains a
significant amount of variance in the dependent variable compared to the
residual variance.
The null hypothesis (\(H_0\)) and
alternative hypothesis (\(H_a\)) for
the F-ratio are stated as follows:
Null Hypothesis (\(H_0\)): The regression model does
not explain a significant portion of the variance in the dependent
variable (median house value). In our case, this means that the
coefficients for all the predictors are equal to zero and none of them
explain any variance in housing price. This can be formally stated as:
\[
H_0: \beta_1 = \beta_2 = \beta_3 = \beta_4 = 0
\]
Alternative Hypothesis (\(H_a\)): At least one of the
predictor variables has a significant effect on the dependent variable.
In our case, this means that at least one of the coefficients for the
predictors is not equal to zero, indicating that the predictor has a
significant impact on housing prices. This can be stated as: \[
H_a: \text{At least one } \beta_i \neq 0
\]
For each individual predictor \(\beta_i\), we also test the following
hypotheses:
Null Hypothesis (\(H_{0i}\)): The coefficient for the
predictor \(i\) is equal to zero,
indicating that it does not have a significant effect on the dependent
variable (median house value). This can be formally stated as: \[
H_{0i}: \beta_i = 0
\]
Alternative Hypothesis (\(H_{ai}\)): The coefficient for the
predictor \(i\) is not equal to zero,
indicating that it has a significant effect on the dependent variable.
This can be stated as: \[
H_{ai}: \beta_i \neq 0
\]
Each predictor’s significance is typically assessed using a t-test,
which tests whether the estimated coefficient differs significantly from
zero.
Additional Analyses
In addition, we conducted stepwise regression to identify the most
important predictors of median house values in Philadelphia. Stepwise
regression is a variable selection technique that automatically selects
the best subset of predictors for the model. It involves adding or
removing predictors based on their statistical significance, with the
goal of creating a parsimonious model that explains the most variance in
the dependent variable.
We acknowledge several limitations of stepwise regression. First, the
final model selected by stepwise regression is not guaranteed to be
optimal in any specific sense. There may be other models that are just
as good, or even better, than the one identified through this process.
Additionally, the method yields only a single final model, even though
multiple models could provide equally valid or informative predictions.
Moreover, stepwise regression does not take into account the
researcher’s domain knowledge regarding the predictors. Important
variables may be excluded unless manually forced into the model, which
can lead to an incomplete or inaccurate understanding of the
relationships between the variables. This method also runs the risk of
Type I and Type II errors—meaning it may include unimportant variables
or exclude important ones.
We also performed K-fold cross-validation to assess the predictive
performance of the model. Cross-validation is a resampling technique
used to evaluate the performance of a predictive model. In K-fold
cross-validation, the dataset is divided into K subsets or folds. The
model is trained on K-1 folds and tested on the remaining fold. This
process is repeated K times, with each fold serving as the test set
exactly once. The performance of the model is then averaged across the K
folds to provide an overall estimate of predictive accuracy. In our
analysis, we used K = 5, which is a common choice for cross-validation.
The root mean squared error (RMSE) is used to compare the performance of
different models. The RMSE is a measure of the differences between
predicted and observed values, with lower values indicating better
predictive accuracy. In previous analysis, we have calculated the sum of
squared errors (SSE) as follows:
\[ \text{SSE} = \sum_{i=1}^{n} (y_i -
\hat{y}_i)^2 \]
Then the mean square errors (MSE) is simply:
\[ \text{MSE} = \frac{1}{n} \sum_{i=1}^{n}
(y_i - \hat{y}_i)^2 \]
And the root mean square error (RMSE) is the square root of the
MSE:
\[
\text{RMSE} = \sqrt{\text{MSE}}
\]
Software and Pacakges
For our data analysis, we are utilizing the R programming language.
The following libraries have been employed to facilitate our
analysis:
tidyverse: A collection of R packages designed for data
science that includes tools for data manipulation, visualization, and
analysis.
here: A package that simplifies file path management,
making it easier to work with project directories.
kableExtra: A package for creating and customizing
tables in R Markdown documents.
ggplot2: A widely-used package for creating static
graphics and visualizations based on the grammar of graphics.
ggcorrplot: A package specifically designed for
visualizing correlation matrices using ggplot2.
sf: A package that provides support for spatial data in
R, enabling the handling and analysis of geometric objects.
patchwork: A package that allows for the combination of
multiple ggplot2 plots into a single cohesive layout.
MASS: A package that provides functions and datasets
for various statistical methods, including linear and generalized linear
models.
caret: A package that streamlines the process of
creating predictive models, including functions for data splitting,
pre-processing, feature selection, and model tuning.
Results
Exploratory Results
We began by summarizing the statistical data for median house values
and various socio-economic predictors. The median house value has an
average of $66,287.73, with a standard deviation of $60,006.08. This is
significantly lower than both the county and state averages and shows
considerable variation in house values. For educational attainment,
16.08% of individuals hold a Bachelor’s degree or higher, much lower
than the state average of 35.3%. The standard deviation of 17.77%
suggests notable variability in this measure. The average number of
households living in poverty is 189.77, with a wide range reflected by a
standard deviation of 164.32. Vacant houses make up an average of
11.29%, slightly higher than the state average of 9.4%, with a standard
deviation of 9.63%. Finally, single house units account for an average
of 9.23%, with a standard deviation of 13.25%.
# examine the mean and standard deviation of dependent and independent variables.
dist_results <- data.frame(Variable = character(), Mean = numeric(), SD = numeric(), stringsAsFactors = FALSE)
variables <- c("MEDHVAL", "PCTBACHMOR", "NBELPOV100", "PCTVACANT", "PCTSINGLES")
relabelled_variables <- c(
"Median House Value", # MEDHVAL
"% of Individuals with Bachelor’s Degrees or Higher", # PCTBACHMOR
"# Households Living in Poverty", # NBELPOV100
"% of Vacant Houses", # PCTVACANT
"% of Single House Units" # PCTSINGLES
)
for (i in seq_along(variables)) {
mean_val <- round(mean(data[[variables[i]]], na.rm = TRUE), 3)
sd_val <- round(sd(data[[variables[i]]], na.rm = TRUE), 3)
# Store the relabeled variable names
dist_results <- rbind(dist_results, data.frame(Variable = relabelled_variables[i], Mean = mean_val, SD = sd_val))
}
dist_results <- rbind(
data.frame(Variable = "Dependent Variable", Mean = "", SD = ""),
data.frame(Variable = "Median House Value", Mean = dist_results$Mean[1], SD = dist_results$SD[1]),
data.frame(Variable = "Predictors", Mean = "", SD = ""),
dist_results[-1, ] # Remove the first row because it has already been used above
)
dist_results %>%
kable(row.names = FALSE) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>%
row_spec(0, bold = TRUE) %>% # Bold the header row
row_spec(1, bold = TRUE) %>% # Bold the 'Dependent Variable' row
row_spec(3, bold = TRUE)
|
Variable
|
Mean
|
SD
|
|
Dependent Variable
|
|
|
|
Median House Value
|
66287.733
|
60006.076
|
|
Predictors
|
|
|
|
% of Individuals with Bachelor’s Degrees or Higher
|
16.081
|
17.77
|
|
# Households Living in Poverty
|
189.771
|
164.318
|
|
% of Vacant Houses
|
11.289
|
9.628
|
|
% of Single House Units
|
9.226
|
13.249
|
According to the histograms, none of the distributions of the
dependent and independent variables were normal. To address this, we
applied a logarithmic transformation to the variables.
# histogram
data %>%
pivot_longer(cols = c("MEDHVAL", "PCTBACHMOR", "NBELPOV100", "PCTVACANT", "PCTSINGLES"),
names_to = "Variable",
values_to = "Value") %>%
ggplot(aes(x = Value)) +
geom_histogram(aes(y = ..count..), fill = "#283d3b", alpha = 0.7) +
facet_wrap(~Variable, scales = "free", ncol = 3, labeller = as_labeller(c(
"MEDHVAL" = "Median House Value",
"PCTBACHMOR" = "% with Bachelor’s Degrees or Higher",
"NBELPOV100" = "# Households Living in Poverty",
"PCTVACANT" = "% of Vacant Houses",
"PCTSINGLES" = "% of Single House Units"
))) +
labs(x = "Value", y = "Count", title = "Histograms of Dependent and Predictor Variables") +
theme_light() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8))

This transformation has helped to normalize some of the
distributions, particularly for variables like median house value,
number of households in poverty, and percentage of vacant houses. These
variables now display more symmetric, bell-shaped distributions.
However, for variables like the percentage of individuals with a
bachelor’s degree and percentage of single house units, the
transformation was less effective, and they still deviate from a normal
distribution.
Moving forward, we will use the log-transformed results for our
analysis. The remaining regression assumptions will be examined in
detail in a separate section titled Regression Assumption Checks.
# histograms of the logged variables
reg_data %>%
pivot_longer(cols = c("LNMEDHVAL", "LNPCTBACHMOR", "LNNBELPOV100", "LNPCTVACANT", "LNPCTSINGLES"),
names_to = "Variable",
values_to = "Value") %>%
ggplot(aes(x = Value)) +
geom_histogram(aes(y = ..count..), fill = "#283d3b", alpha = 0.7) +
facet_wrap(~Variable, scales = "free", ncol = 3, labeller = as_labeller(c(
"LNMEDHVAL" = "Median House Value",
"LNPCTBACHMOR" = "% with Bachelor’s Degrees or Higher",
"LNNBELPOV100" = "# Households Living in Poverty",
"LNPCTVACANT" = "% of Vacant Houses",
"LNPCTSINGLES" = "% of Single House Units"
))) +
labs(x = "Value", y = "Count", title = "Histograms with Logged Transform Variables") +
theme_light() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8))

The choropleth maps of the dependent variable and the predictor
variables reveal several notable patterns. In particular, the map of
median house values shows higher values in the northwest Philadelphia
and center city while lower values in the south and west of
Philadelphia. This pattern is consistent with the distribution of single
house units and the percentage of individuals with a bachelor’s degree
or higher, which also exhibit higher concentrations in the northwest and
center city. In contrast, the maps of households living in poverty and
vacant housing units show higher concentrations in the north, west, and
parts of the south of Philadelphia. These patterns suggest an inverse
relationship between poverty and vacant housing with educational
attainment and single-family homeownership. It also appears that there
might some degree of multicolinearity between percentage of population
with a bachelor’s degree or higher and percentage of single family
units, given that they share similar spatial patterns.
# choropleth maps of predictor and dependent variables
ggplot(philly) +
geom_sf(aes(fill = LNMEDHVAL), color = "transparent") +
scale_fill_gradientn(colors = c("#FAF9F6", "#c44536"),
name = "LNMEDHVAL",
na.value = "transparent") + # Handle NAs
theme(legend.text = element_text(size = 9),
legend.title = element_text(size = 10),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
plot.subtitle = element_text(size = 9, face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
panel.background = element_blank(),
panel.border = element_rect(colour = "grey", fill = NA, size = 0.8)) +
labs(title = "Log Transformed Median House Value")

map_pctvacant <- ggplot(philly) +
geom_sf(aes(fill = PCTVACANT), color = "transparent") +
scale_fill_gradientn(colors = c("#FAF9F6", "#c44536"),
name = "PCTVACANT",
na.value = "transparent") + # Handle NAs
theme(legend.text = element_text(size = 9),
legend.title = element_text(size = 10),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
plot.subtitle = element_text(size = 9, face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
panel.background = element_blank(),
panel.border = element_rect(colour = "grey", fill = NA, size = 0.8)) +
labs(title = "% of Vacant Houses")
map_pctsingles <- ggplot(philly) +
geom_sf(aes(fill = PCTSINGLES), color = "transparent") +
scale_fill_gradientn(colors = c("#FAF9F6", "#c44536"),
name = "PCTSINGLES",
na.value = "transparent") + # Handle NAs
theme(legend.text = element_text(size = 9),
legend.title = element_text(size = 10),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
plot.subtitle = element_text(size = 9, face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
panel.background = element_blank(),
panel.border = element_rect(colour = "grey", fill = NA, size = 0.8)) +
labs(title = "% of Single House Units")
map_pcbachmore <- ggplot(philly) +
geom_sf(aes(fill = PCTBACHMOR), color = "transparent") +
scale_fill_gradientn(colors = c("#FAF9F6", "#c44536"),
name = "PCTBACHMOR",
na.value = "transparent") + # Handle NAs
theme(legend.text = element_text(size = 9),
legend.title = element_text(size = 10),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
plot.subtitle = element_text(size = 9, face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
panel.background = element_blank(),
panel.border = element_rect(colour = "grey", fill = NA, size = 0.8)) +
labs(title = "% Bachelor's Degree or Higher")
map_lnbelpov100 <- ggplot(philly) +
geom_sf(aes(fill = LNNBELPOV), color = "transparent") +
scale_fill_gradientn(colors = c("#FAF9F6", "#c44536"),
name = "LNNBELPOV",
na.value = "transparent") + # Handle NAs
theme(legend.text = element_text(size = 9),
legend.title = element_text(size = 10),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
plot.subtitle = element_text(size = 9, face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
panel.background = element_blank(),
panel.border = element_rect(colour = "grey", fill = NA, size = 0.8)) +
labs(title = "Logged Transformed Poverty")
map_pctvacant + map_pctsingles + map_pcbachmore + map_lnbelpov100 +
plot_layout(ncol = 2)

The correlation matrix supports our observations from the map.
There’s a positive linear relationship between the percentage of people
with at least a Bachelor’s Degree or higher and the percentage of
single-family units, with a correlation coefficient of 0.2. The
percentage of households living below the poverty line also positively
correlated with the percentage of vacant houses, with a correlation
coefficient of 0.25. These correlations suggest that the predictors are
related to each other, but since none of these correlations exceed 0.8,
we can proceed with the regression analysis without concerns about
multicollinearity.
custom_labels <- c(
"% of Individuals with Bachelor’s Degrees or Higher" = "PCTBACHMOR",
"% of Vacant Houses" = "PCTVACANT",
"% of Single House Units" = "PCTSINGLES",
"# Households Living in Poverty" = "LNNBELPOV100"
)
cor_matrix <- cor(reg_data %>% dplyr::select(PCTBACHMOR, PCTVACANT, PCTSINGLES, LNNBELPOV100))
rownames(cor_matrix) <- names(custom_labels)
colnames(cor_matrix) <- names(custom_labels)
ggcorrplot(cor_matrix,
type = "lower",
lab = TRUE,
lab_size = 3,
colors = c("#283d3b", "white", "#c44536")) +
labs(title = "Correlation Matrix for all Predictor Variables") +
theme(plot.subtitle = element_text(size = 9, face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x = element_text(size = 7),
axis.text.y = element_text(size = 7),
axis.title = element_text(size = 8))

Regression Results
Parameter Estimates
Four independent variables, the proportion of vacant housing units
(PCTVACANT), the proportion of single-family detached homes
(PCTSINGLES), the proportion of residents with at least a Bachelor’s
degree (PCTBACHMOR), and the number of log-transformed households living
below the poverty line (LNNBELPOV100), were regressed to predict the
median log-transformed home values (LNMEDHVAL) for the Philadelphia
census block group.
The regression output tells us that the median home values are highly
significant and are associated with the proportion of single-family
detached homes(PCTSINGLES), the proportion of residents with at least a
Bachelor’s degree (PCTBACHMOR), the proportion of vacant housing units
(PCTVACANT), and the number of log-transformed households living below
the poverty line (LNNBELPOV100), with \(p <
0.001\) for all predictors.
As the proportions of vacant housing units (PCTVACANT) goes up by one
unit (i.e.percentage point), the expected change in median home value
is:
\[(e^{\beta} - 1) \times 100\% =
(e^{-0.0191569} - 1) \times 100\% \approx -1.897\% \]
That is, as percentage of population living in poverty goes up by 1
unit (1%), median home value goes down by approximately 1.897%, holding
other predictors constant. The p-value of of less than 0.0001 for
PCTVACANT tells us that if there is actually no relationship between
PCTVACANT and the dependent variable (i.e., if the null hypothesis that
\(\beta_1 = 0\) is actually true), then
the probability of getting a \(\beta_1\) coefficient estimate of
-0.0191569 is less than 0.0001.
Similarly, as the proportion of single-family detached homes
(PCTSINGLES) goes up by one unit (i.e.percentage point), the expected
change in median home value is:
\[(e^{\beta} - 1) \times 100\% =
(e^{0.0029769} - 1) \times 100\% \approx 0.298\% \]
That is, as percentage of population living in poverty goes up by 1
unit (1%), median home value goes up by approximately 0.298%, holding
other predictors constant. The p-value of of less than 0.0001 for
PCTSINGLES tells us that if there is actually no relationship between
PCTSINGLES and the dependent variable (i.e., if the null hypothesis that
\(\beta_2 = 0\) is actually true), then
the probability of getting a \(\beta_2\) coefficient estimate of 0.0029769
is less than 0.0001.
Moreover, as the proportion of people with a Bachelor’s degree or
higher (PCTBACHMOR) goes up by one unit (i.e.percentage point), the
expected change in median home value is:
\[(e^{\beta} - 1) \times 100\% =
(e^{0.0209098} - 1) \times 100\% \approx 2.11\% \]
That is, as percentage of population with a Bachelor’s degree or
higher goes up by 1 unit (1%), median home value goes up by
approximately 2.1%, holding other predictors constant. The p-value of of
less than 0.0001 for PCTBACHMOR tells us that if there is actually no
relationship between PCTBACHMOR and the dependent variable (i.e., if the
null hypothesis that \(\beta_3 = 0\) is
actually true), then the probability of getting a \(\beta_3\) coefficient estimate of 0.0209098
is less than 0.0001.
And finally, as the number of log-transformed households living below
the poverty line (LNNBELPOV100) changes by 1%, the expected value of
median home value changes by
\[(1.01^{\beta} - 1) \times 100\% =
(1.01^{-0.0789054} - 1) \times 100\% \approx -0.078\%\]
That is, as the number of households living below the poverty line
goes up 1%, median home value changes by -0.078%, holding % in other
predictors constant. The p-value of of less than 0.0001 for LNNBELPOV100
tells us that if there is actually no relationship between LNNBELPOV100
and the dependent variable (i.e., if the null hypothesis that \(\beta_4 = 0\) is actually true), then the
probability of getting a \(\beta_4\)
coefficient estimate of -0.0789054 is less than 0.0001.
All of these low probabilities indicate that we can safely reject
\(H_0: \beta_1 = 0\) for \(H_a: \beta_1 \neq 0\), \(H_0: \beta_2 = 0\) for \(H_a: \beta_2 \neq 0\), \(H_0: \beta_3 = 0\) for \(H_a: \beta_3 \neq 0\), and \(H_0: \beta_4 = 0\) for \(H_a: \beta_4 \neq 0\) (at most reasonable
levels of \(\alpha = P(\text{Type I
error})\)).
Model Fit
The residuals from the model show a fairly reasonable distribution of
errors, with a minimum residual value of -2.26, a first quartile of
-0.20, a median of 0.04, a third quartile of 0.22, and a maximum value
of 2.24. This distribution suggests that the model captures changes in
housing values reasonably well, although some of the extreme residuals
suggest that outliers may exist.
The model had a multiple R-squared value of 0.6623 and an adjusted
R-squared value of 0.6615, indicating that approximately 66% of the
variance in LNMEDHVAL is explained by the four predictors. The
F-statistic for this model was 840.9 (p < 0.001), further confirming
the statistical significance of the model as a whole.
fit <- lm(LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100, data=reg_data)
summary(fit)
##
## Call:
## lm(formula = LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR +
## LNNBELPOV100, data = reg_data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.25825 -0.20391 0.03822 0.21744 2.24347
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 11.1137661 0.0465330 238.836 < 0.0000000000000002 ***
## PCTVACANT -0.0191569 0.0009779 -19.590 < 0.0000000000000002 ***
## PCTSINGLES 0.0029769 0.0007032 4.234 0.0000242 ***
## PCTBACHMOR 0.0209098 0.0005432 38.494 < 0.0000000000000002 ***
## LNNBELPOV100 -0.0789054 0.0084569 -9.330 < 0.0000000000000002 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.3665 on 1715 degrees of freedom
## Multiple R-squared: 0.6623, Adjusted R-squared: 0.6615
## F-statistic: 840.9 on 4 and 1715 DF, p-value: < 0.00000000000000022
The analysis of variance (ANOVA) table provides additional insight
into the significance of each predictor in explaining the variation in
LNMEDHVAL. For example, the sum of squares for PCTVACANT is 180.392.
This value represents the variation in LNMEDHVAL that can be attributed
to changes in the percentage of vacant housing units. A higher sum of
squares indicates a stronger relationship between the predictor and the
response variable. The sum of squares for PCTSINGLES is 24.543, showing
that the percentage of single-parent households also contributes to
explaining the variation in LNMEDHVAL, though to a lesser extent than
PCTVACANT. The sum of squares for PCTBACHMOR is 235.118, indicating that
the percentage of residents with a bachelor’s degree or higher explains
a significant portion of the variance in LNMEDHVAL, more than the
previous two predictors. This reinforces the importance of educational
attainment in driving housing values. Lastly, the sum of squares for
LNNBELPOV100 is 11.692, suggesting that while this predictor does
contribute to explaining LNMEDHVAL, its impact is comparatively smaller
than the others.
The total sum of squares, which represents the unexplained variation
in the model, is 230.34, with a mean square error of 0.134.Overall, the
ANOVA results, combined with the OLS regression results, confirmed that
all four predictors-PCTVACANT, PCTSINGLES, PCTBACHMOR, and
LNNBELPOV100-contribute significantly to explaining the changes in
LNMEDHVAL were all significant contributors. These findings provide
strong evidence of the robustness of the model and the relevance of
neighbourhood characteristics in predicting housing values.
anova_table <- anova(fit)
anova_table
## Analysis of Variance Table
##
## Response: LNMEDHVAL
## Df Sum Sq Mean Sq F value Pr(>F)
## PCTVACANT 1 180.392 180.392 1343.087 < 0.00000000000000022 ***
## PCTSINGLES 1 24.543 24.543 182.734 < 0.00000000000000022 ***
## PCTBACHMOR 1 235.118 235.118 1750.551 < 0.00000000000000022 ***
## LNNBELPOV100 1 11.692 11.692 87.054 < 0.00000000000000022 ***
## Residuals 1715 230.344 0.134
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Regression Assumption Check
In this section, we conducted a variety of analyses to check if the
assumptions of the linear regression model were met. Earlier in this
report, we have already checked for variable distribution (see the stats
table above) and multicolinearity (see the corr diagram above). Thus, we
began here by examining the linearity assumption of the
model. We created scatter plots of the dependent variable (LNMEDHVAL)
against each of the predictors (PCTVACANT, PCTSINGLES, PCTBACHMOR, and
LNNBELPOV100).
The scatter plot for PCTVACANT shows a general negative relationship
between the proportion of vacant housing units and LNMEDHVAL. In the
graph, there are clusters of block groups where high vacancy rates
correspond to lower housing values, particularly on the left side of the
plot where the values of LNMEDHVAL are higher. However, the plot is not
perfectly linear. Instead, it reveals a more complex relationship with
significant variation in housing values across different vacancy rates.
In the middle and lower ranges of vacancy rates, the decline in housing
values becomes less pronounced. This suggests that while vacant housing
is associated with lower property values, the impact diminishes or
becomes less predictable as the vacancy rate changes.
In the scatter plot for PCTSINGLES, a weak positive trend can be
observed, though the points are scattered widely around the line,
indicating a weak linear relationship. As the percentage of
single-family homes increases, the values of LNMEDHVAL tend to increase,
but this pattern is not consistent across all block groups. The scatter
of points shows significant variability in housing values at various
levels of single-family housing, with some block groups exhibiting high
values even at lower percentages of single-family homes. This
variability suggests that while there is a positive association between
single-family housing and higher values, the relationship is more
nuanced, and other factors may be influencing house values at the same
time.
The scatter plot for PCTBACHMOR, however, shows a much clearer linear
relationship. As the proportion of residents with at least a bachelor’s
degree increases, the LNMEDHVAL values increase in a more consistent and
linear fashion. The points on the graph form a relatively tight band
along a positive trend line, indicating that higher education levels
within a neighborhood are strongly associated with higher housing
values. The consistent upward trend in this graph suggests that
educational attainment is a key driver of housing prices, and the linear
relationship implies that this variable is well-suited for inclusion in
the linear regression model.
The scatter plot for LNNBELPOV100 reveals a predominantly negative
relationship, but like PCTVACANT, the association is not strictly
linear. In the graph, as the number of households living below the
poverty line increases, the LNMEDHVAL values generally decrease.
However, the points are scattered widely, particularly at lower levels
of poverty, where housing values vary significantly. This indicates that
while poverty levels have a negative impact on housing values, the
effect is not uniform across all block groups. There is substantial
variation in the housing values even in neighborhoods with similar
poverty rates, suggesting that other factors may be at play. The
non-linear pattern observed in this graph highlights the complexity of
poverty’s influence on the housing market.
In summary, the scatterplot shows that while PCTBACHMOR and LNMEDHVAL
exhibit a strong and clear linear relationship, the other predictors -
in particular PCTVACANT and LNNBELPOV100 - exhibit more complex
non-linear patterns. The scatterplots provide important insights into
the relationship between the independent variables and housing values,
suggesting that while the model is assumed to be linear, it may not
fully capture the underlying dynamics. For variables such as PCTVACANT
and LNNBELPOV100, the nonlinearity observed in the plots suggests that
more complex nonlinear models may provide a better fit and more accurate
predictions.
# scatterplot
reg_data %>%
pivot_longer(cols = c("PCTBACHMOR", "LNNBELPOV100", "PCTVACANT", "PCTSINGLES"),
names_to = "Variable",
values_to = "Value") %>%
ggplot(aes(x = Value, y = LNMEDHVAL)) +
geom_point(color = "#283d3b", alpha = 0.7, size = 0.4) +
geom_smooth(method = "lm", color = "#c44536", se = FALSE) + # Add a linear regression line
facet_wrap(~ Variable, scales = "free", labeller = as_labeller(c(
"PCTBACHMOR" = "% with Bachelor’s Degrees or Higher",
"LNNBELPOV100" = "Households Living in Poverty",
"PCTVACANT" = "% of Vacant Houses",
"PCTSINGLES" = "% of Single House Units"
))) +
theme_light() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8)) +
labs(title = "Scatter Plots of Dependent Variable vs. Predictors",
x = "Predictor Value",
y = "Log of Median House Value")

Next, we examined the assumption of normality for
residuals of the regression model. The histogram of
standardized residuals provides a detailed view of the distribution of
the residuals from the OLS regression model. This graph maps the
frequency of residual values along the x-axis, with the residuals
centered around zero. The shape of the histogram approximates a bell
curve, which is characteristic of a normal distribution—a key assumption
for OLS regression.
The majority of the residuals are concentrated between -2 and 2 on
the x-axis, with the highest frequency occurring near zero. This
concentration suggests that most of the predicted values are close to
the observed values, leading to residuals that are small and distributed
symmetrically around zero. This is a positive sign, as it indicates that
the model does not systematically overpredict or underpredict the
dependent variable (LNMEDHVAL).
At the center of the distribution, the residuals form a tall, narrow
peak, representing a large number of residuals close to zero. This
suggests that the model fits most observations well. As we move further
away from the center, the frequency of residuals decreases
symmetrically, with fewer residuals having large positive or negative
values. This tapering off on both sides of the histogram suggests that
extreme residuals are relatively rare, which is typical of a normal
distribution.
However, there are some noticeable deviations from perfect normality
at the tails of the distribution. On the left side of the graph, there
are a few residuals with values smaller than -3, and on the right side,
there are a few residuals larger than 3. These residuals represent
outliers—cases where the model’s predictions deviate significantly from
the observed values. While these extreme values do not appear to
dominate the distribution, they are worth further examination, as they
could indicate areas where the model’s assumptions are being violated or
where influential points might be affecting the overall model fit.
In summary, the histogram of standardized residuals indicates that
the residuals are approximately normally distributed, which supports the
assumption of normality for the regression model. Although there are
some outliers present, their overall impact on the normality of the
residuals seems minimal. The general shape of the histogram suggests
that the OLS regression model fits the data reasonably well, with
residuals mostly falling within an acceptable range around zero.
ggplot(reg_data, aes(x = Standardized_Residuals)) +
geom_histogram(bins = 30, fill = "#283d3b", alpha = 0.7) +
labs(title = "Histogram of Standardized Residuals",
x = "Standardized Residuals",
y = "Frequency") +
theme_light() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8))

Following the normality check, we examined the assumption of
homoscedasticity, which requires that the residuals
have constant variance across all levels of the fitted values. The
scatter plot of standardized residuals versus fitted values is a
valuable diagnostic for testing essential regression assumptions,
including homoscedasticity and the presence of outliers. The fitted
values that the model predicts are plotted on the x-axis, and the
standardized residuals—that is, residuals adjusted by their standard
deviation—are shown on the y-axis. Because standardized residuals give
an indication of the standard deviation of each residual’s divergence
from the expected value, they make it simple to identify outliers and
significant data points. Relatives are generally regarded as normal when
they fall between -2 and +2, and anything outside of these bounds can
lead to anomalous points that could have an impact on the model’s
performance.
Homoscedasticity, or the need that residuals show constant variance
across all levels of fitted values, is one of the fundamental
presumptions of regression. The residuals in this scatter plot show no
discernible trend of rising or falling variance with increasing fitted
values; instead, they seem to be pretty uniformly distributed around the
horizontal line at zero. The fact that there is no obvious funnel shape
or systematic variation trend suggests that the assumption of
homoscedasticity is reasonably satisfied. The notion of constant
variance is supported by the residuals’ generally constant spread across
the fitted value range, which indicates that the variance of errors is
still stable.The symmetry of the residuals around the zero line is
another positive aspect of the plot. This symmetry means that the model
does not systematically over- or under-predict the dependent variable
over the range of fitted values (LNMEDHVAL).
However, the plot does show some potential outliers, particularly
those points that are outside the range of the -3 and +3 standardized
residuals. These extreme residuals are located above and below the main
residual clusters and may indicate that the model’s predicted values
deviate significantly from the actual values. Although the number of
outliers is relatively small, their presence indicates that the model
may not fit all data points well.
In addition, although the residuals are generally well clustered
around zero, some slight dispersion occurs as the fitted values
increase, suggesting that the accuracy of the model predictions may
decrease slightly at higher values of LNMEDHVAL. The higher the fitted
value, the greater the residual variance, which may indicate the
presence of slight heteroskedasticity, but not of sufficient severity to
raise significant concerns about the validity of the model. However,
this pattern could be explored further to ensure that the model performs
well over the entire range of predicted values.
ggplot(reg_data, aes(x = Fitted, y = Standardized_Residuals)) +
geom_point(color = "#283d3b", alpha = 0.6) + # Scatter plot points
geom_hline(yintercept = 0, linetype = "dashed", color = "#c44536") + # Add a horizontal line at y = 0
labs(
title = "Scatter Plot of Standardized Residuals vs Fitted Values",
x = "Fitted Values",
y = "Standardized Residuals"
) +
theme_light() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8))

Another assumption we test here is independence of
observations, especially spatial autocorrelations. In the map
of LNMEDHVAL (log-transformed median house values), there appears to be
a spatial pattern, with higher values concentrated in certain areas,
such as Center City and other affluent neighborhoods, and lower values
clustered in more economically distressed areas. This suggests that the
housing market is not spatially random and that nearby block groups tend
to have similar house values.
Similarly, the map of PCTVACANT (proportion of vacant housing units)
shows clear geographic clusters, with higher vacancy rates concentrated
in certain parts of the city, particularly in areas experiencing
economic decline. For PCTSINGLES (proportion of single-family homes),
the maps reveal spatial patterns as well, with block groups
characterised by a high proportion of single-family homes, often located
in residential areas on the outskirts of a suburb or city. The
PCTBACHMOR (proportion of Residents with at least a Bachelor’s Degree)
map shows a strong spatial pattern, with higher levels of educational
attainment concentrated in the more affluent central areas of the city,
while lower levels of educational attainment are concentrated in the
peripheral areas, which have fewer economic resources. Unsurprisingly,
The LNNBELPOV100 (log-transformed number of households living below the
poverty line) map shows that in some parts of the city, particularly in
economically distressed neighborhoods, there is a clear concentration of
households with higher poverty rates. All of these suggests that
observations (block groups) are not independent of each other and it is
important to account for such dependencies in the model through
geographic weighted regression techniques.
philly %>%
left_join(reg_data %>% dplyr::select(c(POLY_ID, Standardized_Residuals)), by = "POLY_ID") %>%
ggplot(.) +
geom_sf(aes(fill = Standardized_Residuals), color = "transparent") + # Use geom_sf to map the polygons
scale_fill_gradientn(colors = c("#FAF9F6", "#c44536"),
name = "Std Residuals",
na.value = "transparent") + # Choose a color palette, invert direction if needed
labs(title = "Choropleth Map of Standardized Residuals") +
theme(legend.text = element_text(size = 9),
legend.title = element_text(size = 10),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
plot.subtitle = element_text(size = 9, face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
panel.background = element_blank(),
panel.border = element_rect(colour = "grey", fill = NA, size = 0.8))

The choropleth map of standardized regression residuals provides a
detailed geographic breakdown of how well the OLS regression model fits
the data across different areas of the city. The map uses a color
gradient to represent the magnitude of the residuals, with darker red
shades indicating large positive residuals (where the model
underestimates the actual values), and lighter shades (toward white)
indicating large negative residuals (where the model overestimates the
actual values).
In the northwestern part of the city, particularly along some of the
more suburban and affluent areas, dark red shading indicates large
positive residuals. This suggests that the model underestimates housing
values in these neighborhoods. These areas are often characterized by
higher-income households and larger single-family homes, suggesting that
the model may not fully capture the higher market value trends in these
regions, possibly due to unaccounted factors like proximity to
high-demand amenities or specific neighborhood features that influence
property values.
In contrast, in parts of South and Southwest Philadelphia, as well as
parts of North Philadelphia, lighter shaded areas indicate large
negative residuals. Here, the model tends to overestimate housing
values, meaning that the predicted values are higher than the actual
observed values. These neighborhoods may be facing economic challenges,
such as higher vacancy rates, lower household incomes, or poverty, which
the model has difficulty fully capturing through the selected
predictors. The residuals in these areas suggest that housing markets in
these neighborhoods are more complex and influenced by localized factors
not fully represented in the regression model, such as higher levels of
economic distress or neighborhood disinvestment.
Some neighborhoods near Center City display more neutral residuals,
where the model’s predictions are relatively accurate, with values
closer to zero. These areas appear in lighter red or pink shades,
indicating that the model is performing reasonably well in these parts
of the city. This may be because the central areas are more homogeneous
in terms of housing values and more likely to align with the trends
captured by the model’s predictors, such as education levels and vacancy
rates.
The overall pattern observed in the map suggests spatial clustering,
as block groups with similar residual values tend to be geographically
close to each other. The model tends to underestimate housing values in
more affluent suburbs and overestimate housing values in economically
distressed communities. This highlights the need for further improvement
to address spatial auto-correlations.
Additional Analyses
We performed stepwise regression to determine the most relevant
predictors for the model. The initial model included all four
predictors, with a residual sum of squares (RSS) of 230.34 and an Akaike
Information Criterion (AIC) of -3448.07, where a lower AIC indicates a
better balance between goodness of fit and model complexity.
During the stepwise procedure, the process examined whether removing
each predictor would reduce the AIC and improve the model. However,
removing any predictor resulted in a higher AIC and an increase in RSS,
indicating a poorer model fit. For instance, removing PCTSINGLES
increased the RSS to 232.75 and the AIC to -3432.2, while removing
LNNBELPOV100 increased the RSS to 242.04 and the AIC to -3364.9.
Removing PCTVACANT had a more substantial impact, increasing the RSS to
281.89 and the AIC to -3102.7. Finally, removing PCTBACHMOR caused the
RSS to jump to 429.36 and the AIC to -2379.0, indicating a severe
decline in model performance.
Given these results, none of the predictors were removed, as
eliminating any of them worsened the fit of the model. Therefore, the
final model remained unchanged from the initial one, including all four
predictors. The final model had a residual deviance of 230.34 and an AIC
of -3448.07, indicating that the model successfully balanced complexity
with fit.
stepwise_model <- stepAIC(fit, direction = "both")
## Start: AIC=-3448.07
## LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100
##
## Df Sum of Sq RSS AIC
## <none> 230.34 -3448.1
## - PCTSINGLES 1 2.407 232.75 -3432.2
## - LNNBELPOV100 1 11.692 242.04 -3364.9
## - PCTVACANT 1 51.546 281.89 -3102.7
## - PCTBACHMOR 1 199.020 429.36 -2379.0
stepwise_model$anova
## Stepwise Model Path
## Analysis of Deviance Table
##
## Initial Model:
## LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100
##
## Final Model:
## LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100
##
##
## Step Df Deviance Resid. Df Resid. Dev AIC
## 1 1715 230.3435 -3448.073
We performed cross-validation to assess the model’s predictive
accuracy and determine whether a reduced model with fewer predictors
could provide similar performance. The original model, which includes
all four predictors, has a lower RMSE (0.3676) compared to the reduced
model with only two predictors (0.4424). This indicates that the
original model provides better predictive accuracy. The increase in RMSE
when removing the additional predictors (PCTSINGLES and LNNBELPOV100)
suggests that excluding these variables results in a less accurate
model. Overall, the original model outperforms the reduced model,
demonstrating that all four predictors contribute to improved model
accuracy.
lm <- trainControl(method = "cv", number = 5)
cvlm_model <- train(LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100, data=reg_data, method = "lm", trControl = lm)
print(cvlm_model)
## Linear Regression
##
## 1720 samples
## 4 predictor
##
## No pre-processing
## Resampling: Cross-Validated (5 fold)
## Summary of sample sizes: 1376, 1376, 1376, 1376, 1376
## Resampling results:
##
## RMSE Rsquared MAE
## 0.3664127 0.658518 0.2726616
##
## Tuning parameter 'intercept' was held constant at a value of TRUE
cvlm_model_reduced = train(LNMEDHVAL ~ PCTVACANT + MEDHHINC, data = reg_data, method = "lm", trControl = lm)
print(cvlm_model_reduced)
## Linear Regression
##
## 1720 samples
## 2 predictor
##
## No pre-processing
## Resampling: Cross-Validated (5 fold)
## Summary of sample sizes: 1376, 1376, 1376, 1376, 1376
## Resampling results:
##
## RMSE Rsquared MAE
## 0.4427044 0.5050842 0.3174302
##
## Tuning parameter 'intercept' was held constant at a value of TRUE
Discussion and Limitations
In summary, in this report, we conducted a multiple regression to
examine the relationship between median house value (the dependent
variable) and four independent variables: vacancy rates (PCTVACANT),
percentage of single-family housing (PCTSINGLES), educational attainment
(PCTBACHMOR), and poverty levels (LNNBELPOV100).
Our findings show that all four predictors were statistically
significant. Specifically, vacancy rates and poverty levels had a
negative impact on median house value, while single-family housing and
educational attainment had a positive influence. The fact that
educational attainment was highly significant and positively related to
house value is not surprising, as areas with higher education levels
tend to attract higher-income households. Similarly, the negative effect
of vacancy rates and poverty levels aligns with expectations, as these
factors typically lower property values.
The overall quality of the model was good, with an \(R^2\) value of 0.6623, indicating that
approximately 66% of the variance in median house value was explained by
the predictors. Additionally, the F-ratio test, with its extremely low
p-value, confirms that the model as a whole is statistically significant
and that at least one predictor has a significant impact on the
outcome.
Through stepwise regression results, all four predictors were
retained in the final model. This indicates that each of these variables
contributes meaningfully to explaining the variation in median house
value, and none were deemed unnecessary based on the stepwise selection
process.When examining the cross-validation results using RMSE (Root
Mean Square Error), the four-predictor model generally showed a better
fit compared to a simpler model with fewer predictors. This suggests
that including all four predictors leads to more accurate predictions
and better overall model performance.
While the four-predictor model shows better predictive accuracy,
there are likely other variables that could enhance the model’s
explanatory power if included. For instance, factors like crime rates,
transportation accessibility, and proximity to amenities (such as parks,
schools, and shopping centers) are commonly associated with housing
values. Spatial autocorrelation, as suggested by the choropleth maps,
indicates that house prices tend to cluster geographically—nearby
properties often have similar values. This spatial dependency suggests
that including neighborhood or location-based variables, or even
applying spatial lag regression, could better capture the clustered
nature of house prices. Housing values also depend on the
characteristics of the house itself, such as age, size, storage options,
and the presence of amenities like parking or green space. Additionally,
local environmental factors, such as proximity to high-crime areas or
noise pollution, can impact property values. Yet, many of these
variables are often correlated with each other (e.g., transportation
access and crime rates), so care must be taken in selecting which
predictors to include to avoid multicollinearity.
In addition to this limitation of not including some potentially
important predictors, we have to acknowledge there are some other
limitations in terms of meeting the regression assumptions. One key
assumption of OLS regression is that linear relationships exist between
the dependent and independent variables. While the scatter plots showed
that PCTBACHMOR had a clear linear relationship with median house value,
the relationships for PCTVACANT, PCTSINGLES, and LNNBELPOV100 were more
complex and not entirely linear. This suggests that the model may not
fully capture the underlying dynamics of these predictors and their
impact on house values.
Another key assumption is the independence of observations, which is
violated due to spatial autocorrelation. This suggests that the model
may not fully account for the spatial dependencies in the data, which
could lead to biased parameter estimates and inaccurate predictions. To
address this limitation, future analyses could explore spatial
regression techniques, such as spatial lag or spatial error models, to
account for spatial autocorrelation and improve model performance.
On top of that, for our current model, we are using the raw number of
households living in poverty (LNNBELPOV100) as a predictor. The raw
count does not account for differences in population size across
neighborhoods, which could lead to misleading results. Larger
neighborhoods with more households may naturally have more households in
poverty, even if the poverty rate is relatively low. A more meaningful
measure would be to use the percentage of households in poverty, which
normalizes the data across neighborhoods, providing a better sense of
poverty’s prevalence relative to the overall population.
Possibility of Ridge or LASSO Regression
Ridge and LASSO regression are regularization techniques used to
address multicollinearity and overfitting in models with many
predictors. Ridge regression penalizes the size of the coefficients,
shrinking them towards zero but keeping all predictors in the model,
which is useful when all predictors are believed to contribute to the
outcome. LASSO (Least Absolute Shrinkage and Selection Operator) goes a
step further by forcing some coefficients to be exactly zero,
effectively performing variable selection.
In this case, since the stepwise regression suggests that all four
predictors significantly contribute to the model, there’s no strong
indication of multicollinearity or overfitting. Therefore, Ridge or
LASSO might not be necessary here unless there is evidence of high
multicollinearity or many more predictors. If the model were more
complex or had a larger number of predictors, LASSO could help in
selecting the most important ones, while Ridge could help shrink
coefficients to prevent overfitting.
LS0tCnRpdGxlOiAiVXNpbmcgT0xTIFJlZ3Jlc3Npb24gdG8gUHJlZGljdCBNZWRpYW4gSG91c2UgVmFsdWVzIGluIFBoaWxhZGVscGhpYSIKYXV0aG9yOiAiRW1pbHkgWmhvdSwgWml5aSBHdW8sIEVtbWEgSmlhbmciCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogc2ltcGxleAogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHllcwpiaWJsaW9ncmFwaHk6IHJlZmVyZW5jZXMuYmliCmNzbDogYXBhLmNzbCAKCmVkaXRvcl9vcHRpb25zOgogIG1hcmtkb3duOgogICAgd3JhcDogc2VudGVuY2UKLS0tCgpWZXJzaW9uIDMuMCBcfCBGaXJzdCBDcmVhdGVkIFNlcCAyNiwgMjAyNCBcfCBVcGRhdGVkIE9jdCAxNCwgMjAyNAoKS2V5d29yZHM6IE9yZGluYXJ5IExlYXN0IFNxdWFyZSBSZWdyZXNzaW9uLCBLLWZvbGQgQ3Jvc3MgVmFsaWRhdGlvbiwgU3VtIG9mIFNxdWFyZSBFcnJvcnMsIFJvb3QgTWVhbiBTcXVhcmVkIEVycm9yLCBTdGVwd2lzZSBBSUMKCkdpdEh1YiBSZXBvc2l0b3J5OiBbQ1BMTjY3MS1PTFMtUmVncmVzc2lvbl0oaHR0cHM6Ly9naXRodWIuY29tL2VtaWx5emhvdTExMi9DUExONjcxLU9MUy1SZWdyZXNzaW9uKQoKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQoKa25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQoKYGBgCgoKYGBge3IgbGlicmFyaWVzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQoKb3B0aW9ucyhzY2lwZW4gPSA5OTkpCgojIGFsbCB0aGUgbGlicmFyeSBsb2FkZWQKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoaGVyZSkKbGlicmFyeShrYWJsZUV4dHJhKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2djb3JycGxvdCkKbGlicmFyeShzZikKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoTUFTUykKbGlicmFyeShjYXJldCkKCmBgYAoKCmBgYHtyIHJlYWQgZGF0YSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KCiMgcmVhZCBpbiBkYXRhCmRhdGEgPC0gcmVhZF9jc3YoaGVyZSgiZGF0YSIsICJSZWdyZXNzaW9uRGF0YS5jc3YiKSkKCmBgYAoKCiMgSW50cm9kdWN0aW9uCgpIb3VzaW5nIHZhbHVlcyBpbiBQaGlsYWRlbHBoaWEgaGF2ZSBzZWVuIGEgY29uc2lzdGVudCBpbmNyZWFzZSBpbiByZWNlbnQgeWVhcnMsIG1ha2luZyBpdCBhbiBpbXBvcnRhbnQgYXJlYSBvZiBjb25jZXJuIGFuZCByZXNlYXJjaCBmb3IgdXJiYW4gcGxhbm5lcnMgYW5kIHBvbGljeW1ha2Vycy4gVGhpcyB1cHdhcmQgdHJlbmQgaGFzIHJhaXNlZCBpc3N1ZXMgYXJvdW5kIGhvdXNpbmcgYWZmb3JkYWJpbGl0eSwgcGFydGljdWxhcmx5IGZvciBsb3cgYW5kIG1pZGRsZS1pbmNvbWUgaG91c2Vob2xkcy4gTWFueSBuZWlnaGJvcmhvb2RzIGhhdmUgZXhwZXJpZW5jZWQgZ2VudHJpZmljYXRpb24sIGxlYWRpbmcgdG8gdGhlIGRpc3BsYWNlbWVudCBvZiBsb25nLXRlcm0gcmVzaWRlbnRzIGFuZCBjaGFuZ2luZyB0aGUgc29jaW8tZWNvbm9taWMgbGFuZHNjYXBlIG9mIHRoZSBjaXR5LiBFeGFtaW5pbmcgaG91c2luZyB2YWx1ZXMgaXMgY3JpdGljYWwgZm9yIHVuZGVyc3RhbmRpbmcgdGhlc2Ugc2hpZnRzIGFuZCBhZGRyZXNzaW5nIGNvbmNlcm5zIHJlbGF0ZWQgdG8gYWZmb3JkYWJpbGl0eSwgbmVpZ2hib3Job29kIHN0YWJpbGl0eSwgYW5kIGVxdWl0YWJsZSBkZXZlbG9wbWVudCBhY3Jvc3MgUGhpbGFkZWxwaGlhLgoKVG8gYmV0dGVyIHVuZGVyc3RhbmQgdGhlIHBvdGVudGlhbCBmYWN0b3JzIGluZmx1ZW5jaW5nIGhvdXNpbmcgdmFsdWVzIGluIFBoaWxhZGVscGhpYSwgd2UgaWRlbnRpZmllZCBzZXZlcmFsIGtleSB2YXJpYWJsZXMsIGluY2x1ZGluZyBlZHVjYXRpb25hbCBhdHRhaW5tZW50LCB2YWNhbmN5IHJhdGVzLCB0aGUgcHJvcG9ydGlvbiBvZiBkZXRhY2hlZCBzaW5nbGUtZmFtaWx5IGhvbWVzLCBhbmQgcG92ZXJ0eSBsZXZlbHMuIFRoZXNlIGZhY3RvcnMgYXJlIGNsb3NlbHkgbGlua2VkIHRvIGhvdXNpbmcgbWFya2V0IHRyZW5kcyBhbmQgcHJvdmlkZSBpbnNpZ2h0cyBpbnRvIHRoZSBzb2Npby1lY29ub21pYyBjb25kaXRpb25zIHRoYXQgbWF5IGFmZmVjdCBwcm9wZXJ0eSB2YWx1ZXMgYWNyb3NzIHRoZSBjaXR5LgoKRWR1Y2F0aW9uYWwgYXR0YWlubWVudCBpcyBjbG9zZWx5IHRpZWQgdG8gZWNvbm9taWMgb3V0Y29tZXMgYW5kIHRoaXMgaW5jbHVkZXMgcHJvcGVydHkgdmFsdWVzLiBTdHVkaWVzIHN1Z2dlc3QgdGhhdCBhcmVhcyB3aXRoIGhpZ2hlciBsZXZlbHMgb2YgZWR1Y2F0aW9uIHRlbmQgdG8gaGF2ZSBtb3JlIHJvYnVzdCBsb2NhbCBlY29ub21pZXMsIGhpZ2hlciBpbmNvbWVzLCBhbmQgaW5jcmVhc2VkIGRlbWFuZCBmb3IgaG91c2luZywgd2hpY2ggcHVzaGVzIHVwIGhvbWUgdmFsdWVzIEBTY290dDIwMTIuIEhpZ2ggdmFjYW5jeSByYXRlcyBhcmUgdHlwaWNhbGx5IGFzc29jaWF0ZWQgd2l0aCBkZWNsaW5pbmcgbmVpZ2hib3Job29kcyBhbmQgbG93ZXIgbWVkaWFuIGhvdXNlIHZhbHVlcy4gVmFjYW50IHByb3BlcnRpZXMgY2FuIGJlIHNpZ25zIG9mIGVjb25vbWljIGRpc3RyZXNzLCBjb250cmlidXRpbmcgdG8gbmVpZ2hib3Job29kIGRlY2xpbmUgdGhyb3VnaCByZWR1Y2VkIHVwa2VlcCwgaGlnaGVyIGNyaW1lIHJhdGVzLCBhbmQgYSBuZWdhdGl2ZSBwZXJjZXB0aW9uIG9mIHRoZSBhcmVhIEBtYWxsYWNoMjAxOGVtcHR5LiBJbiBQaGlsYWRlbHBoaWEsIHRoZSBpc3N1ZSBvZiB2YWNhbmN5IGhhcyBiZWVuIHBhcnRpY3VsYXJseSBwcm9ibGVtYXRpYyBpbiBjZXJ0YWluIG5laWdoYm9yaG9vZHMsIHdoZXJlIGEgbGFyZ2UgbnVtYmVyIG9mIGFiYW5kb25lZCBwcm9wZXJ0aWVzIGhhcyBsZWQgdG8gc2lnbmlmaWNhbnQgcmVkdWN0aW9ucyBpbiBob3VzaW5nIHZhbHVlcyBAa3JvbWVyMjAwMnZhY2FudC4KClRoZSBwcm9wb3J0aW9uIG9mIHNpbmdsZS1mYW1pbHkgaG9tZXMgaW4gYW4gYXJlYSBjYW4gYWxzbyBpbmZsdWVuY2UgaG91c2luZyB2YWx1ZXMsIGRlcGVuZGluZyBvbiB0aGUgbG9jYWwgbWFya2V0LiBTaW5nbGUtZmFtaWx5IGhvbWVzIGFyZSBnZW5lcmFsbHkgbW9yZSBkZXNpcmFibGUgaW4gbWFueSBVLlMuIGhvdXNpbmcgbWFya2V0cywgYXMgdGhleSBvZmZlciBtb3JlIHNwYWNlLCBwcml2YWN5LCBhbmQgcGVyY2VpdmVkIHN0YWJpbGl0eSBjb21wYXJlZCB0byBtdWx0aS1mYW1pbHkgdW5pdHMgQGdsYWVzZXIyMDE4ZWNvbm9taWMuIFJlc2VhcmNoIGFsc28gY29uc2lzdGVudGx5IGRlbW9uc3RyYXRlcyBhIHN0cm9uZyBjb3JyZWxhdGlvbiBiZXR3ZWVuIHBvdmVydHkgbGV2ZWxzIGFuZCBob3VzaW5nIHZhbHVlcy4gQXJlYXMgd2l0aCBoaWdoZXIgcG92ZXJ0eSByYXRlcyBvZnRlbiBleHBlcmllbmNlIHJlZHVjZWQgZGVtYW5kIGZvciBob3VzaW5nLCBhcyB3ZWxsIGFzIGRpbWluaXNoZWQgaW52ZXN0bWVudCBpbiBsb2NhbCBpbmZyYXN0cnVjdHVyZSBhbmQgc2VydmljZXMsIHdoaWNoIGluIHR1cm4gY2FuIGxlYWQgdG8gbG93ZXIgcHJvcGVydHkgdmFsdWVzIEBHYWxzdGVyMjAwOC4gCgpJbiB0aGlzIHN0dWR5LCB3ZSBhaW0gdG8gZXhwbG9yZSB0aGUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIHRoZXNlIHNvY2lvLWVjb25vbWljIGZhY3RvcnMgYW5kIG1lZGlhbiBob3VzZSB2YWx1ZXMgaW4gUGhpbGFkZWxwaGlhIHVzaW5nIE9yZGluYXJ5IExlYXN0IFNxdWFyZXMgKE9MUykgcmVncmVzc2lvbi4gQnkgYW5hbHl6aW5nIHRoZXNlIHJlbGF0aW9uc2hpcHMsIHdlIGhvcGUgdG8gaWRlbnRpZnkgdGhlIGtleSBwcmVkaWN0b3JzIG9mIGhvdXNpbmcgdmFsdWVzIGluIHRoZSBjaXR5IGFuZCBwcm92aWRlIGluc2lnaHRzIHRoYXQgY2FuIGluZm9ybSBwb2xpY3kgZGVjaXNpb25zLCB1cmJhbiBwbGFubmluZyBzdHJhdGVnaWVzLCBhbmQgY29tbXVuaXR5IGRldmVsb3BtZW50IGluaXRpYXRpdmVzLiAKCiMgTWV0aG9kcwoKIyMgRGF0YSBDbGVhbmluZwoKVGhlIG9yaWdpbmFsIGRhdGFzZXQgdXNlZCBpbiB0aGlzIHN0dWR5IGNvbnNpc3RlZCBvZiAxODE2IGNlbnN1cyBibG9jayBncm91cHMgaW4gUGhpbGFkZWxwaGlhIGFjY29yZGluZyB0byB0aGUgMjAwMCBDZW5zdXMsIGJ1dCB0byBlbnN1cmUgdGhlIGRhdGFzZXQgd2FzIHN1aXRhYmxlIGZvciByZWdyZXNzaW9uIGFuYWx5c2lzLCBzZXZlcmFsIGRhdGEgY2xlYW5pbmcgcHJvY2VkdXJlcyB3ZXJlIHBlcmZvcm1lZC4gRmlyc3QsIGV2ZXJ5IGJsb2NrIGdyb3VwIGluIHRoZSBkYXRhc2V0IHdpdGggYSBwb3B1bGF0aW9uIG9mIGxlc3MgdGhhbiA0MCB3YXMgcmVtb3ZlZC4gVGhlc2UgYmxvY2sgZ3JvdXBzIHJlcHJlc2VudCBzcGFyc2VseSBwb3B1bGF0ZWQgb3IgdW51c3VhbGx5IGhvdXNlZCBhcmVhcyB0aGF0IG1heSBpbnRyb2R1Y2Ugbm9pc2UgaW50byB0aGUgYW5hbHlzaXMuIFNlY29uZGx5LCBibG9jayBncm91cHMgd2l0aG91dCBhbnkgaG91c2luZyB1bml0cyB3ZXJlIGFsc28gZXhjbHVkZWQgZHVlIHRvIHRoZWlyIGxhY2sgb2Ygc2lnbmlmaWNhbmNlIGluIGEgc3R1ZHkgY2VudGVyZWQgb24gaG91c2luZyBhdHRyaWJ1dGVzLiBUaGlyZGx5LCBibG9jayBncm91cHMgd2l0aCBhIG1lZGlhbiBob3VzaW5nIHZhbHVlIG9mIGxlc3MgdGhhbiBcJDEwLDAwMCB3ZXJlIG5vdCBpbmNsdWRlZC4gVGhlc2UgYmxvY2sgZ3JvdXBzIGRvIG5vdCBhY2N1cmF0ZWx5IHJlZmxlY3QgdGhlIHJlYWxpdHkgb2YgdGhlIHR5cGljYWwgaG91c2luZyBtYXJrZXQsIGFuZCB0aGUgdW51c3VhbGx5IGxvdyBob21lIHZhbHVlcyBpbiB0aGVzZSBibG9jayBncm91cHMgbWF5IGJpYXMgdGhlIHJlc3VsdHMgb2YgdGhlIHN0dWR5LiBGaW5hbGx5LCBhIHVuaXF1ZSBjb21iaW5hdGlvbiBvZiB2YWx1ZXMgLSBtZWRpYW4gcHJvcGVydHkgdmFsdWVzIG92ZXIgXCQ4MDAsMDAwIGFuZCB0eXBpY2FsIGhvdXNlaG9sZCBpbmNvbWVzIGxlc3MgdGhhbiBcJDgsMDAwIC0gbGVkIHRvIHRoZSBleGNsdXNpb24gb2Ygb25lIGJsb2NrIGdyb3VwIGluIE5vcnRoIFBoaWxhZGVscGhpYS4gQXMgYSBjbGVhciBvdXRsaWVyLCBpdCB3YXMgZXhjbHVkZWQgdG8gYXZvaWQgYmlhc2luZyB0aGUgcmVzdWx0cy4gVGhlIGZpbmFsIGRhdGFzZXQgaW5jbHVkZXMgMSw3MjAgb2JzZXJ2YXRpb25zLCBlYWNoIGNvcnJlc3BvbmRpbmcgdG8gYSBkaWZmZXJlbnQgUGhpbGFkZWxwaGlhIGJsb2NrIGdyb3VwLCBhbmQgaGFzIHRoZSBmb2xsb3dpbmcgYXR0cmlidXRlczoKCi0gKipQT0xZX0lEKio6IENlbnN1cyBibG9jayBncm91cCBJRAotICoqTUVESFZBTCoqOiBNZWRpYW4gdmFsdWUgb2YgYWxsIG93bmVyIG9jY3VwaWVkIGhvdXNpbmcgdW5pdHMKLSAqKlBDVEJBQ0hNT1IqKjogUHJvcG9ydGlvbiBvZiByZXNpZGVudHMgaW4gQmxvY2sgR3JvdXAgd2l0aCBhdCBsZWFzdCBhIEJhY2hlbG9y4oCZcyBkZWdyZWUKLSAqKlBDVFZBQ0FOVCoqOiBQcm9wb3J0aW9uIG9mIGhvdXNpbmcgdW5pdHMgdGhhdCBhcmUgdmFjYW50Ci0gKipQQ1RTSU5HTEVTKio6IFBlcmNlbnQgb2YgaG91c2luZyB1bml0cyB0aGF0IGFyZSBkZXRhY2hlZCBzaW5nbGUgZmFtaWx5IGhvdXNlcyAKLSAqKk5CRUxQT1YxMDAqKjogTnVtYmVyIG9mIGhvdXNlaG9sZHMgd2l0aCBpbmNvbWVzIGJlbG93IDEwMCUgcG92ZXJ0eSBsZXZlbCAoaS5lLiwgbnVtYmVyIG9mIGhvdXNlaG9sZHMgbGl2aW5nIGluIHBvdmVydHkpCi0gKipNRURISElOQyoqOiBNZWRpYW4gaG91c2Vob2xkIGluY29tZQoKCiMjIEV4cGxvcmF0b3J5IERhdGEgQW5hbHlzaXMKCldlIGJlZ2luIGJ5IGV4YW1pbmluZyB0aGUgc3VtbWFyeSBzdGF0aXN0aWNzIGFuZCBkaXN0cmlidXRpb25zIG9mIHRoZSBkZXBlbmRlbnQgYW5kIGluZGVwZW5kZW50IHZhcmlhYmxlcy4gVGhpcyB3aWxsIHByb3ZpZGUgYSBiZXR0ZXIgdW5kZXJzdGFuZGluZyBvZiB0aGUgZGF0YSBhbmQgaGVscCBpZGVudGlmeSBhbnkgcG90ZW50aWFsIG91dGxpZXJzIG9yIHVudXN1YWwgcGF0dGVybnMgdGhhdCBtYXkgbmVlZCB0byBiZSBhZGRyZXNzZWQgYmVmb3JlIHByb2NlZWRpbmcgd2l0aCByZWdyZXNzaW9uIGFuYWx5c2lzLiBJbiBvdXIgY2FzZSwgdGhlIG1lZGlhbiBob21lIHZhbHVlIChNRURIVkFMKSBpcyB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLiBUaGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzIGFyZSB0aGUgcHJvcG9ydGlvbiBvZiB0aGUgcG9wdWxhdGlvbiB3aXRoIGEgYmFjaGVsb3IncyBkZWdyZWUgb3IgaGlnaGVyIChQQ0JBQ0hNT1JFKSwgdGhlIG51bWJlciBvZiBob3VzZWhvbGRzIGluIHBvdmVydHkgKE5CRUxQT1YxMDApLCB0aGUgcHJvcG9ydGlvbiBvZiB2YWNhbnQgaG9tZXMgKFBDVFZBQ0FOVCksIGFuZCB0aGUgcHJvcG9ydGlvbiBvZiBzaW5nbGUgZmFtaWx5IGhvbWVzIChQQ1RTSU5HTEVTKS4gV2UgY29tcHV0ZWQgdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBmb3IgZWFjaCB2YXJpYWJsZSB0byB1bmRlcnN0YW5kIHRoZSBjZW50cmFsIHRlbmRlbmN5IGFuZCB2YXJpYWJpbGl0eSBvZiB0aGUgZGF0YS4gSWYgcmVzdWx0cyBzaG93IHRoYXQgdGhlIHZhcmlhYmxlIGlzIG5vbi1ub3JtYWxseSBkaXN0cmlidXRlZCwgd2UgYXBwbHkgYSBsb2cgdHJhbnNmb3JtYXRpb24gdG8gbm9ybWFsaXplIHRoZSBkYXRhLgoKVGhpcyBpcyBmb2xsb3dlZCBieSBpbnZlc3RpZ2F0aW5nIHRoZSBjb3JyZWxhdGlvbnMgYmV0d2VlbiB0aGUgcHJlZGljdG9yIHZhcmlhYmxlcyB0byBhdm9pZCBtdWx0aWNvbGxpbmVhcml0eS4gQ29ycmVsYXRpb24gaXMgYSBzdGF0aXN0aWNhbCBtZWFzdXJlIHRoYXQgZGVzY3JpYmVzIHRoZSBzdHJlbmd0aCBhbmQgZGlyZWN0aW9uIG9mIGEgcmVsYXRpb25zaGlwIGJldHdlZW4gdmFyaWFibGVzLiBUaGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgXChyXCkgcXVhbnRpZmllcyB0aGUgZGVncmVlIHRvIHdoaWNoIHR3byB2YXJpYWJsZXMgYXJlIGxpbmVhcmx5IHJlbGF0ZWQuIFRoZSBmb3JtdWxhIGZvciB0aGUgc2FtcGxlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IFwoclwpIGlzIGFzIGZvbGxvd3M6IAoKJCQKciA9IFxmcmFje1xzdW1fe2k9MX1ee259ICh4X2kgLSBcYmFye3h9KSh5X2kgLSBcYmFye3l9KX17XHNxcnR7XHN1bV97aT0xfV57bn0gKHhfaSAtIFxiYXJ7eH0pXjIgXHN1bV97aT0xfV57bn0gKHlfaSAtIFxiYXJ7eX0pXjJ9fQokJApJbiBhIG1vcmUgY29uY2lzZSB3YXksIHRoaXMgYWJvdmUgZm9ybXVsYSBpcyBhbHNvIGVxdWl2YWxlbnQgdG8gdGhlIGZvbGxvd2luZzogCgokJApyID0gXGZyYWN7MX17bi0xfSBcc3VtX3tpPTF9XntufSBcbGVmdCggXGZyYWN7eF9pIC0gXGJhcnt4fX17U194fSBccmlnaHQpIFxsZWZ0KCBcZnJhY3t5X2kgLSBcYmFye3l9fXtTX3l9IFxyaWdodCkKJCQKd2hlcmUgXCh4X2lcKSBhbmQgXCh5X2lcKSBhcmUgaW5kaXZpZHVhbCBkYXRhIHBvaW50cywgXChcYmFye3h9XCkgYW5kIFwoXGJhcnt5fVwpIGFyZSB0aGUgbWVhbnMgb2YgdGhlIHZhcmlhYmxlcyBcKHhcKSBhbmQgXCh5XCksIFwoU194XCkgYW5kIFwoU195XCkgYXJlIHRoZSBzdGFuZGFyZCBkZXZpYXRpb25zIG9mIHRoZSB2YXJpYWJsZXMgXCh4XCkgYW5kIFwoeVwpIHJlc3BlY3RpdmVseS4gCgpGb3IgZWFjaCBvYnNlcnZhdGlvbiBcKGlcKSwgdGhlIGZvcm11bGEgY2FsY3VsYXRlcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBkYXRhIHBvaW50IFwoeF9pXCksIFwoeV9pXCkgYW5kIHRoZSBtZWFuIG9mIHRoZSB2YXJpYWJsZXMgYW5kIHRoZW4gZGl2aWRlcyB0aGVtIGJ5IHRoZWlyIHN0YW5kYXJkIGRldmlhdGlvbi4gVGhlbiwgdGhlc2Ugc3RhbmRhcmRpemVkIHZhbHVlcyBhcmUgbXVsdGlwbGllZCB0b2dldGhlciB0byBhc3Nlc3MgdGhlIGV4dGVudCB0byB3aGljaCB0aGUgdHdvIHZhcmlhYmxlcyBkZXZpYXRlIGZyb20gdGhlaXIgcmVzcGVjdGl2ZSBtZWFucyBpbiB0aGUgc2FtZSBkaXJlY3Rpb24uIFRoZSByZXN1bHQgb2YgdGhpcyBtdWx0aXBsaWNhdGlvbiBpcyBzdW1tZWQgYWNyb3NzIGFsbCBvYnNlcnZhdGlvbnMsIHdoaWNoIGFnZ3JlZ2F0ZXMgdGhlIGluZGl2aWR1YWwgY29udHJpYnV0aW9ucyB0byB0aGUgY29ycmVsYXRpb24uIEZpbmFsbHksIGRpdmlkaW5nIHRoaXMgc3VtIGJ5IFwobi0xXCkgd2hlcmUgXChuXCkgaXMgdGhlIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgeWllbGRzIHRoZSBzYW1wbGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgXChyXCkuCgpUaGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgKipcKHJcKSoqIGNhbiByYW5nZSBmcm9tIC0xIHRvICsxLiBBIHZhbHVlIG9mICsxIGluZGljYXRlcyBhIHBlcmZlY3QgcG9zaXRpdmUgbGluZWFyIHJlbGF0aW9uc2hpcCwgd2hlcmUgaW5jcmVhc2VzIGluIG9uZSB2YXJpYWJsZSBjb3JyZXNwb25kIHdpdGggaW5jcmVhc2VzIGluIHRoZSBvdGhlciwgd2hpbGUgYSB2YWx1ZSBvZiAtMSBpbmRpY2F0ZXMgYSBwZXJmZWN0IG5lZ2F0aXZlIGxpbmVhciByZWxhdGlvbnNoaXAuIEEgdmFsdWUgb2YgMCBzdWdnZXN0cyBubyBsaW5lYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHZhcmlhYmxlcywgbWVhbmluZyBjaGFuZ2VzIGluIG9uZSBkbyBub3QgcHJlZGljdCBjaGFuZ2VzIGluIHRoZSBvdGhlci4gVW5kZXJzdGFuZGluZyB0aGUgY29ycmVsYXRpb25zIGJldHdlZW4gdGhlIHByZWRpY3RvcnMgaXMgY3JpdGljYWwgdG8gaWRlbnRpZnkgd2hldGhlciBhbnkgdmFyaWFibGVzIGFyZSBoaWdobHkgY29ycmVsYXRlZCwgd2hpY2ggd291bGQgc3VnZ2VzdCBtdWx0aWNvbGxpbmVhcml0eS4gTXVsdGljb2xsaW5lYXJpdHkgY2FuIGRpc3RvcnQgdGhlIHJlZ3Jlc3Npb24gcmVzdWx0cyBieSBpbmZsYXRpbmcgdGhlIHN0YW5kYXJkIGVycm9ycyBvZiB0aGUgY29lZmZpY2llbnRzLCB3aGljaCBsZWFkIHRvIGxlc3MgcmVsaWFibGUgaW50ZXJwcmV0YXRpb25zLiAKCiMjIE11bHRpcGxlIFJlZ3Jlc3Npb24gQW5hbHlzaXMKCkFmdGVyIGV4cGxvcmluZyB0aGUgZGF0YSwgd2UgY29uZHVjdCBhIG11bHRpcGxlIHJlZ3Jlc3Npb24gYW5hbHlzaXMgdG8gZXhhbWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIGRlcGVuZGVudCB2YXJpYWJsZSAobWVkaWFuIGhvdXNlIHZhbHVlKSBhbmQgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlcyAoZWR1Y2F0aW9uYWwgYXR0YWlubWVudCwgcG92ZXJ0eSBsZXZlbHMsIHZhY2FuY3kgcmF0ZXMsIGFuZCBzaW5nbGUtZmFtaWx5IGhvdXNpbmcpLiBSZWdyZXNzaW9uIGFuYWx5c2lzIGlzIGEgc3RhdGlzdGljYWwgbWV0aG9kIHVzZWQgdG8gZXhhbWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gYSBkZXBlbmRlbnQgdmFyaWFibGUgYW5kIG9uZSBvciBtb3JlIGluZGVwZW5kZW50IHZhcmlhYmxlcy4gSXQgYWxsb3dzIHJlc2VhcmNoZXJzIHRvIHVuZGVyc3RhbmQgaG93IHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgY2hhbmdlcyBhcyB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzIHZhcnkgYW5kIG1ha2UgaW5mZXJlbmNlcyBhYm91dCB0aGUgcmVsYXRpb25zaGlwcyBhbW9uZyB0aGUgdmFyaWFibGVzLiBUaGUgbW9kZWwgZXN0aW1hdGVzIGNvZWZmaWNpZW50cyBmb3IgZWFjaCBpbmRlcGVuZGVudCB2YXJpYWJsZSwgd2hpY2ggcXVhbnRpZnkgdGhlIGV4cGVjdGVkIGNoYW5nZSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGZvciBhIG9uZS11bml0IGluY3JlYXNlIGluIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZSwgaG9sZGluZyBhbGwgb3RoZXIgdmFyaWFibGVzIGNvbnN0YW50LiBGb3Igb3VyIHByb2JsZW0sIHRoZSBlcXVhdGlvbiBmb3IgdGhlIG11bHRpcGxlIHJlZ3Jlc3Npb24gbW9kZWwgaXMgYXMgZm9sbG93czoKCgokJApcdGV4dHtMTk1FREhWQUx9ID0gXGJldGFfMCArIFxiZXRhXzEgXHRleHR7UENUVkFDQU5UfSArIFxiZXRhXzIgXHRleHR7UENUU0lOR0xFU30gKyBcYmV0YV8zIFx0ZXh0e1BDVEJBQ0hNT1J9ICsgXGJldGFfNCBcdGV4dHtMTihMTk5CRUxQT1YxMDApfSArIFxlcHNpbG9uCiQkCgp3aGVyZSBcKFx0ZXh0e0xOTUVESFZBTH1cKSBpcyB0aGUgbG9nLXRyYW5zZm9ybWVkIG1lZGlhbiBob3VzZSB2YWx1ZSwgXChcdGV4dHtQQ1RWQUNBTlR9XCkgaXMgdGhlIHByb3BvcnRpb24gb2YgdmFjYW50IGhvdXNpbmcgdW5pdHMsIFwoXHRleHR7UENUU0lOR0xFU31cKSBpcyB0aGUgcHJvcG9ydGlvbiBvZiBzaW5nbGUtZmFtaWx5IGRldGFjaGVkIGhvbWVzLCBcKFx0ZXh0e1BDVEJBQ0hNT1J9XCkgaXMgdGhlIHBlcmNlbnRhZ2Ugb2YgcmVzaWRlbnRzIHdpdGggYSBiYWNoZWxvcidzIGRlZ3JlZSBvciBoaWdoZXIsIFwoXHRleHR7TE4oTE5OQkVMUE9WMTAwKX1cKSBpcyB0aGUgbG9nLXRyYW5zZm9ybWVkIG51bWJlciBvZiBob3VzZWhvbGRzIGxpdmluZyBiZWxvdyB0aGUgcG92ZXJ0eSBsaW5lLiAKCgpcKFxiZXRhXzBcKSBpcyB0aGUgaW50ZXJjZXB0LCBcKFxiZXRhXzEsIFxiZXRhXzIsIFxiZXRhXzMsIFxiZXRhXzRcKSBhcmUgdGhlIGNvZWZmaWNpZW50cyBmb3IgZWFjaCBpbmRlcGVuZGVudCB2YXJpYWJsZSwgYW5kIFwoXGVwc2lsb25cKSBpcyB0aGUgcmVzaWR1YWwgZXJyb3IgdGVybS4gVGhlIGNvZWZmaWNpZW50cyBcKFxiZXRhXzEsIFxiZXRhXzIsIFxiZXRhXzMsIFxiZXRhXzRcKSByZXByZXNlbnQgdGhlIGV4cGVjdGVkIGNoYW5nZSBpbiBcKFx0ZXh0e0xOTUVESFZBTH1cKSBmb3IgYSBvbmUtdW5pdCBpbmNyZWFzZSBpbiB0aGUgY29ycmVzcG9uZGluZyBpbmRlcGVuZGVudCB2YXJpYWJsZSwgaG9sZGluZyBhbGwgb3RoZXIgdmFyaWFibGVzIGNvbnN0YW50LiBUaGUgZXJyb3IgdGVybSBcKFxlcHNpbG9uXCkgYWNjb3VudHMgZm9yIHRoZSB2YXJpYWJpbGl0eSBpbiBcKFx0ZXh0e0xOTUVESFZBTH1cKSB0aGF0IGlzIG5vdCBleHBsYWluZWQgYnkgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlcy4KCiMjIyBSZWdyZXNzaW9uIEFzc3VtcHRpb25zCgpUaGVyZSBhcmUgc2V2ZXJhbCBhc3N1bXB0aW9ucyBhc3NvY2lhdGVkIHdpdGggcmVncmVzc2lvbiBhbmFseXNpcyB0aGF0IG5lZWRzIHRvIGJlIGNoZWNrZWQgYmVmb3JlIHdlIGZ1cnRoZXIgcHJvY2VlZC4gRmlyc3QsICoqbGluZWFyaXR5KiogYXNzZXJ0cyB0aGF0IHRoZXJlIHNob3VsZCBiZSBhIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlcyBhbmQgaW5kZXBlbmRlbnQgdmFyaWFibGUuIFRvIHZlcmlmeSB0aGlzIGFzc3VtcHRpb24sIHdlIG1hZGUgc2NhdHRlcnBsb3RzIHRvIHZpc3VhbGl6ZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuICoqXCh5XCkqKiBhbmQgZWFjaCBvZiB0aGUgcHJlZGljdG9yLiAKClNlY29uZCB0aGUgYXNzdW1wdGlvbiBvZiAqKmluZGVwZW5kZW5jZSBvZiBvYnNlcnZhdGlvbnMqKiByZXF1aXJlcyB0aGF0IHRoZSBvYnNlcnZhdGlvbnMgd2l0aGluIHRoZSBkYXRhc2V0IGJlIGluZGVwZW5kZW50IG9mIG9uZSBhbm90aGVyLCB3aXRob3V0IGFueSBzcGF0aWFsLCB0ZW1wb3JhbCwgb3Igb3RoZXIgZGVwZW5kZW5jaWVzLiBJbiBzcGF0aWFsIGNvbnRleHRzLCB3ZSBtYWRlIGNob3JvcGxldGggbWFwcyB0byBhc3Nlc3MgdGhlIHByZXNlbmNlIG9mIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIGluIHRoZSByZXNpZHVhbHMgb3IgZGVwZW5kZW50IHZhcmlhYmxlLiAKClRoaXJkLCB0aGUgKipub3JtYWxpdHkgb2YgcmVzaWR1YWxzKiogYXNzdW1wdGlvbiBzdGF0ZXMgdGhhdCB0aGUgcmVzaWR1YWxzIHNob3VsZCBmb2xsb3cgYSBub3JtYWwgZGlzdHJpYnV0aW9uLiBXaGlsZSB0aGlzIGFzc3VtcHRpb24gaXMgbGVzcyBjcml0aWNhbCBpbiBsYXJnZSBzYW1wbGVzIGR1ZSB0byB0aGUgQ2VudHJhbCBMaW1pdCBUaGVvcmVtLCBpdCByZW1haW5zIGRlc2lyYWJsZSBmb3IgaW5mZXJlbmNlIHB1cnBvc2VzLiBUbyBldmFsdWF0ZSB0aGlzIGFzc3VtcHRpb24sIHdlIG1hZGUgYSBoaXN0b2dyYW0gb2YgdGhlIHJlc2lkdWFscyAtIGEgYmVsbC1zaGFwZWQgY3VydmUgd291bGQgc3VnZ2VzdCB0aGF0IHRoZSByZXNpZHVhbHMgYXJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLgoKQW5vdGhlciBpbXBvcnRhbnQgYXNzdW1wdGlvbiBpcyAqKmhvbW9zY2VkYXN0aWNpdHkqKiwgd2hpY2ggc3RhdGVzIHRoYXQgdGhlIHZhcmlhbmNlIG9mIHRoZSByZXNpZHVhbHMgc2hvdWxkIHJlbWFpbiBjb25zdGFudCBhY3Jvc3MgYWxsIGxldmVscyBvZiB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzLiBXZSBhc3Nlc3NlZCBob21vc2NlZGFzdGljaXR5IGJ5IGV4YW1pbmluZyBzY2F0dGVycGxvdCBvZiBzdGFuZGFyZGl6ZWQgcmVzaWR1YWxzIGFnYWluc3QgcHJlZGljdGVkIHZhbHVlcy4gIElkZWFsbHksIHRoZXNlIHJlc2lkdWFscyBzaG91bGQgYmUgZXZlbmx5IGRpc3RyaWJ1dGVkIGFyb3VuZCB6ZXJvOyBhbnkgcGF0dGVybnMgbWF5IGluZGljYXRlIHRoZSBwcmVzZW5jZSBvZiBoZXRlcm9zY2VkYXN0aWNpdHkuCgpUaGUgYXNzdW1wdGlvbiBvZiAqKm5vIG11bHRpY29sbGluZWFyaXR5KiogYXNzZXJ0cyB0aGF0IHRoZSBwcmVkaWN0b3IgdmFyaWFibGVzIHNob3VsZCBub3QgYmUgaGlnaGx5IGNvcnJlbGF0ZWQgd2l0aCBlYWNoIG90aGVyLCBhcyB0aGlzIGNhbiBpbmZsYXRlIHRoZSB2YXJpYW5jZSBvZiB0aGUgY29lZmZpY2llbnQgZXN0aW1hdGVzIGFuZCBtYWtlIHRoZW0gdW5zdGFibGUuIFRvIGNoZWNrIGZvciBtdWx0aWNvbGxpbmVhcml0eSwgd2UgY3JlYXRlZCBhIGNvcnJlbGF0aW9uIG1hdHJpeGZvciB0aGUgcHJlZGljdG9ycyB0byBsb29rIGZvciBhbnkgY29ycmVsYXRpb25zIGdyZWF0ZXIgdGhhbiAwLjggKG9yIGxlc3MgdGhhbiAtMC44KS4gCgpGaW5hbGx5LCBpdCBpcyBpbXBvcnRhbnQgdG8gY29uc2lkZXIgdGhlICoqcmF0aW8gb2Ygb2JzZXJ2YXRpb25zIHRvIHByZWRpY3RvcnMqKiBpbiB0aGUgbW9kZWwuIEEgZ2VuZXJhbCBndWlkZWxpbmUgc3VnZ2VzdHMgaGF2aW5nIGF0IGxlYXN0IDEwIHRvIDE1IG9ic2VydmF0aW9ucyBmb3IgZWFjaCBwcmVkaWN0b3IgdG8gZW5zdXJlIHJvYnVzdCBlc3RpbWF0ZXMuIFNpbmNlIHdlIGhhdmUgb3ZlciAxNzAwIG9ic2VydmF0aW9ucyBpbiBvdXIgZGF0YXNldCwgdGhpcyBhc3N1bXB0aW9uIGlzIG1ldC4gCgojIyMgUGFyYW1ldGVyIEVzdGltYXRpb25zCgpBZnRlciB2ZXJpZnlpbmcgdGhlc2UgYXNzdW1wdGlvbnMsIHdlIHByb2NlZWQgd2l0aCB0aGUgcmVncmVzc2lvbiBhbmFseXNpcy4gVGhlcmUgYXJlIHNldmVyYWwgcGFyYW1ldGVycyB0aGF0IHdlIG5lZWQgdG8gZXN0aW1hdGUgaGVyZTogXCggXGJldGFfMCBcKSwgd2hpY2ggaXMgdGhlIGludGVyY2VwdCwgIFwoIFxiZXRhXzEsIFxkb3RzLCBcYmV0YV9rIFwpLCB3aGljaCBhcmUgY29lZmZpY2llbnRzIG9mIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZXMsIGFzIHdlbGwgYXMgIFwoIFxzaWdtYV4yIFwpLCB0aGUgdmFyaWFuY2Ugb2YgdGhlIGVycm9yIHRlcm1zLCB3aGljaCByZXByZXNlbnRzIHRoZSB2YXJpYWJpbGl0eSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIFwoWVwpIHRoYXQgaXMgbm90IGV4cGxhaW5lZCBieSB0aGUgcHJlZGljdG9ycyBcKFhfMSwgXGRvdHMsIFhfa1wpLgoKVGhlIGxlYXN0IHNxdWFyZXMgbWV0aG9kIGVzdGltYXRlcyB0aGUgY29lZmZpY2llbnRzIGJ5ICptaW5pbWl6aW5nIHRoZSBzdW0gb2Ygc3F1YXJlZCByZXNpZHVhbHMqLiBHaXZlbiBcKG5cKSBvYnNlcnZhdGlvbnMgb24gXCh5XCksIGFuZCBcKGtcKSBwcmVkaWN0b3JzICBcKFhfMSwgXGRvdHMsIFhfa1wpLCB0aGUgZXN0aW1hdGVzIFwoIFxiZXRhXzEsIFxkb3RzLCBcYmV0YV9rIFwpIGFyZSBjaG9zZW4gc2ltdWx0YW5lb3VzbHkgdG8gbWluaW1pemUgdGhlIGV4cHJlc3Npb24gZm9yIHRoZSBFcnJvciBTdW0gb2YgU3F1YXJlcyAoU1NFKSwgZ2l2ZW4gYnk6CgokJApcdGV4dHtTU0V9ID0gXHN1bV97aT0xfV57bn0gKHlfaSAtIFxoYXR7eX1faSleMiA9IFxzdW1fe2k9MX1ee259ICh5X2kgLSBcaGF0e1xiZXRhfV8wIC0gXGhhdHtcYmV0YX1fMSB4X3tpMX0gLSBcZG90cyAtIFxoYXR7XGJldGF9X2sgeF97aWt9KV4yCiQkCgp3aGVyZSBcKCB5X2kgXCkgcmVwcmVzZW50cyB0aGUgYWN0dWFsIHZhbHVlcywgXCggXGhhdHtcYmV0YX1fMCBcKSBpcyB0aGUgZXN0aW1hdGVkIGludGVyY2VwdCwgXCggXGJldGFfMSBcKSBpcyB0aGUgY29lZmZpY2llbnQgZm9yIHRoZSBwcmVkaWN0b3IgXCh4X3sxaX1cKSwgYW5kIFwoIHhfezFpfSBcKSBpcyB0aGUgcHJlZGljdG9yIHZhbHVlIGZvciB0aGUgXChpXCktdGggb2JzZXJ2YXRpb24uCgpXaXRoIHRoZSBFcnJvciBTdW0gb2YgU3F1YXJlcyAoU1NFKSwgdGhlIGVxdWF0aW9uIG9mIHRoZSBlc3RpbWF0ZWQgdmFyaWFuY2Ugb2YgdGhlIGVycm9yIHRlcm0gXCggXHNpZ21hXjIgXCkgaXMgZ2l2ZW4gYnk6CgokJApcc2lnbWFeMiA9IFxmcmFje1x0ZXh0e1NTRX19e24gLSAoaysxKX0KJCQKCndoZXJlIFwoIG4gXCkgaXMgdGhlIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgYW5kIFwoIGsgXCkgaXMgdGhlIG51bWJlciBvZiBwcmVkaWN0b3JzIGluIHRoZSBtb2RlbC4KCldlIGV2YWx1YXRlZCB0aGUgbW9kZWwncyBnb29kbmVzcyBvZiBmaXQgdXNpbmcgdGhlIGNvZWZmaWNpZW50IG9mIGRldGVybWluYXRpb24gXChSXjJcKSwgd2hpY2ggcXVhbnRpZmllcyB0aGUgcHJvcG9ydGlvbiBvZiB2YXJpYW5jZSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGV4cGxhaW5lZCBieSB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzLiBUaGUgYWRqdXN0ZWQgXChSXjJcKSwgd2hpY2ggYWRqdXN0cyB0aGUgXChSXjJcKSB2YWx1ZSBiYXNlZCBvbiB0aGUgbnVtYmVyIG9mIHByZWRpY3RvcnMgaW4gdGhlIG1vZGVsIHRvIHByb3ZpZGUgYSBtb3JlIGFjY3VyYXRlIG1lYXN1cmUgb2YgbW9kZWwgZml0IGZvciBtdWx0aXBsZSByZWdyZXNzaW9uLiBJbiBzaW1wbGUgcmVncmVzc2lvbjogCgokJApTU1QgPSBcc3VtX3tpPTF9XntufSAoeV9pIC0gXGJhcnt5fSleMgokJAp3aGVyZSBcKCB5X2kgXCkgaXMgdGhlIG9ic2VydmVkIHZhbHVlLCBcKCBcYmFye3l9IFwpIGlzIHRoZSBtZWFuIG9mIHRoZSBvYnNlcnZlZCB2YWx1ZXMsIGFuZCBcKCBuIFwpIGlzIHRoZSBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zLiBUaGVuLCAgIFwoUl4yXCkgY2FuIGJlIHNpbXBseSBvYnRhaW5lZCBieTogCgokJApSXjIgPSAxIC0gXGZyYWN7U1NFfXtTU1R9CiQkClwoUl4yXCkgaXMgdGhlbiB0eXBpY2FsbHkgYWRqdXN0ZWQgYXMgZm9sbG93cyBiYXNlZCBvbiBcKCBuIFwpLCB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBhbmQgXCggayBcKSwgdGhlIG51bWJlciBvZiBwcmVkaWN0b3JzIGluIHRoZSBtb2RlbC4gCgokJApSXjJfe1x0ZXh0e2Fkan19ID0gMSAtIFxmcmFjeygxIC0gUl4yKShuIC0gMSl9e24gLSBrIC0gMX0KJCQKCiMjIyBIeXBvdGhlc2lzIFRlc3RpbmcKCkluIHRoaXMgYW5hbHlzaXMsIHdlIHRlc3Qgc2V2ZXJhbCBoeXBvdGhlc2VzIHRvIGV2YWx1YXRlIHRoZSBzaWduaWZpY2FuY2Ugb2YgdGhlIG1vZGVsIGFuZCBpdHMgcHJlZGljdG9ycy4gVGhlIG92ZXJhbGwgc2lnbmlmaWNhbmNlIG9mIHRoZSByZWdyZXNzaW9uIG1vZGVsIGlzIGFzc2Vzc2VkIHVzaW5nIHRoZSBGLXJhdGlvLiBJdCBjb21wYXJlcyB0aGUgdmFyaWFuY2UgZXhwbGFpbmVkIGJ5IHRoZSByZWdyZXNzaW9uIG1vZGVsIHRvIHRoZSB2YXJpYW5jZSB0aGF0IGlzIG5vdCBleHBsYWluZWQgYnkgdGhlIG1vZGVsLCBhc3Nlc3Npbmcgd2hldGhlciB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzIGFzIGEgd2hvbGUgaGF2ZSBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgZWZmZWN0IG9uIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUuIEEgaGlnaGVyIEYtcmF0aW8gaW5kaWNhdGVzIHRoYXQgdGhlIHJlZ3Jlc3Npb24gbW9kZWwgZXhwbGFpbnMgYSBzaWduaWZpY2FudCBhbW91bnQgb2YgdmFyaWFuY2UgaW4gdGhlIGRlcGVuZGVudCB2YXJpYWJsZSBjb21wYXJlZCB0byB0aGUgcmVzaWR1YWwgdmFyaWFuY2UuCgpUaGUgbnVsbCBoeXBvdGhlc2lzIChcKCBIXzAgXCkpIGFuZCBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIChcKCBIX2EgXCkpIGZvciB0aGUgRi1yYXRpbyBhcmUgc3RhdGVkIGFzIGZvbGxvd3M6CgotICoqTnVsbCBIeXBvdGhlc2lzIChcKCBIXzAgXCkpKio6IFRoZSByZWdyZXNzaW9uIG1vZGVsIGRvZXMgbm90IGV4cGxhaW4gYSBzaWduaWZpY2FudCBwb3J0aW9uIG9mIHRoZSB2YXJpYW5jZSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIChtZWRpYW4gaG91c2UgdmFsdWUpLiBJbiBvdXIgY2FzZSwgdGhpcyBtZWFucyB0aGF0IHRoZSBjb2VmZmljaWVudHMgZm9yIGFsbCB0aGUgcHJlZGljdG9ycyBhcmUgZXF1YWwgdG8gemVybyBhbmQgbm9uZSBvZiB0aGVtIGV4cGxhaW4gYW55IHZhcmlhbmNlIGluIGhvdXNpbmcgcHJpY2UuIFRoaXMgY2FuIGJlIGZvcm1hbGx5IHN0YXRlZCBhczoKICAkJAogIEhfMDogXGJldGFfMSA9IFxiZXRhXzIgPSBcYmV0YV8zID0gXGJldGFfNCA9IDAKICAkJAoKLSAqKkFsdGVybmF0aXZlIEh5cG90aGVzaXMgKFwoIEhfYSBcKSkqKjogQXQgbGVhc3Qgb25lIG9mIHRoZSBwcmVkaWN0b3IgdmFyaWFibGVzIGhhcyBhIHNpZ25pZmljYW50IGVmZmVjdCBvbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLiBJbiBvdXIgY2FzZSwgdGhpcyBtZWFucyB0aGF0IGF0IGxlYXN0IG9uZSBvZiB0aGUgY29lZmZpY2llbnRzIGZvciB0aGUgcHJlZGljdG9ycyBpcyBub3QgZXF1YWwgdG8gemVybywgaW5kaWNhdGluZyB0aGF0IHRoZSBwcmVkaWN0b3IgaGFzIGEgc2lnbmlmaWNhbnQgaW1wYWN0IG9uIGhvdXNpbmcgcHJpY2VzLiBUaGlzIGNhbiBiZSBzdGF0ZWQgYXM6CiAgJCQKICBIX2E6IFx0ZXh0e0F0IGxlYXN0IG9uZSB9IFxiZXRhX2kgXG5lcSAwCiAgJCQKCkZvciBlYWNoIGluZGl2aWR1YWwgcHJlZGljdG9yIFwoIFxiZXRhX2kgXCksIHdlIGFsc28gdGVzdCB0aGUgZm9sbG93aW5nIGh5cG90aGVzZXM6CgotICoqTnVsbCBIeXBvdGhlc2lzIChcKCBIX3swaX0gXCkpKio6IFRoZSBjb2VmZmljaWVudCBmb3IgdGhlIHByZWRpY3RvciBcKCBpIFwpIGlzIGVxdWFsIHRvIHplcm8sIGluZGljYXRpbmcgdGhhdCBpdCBkb2VzIG5vdCBoYXZlIGEgc2lnbmlmaWNhbnQgZWZmZWN0IG9uIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgKG1lZGlhbiBob3VzZSB2YWx1ZSkuIFRoaXMgY2FuIGJlIGZvcm1hbGx5IHN0YXRlZCBhczoKICAkJAogIEhfezBpfTogXGJldGFfaSA9IDAKICAkJAoKLSAqKkFsdGVybmF0aXZlIEh5cG90aGVzaXMgKFwoIEhfe2FpfSBcKSkqKjogVGhlIGNvZWZmaWNpZW50IGZvciB0aGUgcHJlZGljdG9yIFwoIGkgXCkgaXMgbm90IGVxdWFsIHRvIHplcm8sIGluZGljYXRpbmcgdGhhdCBpdCBoYXMgYSBzaWduaWZpY2FudCBlZmZlY3Qgb24gdGhlIGRlcGVuZGVudCB2YXJpYWJsZS4gVGhpcyBjYW4gYmUgc3RhdGVkIGFzOgogICQkCiAgSF97YWl9OiBcYmV0YV9pIFxuZXEgMAogICQkCgpFYWNoIHByZWRpY3RvcidzIHNpZ25pZmljYW5jZSBpcyB0eXBpY2FsbHkgYXNzZXNzZWQgdXNpbmcgYSB0LXRlc3QsIHdoaWNoIHRlc3RzIHdoZXRoZXIgdGhlIGVzdGltYXRlZCBjb2VmZmljaWVudCBkaWZmZXJzIHNpZ25pZmljYW50bHkgZnJvbSB6ZXJvLgoKIyMgQWRkaXRpb25hbCBBbmFseXNlcwoKSW4gYWRkaXRpb24sIHdlIGNvbmR1Y3RlZCBzdGVwd2lzZSByZWdyZXNzaW9uIHRvIGlkZW50aWZ5IHRoZSBtb3N0IGltcG9ydGFudCBwcmVkaWN0b3JzIG9mIG1lZGlhbiBob3VzZSB2YWx1ZXMgaW4gUGhpbGFkZWxwaGlhLiBTdGVwd2lzZSByZWdyZXNzaW9uIGlzIGEgdmFyaWFibGUgc2VsZWN0aW9uIHRlY2huaXF1ZSB0aGF0IGF1dG9tYXRpY2FsbHkgc2VsZWN0cyB0aGUgYmVzdCBzdWJzZXQgb2YgcHJlZGljdG9ycyBmb3IgdGhlIG1vZGVsLiBJdCBpbnZvbHZlcyBhZGRpbmcgb3IgcmVtb3ZpbmcgcHJlZGljdG9ycyBiYXNlZCBvbiB0aGVpciBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UsIHdpdGggdGhlIGdvYWwgb2YgY3JlYXRpbmcgYSBwYXJzaW1vbmlvdXMgbW9kZWwgdGhhdCBleHBsYWlucyB0aGUgbW9zdCB2YXJpYW5jZSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLiAKCldlIGFja25vd2xlZGdlIHNldmVyYWwgbGltaXRhdGlvbnMgb2Ygc3RlcHdpc2UgcmVncmVzc2lvbi4gRmlyc3QsIHRoZSBmaW5hbCBtb2RlbCBzZWxlY3RlZCBieSBzdGVwd2lzZSByZWdyZXNzaW9uIGlzIG5vdCBndWFyYW50ZWVkIHRvIGJlIG9wdGltYWwgaW4gYW55IHNwZWNpZmljIHNlbnNlLiBUaGVyZSBtYXkgYmUgb3RoZXIgbW9kZWxzIHRoYXQgYXJlIGp1c3QgYXMgZ29vZCwgb3IgZXZlbiBiZXR0ZXIsIHRoYW4gdGhlIG9uZSBpZGVudGlmaWVkIHRocm91Z2ggdGhpcyBwcm9jZXNzLiBBZGRpdGlvbmFsbHksIHRoZSBtZXRob2QgeWllbGRzIG9ubHkgYSBzaW5nbGUgZmluYWwgbW9kZWwsIGV2ZW4gdGhvdWdoIG11bHRpcGxlIG1vZGVscyBjb3VsZCBwcm92aWRlIGVxdWFsbHkgdmFsaWQgb3IgaW5mb3JtYXRpdmUgcHJlZGljdGlvbnMuIE1vcmVvdmVyLCBzdGVwd2lzZSByZWdyZXNzaW9uIGRvZXMgbm90IHRha2UgaW50byBhY2NvdW50IHRoZSByZXNlYXJjaGVyJ3MgZG9tYWluIGtub3dsZWRnZSByZWdhcmRpbmcgdGhlIHByZWRpY3RvcnMuIEltcG9ydGFudCB2YXJpYWJsZXMgbWF5IGJlIGV4Y2x1ZGVkIHVubGVzcyBtYW51YWxseSBmb3JjZWQgaW50byB0aGUgbW9kZWwsIHdoaWNoIGNhbiBsZWFkIHRvIGFuIGluY29tcGxldGUgb3IgaW5hY2N1cmF0ZSB1bmRlcnN0YW5kaW5nIG9mIHRoZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gdGhlIHZhcmlhYmxlcy4gVGhpcyBtZXRob2QgYWxzbyBydW5zIHRoZSByaXNrIG9mIFR5cGUgSSBhbmQgVHlwZSBJSSBlcnJvcnPigJRtZWFuaW5nIGl0IG1heSBpbmNsdWRlIHVuaW1wb3J0YW50IHZhcmlhYmxlcyBvciBleGNsdWRlIGltcG9ydGFudCBvbmVzLgoKV2UgYWxzbyBwZXJmb3JtZWQgSy1mb2xkIGNyb3NzLXZhbGlkYXRpb24gdG8gYXNzZXNzIHRoZSBwcmVkaWN0aXZlIHBlcmZvcm1hbmNlIG9mIHRoZSBtb2RlbC4gQ3Jvc3MtdmFsaWRhdGlvbiBpcyBhIHJlc2FtcGxpbmcgdGVjaG5pcXVlIHVzZWQgdG8gZXZhbHVhdGUgdGhlIHBlcmZvcm1hbmNlIG9mIGEgcHJlZGljdGl2ZSBtb2RlbC4gSW4gSy1mb2xkIGNyb3NzLXZhbGlkYXRpb24sIHRoZSBkYXRhc2V0IGlzIGRpdmlkZWQgaW50byBLIHN1YnNldHMgb3IgZm9sZHMuIFRoZSBtb2RlbCBpcyB0cmFpbmVkIG9uIEstMSBmb2xkcyBhbmQgdGVzdGVkIG9uIHRoZSByZW1haW5pbmcgZm9sZC4gVGhpcyBwcm9jZXNzIGlzIHJlcGVhdGVkIEsgdGltZXMsIHdpdGggZWFjaCBmb2xkIHNlcnZpbmcgYXMgdGhlIHRlc3Qgc2V0IGV4YWN0bHkgb25jZS4gVGhlIHBlcmZvcm1hbmNlIG9mIHRoZSBtb2RlbCBpcyB0aGVuIGF2ZXJhZ2VkIGFjcm9zcyB0aGUgSyBmb2xkcyB0byBwcm92aWRlIGFuIG92ZXJhbGwgZXN0aW1hdGUgb2YgcHJlZGljdGl2ZSBhY2N1cmFjeS4gSW4gb3VyIGFuYWx5c2lzLCB3ZSB1c2VkIEsgPSA1LCB3aGljaCBpcyBhIGNvbW1vbiBjaG9pY2UgZm9yIGNyb3NzLXZhbGlkYXRpb24uIFRoZSByb290IG1lYW4gc3F1YXJlZCBlcnJvciAoUk1TRSkgaXMgdXNlZCB0byBjb21wYXJlIHRoZSBwZXJmb3JtYW5jZSBvZiBkaWZmZXJlbnQgbW9kZWxzLiBUaGUgUk1TRSBpcyBhIG1lYXN1cmUgb2YgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gcHJlZGljdGVkIGFuZCBvYnNlcnZlZCB2YWx1ZXMsIHdpdGggbG93ZXIgdmFsdWVzIGluZGljYXRpbmcgYmV0dGVyIHByZWRpY3RpdmUgYWNjdXJhY3kuIEluIHByZXZpb3VzIGFuYWx5c2lzLCB3ZSBoYXZlIGNhbGN1bGF0ZWQgdGhlIHN1bSBvZiBzcXVhcmVkIGVycm9ycyAoU1NFKSBhcyBmb2xsb3dzOgoKJCQgXHRleHR7U1NFfSA9IFxzdW1fe2k9MX1ee259ICh5X2kgLSBcaGF0e3l9X2kpXjIgJCQKClRoZW4gdGhlIG1lYW4gc3F1YXJlIGVycm9ycyAoTVNFKSBpcyBzaW1wbHk6IAoKJCQgXHRleHR7TVNFfSA9IFxmcmFjezF9e259IFxzdW1fe2k9MX1ee259ICh5X2kgLSBcaGF0e3l9X2kpXjIgJCQKCkFuZCB0aGUgcm9vdCBtZWFuIHNxdWFyZSBlcnJvciAoUk1TRSkgaXMgdGhlIHNxdWFyZSByb290IG9mIHRoZSBNU0U6IAoKJCQKXHRleHR7Uk1TRX0gPSBcc3FydHtcdGV4dHtNU0V9fQokJAoKIyMgU29mdHdhcmUgYW5kIFBhY2FrZ2VzIAoKRm9yIG91ciBkYXRhIGFuYWx5c2lzLCB3ZSBhcmUgdXRpbGl6aW5nIHRoZSBSIHByb2dyYW1taW5nIGxhbmd1YWdlLiBUaGUgZm9sbG93aW5nIGxpYnJhcmllcyBoYXZlIGJlZW4gZW1wbG95ZWQgdG8gZmFjaWxpdGF0ZSBvdXIgYW5hbHlzaXM6IAoKLSBgdGlkeXZlcnNlYDogQSBjb2xsZWN0aW9uIG9mIFIgcGFja2FnZXMgZGVzaWduZWQgZm9yIGRhdGEgc2NpZW5jZSB0aGF0IGluY2x1ZGVzIHRvb2xzIGZvciBkYXRhIG1hbmlwdWxhdGlvbiwgdmlzdWFsaXphdGlvbiwgYW5kIGFuYWx5c2lzLgotIGBoZXJlYDogQSBwYWNrYWdlIHRoYXQgc2ltcGxpZmllcyBmaWxlIHBhdGggbWFuYWdlbWVudCwgbWFraW5nIGl0IGVhc2llciB0byB3b3JrIHdpdGggcHJvamVjdCBkaXJlY3Rvcmllcy4KLSBga2FibGVFeHRyYWA6IEEgcGFja2FnZSBmb3IgY3JlYXRpbmcgYW5kIGN1c3RvbWl6aW5nIHRhYmxlcyBpbiBSIE1hcmtkb3duIGRvY3VtZW50cy4KLSBgZ2dwbG90MmA6IEEgd2lkZWx5LXVzZWQgcGFja2FnZSBmb3IgY3JlYXRpbmcgc3RhdGljIGdyYXBoaWNzIGFuZCB2aXN1YWxpemF0aW9ucyBiYXNlZCBvbiB0aGUgZ3JhbW1hciBvZiBncmFwaGljcy4KLSBgZ2djb3JycGxvdGA6IEEgcGFja2FnZSBzcGVjaWZpY2FsbHkgZGVzaWduZWQgZm9yIHZpc3VhbGl6aW5nIGNvcnJlbGF0aW9uIG1hdHJpY2VzIHVzaW5nIGdncGxvdDIuCi0gYHNmYDogQSBwYWNrYWdlIHRoYXQgcHJvdmlkZXMgc3VwcG9ydCBmb3Igc3BhdGlhbCBkYXRhIGluIFIsIGVuYWJsaW5nIHRoZSBoYW5kbGluZyBhbmQgYW5hbHlzaXMgb2YgZ2VvbWV0cmljIG9iamVjdHMuCi0gYHBhdGNod29ya2A6IEEgcGFja2FnZSB0aGF0IGFsbG93cyBmb3IgdGhlIGNvbWJpbmF0aW9uIG9mIG11bHRpcGxlIGdncGxvdDIgcGxvdHMgaW50byBhIHNpbmdsZSBjb2hlc2l2ZSBsYXlvdXQuCi0gYE1BU1NgOiBBIHBhY2thZ2UgdGhhdCBwcm92aWRlcyBmdW5jdGlvbnMgYW5kIGRhdGFzZXRzIGZvciB2YXJpb3VzIHN0YXRpc3RpY2FsIG1ldGhvZHMsIGluY2x1ZGluZyBsaW5lYXIgYW5kIGdlbmVyYWxpemVkIGxpbmVhciBtb2RlbHMuCi0gYGNhcmV0YDogQSBwYWNrYWdlIHRoYXQgc3RyZWFtbGluZXMgdGhlIHByb2Nlc3Mgb2YgY3JlYXRpbmcgcHJlZGljdGl2ZSBtb2RlbHMsIGluY2x1ZGluZyBmdW5jdGlvbnMgZm9yIGRhdGEgc3BsaXR0aW5nLCBwcmUtcHJvY2Vzc2luZywgZmVhdHVyZSBzZWxlY3Rpb24sIGFuZCBtb2RlbCB0dW5pbmcuCgoKIyBSZXN1bHRzCgojIyBFeHBsb3JhdG9yeSBSZXN1bHRzCgpXZSBiZWdhbiBieSBzdW1tYXJpemluZyB0aGUgc3RhdGlzdGljYWwgZGF0YSBmb3IgbWVkaWFuIGhvdXNlIHZhbHVlcyBhbmQgdmFyaW91cyBzb2Npby1lY29ub21pYyBwcmVkaWN0b3JzLiBUaGUgbWVkaWFuIGhvdXNlIHZhbHVlIGhhcyBhbiBhdmVyYWdlIG9mIFwkNjYsMjg3LjczLCB3aXRoIGEgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIFwkNjAsMDA2LjA4LiBUaGlzIGlzIHNpZ25pZmljYW50bHkgbG93ZXIgdGhhbiBib3RoIHRoZSBjb3VudHkgYW5kIHN0YXRlIGF2ZXJhZ2VzIGFuZCBzaG93cyBjb25zaWRlcmFibGUgdmFyaWF0aW9uIGluIGhvdXNlIHZhbHVlcy4gRm9yIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQsIDE2LjA4JSBvZiBpbmRpdmlkdWFscyBob2xkIGEgQmFjaGVsb3LigJlzIGRlZ3JlZSBvciBoaWdoZXIsIG11Y2ggbG93ZXIgdGhhbiB0aGUgc3RhdGUgYXZlcmFnZSBvZiAzNS4zJS4gVGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiAxNy43NyUgc3VnZ2VzdHMgbm90YWJsZSB2YXJpYWJpbGl0eSBpbiB0aGlzIG1lYXN1cmUuIFRoZSBhdmVyYWdlIG51bWJlciBvZiBob3VzZWhvbGRzIGxpdmluZyBpbiBwb3ZlcnR5IGlzIDE4OS43Nywgd2l0aCBhIHdpZGUgcmFuZ2UgcmVmbGVjdGVkIGJ5IGEgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIDE2NC4zMi4gVmFjYW50IGhvdXNlcyBtYWtlIHVwIGFuIGF2ZXJhZ2Ugb2YgMTEuMjklLCBzbGlnaHRseSBoaWdoZXIgdGhhbiB0aGUgc3RhdGUgYXZlcmFnZSBvZiA5LjQlLCB3aXRoIGEgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIDkuNjMlLiBGaW5hbGx5LCBzaW5nbGUgaG91c2UgdW5pdHMgYWNjb3VudCBmb3IgYW4gYXZlcmFnZSBvZiA5LjIzJSwgd2l0aCBhIHN0YW5kYXJkIGRldmlhdGlvbiBvZiAxMy4yNSUuIAoKYGBge3IgbWVhbiBhbmQgc2QsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGV4YW1pbmUgdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBkZXBlbmRlbnQgYW5kIGluZGVwZW5kZW50IHZhcmlhYmxlcy4gCmRpc3RfcmVzdWx0cyA8LSBkYXRhLmZyYW1lKFZhcmlhYmxlID0gY2hhcmFjdGVyKCksIE1lYW4gPSBudW1lcmljKCksIFNEID0gbnVtZXJpYygpLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCnZhcmlhYmxlcyA8LSBjKCJNRURIVkFMIiwgIlBDVEJBQ0hNT1IiLCAiTkJFTFBPVjEwMCIsICJQQ1RWQUNBTlQiLCAiUENUU0lOR0xFUyIpCnJlbGFiZWxsZWRfdmFyaWFibGVzIDwtIGMoCiAgIk1lZGlhbiBIb3VzZSBWYWx1ZSIsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBNRURIVkFMCiAgIiUgb2YgSW5kaXZpZHVhbHMgd2l0aCBCYWNoZWxvcuKAmXMgRGVncmVlcyBvciBIaWdoZXIiLCAgICAjIFBDVEJBQ0hNT1IKICAiIyBIb3VzZWhvbGRzIExpdmluZyBpbiBQb3ZlcnR5IiwgICAgICAgICAgICAgICAgICAgICAgICAjIE5CRUxQT1YxMDAKICAiJSBvZiBWYWNhbnQgSG91c2VzIiwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFBDVFZBQ0FOVAogICIlIG9mIFNpbmdsZSBIb3VzZSBVbml0cyIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgUENUU0lOR0xFUwopCgpmb3IgKGkgaW4gc2VxX2Fsb25nKHZhcmlhYmxlcykpIHsKICAKICBtZWFuX3ZhbCA8LSByb3VuZChtZWFuKGRhdGFbW3ZhcmlhYmxlc1tpXV1dLCBuYS5ybSA9IFRSVUUpLCAzKSAKICBzZF92YWwgPC0gcm91bmQoc2QoZGF0YVtbdmFyaWFibGVzW2ldXV0sIG5hLnJtID0gVFJVRSksIDMpIAogIAogICMgU3RvcmUgdGhlIHJlbGFiZWxlZCB2YXJpYWJsZSBuYW1lcwogIGRpc3RfcmVzdWx0cyA8LSByYmluZChkaXN0X3Jlc3VsdHMsIGRhdGEuZnJhbWUoVmFyaWFibGUgPSByZWxhYmVsbGVkX3ZhcmlhYmxlc1tpXSwgTWVhbiA9IG1lYW5fdmFsLCBTRCA9IHNkX3ZhbCkpCn0KCgpkaXN0X3Jlc3VsdHMgPC0gcmJpbmQoCiAgZGF0YS5mcmFtZShWYXJpYWJsZSA9ICJEZXBlbmRlbnQgVmFyaWFibGUiLCBNZWFuID0gIiIsIFNEID0gIiIpLAogIGRhdGEuZnJhbWUoVmFyaWFibGUgPSAiTWVkaWFuIEhvdXNlIFZhbHVlIiwgTWVhbiA9IGRpc3RfcmVzdWx0cyRNZWFuWzFdLCBTRCA9IGRpc3RfcmVzdWx0cyRTRFsxXSksCiAgZGF0YS5mcmFtZShWYXJpYWJsZSA9ICJQcmVkaWN0b3JzIiwgTWVhbiA9ICIiLCBTRCA9ICIiKSwKICBkaXN0X3Jlc3VsdHNbLTEsIF0gIyBSZW1vdmUgdGhlIGZpcnN0IHJvdyBiZWNhdXNlIGl0IGhhcyBhbHJlYWR5IGJlZW4gdXNlZCBhYm92ZQopCgpkaXN0X3Jlc3VsdHMgJT4lICAKICBrYWJsZShyb3cubmFtZXMgPSBGQUxTRSkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIikpICU+JSAKICByb3dfc3BlYygwLCBib2xkID0gVFJVRSkgJT4lICAjIEJvbGQgdGhlIGhlYWRlciByb3cKICByb3dfc3BlYygxLCBib2xkID0gVFJVRSkgJT4lICAjIEJvbGQgdGhlICdEZXBlbmRlbnQgVmFyaWFibGUnIHJvdwogIHJvd19zcGVjKDMsIGJvbGQgPSBUUlVFKQoKCmBgYAoKQWNjb3JkaW5nIHRvIHRoZSBoaXN0b2dyYW1zLCBub25lIG9mIHRoZSBkaXN0cmlidXRpb25zIG9mIHRoZSBkZXBlbmRlbnQgYW5kIGluZGVwZW5kZW50IHZhcmlhYmxlcyB3ZXJlIG5vcm1hbC4gVG8gYWRkcmVzcyB0aGlzLCB3ZSBhcHBsaWVkIGEgbG9nYXJpdGhtaWMgdHJhbnNmb3JtYXRpb24gdG8gdGhlIHZhcmlhYmxlcy4gCgpgYGB7ciBoaXN0b2dyYW1zLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD05LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyBoaXN0b2dyYW0KCmRhdGEgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKCJNRURIVkFMIiwgIlBDVEJBQ0hNT1IiLCAiTkJFTFBPVjEwMCIsICJQQ1RWQUNBTlQiLCAiUENUU0lOR0xFUyIpLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJWYXJpYWJsZSIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJWYWx1ZSIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBWYWx1ZSkpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uY291bnQuLiksIGZpbGwgPSAiIzI4M2QzYiIsIGFscGhhID0gMC43KSArICAKICBmYWNldF93cmFwKH5WYXJpYWJsZSwgc2NhbGVzID0gImZyZWUiLCBuY29sID0gMywgbGFiZWxsZXIgPSBhc19sYWJlbGxlcihjKAogICAgIk1FREhWQUwiID0gIk1lZGlhbiBIb3VzZSBWYWx1ZSIsCiAgICAiUENUQkFDSE1PUiIgPSAiJSB3aXRoIEJhY2hlbG9y4oCZcyBEZWdyZWVzIG9yIEhpZ2hlciIsCiAgICAiTkJFTFBPVjEwMCIgPSAiIyBIb3VzZWhvbGRzIExpdmluZyBpbiBQb3ZlcnR5IiwKICAgICJQQ1RWQUNBTlQiID0gIiUgb2YgVmFjYW50IEhvdXNlcyIsCiAgICAiUENUU0lOR0xFUyIgPSAiJSBvZiBTaW5nbGUgSG91c2UgVW5pdHMiCiAgKSkpICsgIAogIGxhYnMoeCA9ICJWYWx1ZSIsIHkgPSAiQ291bnQiLCB0aXRsZSA9ICJIaXN0b2dyYW1zIG9mIERlcGVuZGVudCBhbmQgUHJlZGljdG9yIFZhcmlhYmxlcyIpICsKICB0aGVtZV9saWdodCgpICsgICAKICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT02KSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT02KSwgCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT04KSkKCgoKCmBgYAoKVGhpcyB0cmFuc2Zvcm1hdGlvbiBoYXMgaGVscGVkIHRvIG5vcm1hbGl6ZSBzb21lIG9mIHRoZSBkaXN0cmlidXRpb25zLCBwYXJ0aWN1bGFybHkgZm9yIHZhcmlhYmxlcyBsaWtlIG1lZGlhbiBob3VzZSB2YWx1ZSwgbnVtYmVyIG9mIGhvdXNlaG9sZHMgaW4gcG92ZXJ0eSwgYW5kIHBlcmNlbnRhZ2Ugb2YgdmFjYW50IGhvdXNlcy4gVGhlc2UgdmFyaWFibGVzIG5vdyBkaXNwbGF5IG1vcmUgc3ltbWV0cmljLCBiZWxsLXNoYXBlZCBkaXN0cmlidXRpb25zLiBIb3dldmVyLCBmb3IgdmFyaWFibGVzIGxpa2UgdGhlIHBlcmNlbnRhZ2Ugb2YgaW5kaXZpZHVhbHMgd2l0aCBhIGJhY2hlbG9y4oCZcyBkZWdyZWUgYW5kIHBlcmNlbnRhZ2Ugb2Ygc2luZ2xlIGhvdXNlIHVuaXRzLCB0aGUgdHJhbnNmb3JtYXRpb24gd2FzIGxlc3MgZWZmZWN0aXZlLCBhbmQgdGhleSBzdGlsbCBkZXZpYXRlIGZyb20gYSBub3JtYWwgZGlzdHJpYnV0aW9uLiAKCk1vdmluZyBmb3J3YXJkLCB3ZSB3aWxsIHVzZSB0aGUgbG9nLXRyYW5zZm9ybWVkIHJlc3VsdHMgZm9yIG91ciBhbmFseXNpcy4gVGhlIHJlbWFpbmluZyByZWdyZXNzaW9uIGFzc3VtcHRpb25zIHdpbGwgYmUgZXhhbWluZWQgaW4gZGV0YWlsIGluIGEgc2VwYXJhdGUgc2VjdGlvbiB0aXRsZWQgUmVncmVzc2lvbiBBc3N1bXB0aW9uIENoZWNrcy4KCmBgYHtyIGxvZyB2YXJpYWJsZXMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CgojIGxvZyB0aGUgdmFyaWFibGVzCgpyZWdfZGF0YSA8LSBkYXRhICU+JQogIG11dGF0ZSgKICAgIExOTUVESFZBTCA9IGlmIChtaW4oTUVESFZBTCkgPT0gMCkgbG9nKDEgKyBNRURIVkFMKSBlbHNlIGxvZyhNRURIVkFMKSwKICAgIExOUENUQkFDSE1PUiA9IGlmIChtaW4oUENUQkFDSE1PUikgPT0gMCkgbG9nKDEgKyBQQ1RCQUNITU9SKSBlbHNlIGxvZyhQQ1RCQUNITU9SKSwKICAgIExOTkJFTFBPVjEwMCA9IGlmIChtaW4oTkJFTFBPVjEwMCkgPT0gMCkgbG9nKDEgKyBOQkVMUE9WMTAwKSBlbHNlIGxvZyhOQkVMUE9WMTAwKSwKICAgIExOUENUVkFDQU5UID0gaWYgKG1pbihQQ1RWQUNBTlQpID09IDApIGxvZygxICsgUENUVkFDQU5UKSBlbHNlIGxvZyhQQ1RWQUNBTlQpLAogICAgTE5QQ1RTSU5HTEVTID0gaWYgKG1pbihQQ1RTSU5HTEVTKSA9PSAwKSBsb2coMSArIFBDVFNJTkdMRVMpIGVsc2UgbG9nKFBDVFNJTkdMRVMpCiAgKQoKYGBgCgoKYGBge3IgbG9nZ2VkIGhpc3RvZ3JhbXMsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTksIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGhpc3RvZ3JhbXMgb2YgdGhlIGxvZ2dlZCB2YXJpYWJsZXMKcmVnX2RhdGEgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKCJMTk1FREhWQUwiLCAiTE5QQ1RCQUNITU9SIiwgIkxOTkJFTFBPVjEwMCIsICJMTlBDVFZBQ0FOVCIsICJMTlBDVFNJTkdMRVMiKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiVmFyaWFibGUiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiVmFsdWUiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gVmFsdWUpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmNvdW50Li4pLCBmaWxsID0gIiMyODNkM2IiLCBhbHBoYSA9IDAuNykgKyAgCiAgZmFjZXRfd3JhcCh+VmFyaWFibGUsIHNjYWxlcyA9ICJmcmVlIiwgbmNvbCA9IDMsIGxhYmVsbGVyID0gYXNfbGFiZWxsZXIoYygKICAgICJMTk1FREhWQUwiID0gIk1lZGlhbiBIb3VzZSBWYWx1ZSIsCiAgICAiTE5QQ1RCQUNITU9SIiA9ICIlIHdpdGggQmFjaGVsb3LigJlzIERlZ3JlZXMgb3IgSGlnaGVyIiwKICAgICJMTk5CRUxQT1YxMDAiID0gIiMgSG91c2Vob2xkcyBMaXZpbmcgaW4gUG92ZXJ0eSIsCiAgICAiTE5QQ1RWQUNBTlQiID0gIiUgb2YgVmFjYW50IEhvdXNlcyIsCiAgICAiTE5QQ1RTSU5HTEVTIiA9ICIlIG9mIFNpbmdsZSBIb3VzZSBVbml0cyIKICApKSkgKyAgCiAgbGFicyh4ID0gIlZhbHVlIiwgeSA9ICJDb3VudCIsIHRpdGxlID0gIkhpc3RvZ3JhbXMgd2l0aCBMb2dnZWQgVHJhbnNmb3JtIFZhcmlhYmxlcyIpICsKICB0aGVtZV9saWdodCgpICsgICAKICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT02KSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT02KSwgCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT04KSkKCmBgYAoKVGhlIGNob3JvcGxldGggbWFwcyBvZiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGFuZCB0aGUgcHJlZGljdG9yIHZhcmlhYmxlcyByZXZlYWwgc2V2ZXJhbCBub3RhYmxlIHBhdHRlcm5zLiBJbiBwYXJ0aWN1bGFyLCB0aGUgbWFwIG9mIG1lZGlhbiBob3VzZSB2YWx1ZXMgc2hvd3MgaGlnaGVyIHZhbHVlcyBpbiB0aGUgbm9ydGh3ZXN0IFBoaWxhZGVscGhpYSBhbmQgY2VudGVyIGNpdHkgd2hpbGUgbG93ZXIgdmFsdWVzIGluIHRoZSBzb3V0aCBhbmQgd2VzdCBvZiBQaGlsYWRlbHBoaWEuIFRoaXMgcGF0dGVybiBpcyBjb25zaXN0ZW50IHdpdGggdGhlIGRpc3RyaWJ1dGlvbiBvZiBzaW5nbGUgaG91c2UgdW5pdHMgYW5kIHRoZSBwZXJjZW50YWdlIG9mIGluZGl2aWR1YWxzIHdpdGggYSBiYWNoZWxvcidzIGRlZ3JlZSBvciBoaWdoZXIsIHdoaWNoIGFsc28gZXhoaWJpdCBoaWdoZXIgY29uY2VudHJhdGlvbnMgaW4gdGhlIG5vcnRod2VzdCBhbmQgY2VudGVyIGNpdHkuIEluIGNvbnRyYXN0LCB0aGUgbWFwcyBvZiBob3VzZWhvbGRzIGxpdmluZyBpbiBwb3ZlcnR5IGFuZCB2YWNhbnQgaG91c2luZyB1bml0cyBzaG93IGhpZ2hlciBjb25jZW50cmF0aW9ucyBpbiB0aGUgbm9ydGgsIHdlc3QsIGFuZCBwYXJ0cyBvZiB0aGUgc291dGggb2YgUGhpbGFkZWxwaGlhLiBUaGVzZSBwYXR0ZXJucyBzdWdnZXN0IGFuIGludmVyc2UgcmVsYXRpb25zaGlwIGJldHdlZW4gcG92ZXJ0eSBhbmQgdmFjYW50IGhvdXNpbmcgd2l0aCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IGFuZCBzaW5nbGUtZmFtaWx5IGhvbWVvd25lcnNoaXAuIEl0IGFsc28gYXBwZWFycyB0aGF0IHRoZXJlIG1pZ2h0IHNvbWUgZGVncmVlIG9mIG11bHRpY29saW5lYXJpdHkgYmV0d2VlbiBwZXJjZW50YWdlIG9mIHBvcHVsYXRpb24gd2l0aCBhIGJhY2hlbG9yJ3MgZGVncmVlIG9yIGhpZ2hlciBhbmQgcGVyY2VudGFnZSBvZiBzaW5nbGUgZmFtaWx5IHVuaXRzLCBnaXZlbiB0aGF0IHRoZXkgc2hhcmUgc2ltaWxhciBzcGF0aWFsIHBhdHRlcm5zLiAKCmBgYHtyIHJlYWQgaW4gc2hhcGVmaWxlLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQoKcGhpbGx5IDwtIHN0X3JlYWQoaGVyZSgiZGF0YSIsInNoYXBlZmlsZSIsICJSZWdyZXNzaW9uRGF0YS5zaHAiKSkKCmBgYAoKCmBgYHtyIGNob3JvcGxldGgsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIGNob3JvcGxldGggbWFwcyBvZiBwcmVkaWN0b3IgYW5kIGRlcGVuZGVudCB2YXJpYWJsZXMKZ2dwbG90KHBoaWxseSkgKwogIGdlb21fc2YoYWVzKGZpbGwgPSBMTk1FREhWQUwpLCBjb2xvciA9ICJ0cmFuc3BhcmVudCIpICsKICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvcnMgPSBjKCIjRkFGOUY2IiwgIiNjNDQ1MzYiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJMTk1FREhWQUwiLCAKICAgICAgICAgICAgICAgICAgICAgICBuYS52YWx1ZSA9ICJ0cmFuc3BhcmVudCIpICsgICMgSGFuZGxlIE5BcwogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJncmV5IiwgZmlsbCA9IE5BLCBzaXplID0gMC44KSkgKwogIGxhYnModGl0bGUgPSAiTG9nIFRyYW5zZm9ybWVkIE1lZGlhbiBIb3VzZSBWYWx1ZSIpCgpgYGAKCmBgYHtyIG1vcmUgY2hvcm9wbGV0aCwgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPTE1LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKbWFwX3BjdHZhY2FudCA8LSBnZ3Bsb3QocGhpbGx5KSArCiAgZ2VvbV9zZihhZXMoZmlsbCA9IFBDVFZBQ0FOVCksIGNvbG9yID0gInRyYW5zcGFyZW50IikgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG9ycyA9IGMoIiNGQUY5RjYiLCAiI2M0NDUzNiIpLCAKICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gIlBDVFZBQ0FOVCIsIAogICAgICAgICAgICAgICAgICAgICAgIG5hLnZhbHVlID0gInRyYW5zcGFyZW50IikgKyAgIyBIYW5kbGUgTkFzCiAgdGhlbWUobGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSwgZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImdyZXkiLCBmaWxsID0gTkEsIHNpemUgPSAwLjgpKSArCiAgbGFicyh0aXRsZSA9ICIlIG9mIFZhY2FudCBIb3VzZXMiKQoKbWFwX3BjdHNpbmdsZXMgPC0gZ2dwbG90KHBoaWxseSkgKwogIGdlb21fc2YoYWVzKGZpbGwgPSBQQ1RTSU5HTEVTKSwgY29sb3IgPSAidHJhbnNwYXJlbnQiKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3JzID0gYygiI0ZBRjlGNiIsICIjYzQ0NTM2IiksIAogICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiUENUU0lOR0xFUyIsIAogICAgICAgICAgICAgICAgICAgICAgIG5hLnZhbHVlID0gInRyYW5zcGFyZW50IikgKyAgIyBIYW5kbGUgTkFzCiAgdGhlbWUobGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSwgZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImdyZXkiLCBmaWxsID0gTkEsIHNpemUgPSAwLjgpKSArCiAgbGFicyh0aXRsZSA9ICIlIG9mIFNpbmdsZSBIb3VzZSBVbml0cyIpCgptYXBfcGNiYWNobW9yZSA8LSBnZ3Bsb3QocGhpbGx5KSArCiAgZ2VvbV9zZihhZXMoZmlsbCA9IFBDVEJBQ0hNT1IpLCBjb2xvciA9ICJ0cmFuc3BhcmVudCIpICsKICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvcnMgPSBjKCIjRkFGOUY2IiwgIiNjNDQ1MzYiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJQQ1RCQUNITU9SIiwgCiAgICAgICAgICAgICAgICAgICAgICAgbmEudmFsdWUgPSAidHJhbnNwYXJlbnQiKSArICAjIEhhbmRsZSBOQXMKICB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOSksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gIml0YWxpYyIpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiZ3JleSIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuOCkpICsKICBsYWJzKHRpdGxlID0gIiUgQmFjaGVsb3IncyBEZWdyZWUgb3IgSGlnaGVyIikKCgptYXBfbG5iZWxwb3YxMDAgPC0gZ2dwbG90KHBoaWxseSkgKwogIGdlb21fc2YoYWVzKGZpbGwgPSBMTk5CRUxQT1YpLCBjb2xvciA9ICJ0cmFuc3BhcmVudCIpICsKICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvcnMgPSBjKCIjRkFGOUY2IiwgIiNjNDQ1MzYiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJMTk5CRUxQT1YiLCAKICAgICAgICAgICAgICAgICAgICAgICBuYS52YWx1ZSA9ICJ0cmFuc3BhcmVudCIpICsgICMgSGFuZGxlIE5BcwogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJncmV5IiwgZmlsbCA9IE5BLCBzaXplID0gMC44KSkgKwogIGxhYnModGl0bGUgPSAiTG9nZ2VkIFRyYW5zZm9ybWVkIFBvdmVydHkiKQoKbWFwX3BjdHZhY2FudCArIG1hcF9wY3RzaW5nbGVzICsgbWFwX3BjYmFjaG1vcmUgKyBtYXBfbG5iZWxwb3YxMDAgKyAKICBwbG90X2xheW91dChuY29sID0gMikKYGBgCgoKVGhlIGNvcnJlbGF0aW9uIG1hdHJpeCBzdXBwb3J0cyBvdXIgb2JzZXJ2YXRpb25zIGZyb20gdGhlIG1hcC4gVGhlcmUncyBhIHBvc2l0aXZlIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgcGVyY2VudGFnZSBvZiBwZW9wbGUgd2l0aCBhdCBsZWFzdCBhIEJhY2hlbG9yJ3MgRGVncmVlIG9yIGhpZ2hlciBhbmQgdGhlIHBlcmNlbnRhZ2Ugb2Ygc2luZ2xlLWZhbWlseSB1bml0cywgd2l0aCBhIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IG9mIDAuMi4gVGhlIHBlcmNlbnRhZ2Ugb2YgaG91c2Vob2xkcyBsaXZpbmcgYmVsb3cgdGhlIHBvdmVydHkgbGluZSBhbHNvIHBvc2l0aXZlbHkgY29ycmVsYXRlZCB3aXRoIHRoZSBwZXJjZW50YWdlIG9mIHZhY2FudCBob3VzZXMsIHdpdGggYSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBvZiAwLjI1LiBUaGVzZSBjb3JyZWxhdGlvbnMgc3VnZ2VzdCB0aGF0IHRoZSBwcmVkaWN0b3JzIGFyZSByZWxhdGVkIHRvIGVhY2ggb3RoZXIsIGJ1dCBzaW5jZSBub25lIG9mIHRoZXNlIGNvcnJlbGF0aW9ucyBleGNlZWQgMC44LCB3ZSBjYW4gcHJvY2VlZCB3aXRoIHRoZSByZWdyZXNzaW9uIGFuYWx5c2lzIHdpdGhvdXQgY29uY2VybnMgYWJvdXQgbXVsdGljb2xsaW5lYXJpdHkuCiAKCmBgYHtyIGNvcnIgcGxvdCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCmN1c3RvbV9sYWJlbHMgPC0gYygKICAiJSBvZiBJbmRpdmlkdWFscyB3aXRoIEJhY2hlbG9y4oCZcyBEZWdyZWVzIG9yIEhpZ2hlciIgPSAiUENUQkFDSE1PUiIsCiAgIiUgb2YgVmFjYW50IEhvdXNlcyIgPSAiUENUVkFDQU5UIiwKICAiJSBvZiBTaW5nbGUgSG91c2UgVW5pdHMiID0gIlBDVFNJTkdMRVMiLAogICIjIEhvdXNlaG9sZHMgTGl2aW5nIGluIFBvdmVydHkiID0gIkxOTkJFTFBPVjEwMCIKKQoKY29yX21hdHJpeCA8LSBjb3IocmVnX2RhdGEgJT4lIGRwbHlyOjpzZWxlY3QoUENUQkFDSE1PUiwgUENUVkFDQU5ULCBQQ1RTSU5HTEVTLCBMTk5CRUxQT1YxMDApKQpyb3duYW1lcyhjb3JfbWF0cml4KSA8LSBuYW1lcyhjdXN0b21fbGFiZWxzKQpjb2xuYW1lcyhjb3JfbWF0cml4KSA8LSBuYW1lcyhjdXN0b21fbGFiZWxzKQoKZ2djb3JycGxvdChjb3JfbWF0cml4LCAKICAgICAgICAgICB0eXBlID0gImxvd2VyIiwgCiAgICAgICAgICAgbGFiID0gVFJVRSwgCiAgICAgICAgICAgbGFiX3NpemUgPSAzLCAKICAgICAgICAgICBjb2xvcnMgPSBjKCIjMjgzZDNiIiwgIndoaXRlIiwgIiNjNDQ1MzYiKSkgKwogIGxhYnModGl0bGUgPSAiQ29ycmVsYXRpb24gTWF0cml4IGZvciBhbGwgUHJlZGljdG9yIFZhcmlhYmxlcyIpICsKICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gIml0YWxpYyIpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA3KSwgCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpCmBgYAoKCiMjIFJlZ3Jlc3Npb24gUmVzdWx0cwoKIyMjIFBhcmFtZXRlciBFc3RpbWF0ZXMKCkZvdXIgaW5kZXBlbmRlbnQgdmFyaWFibGVzLCB0aGUgcHJvcG9ydGlvbiBvZiB2YWNhbnQgaG91c2luZyB1bml0cyAoUENUVkFDQU5UKSwgdGhlIHByb3BvcnRpb24gb2Ygc2luZ2xlLWZhbWlseSBkZXRhY2hlZCBob21lcyAoUENUU0lOR0xFUyksIHRoZSBwcm9wb3J0aW9uIG9mIHJlc2lkZW50cyB3aXRoIGF0IGxlYXN0IGEgQmFjaGVsb3IncyBkZWdyZWUgKFBDVEJBQ0hNT1IpLCBhbmQgdGhlIG51bWJlciBvZiBsb2ctdHJhbnNmb3JtZWQgaG91c2Vob2xkcyBsaXZpbmcgYmVsb3cgdGhlIHBvdmVydHkgbGluZSAoTE5OQkVMUE9WMTAwKSwgd2VyZSByZWdyZXNzZWQgdG8gcHJlZGljdCB0aGUgbWVkaWFuIGxvZy10cmFuc2Zvcm1lZCBob21lIHZhbHVlcyAoTE5NRURIVkFMKSBmb3IgdGhlIFBoaWxhZGVscGhpYSBjZW5zdXMgYmxvY2sgZ3JvdXAuIAoKVGhlIHJlZ3Jlc3Npb24gb3V0cHV0IHRlbGxzIHVzIHRoYXQgdGhlIG1lZGlhbiBob21lIHZhbHVlcyBhcmUgaGlnaGx5IHNpZ25pZmljYW50IGFuZCBhcmUgYXNzb2NpYXRlZCB3aXRoIHRoZSBwcm9wb3J0aW9uIG9mIHNpbmdsZS1mYW1pbHkgZGV0YWNoZWQgaG9tZXMoUENUU0lOR0xFUyksIHRoZSBwcm9wb3J0aW9uIG9mIHJlc2lkZW50cyB3aXRoIGF0IGxlYXN0IGEgQmFjaGVsb3IncyBkZWdyZWUgKFBDVEJBQ0hNT1IpLCB0aGUgcHJvcG9ydGlvbiBvZiB2YWNhbnQgaG91c2luZyB1bml0cyAoUENUVkFDQU5UKSwgYW5kIHRoZSBudW1iZXIgb2YgbG9nLXRyYW5zZm9ybWVkIGhvdXNlaG9sZHMgbGl2aW5nIGJlbG93IHRoZSBwb3ZlcnR5IGxpbmUgKExOTkJFTFBPVjEwMCksIHdpdGggJHAgPCAwLjAwMSQgZm9yIGFsbCBwcmVkaWN0b3JzLgoKQXMgdGhlIHByb3BvcnRpb25zIG9mIHZhY2FudCBob3VzaW5nIHVuaXRzIChQQ1RWQUNBTlQpIGdvZXMgdXAgYnkgb25lIHVuaXQgKGkuZS5wZXJjZW50YWdlIHBvaW50KSwgdGhlIGV4cGVjdGVkIGNoYW5nZSBpbiBtZWRpYW4gaG9tZSB2YWx1ZSBpczogCgokJChlXntcYmV0YX0gLSAxKSBcdGltZXMgMTAwXCUgPSAoZV57LTAuMDE5MTU2OX0gLSAxKSBcdGltZXMgMTAwXCUgXGFwcHJveCAtMS44OTdcJSAkJAoKVGhhdCBpcywgYXMgcGVyY2VudGFnZSBvZiBwb3B1bGF0aW9uIGxpdmluZyBpbiBwb3ZlcnR5IGdvZXMgdXAgYnkgMSB1bml0ICgxJSksIG1lZGlhbiBob21lIHZhbHVlIGdvZXMgZG93biBieSBhcHByb3hpbWF0ZWx5IDEuODk3JSwgaG9sZGluZyBvdGhlciBwcmVkaWN0b3JzIGNvbnN0YW50LiBUaGUgcC12YWx1ZSBvZiBvZiBsZXNzIHRoYW4gMC4wMDAxIGZvciBQQ1RWQUNBTlQgdGVsbHMgdXMgdGhhdCBpZiB0aGVyZSBpcyBhY3R1YWxseSBubyByZWxhdGlvbnNoaXAgYmV0d2VlbiBQQ1RWQUNBTlQgYW5kIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgKGkuZS4sIGlmIHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCBcKCBcYmV0YV8xID0gMCBcKSBpcyBhY3R1YWxseSB0cnVlKSwgdGhlbiB0aGUgcHJvYmFiaWxpdHkgb2YgZ2V0dGluZyBhIFwoIFxiZXRhXzEgXCkgY29lZmZpY2llbnQgZXN0aW1hdGUgb2YgLTAuMDE5MTU2OSBpcyBsZXNzIHRoYW4gMC4wMDAxLgoKU2ltaWxhcmx5LCBhcyB0aGUgcHJvcG9ydGlvbiBvZiBzaW5nbGUtZmFtaWx5IGRldGFjaGVkIGhvbWVzIChQQ1RTSU5HTEVTKSBnb2VzIHVwIGJ5IG9uZSB1bml0IChpLmUucGVyY2VudGFnZSBwb2ludCksIHRoZSBleHBlY3RlZCBjaGFuZ2UgaW4gbWVkaWFuIGhvbWUgdmFsdWUgaXM6IAoKJCQoZV57XGJldGF9IC0gMSkgXHRpbWVzIDEwMFwlID0gKGVeezAuMDAyOTc2OX0gLSAxKSBcdGltZXMgMTAwXCUgXGFwcHJveCAwLjI5OFwlICQkCgpUaGF0IGlzLCBhcyBwZXJjZW50YWdlIG9mIHBvcHVsYXRpb24gbGl2aW5nIGluIHBvdmVydHkgZ29lcyB1cCBieSAxIHVuaXQgKDElKSwgbWVkaWFuIGhvbWUgdmFsdWUgZ29lcyB1cCBieSBhcHByb3hpbWF0ZWx5IDAuMjk4JSwgaG9sZGluZyBvdGhlciBwcmVkaWN0b3JzIGNvbnN0YW50LiBUaGUgcC12YWx1ZSBvZiBvZiBsZXNzIHRoYW4gMC4wMDAxIGZvciBQQ1RTSU5HTEVTIHRlbGxzIHVzIHRoYXQgaWYgdGhlcmUgaXMgYWN0dWFsbHkgbm8gcmVsYXRpb25zaGlwIGJldHdlZW4gUENUU0lOR0xFUyBhbmQgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSAoaS5lLiwgaWYgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IFwoIFxiZXRhXzIgPSAwIFwpIGlzIGFjdHVhbGx5IHRydWUpLCB0aGVuIHRoZSBwcm9iYWJpbGl0eSBvZiBnZXR0aW5nIGEgXCggXGJldGFfMiBcKSBjb2VmZmljaWVudCBlc3RpbWF0ZSBvZiAwLjAwMjk3NjkgaXMgbGVzcyB0aGFuIDAuMDAwMS4KCk1vcmVvdmVyLCBhcyB0aGUgcHJvcG9ydGlvbiBvZiBwZW9wbGUgd2l0aCBhIEJhY2hlbG9yJ3MgZGVncmVlIG9yIGhpZ2hlciAoUENUQkFDSE1PUikgZ29lcyB1cCBieSBvbmUgdW5pdCAoaS5lLnBlcmNlbnRhZ2UgcG9pbnQpLCB0aGUgZXhwZWN0ZWQgY2hhbmdlIGluIG1lZGlhbiBob21lIHZhbHVlIGlzOiAKCiQkKGVee1xiZXRhfSAtIDEpIFx0aW1lcyAxMDBcJSA9IChlXnswLjAyMDkwOTh9IC0gMSkgXHRpbWVzIDEwMFwlIFxhcHByb3ggMi4xMVwlICQkIAoKVGhhdCBpcywgYXMgcGVyY2VudGFnZSBvZiBwb3B1bGF0aW9uIHdpdGggYSBCYWNoZWxvcidzIGRlZ3JlZSBvciBoaWdoZXIgZ29lcyB1cCBieSAxIHVuaXQgKDElKSwgbWVkaWFuIGhvbWUgdmFsdWUgZ29lcyB1cCBieSBhcHByb3hpbWF0ZWx5IDIuMSUsIGhvbGRpbmcgb3RoZXIgcHJlZGljdG9ycyBjb25zdGFudC4gVGhlIHAtdmFsdWUgb2Ygb2YgbGVzcyB0aGFuIDAuMDAwMSBmb3IgUENUQkFDSE1PUiB0ZWxscyB1cyB0aGF0IGlmIHRoZXJlIGlzIGFjdHVhbGx5IG5vIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIFBDVEJBQ0hNT1IgYW5kIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgKGkuZS4sIGlmIHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCBcKCBcYmV0YV8zID0gMCBcKSBpcyBhY3R1YWxseSB0cnVlKSwgdGhlbiB0aGUgcHJvYmFiaWxpdHkgb2YgZ2V0dGluZyBhIFwoIFxiZXRhXzMgXCkgY29lZmZpY2llbnQgZXN0aW1hdGUgb2YgMC4wMjA5MDk4IGlzIGxlc3MgdGhhbiAwLjAwMDEuCgpBbmQgZmluYWxseSwgYXMgdGhlIG51bWJlciBvZiBsb2ctdHJhbnNmb3JtZWQgaG91c2Vob2xkcyBsaXZpbmcgYmVsb3cgdGhlIHBvdmVydHkgbGluZSAoTE5OQkVMUE9WMTAwKSBjaGFuZ2VzIGJ5IDElLCB0aGUgZXhwZWN0ZWQgdmFsdWUgb2YgbWVkaWFuIGhvbWUgdmFsdWUgY2hhbmdlcyBieSAKCiQkKDEuMDFee1xiZXRhfSAtIDEpIFx0aW1lcyAxMDBcJSA9ICgxLjAxXnstMC4wNzg5MDU0fSAtIDEpIFx0aW1lcyAxMDBcJSAgXGFwcHJveCAtMC4wNzhcJSQkCgpUaGF0IGlzLCBhcyB0aGUgbnVtYmVyIG9mIGhvdXNlaG9sZHMgbGl2aW5nIGJlbG93IHRoZSBwb3ZlcnR5IGxpbmUgZ29lcyB1cCAxJSwgbWVkaWFuIGhvbWUgdmFsdWUgY2hhbmdlcyBieSAtMC4wNzglLCBob2xkaW5nICUgaW4gb3RoZXIgcHJlZGljdG9ycyBjb25zdGFudC4gVGhlIHAtdmFsdWUgb2Ygb2YgbGVzcyB0aGFuIDAuMDAwMSBmb3IgTE5OQkVMUE9WMTAwIHRlbGxzIHVzIHRoYXQgaWYgdGhlcmUgaXMgYWN0dWFsbHkgbm8gcmVsYXRpb25zaGlwIGJldHdlZW4gTE5OQkVMUE9WMTAwIGFuZCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIChpLmUuLCBpZiB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgXCggXGJldGFfNCA9IDAgXCkgaXMgYWN0dWFsbHkgdHJ1ZSksIHRoZW4gdGhlIHByb2JhYmlsaXR5IG9mIGdldHRpbmcgYSBcKCBcYmV0YV80IFwpIGNvZWZmaWNpZW50IGVzdGltYXRlIG9mIC0wLjA3ODkwNTQgaXMgbGVzcyB0aGFuIDAuMDAwMS4KCkFsbCBvZiB0aGVzZSBsb3cgcHJvYmFiaWxpdGllcyBpbmRpY2F0ZSB0aGF0IHdlIGNhbiBzYWZlbHkgcmVqZWN0ICRIXzA6IFxiZXRhXzEgPSAwJCBmb3IgJEhfYTogXGJldGFfMSBcbmVxIDAkLCAkSF8wOiBcYmV0YV8yID0gMCQgZm9yICRIX2E6IFxiZXRhXzIgXG5lcSAwJCwgJEhfMDogXGJldGFfMyA9IDAkIGZvciAkSF9hOiBcYmV0YV8zIFxuZXEgMCQsIGFuZCAkSF8wOiBcYmV0YV80ID0gMCQgZm9yICRIX2E6IFxiZXRhXzQgXG5lcSAwJCAoYXQgbW9zdCByZWFzb25hYmxlIGxldmVscyBvZiAkXGFscGhhID0gUChcdGV4dHtUeXBlIEkgZXJyb3J9KSQpLgoKIyMjIE1vZGVsIEZpdAoKVGhlIHJlc2lkdWFscyBmcm9tIHRoZSBtb2RlbCBzaG93IGEgZmFpcmx5IHJlYXNvbmFibGUgZGlzdHJpYnV0aW9uIG9mIGVycm9ycywgd2l0aCBhIG1pbmltdW0gcmVzaWR1YWwgdmFsdWUgb2YgLTIuMjYsIGEgZmlyc3QgcXVhcnRpbGUgb2YgLTAuMjAsIGEgbWVkaWFuIG9mIDAuMDQsIGEgdGhpcmQgcXVhcnRpbGUgb2YgMC4yMiwgYW5kIGEgbWF4aW11bSB2YWx1ZSBvZiAyLjI0LiBUaGlzIGRpc3RyaWJ1dGlvbiBzdWdnZXN0cyB0aGF0IHRoZSBtb2RlbCBjYXB0dXJlcyBjaGFuZ2VzIGluIGhvdXNpbmcgdmFsdWVzIHJlYXNvbmFibHkgd2VsbCwgYWx0aG91Z2ggc29tZSBvZiB0aGUgZXh0cmVtZSByZXNpZHVhbHMgc3VnZ2VzdCB0aGF0IG91dGxpZXJzIG1heSBleGlzdC4KClRoZSBtb2RlbCBoYWQgYSBtdWx0aXBsZSBSLXNxdWFyZWQgdmFsdWUgb2YgMC42NjIzIGFuZCBhbiBhZGp1c3RlZCBSLXNxdWFyZWQgdmFsdWUgb2YgMC42NjE1LCBpbmRpY2F0aW5nIHRoYXQgYXBwcm94aW1hdGVseSA2NiUgb2YgdGhlIHZhcmlhbmNlIGluIExOTUVESFZBTCBpcyBleHBsYWluZWQgYnkgdGhlIGZvdXIgcHJlZGljdG9ycy4gVGhlIEYtc3RhdGlzdGljIGZvciB0aGlzIG1vZGVsIHdhcyA4NDAuOSAocCA8IDAuMDAxKSwgZnVydGhlciBjb25maXJtaW5nIHRoZSBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2Ugb2YgdGhlIG1vZGVsIGFzIGEgd2hvbGUuCgpgYGB7ciBsaW5lYXIgcmVncmVzc2lvbiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCmZpdCA8LSBsbShMTk1FREhWQUwgfiBQQ1RWQUNBTlQgKyBQQ1RTSU5HTEVTICsgUENUQkFDSE1PUiArIExOTkJFTFBPVjEwMCwgZGF0YT1yZWdfZGF0YSkKc3VtbWFyeShmaXQpCmBgYAoKVGhlIGFuYWx5c2lzIG9mIHZhcmlhbmNlIChBTk9WQSkgdGFibGUgcHJvdmlkZXMgYWRkaXRpb25hbCBpbnNpZ2h0IGludG8gdGhlIHNpZ25pZmljYW5jZSBvZiBlYWNoIHByZWRpY3RvciBpbiBleHBsYWluaW5nIHRoZSB2YXJpYXRpb24gaW4gTE5NRURIVkFMLiBGb3IgZXhhbXBsZSwgdGhlIHN1bSBvZiBzcXVhcmVzIGZvciBQQ1RWQUNBTlQgaXMgMTgwLjM5Mi4gVGhpcyB2YWx1ZSByZXByZXNlbnRzIHRoZSB2YXJpYXRpb24gaW4gTE5NRURIVkFMIHRoYXQgY2FuIGJlIGF0dHJpYnV0ZWQgdG8gY2hhbmdlcyBpbiB0aGUgcGVyY2VudGFnZSBvZiB2YWNhbnQgaG91c2luZyB1bml0cy4gQSBoaWdoZXIgc3VtIG9mIHNxdWFyZXMgaW5kaWNhdGVzIGEgc3Ryb25nZXIgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHByZWRpY3RvciBhbmQgdGhlIHJlc3BvbnNlIHZhcmlhYmxlLiBUaGUgc3VtIG9mIHNxdWFyZXMgZm9yIFBDVFNJTkdMRVMgaXMgMjQuNTQzLCBzaG93aW5nIHRoYXQgdGhlIHBlcmNlbnRhZ2Ugb2Ygc2luZ2xlLXBhcmVudCBob3VzZWhvbGRzIGFsc28gY29udHJpYnV0ZXMgdG8gZXhwbGFpbmluZyB0aGUgdmFyaWF0aW9uIGluIExOTUVESFZBTCwgdGhvdWdoIHRvIGEgbGVzc2VyIGV4dGVudCB0aGFuIFBDVFZBQ0FOVC4gVGhlIHN1bSBvZiBzcXVhcmVzIGZvciBQQ1RCQUNITU9SIGlzIDIzNS4xMTgsIGluZGljYXRpbmcgdGhhdCB0aGUgcGVyY2VudGFnZSBvZiByZXNpZGVudHMgd2l0aCBhIGJhY2hlbG9yJ3MgZGVncmVlIG9yIGhpZ2hlciBleHBsYWlucyBhIHNpZ25pZmljYW50IHBvcnRpb24gb2YgdGhlIHZhcmlhbmNlIGluIExOTUVESFZBTCwgbW9yZSB0aGFuIHRoZSBwcmV2aW91cyB0d28gcHJlZGljdG9ycy4gVGhpcyByZWluZm9yY2VzIHRoZSBpbXBvcnRhbmNlIG9mIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgaW4gZHJpdmluZyBob3VzaW5nIHZhbHVlcy4gTGFzdGx5LCB0aGUgc3VtIG9mIHNxdWFyZXMgZm9yIExOTkJFTFBPVjEwMCBpcyAxMS42OTIsIHN1Z2dlc3RpbmcgdGhhdCB3aGlsZSB0aGlzIHByZWRpY3RvciBkb2VzIGNvbnRyaWJ1dGUgdG8gZXhwbGFpbmluZyBMTk1FREhWQUwsIGl0cyBpbXBhY3QgaXMgY29tcGFyYXRpdmVseSBzbWFsbGVyIHRoYW4gdGhlIG90aGVycy4gCgpUaGUgdG90YWwgc3VtIG9mIHNxdWFyZXMsIHdoaWNoIHJlcHJlc2VudHMgdGhlIHVuZXhwbGFpbmVkIHZhcmlhdGlvbiBpbiB0aGUgbW9kZWwsIGlzIDIzMC4zNCwgd2l0aCBhIG1lYW4gc3F1YXJlIGVycm9yIG9mIDAuMTM0Lk92ZXJhbGwsIHRoZSBBTk9WQSByZXN1bHRzLCBjb21iaW5lZCB3aXRoIHRoZSBPTFMgcmVncmVzc2lvbiByZXN1bHRzLCBjb25maXJtZWQgdGhhdCBhbGwgZm91ciBwcmVkaWN0b3JzLVBDVFZBQ0FOVCwgUENUU0lOR0xFUywgUENUQkFDSE1PUiwgYW5kIExOTkJFTFBPVjEwMC1jb250cmlidXRlIHNpZ25pZmljYW50bHkgdG8gZXhwbGFpbmluZyB0aGUgY2hhbmdlcyBpbiBMTk1FREhWQUwgd2VyZSBhbGwgc2lnbmlmaWNhbnQgY29udHJpYnV0b3JzLiBUaGVzZSBmaW5kaW5ncyBwcm92aWRlIHN0cm9uZyBldmlkZW5jZSBvZiB0aGUgcm9idXN0bmVzcyBvZiB0aGUgbW9kZWwgYW5kIHRoZSByZWxldmFuY2Ugb2YgbmVpZ2hib3VyaG9vZCBjaGFyYWN0ZXJpc3RpY3MgaW4gcHJlZGljdGluZyBob3VzaW5nIHZhbHVlcy4KCmBgYHtyIGFub3ZhIHRhYmxlLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKYW5vdmFfdGFibGUgPC0gYW5vdmEoZml0KQphbm92YV90YWJsZQoKYGBgCgojIyBSZWdyZXNzaW9uIEFzc3VtcHRpb24gQ2hlY2sgCgpJbiB0aGlzIHNlY3Rpb24sIHdlIGNvbmR1Y3RlZCBhIHZhcmlldHkgb2YgYW5hbHlzZXMgdG8gY2hlY2sgaWYgdGhlIGFzc3VtcHRpb25zIG9mIHRoZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCB3ZXJlIG1ldC4gRWFybGllciBpbiB0aGlzIHJlcG9ydCwgd2UgaGF2ZSBhbHJlYWR5IGNoZWNrZWQgZm9yIHZhcmlhYmxlIGRpc3RyaWJ1dGlvbiAoc2VlIHRoZSBzdGF0cyB0YWJsZSBhYm92ZSkgYW5kIG11bHRpY29saW5lYXJpdHkgKHNlZSB0aGUgY29yciBkaWFncmFtIGFib3ZlKS4gVGh1cywgd2UgYmVnYW4gaGVyZSBieSBleGFtaW5pbmcgdGhlICoqbGluZWFyaXR5KiogYXNzdW1wdGlvbiBvZiB0aGUgbW9kZWwuIFdlIGNyZWF0ZWQgc2NhdHRlciBwbG90cyBvZiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIChMTk1FREhWQUwpIGFnYWluc3QgZWFjaCBvZiB0aGUgcHJlZGljdG9ycyAoUENUVkFDQU5ULCBQQ1RTSU5HTEVTLCBQQ1RCQUNITU9SLCBhbmQgTE5OQkVMUE9WMTAwKS4gCgpUaGUgc2NhdHRlciBwbG90IGZvciBQQ1RWQUNBTlQgc2hvd3MgYSBnZW5lcmFsIG5lZ2F0aXZlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBwcm9wb3J0aW9uIG9mIHZhY2FudCBob3VzaW5nIHVuaXRzIGFuZCBMTk1FREhWQUwuIEluIHRoZSBncmFwaCwgdGhlcmUgYXJlIGNsdXN0ZXJzIG9mIGJsb2NrIGdyb3VwcyB3aGVyZSBoaWdoIHZhY2FuY3kgcmF0ZXMgY29ycmVzcG9uZCB0byBsb3dlciBob3VzaW5nIHZhbHVlcywgcGFydGljdWxhcmx5IG9uIHRoZSBsZWZ0IHNpZGUgb2YgdGhlIHBsb3Qgd2hlcmUgdGhlIHZhbHVlcyBvZiBMTk1FREhWQUwgYXJlIGhpZ2hlci4gSG93ZXZlciwgdGhlIHBsb3QgaXMgbm90IHBlcmZlY3RseSBsaW5lYXIuIEluc3RlYWQsIGl0IHJldmVhbHMgYSBtb3JlIGNvbXBsZXggcmVsYXRpb25zaGlwIHdpdGggc2lnbmlmaWNhbnQgdmFyaWF0aW9uIGluIGhvdXNpbmcgdmFsdWVzIGFjcm9zcyBkaWZmZXJlbnQgdmFjYW5jeSByYXRlcy4gSW4gdGhlIG1pZGRsZSBhbmQgbG93ZXIgcmFuZ2VzIG9mIHZhY2FuY3kgcmF0ZXMsIHRoZSBkZWNsaW5lIGluIGhvdXNpbmcgdmFsdWVzIGJlY29tZXMgbGVzcyBwcm9ub3VuY2VkLiBUaGlzIHN1Z2dlc3RzIHRoYXQgd2hpbGUgdmFjYW50IGhvdXNpbmcgaXMgYXNzb2NpYXRlZCB3aXRoIGxvd2VyIHByb3BlcnR5IHZhbHVlcywgdGhlIGltcGFjdCBkaW1pbmlzaGVzIG9yIGJlY29tZXMgbGVzcyBwcmVkaWN0YWJsZSBhcyB0aGUgdmFjYW5jeSByYXRlIGNoYW5nZXMuCgpJbiB0aGUgc2NhdHRlciBwbG90IGZvciBQQ1RTSU5HTEVTLCBhIHdlYWsgcG9zaXRpdmUgdHJlbmQgY2FuIGJlIG9ic2VydmVkLCB0aG91Z2ggdGhlIHBvaW50cyBhcmUgc2NhdHRlcmVkIHdpZGVseSBhcm91bmQgdGhlIGxpbmUsIGluZGljYXRpbmcgYSB3ZWFrIGxpbmVhciByZWxhdGlvbnNoaXAuIEFzIHRoZSBwZXJjZW50YWdlIG9mIHNpbmdsZS1mYW1pbHkgaG9tZXMgaW5jcmVhc2VzLCB0aGUgdmFsdWVzIG9mIExOTUVESFZBTCB0ZW5kIHRvIGluY3JlYXNlLCBidXQgdGhpcyBwYXR0ZXJuIGlzIG5vdCBjb25zaXN0ZW50IGFjcm9zcyBhbGwgYmxvY2sgZ3JvdXBzLiBUaGUgc2NhdHRlciBvZiBwb2ludHMgc2hvd3Mgc2lnbmlmaWNhbnQgdmFyaWFiaWxpdHkgaW4gaG91c2luZyB2YWx1ZXMgYXQgdmFyaW91cyBsZXZlbHMgb2Ygc2luZ2xlLWZhbWlseSBob3VzaW5nLCB3aXRoIHNvbWUgYmxvY2sgZ3JvdXBzIGV4aGliaXRpbmcgaGlnaCB2YWx1ZXMgZXZlbiBhdCBsb3dlciBwZXJjZW50YWdlcyBvZiBzaW5nbGUtZmFtaWx5IGhvbWVzLiBUaGlzIHZhcmlhYmlsaXR5IHN1Z2dlc3RzIHRoYXQgd2hpbGUgdGhlcmUgaXMgYSBwb3NpdGl2ZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIHNpbmdsZS1mYW1pbHkgaG91c2luZyBhbmQgaGlnaGVyIHZhbHVlcywgdGhlIHJlbGF0aW9uc2hpcCBpcyBtb3JlIG51YW5jZWQsIGFuZCBvdGhlciBmYWN0b3JzIG1heSBiZSBpbmZsdWVuY2luZyBob3VzZSB2YWx1ZXMgYXQgdGhlIHNhbWUgdGltZS4KClRoZSBzY2F0dGVyIHBsb3QgZm9yIFBDVEJBQ0hNT1IsIGhvd2V2ZXIsIHNob3dzIGEgbXVjaCBjbGVhcmVyIGxpbmVhciByZWxhdGlvbnNoaXAuIEFzIHRoZSBwcm9wb3J0aW9uIG9mIHJlc2lkZW50cyB3aXRoIGF0IGxlYXN0IGEgYmFjaGVsb3LigJlzIGRlZ3JlZSBpbmNyZWFzZXMsIHRoZSBMTk1FREhWQUwgdmFsdWVzIGluY3JlYXNlIGluIGEgbW9yZSBjb25zaXN0ZW50IGFuZCBsaW5lYXIgZmFzaGlvbi4gVGhlIHBvaW50cyBvbiB0aGUgZ3JhcGggZm9ybSBhIHJlbGF0aXZlbHkgdGlnaHQgYmFuZCBhbG9uZyBhIHBvc2l0aXZlIHRyZW5kIGxpbmUsIGluZGljYXRpbmcgdGhhdCBoaWdoZXIgZWR1Y2F0aW9uIGxldmVscyB3aXRoaW4gYSBuZWlnaGJvcmhvb2QgYXJlIHN0cm9uZ2x5IGFzc29jaWF0ZWQgd2l0aCBoaWdoZXIgaG91c2luZyB2YWx1ZXMuIFRoZSBjb25zaXN0ZW50IHVwd2FyZCB0cmVuZCBpbiB0aGlzIGdyYXBoIHN1Z2dlc3RzIHRoYXQgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCBpcyBhIGtleSBkcml2ZXIgb2YgaG91c2luZyBwcmljZXMsIGFuZCB0aGUgbGluZWFyIHJlbGF0aW9uc2hpcCBpbXBsaWVzIHRoYXQgdGhpcyB2YXJpYWJsZSBpcyB3ZWxsLXN1aXRlZCBmb3IgaW5jbHVzaW9uIGluIHRoZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbC4KClRoZSBzY2F0dGVyIHBsb3QgZm9yIExOTkJFTFBPVjEwMCByZXZlYWxzIGEgcHJlZG9taW5hbnRseSBuZWdhdGl2ZSByZWxhdGlvbnNoaXAsIGJ1dCBsaWtlIFBDVFZBQ0FOVCwgdGhlIGFzc29jaWF0aW9uIGlzIG5vdCBzdHJpY3RseSBsaW5lYXIuIEluIHRoZSBncmFwaCwgYXMgdGhlIG51bWJlciBvZiBob3VzZWhvbGRzIGxpdmluZyBiZWxvdyB0aGUgcG92ZXJ0eSBsaW5lIGluY3JlYXNlcywgdGhlIExOTUVESFZBTCB2YWx1ZXMgZ2VuZXJhbGx5IGRlY3JlYXNlLiBIb3dldmVyLCB0aGUgcG9pbnRzIGFyZSBzY2F0dGVyZWQgd2lkZWx5LCBwYXJ0aWN1bGFybHkgYXQgbG93ZXIgbGV2ZWxzIG9mIHBvdmVydHksIHdoZXJlIGhvdXNpbmcgdmFsdWVzIHZhcnkgc2lnbmlmaWNhbnRseS4gVGhpcyBpbmRpY2F0ZXMgdGhhdCB3aGlsZSBwb3ZlcnR5IGxldmVscyBoYXZlIGEgbmVnYXRpdmUgaW1wYWN0IG9uIGhvdXNpbmcgdmFsdWVzLCB0aGUgZWZmZWN0IGlzIG5vdCB1bmlmb3JtIGFjcm9zcyBhbGwgYmxvY2sgZ3JvdXBzLiBUaGVyZSBpcyBzdWJzdGFudGlhbCB2YXJpYXRpb24gaW4gdGhlIGhvdXNpbmcgdmFsdWVzIGV2ZW4gaW4gbmVpZ2hib3Job29kcyB3aXRoIHNpbWlsYXIgcG92ZXJ0eSByYXRlcywgc3VnZ2VzdGluZyB0aGF0IG90aGVyIGZhY3RvcnMgbWF5IGJlIGF0IHBsYXkuIFRoZSBub24tbGluZWFyIHBhdHRlcm4gb2JzZXJ2ZWQgaW4gdGhpcyBncmFwaCBoaWdobGlnaHRzIHRoZSBjb21wbGV4aXR5IG9mIHBvdmVydHnigJlzIGluZmx1ZW5jZSBvbiB0aGUgaG91c2luZyBtYXJrZXQuCgpJbiBzdW1tYXJ5LCB0aGUgc2NhdHRlcnBsb3Qgc2hvd3MgdGhhdCB3aGlsZSBQQ1RCQUNITU9SIGFuZCBMTk1FREhWQUwgZXhoaWJpdCBhIHN0cm9uZyBhbmQgY2xlYXIgbGluZWFyIHJlbGF0aW9uc2hpcCwgdGhlIG90aGVyIHByZWRpY3RvcnMgLSBpbiBwYXJ0aWN1bGFyIFBDVFZBQ0FOVCBhbmQgTE5OQkVMUE9WMTAwIC0gZXhoaWJpdCBtb3JlIGNvbXBsZXggbm9uLWxpbmVhciBwYXR0ZXJucy4gVGhlIHNjYXR0ZXJwbG90cyBwcm92aWRlIGltcG9ydGFudCBpbnNpZ2h0cyBpbnRvIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzIGFuZCBob3VzaW5nIHZhbHVlcywgc3VnZ2VzdGluZyB0aGF0IHdoaWxlIHRoZSBtb2RlbCBpcyBhc3N1bWVkIHRvIGJlIGxpbmVhciwgaXQgbWF5IG5vdCBmdWxseSBjYXB0dXJlIHRoZSB1bmRlcmx5aW5nIGR5bmFtaWNzLiBGb3IgdmFyaWFibGVzIHN1Y2ggYXMgUENUVkFDQU5UIGFuZCBMTk5CRUxQT1YxMDAsIHRoZSBub25saW5lYXJpdHkgb2JzZXJ2ZWQgaW4gdGhlIHBsb3RzIHN1Z2dlc3RzIHRoYXQgbW9yZSBjb21wbGV4IG5vbmxpbmVhciBtb2RlbHMgbWF5IHByb3ZpZGUgYSBiZXR0ZXIgZml0IGFuZCBtb3JlIGFjY3VyYXRlIHByZWRpY3Rpb25zLgoKYGBge3Igc2NhdHRlcnBsb3QsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTEwLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyBzY2F0dGVycGxvdAoKcmVnX2RhdGEgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKCJQQ1RCQUNITU9SIiwgIkxOTkJFTFBPVjEwMCIsICJQQ1RWQUNBTlQiLCAiUENUU0lOR0xFUyIpLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJWYXJpYWJsZSIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJWYWx1ZSIpICU+JSAKZ2dwbG90KGFlcyh4ID0gVmFsdWUsIHkgPSBMTk1FREhWQUwpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICIjMjgzZDNiIiwgYWxwaGEgPSAwLjcsIHNpemUgPSAwLjQpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBjb2xvciA9ICIjYzQ0NTM2Iiwgc2UgPSBGQUxTRSkgKyAgIyBBZGQgYSBsaW5lYXIgcmVncmVzc2lvbiBsaW5lCiAgZmFjZXRfd3JhcCh+IFZhcmlhYmxlLCBzY2FsZXMgPSAiZnJlZSIsIGxhYmVsbGVyID0gYXNfbGFiZWxsZXIoYygKICAgICJQQ1RCQUNITU9SIiA9ICIlIHdpdGggQmFjaGVsb3LigJlzIERlZ3JlZXMgb3IgSGlnaGVyIiwKICAgICJMTk5CRUxQT1YxMDAiID0gIkhvdXNlaG9sZHMgTGl2aW5nIGluIFBvdmVydHkiLAogICAgIlBDVFZBQ0FOVCIgPSAiJSBvZiBWYWNhbnQgSG91c2VzIiwKICAgICJQQ1RTSU5HTEVTIiA9ICIlIG9mIFNpbmdsZSBIb3VzZSBVbml0cyIKICApKSkgICsKICB0aGVtZV9saWdodCgpICsgICAKICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT02KSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT02KSwgCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT04KSkgKwogIGxhYnModGl0bGUgPSAiU2NhdHRlciBQbG90cyBvZiBEZXBlbmRlbnQgVmFyaWFibGUgdnMuIFByZWRpY3RvcnMiLCAKICAgICAgIHggPSAiUHJlZGljdG9yIFZhbHVlIiwgCiAgICAgICB5ID0gIkxvZyBvZiBNZWRpYW4gSG91c2UgVmFsdWUiKQoKYGBgCgpOZXh0LCB3ZSBleGFtaW5lZCB0aGUgYXNzdW1wdGlvbiBvZiAqKm5vcm1hbGl0eSBmb3IgcmVzaWR1YWxzKiogb2YgdGhlIHJlZ3Jlc3Npb24gbW9kZWwuIFRoZSBoaXN0b2dyYW0gb2Ygc3RhbmRhcmRpemVkIHJlc2lkdWFscyBwcm92aWRlcyBhIGRldGFpbGVkIHZpZXcgb2YgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgcmVzaWR1YWxzIGZyb20gdGhlIE9MUyByZWdyZXNzaW9uIG1vZGVsLiBUaGlzIGdyYXBoIG1hcHMgdGhlIGZyZXF1ZW5jeSBvZiByZXNpZHVhbCB2YWx1ZXMgYWxvbmcgdGhlIHgtYXhpcywgd2l0aCB0aGUgcmVzaWR1YWxzIGNlbnRlcmVkIGFyb3VuZCB6ZXJvLiBUaGUgc2hhcGUgb2YgdGhlIGhpc3RvZ3JhbSBhcHByb3hpbWF0ZXMgYSBiZWxsIGN1cnZlLCB3aGljaCBpcyBjaGFyYWN0ZXJpc3RpYyBvZiBhIG5vcm1hbCBkaXN0cmlidXRpb27igJRhIGtleSBhc3N1bXB0aW9uIGZvciBPTFMgcmVncmVzc2lvbi4KClRoZSBtYWpvcml0eSBvZiB0aGUgcmVzaWR1YWxzIGFyZSBjb25jZW50cmF0ZWQgYmV0d2VlbiAtMiBhbmQgMiBvbiB0aGUgeC1heGlzLCB3aXRoIHRoZSBoaWdoZXN0IGZyZXF1ZW5jeSBvY2N1cnJpbmcgbmVhciB6ZXJvLiBUaGlzIGNvbmNlbnRyYXRpb24gc3VnZ2VzdHMgdGhhdCBtb3N0IG9mIHRoZSBwcmVkaWN0ZWQgdmFsdWVzIGFyZSBjbG9zZSB0byB0aGUgb2JzZXJ2ZWQgdmFsdWVzLCBsZWFkaW5nIHRvIHJlc2lkdWFscyB0aGF0IGFyZSBzbWFsbCBhbmQgZGlzdHJpYnV0ZWQgc3ltbWV0cmljYWxseSBhcm91bmQgemVyby4gVGhpcyBpcyBhIHBvc2l0aXZlIHNpZ24sIGFzIGl0IGluZGljYXRlcyB0aGF0IHRoZSBtb2RlbCBkb2VzIG5vdCBzeXN0ZW1hdGljYWxseSBvdmVycHJlZGljdCBvciB1bmRlcnByZWRpY3QgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSAoTE5NRURIVkFMKS4KCkF0IHRoZSBjZW50ZXIgb2YgdGhlIGRpc3RyaWJ1dGlvbiwgdGhlIHJlc2lkdWFscyBmb3JtIGEgdGFsbCwgbmFycm93IHBlYWssIHJlcHJlc2VudGluZyBhIGxhcmdlIG51bWJlciBvZiByZXNpZHVhbHMgY2xvc2UgdG8gemVyby4gVGhpcyBzdWdnZXN0cyB0aGF0IHRoZSBtb2RlbCBmaXRzIG1vc3Qgb2JzZXJ2YXRpb25zIHdlbGwuIEFzIHdlIG1vdmUgZnVydGhlciBhd2F5IGZyb20gdGhlIGNlbnRlciwgdGhlIGZyZXF1ZW5jeSBvZiByZXNpZHVhbHMgZGVjcmVhc2VzIHN5bW1ldHJpY2FsbHksIHdpdGggZmV3ZXIgcmVzaWR1YWxzIGhhdmluZyBsYXJnZSBwb3NpdGl2ZSBvciBuZWdhdGl2ZSB2YWx1ZXMuIFRoaXMgdGFwZXJpbmcgb2ZmIG9uIGJvdGggc2lkZXMgb2YgdGhlIGhpc3RvZ3JhbSBzdWdnZXN0cyB0aGF0IGV4dHJlbWUgcmVzaWR1YWxzIGFyZSByZWxhdGl2ZWx5IHJhcmUsIHdoaWNoIGlzIHR5cGljYWwgb2YgYSBub3JtYWwgZGlzdHJpYnV0aW9uLgoKSG93ZXZlciwgdGhlcmUgYXJlIHNvbWUgbm90aWNlYWJsZSBkZXZpYXRpb25zIGZyb20gcGVyZmVjdCBub3JtYWxpdHkgYXQgdGhlIHRhaWxzIG9mIHRoZSBkaXN0cmlidXRpb24uIE9uIHRoZSBsZWZ0IHNpZGUgb2YgdGhlIGdyYXBoLCB0aGVyZSBhcmUgYSBmZXcgcmVzaWR1YWxzIHdpdGggdmFsdWVzIHNtYWxsZXIgdGhhbiAtMywgYW5kIG9uIHRoZSByaWdodCBzaWRlLCB0aGVyZSBhcmUgYSBmZXcgcmVzaWR1YWxzIGxhcmdlciB0aGFuIDMuIFRoZXNlIHJlc2lkdWFscyByZXByZXNlbnQgb3V0bGllcnPigJRjYXNlcyB3aGVyZSB0aGUgbW9kZWwncyBwcmVkaWN0aW9ucyBkZXZpYXRlIHNpZ25pZmljYW50bHkgZnJvbSB0aGUgb2JzZXJ2ZWQgdmFsdWVzLiBXaGlsZSB0aGVzZSBleHRyZW1lIHZhbHVlcyBkbyBub3QgYXBwZWFyIHRvIGRvbWluYXRlIHRoZSBkaXN0cmlidXRpb24sIHRoZXkgYXJlIHdvcnRoIGZ1cnRoZXIgZXhhbWluYXRpb24sIGFzIHRoZXkgY291bGQgaW5kaWNhdGUgYXJlYXMgd2hlcmUgdGhlIG1vZGVsJ3MgYXNzdW1wdGlvbnMgYXJlIGJlaW5nIHZpb2xhdGVkIG9yIHdoZXJlIGluZmx1ZW50aWFsIHBvaW50cyBtaWdodCBiZSBhZmZlY3RpbmcgdGhlIG92ZXJhbGwgbW9kZWwgZml0LgoKSW4gc3VtbWFyeSwgdGhlIGhpc3RvZ3JhbSBvZiBzdGFuZGFyZGl6ZWQgcmVzaWR1YWxzIGluZGljYXRlcyB0aGF0IHRoZSByZXNpZHVhbHMgYXJlIGFwcHJveGltYXRlbHkgbm9ybWFsbHkgZGlzdHJpYnV0ZWQsIHdoaWNoIHN1cHBvcnRzIHRoZSBhc3N1bXB0aW9uIG9mIG5vcm1hbGl0eSBmb3IgdGhlIHJlZ3Jlc3Npb24gbW9kZWwuIEFsdGhvdWdoIHRoZXJlIGFyZSBzb21lIG91dGxpZXJzIHByZXNlbnQsIHRoZWlyIG92ZXJhbGwgaW1wYWN0IG9uIHRoZSBub3JtYWxpdHkgb2YgdGhlIHJlc2lkdWFscyBzZWVtcyBtaW5pbWFsLiBUaGUgZ2VuZXJhbCBzaGFwZSBvZiB0aGUgaGlzdG9ncmFtIHN1Z2dlc3RzIHRoYXQgdGhlIE9MUyByZWdyZXNzaW9uIG1vZGVsIGZpdHMgdGhlIGRhdGEgcmVhc29uYWJseSB3ZWxsLCB3aXRoIHJlc2lkdWFscyBtb3N0bHkgZmFsbGluZyB3aXRoaW4gYW4gYWNjZXB0YWJsZSByYW5nZSBhcm91bmQgemVyby4gCgpgYGB7ciBjb21wdXRlIHJlc2lkdWFscywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KCmZpdHRlZF92YWx1ZXMgPC0gZml0dGVkKGZpdCkKcmVzaWR1YWxzX3ZhbHVlcyA8LSByZXNpZHVhbHMoZml0KQpzdGFuZGFyZGl6ZWRfcmVzaWR1YWxzIDwtIHJzdGFuZGFyZChmaXQpCgpyZWdfZGF0YSA8LSByZWdfZGF0YSAlPiUKICBtdXRhdGUoCiAgICBGaXR0ZWQgPSBmaXR0ZWRfdmFsdWVzLAogICAgUmVzaWR1YWxzID0gcmVzaWR1YWxzX3ZhbHVlcywKICAgIFN0YW5kYXJkaXplZF9SZXNpZHVhbHMgPSBzdGFuZGFyZGl6ZWRfcmVzaWR1YWxzKQoKYGBgCgoKYGBge3IgcmVzaWR1YWwgaGlzdG9ncmFtcywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCmdncGxvdChyZWdfZGF0YSwgYWVzKHggPSBTdGFuZGFyZGl6ZWRfUmVzaWR1YWxzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbnMgPSAzMCwgZmlsbCA9ICIjMjgzZDNiIiwgYWxwaGEgPSAwLjcpICsKICBsYWJzKHRpdGxlID0gIkhpc3RvZ3JhbSBvZiBTdGFuZGFyZGl6ZWQgUmVzaWR1YWxzIiwgCiAgICAgICB4ID0gIlN0YW5kYXJkaXplZCBSZXNpZHVhbHMiLCAKICAgICAgIHkgPSAiRnJlcXVlbmN5IikgKwogIHRoZW1lX2xpZ2h0KCkgKyAgIAogIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksIAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTYpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTYpLCAKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTgpKQoKYGBgCgpGb2xsb3dpbmcgdGhlIG5vcm1hbGl0eSBjaGVjaywgd2UgZXhhbWluZWQgdGhlIGFzc3VtcHRpb24gb2YgKipob21vc2NlZGFzdGljaXR5KiosIHdoaWNoIHJlcXVpcmVzIHRoYXQgdGhlIHJlc2lkdWFscyBoYXZlIGNvbnN0YW50IHZhcmlhbmNlIGFjcm9zcyBhbGwgbGV2ZWxzIG9mIHRoZSBmaXR0ZWQgdmFsdWVzLiBUaGUgc2NhdHRlciBwbG90IG9mIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgdmVyc3VzIGZpdHRlZCB2YWx1ZXMgaXMgYSB2YWx1YWJsZSBkaWFnbm9zdGljIGZvciB0ZXN0aW5nIGVzc2VudGlhbCByZWdyZXNzaW9uIGFzc3VtcHRpb25zLCBpbmNsdWRpbmcgaG9tb3NjZWRhc3RpY2l0eSBhbmQgdGhlIHByZXNlbmNlIG9mIG91dGxpZXJzLiBUaGUgZml0dGVkIHZhbHVlcyB0aGF0IHRoZSBtb2RlbCBwcmVkaWN0cyBhcmUgcGxvdHRlZCBvbiB0aGUgeC1heGlzLCBhbmQgdGhlIHN0YW5kYXJkaXplZCByZXNpZHVhbHPigJR0aGF0IGlzLCByZXNpZHVhbHMgYWRqdXN0ZWQgYnkgdGhlaXIgc3RhbmRhcmQgZGV2aWF0aW9u4oCUYXJlIHNob3duIG9uIHRoZSB5LWF4aXMuIEJlY2F1c2Ugc3RhbmRhcmRpemVkIHJlc2lkdWFscyBnaXZlIGFuIGluZGljYXRpb24gb2YgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBlYWNoIHJlc2lkdWFsJ3MgZGl2ZXJnZW5jZSBmcm9tIHRoZSBleHBlY3RlZCB2YWx1ZSwgdGhleSBtYWtlIGl0IHNpbXBsZSB0byBpZGVudGlmeSBvdXRsaWVycyBhbmQgc2lnbmlmaWNhbnQgZGF0YSBwb2ludHMuIFJlbGF0aXZlcyBhcmUgZ2VuZXJhbGx5IHJlZ2FyZGVkIGFzIG5vcm1hbCB3aGVuIHRoZXkgZmFsbCBiZXR3ZWVuIC0yIGFuZCArMiwgYW5kIGFueXRoaW5nIG91dHNpZGUgb2YgdGhlc2UgYm91bmRzIGNhbiBsZWFkIHRvIGFub21hbG91cyBwb2ludHMgdGhhdCBjb3VsZCBoYXZlIGFuIGltcGFjdCBvbiB0aGUgbW9kZWwncyBwZXJmb3JtYW5jZS4KCkhvbW9zY2VkYXN0aWNpdHksIG9yIHRoZSBuZWVkIHRoYXQgcmVzaWR1YWxzIHNob3cgY29uc3RhbnQgdmFyaWFuY2UgYWNyb3NzIGFsbCBsZXZlbHMgb2YgZml0dGVkIHZhbHVlcywgaXMgb25lIG9mIHRoZSBmdW5kYW1lbnRhbCBwcmVzdW1wdGlvbnMgb2YgcmVncmVzc2lvbi4gVGhlIHJlc2lkdWFscyBpbiB0aGlzIHNjYXR0ZXIgcGxvdCBzaG93IG5vIGRpc2Nlcm5pYmxlIHRyZW5kIG9mIHJpc2luZyBvciBmYWxsaW5nIHZhcmlhbmNlIHdpdGggaW5jcmVhc2luZyBmaXR0ZWQgdmFsdWVzOyBpbnN0ZWFkLCB0aGV5IHNlZW0gdG8gYmUgcHJldHR5IHVuaWZvcm1seSBkaXN0cmlidXRlZCBhcm91bmQgdGhlIGhvcml6b250YWwgbGluZSBhdCB6ZXJvLiBUaGUgZmFjdCB0aGF0IHRoZXJlIGlzIG5vIG9idmlvdXMgZnVubmVsIHNoYXBlIG9yIHN5c3RlbWF0aWMgdmFyaWF0aW9uIHRyZW5kIHN1Z2dlc3RzIHRoYXQgdGhlIGFzc3VtcHRpb24gb2YgaG9tb3NjZWRhc3RpY2l0eSBpcyByZWFzb25hYmx5IHNhdGlzZmllZC4gVGhlIG5vdGlvbiBvZiBjb25zdGFudCB2YXJpYW5jZSBpcyBzdXBwb3J0ZWQgYnkgdGhlIHJlc2lkdWFscycgZ2VuZXJhbGx5IGNvbnN0YW50IHNwcmVhZCBhY3Jvc3MgdGhlIGZpdHRlZCB2YWx1ZSByYW5nZSwgd2hpY2ggaW5kaWNhdGVzIHRoYXQgdGhlIHZhcmlhbmNlIG9mIGVycm9ycyBpcyBzdGlsbCBzdGFibGUuVGhlIHN5bW1ldHJ5IG9mIHRoZSByZXNpZHVhbHMgYXJvdW5kIHRoZSB6ZXJvIGxpbmUgaXMgYW5vdGhlciBwb3NpdGl2ZSBhc3BlY3Qgb2YgdGhlIHBsb3QuIFRoaXMgc3ltbWV0cnkgbWVhbnMgdGhhdCB0aGUgbW9kZWwgZG9lcyBub3Qgc3lzdGVtYXRpY2FsbHkgb3Zlci0gb3IgdW5kZXItcHJlZGljdCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIG92ZXIgdGhlIHJhbmdlIG9mIGZpdHRlZCB2YWx1ZXMgKExOTUVESFZBTCkuIAoKSG93ZXZlciwgdGhlIHBsb3QgZG9lcyBzaG93IHNvbWUgcG90ZW50aWFsIG91dGxpZXJzLCBwYXJ0aWN1bGFybHkgdGhvc2UgcG9pbnRzIHRoYXQgYXJlIG91dHNpZGUgdGhlIHJhbmdlIG9mIHRoZSAtMyBhbmQgKzMgc3RhbmRhcmRpemVkIHJlc2lkdWFscy4gVGhlc2UgZXh0cmVtZSByZXNpZHVhbHMgYXJlIGxvY2F0ZWQgYWJvdmUgYW5kIGJlbG93IHRoZSBtYWluIHJlc2lkdWFsIGNsdXN0ZXJzIGFuZCBtYXkgaW5kaWNhdGUgdGhhdCB0aGUgbW9kZWwncyBwcmVkaWN0ZWQgdmFsdWVzIGRldmlhdGUgc2lnbmlmaWNhbnRseSBmcm9tIHRoZSBhY3R1YWwgdmFsdWVzLiBBbHRob3VnaCB0aGUgbnVtYmVyIG9mIG91dGxpZXJzIGlzIHJlbGF0aXZlbHkgc21hbGwsIHRoZWlyIHByZXNlbmNlIGluZGljYXRlcyB0aGF0IHRoZSBtb2RlbCBtYXkgbm90IGZpdCBhbGwgZGF0YSBwb2ludHMgd2VsbC4gCgpJbiBhZGRpdGlvbiwgYWx0aG91Z2ggdGhlIHJlc2lkdWFscyBhcmUgZ2VuZXJhbGx5IHdlbGwgY2x1c3RlcmVkIGFyb3VuZCB6ZXJvLCBzb21lIHNsaWdodCBkaXNwZXJzaW9uIG9jY3VycyBhcyB0aGUgZml0dGVkIHZhbHVlcyBpbmNyZWFzZSwgc3VnZ2VzdGluZyB0aGF0IHRoZSBhY2N1cmFjeSBvZiB0aGUgbW9kZWwgcHJlZGljdGlvbnMgbWF5IGRlY3JlYXNlIHNsaWdodGx5IGF0IGhpZ2hlciB2YWx1ZXMgb2YgTE5NRURIVkFMLiBUaGUgaGlnaGVyIHRoZSBmaXR0ZWQgdmFsdWUsIHRoZSBncmVhdGVyIHRoZSByZXNpZHVhbCB2YXJpYW5jZSwgd2hpY2ggbWF5IGluZGljYXRlIHRoZSBwcmVzZW5jZSBvZiBzbGlnaHQgaGV0ZXJvc2tlZGFzdGljaXR5LCBidXQgbm90IG9mIHN1ZmZpY2llbnQgc2V2ZXJpdHkgdG8gcmFpc2Ugc2lnbmlmaWNhbnQgY29uY2VybnMgYWJvdXQgdGhlIHZhbGlkaXR5IG9mIHRoZSBtb2RlbC4gSG93ZXZlciwgdGhpcyBwYXR0ZXJuIGNvdWxkIGJlIGV4cGxvcmVkIGZ1cnRoZXIgdG8gZW5zdXJlIHRoYXQgdGhlIG1vZGVsIHBlcmZvcm1zIHdlbGwgb3ZlciB0aGUgZW50aXJlIHJhbmdlIG9mIHByZWRpY3RlZCB2YWx1ZXMuCgoKYGBge3IgcmVzaWR1YWwgcGxvdCwgIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgpnZ3Bsb3QocmVnX2RhdGEsIGFlcyh4ID0gRml0dGVkLCB5ID0gU3RhbmRhcmRpemVkX1Jlc2lkdWFscykpICsKICBnZW9tX3BvaW50KGNvbG9yID0gIiMyODNkM2IiLCBhbHBoYSA9IDAuNikgKyAgICAjIFNjYXR0ZXIgcGxvdCBwb2ludHMKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICIjYzQ0NTM2IikgKyAgICMgQWRkIGEgaG9yaXpvbnRhbCBsaW5lIGF0IHkgPSAwCiAgbGFicygKICAgIHRpdGxlID0gIlNjYXR0ZXIgUGxvdCBvZiBTdGFuZGFyZGl6ZWQgUmVzaWR1YWxzIHZzIEZpdHRlZCBWYWx1ZXMiLAogICAgeCA9ICJGaXR0ZWQgVmFsdWVzIiwKICAgIHkgPSAiU3RhbmRhcmRpemVkIFJlc2lkdWFscyIKICApICsKICB0aGVtZV9saWdodCgpICsgICAKICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT02KSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT02KSwgCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT04KSkKCgpgYGAKCkFub3RoZXIgYXNzdW1wdGlvbiB3ZSB0ZXN0IGhlcmUgaXMgKippbmRlcGVuZGVuY2Ugb2Ygb2JzZXJ2YXRpb25zKiosIGVzcGVjaWFsbHkgc3BhdGlhbCBhdXRvY29ycmVsYXRpb25zLiBJbiB0aGUgbWFwIG9mIExOTUVESFZBTCAobG9nLXRyYW5zZm9ybWVkIG1lZGlhbiBob3VzZSB2YWx1ZXMpLCB0aGVyZSBhcHBlYXJzIHRvIGJlIGEgc3BhdGlhbCBwYXR0ZXJuLCB3aXRoIGhpZ2hlciB2YWx1ZXMgY29uY2VudHJhdGVkIGluIGNlcnRhaW4gYXJlYXMsIHN1Y2ggYXMgQ2VudGVyIENpdHkgYW5kIG90aGVyIGFmZmx1ZW50IG5laWdoYm9yaG9vZHMsIGFuZCBsb3dlciB2YWx1ZXMgY2x1c3RlcmVkIGluIG1vcmUgZWNvbm9taWNhbGx5IGRpc3RyZXNzZWQgYXJlYXMuIFRoaXMgc3VnZ2VzdHMgdGhhdCB0aGUgaG91c2luZyBtYXJrZXQgaXMgbm90IHNwYXRpYWxseSByYW5kb20gYW5kIHRoYXQgbmVhcmJ5IGJsb2NrIGdyb3VwcyB0ZW5kIHRvIGhhdmUgc2ltaWxhciBob3VzZSB2YWx1ZXMuIAoKU2ltaWxhcmx5LCB0aGUgbWFwIG9mIFBDVFZBQ0FOVCAocHJvcG9ydGlvbiBvZiB2YWNhbnQgaG91c2luZyB1bml0cykgc2hvd3MgY2xlYXIgZ2VvZ3JhcGhpYyBjbHVzdGVycywgd2l0aCBoaWdoZXIgdmFjYW5jeSByYXRlcyBjb25jZW50cmF0ZWQgaW4gY2VydGFpbiBwYXJ0cyBvZiB0aGUgY2l0eSwgcGFydGljdWxhcmx5IGluIGFyZWFzIGV4cGVyaWVuY2luZyBlY29ub21pYyBkZWNsaW5lLiBGb3IgUENUU0lOR0xFUyAocHJvcG9ydGlvbiBvZiBzaW5nbGUtZmFtaWx5IGhvbWVzKSwgdGhlIG1hcHMgcmV2ZWFsIHNwYXRpYWwgcGF0dGVybnMgYXMgd2VsbCwgd2l0aCBibG9jayBncm91cHMgY2hhcmFjdGVyaXNlZCBieSBhIGhpZ2ggcHJvcG9ydGlvbiBvZiBzaW5nbGUtZmFtaWx5IGhvbWVzLCBvZnRlbiBsb2NhdGVkIGluIHJlc2lkZW50aWFsIGFyZWFzIG9uIHRoZSBvdXRza2lydHMgb2YgYSBzdWJ1cmIgb3IgY2l0eS4gVGhlIFBDVEJBQ0hNT1IgKHByb3BvcnRpb24gb2YgUmVzaWRlbnRzIHdpdGggYXQgbGVhc3QgYSBCYWNoZWxvcidzIERlZ3JlZSkgbWFwIHNob3dzIGEgc3Ryb25nIHNwYXRpYWwgcGF0dGVybiwgd2l0aCBoaWdoZXIgbGV2ZWxzIG9mIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgY29uY2VudHJhdGVkIGluIHRoZSBtb3JlIGFmZmx1ZW50IGNlbnRyYWwgYXJlYXMgb2YgdGhlIGNpdHksIHdoaWxlIGxvd2VyIGxldmVscyBvZiBlZHVjYXRpb25hbCBhdHRhaW5tZW50IGFyZSBjb25jZW50cmF0ZWQgaW4gdGhlIHBlcmlwaGVyYWwgYXJlYXMsIHdoaWNoIGhhdmUgZmV3ZXIgZWNvbm9taWMgcmVzb3VyY2VzLiBVbnN1cnByaXNpbmdseSwgVGhlIExOTkJFTFBPVjEwMCAobG9nLXRyYW5zZm9ybWVkIG51bWJlciBvZiBob3VzZWhvbGRzIGxpdmluZyBiZWxvdyB0aGUgcG92ZXJ0eSBsaW5lKSBtYXAgc2hvd3MgdGhhdCBpbiBzb21lIHBhcnRzIG9mIHRoZSBjaXR5LCBwYXJ0aWN1bGFybHkgaW4gZWNvbm9taWNhbGx5IGRpc3RyZXNzZWQgbmVpZ2hib3Job29kcywgdGhlcmUgaXMgYSBjbGVhciBjb25jZW50cmF0aW9uIG9mIGhvdXNlaG9sZHMgd2l0aCBoaWdoZXIgcG92ZXJ0eSByYXRlcy4gQWxsIG9mIHRoZXNlIHN1Z2dlc3RzIHRoYXQgb2JzZXJ2YXRpb25zIChibG9jayBncm91cHMpIGFyZSBub3QgaW5kZXBlbmRlbnQgb2YgZWFjaCBvdGhlciBhbmQgaXQgaXMgaW1wb3J0YW50IHRvIGFjY291bnQgZm9yIHN1Y2ggZGVwZW5kZW5jaWVzIGluIHRoZSBtb2RlbCB0aHJvdWdoIGdlb2dyYXBoaWMgd2VpZ2h0ZWQgcmVncmVzc2lvbiB0ZWNobmlxdWVzLiAKCgpgYGB7ciByZXNpZHVhbCBtYXBzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKcGhpbGx5ICU+JQogIGxlZnRfam9pbihyZWdfZGF0YSAlPiUgZHBseXI6OnNlbGVjdChjKFBPTFlfSUQsIFN0YW5kYXJkaXplZF9SZXNpZHVhbHMpKSwgYnkgPSAiUE9MWV9JRCIpICU+JSAKICBnZ3Bsb3QoLikgKwogIGdlb21fc2YoYWVzKGZpbGwgPSBTdGFuZGFyZGl6ZWRfUmVzaWR1YWxzKSwgY29sb3IgPSAidHJhbnNwYXJlbnQiKSArICAjIFVzZSBnZW9tX3NmIHRvIG1hcCB0aGUgcG9seWdvbnMKICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvcnMgPSBjKCIjRkFGOUY2IiwgIiNjNDQ1MzYiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJTdGQgUmVzaWR1YWxzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgbmEudmFsdWUgPSAidHJhbnNwYXJlbnQiKSArICAjIENob29zZSBhIGNvbG9yIHBhbGV0dGUsIGludmVydCBkaXJlY3Rpb24gaWYgbmVlZGVkCiAgbGFicyh0aXRsZSA9ICJDaG9yb3BsZXRoIE1hcCBvZiBTdGFuZGFyZGl6ZWQgUmVzaWR1YWxzIikgKwogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJncmV5IiwgZmlsbCA9IE5BLCBzaXplID0gMC44KSkKCgoKYGBgCgpUaGUgY2hvcm9wbGV0aCBtYXAgb2Ygc3RhbmRhcmRpemVkIHJlZ3Jlc3Npb24gcmVzaWR1YWxzIHByb3ZpZGVzIGEgZGV0YWlsZWQgZ2VvZ3JhcGhpYyBicmVha2Rvd24gb2YgaG93IHdlbGwgdGhlIE9MUyByZWdyZXNzaW9uIG1vZGVsIGZpdHMgdGhlIGRhdGEgYWNyb3NzIGRpZmZlcmVudCBhcmVhcyBvZiB0aGUgY2l0eS4gVGhlIG1hcCB1c2VzIGEgY29sb3IgZ3JhZGllbnQgdG8gcmVwcmVzZW50IHRoZSBtYWduaXR1ZGUgb2YgdGhlIHJlc2lkdWFscywgd2l0aCBkYXJrZXIgcmVkIHNoYWRlcyBpbmRpY2F0aW5nIGxhcmdlIHBvc2l0aXZlIHJlc2lkdWFscyAod2hlcmUgdGhlIG1vZGVsIHVuZGVyZXN0aW1hdGVzIHRoZSBhY3R1YWwgdmFsdWVzKSwgYW5kIGxpZ2h0ZXIgc2hhZGVzICh0b3dhcmQgd2hpdGUpIGluZGljYXRpbmcgbGFyZ2UgbmVnYXRpdmUgcmVzaWR1YWxzICh3aGVyZSB0aGUgbW9kZWwgb3ZlcmVzdGltYXRlcyB0aGUgYWN0dWFsIHZhbHVlcykuIAoKSW4gdGhlIG5vcnRod2VzdGVybiBwYXJ0IG9mIHRoZSBjaXR5LCBwYXJ0aWN1bGFybHkgYWxvbmcgc29tZSBvZiB0aGUgbW9yZSBzdWJ1cmJhbiBhbmQgYWZmbHVlbnQgYXJlYXMsIGRhcmsgcmVkIHNoYWRpbmcgaW5kaWNhdGVzIGxhcmdlIHBvc2l0aXZlIHJlc2lkdWFscy4gVGhpcyBzdWdnZXN0cyB0aGF0IHRoZSBtb2RlbCB1bmRlcmVzdGltYXRlcyBob3VzaW5nIHZhbHVlcyBpbiB0aGVzZSBuZWlnaGJvcmhvb2RzLiBUaGVzZSBhcmVhcyBhcmUgb2Z0ZW4gY2hhcmFjdGVyaXplZCBieSBoaWdoZXItaW5jb21lIGhvdXNlaG9sZHMgYW5kIGxhcmdlciBzaW5nbGUtZmFtaWx5IGhvbWVzLCBzdWdnZXN0aW5nIHRoYXQgdGhlIG1vZGVsIG1heSBub3QgZnVsbHkgY2FwdHVyZSB0aGUgaGlnaGVyIG1hcmtldCB2YWx1ZSB0cmVuZHMgaW4gdGhlc2UgcmVnaW9ucywgcG9zc2libHkgZHVlIHRvIHVuYWNjb3VudGVkIGZhY3RvcnMgbGlrZSBwcm94aW1pdHkgdG8gaGlnaC1kZW1hbmQgYW1lbml0aWVzIG9yIHNwZWNpZmljIG5laWdoYm9yaG9vZCBmZWF0dXJlcyB0aGF0IGluZmx1ZW5jZSBwcm9wZXJ0eSB2YWx1ZXMuCgpJbiBjb250cmFzdCwgaW4gcGFydHMgb2YgU291dGggYW5kIFNvdXRod2VzdCBQaGlsYWRlbHBoaWEsIGFzIHdlbGwgYXMgcGFydHMgb2YgTm9ydGggUGhpbGFkZWxwaGlhLCBsaWdodGVyIHNoYWRlZCBhcmVhcyBpbmRpY2F0ZSBsYXJnZSBuZWdhdGl2ZSByZXNpZHVhbHMuIEhlcmUsIHRoZSBtb2RlbCB0ZW5kcyB0byBvdmVyZXN0aW1hdGUgaG91c2luZyB2YWx1ZXMsIG1lYW5pbmcgdGhhdCB0aGUgcHJlZGljdGVkIHZhbHVlcyBhcmUgaGlnaGVyIHRoYW4gdGhlIGFjdHVhbCBvYnNlcnZlZCB2YWx1ZXMuIFRoZXNlIG5laWdoYm9yaG9vZHMgbWF5IGJlIGZhY2luZyBlY29ub21pYyBjaGFsbGVuZ2VzLCBzdWNoIGFzIGhpZ2hlciB2YWNhbmN5IHJhdGVzLCBsb3dlciBob3VzZWhvbGQgaW5jb21lcywgb3IgcG92ZXJ0eSwgd2hpY2ggdGhlIG1vZGVsIGhhcyBkaWZmaWN1bHR5IGZ1bGx5IGNhcHR1cmluZyB0aHJvdWdoIHRoZSBzZWxlY3RlZCBwcmVkaWN0b3JzLiBUaGUgcmVzaWR1YWxzIGluIHRoZXNlIGFyZWFzIHN1Z2dlc3QgdGhhdCBob3VzaW5nIG1hcmtldHMgaW4gdGhlc2UgbmVpZ2hib3Job29kcyBhcmUgbW9yZSBjb21wbGV4IGFuZCBpbmZsdWVuY2VkIGJ5IGxvY2FsaXplZCBmYWN0b3JzIG5vdCBmdWxseSByZXByZXNlbnRlZCBpbiB0aGUgcmVncmVzc2lvbiBtb2RlbCwgc3VjaCBhcyBoaWdoZXIgbGV2ZWxzIG9mIGVjb25vbWljIGRpc3RyZXNzIG9yIG5laWdoYm9yaG9vZCBkaXNpbnZlc3RtZW50LgoKU29tZSBuZWlnaGJvcmhvb2RzIG5lYXIgQ2VudGVyIENpdHkgZGlzcGxheSBtb3JlIG5ldXRyYWwgcmVzaWR1YWxzLCB3aGVyZSB0aGUgbW9kZWwncyBwcmVkaWN0aW9ucyBhcmUgcmVsYXRpdmVseSBhY2N1cmF0ZSwgd2l0aCB2YWx1ZXMgY2xvc2VyIHRvIHplcm8uIFRoZXNlIGFyZWFzIGFwcGVhciBpbiBsaWdodGVyIHJlZCBvciBwaW5rIHNoYWRlcywgaW5kaWNhdGluZyB0aGF0IHRoZSBtb2RlbCBpcyBwZXJmb3JtaW5nIHJlYXNvbmFibHkgd2VsbCBpbiB0aGVzZSBwYXJ0cyBvZiB0aGUgY2l0eS4gVGhpcyBtYXkgYmUgYmVjYXVzZSB0aGUgY2VudHJhbCBhcmVhcyBhcmUgbW9yZSBob21vZ2VuZW91cyBpbiB0ZXJtcyBvZiBob3VzaW5nIHZhbHVlcyBhbmQgbW9yZSBsaWtlbHkgdG8gYWxpZ24gd2l0aCB0aGUgdHJlbmRzIGNhcHR1cmVkIGJ5IHRoZSBtb2RlbCdzIHByZWRpY3RvcnMsIHN1Y2ggYXMgZWR1Y2F0aW9uIGxldmVscyBhbmQgdmFjYW5jeSByYXRlcy4KClRoZSBvdmVyYWxsIHBhdHRlcm4gb2JzZXJ2ZWQgaW4gdGhlIG1hcCBzdWdnZXN0cyBzcGF0aWFsIGNsdXN0ZXJpbmcsIGFzIGJsb2NrIGdyb3VwcyB3aXRoIHNpbWlsYXIgcmVzaWR1YWwgdmFsdWVzIHRlbmQgdG8gYmUgZ2VvZ3JhcGhpY2FsbHkgY2xvc2UgdG8gZWFjaCBvdGhlci4gVGhlIG1vZGVsIHRlbmRzIHRvIHVuZGVyZXN0aW1hdGUgaG91c2luZyB2YWx1ZXMgaW4gbW9yZSBhZmZsdWVudCBzdWJ1cmJzIGFuZCBvdmVyZXN0aW1hdGUgaG91c2luZyB2YWx1ZXMgaW4gZWNvbm9taWNhbGx5IGRpc3RyZXNzZWQgY29tbXVuaXRpZXMuIFRoaXMgaGlnaGxpZ2h0cyB0aGUgbmVlZCBmb3IgZnVydGhlciBpbXByb3ZlbWVudCB0byBhZGRyZXNzIHNwYXRpYWwgYXV0by1jb3JyZWxhdGlvbnMuIAoKIyMgQWRkaXRpb25hbCBBbmFseXNlcwoKV2UgcGVyZm9ybWVkIHN0ZXB3aXNlIHJlZ3Jlc3Npb24gdG8gZGV0ZXJtaW5lIHRoZSBtb3N0IHJlbGV2YW50IHByZWRpY3RvcnMgZm9yIHRoZSBtb2RlbC4gVGhlIGluaXRpYWwgbW9kZWwgaW5jbHVkZWQgYWxsIGZvdXIgcHJlZGljdG9ycywgd2l0aCBhIHJlc2lkdWFsIHN1bSBvZiBzcXVhcmVzIChSU1MpIG9mIDIzMC4zNCBhbmQgYW4gQWthaWtlIEluZm9ybWF0aW9uIENyaXRlcmlvbiAoQUlDKSBvZiAtMzQ0OC4wNywgd2hlcmUgYSBsb3dlciBBSUMgaW5kaWNhdGVzIGEgYmV0dGVyIGJhbGFuY2UgYmV0d2VlbiBnb29kbmVzcyBvZiBmaXQgYW5kIG1vZGVsIGNvbXBsZXhpdHkuCgpEdXJpbmcgdGhlIHN0ZXB3aXNlIHByb2NlZHVyZSwgdGhlIHByb2Nlc3MgZXhhbWluZWQgd2hldGhlciByZW1vdmluZyBlYWNoIHByZWRpY3RvciB3b3VsZCByZWR1Y2UgdGhlIEFJQyBhbmQgaW1wcm92ZSB0aGUgbW9kZWwuIEhvd2V2ZXIsIHJlbW92aW5nIGFueSBwcmVkaWN0b3IgcmVzdWx0ZWQgaW4gYSBoaWdoZXIgQUlDIGFuZCBhbiBpbmNyZWFzZSBpbiBSU1MsIGluZGljYXRpbmcgYSBwb29yZXIgbW9kZWwgZml0LiBGb3IgaW5zdGFuY2UsIHJlbW92aW5nIFBDVFNJTkdMRVMgaW5jcmVhc2VkIHRoZSBSU1MgdG8gMjMyLjc1IGFuZCB0aGUgQUlDIHRvIC0zNDMyLjIsIHdoaWxlIHJlbW92aW5nIExOTkJFTFBPVjEwMCBpbmNyZWFzZWQgdGhlIFJTUyB0byAyNDIuMDQgYW5kIHRoZSBBSUMgdG8gLTMzNjQuOS4gUmVtb3ZpbmcgUENUVkFDQU5UIGhhZCBhIG1vcmUgc3Vic3RhbnRpYWwgaW1wYWN0LCBpbmNyZWFzaW5nIHRoZSBSU1MgdG8gMjgxLjg5IGFuZCB0aGUgQUlDIHRvIC0zMTAyLjcuIEZpbmFsbHksIHJlbW92aW5nIFBDVEJBQ0hNT1IgY2F1c2VkIHRoZSBSU1MgdG8ganVtcCB0byA0MjkuMzYgYW5kIHRoZSBBSUMgdG8gLTIzNzkuMCwgaW5kaWNhdGluZyBhIHNldmVyZSBkZWNsaW5lIGluIG1vZGVsIHBlcmZvcm1hbmNlLgoKR2l2ZW4gdGhlc2UgcmVzdWx0cywgbm9uZSBvZiB0aGUgcHJlZGljdG9ycyB3ZXJlIHJlbW92ZWQsIGFzIGVsaW1pbmF0aW5nIGFueSBvZiB0aGVtIHdvcnNlbmVkIHRoZSBmaXQgb2YgdGhlIG1vZGVsLiBUaGVyZWZvcmUsIHRoZSBmaW5hbCBtb2RlbCByZW1haW5lZCB1bmNoYW5nZWQgZnJvbSB0aGUgaW5pdGlhbCBvbmUsIGluY2x1ZGluZyBhbGwgZm91ciBwcmVkaWN0b3JzLiBUaGUgZmluYWwgbW9kZWwgaGFkIGEgcmVzaWR1YWwgZGV2aWFuY2Ugb2YgMjMwLjM0IGFuZCBhbiBBSUMgb2YgLTM0NDguMDcsIGluZGljYXRpbmcgdGhhdCB0aGUgbW9kZWwgc3VjY2Vzc2Z1bGx5IGJhbGFuY2VkIGNvbXBsZXhpdHkgd2l0aCBmaXQuCgpgYGB7ciBzdGVwd2lzZSByZWdyZXNzaW9uLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKc3RlcHdpc2VfbW9kZWwgPC0gIHN0ZXBBSUMoZml0LCBkaXJlY3Rpb24gPSAiYm90aCIpCnN0ZXB3aXNlX21vZGVsJGFub3ZhCgpgYGAKCldlIHBlcmZvcm1lZCBjcm9zcy12YWxpZGF0aW9uIHRvIGFzc2VzcyB0aGUgbW9kZWwncyBwcmVkaWN0aXZlIGFjY3VyYWN5IGFuZCBkZXRlcm1pbmUgd2hldGhlciBhIHJlZHVjZWQgbW9kZWwgd2l0aCBmZXdlciBwcmVkaWN0b3JzIGNvdWxkIHByb3ZpZGUgc2ltaWxhciBwZXJmb3JtYW5jZS4gVGhlIG9yaWdpbmFsIG1vZGVsLCB3aGljaCBpbmNsdWRlcyBhbGwgZm91ciBwcmVkaWN0b3JzLCBoYXMgYSBsb3dlciBSTVNFICgwLjM2NzYpIGNvbXBhcmVkIHRvIHRoZSByZWR1Y2VkIG1vZGVsIHdpdGggb25seSB0d28gcHJlZGljdG9ycyAoMC40NDI0KS4gVGhpcyBpbmRpY2F0ZXMgdGhhdCB0aGUgb3JpZ2luYWwgbW9kZWwgcHJvdmlkZXMgYmV0dGVyIHByZWRpY3RpdmUgYWNjdXJhY3kuIFRoZSBpbmNyZWFzZSBpbiBSTVNFIHdoZW4gcmVtb3ZpbmcgdGhlIGFkZGl0aW9uYWwgcHJlZGljdG9ycyAoUENUU0lOR0xFUyBhbmQgTE5OQkVMUE9WMTAwKSBzdWdnZXN0cyB0aGF0IGV4Y2x1ZGluZyB0aGVzZSB2YXJpYWJsZXMgcmVzdWx0cyBpbiBhIGxlc3MgYWNjdXJhdGUgbW9kZWwuIE92ZXJhbGwsIHRoZSBvcmlnaW5hbCBtb2RlbCBvdXRwZXJmb3JtcyB0aGUgcmVkdWNlZCBtb2RlbCwgZGVtb25zdHJhdGluZyB0aGF0IGFsbCBmb3VyIHByZWRpY3RvcnMgY29udHJpYnV0ZSB0byBpbXByb3ZlZCBtb2RlbCBhY2N1cmFjeS4KCmBgYHtyIGNyb3NzIHZhbGlkYXRpb24sIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0KCmxtIDwtICB0cmFpbkNvbnRyb2wobWV0aG9kID0gImN2IiwgbnVtYmVyID0gNSkKCmN2bG1fbW9kZWwgPC0gdHJhaW4oTE5NRURIVkFMIH4gUENUVkFDQU5UICsgUENUU0lOR0xFUyArIFBDVEJBQ0hNT1IgKyBMTk5CRUxQT1YxMDAsIGRhdGE9cmVnX2RhdGEsIG1ldGhvZCA9ICJsbSIsIHRyQ29udHJvbCA9IGxtKQoKcHJpbnQoY3ZsbV9tb2RlbCkKCmBgYAoKCmBgYHtyIHJlZHVjZSBjdiBtb2RlbCxtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKY3ZsbV9tb2RlbF9yZWR1Y2VkID0gdHJhaW4oTE5NRURIVkFMIH4gUENUVkFDQU5UICsgTUVESEhJTkMsIGRhdGEgPSByZWdfZGF0YSwgbWV0aG9kID0gImxtIiwgdHJDb250cm9sID0gbG0pCgpwcmludChjdmxtX21vZGVsX3JlZHVjZWQpCmBgYAoKIyBEaXNjdXNzaW9uIGFuZCBMaW1pdGF0aW9ucwoKSW4gc3VtbWFyeSwgaW4gdGhpcyByZXBvcnQsIHdlIGNvbmR1Y3RlZCBhIG11bHRpcGxlIHJlZ3Jlc3Npb24gdG8gZXhhbWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gbWVkaWFuIGhvdXNlIHZhbHVlICh0aGUgZGVwZW5kZW50IHZhcmlhYmxlKSBhbmQgZm91ciBpbmRlcGVuZGVudCB2YXJpYWJsZXM6IHZhY2FuY3kgcmF0ZXMgKFBDVFZBQ0FOVCksIHBlcmNlbnRhZ2Ugb2Ygc2luZ2xlLWZhbWlseSBob3VzaW5nIChQQ1RTSU5HTEVTKSwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCAoUENUQkFDSE1PUiksIGFuZCBwb3ZlcnR5IGxldmVscyAoTE5OQkVMUE9WMTAwKS4gCgpPdXIgZmluZGluZ3Mgc2hvdyB0aGF0IGFsbCBmb3VyIHByZWRpY3RvcnMgd2VyZSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LiBTcGVjaWZpY2FsbHksIHZhY2FuY3kgcmF0ZXMgYW5kIHBvdmVydHkgbGV2ZWxzIGhhZCBhIG5lZ2F0aXZlIGltcGFjdCBvbiBtZWRpYW4gaG91c2UgdmFsdWUsIHdoaWxlIHNpbmdsZS1mYW1pbHkgaG91c2luZyBhbmQgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCBoYWQgYSBwb3NpdGl2ZSBpbmZsdWVuY2UuIFRoZSBmYWN0IHRoYXQgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB3YXMgaGlnaGx5IHNpZ25pZmljYW50IGFuZCBwb3NpdGl2ZWx5IHJlbGF0ZWQgdG8gaG91c2UgdmFsdWUgaXMgbm90IHN1cnByaXNpbmcsIGFzIGFyZWFzIHdpdGggaGlnaGVyIGVkdWNhdGlvbiBsZXZlbHMgdGVuZCB0byBhdHRyYWN0IGhpZ2hlci1pbmNvbWUgaG91c2Vob2xkcy4gU2ltaWxhcmx5LCB0aGUgbmVnYXRpdmUgZWZmZWN0IG9mIHZhY2FuY3kgcmF0ZXMgYW5kIHBvdmVydHkgbGV2ZWxzIGFsaWducyB3aXRoIGV4cGVjdGF0aW9ucywgYXMgdGhlc2UgZmFjdG9ycyB0eXBpY2FsbHkgbG93ZXIgcHJvcGVydHkgdmFsdWVzLgoKVGhlIG92ZXJhbGwgcXVhbGl0eSBvZiB0aGUgbW9kZWwgd2FzIGdvb2QsIHdpdGggYW4gJFJeMiQgdmFsdWUgb2YgMC42NjIzLCBpbmRpY2F0aW5nIHRoYXQgYXBwcm94aW1hdGVseSA2NiUgb2YgdGhlIHZhcmlhbmNlIGluIG1lZGlhbiBob3VzZSB2YWx1ZSB3YXMgZXhwbGFpbmVkIGJ5IHRoZSBwcmVkaWN0b3JzLiBBZGRpdGlvbmFsbHksIHRoZSBGLXJhdGlvIHRlc3QsIHdpdGggaXRzIGV4dHJlbWVseSBsb3cgcC12YWx1ZSwgY29uZmlybXMgdGhhdCB0aGUgbW9kZWwgYXMgYSB3aG9sZSBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGFuZCB0aGF0IGF0IGxlYXN0IG9uZSBwcmVkaWN0b3IgaGFzIGEgc2lnbmlmaWNhbnQgaW1wYWN0IG9uIHRoZSBvdXRjb21lLiAKClRocm91Z2ggc3RlcHdpc2UgcmVncmVzc2lvbiByZXN1bHRzLCBhbGwgZm91ciBwcmVkaWN0b3JzIHdlcmUgcmV0YWluZWQgaW4gdGhlIGZpbmFsIG1vZGVsLiBUaGlzIGluZGljYXRlcyB0aGF0IGVhY2ggb2YgdGhlc2UgdmFyaWFibGVzIGNvbnRyaWJ1dGVzIG1lYW5pbmdmdWxseSB0byBleHBsYWluaW5nIHRoZSB2YXJpYXRpb24gaW4gbWVkaWFuIGhvdXNlIHZhbHVlLCBhbmQgbm9uZSB3ZXJlIGRlZW1lZCB1bm5lY2Vzc2FyeSBiYXNlZCBvbiB0aGUgc3RlcHdpc2Ugc2VsZWN0aW9uIHByb2Nlc3MuV2hlbiBleGFtaW5pbmcgdGhlIGNyb3NzLXZhbGlkYXRpb24gcmVzdWx0cyB1c2luZyBSTVNFIChSb290IE1lYW4gU3F1YXJlIEVycm9yKSwgdGhlIGZvdXItcHJlZGljdG9yIG1vZGVsIGdlbmVyYWxseSBzaG93ZWQgYSBiZXR0ZXIgZml0IGNvbXBhcmVkIHRvIGEgc2ltcGxlciBtb2RlbCB3aXRoIGZld2VyIHByZWRpY3RvcnMuIFRoaXMgc3VnZ2VzdHMgdGhhdCBpbmNsdWRpbmcgYWxsIGZvdXIgcHJlZGljdG9ycyBsZWFkcyB0byBtb3JlIGFjY3VyYXRlIHByZWRpY3Rpb25zIGFuZCBiZXR0ZXIgb3ZlcmFsbCBtb2RlbCBwZXJmb3JtYW5jZS4gCgpXaGlsZSB0aGUgZm91ci1wcmVkaWN0b3IgbW9kZWwgc2hvd3MgYmV0dGVyIHByZWRpY3RpdmUgYWNjdXJhY3ksIHRoZXJlIGFyZSBsaWtlbHkgb3RoZXIgdmFyaWFibGVzIHRoYXQgY291bGQgZW5oYW5jZSB0aGUgbW9kZWzigJlzIGV4cGxhbmF0b3J5IHBvd2VyIGlmIGluY2x1ZGVkLiBGb3IgaW5zdGFuY2UsIGZhY3RvcnMgbGlrZSBjcmltZSByYXRlcywgdHJhbnNwb3J0YXRpb24gYWNjZXNzaWJpbGl0eSwgYW5kIHByb3hpbWl0eSB0byBhbWVuaXRpZXMgKHN1Y2ggYXMgcGFya3MsIHNjaG9vbHMsIGFuZCBzaG9wcGluZyBjZW50ZXJzKSBhcmUgY29tbW9ubHkgYXNzb2NpYXRlZCB3aXRoIGhvdXNpbmcgdmFsdWVzLiBTcGF0aWFsIGF1dG9jb3JyZWxhdGlvbiwgYXMgc3VnZ2VzdGVkIGJ5IHRoZSBjaG9yb3BsZXRoIG1hcHMsIGluZGljYXRlcyB0aGF0IGhvdXNlIHByaWNlcyB0ZW5kIHRvIGNsdXN0ZXIgZ2VvZ3JhcGhpY2FsbHnigJRuZWFyYnkgcHJvcGVydGllcyBvZnRlbiBoYXZlIHNpbWlsYXIgdmFsdWVzLiBUaGlzIHNwYXRpYWwgZGVwZW5kZW5jeSBzdWdnZXN0cyB0aGF0IGluY2x1ZGluZyBuZWlnaGJvcmhvb2Qgb3IgbG9jYXRpb24tYmFzZWQgdmFyaWFibGVzLCBvciBldmVuIGFwcGx5aW5nIHNwYXRpYWwgbGFnIHJlZ3Jlc3Npb24sIGNvdWxkIGJldHRlciBjYXB0dXJlIHRoZSBjbHVzdGVyZWQgbmF0dXJlIG9mIGhvdXNlIHByaWNlcy4gSG91c2luZyB2YWx1ZXMgYWxzbyBkZXBlbmQgb24gdGhlIGNoYXJhY3RlcmlzdGljcyBvZiB0aGUgaG91c2UgaXRzZWxmLCBzdWNoIGFzIGFnZSwgc2l6ZSwgc3RvcmFnZSBvcHRpb25zLCBhbmQgdGhlIHByZXNlbmNlIG9mIGFtZW5pdGllcyBsaWtlIHBhcmtpbmcgb3IgZ3JlZW4gc3BhY2UuIEFkZGl0aW9uYWxseSwgbG9jYWwgZW52aXJvbm1lbnRhbCBmYWN0b3JzLCBzdWNoIGFzIHByb3hpbWl0eSB0byBoaWdoLWNyaW1lIGFyZWFzIG9yIG5vaXNlIHBvbGx1dGlvbiwgY2FuIGltcGFjdCBwcm9wZXJ0eSB2YWx1ZXMuIFlldCwgbWFueSBvZiB0aGVzZSB2YXJpYWJsZXMgYXJlIG9mdGVuIGNvcnJlbGF0ZWQgd2l0aCBlYWNoIG90aGVyIChlLmcuLCB0cmFuc3BvcnRhdGlvbiBhY2Nlc3MgYW5kIGNyaW1lIHJhdGVzKSwgc28gY2FyZSBtdXN0IGJlIHRha2VuIGluIHNlbGVjdGluZyB3aGljaCBwcmVkaWN0b3JzIHRvIGluY2x1ZGUgdG8gYXZvaWQgbXVsdGljb2xsaW5lYXJpdHkuIAoKSW4gYWRkaXRpb24gdG8gdGhpcyBsaW1pdGF0aW9uIG9mIG5vdCBpbmNsdWRpbmcgc29tZSBwb3RlbnRpYWxseSBpbXBvcnRhbnQgcHJlZGljdG9ycywgd2UgaGF2ZSB0byBhY2tub3dsZWRnZSB0aGVyZSBhcmUgc29tZSBvdGhlciBsaW1pdGF0aW9ucyBpbiB0ZXJtcyBvZiBtZWV0aW5nIHRoZSByZWdyZXNzaW9uIGFzc3VtcHRpb25zLiBPbmUga2V5IGFzc3VtcHRpb24gb2YgT0xTIHJlZ3Jlc3Npb24gaXMgdGhhdCBsaW5lYXIgcmVsYXRpb25zaGlwcyBleGlzdCBiZXR3ZWVuIHRoZSBkZXBlbmRlbnQgYW5kIGluZGVwZW5kZW50IHZhcmlhYmxlcy4gV2hpbGUgdGhlIHNjYXR0ZXIgcGxvdHMgc2hvd2VkIHRoYXQgUENUQkFDSE1PUiBoYWQgYSBjbGVhciBsaW5lYXIgcmVsYXRpb25zaGlwIHdpdGggbWVkaWFuIGhvdXNlIHZhbHVlLCB0aGUgcmVsYXRpb25zaGlwcyBmb3IgUENUVkFDQU5ULCBQQ1RTSU5HTEVTLCBhbmQgTE5OQkVMUE9WMTAwIHdlcmUgbW9yZSBjb21wbGV4IGFuZCBub3QgZW50aXJlbHkgbGluZWFyLiBUaGlzIHN1Z2dlc3RzIHRoYXQgdGhlIG1vZGVsIG1heSBub3QgZnVsbHkgY2FwdHVyZSB0aGUgdW5kZXJseWluZyBkeW5hbWljcyBvZiB0aGVzZSBwcmVkaWN0b3JzIGFuZCB0aGVpciBpbXBhY3Qgb24gaG91c2UgdmFsdWVzLiAKCkFub3RoZXIga2V5IGFzc3VtcHRpb24gaXMgdGhlIGluZGVwZW5kZW5jZSBvZiBvYnNlcnZhdGlvbnMsIHdoaWNoIGlzIHZpb2xhdGVkIGR1ZSB0byBzcGF0aWFsIGF1dG9jb3JyZWxhdGlvbi4gVGhpcyBzdWdnZXN0cyB0aGF0IHRoZSBtb2RlbCBtYXkgbm90IGZ1bGx5IGFjY291bnQgZm9yIHRoZSBzcGF0aWFsIGRlcGVuZGVuY2llcyBpbiB0aGUgZGF0YSwgd2hpY2ggY291bGQgbGVhZCB0byBiaWFzZWQgcGFyYW1ldGVyIGVzdGltYXRlcyBhbmQgaW5hY2N1cmF0ZSBwcmVkaWN0aW9ucy4gVG8gYWRkcmVzcyB0aGlzIGxpbWl0YXRpb24sIGZ1dHVyZSBhbmFseXNlcyBjb3VsZCBleHBsb3JlIHNwYXRpYWwgcmVncmVzc2lvbiB0ZWNobmlxdWVzLCBzdWNoIGFzIHNwYXRpYWwgbGFnIG9yIHNwYXRpYWwgZXJyb3IgbW9kZWxzLCB0byBhY2NvdW50IGZvciBzcGF0aWFsIGF1dG9jb3JyZWxhdGlvbiBhbmQgaW1wcm92ZSBtb2RlbCBwZXJmb3JtYW5jZS4KCk9uIHRvcCBvZiB0aGF0LCBmb3Igb3VyIGN1cnJlbnQgbW9kZWwsIHdlIGFyZSB1c2luZyB0aGUgcmF3IG51bWJlciBvZiBob3VzZWhvbGRzIGxpdmluZyBpbiBwb3ZlcnR5IChMTk5CRUxQT1YxMDApIGFzIGEgcHJlZGljdG9yLiBUaGUgcmF3IGNvdW50IGRvZXMgbm90IGFjY291bnQgZm9yIGRpZmZlcmVuY2VzIGluIHBvcHVsYXRpb24gc2l6ZSBhY3Jvc3MgbmVpZ2hib3Job29kcywgd2hpY2ggY291bGQgbGVhZCB0byBtaXNsZWFkaW5nIHJlc3VsdHMuIExhcmdlciBuZWlnaGJvcmhvb2RzIHdpdGggbW9yZSBob3VzZWhvbGRzIG1heSBuYXR1cmFsbHkgaGF2ZSBtb3JlIGhvdXNlaG9sZHMgaW4gcG92ZXJ0eSwgZXZlbiBpZiB0aGUgcG92ZXJ0eSByYXRlIGlzIHJlbGF0aXZlbHkgbG93LiBBIG1vcmUgbWVhbmluZ2Z1bCBtZWFzdXJlIHdvdWxkIGJlIHRvIHVzZSB0aGUgcGVyY2VudGFnZSBvZiBob3VzZWhvbGRzIGluIHBvdmVydHksIHdoaWNoIG5vcm1hbGl6ZXMgdGhlIGRhdGEgYWNyb3NzIG5laWdoYm9yaG9vZHMsIHByb3ZpZGluZyBhIGJldHRlciBzZW5zZSBvZiBwb3ZlcnR5J3MgcHJldmFsZW5jZSByZWxhdGl2ZSB0byB0aGUgb3ZlcmFsbCBwb3B1bGF0aW9uLgoKIyMjIFBvc3NpYmlsaXR5IG9mIFJpZGdlIG9yIExBU1NPIFJlZ3Jlc3Npb24KClJpZGdlIGFuZCBMQVNTTyByZWdyZXNzaW9uIGFyZSByZWd1bGFyaXphdGlvbiB0ZWNobmlxdWVzIHVzZWQgdG8gYWRkcmVzcyBtdWx0aWNvbGxpbmVhcml0eSBhbmQgb3ZlcmZpdHRpbmcgaW4gbW9kZWxzIHdpdGggbWFueSBwcmVkaWN0b3JzLiBSaWRnZSByZWdyZXNzaW9uIHBlbmFsaXplcyB0aGUgc2l6ZSBvZiB0aGUgY29lZmZpY2llbnRzLCBzaHJpbmtpbmcgdGhlbSB0b3dhcmRzIHplcm8gYnV0IGtlZXBpbmcgYWxsIHByZWRpY3RvcnMgaW4gdGhlIG1vZGVsLCB3aGljaCBpcyB1c2VmdWwgd2hlbiBhbGwgcHJlZGljdG9ycyBhcmUgYmVsaWV2ZWQgdG8gY29udHJpYnV0ZSB0byB0aGUgb3V0Y29tZS4gTEFTU08gKExlYXN0IEFic29sdXRlIFNocmlua2FnZSBhbmQgU2VsZWN0aW9uIE9wZXJhdG9yKSBnb2VzIGEgc3RlcCBmdXJ0aGVyIGJ5IGZvcmNpbmcgc29tZSBjb2VmZmljaWVudHMgdG8gYmUgZXhhY3RseSB6ZXJvLCBlZmZlY3RpdmVseSBwZXJmb3JtaW5nIHZhcmlhYmxlIHNlbGVjdGlvbi4KCkluIHRoaXMgY2FzZSwgc2luY2UgdGhlIHN0ZXB3aXNlIHJlZ3Jlc3Npb24gc3VnZ2VzdHMgdGhhdCBhbGwgZm91ciBwcmVkaWN0b3JzIHNpZ25pZmljYW50bHkgY29udHJpYnV0ZSB0byB0aGUgbW9kZWwsIHRoZXJl4oCZcyBubyBzdHJvbmcgaW5kaWNhdGlvbiBvZiBtdWx0aWNvbGxpbmVhcml0eSBvciBvdmVyZml0dGluZy4gVGhlcmVmb3JlLCBSaWRnZSBvciBMQVNTTyBtaWdodCBub3QgYmUgbmVjZXNzYXJ5IGhlcmUgdW5sZXNzIHRoZXJlIGlzIGV2aWRlbmNlIG9mIGhpZ2ggbXVsdGljb2xsaW5lYXJpdHkgb3IgbWFueSBtb3JlIHByZWRpY3RvcnMuIElmIHRoZSBtb2RlbCB3ZXJlIG1vcmUgY29tcGxleCBvciBoYWQgYSBsYXJnZXIgbnVtYmVyIG9mIHByZWRpY3RvcnMsIExBU1NPIGNvdWxkIGhlbHAgaW4gc2VsZWN0aW5nIHRoZSBtb3N0IGltcG9ydGFudCBvbmVzLCB3aGlsZSBSaWRnZSBjb3VsZCBoZWxwIHNocmluayBjb2VmZmljaWVudHMgdG8gcHJldmVudCBvdmVyZml0dGluZy4KCgoKIyBSZWZlcmVuY2VzCgoKCgoKCgo=